xref: /aosp_15_r20/external/bazelbuild-rules_go/third_party/org_golang_x_tools-deletegopls.patch (revision 9bb1b549b6a84214c53be0924760be030e66b93a)
1diff -urN a/gopls/api-diff/api_diff.go b/gopls/api-diff/api_diff.go
2--- a/gopls/api-diff/api_diff.go	2000-01-01 00:00:00.000000000 -0000
3+++ b/gopls/api-diff/api_diff.go	1970-01-01 00:00:00.000000000 +0000
4@@ -1,89 +0,0 @@
5-// Copyright 2021 The Go Authors. All rights reserved.
6-// Use of this source code is governed by a BSD-style
7-// license that can be found in the LICENSE file.
8-
9-//go:build go1.18
10-// +build go1.18
11-
12-package main
13-
14-import (
15-	"bytes"
16-	"context"
17-	"encoding/json"
18-	"flag"
19-	"fmt"
20-	"log"
21-	"os"
22-	"os/exec"
23-
24-	"github.com/google/go-cmp/cmp"
25-	"golang.org/x/tools/gopls/internal/lsp/source"
26-)
27-
28-const usage = `api-diff <previous version> [<current version>]
29-
30-Compare the API of two gopls versions. If the second argument is provided, it
31-will be used as the new version to compare against. Otherwise, compare against
32-the current API.
33-`
34-
35-func main() {
36-	flag.Parse()
37-
38-	if flag.NArg() < 1 || flag.NArg() > 2 {
39-		fmt.Fprint(os.Stderr, usage)
40-		os.Exit(2)
41-	}
42-
43-	oldVer := flag.Arg(0)
44-	newVer := ""
45-	if flag.NArg() == 2 {
46-		newVer = flag.Arg(1)
47-	}
48-
49-	apiDiff, err := diffAPI(oldVer, newVer)
50-	if err != nil {
51-		log.Fatal(err)
52-	}
53-	fmt.Println("\n" + apiDiff)
54-}
55-
56-func diffAPI(oldVer, newVer string) (string, error) {
57-	ctx := context.Background()
58-	previousAPI, err := loadAPI(ctx, oldVer)
59-	if err != nil {
60-		return "", fmt.Errorf("loading %s: %v", oldVer, err)
61-	}
62-	var currentAPI *source.APIJSON
63-	if newVer == "" {
64-		currentAPI = source.GeneratedAPIJSON
65-	} else {
66-		var err error
67-		currentAPI, err = loadAPI(ctx, newVer)
68-		if err != nil {
69-			return "", fmt.Errorf("loading %s: %v", newVer, err)
70-		}
71-	}
72-
73-	return cmp.Diff(previousAPI, currentAPI), nil
74-}
75-
76-func loadAPI(ctx context.Context, version string) (*source.APIJSON, error) {
77-	ver := fmt.Sprintf("golang.org/x/tools/gopls@%s", version)
78-	cmd := exec.Command("go", "run", ver, "api-json")
79-
80-	stdout := &bytes.Buffer{}
81-	stderr := &bytes.Buffer{}
82-	cmd.Stdout = stdout
83-	cmd.Stderr = stderr
84-
85-	if err := cmd.Run(); err != nil {
86-		return nil, fmt.Errorf("go run failed: %v; stderr:\n%s", err, stderr)
87-	}
88-	apiJson := &source.APIJSON{}
89-	if err := json.Unmarshal(stdout.Bytes(), apiJson); err != nil {
90-		return nil, fmt.Errorf("unmarshal: %v", err)
91-	}
92-	return apiJson, nil
93-}
94diff -urN a/gopls/doc/advanced.md b/gopls/doc/advanced.md
95--- a/gopls/doc/advanced.md	2000-01-01 00:00:00.000000000 -0000
96+++ b/gopls/doc/advanced.md	1970-01-01 00:00:00.000000000 +0000
97@@ -1,69 +0,0 @@
98-# Advanced topics
99-
100-This documentation is for advanced `gopls` users, who may want to test
101-unreleased versions or try out special features.
102-
103-## Installing unreleased versions
104-
105-To get a specific version of `gopls` (for example, to test a prerelease
106-version), run:
107-
108-```sh
109-GO111MODULE=on go install golang.org/x/tools/gopls@vX.Y.Z
110-```
111-
112-Where `vX.Y.Z` is the desired version.
113-
114-### Unstable versions
115-
116-To update `gopls` to the latest **unstable** version, use the following
117-commands.
118-
119-```sh
120-# Create an empty go.mod file, only for tracking requirements.
121-cd $(mktemp -d)
122-go mod init gopls-unstable
123-
124-# Use 'go get' to add requirements and to ensure they work together.
125-go get -d golang.org/x/tools/gopls@master golang.org/x/tools@master
126-
127-go install golang.org/x/tools/gopls
128-```
129-
130-## Working on the Go source distribution
131-
132-If you are working on the [Go project] itself, the `go` command that `gopls`
133-invokes will have to correspond to the version of the source you are working
134-on. That is, if you have checked out the Go project to `$HOME/go`, your `go`
135-command should be the `$HOME/go/bin/go` executable that you built with
136-`make.bash` or equivalent.
137-
138-You can achieve this by adding the right version of `go` to your `PATH`
139-(`export PATH=$HOME/go/bin:$PATH` on Unix systems) or by configuring your
140-editor.
141-
142-## Working with generic code
143-
144-Gopls has support for editing generic Go code. To enable this support, you need
145-to **install gopls using Go 1.18 or later**. The easiest way to do this is by
146-[installing Go 1.18+](https://go.dev/dl) and then using this Go version to
147-install gopls:
148-
149-```
150-$ go install golang.org/x/tools/gopls@latest
151-```
152-
153-It is strongly recommended that you install the latest version of `gopls`, or
154-the latest **unstable** version as [described above](#installing-unreleased-versions).
155-We're still working on improving our generics support.
156-
157-The `gopls` built with these instructions understands generic code. See the
158-[generics tutorial](https://go.dev/doc/tutorial/generics) for more information
159-on how to use generics in Go!
160-
161-### Known issues
162-
163-  * [`staticcheck`](https://github.com/golang/tools/blob/master/gopls/doc/settings.md#staticcheck-bool)
164-    on generic code is not supported yet.
165-
166-[Go project]: https://go.googlesource.com/go
167diff -urN a/gopls/doc/analyzers.md b/gopls/doc/analyzers.md
168--- a/gopls/doc/analyzers.md	2000-01-01 00:00:00.000000000 -0000
169+++ b/gopls/doc/analyzers.md	1970-01-01 00:00:00.000000000 +0000
170@@ -1,762 +0,0 @@
171-# Analyzers
172-
173-This document describes the analyzers that `gopls` uses inside the editor.
174-
175-Details about how to enable/disable these analyses can be found
176-[here](settings.md#analyses).
177-
178-<!-- BEGIN Analyzers: DO NOT MANUALLY EDIT THIS SECTION -->
179-## **asmdecl**
180-
181-report mismatches between assembly files and Go declarations
182-
183-**Enabled by default.**
184-
185-## **assign**
186-
187-check for useless assignments
188-
189-This checker reports assignments of the form x = x or a[i] = a[i].
190-These are almost always useless, and even when they aren't they are
191-usually a mistake.
192-
193-**Enabled by default.**
194-
195-## **atomic**
196-
197-check for common mistakes using the sync/atomic package
198-
199-The atomic checker looks for assignment statements of the form:
200-
201-	x = atomic.AddUint64(&x, 1)
202-
203-which are not atomic.
204-
205-**Enabled by default.**
206-
207-## **atomicalign**
208-
209-check for non-64-bits-aligned arguments to sync/atomic functions
210-
211-**Enabled by default.**
212-
213-## **bools**
214-
215-check for common mistakes involving boolean operators
216-
217-**Enabled by default.**
218-
219-## **buildtag**
220-
221-check //go:build and // +build directives
222-
223-**Enabled by default.**
224-
225-## **cgocall**
226-
227-detect some violations of the cgo pointer passing rules
228-
229-Check for invalid cgo pointer passing.
230-This looks for code that uses cgo to call C code passing values
231-whose types are almost always invalid according to the cgo pointer
232-sharing rules.
233-Specifically, it warns about attempts to pass a Go chan, map, func,
234-or slice to C, either directly, or via a pointer, array, or struct.
235-
236-**Enabled by default.**
237-
238-## **composites**
239-
240-check for unkeyed composite literals
241-
242-This analyzer reports a diagnostic for composite literals of struct
243-types imported from another package that do not use the field-keyed
244-syntax. Such literals are fragile because the addition of a new field
245-(even if unexported) to the struct will cause compilation to fail.
246-
247-As an example,
248-
249-	err = &net.DNSConfigError{err}
250-
251-should be replaced by:
252-
253-	err = &net.DNSConfigError{Err: err}
254-
255-
256-**Enabled by default.**
257-
258-## **copylocks**
259-
260-check for locks erroneously passed by value
261-
262-Inadvertently copying a value containing a lock, such as sync.Mutex or
263-sync.WaitGroup, may cause both copies to malfunction. Generally such
264-values should be referred to through a pointer.
265-
266-**Enabled by default.**
267-
268-## **deepequalerrors**
269-
270-check for calls of reflect.DeepEqual on error values
271-
272-The deepequalerrors checker looks for calls of the form:
273-
274-    reflect.DeepEqual(err1, err2)
275-
276-where err1 and err2 are errors. Using reflect.DeepEqual to compare
277-errors is discouraged.
278-
279-**Enabled by default.**
280-
281-## **directive**
282-
283-check Go toolchain directives such as //go:debug
284-
285-This analyzer checks for problems with known Go toolchain directives
286-in all Go source files in a package directory, even those excluded by
287-//go:build constraints, and all non-Go source files too.
288-
289-For //go:debug (see https://go.dev/doc/godebug), the analyzer checks
290-that the directives are placed only in Go source files, only above the
291-package comment, and only in package main or *_test.go files.
292-
293-Support for other known directives may be added in the future.
294-
295-This analyzer does not check //go:build, which is handled by the
296-buildtag analyzer.
297-
298-
299-**Enabled by default.**
300-
301-## **embed**
302-
303-check for //go:embed directive import
304-
305-This analyzer checks that the embed package is imported when source code contains //go:embed comment directives.
306-The embed package must be imported for //go:embed directives to function.import _ "embed".
307-
308-**Enabled by default.**
309-
310-## **errorsas**
311-
312-report passing non-pointer or non-error values to errors.As
313-
314-The errorsas analysis reports calls to errors.As where the type
315-of the second argument is not a pointer to a type implementing error.
316-
317-**Enabled by default.**
318-
319-## **fieldalignment**
320-
321-find structs that would use less memory if their fields were sorted
322-
323-This analyzer find structs that can be rearranged to use less memory, and provides
324-a suggested edit with the most compact order.
325-
326-Note that there are two different diagnostics reported. One checks struct size,
327-and the other reports "pointer bytes" used. Pointer bytes is how many bytes of the
328-object that the garbage collector has to potentially scan for pointers, for example:
329-
330-	struct { uint32; string }
331-
332-have 16 pointer bytes because the garbage collector has to scan up through the string's
333-inner pointer.
334-
335-	struct { string; *uint32 }
336-
337-has 24 pointer bytes because it has to scan further through the *uint32.
338-
339-	struct { string; uint32 }
340-
341-has 8 because it can stop immediately after the string pointer.
342-
343-Be aware that the most compact order is not always the most efficient.
344-In rare cases it may cause two variables each updated by its own goroutine
345-to occupy the same CPU cache line, inducing a form of memory contention
346-known as "false sharing" that slows down both goroutines.
347-
348-
349-**Disabled by default. Enable it by setting `"analyses": {"fieldalignment": true}`.**
350-
351-## **httpresponse**
352-
353-check for mistakes using HTTP responses
354-
355-A common mistake when using the net/http package is to defer a function
356-call to close the http.Response Body before checking the error that
357-determines whether the response is valid:
358-
359-	resp, err := http.Head(url)
360-	defer resp.Body.Close()
361-	if err != nil {
362-		log.Fatal(err)
363-	}
364-	// (defer statement belongs here)
365-
366-This checker helps uncover latent nil dereference bugs by reporting a
367-diagnostic for such mistakes.
368-
369-**Enabled by default.**
370-
371-## **ifaceassert**
372-
373-detect impossible interface-to-interface type assertions
374-
375-This checker flags type assertions v.(T) and corresponding type-switch cases
376-in which the static type V of v is an interface that cannot possibly implement
377-the target interface T. This occurs when V and T contain methods with the same
378-name but different signatures. Example:
379-
380-	var v interface {
381-		Read()
382-	}
383-	_ = v.(io.Reader)
384-
385-The Read method in v has a different signature than the Read method in
386-io.Reader, so this assertion cannot succeed.
387-
388-
389-**Enabled by default.**
390-
391-## **infertypeargs**
392-
393-check for unnecessary type arguments in call expressions
394-
395-Explicit type arguments may be omitted from call expressions if they can be
396-inferred from function arguments, or from other type arguments:
397-
398-	func f[T any](T) {}
399-
400-	func _() {
401-		f[string]("foo") // string could be inferred
402-	}
403-
404-
405-**Enabled by default.**
406-
407-## **loopclosure**
408-
409-check references to loop variables from within nested functions
410-
411-This analyzer reports places where a function literal references the
412-iteration variable of an enclosing loop, and the loop calls the function
413-in such a way (e.g. with go or defer) that it may outlive the loop
414-iteration and possibly observe the wrong value of the variable.
415-
416-In this example, all the deferred functions run after the loop has
417-completed, so all observe the final value of v.
418-
419-    for _, v := range list {
420-        defer func() {
421-            use(v) // incorrect
422-        }()
423-    }
424-
425-One fix is to create a new variable for each iteration of the loop:
426-
427-    for _, v := range list {
428-        v := v // new var per iteration
429-        defer func() {
430-            use(v) // ok
431-        }()
432-    }
433-
434-The next example uses a go statement and has a similar problem.
435-In addition, it has a data race because the loop updates v
436-concurrent with the goroutines accessing it.
437-
438-    for _, v := range elem {
439-        go func() {
440-            use(v)  // incorrect, and a data race
441-        }()
442-    }
443-
444-A fix is the same as before. The checker also reports problems
445-in goroutines started by golang.org/x/sync/errgroup.Group.
446-A hard-to-spot variant of this form is common in parallel tests:
447-
448-    func Test(t *testing.T) {
449-        for _, test := range tests {
450-            t.Run(test.name, func(t *testing.T) {
451-                t.Parallel()
452-                use(test) // incorrect, and a data race
453-            })
454-        }
455-    }
456-
457-The t.Parallel() call causes the rest of the function to execute
458-concurrent with the loop.
459-
460-The analyzer reports references only in the last statement,
461-as it is not deep enough to understand the effects of subsequent
462-statements that might render the reference benign.
463-("Last statement" is defined recursively in compound
464-statements such as if, switch, and select.)
465-
466-See: https://golang.org/doc/go_faq.html#closures_and_goroutines
467-
468-**Enabled by default.**
469-
470-## **lostcancel**
471-
472-check cancel func returned by context.WithCancel is called
473-
474-The cancellation function returned by context.WithCancel, WithTimeout,
475-and WithDeadline must be called or the new context will remain live
476-until its parent context is cancelled.
477-(The background context is never cancelled.)
478-
479-**Enabled by default.**
480-
481-## **nilfunc**
482-
483-check for useless comparisons between functions and nil
484-
485-A useless comparison is one like f == nil as opposed to f() == nil.
486-
487-**Enabled by default.**
488-
489-## **nilness**
490-
491-check for redundant or impossible nil comparisons
492-
493-The nilness checker inspects the control-flow graph of each function in
494-a package and reports nil pointer dereferences, degenerate nil
495-pointers, and panics with nil values. A degenerate comparison is of the form
496-x==nil or x!=nil where x is statically known to be nil or non-nil. These are
497-often a mistake, especially in control flow related to errors. Panics with nil
498-values are checked because they are not detectable by
499-
500-	if r := recover(); r != nil {
501-
502-This check reports conditions such as:
503-
504-	if f == nil { // impossible condition (f is a function)
505-	}
506-
507-and:
508-
509-	p := &v
510-	...
511-	if p != nil { // tautological condition
512-	}
513-
514-and:
515-
516-	if p == nil {
517-		print(*p) // nil dereference
518-	}
519-
520-and:
521-
522-	if p == nil {
523-		panic(p)
524-	}
525-
526-
527-**Disabled by default. Enable it by setting `"analyses": {"nilness": true}`.**
528-
529-## **printf**
530-
531-check consistency of Printf format strings and arguments
532-
533-The check applies to known functions (for example, those in package fmt)
534-as well as any detected wrappers of known functions.
535-
536-A function that wants to avail itself of printf checking but is not
537-found by this analyzer's heuristics (for example, due to use of
538-dynamic calls) can insert a bogus call:
539-
540-	if false {
541-		_ = fmt.Sprintf(format, args...) // enable printf checking
542-	}
543-
544-The -funcs flag specifies a comma-separated list of names of additional
545-known formatting functions or methods. If the name contains a period,
546-it must denote a specific function using one of the following forms:
547-
548-	dir/pkg.Function
549-	dir/pkg.Type.Method
550-	(*dir/pkg.Type).Method
551-
552-Otherwise the name is interpreted as a case-insensitive unqualified
553-identifier such as "errorf". Either way, if a listed name ends in f, the
554-function is assumed to be Printf-like, taking a format string before the
555-argument list. Otherwise it is assumed to be Print-like, taking a list
556-of arguments with no format string.
557-
558-
559-**Enabled by default.**
560-
561-## **shadow**
562-
563-check for possible unintended shadowing of variables
564-
565-This analyzer check for shadowed variables.
566-A shadowed variable is a variable declared in an inner scope
567-with the same name and type as a variable in an outer scope,
568-and where the outer variable is mentioned after the inner one
569-is declared.
570-
571-(This definition can be refined; the module generates too many
572-false positives and is not yet enabled by default.)
573-
574-For example:
575-
576-	func BadRead(f *os.File, buf []byte) error {
577-		var err error
578-		for {
579-			n, err := f.Read(buf) // shadows the function variable 'err'
580-			if err != nil {
581-				break // causes return of wrong value
582-			}
583-			foo(buf)
584-		}
585-		return err
586-	}
587-
588-
589-**Disabled by default. Enable it by setting `"analyses": {"shadow": true}`.**
590-
591-## **shift**
592-
593-check for shifts that equal or exceed the width of the integer
594-
595-**Enabled by default.**
596-
597-## **simplifycompositelit**
598-
599-check for composite literal simplifications
600-
601-An array, slice, or map composite literal of the form:
602-	[]T{T{}, T{}}
603-will be simplified to:
604-	[]T{{}, {}}
605-
606-This is one of the simplifications that "gofmt -s" applies.
607-
608-**Enabled by default.**
609-
610-## **simplifyrange**
611-
612-check for range statement simplifications
613-
614-A range of the form:
615-	for x, _ = range v {...}
616-will be simplified to:
617-	for x = range v {...}
618-
619-A range of the form:
620-	for _ = range v {...}
621-will be simplified to:
622-	for range v {...}
623-
624-This is one of the simplifications that "gofmt -s" applies.
625-
626-**Enabled by default.**
627-
628-## **simplifyslice**
629-
630-check for slice simplifications
631-
632-A slice expression of the form:
633-	s[a:len(s)]
634-will be simplified to:
635-	s[a:]
636-
637-This is one of the simplifications that "gofmt -s" applies.
638-
639-**Enabled by default.**
640-
641-## **sortslice**
642-
643-check the argument type of sort.Slice
644-
645-sort.Slice requires an argument of a slice type. Check that
646-the interface{} value passed to sort.Slice is actually a slice.
647-
648-**Enabled by default.**
649-
650-## **stdmethods**
651-
652-check signature of methods of well-known interfaces
653-
654-Sometimes a type may be intended to satisfy an interface but may fail to
655-do so because of a mistake in its method signature.
656-For example, the result of this WriteTo method should be (int64, error),
657-not error, to satisfy io.WriterTo:
658-
659-	type myWriterTo struct{...}
660-        func (myWriterTo) WriteTo(w io.Writer) error { ... }
661-
662-This check ensures that each method whose name matches one of several
663-well-known interface methods from the standard library has the correct
664-signature for that interface.
665-
666-Checked method names include:
667-	Format GobEncode GobDecode MarshalJSON MarshalXML
668-	Peek ReadByte ReadFrom ReadRune Scan Seek
669-	UnmarshalJSON UnreadByte UnreadRune WriteByte
670-	WriteTo
671-
672-
673-**Enabled by default.**
674-
675-## **stringintconv**
676-
677-check for string(int) conversions
678-
679-This checker flags conversions of the form string(x) where x is an integer
680-(but not byte or rune) type. Such conversions are discouraged because they
681-return the UTF-8 representation of the Unicode code point x, and not a decimal
682-string representation of x as one might expect. Furthermore, if x denotes an
683-invalid code point, the conversion cannot be statically rejected.
684-
685-For conversions that intend on using the code point, consider replacing them
686-with string(rune(x)). Otherwise, strconv.Itoa and its equivalents return the
687-string representation of the value in the desired base.
688-
689-
690-**Enabled by default.**
691-
692-## **structtag**
693-
694-check that struct field tags conform to reflect.StructTag.Get
695-
696-Also report certain struct tags (json, xml) used with unexported fields.
697-
698-**Enabled by default.**
699-
700-## **testinggoroutine**
701-
702-report calls to (*testing.T).Fatal from goroutines started by a test.
703-
704-Functions that abruptly terminate a test, such as the Fatal, Fatalf, FailNow, and
705-Skip{,f,Now} methods of *testing.T, must be called from the test goroutine itself.
706-This checker detects calls to these functions that occur within a goroutine
707-started by the test. For example:
708-
709-func TestFoo(t *testing.T) {
710-    go func() {
711-        t.Fatal("oops") // error: (*T).Fatal called from non-test goroutine
712-    }()
713-}
714-
715-
716-**Enabled by default.**
717-
718-## **tests**
719-
720-check for common mistaken usages of tests and examples
721-
722-The tests checker walks Test, Benchmark and Example functions checking
723-malformed names, wrong signatures and examples documenting non-existent
724-identifiers.
725-
726-Please see the documentation for package testing in golang.org/pkg/testing
727-for the conventions that are enforced for Tests, Benchmarks, and Examples.
728-
729-**Enabled by default.**
730-
731-## **timeformat**
732-
733-check for calls of (time.Time).Format or time.Parse with 2006-02-01
734-
735-The timeformat checker looks for time formats with the 2006-02-01 (yyyy-dd-mm)
736-format. Internationally, "yyyy-dd-mm" does not occur in common calendar date
737-standards, and so it is more likely that 2006-01-02 (yyyy-mm-dd) was intended.
738-
739-
740-**Enabled by default.**
741-
742-## **unmarshal**
743-
744-report passing non-pointer or non-interface values to unmarshal
745-
746-The unmarshal analysis reports calls to functions such as json.Unmarshal
747-in which the argument type is not a pointer or an interface.
748-
749-**Enabled by default.**
750-
751-## **unreachable**
752-
753-check for unreachable code
754-
755-The unreachable analyzer finds statements that execution can never reach
756-because they are preceded by an return statement, a call to panic, an
757-infinite loop, or similar constructs.
758-
759-**Enabled by default.**
760-
761-## **unsafeptr**
762-
763-check for invalid conversions of uintptr to unsafe.Pointer
764-
765-The unsafeptr analyzer reports likely incorrect uses of unsafe.Pointer
766-to convert integers to pointers. A conversion from uintptr to
767-unsafe.Pointer is invalid if it implies that there is a uintptr-typed
768-word in memory that holds a pointer value, because that word will be
769-invisible to stack copying and to the garbage collector.
770-
771-**Enabled by default.**
772-
773-## **unusedparams**
774-
775-check for unused parameters of functions
776-
777-The unusedparams analyzer checks functions to see if there are
778-any parameters that are not being used.
779-
780-To reduce false positives it ignores:
781-- methods
782-- parameters that do not have a name or are underscored
783-- functions in test files
784-- functions with empty bodies or those with just a return stmt
785-
786-**Disabled by default. Enable it by setting `"analyses": {"unusedparams": true}`.**
787-
788-## **unusedresult**
789-
790-check for unused results of calls to some functions
791-
792-Some functions like fmt.Errorf return a result and have no side effects,
793-so it is always a mistake to discard the result. This analyzer reports
794-calls to certain functions in which the result of the call is ignored.
795-
796-The set of functions may be controlled using flags.
797-
798-**Enabled by default.**
799-
800-## **unusedwrite**
801-
802-checks for unused writes
803-
804-The analyzer reports instances of writes to struct fields and
805-arrays that are never read. Specifically, when a struct object
806-or an array is copied, its elements are copied implicitly by
807-the compiler, and any element write to this copy does nothing
808-with the original object.
809-
810-For example:
811-
812-	type T struct { x int }
813-	func f(input []T) {
814-		for i, v := range input {  // v is a copy
815-			v.x = i  // unused write to field x
816-		}
817-	}
818-
819-Another example is about non-pointer receiver:
820-
821-	type T struct { x int }
822-	func (t T) f() {  // t is a copy
823-		t.x = i  // unused write to field x
824-	}
825-
826-
827-**Disabled by default. Enable it by setting `"analyses": {"unusedwrite": true}`.**
828-
829-## **useany**
830-
831-check for constraints that could be simplified to "any"
832-
833-**Disabled by default. Enable it by setting `"analyses": {"useany": true}`.**
834-
835-## **fillreturns**
836-
837-suggest fixes for errors due to an incorrect number of return values
838-
839-This checker provides suggested fixes for type errors of the
840-type "wrong number of return values (want %d, got %d)". For example:
841-	func m() (int, string, *bool, error) {
842-		return
843-	}
844-will turn into
845-	func m() (int, string, *bool, error) {
846-		return 0, "", nil, nil
847-	}
848-
849-This functionality is similar to https://github.com/sqs/goreturns.
850-
851-
852-**Enabled by default.**
853-
854-## **nonewvars**
855-
856-suggested fixes for "no new vars on left side of :="
857-
858-This checker provides suggested fixes for type errors of the
859-type "no new vars on left side of :=". For example:
860-	z := 1
861-	z := 2
862-will turn into
863-	z := 1
864-	z = 2
865-
866-
867-**Enabled by default.**
868-
869-## **noresultvalues**
870-
871-suggested fixes for unexpected return values
872-
873-This checker provides suggested fixes for type errors of the
874-type "no result values expected" or "too many return values".
875-For example:
876-	func z() { return nil }
877-will turn into
878-	func z() { return }
879-
880-
881-**Enabled by default.**
882-
883-## **undeclaredname**
884-
885-suggested fixes for "undeclared name: <>"
886-
887-This checker provides suggested fixes for type errors of the
888-type "undeclared name: <>". It will either insert a new statement,
889-such as:
890-
891-"<> := "
892-
893-or a new function declaration, such as:
894-
895-func <>(inferred parameters) {
896-	panic("implement me!")
897-}
898-
899-
900-**Enabled by default.**
901-
902-## **unusedvariable**
903-
904-check for unused variables
905-
906-The unusedvariable analyzer suggests fixes for unused variables errors.
907-
908-
909-**Disabled by default. Enable it by setting `"analyses": {"unusedvariable": true}`.**
910-
911-## **fillstruct**
912-
913-note incomplete struct initializations
914-
915-This analyzer provides diagnostics for any struct literals that do not have
916-any fields initialized. Because the suggested fix for this analysis is
917-expensive to compute, callers should compute it separately, using the
918-SuggestedFix function below.
919-
920-
921-**Enabled by default.**
922-
923-## **stubmethods**
924-
925-stub methods analyzer
926-
927-This analyzer generates method stubs for concrete types
928-in order to implement a target interface
929-
930-**Enabled by default.**
931-
932-<!-- END Analyzers: DO NOT MANUALLY EDIT THIS SECTION -->
933diff -urN a/gopls/doc/command-line.md b/gopls/doc/command-line.md
934--- a/gopls/doc/command-line.md	2000-01-01 00:00:00.000000000 -0000
935+++ b/gopls/doc/command-line.md	1970-01-01 00:00:00.000000000 +0000
936@@ -1,15 +0,0 @@
937-# Command line
938-
939-**Note: The `gopls` command-line is still experimental and subject to change at any point.**
940-
941-`gopls` exposes some (but not all) features on the command-line. This can be useful for debugging `gopls` itself.
942-
943-<!--TODO(rstambler): Generate this file.-->
944-
945-Learn about available commands and flags by running `gopls help`.
946-
947-Much of the functionality of `gopls` is available through a command line interface.
948-
949-There are two main reasons for this. The first is that we do not want users to rely on separate command line tools when they wish to do some task outside of an editor. The second is that the CLI assists in debugging. It is easier to reproduce behavior via single command.
950-
951-It is not a goal of `gopls` to be a high performance command line tool. Its command line is intended for single file/package user interaction speeds, not bulk processing.
952diff -urN a/gopls/doc/commands.md b/gopls/doc/commands.md
953--- a/gopls/doc/commands.md	2000-01-01 00:00:00.000000000 -0000
954+++ b/gopls/doc/commands.md	1970-01-01 00:00:00.000000000 +0000
955@@ -1,467 +0,0 @@
956-# Commands
957-
958-This document describes the LSP-level commands supported by `gopls`. They cannot be invoked directly by users, and all the details are subject to change, so nobody should rely on this information.
959-
960-<!-- BEGIN Commands: DO NOT MANUALLY EDIT THIS SECTION -->
961-### **Add a dependency**
962-Identifier: `gopls.add_dependency`
963-
964-Adds a dependency to the go.mod file for a module.
965-
966-Args:
967-
968-```
969-{
970-	// The go.mod file URI.
971-	"URI": string,
972-	// Additional args to pass to the go command.
973-	"GoCmdArgs": []string,
974-	// Whether to add a require directive.
975-	"AddRequire": bool,
976-}
977-```
978-
979-### **Add an import**
980-Identifier: `gopls.add_import`
981-
982-Ask the server to add an import path to a given Go file.  The method will
983-call applyEdit on the client so that clients don't have to apply the edit
984-themselves.
985-
986-Args:
987-
988-```
989-{
990-	// ImportPath is the target import path that should
991-	// be added to the URI file
992-	"ImportPath": string,
993-	// URI is the file that the ImportPath should be
994-	// added to
995-	"URI": string,
996-}
997-```
998-
999-### **Apply a fix**
1000-Identifier: `gopls.apply_fix`
1001-
1002-Applies a fix to a region of source code.
1003-
1004-Args:
1005-
1006-```
1007-{
1008-	// The fix to apply.
1009-	"Fix": string,
1010-	// The file URI for the document to fix.
1011-	"URI": string,
1012-	// The document range to scan for fixes.
1013-	"Range": {
1014-		"start": {
1015-			"line": uint32,
1016-			"character": uint32,
1017-		},
1018-		"end": {
1019-			"line": uint32,
1020-			"character": uint32,
1021-		},
1022-	},
1023-}
1024-```
1025-
1026-### **Check for upgrades**
1027-Identifier: `gopls.check_upgrades`
1028-
1029-Checks for module upgrades.
1030-
1031-Args:
1032-
1033-```
1034-{
1035-	// The go.mod file URI.
1036-	"URI": string,
1037-	// The modules to check.
1038-	"Modules": []string,
1039-}
1040-```
1041-
1042-### **Run go mod edit -go=version**
1043-Identifier: `gopls.edit_go_directive`
1044-
1045-Runs `go mod edit -go=version` for a module.
1046-
1047-Args:
1048-
1049-```
1050-{
1051-	// Any document URI within the relevant module.
1052-	"URI": string,
1053-	// The version to pass to `go mod edit -go`.
1054-	"Version": string,
1055-}
1056-```
1057-
1058-### **Get known vulncheck result**
1059-Identifier: `gopls.fetch_vulncheck_result`
1060-
1061-Fetch the result of latest vulnerability check (`govulncheck`).
1062-
1063-Args:
1064-
1065-```
1066-{
1067-	// The file URI.
1068-	"URI": string,
1069-}
1070-```
1071-
1072-Result:
1073-
1074-```
1075-map[golang.org/x/tools/gopls/internal/lsp/protocol.DocumentURI]*golang.org/x/tools/gopls/internal/govulncheck.Result
1076-```
1077-
1078-### **Toggle gc_details**
1079-Identifier: `gopls.gc_details`
1080-
1081-Toggle the calculation of gc annotations.
1082-
1083-Args:
1084-
1085-```
1086-string
1087-```
1088-
1089-### **Run go generate**
1090-Identifier: `gopls.generate`
1091-
1092-Runs `go generate` for a given directory.
1093-
1094-Args:
1095-
1096-```
1097-{
1098-	// URI for the directory to generate.
1099-	"Dir": string,
1100-	// Whether to generate recursively (go generate ./...)
1101-	"Recursive": bool,
1102-}
1103-```
1104-
1105-### **go get a package**
1106-Identifier: `gopls.go_get_package`
1107-
1108-Runs `go get` to fetch a package.
1109-
1110-Args:
1111-
1112-```
1113-{
1114-	// Any document URI within the relevant module.
1115-	"URI": string,
1116-	// The package to go get.
1117-	"Pkg": string,
1118-	"AddRequire": bool,
1119-}
1120-```
1121-
1122-### **List imports of a file and its package**
1123-Identifier: `gopls.list_imports`
1124-
1125-Retrieve a list of imports in the given Go file, and the package it
1126-belongs to.
1127-
1128-Args:
1129-
1130-```
1131-{
1132-	// The file URI.
1133-	"URI": string,
1134-}
1135-```
1136-
1137-Result:
1138-
1139-```
1140-{
1141-	// Imports is a list of imports in the requested file.
1142-	"Imports": []{
1143-		"Path": string,
1144-		"Name": string,
1145-	},
1146-	// PackageImports is a list of all imports in the requested file's package.
1147-	"PackageImports": []{
1148-		"Path": string,
1149-	},
1150-}
1151-```
1152-
1153-### **List known packages**
1154-Identifier: `gopls.list_known_packages`
1155-
1156-Retrieve a list of packages that are importable from the given URI.
1157-
1158-Args:
1159-
1160-```
1161-{
1162-	// The file URI.
1163-	"URI": string,
1164-}
1165-```
1166-
1167-Result:
1168-
1169-```
1170-{
1171-	// Packages is a list of packages relative
1172-	// to the URIArg passed by the command request.
1173-	// In other words, it omits paths that are already
1174-	// imported or cannot be imported due to compiler
1175-	// restrictions.
1176-	"Packages": []string,
1177-}
1178-```
1179-
1180-### **fetch memory statistics**
1181-Identifier: `gopls.mem_stats`
1182-
1183-Call runtime.GC multiple times and return memory statistics as reported by
1184-runtime.MemStats.
1185-
1186-This command is used for benchmarking, and may change in the future.
1187-
1188-Result:
1189-
1190-```
1191-{
1192-	"HeapAlloc": uint64,
1193-	"HeapInUse": uint64,
1194-}
1195-```
1196-
1197-### **Regenerate cgo**
1198-Identifier: `gopls.regenerate_cgo`
1199-
1200-Regenerates cgo definitions.
1201-
1202-Args:
1203-
1204-```
1205-{
1206-	// The file URI.
1207-	"URI": string,
1208-}
1209-```
1210-
1211-### **Remove a dependency**
1212-Identifier: `gopls.remove_dependency`
1213-
1214-Removes a dependency from the go.mod file of a module.
1215-
1216-Args:
1217-
1218-```
1219-{
1220-	// The go.mod file URI.
1221-	"URI": string,
1222-	// The module path to remove.
1223-	"ModulePath": string,
1224-	"OnlyDiagnostic": bool,
1225-}
1226-```
1227-
1228-### **Reset go.mod diagnostics**
1229-Identifier: `gopls.reset_go_mod_diagnostics`
1230-
1231-Reset diagnostics in the go.mod file of a module.
1232-
1233-Args:
1234-
1235-```
1236-{
1237-	"URIArg": {
1238-		"URI": string,
1239-	},
1240-	// Optional: source of the diagnostics to reset.
1241-	// If not set, all resettable go.mod diagnostics will be cleared.
1242-	"DiagnosticSource": string,
1243-}
1244-```
1245-
1246-### **Run govulncheck.**
1247-Identifier: `gopls.run_govulncheck`
1248-
1249-Run vulnerability check (`govulncheck`).
1250-
1251-Args:
1252-
1253-```
1254-{
1255-	// Any document in the directory from which govulncheck will run.
1256-	"URI": string,
1257-	// Package pattern. E.g. "", ".", "./...".
1258-	"Pattern": string,
1259-}
1260-```
1261-
1262-Result:
1263-
1264-```
1265-{
1266-	// Token holds the progress token for LSP workDone reporting of the vulncheck
1267-	// invocation.
1268-	"Token": interface{},
1269-}
1270-```
1271-
1272-### **Run test(s)**
1273-Identifier: `gopls.run_tests`
1274-
1275-Runs `go test` for a specific set of test or benchmark functions.
1276-
1277-Args:
1278-
1279-```
1280-{
1281-	// The test file containing the tests to run.
1282-	"URI": string,
1283-	// Specific test names to run, e.g. TestFoo.
1284-	"Tests": []string,
1285-	// Specific benchmarks to run, e.g. BenchmarkFoo.
1286-	"Benchmarks": []string,
1287-}
1288-```
1289-
1290-### **Start the gopls debug server**
1291-Identifier: `gopls.start_debugging`
1292-
1293-Start the gopls debug server if it isn't running, and return the debug
1294-address.
1295-
1296-Args:
1297-
1298-```
1299-{
1300-	// Optional: the address (including port) for the debug server to listen on.
1301-	// If not provided, the debug server will bind to "localhost:0", and the
1302-	// full debug URL will be contained in the result.
1303-	//
1304-	// If there is more than one gopls instance along the serving path (i.e. you
1305-	// are using a daemon), each gopls instance will attempt to start debugging.
1306-	// If Addr specifies a port, only the daemon will be able to bind to that
1307-	// port, and each intermediate gopls instance will fail to start debugging.
1308-	// For this reason it is recommended not to specify a port (or equivalently,
1309-	// to specify ":0").
1310-	//
1311-	// If the server was already debugging this field has no effect, and the
1312-	// result will contain the previously configured debug URL(s).
1313-	"Addr": string,
1314-}
1315-```
1316-
1317-Result:
1318-
1319-```
1320-{
1321-	// The URLs to use to access the debug servers, for all gopls instances in
1322-	// the serving path. For the common case of a single gopls instance (i.e. no
1323-	// daemon), this will be exactly one address.
1324-	//
1325-	// In the case of one or more gopls instances forwarding the LSP to a daemon,
1326-	// URLs will contain debug addresses for each server in the serving path, in
1327-	// serving order. The daemon debug address will be the last entry in the
1328-	// slice. If any intermediate gopls instance fails to start debugging, no
1329-	// error will be returned but the debug URL for that server in the URLs slice
1330-	// will be empty.
1331-	"URLs": []string,
1332-}
1333-```
1334-
1335-### **Run test(s) (legacy)**
1336-Identifier: `gopls.test`
1337-
1338-Runs `go test` for a specific set of test or benchmark functions.
1339-
1340-Args:
1341-
1342-```
1343-string,
1344-[]string,
1345-[]string
1346-```
1347-
1348-### **Run go mod tidy**
1349-Identifier: `gopls.tidy`
1350-
1351-Runs `go mod tidy` for a module.
1352-
1353-Args:
1354-
1355-```
1356-{
1357-	// The file URIs.
1358-	"URIs": []string,
1359-}
1360-```
1361-
1362-### **Toggle gc_details**
1363-Identifier: `gopls.toggle_gc_details`
1364-
1365-Toggle the calculation of gc annotations.
1366-
1367-Args:
1368-
1369-```
1370-{
1371-	// The file URI.
1372-	"URI": string,
1373-}
1374-```
1375-
1376-### **Update go.sum**
1377-Identifier: `gopls.update_go_sum`
1378-
1379-Updates the go.sum file for a module.
1380-
1381-Args:
1382-
1383-```
1384-{
1385-	// The file URIs.
1386-	"URIs": []string,
1387-}
1388-```
1389-
1390-### **Upgrade a dependency**
1391-Identifier: `gopls.upgrade_dependency`
1392-
1393-Upgrades a dependency in the go.mod file for a module.
1394-
1395-Args:
1396-
1397-```
1398-{
1399-	// The go.mod file URI.
1400-	"URI": string,
1401-	// Additional args to pass to the go command.
1402-	"GoCmdArgs": []string,
1403-	// Whether to add a require directive.
1404-	"AddRequire": bool,
1405-}
1406-```
1407-
1408-### **Run go mod vendor**
1409-Identifier: `gopls.vendor`
1410-
1411-Runs `go mod vendor` for a module.
1412-
1413-Args:
1414-
1415-```
1416-{
1417-	// The file URI.
1418-	"URI": string,
1419-}
1420-```
1421-
1422-<!-- END Commands: DO NOT MANUALLY EDIT THIS SECTION -->
1423diff -urN a/gopls/doc/contributing.md b/gopls/doc/contributing.md
1424--- a/gopls/doc/contributing.md	2000-01-01 00:00:00.000000000 -0000
1425+++ b/gopls/doc/contributing.md	1970-01-01 00:00:00.000000000 +0000
1426@@ -1,119 +0,0 @@
1427-# Documentation for contributors
1428-
1429-This documentation augments the general documentation for contributing to the
1430-x/tools repository, described at the [repository root](../../CONTRIBUTING.md).
1431-
1432-Contributions are welcome, but since development is so active, we request that
1433-you file an issue and claim it before starting to work on something. Otherwise,
1434-it is likely that we might already be working on a fix for your issue.
1435-
1436-## Finding issues
1437-
1438-All `gopls` issues are labeled as such (see the [`gopls` label][issue-gopls]).
1439-Issues that are suitable for contributors are additionally tagged with the
1440-[`help-wanted` label][issue-wanted].
1441-
1442-Before you begin working on an issue, please leave a comment that you are
1443-claiming it.
1444-
1445-## Getting started
1446-
1447-Most of the `gopls` logic is in the `golang.org/x/tools/gopls/internal/lsp`
1448-directory.
1449-
1450-## Build
1451-
1452-To build a version of `gopls` with your changes applied:
1453-
1454-```bash
1455-cd /path/to/tools/gopls
1456-go install
1457-```
1458-
1459-To confirm that you are testing with the correct `gopls` version, check that
1460-your `gopls` version looks like this:
1461-
1462-```bash
1463-$ gopls version
1464-golang.org/x/tools/gopls master
1465-    golang.org/x/tools/gopls@(devel)
1466-```
1467-
1468-## Getting help
1469-
1470-The best way to contact the gopls team directly is via the
1471-[#gopls-dev](https://app.slack.com/client/T029RQSE6/CRWSN9NCD) channel on the
1472-gophers slack. Please feel free to ask any questions about your contribution or
1473-about contributing in general.
1474-
1475-## Testing
1476-
1477-To run tests for just `gopls/`, run,
1478-
1479-```bash
1480-cd /path/to/tools/gopls
1481-go test ./...
1482-```
1483-
1484-But, much of the gopls work involves `internal/lsp` too, so you will want to
1485-run both:
1486-
1487-```bash
1488-cd /path/to/tools
1489-cd gopls && go test ./...
1490-cd ..
1491-go test ./internal/lsp/...
1492-```
1493-
1494-There is additional information about the `internal/lsp` tests in the
1495-[internal/lsp/tests `README`](https://github.com/golang/tools/blob/master/internal/lsp/tests/README.md).
1496-
1497-### Regtests
1498-
1499-gopls has a suite of regression tests defined in the `./gopls/internal/regtest`
1500-directory. Each of these tests writes files to a temporary directory, starts a
1501-separate gopls session, and scripts interactions using an editor-like API. As a
1502-result of this overhead they can be quite slow, particularly on systems where
1503-file operations are costly.
1504-
1505-Due to the asynchronous nature of the LSP, regtests assertions are written
1506-as 'expectations' that the editor state must achieve _eventually_. This can
1507-make debugging the regtests difficult. To aid with debugging, the regtests
1508-output their LSP logs on any failure. If your CL gets a test failure while
1509-running the regtests, please do take a look at the description of the error and
1510-the LSP logs, but don't hesitate to [reach out](#getting-help) to the gopls
1511-team if you need help.
1512-
1513-### CI
1514-
1515-When you mail your CL and you or a fellow contributor assigns the
1516-`Run-TryBot=1` label in Gerrit, the
1517-[TryBots](https://golang.org/doc/contribute.html#trybots) will run tests in
1518-both the `golang.org/x/tools` and `golang.org/x/tools/gopls` modules, as
1519-described above.
1520-
1521-Furthermore, an additional "gopls-CI" pass will be run by _Kokoro_, which is a
1522-Jenkins-like Google infrastructure for running Dockerized tests. This allows us
1523-to run gopls tests in various environments that would be difficult to add to
1524-the TryBots. Notably, Kokoro runs tests on
1525-[older Go versions](../README.md#supported-go-versions) that are no longer supported
1526-by the TryBots. Per that that policy, support for these older Go versions is
1527-best-effort, and test failures may be skipped rather than fixed.
1528-
1529-Kokoro runs are triggered by the `Run-TryBot=1` label, just like TryBots, but
1530-unlike TryBots they do not automatically re-run if the "gopls-CI" result is
1531-removed in Gerrit. To force a re-run of the Kokoro CI on a CL containing the
1532-`Run-TryBot=1` label, you can reply in Gerrit with the comment "kokoro rerun".
1533-
1534-## Debugging
1535-
1536-The easiest way to debug your change is to run a single `gopls` test with a
1537-debugger.
1538-
1539-See also [Troubleshooting](troubleshooting.md#troubleshooting).
1540-
1541-<!--TODO(rstambler): Add more details about the debug server and viewing
1542-telemetry.-->
1543-
1544-[issue-gopls]: https://github.com/golang/go/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Agopls "gopls issues"
1545-[issue-wanted]: https://github.com/golang/go/issues?utf8=✓&q=is%3Aissue+is%3Aopen+label%3Agopls+label%3A"help+wanted" "help wanted"
1546diff -urN a/gopls/doc/daemon.md b/gopls/doc/daemon.md
1547--- a/gopls/doc/daemon.md	2000-01-01 00:00:00.000000000 -0000
1548+++ b/gopls/doc/daemon.md	1970-01-01 00:00:00.000000000 +0000
1549@@ -1,183 +0,0 @@
1550-# Running gopls as a daemon
1551-
1552-**Note: this feature is new. If you encounter bugs, please [file an
1553-issue](troubleshooting.md#file-an-issue).**
1554-
1555-If you just want to try this out, skip ahead to the [quickstart](#quickstart).
1556-
1557-## Background: gopls execution modes
1558-
1559-Gopls was originally implemented as an LSP sidecar: a process started by
1560-editors or editor plugins, and communicated with using jsonrpc 2.0 over
1561-stdin/stdout. By executing as a stateful process, gopls can maintain a
1562-significant amount of cache and can eagerly perform analysis on the source code
1563-being edited.
1564-
1565-This execution mode does not work as well when there are many separate editor
1566-processes or when editor processes are short-lived, as is often the case for
1567-users of non-IDE editors such as Vim or Emacs. Having many processes means
1568-having many caches, consuming a significant amount of system resources. Using
1569-short-lived sessions means paying a start-up cost each time a session is
1570-created.
1571-
1572-To support these types of workflows, a new mode of gopls execution is supported
1573-wherein a single, persistent, shared gopls "daemon" process is responsible for
1574-managing all gopls sessions. In this mode, editors still start a gopls sidecar,
1575-but this sidecar merely acts as a thin "forwarder", responsible for forwarding
1576-the LSP to the shared gopls instance and recording metrics, logs, and rpc
1577-traces.
1578-
1579-## Quickstart
1580-
1581-To use a shared gopls instance you must either manage the daemon process
1582-yourself, or let the gopls forwarder processes start the shared daemon as
1583-needed.
1584-
1585-### Running with `-remote=auto`
1586-
1587-Automatic management of the daemon is easiest, and can be done by passing the
1588-flag `-remote=auto` to the gopls process started by your editor. This will
1589-cause this process to auto-start the gopls daemon if needed, connect to it, and
1590-forward the LSP. For example, here is a reasonable gopls invocation, that sets
1591-some additional flags for easier [debugging](#debugging):
1592-
1593-```bash
1594-gopls -remote=auto -logfile=auto -debug=:0 -remote.debug=:0 -rpc.trace
1595-```
1596-
1597-Note that the shared gopls process will automatically shut down after one
1598-minute with no connected clients.
1599-
1600-### Managing the daemon manually
1601-
1602-To manage the gopls daemon process via external means rather than having the
1603-forwarders manage it, you must start a gopls daemon process with the
1604-`-listen=<addr>` flag, and then pass `-remote=<addr>` to the gopls processes
1605-started by your editor.
1606-
1607-For example, to host the daemon on the TCP port `37374`, do:
1608-
1609-```bash
1610-gopls -listen=:37374 -logfile=auto -debug=:0
1611-```
1612-
1613-And then from the editor, run
1614-
1615-```bash
1616-gopls -remote=:37374 -logfile=auto -debug=:0 -rpc.trace
1617-```
1618-
1619-If you are on a POSIX system, you can also use unix domain sockets by prefixing
1620-the flag values with `unix;`. For example:
1621-
1622-```bash
1623-gopls -listen="unix;/tmp/gopls-daemon-socket" -logfile=auto -debug=:0
1624-```
1625-
1626-And connect via:
1627-
1628-```bash
1629-gopls -remote="unix;/tmp/gopls-daemon-socket" -logfile=auto -debug=:0 -rpc.trace
1630-```
1631-
1632-(Note that these flag values MUST be enclosed in quotes, because ';' is a
1633-special shell character. For this reason, this syntax is subject to change in
1634-the future.)
1635-
1636-## Debugging
1637-
1638-Debugging a shared gopls session is more complicated than a singleton session,
1639-because there are now two gopls processes involved with handling the LSP. Here
1640-are some tips:
1641-
1642-### Finding logfiles and debug addresses
1643-
1644-When running in daemon mode, you can use the `gopls inspect sessions` command
1645-to find the logfile and debug port for your gopls daemon instance (as well as
1646-for all its connected clients). By default, this inspects the default daemon
1647-(i.e. `-remote=auto`). To inspect a different daemon, use the `-remote` flag
1648-explicitly: `gopls -remote=localhost:12345 inspect sessions`.
1649-
1650-This works whether or not you have enabled `-remote.debug`.
1651-
1652-### Traversing debug pages
1653-
1654-When `-debug=:0` is passed to gopls, it runs a webserver that serves stateful
1655-debug pages (see [troubleshooting.md](troubleshooting.md)). You can find the
1656-actual port hosting these pages by either using the `gopls inspect sessions`
1657-command, or by checking the start of the logfile -- it will be one of the first
1658-log messages. For example, if using `-logfile=auto`, find the debug address by
1659-checking `head /tmp/gopls-<pid>.log`.
1660-
1661-By default, the gopls daemon is not started with `-debug`. To enable it, set
1662-the `-remote.debug` flag on the forwarder instance, so that it invokes gopls
1663-with `-debug` when starting the daemon.
1664-
1665-The debug pages of the forwarder process will have a link to the debug pages of
1666-the daemon server process. Correspondingly, the debug pages of the daemon
1667-process will have a link to each of its clients.
1668-
1669-This can help you find metrics, traces, and log files for all of the various
1670-servers and clients.
1671-
1672-### Using logfiles
1673-
1674-The gopls daemon is started with logging disabled by default. To customize
1675-this, pass `-remote.logfile` to the gopls forwarder. Using
1676-`-remote.logfile=auto`, the daemon will log to a default location (on posix
1677-systems: `/tmp/gopls-daemon-<pid>.log`).
1678-
1679-The gopls daemon does not log session-scoped messages: those are instead
1680-reflected back to the forwarder so that they can be accessed by the editor.
1681-Daemon logs will only contain global messages, for example logs when sessions
1682-connect and disconnect.
1683-
1684-It is recommended to start the forwarder gopls process with `-rpc.trace`, so
1685-that its logfile will contain rpc trace logs specific to the LSP session.
1686-
1687-## Using multiple shared gopls instances
1688-
1689-There may be environments where it is desirable to have more than one shared
1690-gopls instance. If managing the daemon manually, this can be done by simply
1691-choosing different `-listen` addresses for each distinct daemon process.
1692-
1693-On POSIX systems, there is also support for automatic management of distinct
1694-shared gopls processes: distinct daemons can be selected by passing
1695-`-remote="auto;<id>"`. Any gopls forwarder passing the same value for `<id>`
1696-will use the same shared daemon.
1697-
1698-## FAQ
1699-
1700-**Q: Why am I not saving as much memory as I expected when using a shared gopls?**
1701-
1702-A: As described in [implementation.md](design/implementation.md), gopls has a
1703-concept of view/session/cache. Each session and view map onto exactly one
1704-editor session (because they contain things like edited but unsaved buffers).
1705-The cache contains things that are independent of any editor session, and can
1706-therefore be shared.
1707-
1708-When, for example, three editor session are sharing a single gopls process,
1709-they will share the cache but will each have their own session and view. The
1710-memory savings in this mode, when compared to three separate gopls processes,
1711-corresponds to the amount of cache overlap across sessions.
1712-
1713-Because this hasn't mattered much in the past, it is likely that there is state
1714-that can be moved out of the session/view, and into the cache, thereby
1715-increasing the amount of memory savings in the shared mode.
1716-
1717-**Q: How do I customize the daemon instance when using `-remote=auto`?**
1718-
1719-The daemon may be customized using flags of the form `-remote.*` on the
1720-forwarder gopls. This causes the forwarder to invoke gopls with these settings
1721-when starting the daemon. As of writing, we expose the following configuration:
1722-
1723-* `-remote.logfile`: the location of the daemon logfile
1724-* `-remote.debug`: the daemon's debug address
1725-* `-remote.listen.timeout`: the amount of time the daemon should wait for new
1726-  connections while there are no current connections, before shutting down.
1727-  Must be set to a valid `time.Duration` (e.g. `30s` or `5m`). If `0`, listen
1728-  indefinitely. Default: `1m`.
1729-
1730-Note that once the daemon is already running, setting these flags will not
1731-change its configuration. These flags only matter for the forwarder process
1732-that actually starts the daemon.
1733diff -urN a/gopls/doc/design/design.md b/gopls/doc/design/design.md
1734--- a/gopls/doc/design/design.md	2000-01-01 00:00:00.000000000 -0000
1735+++ b/gopls/doc/design/design.md	1970-01-01 00:00:00.000000000 +0000
1736@@ -1,394 +0,0 @@
1737-# `gopls` design documentation
1738-
1739-## Goals
1740-
1741-* `gopls` should **become the default editor backend** for the major editors used by Go programmers, fully supported by the Go team.
1742-* `gopls` will be a **full implementation of LSP**, as described in the [LSP specification], to standardize as many of its features as possible.
1743-* `gopls` will be **clean and extensible** so that it can encompass additional features in the future, allowing Go tooling to become best in class once more.
1744-* `gopls` will **support alternate build systems and file layouts**, allowing Go development to be simpler and more powerful in any environment.
1745-
1746-## Context
1747-
1748-While Go has a number of excellent and useful command-line tools that enhance the developer experience, it has become clear that integrating these tools with IDEs can pose challenges.
1749-
1750-Support of these tools has relied on the goodwill of community members, and they have been put under a large burden of support at times as the language, toolchain and environments change. As a result many tools have ceased to work, have had support problems, or become confusing with forks and replacements, or provided an experience that is not as good as it could be.
1751-See the section below on [existing solutions](#existing-solutions) for more problems and details.
1752-
1753-This is fine for tools used occasionally, but for core IDE features, this is not acceptable.
1754-Autocompletion, jump to definition, formatting, and other such features should always work, as they are key for Go development.
1755-
1756-The Go team will create an editor backend that works in any build system.
1757-It will also be able to improve upon the latency of Go tools, since each tool will no longer have to individually run the type-checker on each invocation, instead there will be a long-running process and data can be shared between the definitions, completions, diagnostics, and other features.
1758-
1759-By taking ownership of these tools and packaging them together in the form of gopls, the Go team will ensure that the Go development experience isn’t unnecessarily complicated for Go users.
1760-Having one editor backend will simplify the lives of Go developers, the Go team, and the maintainers of Go editor plugins.
1761-
1762-See Rebecca's excellent GopherCon keynote [talk] and [slides] for some more context.
1763-
1764-## Non-Goals
1765-
1766-* Command line speed
1767-
1768-  Although gopls will have a command line mode, it will be optimized for long running and not command responsiveness, as such it may not be the right tool for things like CI systems.
1769-  For such cases there will have to be an alternate tool using the same underlying libraries for consistency.
1770-
1771-* Low memory environments
1772-
1773-  In order to do a good job of processing large projects with very low latencies gopls will be holding a lot of information in memory.
1774-  It is presumed that developers are normally working on systems with significant RAM and this will not be a problem.
1775-  In general this is upheld by the large memory usage of existing IDE solutions (like IntelliJ)
1776-
1777-* Syntax highlighting
1778-
1779-  At the moment there is no editor that delegates this functionality to a separate binary, and no standard way of doing it.
1780-
1781-## Existing solutions
1782-
1783-Every year the Go team conducts a survey, asking developers about their experiences with the language.
1784-
1785-One question that is asked is “How do you feel about your editor?”.
1786-
1787-The responses told a very negative story. Some categorized quotes:
1788-
1789-* Setup
1790-  * "Hard to install and configure"
1791-  * "Inadequate documentation"
1792-* Performance
1793-  * "Performance is very poor"
1794-  * "Pretty slow in large projects"
1795-* Reliability
1796-  * "Features work one day, but not the next"
1797-  * "Tooling is not updated with new language features"
1798-
1799-Each editor has its own plugin that shells out to a variety of tools, many of which break with new Go releases or because they are no longer maintained.
1800-
1801-The individual tools each have to do the work to understand the code and all its transitive dependencies.
1802-
1803-Each feature is a different tool, with a different set of patterns for its command line, a different way to accept input and parse output, a different way of specifying source code locations.
1804-To support its existing feature set, VSCode installed 24 different command line tools, many of which have options or forks to configure. When looking at the set of tools that needed to be migrated to modules, across all the editors, there were 63 separate tools.
1805-
1806-All these tools need to understand the code, and they use the same standard libraries to do it. Those libraries are optimized for these kinds of tools, but even so processing that much code takes a lot of time time. Almost none of the tools are capable of returning results within 100ms.
1807-As developers type in their editor, multiple of these features need to activate, which means they are not just paying the cost once, but many times. The overall effect is an editing experience that feels sluggish, and features that are either not enabled or sometimes produce results that appear so slowly they are no longer useful when they arrive. This is a problem that increases with the size of the code base, which means it is getting worse over time, and is especially bad for the kinds of large code bases companies are dealing with as they use Go for more major tasks.
1808-
1809-## Requirements
1810-
1811-### Complete feature set
1812-
1813-For gopls to be considered a success it has to implement the full feature set discussed [below](#Features).
1814-This is the set of features that users need in order to feel as productive as they were with the tooling it is replacing. It does not include every feature of previous implementations, there are some features that are almost never used that should be dropped (like guru's pointer analysis) and some other features that do not easily fit and will have to be worked around (replacing the save hook/linter).
1815-
1816-### Equivalent or better experience
1817-
1818-For all of those features, the user experience must match or exceed the current one available in all editors.
1819-This is an easy statement to make, but a hard one to validate or measure. Many of the possible measures fail to capture the experience.
1820-
1821-For instance, if an attempt was made to measure the latency of a jump to definition call, the results would be fairly consistent from the old godef tool. From the gopls implementation there may be a much larger range of latencies, with the best being orders of magnitude faster, and the worse slightly worse, because gopls attempts to do far more work, but manages to cache it across calls.
1822-
1823-Or for a completion call, it might be slower but produce a better first match such that users accept it more often, resulting in an overall better experience.
1824-
1825-For the most part this has to rely on user reports. If users are refusing to switch because the experience is not better, it is clearly not done, if they are switching but most people are complaining, there are probably enough areas that are better to make the switch compelling but other areas which are worse. If most people are switching and either staying silent or being positive, it is probably done. When writing tools, the user is all that matters.
1826-
1827-### Solid community of contributors
1828-
1829-The scope and scale of the problem gopls is trying to solve is untenable for the core Go team, it is going to require a strong community to make it all happen.
1830-
1831-This implies the code must be easy to contribute to, and easy for many developers to work on in parallel. The functionality needs to be well decoupled, and have a thorough testing story.
1832-
1833-### Latencies that fall within user tolerance
1834-
1835-There has been a lot of research on acceptable latencies for user actions.
1836-<!-- TODO: research links -->
1837-The main result that affects gopls is that feedback in direct response to continuous user actions needs to be under 100ms to be imperceptible, and anything above 200ms aggravates the user.
1838-This means in general the aim has to be <100ms for anything that happens as the developer types.
1839-There will always be cases where gopls fails to meet this deadline, and there needs to be ways to make the user experience okay in those cases, but in general the point of this deadline is to inform the basic architecture design, any solution that cannot theoretically meet this goal in the long term is the wrong answer.
1840-
1841-### Easy to configure
1842-
1843-Developers are very particular, and have very differing desires in their coding experience. gopls is going to have to support a significant amount of flexibility, in order to meet those desires.
1844-The default settings however with no configuration at all must be the one that is best experience for most users, and where possible the features must be flexible without configuration so that the client can easily make the choices about treatment without changing its communication with gopls.
1845-
1846-## Difficulties
1847-
1848-### Volume of data
1849-
1850-<!-- TODO: project sizes -->
1851-* Small:
1852-* Medium:
1853-* Large:
1854-* Corporate mono-repo: Much much bigger
1855-
1856-Parsing and type checking large amounts of code is quite expensive, and the converted forms use a lot of space. As gopls has to keep updating this information while the developer types, it needs to manage how it caches the converted forms very carefully to balance memory use vs speed.
1857-
1858-### Cache invalidation
1859-
1860-The basic unit of operation for the type checking is the package, but the basic unit of operation for an editor is the file.
1861-gopls needs to be able to map files to packages efficiently, so that when files change it knows which packages need to be updated (along with any other packages that transitively depended on them).
1862-This is made especially difficult by the fact that changing the content of a file can modify which packages it is considered part of (either by changing the package declaration or the build tags), a file can be in more than one package, and changes can be made to files without using the editor, in which case it will not notify us of the changes.
1863-
1864-### Inappropriate core functionality
1865-
1866-The base libraries for Go (things like [go/token], [go/ast] and [go/types]) are all designed for compiler-like applications.
1867-They tend to worry more about throughput than memory use, they have structures that are intended to grow and then be thrown away at program exit, and they are not designed to keep going in the presence of errors in the source they are handling.
1868-They also have no abilities to do incremental changes.
1869-
1870-Making a long running service work well with those libraries is a very large challenge, but writing new libraries would be far more work, and cause a significant long term cost as both sets of libraries would have to be maintained. Right now it is more important to get a working tool into the hands of users. In the long term this decision may have to be revisited, new low level libraries may be the only way to keep pushing the capabilities forwards.
1871-
1872-### Build system capabilities
1873-
1874-gopls is supposed to be build system agnostic, but it must use the build system to discover how files map to packages. When it tries to do so, even when the functionality is the same, the costs (in time, CPU and memory) are very different, and can significantly impact the user experience. Designing how gopls interacts with the build system to try to minimize or hide these differences is hard.
1875-
1876-### Build tags
1877-
1878-The build tag system in Go is quite powerful, and has many use cases. Source files can exclude themselves using powerful boolean logic on the set of active tags.
1879-It is however designed for specifying the set of active tags on the command line, and the libraries are all designed to cope with only one valid combination at a time. There is also no way to work out the set of valid combinations.
1880-
1881-Type checking a file requires knowledge of all the other files in the same package, and that set of files is modified by the build tags. The set of exported identifiers of a package is also affected by which files are in the package, and thus its build tags.
1882-
1883-This means that even for files or packages that have no build tag controls it is not possible to produce correct results without knowing the set of build tags to consider.
1884-This makes it very hard to produce useful results when viewing a file.
1885-
1886-### Features not supported by LSP
1887-
1888-There are some things it would be good to be able to do that do not fit easily into the existing LSP protocol.
1889-For instance, displaying control flow information, automatic struct tags, complex refactoring...
1890-
1891-Each feature will have to be considered carefully, and either propose a change to LSP, or add a way to have gopls specific extensions to the protocol that are still easy to use in all the editor plugins.
1892-
1893-To avoid these at the start, only core LSP features will be implemented, as they are sufficient to meet the baseline requirements anyway, but the potential features need to be kept in mind in the core architecture.
1894-
1895-### Distribution
1896-
1897-Making sure that users are using the right version of gopls is going to be a problem. Each editor plugin is probably going to install the tools in its own way, some will choose to install it system wide, some will keep their own copy.
1898-
1899-Because it is a brand new tool, it will be changing rapidly. If users are not informed they are on an old version they will be experiencing problems that have already been fixed, which is worse for them, and then probably reporting them, which wastes time for the gopls team. There needs to be a mechanism for gopls to check if is up to date, and a recommended way to install an up to date version.
1900-
1901-### Debugging user problems
1902-
1903-gopls is essentially a very stateful long running server on the developer's machine. Its basic operation is affected by many things, from the users environment to the contents of the local build cache. The data it is operating on is often a confidential code base that cannot be shared.
1904-All of these things make it hard for users to report a bug usefully, or create a minimal reproduction.
1905-
1906-There needs to be easy ways for users to report what information they can, and ways to attempt to reproduce problems without their entire state. This is also needed to produce regression tests.
1907-
1908-## Basic design decisions
1909-
1910-There are some fundamental architecture decisions that affect much of the rest of the design of the tool, making fundamental trade offs that impact the user experience.
1911-
1912-### Process lifetime: *managed by the editor*
1913-
1914-Processing a large code base to fully type check and then analyze it within the latency requirements is not feasible, and is one of the primary problems with the existing solutions. This remains true even if the computed information was cached on disk, as running analyzers and type checkers ends up requiring the full AST of all files in the dependency graph.
1915-It is theoretically possible to do better, but only with a major re-write of the existing parsing and type checking libraries, something that is not feasible at this time.
1916-
1917-This implies that gopls should be a long running process, that is able to cache and pre-calculate results in memory so that when a request arrives it can produce the answer much faster.
1918-
1919-It could run as a daemon on the user's machine, but there are a lot of issues with managing a daemon. It may well be the right choice in the long term, and it should be allowed for in the fundamental architecture design, but to start with it will instead have a process that lasts as long as the editor that starts it, and that can easily be restarted.
1920-
1921-### Caching: *in memory*
1922-
1923-Persistent disk caches are very expensive to maintain, and require solving a lot of extra problems.
1924-Although building the information required is expensive compared to the latencies required of the requests, it is fairly minor compared to the startup times of an editor, so it is expected that rebuilding the information when gopls is restarted will be acceptable.
1925-
1926-The advantage gained from this is that gopls becomes stateless across restarts which means if it has issues or gets its state confused, a simple restart will often fix the problem.
1927-It also means that when users report problems, the entire state of the on disk cache is not needed to diagnose and reproduce the issue.
1928-
1929-### Communication: *stdin/stdout JSON*
1930-
1931-The LSP specification defines the JSON messages that are normally used, but it does not define how those message should be sent, and there are implementations of the LSP that do not use JSON (for instance, Protocol buffers are an option).
1932-
1933-The constraints on gopls are that it must be easy to integrate into *every editor* on *all operating systems*, and that it should not have large external dependencies.
1934-
1935-JSON is part of the Go standard library, and is also the native language of LSP, so it makes the most sense. By far the best supported communication mechanism is the standard input and output of a process, and the common client implementations all have ways of using [JSON rpc 2] in this mode.  There were no complete and low dependency implementations of this protocol in Go, but it is a fairly small protocol on top of the JSON library that can be implemented with a moderate effort, and would be a generally useful library to have anyway.
1936-
1937-In the future it is expected to run in separated client server mode, so writing it in a way that could use sockets instead of stdin/stdout from the start was the best way to make sure it remained possible. It was also a huge debugging aid to be able to run the gopls server by hand and watch/debug it outside the editor.
1938-
1939-### Running other tools: *no*
1940-
1941-<!--- TODO: subprocess discuss --->
1942-
1943-## Features
1944-
1945-<!--TODO(rstambler): Generate a file that lists all of the supported features.-->
1946-
1947-There is a set of features that gopls needs to expose to be a comprehensive IDE solution.
1948-The following is the minimum set of features, along with their existing solutions and how they should map to the LSP.
1949-
1950-### Introspection
1951-
1952-Introspection features tell developers information about their code while they work. They do not make or suggest changes.
1953-
1954----
1955-Diagnostics | Static analysis results of the code, including compilation and lint errors
1956------------ | ---
1957-Requires    | Full go/analysis run, which needs full AST, type and SSA information
1958-LSP         | [`textDocument/publishDiagnostics`]
1959-Previous    | `go build`, `go vet`, `golint`, [errcheck], [staticcheck] <!-- TODO: and all the rest -->
1960-|           | This is one of the most important IDE features, allowing fast turn around without having to run compilers and checkers in the shell. Often used to power problem lists, gutter markers and squiggle underlines in the IDE. <br/> There is some complicated design work to do in order to let users customize the set of checks being run, preferably without having to recompile the main LSP binary.
1961-
1962----
1963-Hover    | Information about the code under the cursor.
1964--------- | ---
1965-Requires | AST and type information for the file and all dependencies
1966-LSP      | [`textDocument/hover`]
1967-Previous | [godoc], [gogetdoc]
1968-|        | Used when reading code to display information known to the compiler but not always obvious from the code. For instance it may return the types of identifiers, or the documentation.
1969-
1970----
1971-Signature help | Function parameter information and documentation
1972--------------- | ---
1973-Requires       | AST and type information for the file and all dependencies
1974-LSP            | [`textDocument/signatureHelp`]
1975-Previous       | [gogetdoc]
1976-|              | As a function call is being typed into code, it is helpful to know the parameters of that call to enable the developer to call it correctly.
1977-
1978-### Navigation
1979-
1980-Navigation features are designed to make it easier for a developer to find their way round a code base.
1981-
1982----
1983-Definition | Select an identifier, and jump to the code where that identifier was defined.
1984----------- | ---
1985-Requires   | Full type information for file and all dependencies
1986-LSP        | [`textDocument/declaration`]
1987-|          | [`textDocument/definition`]
1988-|          | [`textDocument/typeDefinition`]
1989-Previous   | [godef] |
1990-|          | Asking the editor to open the place where a symbol was defined is one of the most commonly used code navigation tools inside an IDE when available. It is especially valuable when exploring an unfamiliar code base.<br/>Due to a limitation of the compiler output, it is not possible to use the binary data for this task (specifically it does not know column information) and thus it must parse from source.
1991-
1992----
1993-Implementation | Reports the types that implement an interface
1994--------------- | ---
1995-Requires       | Full workspace type knowledge
1996-LSP            | [`textDocument/implementation`]
1997-Previous       | [impl]
1998-|              | This feature is hard to scale up to large code bases, and is going to take thought to get right. It may be feasible to implemented a more limited form in the meantime.
1999-
2000----
2001-Document symbols | Provides the set of top level symbols in the current file.
2002----------------- | ---
2003-Requires         | AST of the current file only
2004-LSP              | [`textDocument/documentSymbol`]
2005-Previous         | [go-outline], [go-symbols]
2006-|                | Used to drive things like outline mode.
2007-
2008----
2009-References | Find all references to the symbol under the cursor.
2010----------- | ---
2011-Requires   | AST and type information for the **reverse** transitive closure
2012-LSP        | [`textDocument/references`]
2013-Previous   | [guru]
2014-|          | This requires knowledge of every package that could possible depend on any packages the current file is part of. In the past this has been implemented either by global knowledge, which does not scale, or by specifying a "scope" which confused users to the point where they just did not use the tools. gopls is probably going to need a more powerful solution in the long term, but to start with automatically limiting the scope may produce acceptable results. This would probably be the module if known, or some sensible parent directory otherwise.
2015-
2016----
2017-Folding  | Report logical hierarchies of blocks
2018--------- | ---
2019-Requires | AST of the current file only
2020-LSP      | [`textDocument/foldingRange`]
2021-Previous | [go-outline]
2022-|        | This is normally used to provide expand and collapse behavior in editors.
2023-
2024----
2025-Selection | Report regions of logical selection around the cursor
2026---------- | ---
2027-Requires  | AST of the current file only
2028-LSP       | [`textDocument/selectionRange`]
2029-Previous  | [guru]
2030-|         | Used in editor features like expand selection.
2031-
2032-
2033-### Edit assistance
2034-
2035-These features suggest or apply edits to the code for the user, including refactoring features, for which there are many potential use cases.
2036-Refactoring is one of the places where Go tools could potentially be very strong, but have not been so far, and thus there is huge potential for improvements in the developer experience.
2037-There is not yet a clear understanding of the kinds of refactoring people need or how they should express them however, and there are weaknesses in the LSP protocol around this.
2038-This means it may be much more of a research project.
2039-
2040-
2041----
2042-Format   | Fix the formatting of the file
2043--------- | ---
2044-Requires | AST of current file
2045-LSP      | [`textDocument/formatting`]
2046-|        | [`textDocument/rangeFormatting`]
2047-|        | [`textDocument/onTypeFormatting`]
2048-Previous | [gofmt], [goimports], [goreturns]
2049-|        | It will use the standard format package. <br/> Current limitations are that it does not work on malformed code. It may need some very careful changes to the formatter to allow for formatting an invalid AST or changes to force the AST to a valid mode. These changes would improve range and file mode as well, but are basically vital to onTypeFormatting
2050-
2051----
2052-Imports  | Rewrite the imports block automatically to match the symbols used.
2053--------- | ---
2054-Requires | AST of the current file and full symbol knowledge for all candidate packages.
2055-LSP      | [`textDocument/codeAction`]
2056-Previous | [goimports], [goreturns]
2057-|        | This needs knowledge of packages that are not yet in use, and the ability to find those packages by name. <br/> It also needs exported symbol information for all the packages it discovers. <br/> It should be implemented using the standard imports package, but there may need to be exposed a more fine grained API than just a file rewrite for some of the interactions.
2058-
2059----
2060-Autocompletion | Makes suggestions to complete the entity currently being typed.
2061--------------- | ---
2062-Requires       | AST and type information for the file and all dependencies<br/> Also full exported symbol knowledge for all packages.
2063-LSP            | [`textDocument/completion`]
2064-|              | [`completionItem/resolve`]
2065-Previous       | [gocode]
2066-|              | Autocomplete is one of the most complicated features, and the more it knows the better its suggestions can be. For instance it can autocomplete into packages that are not yet being imported if it has their public symbols. It can make better suggestions of options if it knows what kind of program you are writing. It can suggest better arguments if it knows how you normally call a function. It can suggest entire patterns of code if it knows they are common. Unlike many other features, which have a specific task, and once it is doing that task the feature is done, autocomplete will never be finished. Balancing and improving both the candidates and how they are ranked will be a research problem for a long time to come.
2067-
2068----
2069-Rename   | Rename an identifier
2070--------- | ---
2071-Requires | AST and type information for the **reverse** transitive closure
2072-LSP      | [`textDocument/rename`]
2073-|        | [`textDocument/prepareRename`]
2074-Previous | [gorename]
2075-|        | This uses the same information that find references does, with all the same problems and limitations. It is slightly worse because the changes it suggests make it intolerant of incorrect results. It is also dangerous using it to change the public API of a package.
2076-
2077----
2078-Suggested fixes | Suggestions that can be manually or automatically accepted to change the code
2079---------------- | ---
2080-Requires        | Full go/analysis run, which needs full AST, type and SSA information
2081-LSP             | [`textDocument/codeAction`]
2082-Previous        | N/A
2083-|               | This is a brand new feature powered by the new go/analysis engine, and it should allow a huge amount of automated refactoring.
2084-
2085-[LSP specification]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/
2086-[talk]: TODO
2087-[slides]: https://github.com/gophercon/2019-talks/blob/master/RebeccaStambler-GoPleaseStopBreakingMyEditor/slides.pdf "Go, please stop breaking my editor!"
2088-[JSON rpc 2]: https://www.jsonrpc.org/specification
2089-
2090-[errcheck]: https://github.com/kisielk/errcheck
2091-[go-outline]: https://github.com/lukehoban/go-outline
2092-[go-symbols]: https://github.com/acroca/go-symbols
2093-[gocode]: https://github.com/stamblerre/gocode
2094-[godef]: https://github.com/rogpeppe/godef
2095-[godoc]: https://golang.org/cmd/godoc
2096-[gofmt]: https://golang.org/cmd/gofmt
2097-[gogetdoc]: https://github.com/zmb3/gogetdoc
2098-[goimports]: https://pkg.go.dev/golang.org/x/tools/cmd/goimports
2099-[gorename]: https://pkg.go.dev/golang.org/x/tools/cmd/gorename
2100-[goreturns]: https://github.com/sqs/goreturns
2101-[gotags]: https://github.com/jstemmer/gotags
2102-[guru]: https://pkg.go.dev/golang.org/x/tools/cmd/guru
2103-[impl]: https://github.com/josharian/impl
2104-[staticcheck]: https://staticcheck.io/docs/
2105-[go/types]: https://golang.org/pkg/go/types/
2106-[go/ast]: https://golang.org/pkg/go/ast/
2107-[go/token]: https://golang.org/pkg/go/token/
2108-
2109-[`completionItem/resolve`]:https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#completionItem_resolve
2110-[`textDocument/codeAction`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_codeAction
2111-[`textDocument/completion`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_completion
2112-[`textDocument/declaration`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_declaration
2113-[`textDocument/definition`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_definition
2114-[`textDocument/documentLink`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_documentLink
2115-[`textDocument/documentSymbol`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_documentSymbol
2116-[`textDocument/foldingRange`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_foldingRange
2117-[`textDocument/formatting`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_formatting
2118-[`textDocument/highlight`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_highlight
2119-[`textDocument/hover`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_hover
2120-[`textDocument/implementation`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_implementation
2121-[`textDocument/onTypeFormatting`]:https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_onTypeFormatting
2122-[`textDocument/prepareRename`]:https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_prepareRename
2123-[`textDocument/publishDiagnostics`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_publishDiagnostics
2124-[`textDocument/rangeFormatting`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_rangeFormatting
2125-[`textDocument/references`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_references
2126-[`textDocument/rename`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_rename
2127-[`textDocument/selectionRange`]:https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_selectionRange
2128-[`textDocument/signatureHelp`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_signatureHelp
2129-[`textDocument/typeDefinition`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_typeDefinition
2130-[`workspace/didChangeWatchedFiles`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#workspace_didChangeWatchedFiles
2131diff -urN a/gopls/doc/design/implementation.md b/gopls/doc/design/implementation.md
2132--- a/gopls/doc/design/implementation.md	2000-01-01 00:00:00.000000000 -0000
2133+++ b/gopls/doc/design/implementation.md	1970-01-01 00:00:00.000000000 +0000
2134@@ -1,48 +0,0 @@
2135-# gopls implementation documentation
2136-
2137-This is not intended as a complete description of the implementation, for the most the part the package godoc, code comments and the code itself hold that.
2138-Instead this is meant to be a guide into finding parts of the implementation, and understanding some core concepts used throughout the implementation.
2139-
2140-## View/Session/Cache
2141-
2142-Throughout the code there are references to these three concepts, and they build on each other.
2143-
2144-At the base is the *Cache*. This is the level at which we hold information that is global in nature, for instance information about the file system and its contents.
2145-
2146-Above that is the *Session*, which holds information for a connection to an editor. This layer hold things like the edited files (referred to as overlays).
2147-
2148-The top layer is called the *View*. This holds the configuration, and the mapping to configured packages.
2149-
2150-The purpose of this layering is to allow a single editor session to have multiple views active whilst still sharing as much information as possible for efficiency.
2151-In theory if only the View layer existed, the results would be identical, but slower and using more memory.
2152-
2153-## Code location
2154-
2155-gopls will be developed in the [x/tools] Go repository; the core packages are in [internal/lsp], and the binary and integration tests are located in [gopls].
2156-
2157-Below is a list of the core packages of gopls, and their primary purpose:
2158-
2159-Package | Description
2160---- | ---
2161-[gopls] | the main binary, plugins and integration tests
2162-[internal/lsp] | the core message handling package
2163-[internal/lsp/cache] | the cache layer
2164-[internal/lsp/cmd] | the gopls command line layer
2165-[internal/lsp/debug] | features to aid in debugging gopls
2166-[internal/lsp/protocol] | the types of LSP request and response messages
2167-[internal/lsp/source] | the core feature implementations
2168-[internal/span] | a package for dealing with source file locations
2169-[internal/memoize] | a function invocation cache used to reduce the work done
2170-[internal/jsonrpc2] | an implementation of the JSON RPC2 specification
2171-
2172-[gopls]: https://github.com/golang/tools/tree/master/gopls
2173-[internal/jsonrpc2]: https://github.com/golang/tools/tree/master/internal/jsonrpc2
2174-[internal/lsp]: https://github.com/golang/tools/tree/master/internal/lsp
2175-[internal/lsp/cache]: https://github.com/golang/tools/tree/master/internal/lsp/cache
2176-[internal/lsp/cmd]: https://github.com/golang/tools/tree/master/internal/lsp/cmd
2177-[internal/lsp/debug]: https://github.com/golang/tools/tree/master/internal/lsp/debug
2178-[internal/lsp/protocol]: https://github.com/golang/tools/tree/master/internal/lsp/protocol
2179-[internal/lsp/source]: https://github.com/golang/tools/tree/master/internal/lsp/source
2180-[internal/memoize]: https://github.com/golang/tools/tree/master/internal/memoize
2181-[internal/span]: https://github.com/golang/tools/tree/master/internal/span
2182-[x/tools]: https://github.com/golang/tools
2183diff -urN a/gopls/doc/design/integrating.md b/gopls/doc/design/integrating.md
2184--- a/gopls/doc/design/integrating.md	2000-01-01 00:00:00.000000000 -0000
2185+++ b/gopls/doc/design/integrating.md	1970-01-01 00:00:00.000000000 +0000
2186@@ -1,91 +0,0 @@
2187-# Documentation for plugin authors
2188-
2189-If you are integrating `gopls` into an editor by writing an editor plugin, there are quite a few semantics of the communication between the editor and `gopls` that are not specified by the [LSP specification].
2190-
2191-We attempt to document those details along with any other information that has been helpful to other plugin authors here.
2192-
2193-If you are implementing a plugin yourself and have questions this page does not answer, please reach out to us to ask, and then also contribute your findings back to this page.
2194-
2195-## Supported features
2196-
2197-For the most part you should look at the [list](status.md#supported-features) in the current status document to know if gopls supports a feature.
2198-For a truly authoritative answer you should check the [result][InitializeResult] of the [initialize] request, where gopls enumerates its support in the [ServerCapabilities].
2199-
2200-
2201-## Positions and ranges
2202-
2203-Many LSP requests pass position or range information. This is described in the [LSP specification][lsp-text-documents]:
2204-
2205-> A position inside a document (see Position definition below) is expressed as a zero-based line and character offset. The offsets are based on a UTF-16 string representation. So a string of the form a��b the character offset of the character a is 0, the character offset of �� is 1 and the character offset of b is 3 since �� is represented using two code units in UTF-16.
2206-
2207-This means that integrators will need to calculate UTF-16 based column offsets.
2208-
2209-[`golang.org/x/tools/gopls/internal/span`] has the code to do this in go.
2210-[#31080] tracks making `span` and other useful packages non-internal.
2211-
2212-## Edits
2213-
2214-In order to deliver changes from gopls to the editor, the LSP supports arrays of [`TextEdit`][lsp-textedit]s in responses.
2215-The spec specifies exactly how these should be applied:
2216-
2217-> All text edits ranges refer to positions in the original document. Text edits ranges must never overlap, that means no part of the original document must be manipulated by more than one edit. However, it is possible that multiple edits have the same start position: multiple inserts, or any number of inserts followed by a single remove or replace edit. If multiple inserts have the same position, the order in the array defines the order in which the inserted strings appear in the resulting text.
2218-
2219-All `[]TextEdit` are sorted such that applying the array of deltas received in reverse order achieves the desired result that holds with the spec.
2220-
2221-## Errors
2222-
2223-Various error codes are described in the [LSP specification][lsp-response]. We are still determining what it means for a method to return an error; are errors only for low-level LSP/transport issues or can other conditions cause errors to be returned? See some of this discussion on [#31526].
2224-
2225-The method chosen is currently influenced by the exact treatment in the currently popular editor integrations. It may well change, and ideally would become more coherent across requests.
2226-
2227-* [`textDocument/codeAction`]: Return error if there was an error computing code actions.
2228-* [`textDocument/completion`]: Log errors, return empty result list.
2229-* [`textDocument/definition`]: Return error if there was an error computing the definition for the position.
2230-* [`textDocument/typeDefinition`]: Return error if there was an error computing the type definition for the position.
2231-* [`textDocument/formatting`]: Return error if there was an error formatting the file.
2232-* [`textDocument/highlight`]: Log errors, return empty result.
2233-* [`textDocument/hover`]: Return empty result.
2234-* [`textDocument/documentLink`]: Log errors, return nil result.
2235-* [`textDocument/publishDiagnostics`]: Log errors if there were any while computing diagnostics.
2236-* [`textDocument/references`]: Log errors, return empty result.
2237-* [`textDocument/rename`]: Return error if there was an error computing renames.
2238-* [`textDocument/signatureHelp`]: Log errors, return nil result.
2239-* [`textDocument/documentSymbols`]: Return error if there was an error computing document symbols.
2240-
2241-## Watching files
2242-
2243-It is fairly normal for files that affect `gopls` to be modified outside of the editor it is associated with.
2244-
2245-For instance, files that are needed to do correct type checking are modified by switching branches in git, or updated by a code generator.
2246-
2247-Monitoring files inside gopls directly has a lot of awkward problems, but the [LSP specification] has methods that allow gopls to request that the client notify it of file system changes, specifically [`workspace/didChangeWatchedFiles`].
2248-This is currently being added to gopls by a community member, and tracked in [#31553]
2249-
2250-[InitializeResult]: https://pkg.go.dev/golang.org/x/tools/gopls/internal/lsp/protocol#InitializeResult
2251-[ServerCapabilities]: https://pkg.go.dev/golang.org/x/tools/gopls/internal/lsp/protocol#ServerCapabilities
2252-[`golang.org/x/tools/gopls/internal/span`]: https://pkg.go.dev/golang.org/x/tools/internal/span#NewPoint
2253-
2254-[LSP specification]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/
2255-[lsp-response]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#response-message
2256-[initialize]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/#initialize
2257-[lsp-text-documents]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#text-documents
2258-[lsp-textedit]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textedit
2259-
2260-[`textDocument/codeAction`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_codeAction
2261-[`textDocument/completion`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_completion
2262-[`textDocument/definition`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_definition
2263-[`textDocument/typeDefinition`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_typeDefinition
2264-[`textDocument/formatting`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_formatting
2265-[`textDocument/highlight`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_highlight
2266-[`textDocument/hover`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_hover
2267-[`textDocument/documentLink`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_documentLink
2268-[`textDocument/publishDiagnostics`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_publishDiagnostics
2269-[`textDocument/references`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_references
2270-[`textDocument/rename`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_rename
2271-[`textDocument/signatureHelp`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_signatureHelp
2272-[`textDocument/documentSymbols`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_documentSymbols
2273-[`workspace/didChangeWatchedFiles`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#workspace_didChangeWatchedFiles
2274-
2275-[#31080]: https://github.com/golang/go/issues/31080
2276-[#31553]: https://github.com/golang/go/issues/31553
2277-[#31526]: https://github.com/golang/go/issues/31526
2278diff -urN a/gopls/doc/emacs.md b/gopls/doc/emacs.md
2279--- a/gopls/doc/emacs.md	2000-01-01 00:00:00.000000000 -0000
2280+++ b/gopls/doc/emacs.md	1970-01-01 00:00:00.000000000 +0000
2281@@ -1,183 +0,0 @@
2282-# Emacs
2283-
2284-## Installing `gopls`
2285-
2286-To use `gopls` with Emacs, you must first
2287-[install the `gopls` binary](../README.md#installation) and ensure that the directory
2288-containing the resulting binary (either `$(go env GOBIN)` or `$(go env
2289-GOPATH)/bin`) is in your `PATH`.
2290-
2291-## Choosing an Emacs LSP client
2292-
2293-To use `gopls` with Emacs, you will need to choose and install an Emacs LSP
2294-client package. Two popular client packages are [LSP Mode] and [Eglot].
2295-
2296-LSP Mode takes a batteries-included approach, with many integrations enabled
2297-“out of the box” and several additional behaviors provided by `lsp-mode` itself.
2298-
2299-Eglot takes a minimally-intrusive approach, focusing on smooth integration with
2300-other established packages. It provides a few of its own `eglot-` commands but
2301-no additional keybindings by default.
2302-
2303-Once you have selected which client you want to use, install it per the packages
2304-instructions: see [Eglot 1-2-3](https://github.com/joaotavora/eglot#1-2-3) or
2305-[LSP Mode Installation](https://emacs-lsp.github.io/lsp-mode/page/installation/).
2306-
2307-## Common configuration
2308-
2309-Both Eglot and LSP Mode can integrate with popular packages in the Emacs
2310-ecosystem:
2311-
2312-* The built-in [`xref`] package provides cross-references.
2313-* The built-in [Flymake] package provides an on-the-fly diagnostic overlay.
2314-* [Company] mode displays code completion candidates (with a richer UI than
2315-  the built-in [`completion-at-point`]).
2316-
2317-Eglot provides documentation using the built-in [ElDoc] minor mode, while LSP
2318-Mode by default provides documentation using its own [`lsp-ui`] mode.
2319-
2320-Eglot by default locates the project root using the [`project`] package. In LSP
2321-Mode, this behavior can be configured using the `lsp-auto-guess-root` setting.
2322-
2323-## Configuring LSP Mode
2324-
2325-### Loading LSP Mode in `.emacs`
2326-
2327-```elisp
2328-(require 'lsp-mode)
2329-(add-hook 'go-mode-hook #'lsp-deferred)
2330-
2331-;; Set up before-save hooks to format buffer and add/delete imports.
2332-;; Make sure you don't have other gofmt/goimports hooks enabled.
2333-(defun lsp-go-install-save-hooks ()
2334-  (add-hook 'before-save-hook #'lsp-format-buffer t t)
2335-  (add-hook 'before-save-hook #'lsp-organize-imports t t))
2336-(add-hook 'go-mode-hook #'lsp-go-install-save-hooks)
2337-```
2338-
2339-### Configuring `gopls` via LSP Mode
2340-
2341-See [settings] for information about available gopls settings.
2342-
2343-Stable gopls settings have corresponding configuration variables in `lsp-mode`.
2344-For example, `(setq lsp-gopls-use-placeholders nil)` will disable placeholders
2345-in completion snippets. See [`lsp-go`] for a list of available variables.
2346-
2347-Experimental settings can be configured via `lsp-register-custom-settings`:
2348-
2349-```lisp
2350-(lsp-register-custom-settings
2351- '(("gopls.completeUnimported" t t)
2352-   ("gopls.staticcheck" t t)))
2353-```
2354-
2355-Note that after changing settings you must restart gopls using e.g. `M-x
2356-lsp-restart-workspace`.
2357-
2358-## Configuring Eglot
2359-
2360-### Configuring `project` for Go modules in `.emacs`
2361-
2362-Eglot uses the built-in `project` package to identify the LSP workspace for a
2363-newly-opened buffer. The `project` package does not natively know about `GOPATH`
2364-or Go modules. Fortunately, you can give it a custom hook to tell it to look for
2365-the nearest parent `go.mod` file (that is, the root of the Go module) as the
2366-project root.
2367-
2368-```elisp
2369-(require 'project)
2370-
2371-(defun project-find-go-module (dir)
2372-  (when-let ((root (locate-dominating-file dir "go.mod")))
2373-    (cons 'go-module root)))
2374-
2375-(cl-defmethod project-root ((project (head go-module)))
2376-  (cdr project))
2377-
2378-(add-hook 'project-find-functions #'project-find-go-module)
2379-```
2380-
2381-### Loading Eglot in `.emacs`
2382-
2383-```elisp
2384-;; Optional: load other packages before eglot to enable eglot integrations.
2385-(require 'company)
2386-(require 'yasnippet)
2387-
2388-(require 'go-mode)
2389-(require 'eglot)
2390-(add-hook 'go-mode-hook 'eglot-ensure)
2391-
2392-;; Optional: install eglot-format-buffer as a save hook.
2393-;; The depth of -10 places this before eglot's willSave notification,
2394-;; so that that notification reports the actual contents that will be saved.
2395-(defun eglot-format-buffer-on-save ()
2396-  (add-hook 'before-save-hook #'eglot-format-buffer -10 t))
2397-(add-hook 'go-mode-hook #'eglot-format-buffer-on-save)
2398-```
2399-
2400-### Configuring `gopls` via Eglot
2401-
2402-See [settings] for information about available gopls settings.
2403-
2404-LSP server settings are controlled by the `eglot-workspace-configuration`
2405-variable, which can be set either globally in `.emacs` or in a `.dir-locals.el` file in the project root.
2406-
2407-`.emacs`:
2408-```elisp
2409-(setq-default eglot-workspace-configuration
2410-    '((:gopls .
2411-        ((staticcheck . t)
2412-         (matcher . "CaseSensitive")))))
2413-```
2414-
2415-`.dir-locals.el`:
2416-```elisp
2417-((nil (eglot-workspace-configuration . ((gopls . ((staticcheck . t)
2418-						  (matcher . "CaseSensitive")))))))
2419-```
2420-
2421-### Organizing imports with Eglot
2422-
2423-`gopls` provides the import-organizing functionality of `goimports` as an LSP
2424-code action, which you can invoke as needed by running `M-x eglot-code-actions`
2425-(or a key of your choice bound to the `eglot-code-actions` function) and
2426-selecting `Organize Imports` at the prompt.
2427-
2428-Eglot does not currently support a standalone function to execute a specific
2429-code action (see
2430-[joaotavora/eglot#411](https://github.com/joaotavora/eglot/issues/411)), nor an
2431-option to organize imports as a `before-save-hook` (see
2432-[joaotavora/eglot#574](https://github.com/joaotavora/eglot/issues/574)). In the
2433-meantime, see those issues for discussion and possible workarounds.
2434-
2435-## Troubleshooting
2436-
2437-Common errors:
2438-
2439-* When prompted by Emacs for your project folder, if you are using modules you
2440-  must select the module's root folder (i.e. the directory with the "go.mod").
2441-  If you are using GOPATH, select your $GOPATH as your folder.
2442-* Emacs must have your environment set properly (PATH, GOPATH, etc). You can
2443-  run `M-x getenv <RET> PATH <RET>` to see if your PATH is set in Emacs. If
2444-  not, you can try starting Emacs from your terminal, using [this
2445-  package][exec-path-from-shell], or moving your shell config from `.bashrc`
2446-  into `.profile` and logging out and back in.
2447-* Make sure only one LSP client mode is installed. (For example, if using
2448-  `lsp-mode`, ensure that you are not _also_ enabling `eglot`.)
2449-* Look for errors in the `*lsp-log*` buffer or run `M-x eglot-events-buffer`.
2450-* Ask for help in the `#emacs` channel on the [Gophers slack].
2451-
2452-[LSP Mode]: https://emacs-lsp.github.io/lsp-mode/
2453-[Eglot]: https://github.com/joaotavora/eglot/blob/master/README.md
2454-[`xref`]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html
2455-[Flymake]: https://www.gnu.org/software/emacs/manual/html_node/flymake/Using-Flymake.html#Using-Flymake
2456-[Company]: https://company-mode.github.io/
2457-[`completion-at-point`]: https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion-in-Buffers.html
2458-[ElDoc]: https://elpa.gnu.org/packages/eldoc.html
2459-[`lsp-ui`]: https://emacs-lsp.github.io/lsp-ui/
2460-[`lsp-go`]: https://github.com/emacs-lsp/lsp-mode/blob/master/clients/lsp-go.el
2461-[`use-package`]: https://github.com/jwiegley/use-package
2462-[`exec-path-from-shell`]: https://github.com/purcell/exec-path-from-shell
2463-[settings]: settings.md
2464-[Gophers slack]: https://invite.slack.golangbridge.org/
2465diff -urN a/gopls/doc/features.md b/gopls/doc/features.md
2466--- a/gopls/doc/features.md	2000-01-01 00:00:00.000000000 -0000
2467+++ b/gopls/doc/features.md	1970-01-01 00:00:00.000000000 +0000
2468@@ -1,55 +0,0 @@
2469-# Features
2470-
2471-This document describes some of the features supported by `gopls`. It is
2472-currently under construction, so, for a comprehensive list, see the
2473-[Language Server Protocol](https://microsoft.github.io/language-server-protocol/).
2474-
2475-## Special features
2476-
2477-Here, only special features outside of the LSP are described.
2478-
2479-### Symbol Queries
2480-
2481-Gopls supports some extended syntax for `workspace/symbol` requests, when using
2482-the `fuzzy` symbol matcher (the default). Inspired by the popular fuzzy matcher
2483-[FZF](https://github.com/junegunn/fzf), the following special characters are
2484-supported within symbol queries:
2485-
2486-| Character | Usage     | Match        |
2487-| --------- | --------- | ------------ |
2488-| `'`       | `'abc`    | exact        |
2489-| `^`       | `^printf` | exact prefix |
2490-| `$`       | `printf$` | exact suffix |
2491-
2492-## Template Files
2493-
2494-Gopls provides some support for Go template files, that is, files that
2495-are parsed by `text/template` or `html/template`.
2496-Gopls recognizes template files based on their file extension, which may be
2497-configured by the
2498-[`templateExtensions`](https://github.com/golang/tools/blob/master/gopls/doc/settings.md#templateextensions-string) setting.
2499-Making this list empty turns off template support.
2500-
2501-In template files, template support works inside
2502-the default `{{` delimiters. (Go template parsing
2503-allows the user to specify other delimiters, but
2504-gopls does not know how to do that.)
2505-
2506-Gopls template support includes the following features:
2507-+ **Diagnostics**: if template parsing returns an error,
2508-it is presented as a diagnostic. (Missing functions do not produce errors.)
2509-+ **Syntax Highlighting**: syntax highlighting is provided for template files.
2510-+  **Definitions**: gopls provides jump-to-definition inside templates, though it does not understand scoping (all templates are considered to be in one global scope).
2511-+  **References**: gopls provides find-references, with the same scoping limitation as definitions.
2512-+ **Completions**: gopls will attempt to suggest completions inside templates.
2513-
2514-### Configuring your editor
2515-
2516-In addition to configuring `templateExtensions`, you may need to configure your
2517-editor or LSP client to activate `gopls` for template files. For example, in
2518-`VS Code` you will need to configure both
2519-[`files.associations`](https://code.visualstudio.com/docs/languages/identifiers)
2520-and `build.templateExtensions` (the gopls setting).
2521-
2522-<!--TODO(rstambler): Automatically generate a list of supported features.-->
2523-
2524diff -urN a/gopls/doc/generate.go b/gopls/doc/generate.go
2525--- a/gopls/doc/generate.go	2000-01-01 00:00:00.000000000 -0000
2526+++ b/gopls/doc/generate.go	1970-01-01 00:00:00.000000000 +0000
2527@@ -1,778 +0,0 @@
2528-// Copyright 2020 The Go Authors. All rights reserved.
2529-// Use of this source code is governed by a BSD-style
2530-// license that can be found in the LICENSE file.
2531-
2532-//go:build go1.16
2533-// +build go1.16
2534-
2535-// Command generate creates API (settings, etc) documentation in JSON and
2536-// Markdown for machine and human consumption.
2537-package main
2538-
2539-import (
2540-	"bytes"
2541-	"encoding/json"
2542-	"fmt"
2543-	"go/ast"
2544-	"go/format"
2545-	"go/token"
2546-	"go/types"
2547-	"io"
2548-	"io/ioutil"
2549-	"os"
2550-	"os/exec"
2551-	"path/filepath"
2552-	"reflect"
2553-	"regexp"
2554-	"sort"
2555-	"strconv"
2556-	"strings"
2557-	"time"
2558-	"unicode"
2559-
2560-	"github.com/jba/printsrc"
2561-	"golang.org/x/tools/go/ast/astutil"
2562-	"golang.org/x/tools/go/packages"
2563-	"golang.org/x/tools/gopls/internal/lsp/command"
2564-	"golang.org/x/tools/gopls/internal/lsp/command/commandmeta"
2565-	"golang.org/x/tools/gopls/internal/lsp/mod"
2566-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
2567-	"golang.org/x/tools/gopls/internal/lsp/source"
2568-)
2569-
2570-func main() {
2571-	if _, err := doMain(true); err != nil {
2572-		fmt.Fprintf(os.Stderr, "Generation failed: %v\n", err)
2573-		os.Exit(1)
2574-	}
2575-}
2576-
2577-func doMain(write bool) (bool, error) {
2578-	api, err := loadAPI()
2579-	if err != nil {
2580-		return false, err
2581-	}
2582-
2583-	sourceDir, err := pkgDir("golang.org/x/tools/gopls/internal/lsp/source")
2584-	if err != nil {
2585-		return false, err
2586-	}
2587-
2588-	if ok, err := rewriteFile(filepath.Join(sourceDir, "api_json.go"), api, write, rewriteAPI); !ok || err != nil {
2589-		return ok, err
2590-	}
2591-
2592-	goplsDir, err := pkgDir("golang.org/x/tools/gopls")
2593-	if err != nil {
2594-		return false, err
2595-	}
2596-
2597-	if ok, err := rewriteFile(filepath.Join(goplsDir, "doc", "settings.md"), api, write, rewriteSettings); !ok || err != nil {
2598-		return ok, err
2599-	}
2600-	if ok, err := rewriteFile(filepath.Join(goplsDir, "doc", "commands.md"), api, write, rewriteCommands); !ok || err != nil {
2601-		return ok, err
2602-	}
2603-	if ok, err := rewriteFile(filepath.Join(goplsDir, "doc", "analyzers.md"), api, write, rewriteAnalyzers); !ok || err != nil {
2604-		return ok, err
2605-	}
2606-	if ok, err := rewriteFile(filepath.Join(goplsDir, "doc", "inlayHints.md"), api, write, rewriteInlayHints); !ok || err != nil {
2607-		return ok, err
2608-	}
2609-
2610-	return true, nil
2611-}
2612-
2613-// pkgDir returns the directory corresponding to the import path pkgPath.
2614-func pkgDir(pkgPath string) (string, error) {
2615-	out, err := exec.Command("go", "list", "-f", "{{.Dir}}", pkgPath).Output()
2616-	if err != nil {
2617-		return "", err
2618-	}
2619-	return strings.TrimSpace(string(out)), nil
2620-}
2621-
2622-func loadAPI() (*source.APIJSON, error) {
2623-	pkgs, err := packages.Load(
2624-		&packages.Config{
2625-			Mode: packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedDeps,
2626-		},
2627-		"golang.org/x/tools/gopls/internal/lsp/source",
2628-	)
2629-	if err != nil {
2630-		return nil, err
2631-	}
2632-	pkg := pkgs[0]
2633-
2634-	api := &source.APIJSON{
2635-		Options: map[string][]*source.OptionJSON{},
2636-	}
2637-	defaults := source.DefaultOptions()
2638-
2639-	api.Commands, err = loadCommands(pkg)
2640-	if err != nil {
2641-		return nil, err
2642-	}
2643-	api.Lenses = loadLenses(api.Commands)
2644-
2645-	// Transform the internal command name to the external command name.
2646-	for _, c := range api.Commands {
2647-		c.Command = command.ID(c.Command)
2648-	}
2649-	for _, m := range []map[string]*source.Analyzer{
2650-		defaults.DefaultAnalyzers,
2651-		defaults.TypeErrorAnalyzers,
2652-		defaults.ConvenienceAnalyzers,
2653-		// Don't yet add staticcheck analyzers.
2654-	} {
2655-		api.Analyzers = append(api.Analyzers, loadAnalyzers(m)...)
2656-	}
2657-	api.Hints = loadHints(source.AllInlayHints)
2658-	for _, category := range []reflect.Value{
2659-		reflect.ValueOf(defaults.UserOptions),
2660-	} {
2661-		// Find the type information and ast.File corresponding to the category.
2662-		optsType := pkg.Types.Scope().Lookup(category.Type().Name())
2663-		if optsType == nil {
2664-			return nil, fmt.Errorf("could not find %v in scope %v", category.Type().Name(), pkg.Types.Scope())
2665-		}
2666-		opts, err := loadOptions(category, optsType, pkg, "")
2667-		if err != nil {
2668-			return nil, err
2669-		}
2670-		catName := strings.TrimSuffix(category.Type().Name(), "Options")
2671-		api.Options[catName] = opts
2672-
2673-		// Hardcode the expected values for the analyses and code lenses
2674-		// settings, since their keys are not enums.
2675-		for _, opt := range opts {
2676-			switch opt.Name {
2677-			case "analyses":
2678-				for _, a := range api.Analyzers {
2679-					opt.EnumKeys.Keys = append(opt.EnumKeys.Keys, source.EnumKey{
2680-						Name:    fmt.Sprintf("%q", a.Name),
2681-						Doc:     a.Doc,
2682-						Default: strconv.FormatBool(a.Default),
2683-					})
2684-				}
2685-			case "codelenses":
2686-				// Hack: Lenses don't set default values, and we don't want to
2687-				// pass in the list of expected lenses to loadOptions. Instead,
2688-				// format the defaults using reflection here. The hackiest part
2689-				// is reversing lowercasing of the field name.
2690-				reflectField := category.FieldByName(upperFirst(opt.Name))
2691-				for _, l := range api.Lenses {
2692-					def, err := formatDefaultFromEnumBoolMap(reflectField, l.Lens)
2693-					if err != nil {
2694-						return nil, err
2695-					}
2696-					opt.EnumKeys.Keys = append(opt.EnumKeys.Keys, source.EnumKey{
2697-						Name:    fmt.Sprintf("%q", l.Lens),
2698-						Doc:     l.Doc,
2699-						Default: def,
2700-					})
2701-				}
2702-			case "hints":
2703-				for _, a := range api.Hints {
2704-					opt.EnumKeys.Keys = append(opt.EnumKeys.Keys, source.EnumKey{
2705-						Name:    fmt.Sprintf("%q", a.Name),
2706-						Doc:     a.Doc,
2707-						Default: strconv.FormatBool(a.Default),
2708-					})
2709-				}
2710-			}
2711-		}
2712-	}
2713-	return api, nil
2714-}
2715-
2716-func loadOptions(category reflect.Value, optsType types.Object, pkg *packages.Package, hierarchy string) ([]*source.OptionJSON, error) {
2717-	file, err := fileForPos(pkg, optsType.Pos())
2718-	if err != nil {
2719-		return nil, err
2720-	}
2721-
2722-	enums, err := loadEnums(pkg)
2723-	if err != nil {
2724-		return nil, err
2725-	}
2726-
2727-	var opts []*source.OptionJSON
2728-	optsStruct := optsType.Type().Underlying().(*types.Struct)
2729-	for i := 0; i < optsStruct.NumFields(); i++ {
2730-		// The types field gives us the type.
2731-		typesField := optsStruct.Field(i)
2732-
2733-		// If the field name ends with "Options", assume it is a struct with
2734-		// additional options and process it recursively.
2735-		if h := strings.TrimSuffix(typesField.Name(), "Options"); h != typesField.Name() {
2736-			// Keep track of the parent structs.
2737-			if hierarchy != "" {
2738-				h = hierarchy + "." + h
2739-			}
2740-			options, err := loadOptions(category, typesField, pkg, strings.ToLower(h))
2741-			if err != nil {
2742-				return nil, err
2743-			}
2744-			opts = append(opts, options...)
2745-			continue
2746-		}
2747-		path, _ := astutil.PathEnclosingInterval(file, typesField.Pos(), typesField.Pos())
2748-		if len(path) < 2 {
2749-			return nil, fmt.Errorf("could not find AST node for field %v", typesField)
2750-		}
2751-		// The AST field gives us the doc.
2752-		astField, ok := path[1].(*ast.Field)
2753-		if !ok {
2754-			return nil, fmt.Errorf("unexpected AST path %v", path)
2755-		}
2756-
2757-		// The reflect field gives us the default value.
2758-		reflectField := category.FieldByName(typesField.Name())
2759-		if !reflectField.IsValid() {
2760-			return nil, fmt.Errorf("could not find reflect field for %v", typesField.Name())
2761-		}
2762-
2763-		def, err := formatDefault(reflectField)
2764-		if err != nil {
2765-			return nil, err
2766-		}
2767-
2768-		typ := typesField.Type().String()
2769-		if _, ok := enums[typesField.Type()]; ok {
2770-			typ = "enum"
2771-		}
2772-		name := lowerFirst(typesField.Name())
2773-
2774-		var enumKeys source.EnumKeys
2775-		if m, ok := typesField.Type().(*types.Map); ok {
2776-			e, ok := enums[m.Key()]
2777-			if ok {
2778-				typ = strings.Replace(typ, m.Key().String(), m.Key().Underlying().String(), 1)
2779-			}
2780-			keys, err := collectEnumKeys(name, m, reflectField, e)
2781-			if err != nil {
2782-				return nil, err
2783-			}
2784-			if keys != nil {
2785-				enumKeys = *keys
2786-			}
2787-		}
2788-
2789-		// Get the status of the field by checking its struct tags.
2790-		reflectStructField, ok := category.Type().FieldByName(typesField.Name())
2791-		if !ok {
2792-			return nil, fmt.Errorf("no struct field for %s", typesField.Name())
2793-		}
2794-		status := reflectStructField.Tag.Get("status")
2795-
2796-		opts = append(opts, &source.OptionJSON{
2797-			Name:       name,
2798-			Type:       typ,
2799-			Doc:        lowerFirst(astField.Doc.Text()),
2800-			Default:    def,
2801-			EnumKeys:   enumKeys,
2802-			EnumValues: enums[typesField.Type()],
2803-			Status:     status,
2804-			Hierarchy:  hierarchy,
2805-		})
2806-	}
2807-	return opts, nil
2808-}
2809-
2810-func loadEnums(pkg *packages.Package) (map[types.Type][]source.EnumValue, error) {
2811-	enums := map[types.Type][]source.EnumValue{}
2812-	for _, name := range pkg.Types.Scope().Names() {
2813-		obj := pkg.Types.Scope().Lookup(name)
2814-		cnst, ok := obj.(*types.Const)
2815-		if !ok {
2816-			continue
2817-		}
2818-		f, err := fileForPos(pkg, cnst.Pos())
2819-		if err != nil {
2820-			return nil, fmt.Errorf("finding file for %q: %v", cnst.Name(), err)
2821-		}
2822-		path, _ := astutil.PathEnclosingInterval(f, cnst.Pos(), cnst.Pos())
2823-		spec := path[1].(*ast.ValueSpec)
2824-		value := cnst.Val().ExactString()
2825-		doc := valueDoc(cnst.Name(), value, spec.Doc.Text())
2826-		v := source.EnumValue{
2827-			Value: value,
2828-			Doc:   doc,
2829-		}
2830-		enums[obj.Type()] = append(enums[obj.Type()], v)
2831-	}
2832-	return enums, nil
2833-}
2834-
2835-func collectEnumKeys(name string, m *types.Map, reflectField reflect.Value, enumValues []source.EnumValue) (*source.EnumKeys, error) {
2836-	// Make sure the value type gets set for analyses and codelenses
2837-	// too.
2838-	if len(enumValues) == 0 && !hardcodedEnumKeys(name) {
2839-		return nil, nil
2840-	}
2841-	keys := &source.EnumKeys{
2842-		ValueType: m.Elem().String(),
2843-	}
2844-	// We can get default values for enum -> bool maps.
2845-	var isEnumBoolMap bool
2846-	if basic, ok := m.Elem().(*types.Basic); ok && basic.Kind() == types.Bool {
2847-		isEnumBoolMap = true
2848-	}
2849-	for _, v := range enumValues {
2850-		var def string
2851-		if isEnumBoolMap {
2852-			var err error
2853-			def, err = formatDefaultFromEnumBoolMap(reflectField, v.Value)
2854-			if err != nil {
2855-				return nil, err
2856-			}
2857-		}
2858-		keys.Keys = append(keys.Keys, source.EnumKey{
2859-			Name:    v.Value,
2860-			Doc:     v.Doc,
2861-			Default: def,
2862-		})
2863-	}
2864-	return keys, nil
2865-}
2866-
2867-func formatDefaultFromEnumBoolMap(reflectMap reflect.Value, enumKey string) (string, error) {
2868-	if reflectMap.Kind() != reflect.Map {
2869-		return "", nil
2870-	}
2871-	name := enumKey
2872-	if unquoted, err := strconv.Unquote(name); err == nil {
2873-		name = unquoted
2874-	}
2875-	for _, e := range reflectMap.MapKeys() {
2876-		if e.String() == name {
2877-			value := reflectMap.MapIndex(e)
2878-			if value.Type().Kind() == reflect.Bool {
2879-				return formatDefault(value)
2880-			}
2881-		}
2882-	}
2883-	// Assume that if the value isn't mentioned in the map, it defaults to
2884-	// the default value, false.
2885-	return formatDefault(reflect.ValueOf(false))
2886-}
2887-
2888-// formatDefault formats the default value into a JSON-like string.
2889-// VS Code exposes settings as JSON, so showing them as JSON is reasonable.
2890-// TODO(rstambler): Reconsider this approach, as the VS Code Go generator now
2891-// marshals to JSON.
2892-func formatDefault(reflectField reflect.Value) (string, error) {
2893-	def := reflectField.Interface()
2894-
2895-	// Durations marshal as nanoseconds, but we want the stringy versions,
2896-	// e.g. "100ms".
2897-	if t, ok := def.(time.Duration); ok {
2898-		def = t.String()
2899-	}
2900-	defBytes, err := json.Marshal(def)
2901-	if err != nil {
2902-		return "", err
2903-	}
2904-
2905-	// Nil values format as "null" so print them as hardcoded empty values.
2906-	switch reflectField.Type().Kind() {
2907-	case reflect.Map:
2908-		if reflectField.IsNil() {
2909-			defBytes = []byte("{}")
2910-		}
2911-	case reflect.Slice:
2912-		if reflectField.IsNil() {
2913-			defBytes = []byte("[]")
2914-		}
2915-	}
2916-	return string(defBytes), err
2917-}
2918-
2919-// valueDoc transforms a docstring documenting an constant identifier to a
2920-// docstring documenting its value.
2921-//
2922-// If doc is of the form "Foo is a bar", it returns '`"fooValue"` is a bar'. If
2923-// doc is non-standard ("this value is a bar"), it returns '`"fooValue"`: this
2924-// value is a bar'.
2925-func valueDoc(name, value, doc string) string {
2926-	if doc == "" {
2927-		return ""
2928-	}
2929-	if strings.HasPrefix(doc, name) {
2930-		// docstring in standard form. Replace the subject with value.
2931-		return fmt.Sprintf("`%s`%s", value, doc[len(name):])
2932-	}
2933-	return fmt.Sprintf("`%s`: %s", value, doc)
2934-}
2935-
2936-func loadCommands(pkg *packages.Package) ([]*source.CommandJSON, error) {
2937-	var commands []*source.CommandJSON
2938-
2939-	_, cmds, err := commandmeta.Load()
2940-	if err != nil {
2941-		return nil, err
2942-	}
2943-	// Parse the objects it contains.
2944-	for _, cmd := range cmds {
2945-		cmdjson := &source.CommandJSON{
2946-			Command: cmd.Name,
2947-			Title:   cmd.Title,
2948-			Doc:     cmd.Doc,
2949-			ArgDoc:  argsDoc(cmd.Args),
2950-		}
2951-		if cmd.Result != nil {
2952-			cmdjson.ResultDoc = typeDoc(cmd.Result, 0)
2953-		}
2954-		commands = append(commands, cmdjson)
2955-	}
2956-	return commands, nil
2957-}
2958-
2959-func argsDoc(args []*commandmeta.Field) string {
2960-	var b strings.Builder
2961-	for i, arg := range args {
2962-		b.WriteString(typeDoc(arg, 0))
2963-		if i != len(args)-1 {
2964-			b.WriteString(",\n")
2965-		}
2966-	}
2967-	return b.String()
2968-}
2969-
2970-func typeDoc(arg *commandmeta.Field, level int) string {
2971-	// Max level to expand struct fields.
2972-	const maxLevel = 3
2973-	if len(arg.Fields) > 0 {
2974-		if level < maxLevel {
2975-			return arg.FieldMod + structDoc(arg.Fields, level)
2976-		}
2977-		return "{ ... }"
2978-	}
2979-	under := arg.Type.Underlying()
2980-	switch u := under.(type) {
2981-	case *types.Slice:
2982-		return fmt.Sprintf("[]%s", u.Elem().Underlying().String())
2983-	}
2984-	return types.TypeString(under, nil)
2985-}
2986-
2987-func structDoc(fields []*commandmeta.Field, level int) string {
2988-	var b strings.Builder
2989-	b.WriteString("{\n")
2990-	indent := strings.Repeat("\t", level)
2991-	for _, fld := range fields {
2992-		if fld.Doc != "" && level == 0 {
2993-			doclines := strings.Split(fld.Doc, "\n")
2994-			for _, line := range doclines {
2995-				fmt.Fprintf(&b, "%s\t// %s\n", indent, line)
2996-			}
2997-		}
2998-		tag := strings.Split(fld.JSONTag, ",")[0]
2999-		if tag == "" {
3000-			tag = fld.Name
3001-		}
3002-		fmt.Fprintf(&b, "%s\t%q: %s,\n", indent, tag, typeDoc(fld, level+1))
3003-	}
3004-	fmt.Fprintf(&b, "%s}", indent)
3005-	return b.String()
3006-}
3007-
3008-func loadLenses(commands []*source.CommandJSON) []*source.LensJSON {
3009-	all := map[command.Command]struct{}{}
3010-	for k := range source.LensFuncs() {
3011-		all[k] = struct{}{}
3012-	}
3013-	for k := range mod.LensFuncs() {
3014-		if _, ok := all[k]; ok {
3015-			panic(fmt.Sprintf("duplicate lens %q", string(k)))
3016-		}
3017-		all[k] = struct{}{}
3018-	}
3019-
3020-	var lenses []*source.LensJSON
3021-
3022-	for _, cmd := range commands {
3023-		if _, ok := all[command.Command(cmd.Command)]; ok {
3024-			lenses = append(lenses, &source.LensJSON{
3025-				Lens:  cmd.Command,
3026-				Title: cmd.Title,
3027-				Doc:   cmd.Doc,
3028-			})
3029-		}
3030-	}
3031-	return lenses
3032-}
3033-
3034-func loadAnalyzers(m map[string]*source.Analyzer) []*source.AnalyzerJSON {
3035-	var sorted []string
3036-	for _, a := range m {
3037-		sorted = append(sorted, a.Analyzer.Name)
3038-	}
3039-	sort.Strings(sorted)
3040-	var json []*source.AnalyzerJSON
3041-	for _, name := range sorted {
3042-		a := m[name]
3043-		json = append(json, &source.AnalyzerJSON{
3044-			Name:    a.Analyzer.Name,
3045-			Doc:     a.Analyzer.Doc,
3046-			Default: a.Enabled,
3047-		})
3048-	}
3049-	return json
3050-}
3051-
3052-func loadHints(m map[string]*source.Hint) []*source.HintJSON {
3053-	var sorted []string
3054-	for _, h := range m {
3055-		sorted = append(sorted, h.Name)
3056-	}
3057-	sort.Strings(sorted)
3058-	var json []*source.HintJSON
3059-	for _, name := range sorted {
3060-		h := m[name]
3061-		json = append(json, &source.HintJSON{
3062-			Name: h.Name,
3063-			Doc:  h.Doc,
3064-		})
3065-	}
3066-	return json
3067-}
3068-
3069-func lowerFirst(x string) string {
3070-	if x == "" {
3071-		return x
3072-	}
3073-	return strings.ToLower(x[:1]) + x[1:]
3074-}
3075-
3076-func upperFirst(x string) string {
3077-	if x == "" {
3078-		return x
3079-	}
3080-	return strings.ToUpper(x[:1]) + x[1:]
3081-}
3082-
3083-func fileForPos(pkg *packages.Package, pos token.Pos) (*ast.File, error) {
3084-	fset := pkg.Fset
3085-	for _, f := range pkg.Syntax {
3086-		if safetoken.StartPosition(fset, f.Pos()).Filename == safetoken.StartPosition(fset, pos).Filename {
3087-			return f, nil
3088-		}
3089-	}
3090-	return nil, fmt.Errorf("no file for pos %v", pos)
3091-}
3092-
3093-func rewriteFile(file string, api *source.APIJSON, write bool, rewrite func([]byte, *source.APIJSON) ([]byte, error)) (bool, error) {
3094-	old, err := ioutil.ReadFile(file)
3095-	if err != nil {
3096-		return false, err
3097-	}
3098-
3099-	new, err := rewrite(old, api)
3100-	if err != nil {
3101-		return false, fmt.Errorf("rewriting %q: %v", file, err)
3102-	}
3103-
3104-	if !write {
3105-		return bytes.Equal(old, new), nil
3106-	}
3107-
3108-	if err := ioutil.WriteFile(file, new, 0); err != nil {
3109-		return false, err
3110-	}
3111-
3112-	return true, nil
3113-}
3114-
3115-func rewriteAPI(_ []byte, api *source.APIJSON) ([]byte, error) {
3116-	var buf bytes.Buffer
3117-	fmt.Fprintf(&buf, "// Code generated by \"golang.org/x/tools/gopls/doc/generate\"; DO NOT EDIT.\n\npackage source\n\nvar GeneratedAPIJSON = ")
3118-	if err := printsrc.NewPrinter("golang.org/x/tools/gopls/internal/lsp/source").Fprint(&buf, api); err != nil {
3119-		return nil, err
3120-	}
3121-	return format.Source(buf.Bytes())
3122-}
3123-
3124-type optionsGroup struct {
3125-	title   string
3126-	final   string
3127-	level   int
3128-	options []*source.OptionJSON
3129-}
3130-
3131-func rewriteSettings(doc []byte, api *source.APIJSON) ([]byte, error) {
3132-	result := doc
3133-	for category, opts := range api.Options {
3134-		groups := collectGroups(opts)
3135-
3136-		// First, print a table of contents.
3137-		section := bytes.NewBuffer(nil)
3138-		fmt.Fprintln(section, "")
3139-		for _, h := range groups {
3140-			writeBullet(section, h.final, h.level)
3141-		}
3142-		fmt.Fprintln(section, "")
3143-
3144-		// Currently, the settings document has a title and a subtitle, so
3145-		// start at level 3 for a header beginning with "###".
3146-		baseLevel := 3
3147-		for _, h := range groups {
3148-			level := baseLevel + h.level
3149-			writeTitle(section, h.final, level)
3150-			for _, opt := range h.options {
3151-				header := strMultiply("#", level+1)
3152-				fmt.Fprintf(section, "%s ", header)
3153-				opt.Write(section)
3154-			}
3155-		}
3156-		var err error
3157-		result, err = replaceSection(result, category, section.Bytes())
3158-		if err != nil {
3159-			return nil, err
3160-		}
3161-	}
3162-
3163-	section := bytes.NewBuffer(nil)
3164-	for _, lens := range api.Lenses {
3165-		fmt.Fprintf(section, "### **%v**\n\nIdentifier: `%v`\n\n%v\n", lens.Title, lens.Lens, lens.Doc)
3166-	}
3167-	return replaceSection(result, "Lenses", section.Bytes())
3168-}
3169-
3170-func collectGroups(opts []*source.OptionJSON) []optionsGroup {
3171-	optsByHierarchy := map[string][]*source.OptionJSON{}
3172-	for _, opt := range opts {
3173-		optsByHierarchy[opt.Hierarchy] = append(optsByHierarchy[opt.Hierarchy], opt)
3174-	}
3175-
3176-	// As a hack, assume that uncategorized items are less important to
3177-	// users and force the empty string to the end of the list.
3178-	var containsEmpty bool
3179-	var sorted []string
3180-	for h := range optsByHierarchy {
3181-		if h == "" {
3182-			containsEmpty = true
3183-			continue
3184-		}
3185-		sorted = append(sorted, h)
3186-	}
3187-	sort.Strings(sorted)
3188-	if containsEmpty {
3189-		sorted = append(sorted, "")
3190-	}
3191-	var groups []optionsGroup
3192-	baseLevel := 0
3193-	for _, h := range sorted {
3194-		split := strings.SplitAfter(h, ".")
3195-		last := split[len(split)-1]
3196-		// Hack to capitalize all of UI.
3197-		if last == "ui" {
3198-			last = "UI"
3199-		}
3200-		// A hierarchy may look like "ui.formatting". If "ui" has no
3201-		// options of its own, it may not be added to the map, but it
3202-		// still needs a heading.
3203-		components := strings.Split(h, ".")
3204-		for i := 1; i < len(components); i++ {
3205-			parent := strings.Join(components[0:i], ".")
3206-			if _, ok := optsByHierarchy[parent]; !ok {
3207-				groups = append(groups, optionsGroup{
3208-					title: parent,
3209-					final: last,
3210-					level: baseLevel + i,
3211-				})
3212-			}
3213-		}
3214-		groups = append(groups, optionsGroup{
3215-			title:   h,
3216-			final:   last,
3217-			level:   baseLevel + strings.Count(h, "."),
3218-			options: optsByHierarchy[h],
3219-		})
3220-	}
3221-	return groups
3222-}
3223-
3224-func hardcodedEnumKeys(name string) bool {
3225-	return name == "analyses" || name == "codelenses"
3226-}
3227-
3228-func writeBullet(w io.Writer, title string, level int) {
3229-	if title == "" {
3230-		return
3231-	}
3232-	// Capitalize the first letter of each title.
3233-	prefix := strMultiply("  ", level)
3234-	fmt.Fprintf(w, "%s* [%s](#%s)\n", prefix, capitalize(title), strings.ToLower(title))
3235-}
3236-
3237-func writeTitle(w io.Writer, title string, level int) {
3238-	if title == "" {
3239-		return
3240-	}
3241-	// Capitalize the first letter of each title.
3242-	fmt.Fprintf(w, "%s %s\n\n", strMultiply("#", level), capitalize(title))
3243-}
3244-
3245-func capitalize(s string) string {
3246-	return string(unicode.ToUpper(rune(s[0]))) + s[1:]
3247-}
3248-
3249-func strMultiply(str string, count int) string {
3250-	var result string
3251-	for i := 0; i < count; i++ {
3252-		result += string(str)
3253-	}
3254-	return result
3255-}
3256-
3257-func rewriteCommands(doc []byte, api *source.APIJSON) ([]byte, error) {
3258-	section := bytes.NewBuffer(nil)
3259-	for _, command := range api.Commands {
3260-		command.Write(section)
3261-	}
3262-	return replaceSection(doc, "Commands", section.Bytes())
3263-}
3264-
3265-func rewriteAnalyzers(doc []byte, api *source.APIJSON) ([]byte, error) {
3266-	section := bytes.NewBuffer(nil)
3267-	for _, analyzer := range api.Analyzers {
3268-		fmt.Fprintf(section, "## **%v**\n\n", analyzer.Name)
3269-		fmt.Fprintf(section, "%s\n\n", analyzer.Doc)
3270-		switch analyzer.Default {
3271-		case true:
3272-			fmt.Fprintf(section, "**Enabled by default.**\n\n")
3273-		case false:
3274-			fmt.Fprintf(section, "**Disabled by default. Enable it by setting `\"analyses\": {\"%s\": true}`.**\n\n", analyzer.Name)
3275-		}
3276-	}
3277-	return replaceSection(doc, "Analyzers", section.Bytes())
3278-}
3279-
3280-func rewriteInlayHints(doc []byte, api *source.APIJSON) ([]byte, error) {
3281-	section := bytes.NewBuffer(nil)
3282-	for _, hint := range api.Hints {
3283-		fmt.Fprintf(section, "## **%v**\n\n", hint.Name)
3284-		fmt.Fprintf(section, "%s\n\n", hint.Doc)
3285-		switch hint.Default {
3286-		case true:
3287-			fmt.Fprintf(section, "**Enabled by default.**\n\n")
3288-		case false:
3289-			fmt.Fprintf(section, "**Disabled by default. Enable it by setting `\"hints\": {\"%s\": true}`.**\n\n", hint.Name)
3290-		}
3291-	}
3292-	return replaceSection(doc, "Hints", section.Bytes())
3293-}
3294-
3295-func replaceSection(doc []byte, sectionName string, replacement []byte) ([]byte, error) {
3296-	re := regexp.MustCompile(fmt.Sprintf(`(?s)<!-- BEGIN %v.* -->\n(.*?)<!-- END %v.* -->`, sectionName, sectionName))
3297-	idx := re.FindSubmatchIndex(doc)
3298-	if idx == nil {
3299-		return nil, fmt.Errorf("could not find section %q", sectionName)
3300-	}
3301-	result := append([]byte(nil), doc[:idx[2]]...)
3302-	result = append(result, replacement...)
3303-	result = append(result, doc[idx[3]:]...)
3304-	return result, nil
3305-}
3306diff -urN a/gopls/doc/generate_test.go b/gopls/doc/generate_test.go
3307--- a/gopls/doc/generate_test.go	2000-01-01 00:00:00.000000000 -0000
3308+++ b/gopls/doc/generate_test.go	1970-01-01 00:00:00.000000000 +0000
3309@@ -1,26 +0,0 @@
3310-// Copyright 2020 The Go Authors. All rights reserved.
3311-// Use of this source code is governed by a BSD-style
3312-// license that can be found in the LICENSE file.
3313-
3314-package main
3315-
3316-import (
3317-	"testing"
3318-
3319-	"golang.org/x/tools/internal/testenv"
3320-)
3321-
3322-func TestGenerated(t *testing.T) {
3323-	// This test fails on 1.18 Kokoro for unknown reasons; in any case, it
3324-	// suffices to run this test on any builder.
3325-	testenv.NeedsGo1Point(t, 19)
3326-	testenv.NeedsGoBuild(t) // This is a lie. We actually need the source code.
3327-
3328-	ok, err := doMain(false)
3329-	if err != nil {
3330-		t.Fatal(err)
3331-	}
3332-	if !ok {
3333-		t.Error("documentation needs updating. run: `go run doc/generate.go` from the gopls module.")
3334-	}
3335-}
3336diff -urN a/gopls/doc/inlayHints.md b/gopls/doc/inlayHints.md
3337--- a/gopls/doc/inlayHints.md	2000-01-01 00:00:00.000000000 -0000
3338+++ b/gopls/doc/inlayHints.md	1970-01-01 00:00:00.000000000 +0000
3339@@ -1,80 +0,0 @@
3340-# Hints
3341-
3342-This document describes the inlay hints that `gopls` uses inside the editor.
3343-
3344-<!-- BEGIN Hints: DO NOT MANUALLY EDIT THIS SECTION -->
3345-## **assignVariableTypes**
3346-
3347-Enable/disable inlay hints for variable types in assign statements:
3348-```go
3349-	i/* int*/, j/* int*/ := 0, len(r)-1
3350-```
3351-
3352-**Disabled by default. Enable it by setting `"hints": {"assignVariableTypes": true}`.**
3353-
3354-## **compositeLiteralFields**
3355-
3356-Enable/disable inlay hints for composite literal field names:
3357-```go
3358-	{/*in: */"Hello, world", /*want: */"dlrow ,olleH"}
3359-```
3360-
3361-**Disabled by default. Enable it by setting `"hints": {"compositeLiteralFields": true}`.**
3362-
3363-## **compositeLiteralTypes**
3364-
3365-Enable/disable inlay hints for composite literal types:
3366-```go
3367-	for _, c := range []struct {
3368-		in, want string
3369-	}{
3370-		/*struct{ in string; want string }*/{"Hello, world", "dlrow ,olleH"},
3371-	}
3372-```
3373-
3374-**Disabled by default. Enable it by setting `"hints": {"compositeLiteralTypes": true}`.**
3375-
3376-## **constantValues**
3377-
3378-Enable/disable inlay hints for constant values:
3379-```go
3380-	const (
3381-		KindNone   Kind = iota/* = 0*/
3382-		KindPrint/*  = 1*/
3383-		KindPrintf/* = 2*/
3384-		KindErrorf/* = 3*/
3385-	)
3386-```
3387-
3388-**Disabled by default. Enable it by setting `"hints": {"constantValues": true}`.**
3389-
3390-## **functionTypeParameters**
3391-
3392-Enable/disable inlay hints for implicit type parameters on generic functions:
3393-```go
3394-	myFoo/*[int, string]*/(1, "hello")
3395-```
3396-
3397-**Disabled by default. Enable it by setting `"hints": {"functionTypeParameters": true}`.**
3398-
3399-## **parameterNames**
3400-
3401-Enable/disable inlay hints for parameter names:
3402-```go
3403-	parseInt(/* str: */ "123", /* radix: */ 8)
3404-```
3405-
3406-**Disabled by default. Enable it by setting `"hints": {"parameterNames": true}`.**
3407-
3408-## **rangeVariableTypes**
3409-
3410-Enable/disable inlay hints for variable types in range statements:
3411-```go
3412-	for k/* int*/, v/* string*/ := range []string{} {
3413-		fmt.Println(k, v)
3414-	}
3415-```
3416-
3417-**Disabled by default. Enable it by setting `"hints": {"rangeVariableTypes": true}`.**
3418-
3419-<!-- END Hints: DO NOT MANUALLY EDIT THIS SECTION -->
3420diff -urN a/gopls/doc/releases.md b/gopls/doc/releases.md
3421--- a/gopls/doc/releases.md	2000-01-01 00:00:00.000000000 -0000
3422+++ b/gopls/doc/releases.md	1970-01-01 00:00:00.000000000 +0000
3423@@ -1,25 +0,0 @@
3424-# Gopls release policy
3425-
3426-Gopls releases follow [semver](http://semver.org), with major changes and new
3427-features introduced only in new minor versions (i.e. versions of the form
3428-`v*.N.0` for some N). Subsequent patch releases contain only cherry-picked
3429-fixes or superficial updates.
3430-
3431-In order to align with the
3432-[Go release timeline](https://github.com/golang/go/wiki/Go-Release-Cycle#timeline),
3433-we aim to release a new minor version of Gopls approximately every three
3434-months, with patch releases approximately every month, according to the
3435-following table:
3436-
3437-| Month   | Version(s)   |
3438-| ----    | -------      |
3439-| Jan     | `v*.<N+0>.0` |
3440-| Jan-Mar | `v*.<N+0>.*` |
3441-| Apr     | `v*.<N+1>.0` |
3442-| Apr-Jun | `v*.<N+1>.*` |
3443-| Jul     | `v*.<N+2>.0` |
3444-| Jul-Sep | `v*.<N+2>.*` |
3445-| Oct     | `v*.<N+3>.0` |
3446-| Oct-Dec | `v*.<N+3>.*` |
3447-
3448-For more background on this policy, see https://go.dev/issue/55267.
3449diff -urN a/gopls/doc/semantictokens.md b/gopls/doc/semantictokens.md
3450--- a/gopls/doc/semantictokens.md	2000-01-01 00:00:00.000000000 -0000
3451+++ b/gopls/doc/semantictokens.md	1970-01-01 00:00:00.000000000 +0000
3452@@ -1,121 +0,0 @@
3453-# Semantic Tokens
3454-
3455-The [LSP](https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#textDocument_semanticTokens)
3456-specifies semantic tokens as a way of telling clients about language-specific
3457-properties of pieces of code in a file being edited.
3458-
3459-The client asks for a set of semantic tokens and modifiers. This note describe which ones
3460-gopls will return, and under what circumstances. Gopls has no control over how the client
3461-converts semantic tokens into colors (or some other visible indication). In vscode it
3462-is possible to modify the color a theme uses by setting the `editor.semanticTokenColorCustomizations`
3463-object. We provide a little [guidance](#Colors) later.
3464-
3465-There are 22 semantic tokens, with 10 possible modifiers. The protocol allows each semantic
3466-token to be used with any of the 1024 subsets of possible modifiers, but most combinations
3467-don't make intuitive sense (although `async documentation` has a certain appeal).
3468-
3469-The 22 semantic tokens are `namespace`, `type`, `class`, `enum`, `interface`,
3470-		`struct`, `typeParameter`, `parameter`, `variable`, `property`, `enumMember`,
3471-		`event`, `function`, `method`, `macro`, `keyword`, `modifier`, `comment`,
3472-		`string`, `number`, `regexp`, `operator`.
3473-
3474-The 10 modifiers are `declaration`, `definition`, `readonly`, `static`,
3475-		`deprecated`, `abstract`, `async`, `modification`, `documentation`, `defaultLibrary`.
3476-
3477-The authoritative lists are in the [specification](https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#semanticTokenTypes)
3478-
3479-For the implementation to work correctly the client and server have to agree on the ordering
3480-of the tokens and of the modifiers. Gopls, therefore, will only send tokens and modifiers
3481-that the client has asked for. This document says what gopls would send if the client
3482-asked for everything. By default, vscode asks for everything.
3483-
3484-Gopls sends 11 token types for `.go` files and 1 for `.*tmpl` files.
3485-Nothing is sent for any other kind of file.
3486-This all could change. (When Go has generics, gopls will return `typeParameter`.)
3487-
3488-For `.*tmpl` files gopls sends `macro`, and no modifiers, for each `{{`...`}}` scope.
3489-
3490-## Semantic tokens for Go files
3491-
3492-There are two contrasting guiding principles that might be used to decide what to mark
3493-with semantic tokens. All clients already do some kind of syntax marking. E.g., vscode
3494-uses a TextMate grammar. The minimal principle would send semantic tokens only for those
3495-language features that cannot be reliably found without parsing Go and looking at types.
3496-The maximal principle would attempt to convey as much as possible about the Go code,
3497-using all available parsing and type information.
3498-
3499-There is much to be said for returning minimal information, but the minimal principle is
3500-not well-specified. Gopls has no way of knowing what the clients know about the Go program
3501-being edited. Even in vscode the TextMate grammars can be more or less elaborate
3502-and change over time. (Nonetheless, a minimal implementation would not return `keyword`,
3503-`number`, `comment`, or `string`.)
3504-
3505-The maximal position isn't particularly well-specified either. To chose one example, a
3506-format string might have formatting codes (`%[4]-3.6f`), escape sequences (`\U00010604`), and regular
3507-characters. Should these all be distinguished? One could even imagine distinguishing
3508-different runes by their Unicode language assignment, or some other Unicode property, such as
3509-being [confusable](http://www.unicode.org/Public/security/10.0.0/confusables.txt).
3510-
3511-Gopls does not come close to either of these principles.  Semantic tokens are returned for
3512-identifiers, keywords, operators, comments, and literals. (Semantic tokens do not
3513-cover the file. They are not returned for
3514-white space or punctuation, and there is no semantic token for labels.)
3515-The following describes more precisely what gopls
3516-does, with a few notes on possible alternative choices.
3517-The references to *object* refer to the
3518-```types.Object``` returned by the type checker. The references to *nodes* refer to the
3519-```ast.Node``` from the parser.
3520-
3521-1. __`keyword`__ All Go [keywords](https://golang.org/ref/spec#Keywords) are marked `keyword`.
3522-1. __`namespace`__ All package names are marked `namespace`. In an import, if there is an
3523-alias, it would be marked. Otherwise the last component of the import path is marked.
3524-1. __`type`__ Objects of type ```types.TypeName``` are marked `type`.
3525-If they are also ```types.Basic```
3526-the modifier is `defaultLibrary`. (And in ```type B struct{C}```, ```B``` has modifier `definition`.)
3527-1. __`parameter`__ The formal arguments in ```ast.FuncDecl``` and ```ast.FuncType``` nodes are marked `parameter`.
3528-1. __`variable`__  Identifiers in the
3529-scope of ```const``` are modified with `readonly`. ```nil``` is usually a `variable` modified with both
3530-`readonly` and `defaultLibrary`. (```nil``` is a predefined identifier; the user can redefine it,
3531-in which case it would just be a variable, or whatever.) Identifiers of type ```types.Variable``` are,
3532-not surprisingly, marked `variable`. Identifiers being defined (node ```ast.GenDecl```) are modified
3533-by `definition` and, if appropriate, `readonly`. Receivers (in method declarations) are
3534-`variable`.
3535-1. __`method`__ Methods are marked at their definition (```func (x foo) bar() {}```) or declaration
3536-in an ```interface```. Methods are not marked where they are used.
3537-In ```x.bar()```, ```x``` will be marked
3538-either as a `namespace` if it is a package name, or as a `variable` if it is an interface value,
3539-so distinguishing ```bar``` seemed superfluous.
3540-1. __`function`__ Bultins (```types.Builtin```) are modified with `defaultLibrary`
3541-(e.g., ```make```, ```len```, ```copy```). Identifiers whose
3542-object is ```types.Func``` or whose node is ```ast.FuncDecl``` are `function`.
3543-1. __`comment`__ Comments and struct tags. (Perhaps struct tags should be `property`?)
3544-1. __`string`__ Strings. Could add modifiers for e.g., escapes or format codes.
3545-1. __`number`__ Numbers. Should the ```i``` in ```23i``` be handled specially?
3546-1. __`operator`__ Assignment operators, binary operators, ellipses (```...```), increment/decrement
3547-operators, sends (```<-```), and unary operators.
3548-
3549-Gopls will send the modifier `deprecated` if it finds a comment
3550-```// deprecated``` in the godoc.
3551-
3552-The unused tokens for Go code are `class`, `enum`, `interface`,
3553-		`struct`, `typeParameter`, `property`, `enumMember`,
3554-		`event`, `macro`, `modifier`,
3555-		`regexp`
3556-
3557-## Colors
3558-
3559-These comments are about vscode.
3560-
3561-The documentation has a [helpful](https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide#custom-textmate-scope-mappings)
3562-description of which semantic tokens correspond to scopes in TextMate grammars. Themes seem
3563-to use the TextMate scopes to decide on colors.
3564-
3565-Some examples of color customizations are [here](https://medium.com/@danromans/how-to-customize-semantic-token-colorization-with-visual-studio-code-ac3eab96141b).
3566-
3567-## Note
3568-
3569-While a file is being edited it may temporarily contain either
3570-parsing errors or type errors. In this case gopls cannot determine some (or maybe any)
3571-of the semantic tokens. To avoid weird flickering it is the responsibility
3572-of clients to maintain the semantic token information
3573-in the unedited part of the file, and they do.
3574\ No newline at end of file
3575diff -urN a/gopls/doc/settings.md b/gopls/doc/settings.md
3576--- a/gopls/doc/settings.md	2000-01-01 00:00:00.000000000 -0000
3577+++ b/gopls/doc/settings.md	1970-01-01 00:00:00.000000000 +0000
3578@@ -1,527 +0,0 @@
3579-# Settings
3580-
3581-<!--TODO: Generate this file from the documentation in golang.org/x/tools/gopls/internal/lsp/source/options.go.-->
3582-
3583-This document describes the global settings for `gopls` inside the editor.
3584-The settings block will be called `"gopls"` and contains a collection of
3585-controls for `gopls` that the editor is not expected to understand or control.
3586-These settings can also be configured differently per workspace folder.
3587-
3588-In VSCode, this would be a section in your `settings.json` file that might look
3589-like this:
3590-
3591-```json5
3592-  "gopls": {
3593-    "ui.completion.usePlaceholders": true,
3594-     ...
3595-  },
3596-```
3597-
3598-## Officially supported
3599-
3600-Below is the list of settings that are officially supported for `gopls`.
3601-
3602-Any settings that are experimental or for debugging purposes are marked as
3603-such.
3604-
3605-To enable all experimental features, use **allExperiments: `true`**. You will
3606-still be able to independently override specific experimental features.
3607-
3608-<!-- BEGIN User: DO NOT MANUALLY EDIT THIS SECTION -->
3609-
3610-* [Build](#build)
3611-* [Formatting](#formatting)
3612-* [UI](#ui)
3613-  * [Completion](#completion)
3614-  * [Diagnostic](#diagnostic)
3615-  * [Documentation](#documentation)
3616-  * [Inlayhint](#inlayhint)
3617-  * [Navigation](#navigation)
3618-
3619-### Build
3620-
3621-#### **buildFlags** *[]string*
3622-
3623-buildFlags is the set of flags passed on to the build system when invoked.
3624-It is applied to queries like `go list`, which is used when discovering files.
3625-The most common use is to set `-tags`.
3626-
3627-Default: `[]`.
3628-
3629-#### **env** *map[string]string*
3630-
3631-env adds environment variables to external commands run by `gopls`, most notably `go list`.
3632-
3633-Default: `{}`.
3634-
3635-#### **directoryFilters** *[]string*
3636-
3637-directoryFilters can be used to exclude unwanted directories from the
3638-workspace. By default, all directories are included. Filters are an
3639-operator, `+` to include and `-` to exclude, followed by a path prefix
3640-relative to the workspace folder. They are evaluated in order, and
3641-the last filter that applies to a path controls whether it is included.
3642-The path prefix can be empty, so an initial `-` excludes everything.
3643-
3644-DirectoryFilters also supports the `**` operator to match 0 or more directories.
3645-
3646-Examples:
3647-
3648-Exclude node_modules at current depth: `-node_modules`
3649-
3650-Exclude node_modules at any depth: `-**/node_modules`
3651-
3652-Include only project_a: `-` (exclude everything), `+project_a`
3653-
3654-Include only project_a, but not node_modules inside it: `-`, `+project_a`, `-project_a/node_modules`
3655-
3656-Default: `["-**/node_modules"]`.
3657-
3658-#### **templateExtensions** *[]string*
3659-
3660-templateExtensions gives the extensions of file names that are treateed
3661-as template files. (The extension
3662-is the part of the file name after the final dot.)
3663-
3664-Default: `[]`.
3665-
3666-#### **memoryMode** *enum*
3667-
3668-**This setting is experimental and may be deleted.**
3669-
3670-memoryMode controls the tradeoff `gopls` makes between memory usage and
3671-correctness.
3672-
3673-Values other than `Normal` are untested and may break in surprising ways.
3674-
3675-Must be one of:
3676-
3677-* `"DegradeClosed"`: In DegradeClosed mode, `gopls` will collect less information about
3678-packages without open files. As a result, features like Find
3679-References and Rename will miss results in such packages.
3680-* `"Normal"`
3681-
3682-Default: `"Normal"`.
3683-
3684-#### **expandWorkspaceToModule** *bool*
3685-
3686-**This setting is experimental and may be deleted.**
3687-
3688-expandWorkspaceToModule instructs `gopls` to adjust the scope of the
3689-workspace to find the best available module root. `gopls` first looks for
3690-a go.mod file in any parent directory of the workspace folder, expanding
3691-the scope to that directory if it exists. If no viable parent directory is
3692-found, gopls will check if there is exactly one child directory containing
3693-a go.mod file, narrowing the scope to that directory if it exists.
3694-
3695-Default: `true`.
3696-
3697-#### **allowModfileModifications** *bool*
3698-
3699-**This setting is experimental and may be deleted.**
3700-
3701-allowModfileModifications disables -mod=readonly, allowing imports from
3702-out-of-scope modules. This option will eventually be removed.
3703-
3704-Default: `false`.
3705-
3706-#### **allowImplicitNetworkAccess** *bool*
3707-
3708-**This setting is experimental and may be deleted.**
3709-
3710-allowImplicitNetworkAccess disables GOPROXY=off, allowing implicit module
3711-downloads rather than requiring user action. This option will eventually
3712-be removed.
3713-
3714-Default: `false`.
3715-
3716-#### **standaloneTags** *[]string*
3717-
3718-standaloneTags specifies a set of build constraints that identify
3719-individual Go source files that make up the entire main package of an
3720-executable.
3721-
3722-A common example of standalone main files is the convention of using the
3723-directive `//go:build ignore` to denote files that are not intended to be
3724-included in any package, for example because they are invoked directly by
3725-the developer using `go run`.
3726-
3727-Gopls considers a file to be a standalone main file if and only if it has
3728-package name "main" and has a build directive of the exact form
3729-"//go:build tag" or "// +build tag", where tag is among the list of tags
3730-configured by this setting. Notably, if the build constraint is more
3731-complicated than a simple tag (such as the composite constraint
3732-`//go:build tag && go1.18`), the file is not considered to be a standalone
3733-main file.
3734-
3735-This setting is only supported when gopls is built with Go 1.16 or later.
3736-
3737-Default: `["ignore"]`.
3738-
3739-### Formatting
3740-
3741-#### **local** *string*
3742-
3743-local is the equivalent of the `goimports -local` flag, which puts
3744-imports beginning with this string after third-party packages. It should
3745-be the prefix of the import path whose imports should be grouped
3746-separately.
3747-
3748-Default: `""`.
3749-
3750-#### **gofumpt** *bool*
3751-
3752-gofumpt indicates if we should run gofumpt formatting.
3753-
3754-Default: `false`.
3755-
3756-### UI
3757-
3758-#### **codelenses** *map[string]bool*
3759-
3760-codelenses overrides the enabled/disabled state of code lenses. See the
3761-"Code Lenses" section of the
3762-[Settings page](https://github.com/golang/tools/blob/master/gopls/doc/settings.md#code-lenses)
3763-for the list of supported lenses.
3764-
3765-Example Usage:
3766-
3767-```json5
3768-"gopls": {
3769-...
3770-  "codelenses": {
3771-    "generate": false,  // Don't show the `go generate` lens.
3772-    "gc_details": true  // Show a code lens toggling the display of gc's choices.
3773-  }
3774-...
3775-}
3776-```
3777-
3778-Default: `{"gc_details":false,"generate":true,"regenerate_cgo":true,"tidy":true,"upgrade_dependency":true,"vendor":true}`.
3779-
3780-#### **semanticTokens** *bool*
3781-
3782-**This setting is experimental and may be deleted.**
3783-
3784-semanticTokens controls whether the LSP server will send
3785-semantic tokens to the client.
3786-
3787-Default: `false`.
3788-
3789-#### **noSemanticString** *bool*
3790-
3791-**This setting is experimental and may be deleted.**
3792-
3793-noSemanticString turns off the sending of the semantic token 'string'
3794-
3795-Default: `false`.
3796-
3797-#### **noSemanticNumber** *bool*
3798-
3799-**This setting is experimental and may be deleted.**
3800-
3801-noSemanticNumber  turns off the sending of the semantic token 'number'
3802-
3803-Default: `false`.
3804-
3805-#### Completion
3806-
3807-##### **usePlaceholders** *bool*
3808-
3809-placeholders enables placeholders for function parameters or struct
3810-fields in completion responses.
3811-
3812-Default: `false`.
3813-
3814-##### **completionBudget** *time.Duration*
3815-
3816-**This setting is for debugging purposes only.**
3817-
3818-completionBudget is the soft latency goal for completion requests. Most
3819-requests finish in a couple milliseconds, but in some cases deep
3820-completions can take much longer. As we use up our budget we
3821-dynamically reduce the search scope to ensure we return timely
3822-results. Zero means unlimited.
3823-
3824-Default: `"100ms"`.
3825-
3826-##### **matcher** *enum*
3827-
3828-**This is an advanced setting and should not be configured by most `gopls` users.**
3829-
3830-matcher sets the algorithm that is used when calculating completion
3831-candidates.
3832-
3833-Must be one of:
3834-
3835-* `"CaseInsensitive"`
3836-* `"CaseSensitive"`
3837-* `"Fuzzy"`
3838-
3839-Default: `"Fuzzy"`.
3840-
3841-##### **experimentalPostfixCompletions** *bool*
3842-
3843-**This setting is experimental and may be deleted.**
3844-
3845-experimentalPostfixCompletions enables artificial method snippets
3846-such as "someSlice.sort!".
3847-
3848-Default: `true`.
3849-
3850-#### Diagnostic
3851-
3852-##### **analyses** *map[string]bool*
3853-
3854-analyses specify analyses that the user would like to enable or disable.
3855-A map of the names of analysis passes that should be enabled/disabled.
3856-A full list of analyzers that gopls uses can be found in
3857-[analyzers.md](https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md).
3858-
3859-Example Usage:
3860-
3861-```json5
3862-...
3863-"analyses": {
3864-  "unreachable": false, // Disable the unreachable analyzer.
3865-  "unusedparams": true  // Enable the unusedparams analyzer.
3866-}
3867-...
3868-```
3869-
3870-Default: `{}`.
3871-
3872-##### **staticcheck** *bool*
3873-
3874-**This setting is experimental and may be deleted.**
3875-
3876-staticcheck enables additional analyses from staticcheck.io.
3877-These analyses are documented on
3878-[Staticcheck's website](https://staticcheck.io/docs/checks/).
3879-
3880-Default: `false`.
3881-
3882-##### **annotations** *map[string]bool*
3883-
3884-**This setting is experimental and may be deleted.**
3885-
3886-annotations specifies the various kinds of optimization diagnostics
3887-that should be reported by the gc_details command.
3888-
3889-Can contain any of:
3890-
3891-* `"bounds"` controls bounds checking diagnostics.
3892-* `"escape"` controls diagnostics about escape choices.
3893-* `"inline"` controls diagnostics about inlining choices.
3894-* `"nil"` controls nil checks.
3895-
3896-Default: `{"bounds":true,"escape":true,"inline":true,"nil":true}`.
3897-
3898-##### **vulncheck** *enum*
3899-
3900-**This setting is experimental and may be deleted.**
3901-
3902-vulncheck enables vulnerability scanning.
3903-
3904-Must be one of:
3905-
3906-* `"Imports"`: In Imports mode, `gopls` will report vulnerabilities that affect packages
3907-directly and indirectly used by the analyzed main module.
3908-* `"Off"`: Disable vulnerability analysis.
3909-
3910-Default: `"Off"`.
3911-
3912-##### **diagnosticsDelay** *time.Duration*
3913-
3914-**This is an advanced setting and should not be configured by most `gopls` users.**
3915-
3916-diagnosticsDelay controls the amount of time that gopls waits
3917-after the most recent file modification before computing deep diagnostics.
3918-Simple diagnostics (parsing and type-checking) are always run immediately
3919-on recently modified packages.
3920-
3921-This option must be set to a valid duration string, for example `"250ms"`.
3922-
3923-Default: `"250ms"`.
3924-
3925-#### Documentation
3926-
3927-##### **hoverKind** *enum*
3928-
3929-hoverKind controls the information that appears in the hover text.
3930-SingleLine and Structured are intended for use only by authors of editor plugins.
3931-
3932-Must be one of:
3933-
3934-* `"FullDocumentation"`
3935-* `"NoDocumentation"`
3936-* `"SingleLine"`
3937-* `"Structured"` is an experimental setting that returns a structured hover format.
3938-This format separates the signature from the documentation, so that the client
3939-can do more manipulation of these fields.\
3940-This should only be used by clients that support this behavior.
3941-* `"SynopsisDocumentation"`
3942-
3943-Default: `"FullDocumentation"`.
3944-
3945-##### **linkTarget** *string*
3946-
3947-linkTarget controls where documentation links go.
3948-It might be one of:
3949-
3950-* `"godoc.org"`
3951-* `"pkg.go.dev"`
3952-
3953-If company chooses to use its own `godoc.org`, its address can be used as well.
3954-
3955-Modules matching the GOPRIVATE environment variable will not have
3956-documentation links in hover.
3957-
3958-Default: `"pkg.go.dev"`.
3959-
3960-##### **linksInHover** *bool*
3961-
3962-linksInHover toggles the presence of links to documentation in hover.
3963-
3964-Default: `true`.
3965-
3966-#### Inlayhint
3967-
3968-##### **hints** *map[string]bool*
3969-
3970-**This setting is experimental and may be deleted.**
3971-
3972-hints specify inlay hints that users want to see. A full list of hints
3973-that gopls uses can be found in
3974-[inlayHints.md](https://github.com/golang/tools/blob/master/gopls/doc/inlayHints.md).
3975-
3976-Default: `{}`.
3977-
3978-#### Navigation
3979-
3980-##### **importShortcut** *enum*
3981-
3982-importShortcut specifies whether import statements should link to
3983-documentation or go to definitions.
3984-
3985-Must be one of:
3986-
3987-* `"Both"`
3988-* `"Definition"`
3989-* `"Link"`
3990-
3991-Default: `"Both"`.
3992-
3993-##### **symbolMatcher** *enum*
3994-
3995-**This is an advanced setting and should not be configured by most `gopls` users.**
3996-
3997-symbolMatcher sets the algorithm that is used when finding workspace symbols.
3998-
3999-Must be one of:
4000-
4001-* `"CaseInsensitive"`
4002-* `"CaseSensitive"`
4003-* `"FastFuzzy"`
4004-* `"Fuzzy"`
4005-
4006-Default: `"FastFuzzy"`.
4007-
4008-##### **symbolStyle** *enum*
4009-
4010-**This is an advanced setting and should not be configured by most `gopls` users.**
4011-
4012-symbolStyle controls how symbols are qualified in symbol responses.
4013-
4014-Example Usage:
4015-
4016-```json5
4017-"gopls": {
4018-...
4019-  "symbolStyle": "Dynamic",
4020-...
4021-}
4022-```
4023-
4024-Must be one of:
4025-
4026-* `"Dynamic"` uses whichever qualifier results in the highest scoring
4027-match for the given symbol query. Here a "qualifier" is any "/" or "."
4028-delimited suffix of the fully qualified symbol. i.e. "to/pkg.Foo.Field" or
4029-just "Foo.Field".
4030-* `"Full"` is fully qualified symbols, i.e.
4031-"path/to/pkg.Foo.Field".
4032-* `"Package"` is package qualified symbols i.e.
4033-"pkg.Foo.Field".
4034-
4035-Default: `"Dynamic"`.
4036-
4037-#### **verboseOutput** *bool*
4038-
4039-**This setting is for debugging purposes only.**
4040-
4041-verboseOutput enables additional debug logging.
4042-
4043-Default: `false`.
4044-
4045-<!-- END User: DO NOT MANUALLY EDIT THIS SECTION -->
4046-
4047-#### **newDiff** *string*
4048-
4049-newDiff enables the new diff implementation. If this is "both", for now both
4050-diffs will be run and statistics will be generated in a file in $TMPDIR. This
4051-is a risky setting; help in trying it is appreciated. If it is "old" the old
4052-implementation is used, and if it is "new", just the new implementation is
4053-used. This setting will eventually be deleted, once gopls has fully migrated to
4054-the new diff algorithm.
4055-
4056-Default: 'both'.
4057-
4058-## Code Lenses
4059-
4060-These are the code lenses that `gopls` currently supports. They can be enabled
4061-and disabled using the `codelenses` setting, documented above. Their names and
4062-features are subject to change.
4063-
4064-<!-- BEGIN Lenses: DO NOT MANUALLY EDIT THIS SECTION -->
4065-### **Toggle gc_details**
4066-
4067-Identifier: `gc_details`
4068-
4069-Toggle the calculation of gc annotations.
4070-### **Run go generate**
4071-
4072-Identifier: `generate`
4073-
4074-Runs `go generate` for a given directory.
4075-### **Regenerate cgo**
4076-
4077-Identifier: `regenerate_cgo`
4078-
4079-Regenerates cgo definitions.
4080-### **Run govulncheck.**
4081-
4082-Identifier: `run_govulncheck`
4083-
4084-Run vulnerability check (`govulncheck`).
4085-### **Run test(s) (legacy)**
4086-
4087-Identifier: `test`
4088-
4089-Runs `go test` for a specific set of test or benchmark functions.
4090-### **Run go mod tidy**
4091-
4092-Identifier: `tidy`
4093-
4094-Runs `go mod tidy` for a module.
4095-### **Upgrade a dependency**
4096-
4097-Identifier: `upgrade_dependency`
4098-
4099-Upgrades a dependency in the go.mod file for a module.
4100-### **Run go mod vendor**
4101-
4102-Identifier: `vendor`
4103-
4104-Runs `go mod vendor` for a module.
4105-<!-- END Lenses: DO NOT MANUALLY EDIT THIS SECTION -->
4106diff -urN a/gopls/doc/subl.md b/gopls/doc/subl.md
4107--- a/gopls/doc/subl.md	2000-01-01 00:00:00.000000000 -0000
4108+++ b/gopls/doc/subl.md	1970-01-01 00:00:00.000000000 +0000
4109@@ -1,81 +0,0 @@
4110-# Sublime Text
4111-
4112-Use the [LSP] package. After installing it using Package Control, do the following:
4113-
4114-* Open the **Command Palette**
4115-* Find and run the command **LSP: Enable Language Server Globally**
4116-* Select the **gopls** item. Be careful not to select the similarly named *golsp* by mistake.
4117-
4118-Finally, you should familiarise yourself with the LSP package's *Settings* and *Key Bindings*. Find them under the menu item **Preferences > Package Settings > LSP**.
4119-
4120-## Examples
4121-Minimal global LSP settings, that assume **gopls** and **go** appear on the PATH seen by Sublime Text:<br>
4122-```
4123-{
4124-    "clients": {
4125-        "gopls": {
4126-             "enabled": true,
4127-         }
4128-    }
4129-}
4130-```
4131-
4132-Global LSP settings that supply a specific PATH for finding **gopls** and **go**, as well as some settings for Sublime LSP itself:
4133-```
4134-{
4135-    "clients": {
4136-        "gopls": {
4137-            "enabled": true,
4138-            "env": {
4139-                "PATH": "/path/to/your/go/bin",
4140-            }
4141-        }
4142-    },
4143-    // Recommended by https://agniva.me/gopls/2021/01/02/setting-up-gopls-sublime.html
4144-    // except log_stderr mentioned there is no longer recognized.
4145-    "show_references_in_quick_panel": true,
4146-    "log_debug": true,
4147-    // These two are recommended by LSP-json as replacement for deprecated only_show_lsp_completions
4148-    "inhibit_snippet_completions": true,
4149-    "inhibit_word_completions": true,
4150- }
4151- ```
4152-
4153-LSP and gopls settings can also be adjusted on a per-project basis to override global settings.
4154-```
4155-{
4156-    "folders": [
4157-        {
4158-            "path": "/path/to/a/folder/one"
4159-        },
4160-        {
4161-            // If you happen to be working on Go itself, this can be helpful; go-dev/bin should be on PATH.
4162-            "path": "/path/to/your/go-dev/src/cmd"
4163-        }
4164-     ],
4165-    "settings": {
4166-        "LSP": {
4167-            "gopls": {
4168-                // To use a specific version of gopls with Sublime Text LSP (e.g., to try new features in development)
4169-                "command": [
4170-                    "/path/to/your/go/bin/gopls"
4171-                ],
4172-                "env": {
4173-                    "PATH": "/path/to/your/go-dev/bin:/path/to/your/go/bin",
4174-                    "GOPATH": "",
4175-                },
4176-                "settings": {
4177-                    "experimentalWorkspaceModule": true
4178-                }
4179-            }
4180-        },
4181-        // This will apply for all languages in this project that have
4182-        // LSP servers, not just Go, however cannot enable just for Go.
4183-        "lsp_format_on_save": true,
4184-    }
4185-}
4186-```
4187-
4188-Usually changes to these settings are recognized after saving the project file, but it may sometimes be necessary to either restart the server(s) (**Tools > LSP > Restart Servers**) or quit and restart Sublime Text itself.
4189-
4190-[LSP]: https://packagecontrol.io/packages/LSP
4191diff -urN a/gopls/doc/troubleshooting.md b/gopls/doc/troubleshooting.md
4192--- a/gopls/doc/troubleshooting.md	2000-01-01 00:00:00.000000000 -0000
4193+++ b/gopls/doc/troubleshooting.md	1970-01-01 00:00:00.000000000 +0000
4194@@ -1,48 +0,0 @@
4195-# Troubleshooting
4196-
4197-If you suspect that `gopls` is crashing or not working correctly, please follow the troubleshooting steps below.
4198-
4199-If `gopls` is using too much memory, please follow the steps under [Memory usage](#debug-memory-usage).
4200-
4201-## Steps
4202-
4203-VS Code users should follow [their troubleshooting guide](https://github.com/golang/vscode-go/blob/master/docs/troubleshooting.md), which has more a more specific version of these instructions.
4204-
4205-1. Verify that your project is in good shape by working with it outside of your editor. Running a command like `go build ./...` in the workspace directory will compile everything. For modules, `go mod tidy` is another good check, though it may modify your `go.mod`.
4206-1. Check that your editor isn't showing any diagnostics that indicate a problem with your workspace. They may appear as diagnostics on a Go file's package declaration, diagnostics in a go.mod file, or as a status or progress message. Problems in the workspace configuration can cause many different symptoms. See the [workspace setup instructions](workspace.md) for help.
4207-1. Make sure `gopls` is up to date by following the [installation instructions](../README.md#installation), then [restarting gopls](#restart-gopls).
4208-1. Optionally, [ask for help](#ask-for-help) on Gophers Slack.
4209-1. Finally, [report the issue](#file-an-issue) to the `gopls` developers.
4210-
4211-## Restart `gopls`
4212-
4213-`gopls` has no persistent state, so restarting it will fix transient problems. This is good and bad: good, because you can keep working, and bad, because you won't be able to debug the issue until it recurs.
4214-
4215-In most cases, closing all your open editors will guarantee that `gopls` is killed and restarted. If you don't want to do that, there may be an editor command you can use to restart only `gopls`. Note that some `vim` configurations keep the server alive for a while after the editor exits; you may need to explicitly kill `gopls` if you use `vim`.
4216-
4217-## Ask for help
4218-
4219-Gophers Slack has active editor-specific channels like [#emacs](https://gophers.slack.com/archives/C0HKHULEM), [#vim](https://gophers.slack.com/archives/C07GBR52P), and [#vscode](https://gophers.slack.com/archives/C2B4L99RS) that can help debug further. If you're confident the problem is with `gopls`, you can go straight to [#gopls](https://gophers.slack.com/archives/CJZH85XCZ). Invites are [available to everyone](https://invite.slack.golangbridge.org). Come prepared with a short description of the issue, and try to be available to answer questions for a while afterward.
4220-
4221-## File an issue
4222-
4223-We can't diagnose a problem from just a description. When filing an issue, please include as much as possible of the following information:
4224-
4225-1. Your editor and any settings you have configured (for example, your VSCode `settings.json` file).
4226-1. A sample program that reproduces the issue, if possible.
4227-1. The output of `gopls version` on the command line.
4228-1. A complete gopls log file from a session where the issue occurred. It should have a `go env for <workspace folder>` log line near the beginning. It's also helpful to tell us the timestamp the problem occurred, so we can find it the log. See the [instructions](#capture-logs) for information on how to capture gopls logs.
4229-
4230-Your editor may have a command that fills out some of the necessary information, such as `:GoReportGitHubIssue` in `vim-go`. Otherwise, you can use `gopls bug` on the command line. If neither of those work you can start from scratch directly on the [Go issue tracker](https://github.com/golang/go/issues/new?title=x%2Ftools%2Fgopls%3A%20%3Cfill%20this%20in%3E).
4231-
4232-## Capture logs
4233-
4234-You may have to change your editor's configuration to pass a `-logfile` flag to gopls.
4235-
4236-To increase the level of detail in your logs, start `gopls` with the `-rpc.trace` flag. To start a debug server that will allow you to see profiles and memory usage, start `gopls` with `serve --debug=localhost:6060`. You will then be able to view debug information by navigating to `localhost:6060`.
4237-
4238-If you are unsure of how to pass a flag to `gopls` through your editor, please see the [documentation for your editor](../README.md#editors).
4239-
4240-## Debug memory usage
4241-
4242-`gopls` automatically writes out memory debug information when your usage exceeds 1GB. This information can be found in your temporary directory with names like `gopls.1234-5GiB-withnames.zip`. On Windows, your temporary directory will be located at `%TMP%`, and on Unixes, it will be `$TMPDIR`, which is usually `/tmp`. Please [file an issue](#file-an-issue) with this memory debug information attached. If you are uncomfortable sharing the package names of your code, you can share the `-nonames` zip instead, but it's much less useful.
4243diff -urN a/gopls/doc/vim.md b/gopls/doc/vim.md
4244--- a/gopls/doc/vim.md	2000-01-01 00:00:00.000000000 -0000
4245+++ b/gopls/doc/vim.md	1970-01-01 00:00:00.000000000 +0000
4246@@ -1,216 +0,0 @@
4247-# Vim / Neovim
4248-
4249-* [vim-go](#vimgo)
4250-* [LanguageClient-neovim](#lcneovim)
4251-* [Ale](#ale)
4252-* [vim-lsp](#vimlsp)
4253-* [vim-lsc](#vimlsc)
4254-* [coc.nvim](#cocnvim)
4255-* [govim](#govim)
4256-* [Neovim v0.5.0+](#neovim)
4257-  * [Installation](#neovim-install)
4258-  * [Custom Configuration](#neovim-config)
4259-  * [Imports](#neovim-imports)
4260-  * [Omnifunc](#neovim-omnifunc)
4261-  * [Additional Links](#neovim-links)
4262-
4263-## <a href="#vimgo" id="vimgo">vim-go</a>
4264-
4265-Use [vim-go] ver 1.20+, with the following configuration:
4266-
4267-```vim
4268-let g:go_def_mode='gopls'
4269-let g:go_info_mode='gopls'
4270-```
4271-
4272-## <a href="#lcneovim" id="lcneovim">LanguageClient-neovim</a>
4273-
4274-Use [LanguageClient-neovim], with the following configuration:
4275-
4276-```vim
4277-" Launch gopls when Go files are in use
4278-let g:LanguageClient_serverCommands = {
4279-       \ 'go': ['gopls']
4280-       \ }
4281-" Run gofmt on save
4282-autocmd BufWritePre *.go :call LanguageClient#textDocument_formatting_sync()
4283-```
4284-
4285-## <a href="#ale" id="ale">Ale</a>
4286-
4287-Use [ale]:
4288-
4289-```vim
4290-let g:ale_linters = {
4291-  \ 'go': ['gopls'],
4292-  \}
4293-```
4294-
4295-see [this issue][ale-issue-2179]
4296-
4297-## <a href="#vimlsp" id="vimlsp">vim-lsp</a>
4298-
4299-Use [prabirshrestha/vim-lsp], with the following configuration:
4300-
4301-```vim
4302-augroup LspGo
4303-  au!
4304-  autocmd User lsp_setup call lsp#register_server({
4305-      \ 'name': 'go-lang',
4306-      \ 'cmd': {server_info->['gopls']},
4307-      \ 'whitelist': ['go'],
4308-      \ })
4309-  autocmd FileType go setlocal omnifunc=lsp#complete
4310-  "autocmd FileType go nmap <buffer> gd <plug>(lsp-definition)
4311-  "autocmd FileType go nmap <buffer> ,n <plug>(lsp-next-error)
4312-  "autocmd FileType go nmap <buffer> ,p <plug>(lsp-previous-error)
4313-augroup END
4314-```
4315-
4316-## <a href="#vimlsc" id="vimlsc">vim-lsc</a>
4317-
4318-Use [natebosch/vim-lsc], with the following configuration:
4319-
4320-```vim
4321-let g:lsc_server_commands = {
4322-\  "go": {
4323-\    "command": "gopls serve",
4324-\    "log_level": -1,
4325-\    "suppress_stderr": v:true,
4326-\  },
4327-\}
4328-```
4329-
4330-The `log_level` and `suppress_stderr` parts are needed to prevent breakage from logging. See
4331-issues [#180](https://github.com/natebosch/vim-lsc/issues/180) and
4332-[#213](https://github.com/natebosch/vim-lsc/issues/213).
4333-
4334-## <a href="#cocnvim" id="cocnvim">coc.nvim</a>
4335-
4336-Use [coc.nvim], with the following `coc-settings.json` configuration:
4337-
4338-```json
4339-  "languageserver": {
4340-    "golang": {
4341-      "command": "gopls",
4342-      "rootPatterns": ["go.work", "go.mod", ".vim/", ".git/", ".hg/"],
4343-      "filetypes": ["go"],
4344-      "initializationOptions": {
4345-        "usePlaceholders": true
4346-      }
4347-    }
4348-  }
4349-```
4350-
4351-If you use `go.work` files, you may want to set the
4352-`workspace.workspaceFolderCheckCwd` option. This will force coc.nvim to search
4353-parent directories for `go.work` files, even if the current open directory has
4354-a `go.mod` file. See the
4355-[coc.nvim documentation](https://github.com/neoclide/coc.nvim/wiki/Using-workspaceFolders)
4356-for more details.
4357-
4358-Other [settings](settings.md) can be added in `initializationOptions` too.
4359-
4360-The `editor.action.organizeImport` code action will auto-format code and add missing imports. To run this automatically on save, add the following line to your `init.vim`:
4361-
4362-```vim
4363-autocmd BufWritePre *.go :call CocAction('runCommand', 'editor.action.organizeImport')
4364-```
4365-
4366-## <a href="#govim" id="govim">govim</a>
4367-
4368-In vim classic only, use the experimental [`govim`], simply follow the [install steps][govim-install].
4369-
4370-## <a href="#neovim" id="neovim">Neovim v0.5.0+</a>
4371-
4372-To use the new native LSP client in Neovim, make sure you
4373-[install][nvim-install] Neovim v.0.5.0+,
4374-the `nvim-lspconfig` configuration helper plugin, and check the
4375-[`gopls` configuration section][nvim-lspconfig] there.
4376-
4377-### <a href="#neovim-install" id="neovim-install">Installation</a>
4378-
4379-You can use Neovim's native plugin system.  On a Unix system, you can do that by
4380-cloning the `nvim-lspconfig` repository into the correct directory:
4381-
4382-```sh
4383-dir="${HOME}/.local/share/nvim/site/pack/nvim-lspconfig/opt/nvim-lspconfig/"
4384-mkdir -p "$dir"
4385-cd "$dir"
4386-git clone 'https://github.com/neovim/nvim-lspconfig.git' .
4387-```
4388-
4389-### <a href="#neovim-config" id="neovim-config">Custom Configuration</a>
4390-
4391-You can add custom configuration using Lua.  Here is an example of enabling the
4392-`unusedparams` check as well as `staticcheck`:
4393-
4394-```vim
4395-lua <<EOF
4396-  lspconfig = require "lspconfig"
4397-  util = require "lspconfig/util"
4398-
4399-  lspconfig.gopls.setup {
4400-    cmd = {"gopls", "serve"},
4401-    filetypes = {"go", "gomod"},
4402-    root_dir = util.root_pattern("go.work", "go.mod", ".git"),
4403-    settings = {
4404-      gopls = {
4405-        analyses = {
4406-          unusedparams = true,
4407-        },
4408-        staticcheck = true,
4409-      },
4410-    },
4411-  }
4412-EOF
4413-```
4414-
4415-### <a href="#neovim-imports" id="neovim-imports">Imports</a>
4416-
4417-Use the following configuration to have your imports organized on save using
4418-the logic of `goimports`. Note: this requires Neovim v0.7.0 or later.
4419-
4420-```lua
4421-vim.api.nvim_create_autocmd('BufWritePre', {
4422-  pattern = '*.go',
4423-  callback = function()
4424-    vim.lsp.buf.code_action({ context = { only = { 'source.organizeImports' } }, apply = true })
4425-  end
4426-})
4427-```
4428-
4429-### <a href="#neovim-omnifunc" id="neovim-omnifunc">Omnifunc</a>
4430-
4431-In Neovim v0.8.1 and later if you don't set the option `omnifunc`, it will auto
4432-set to `v:lua.vim.lsp.omnifunc`. If you are using an earlier version, you can
4433-configure it manually:
4434-
4435-```lua
4436-local on_attach = function(client, bufnr)
4437-  -- Enable completion triggered by <c-x><c-o>
4438-  vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
4439-end
4440-require('lspconfig').gopls.setup({
4441-   on_attach = on_attach
4442-})
4443-```
4444-
4445-### <a href="#neovim-links" id="neovim-links">Additional Links</a>
4446-
4447-* [Neovim's official LSP documentation][nvim-docs].
4448-
4449-[vim-go]: https://github.com/fatih/vim-go
4450-[LanguageClient-neovim]: https://github.com/autozimu/LanguageClient-neovim
4451-[ale]: https://github.com/w0rp/ale
4452-[ale-issue-2179]: https://github.com/w0rp/ale/issues/2179
4453-[prabirshrestha/vim-lsp]: https://github.com/prabirshrestha/vim-lsp/
4454-[natebosch/vim-lsc]: https://github.com/natebosch/vim-lsc/
4455-[natebosch/vim-lsc#180]: https://github.com/natebosch/vim-lsc/issues/180
4456-[coc.nvim]: https://github.com/neoclide/coc.nvim/
4457-[`govim`]: https://github.com/myitcv/govim
4458-[govim-install]: https://github.com/myitcv/govim/blob/master/README.md#govim---go-development-plugin-for-vim8
4459-[nvim-docs]: https://neovim.io/doc/user/lsp.html
4460-[nvim-install]: https://github.com/neovim/neovim/wiki/Installing-Neovim
4461-[nvim-lspconfig]: https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#gopls
4462-[nvim-lspconfig-imports]: https://github.com/neovim/nvim-lspconfig/issues/115
4463diff -urN a/gopls/doc/workspace.md b/gopls/doc/workspace.md
4464--- a/gopls/doc/workspace.md	2000-01-01 00:00:00.000000000 -0000
4465+++ b/gopls/doc/workspace.md	1970-01-01 00:00:00.000000000 +0000
4466@@ -1,101 +0,0 @@
4467-# Setting up your workspace
4468-
4469-`gopls` supports both Go module and GOPATH modes. However, it needs a defined
4470-scope in which language features like references, rename, and implementation
4471-should operate.
4472-
4473-The following options are available for configuring this scope:
4474-
4475-## Module mode
4476-
4477-### One module
4478-
4479-If you are working with a single module, you can open the module root (the
4480-directory containing the `go.mod` file), a subdirectory within the module,
4481-or a parent directory containing the module.
4482-
4483-**Note**: If you open a parent directory containing a module, it must **only**
4484-contain that single module. Otherwise, you are working with multiple modules.
4485-
4486-### Multiple modules
4487-
4488-Gopls has several alternatives for working on multiple modules simultaneously,
4489-described below. Starting with Go 1.18, Go workspaces are the preferred solution.
4490-
4491-#### Go workspaces (Go 1.18+)
4492-
4493-Starting with Go 1.18, the `go` command has native support for multi-module
4494-workspaces, via [`go.work`](https://go.dev/ref/mod#workspaces) files. These
4495-files are recognized by gopls starting with `[email protected]`.
4496-
4497-The easiest way to work on multiple modules in Go 1.18 and later is therefore
4498-to create a `go.work` file containing the modules you wish to work on, and set
4499-your workspace root to the directory containing the `go.work` file.
4500-
4501-For example, suppose this repo is checked out into the `$WORK/tools` directory.
4502-We can work on both `golang.org/x/tools` and `golang.org/x/tools/gopls`
4503-simultaneously by creating a `go.work` file using `go work init`, followed by
4504-`go work use MODULE_DIRECTORIES...` to add directories containing `go.mod` files to the
4505-workspace:
4506-
4507-```sh
4508-cd $WORK
4509-go work init
4510-go work use ./tools/ ./tools/gopls/
4511-```
4512-
4513-...followed by opening the `$WORK` directory in our editor.
4514-
4515-#### DEPRECATED: Experimental workspace module (Go 1.17 and earlier)
4516-
4517-**This feature is deprecated and will be removed in future versions of gopls.
4518-Please see [issue #52897](https://go.dev/issue/52897) for additional
4519-information.**
4520-
4521-With earlier versions of Go, `gopls` can simulate multi-module workspaces by
4522-creating a synthetic module requiring the modules in the workspace root.
4523-See [the design document](https://github.com/golang/proposal/blob/master/design/37720-gopls-workspaces.md)
4524-for more information.
4525-
4526-This feature is experimental, and will eventually be removed once `go.work`
4527-files are accepted by all supported Go versions.
4528-
4529-You can enable this feature by configuring the
4530-[experimentalWorkspaceModule](settings.md#experimentalworkspacemodule-bool)
4531-setting.
4532-
4533-#### Multiple workspace folders
4534-
4535-If neither of the above solutions work, and your editor allows configuring the
4536-set of
4537-["workspace folders"](https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#workspaceFolder)
4538-used during your LSP session, you can still work on multiple modules by adding
4539-a workspace folder at each module root (the locations of `go.mod` files). This
4540-means that each module has its own scope, and features will not work across
4541-modules.
4542-
4543-In VS Code, you can create a workspace folder by setting up a
4544-[multi-root workspace](https://code.visualstudio.com/docs/editor/multi-root-workspaces).
4545-View the [documentation for your editor plugin](../README.md#editor) to learn how to
4546-configure a workspace folder in your editor.
4547-
4548-### GOPATH mode
4549-
4550-When opening a directory within your GOPATH, the workspace scope will be just
4551-that directory.
4552-
4553-### At your own risk
4554-
4555-Some users or companies may have projects that encompass one `$GOPATH`. If you
4556-open your entire `$GOPATH` or `$GOPATH/src` folder, the workspace scope will be
4557-your entire `GOPATH`. If your GOPATH is large, `gopls` to be very slow to start
4558-because it will try to find all of the Go files in the directory you have
4559-opened. It will then load all of the files it has found.
4560-
4561-To work around this case, you can create a new `$GOPATH` that contains only the
4562-packages you want to work on.
4563-
4564----
4565-
4566-If you have additional use cases that are not mentioned above, please
4567-[file a new issue](https://github.com/golang/go/issues/new).
4568diff -urN a/gopls/go.mod b/gopls/go.mod
4569--- a/gopls/go.mod	2000-01-01 00:00:00.000000000 -0000
4570+++ b/gopls/go.mod	1970-01-01 00:00:00.000000000 +0000
4571@@ -1,29 +0,0 @@
4572-module golang.org/x/tools/gopls
4573-
4574-go 1.18
4575-
4576-require (
4577-	github.com/google/go-cmp v0.5.9
4578-	github.com/jba/printsrc v0.2.2
4579-	github.com/jba/templatecheck v0.6.0
4580-	github.com/sergi/go-diff v1.1.0
4581-	golang.org/x/mod v0.9.0
4582-	golang.org/x/sync v0.1.0
4583-	golang.org/x/sys v0.6.0
4584-	golang.org/x/text v0.8.0
4585-	golang.org/x/tools v0.6.0
4586-	golang.org/x/vuln v0.0.0-20230110180137-6ad3e3d07815
4587-	gopkg.in/yaml.v3 v3.0.1
4588-	honnef.co/go/tools v0.4.2
4589-	mvdan.cc/gofumpt v0.4.0
4590-	mvdan.cc/xurls/v2 v2.4.0
4591-)
4592-
4593-require (
4594-	github.com/BurntSushi/toml v1.2.1 // indirect
4595-	github.com/google/safehtml v0.1.0 // indirect
4596-	golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
4597-	golang.org/x/exp/typeparams v0.0.0-20221212164502-fae10dda9338 // indirect
4598-)
4599-
4600-replace golang.org/x/tools => ../
4601diff -urN a/gopls/go.sum b/gopls/go.sum
4602--- a/gopls/go.sum	2000-01-01 00:00:00.000000000 -0000
4603+++ b/gopls/go.sum	1970-01-01 00:00:00.000000000 +0000
4604@@ -1,101 +0,0 @@
4605-github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
4606-github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
4607-github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
4608-github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
4609-github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
4610-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
4611-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4612-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4613-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4614-github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
4615-github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
4616-github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o=
4617-github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
4618-github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
4619-github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
4620-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
4621-github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
4622-github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
4623-github.com/google/safehtml v0.0.2/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU=
4624-github.com/google/safehtml v0.1.0 h1:EwLKo8qawTKfsi0orxcQAZzu07cICaBeFMegAU9eaT8=
4625-github.com/google/safehtml v0.1.0/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU=
4626-github.com/jba/printsrc v0.2.2 h1:9OHK51UT+/iMAEBlQIIXW04qvKyF3/vvLuwW/hL8tDU=
4627-github.com/jba/printsrc v0.2.2/go.mod h1:1xULjw59sL0dPdWpDoVU06TIEO/Wnfv6AHRpiElTwYM=
4628-github.com/jba/templatecheck v0.6.0 h1:SwM8C4hlK/YNLsdcXStfnHWE2HKkuTVwy5FKQHt5ro8=
4629-github.com/jba/templatecheck v0.6.0/go.mod h1:/1k7EajoSErFI9GLHAsiIJEaNLt3ALKNw2TV7z2SYv4=
4630-github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
4631-github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
4632-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
4633-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
4634-github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
4635-github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
4636-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
4637-github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
4638-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4639-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
4640-github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
4641-github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
4642-github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
4643-github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
4644-github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
4645-github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
4646-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
4647-github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
4648-github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
4649-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
4650-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
4651-golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
4652-golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
4653-golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
4654-golang.org/x/exp/typeparams v0.0.0-20221212164502-fae10dda9338 h1:2O2DON6y3XMJiQRAS1UWU+54aec2uopH3x7MAiqGW6Y=
4655-golang.org/x/exp/typeparams v0.0.0-20221212164502-fae10dda9338/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
4656-golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
4657-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
4658-golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
4659-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
4660-golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
4661-golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
4662-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
4663-golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
4664-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
4665-golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
4666-golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
4667-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
4668-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
4669-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
4670-golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
4671-golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
4672-golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
4673-golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
4674-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
4675-golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
4676-golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
4677-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
4678-golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
4679-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
4680-golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
4681-golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
4682-golang.org/x/vuln v0.0.0-20230110180137-6ad3e3d07815 h1:A9kONVi4+AnuOr1dopsibH6hLi1Huy54cbeJxnq4vmU=
4683-golang.org/x/vuln v0.0.0-20230110180137-6ad3e3d07815/go.mod h1:XJiVExZgoZfrrxoTeVsFYrSSk1snhfpOEC95JL+A4T0=
4684-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
4685-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
4686-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
4687-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
4688-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
4689-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
4690-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
4691-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
4692-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
4693-gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
4694-gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
4695-gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
4696-gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
4697-honnef.co/go/tools v0.2.2/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=
4698-honnef.co/go/tools v0.4.2 h1:6qXr+R5w+ktL5UkwEbPp+fEvfyoMPche6GkOpGHZcLc=
4699-honnef.co/go/tools v0.4.2/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA=
4700-mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM=
4701-mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ=
4702-mvdan.cc/unparam v0.0.0-20211214103731-d0ef000c54e5 h1:Jh3LAeMt1eGpxomyu3jVkmVZWW2MxZ1qIIV2TZ/nRio=
4703-mvdan.cc/unparam v0.0.0-20211214103731-d0ef000c54e5/go.mod h1:b8RRCBm0eeiWR8cfN88xeq2G5SG3VKGO+5UPWi5FSOY=
4704-mvdan.cc/xurls/v2 v2.4.0 h1:tzxjVAj+wSBmDcF6zBB7/myTy3gX9xvi8Tyr28AuQgc=
4705-mvdan.cc/xurls/v2 v2.4.0/go.mod h1:+GEjq9uNjqs8LQfM9nVnM8rff0OQ5Iash5rzX+N1CSg=
4706diff -urN a/gopls/integration/govim/artifacts.go b/gopls/integration/govim/artifacts.go
4707--- a/gopls/integration/govim/artifacts.go	2000-01-01 00:00:00.000000000 -0000
4708+++ b/gopls/integration/govim/artifacts.go	1970-01-01 00:00:00.000000000 +0000
4709@@ -1,67 +0,0 @@
4710-// Copyright 2020 The Go Authors. All rights reserved.
4711-// Use of this source code is governed by a BSD-style
4712-// license that can be found in the LICENSE file.
4713-
4714-package main
4715-
4716-import (
4717-	"flag"
4718-	"fmt"
4719-	"io/ioutil"
4720-	"net/http"
4721-	"os"
4722-	"path"
4723-)
4724-
4725-var bucket = flag.String("bucket", "golang-gopls_integration_tests", "GCS bucket holding test artifacts.")
4726-
4727-const usage = `
4728-artifacts [--bucket=<bucket ID>] <cloud build evaluation ID>
4729-
4730-Fetch artifacts from an integration test run. Evaluation ID should be extracted
4731-from the cloud build notification.
4732-
4733-In order for this to work, the GCS bucket that artifacts were written to must
4734-be publicly readable. By default, this fetches from the
4735-golang-gopls_integration_tests bucket.
4736-`
4737-
4738-func main() {
4739-	flag.Usage = func() {
4740-		fmt.Fprint(flag.CommandLine.Output(), usage)
4741-	}
4742-	flag.Parse()
4743-	if flag.NArg() != 1 {
4744-		flag.Usage()
4745-		os.Exit(2)
4746-	}
4747-	evalID := flag.Arg(0)
4748-	logURL := fmt.Sprintf("https://storage.googleapis.com/%s/log-%s.txt", *bucket, evalID)
4749-	if err := download(logURL); err != nil {
4750-		fmt.Fprintf(os.Stderr, "downloading logs: %v", err)
4751-	}
4752-	tarURL := fmt.Sprintf("https://storage.googleapis.com/%s/govim/%s/artifacts.tar.gz", *bucket, evalID)
4753-	if err := download(tarURL); err != nil {
4754-		fmt.Fprintf(os.Stderr, "downloading artifact tarball: %v", err)
4755-	}
4756-}
4757-
4758-func download(artifactURL string) error {
4759-	name := path.Base(artifactURL)
4760-	resp, err := http.Get(artifactURL)
4761-	if err != nil {
4762-		return fmt.Errorf("fetching from GCS: %v", err)
4763-	}
4764-	defer resp.Body.Close()
4765-	if resp.StatusCode != http.StatusOK {
4766-		return fmt.Errorf("got status code %d from GCS", resp.StatusCode)
4767-	}
4768-	data, err := ioutil.ReadAll(resp.Body)
4769-	if err != nil {
4770-		return fmt.Errorf("reading result: %v", err)
4771-	}
4772-	if err := ioutil.WriteFile(name, data, 0644); err != nil {
4773-		return fmt.Errorf("writing artifact: %v", err)
4774-	}
4775-	return nil
4776-}
4777diff -urN a/gopls/integration/govim/cloudbuild.harness.yaml b/gopls/integration/govim/cloudbuild.harness.yaml
4778--- a/gopls/integration/govim/cloudbuild.harness.yaml	2000-01-01 00:00:00.000000000 -0000
4779+++ b/gopls/integration/govim/cloudbuild.harness.yaml	1970-01-01 00:00:00.000000000 +0000
4780@@ -1,21 +0,0 @@
4781-# Copyright 2019 The Go Authors. All rights reserved.
4782-# Use of this source code is governed by a BSD-style
4783-# license that can be found in the LICENSE file.
4784-
4785-# Build the govim test harness that will be used to run govim integration tests
4786-# for gopls. See README.md for instructions on how to use this.
4787-steps:
4788-  - name: 'gcr.io/cloud-builders/docker'
4789-    args: ['build',
4790-      # To allow for breaking changes to this test harness, tag with a major
4791-      # version number.
4792-      '-t', 'gcr.io/$PROJECT_ID/govim-harness:latest',
4793-      '-t', 'gcr.io/$PROJECT_ID/govim-harness:3',
4794-      # It is assumed that this build is running from the root directory of the
4795-      # tools repository.
4796-      '-f', 'gopls/integration/govim/Dockerfile',
4797-      # Use the integration test directory as build context: the test harness
4798-      # doesn't actually require any local files.
4799-      'gopls/integration/govim']
4800-images:
4801-  - gcr.io/$PROJECT_ID/govim-harness
4802diff -urN a/gopls/integration/govim/cloudbuild.yaml b/gopls/integration/govim/cloudbuild.yaml
4803--- a/gopls/integration/govim/cloudbuild.yaml	2000-01-01 00:00:00.000000000 -0000
4804+++ b/gopls/integration/govim/cloudbuild.yaml	1970-01-01 00:00:00.000000000 +0000
4805@@ -1,51 +0,0 @@
4806-# Copyright 2019 The Go Authors. All rights reserved.
4807-# Use of this source code is governed by a BSD-style
4808-# license that can be found in the LICENSE file.
4809-
4810-# Build gopls, and run the govim integration tests.  See README.md for
4811-# instructions on how to use this.
4812-
4813-substitutions:
4814-  # This bucket must be owned by the GCP project executing the build. If
4815-  # you are running this from your own project, override using --substitutions.
4816-  _RESULT_BUCKET: 'golang-gopls_integration_tests'
4817-
4818-steps:
4819-  # Build gopls from source, to use with the govim integration tests.
4820-  - name: 'golang:1.14'
4821-    env: ['GOPROXY=https://proxy.golang.org']
4822-    dir: 'gopls'
4823-    args: ['go', 'build']
4824-
4825-  # Run the tests. Note that the script in this step does not return the exit
4826-  # code from `go test`, but rather saves it for use in the final step after
4827-  # uploading artifacts.
4828-  - name: 'gcr.io/$PROJECT_ID/govim-harness:3'
4829-    dir: '/src/govim'
4830-    volumes:
4831-      - name: artifacts
4832-        path: /artifacts
4833-    env:
4834-      - GOVIM_TESTSCRIPT_WORKDIR_ROOT=/artifacts
4835-      - VIM_FLAVOR=vim
4836-    args: ['/workspace/gopls/integration/govim/run_tests_for_cloudbuild.sh']
4837-
4838-  # The govim tests produce a large number of artifacts; tarball/gzip to reduce
4839-  # roundtrips and save space.
4840-  - name: 'ubuntu'
4841-    volumes:
4842-      - name: artifacts
4843-        path: /artifacts
4844-    args: ['tar', '-czf', 'artifacts.tar.gz', '/artifacts']
4845-
4846-  # Upload artifacts to GCS.
4847-  - name: 'gcr.io/cloud-builders/gsutil'
4848-    args: ['cp', 'artifacts.tar.gz', 'gs://${_RESULT_BUCKET}/govim/${BUILD_ID}/artifacts.tar.gz']
4849-
4850-  # Exit with the actual exit code of the integration tests.
4851-  - name: 'ubuntu'
4852-    args: ['bash', 'govim_test_result.sh']
4853-
4854-# Write build logs to the same bucket as artifacts, so they can be more easily
4855-# shared.
4856-logsBucket: 'gs://${_RESULT_BUCKET}'
4857diff -urN a/gopls/integration/govim/Dockerfile b/gopls/integration/govim/Dockerfile
4858--- a/gopls/integration/govim/Dockerfile	2000-01-01 00:00:00.000000000 -0000
4859+++ b/gopls/integration/govim/Dockerfile	1970-01-01 00:00:00.000000000 +0000
4860@@ -1,16 +0,0 @@
4861-# Copyright 2019 The Go Authors. All rights reserved.
4862-# Use of this source code is governed by a BSD-style
4863-# license that can be found in the LICENSE file.
4864-
4865-# govim requires a more recent version of vim than is available in most
4866-# distros, so we build from their base image.
4867-FROM govim/govim:latest-vim
4868-ARG GOVIM_REF
4869-
4870-ENV GOPROXY=https://proxy.golang.org GOPATH=/go VIM_FLAVOR=vim
4871-WORKDIR /src
4872-
4873-# Clone govim. In order to use the go command for resolving latest, we download
4874-# a redundant copy of govim to the build cache using `go mod download`.
4875-RUN git clone https://github.com/govim/govim /src/govim && cd /src/govim && \
4876-    git checkout $GOVIM_REF
4877diff -urN a/gopls/integration/govim/README.md b/gopls/integration/govim/README.md
4878--- a/gopls/integration/govim/README.md	2000-01-01 00:00:00.000000000 -0000
4879+++ b/gopls/integration/govim/README.md	1970-01-01 00:00:00.000000000 +0000
4880@@ -1,47 +0,0 @@
4881-# govim integration tests
4882-
4883-Files in this directory configure Cloud Build to run [govim] integration tests
4884-against a gopls binary built from source.
4885-
4886-## Running on GCP
4887-
4888-To run these integration tests in Cloud Build, use the following steps.  Here
4889-we assume that `$PROJECT_ID` is a valid GCP project and `$BUCKET` is a cloud
4890-storage bucket owned by that project.
4891-
4892-- `cd` to the root directory of the tools project.
4893-- (at least once per GCP project) Build the test harness:
4894-```
4895-$ gcloud builds submit \
4896-	--project="${PROJECT_ID}" \
4897-	--config=gopls/integration/govim/cloudbuild.harness.yaml
4898-```
4899-- Run the integration tests:
4900-```
4901-$ gcloud builds submit \
4902-	--project="${PROJECT_ID}" \
4903-	--config=gopls/integration/govim/cloudbuild.yaml \
4904-	--substitutions=_RESULT_BUCKET="${BUCKET}"
4905-```
4906-
4907-## Fetching Artifacts
4908-
4909-Assuming the artifacts bucket is world readable, you can fetch integration from
4910-GCS. They are located at:
4911-
4912-- logs: `https://storage.googleapis.com/${BUCKET}/log-${EVALUATION_ID}.txt`
4913-- artifact tarball: `https://storage.googleapis.com/${BUCKET}/govim/${EVALUATION_ID}/artifacts.tar.gz`
4914-
4915-The `artifacts.go` command can be used to fetch both artifacts using an
4916-evaluation id.
4917-
4918-## Running locally
4919-
4920-Run `gopls/integration/govim/run_local.sh`. This may take a while the first
4921-time it is run, as it will require building the test harness. This script
4922-accepts two flags to modify its behavior:
4923-
4924-**--sudo**: run docker with `sudo`
4925-**--short**: run `go test -short`
4926-
4927-[govim]: https://github.com/govim/govim
4928diff -urN a/gopls/integration/govim/run_local.sh b/gopls/integration/govim/run_local.sh
4929--- a/gopls/integration/govim/run_local.sh	2000-01-01 00:00:00.000000000 -0000
4930+++ b/gopls/integration/govim/run_local.sh	1970-01-01 00:00:00.000000000 +0000
4931@@ -1,96 +0,0 @@
4932-#!/bin/bash -e
4933-
4934-# Copyright 2019 The Go Authors. All rights reserved.
4935-# Use of this source code is governed by a BSD-style
4936-# license that can be found in the LICENSE file.
4937-
4938-# Run govim integration tests against a local gopls.
4939-
4940-usage() {
4941-  cat <<EOUSAGE
4942-Usage: $0 [--sudo] [--short] [--version (semver|latest)]
4943-
4944-Args:
4945-  --sudo     run docker with sudo
4946-  --short    run `go test` with `-short`
4947-  --version  run on the specific tagged govim version (or latest) rather
4948-             than the default branch
4949-
4950-Run govim tests against HEAD using local docker.
4951-EOUSAGE
4952-}
4953-
4954-SUDO_IF_NEEDED=
4955-TEST_SHORT=
4956-DOCKERFILE=gopls/integration/govim/Dockerfile
4957-GOVIM_REF=main
4958-while [[ $# -gt 0 ]]; do
4959-  case "$1" in
4960-    "-h" | "--help" | "help")
4961-      usage
4962-      exit 0
4963-      ;;
4964-    "--sudo")
4965-      SUDO_IF_NEEDED="sudo "
4966-      shift
4967-      ;;
4968-    "--short")
4969-      TEST_SHORT="-short"
4970-      shift
4971-      ;;
4972-    "--version")
4973-      if [[ -z "$2" ]]; then
4974-        usage
4975-        exit 1
4976-      fi
4977-      GOVIM_REF=$2
4978-      if [[ "${GOVIM_REF}" == "latest" ]]; then
4979-        TMPGOPATH=$(mktemp -d)
4980-        trap "GOPATH=${TMPGOPATH} go clean -modcache && rm -r ${TMPGOPATH}" EXIT
4981-        GOVIM_REF=$(GOPATH=${TMPGOPATH} go mod download -json \
4982-          github.com/govim/govim@latest | jq -r .Version)
4983-      fi
4984-      shift 2
4985-      ;;
4986-    *)
4987-      usage
4988-      exit 1
4989-  esac
4990-done
4991-
4992-# Find the tools root, so that this script can be run from any directory.
4993-script_dir=$(dirname "$(readlink -f "$0")")
4994-tools_dir=$(readlink -f "${script_dir}/../../..")
4995-
4996-# Build gopls.
4997-cd "${tools_dir}/gopls"
4998-temp_gopls=$(mktemp -p "$PWD")
4999-trap "rm -f \"${temp_gopls}\"" EXIT
5000-# For consistency across environments, use golang docker to build rather than
5001-# the local go command.
5002-${SUDO_IF_NEEDED}docker run --rm -t \
5003-  -v "${tools_dir}:/src/tools" \
5004-  -w "/src/tools/gopls" \
5005-  golang:rc \
5006-  go build -o $(basename ${temp_gopls})
5007-
5008-# Build the test harness. Here we are careful to pass in a very limited build
5009-# context so as to optimize caching.
5010-echo "Checking out govim@${GOVIM_REF}"
5011-cd "${tools_dir}"
5012-${SUDO_IF_NEEDED}docker build \
5013-  --build-arg GOVIM_REF="${GOVIM_REF}" \
5014-  -t gopls-govim-harness:${GOVIM_REF} \
5015-  -f gopls/integration/govim/Dockerfile \
5016-  gopls/integration/govim
5017-
5018-# Run govim integration tests.
5019-echo "running govim integration tests using ${temp_gopls}"
5020-temp_gopls_name=$(basename "${temp_gopls}")
5021-${SUDO_IF_NEEDED}docker run --rm -t \
5022-  -v "${tools_dir}:/src/tools" \
5023-  -w "/src/govim" \
5024-  --ulimit memlock=-1:-1 \
5025-  gopls-govim-harness:${GOVIM_REF} \
5026-  go test ${TEST_SHORT} ./cmd/govim \
5027-    -gopls "/src/tools/gopls/${temp_gopls_name}"
5028diff -urN a/gopls/integration/govim/run_tests_for_cloudbuild.sh b/gopls/integration/govim/run_tests_for_cloudbuild.sh
5029--- a/gopls/integration/govim/run_tests_for_cloudbuild.sh	2000-01-01 00:00:00.000000000 -0000
5030+++ b/gopls/integration/govim/run_tests_for_cloudbuild.sh	1970-01-01 00:00:00.000000000 +0000
5031@@ -1,28 +0,0 @@
5032-#!/bin/bash
5033-
5034-# Copyright 2020 The Go Authors. All rights reserved.
5035-# Use of this source code is governed by a BSD-style
5036-# license that can be found in the LICENSE file.
5037-
5038-# This script runs govim integration tests but always succeeds, instead writing
5039-# their result to a file so that any test failure can be deferred to a later
5040-# build step. We do this so that we can capture govim test artifacts regardless
5041-# of the test results.
5042-
5043-# Substitute the locally built gopls binary for use in govim integration tests.
5044-go test -short ./cmd/govim -gopls /workspace/gopls/gopls
5045-
5046-# Stash the error, for use in a later build step.
5047-echo "exit $?" > /workspace/govim_test_result.sh
5048-
5049-# Clean up unnecessary artifacts. This is based on govim/_scripts/tidyUp.bash.
5050-# Since we're fetching govim using the go command, we won't have this non-go
5051-# source directory available to us.
5052-if [[ -n "$GOVIM_TESTSCRIPT_WORKDIR_ROOT" ]]; then
5053-  echo "Cleaning up build artifacts..."
5054-  # Make artifacts writable so that rm -rf doesn't complain.
5055-  chmod -R u+w "$GOVIM_TESTSCRIPT_WORKDIR_ROOT"
5056-
5057-  # Remove directories we don't care about.
5058-  find "$GOVIM_TESTSCRIPT_WORKDIR_ROOT" -type d \( -name .vim -o -name gopath \) -prune -exec rm -rf '{}' \;
5059-fi
5060diff -urN a/gopls/internal/coverage/coverage.go b/gopls/internal/coverage/coverage.go
5061--- a/gopls/internal/coverage/coverage.go	2000-01-01 00:00:00.000000000 -0000
5062+++ b/gopls/internal/coverage/coverage.go	1970-01-01 00:00:00.000000000 +0000
5063@@ -1,266 +0,0 @@
5064-// Copyright 2021 The Go Authors. All rights reserved.
5065-// Use of this source code is governed by a BSD-style
5066-// license that can be found in the LICENSE file.
5067-
5068-//go:build go.1.16
5069-// +build go.1.16
5070-
5071-// Running this program in the tools directory will produce a coverage file /tmp/cover.out
5072-// and a coverage report for all the packages under internal/lsp, accumulated by all the tests
5073-// under gopls.
5074-//
5075-// -o controls where the coverage file is written, defaulting to /tmp/cover.out
5076-// -i coverage-file will generate the report from an existing coverage file
5077-// -v controls verbosity (0: only report coverage, 1: report as each directory is finished,
5078-//
5079-//	2: report on each test, 3: more details, 4: too much)
5080-//
5081-// -t tests only tests packages in the given comma-separated list of directories in gopls.
5082-//
5083-//	The names should start with ., as in ./internal/regtest/bench
5084-//
5085-// -run tests. If set, -run tests is passed on to the go test command.
5086-//
5087-// Despite gopls' use of goroutines, the counts are almost deterministic.
5088-package main
5089-
5090-import (
5091-	"bytes"
5092-	"encoding/json"
5093-	"flag"
5094-	"fmt"
5095-	"log"
5096-	"os"
5097-	"os/exec"
5098-	"path/filepath"
5099-	"sort"
5100-	"strings"
5101-	"time"
5102-
5103-	"golang.org/x/tools/cover"
5104-)
5105-
5106-var (
5107-	proFile = flag.String("i", "", "existing profile file")
5108-	outFile = flag.String("o", "/tmp/cover.out", "where to write the coverage file")
5109-	verbose = flag.Int("v", 0, "how much detail to print as tests are running")
5110-	tests   = flag.String("t", "", "list of tests to run")
5111-	run     = flag.String("run", "", "value of -run to pass to go test")
5112-)
5113-
5114-func main() {
5115-	log.SetFlags(log.Lshortfile)
5116-	flag.Parse()
5117-
5118-	if *proFile != "" {
5119-		report(*proFile)
5120-		return
5121-	}
5122-
5123-	checkCwd()
5124-	// find the packages under gopls containing tests
5125-	tests := listDirs("gopls")
5126-	tests = onlyTests(tests)
5127-	tests = realTestName(tests)
5128-
5129-	// report coverage for packages under internal/lsp
5130-	parg := "golang.org/x/tools/gopls/internal/lsp/..."
5131-
5132-	accum := []string{}
5133-	seen := make(map[string]bool)
5134-	now := time.Now()
5135-	for _, toRun := range tests {
5136-		if excluded(toRun) {
5137-			continue
5138-		}
5139-		x := runTest(toRun, parg)
5140-		if *verbose > 0 {
5141-			fmt.Printf("finished %s %.1fs\n", toRun, time.Since(now).Seconds())
5142-		}
5143-		lines := bytes.Split(x, []byte{'\n'})
5144-		for _, l := range lines {
5145-			if len(l) == 0 {
5146-				continue
5147-			}
5148-			if !seen[string(l)] {
5149-				// not accumulating counts, so only works for mode:set
5150-				seen[string(l)] = true
5151-				accum = append(accum, string(l))
5152-			}
5153-		}
5154-	}
5155-	sort.Strings(accum[1:])
5156-	if err := os.WriteFile(*outFile, []byte(strings.Join(accum, "\n")), 0644); err != nil {
5157-		log.Print(err)
5158-	}
5159-	report(*outFile)
5160-}
5161-
5162-type result struct {
5163-	Time    time.Time
5164-	Test    string
5165-	Action  string
5166-	Package string
5167-	Output  string
5168-	Elapsed float64
5169-}
5170-
5171-func runTest(tName, parg string) []byte {
5172-	args := []string{"test", "-short", "-coverpkg", parg, "-coverprofile", *outFile,
5173-		"-json"}
5174-	if *run != "" {
5175-		args = append(args, fmt.Sprintf("-run=%s", *run))
5176-	}
5177-	args = append(args, tName)
5178-	cmd := exec.Command("go", args...)
5179-	cmd.Dir = "./gopls"
5180-	ans, err := cmd.Output()
5181-	if *verbose > 1 {
5182-		got := strings.Split(string(ans), "\n")
5183-		for _, g := range got {
5184-			if g == "" {
5185-				continue
5186-			}
5187-			var m result
5188-			if err := json.Unmarshal([]byte(g), &m); err != nil {
5189-				log.Printf("%T/%v", err, err) // shouldn't happen
5190-				continue
5191-			}
5192-			maybePrint(m)
5193-		}
5194-	}
5195-	if err != nil {
5196-		log.Printf("%s: %q, cmd=%s", tName, ans, cmd.String())
5197-	}
5198-	buf, err := os.ReadFile(*outFile)
5199-	if err != nil {
5200-		log.Fatal(err)
5201-	}
5202-	return buf
5203-}
5204-
5205-func report(fn string) {
5206-	profs, err := cover.ParseProfiles(fn)
5207-	if err != nil {
5208-		log.Fatal(err)
5209-	}
5210-	for _, p := range profs {
5211-		statements, counts := 0, 0
5212-		for _, x := range p.Blocks {
5213-			statements += x.NumStmt
5214-			if x.Count != 0 {
5215-				counts += x.NumStmt // sic: if any were executed, all were
5216-			}
5217-		}
5218-		pc := 100 * float64(counts) / float64(statements)
5219-		fmt.Printf("%3.0f%% %3d/%3d %s\n", pc, counts, statements, p.FileName)
5220-	}
5221-}
5222-
5223-var todo []string // tests to run
5224-
5225-func excluded(tname string) bool {
5226-	if *tests == "" { // run all tests
5227-		return false
5228-	}
5229-	if todo == nil {
5230-		todo = strings.Split(*tests, ",")
5231-	}
5232-	for _, nm := range todo {
5233-		if tname == nm { // run this test
5234-			return false
5235-		}
5236-	}
5237-	// not in list, skip it
5238-	return true
5239-}
5240-
5241-// should m.Package be printed sometime?
5242-func maybePrint(m result) {
5243-	switch m.Action {
5244-	case "pass", "fail", "skip":
5245-		fmt.Printf("%s %s %.3f\n", m.Action, m.Test, m.Elapsed)
5246-	case "run":
5247-		if *verbose > 2 {
5248-			fmt.Printf("%s %s %.3f\n", m.Action, m.Test, m.Elapsed)
5249-		}
5250-	case "output":
5251-		if *verbose > 3 {
5252-			fmt.Printf("%s %s %q %.3f\n", m.Action, m.Test, m.Output, m.Elapsed)
5253-		}
5254-	case "pause", "cont":
5255-		if *verbose > 2 {
5256-			fmt.Printf("%s %s %.3f\n", m.Action, m.Test, m.Elapsed)
5257-		}
5258-	default:
5259-		fmt.Printf("%#v\n", m)
5260-		log.Fatalf("unknown action %s\n", m.Action)
5261-	}
5262-}
5263-
5264-// return only the directories that contain tests
5265-func onlyTests(s []string) []string {
5266-	ans := []string{}
5267-outer:
5268-	for _, d := range s {
5269-		files, err := os.ReadDir(d)
5270-		if err != nil {
5271-			log.Fatalf("%s: %v", d, err)
5272-		}
5273-		for _, de := range files {
5274-			if strings.Contains(de.Name(), "_test.go") {
5275-				ans = append(ans, d)
5276-				continue outer
5277-			}
5278-		}
5279-	}
5280-	return ans
5281-}
5282-
5283-// replace the prefix gopls/ with ./ as the tests are run in the gopls directory
5284-func realTestName(p []string) []string {
5285-	ans := []string{}
5286-	for _, x := range p {
5287-		x = x[len("gopls/"):]
5288-		ans = append(ans, "./"+x)
5289-	}
5290-	return ans
5291-}
5292-
5293-// make sure we start in a tools directory
5294-func checkCwd() {
5295-	dir, err := os.Getwd()
5296-	if err != nil {
5297-		log.Fatal(err)
5298-	}
5299-	// we expect to be at the root of golang.org/x/tools
5300-	cmd := exec.Command("go", "list", "-m", "-f", "{{.Dir}}", "golang.org/x/tools")
5301-	buf, err := cmd.Output()
5302-	buf = bytes.Trim(buf, "\n \t") // remove \n at end
5303-	if err != nil {
5304-		log.Fatal(err)
5305-	}
5306-	if string(buf) != dir {
5307-		log.Fatalf("wrong directory: in %q, should be in %q", dir, string(buf))
5308-	}
5309-	// and we expect gopls and internal/lsp as subdirectories
5310-	_, err = os.Stat("gopls")
5311-	if err != nil {
5312-		log.Fatalf("expected a gopls directory, %v", err)
5313-	}
5314-}
5315-
5316-func listDirs(dir string) []string {
5317-	ans := []string{}
5318-	f := func(path string, dirEntry os.DirEntry, err error) error {
5319-		if strings.HasSuffix(path, "/testdata") || strings.HasSuffix(path, "/typescript") {
5320-			return filepath.SkipDir
5321-		}
5322-		if dirEntry.IsDir() {
5323-			ans = append(ans, path)
5324-		}
5325-		return nil
5326-	}
5327-	filepath.WalkDir(dir, f)
5328-	return ans
5329-}
5330diff -urN a/gopls/internal/govulncheck/semver/semver.go b/gopls/internal/govulncheck/semver/semver.go
5331--- a/gopls/internal/govulncheck/semver/semver.go	2000-01-01 00:00:00.000000000 -0000
5332+++ b/gopls/internal/govulncheck/semver/semver.go	1970-01-01 00:00:00.000000000 +0000
5333@@ -1,51 +0,0 @@
5334-// Copyright 2022 The Go Authors. All rights reserved.
5335-// Use of this source code is governed by a BSD-style
5336-// license that can be found in the LICENSE file.
5337-
5338-//go:build go1.18
5339-// +build go1.18
5340-
5341-// Package semver provides shared utilities for manipulating
5342-// Go semantic versions.
5343-package semver
5344-
5345-import (
5346-	"regexp"
5347-	"strings"
5348-)
5349-
5350-// addSemverPrefix adds a 'v' prefix to s if it isn't already prefixed
5351-// with 'v' or 'go'. This allows us to easily test go-style SEMVER
5352-// strings against normal SEMVER strings.
5353-func addSemverPrefix(s string) string {
5354-	if !strings.HasPrefix(s, "v") && !strings.HasPrefix(s, "go") {
5355-		return "v" + s
5356-	}
5357-	return s
5358-}
5359-
5360-// removeSemverPrefix removes the 'v' or 'go' prefixes from go-style
5361-// SEMVER strings, for usage in the public vulnerability format.
5362-func removeSemverPrefix(s string) string {
5363-	s = strings.TrimPrefix(s, "v")
5364-	s = strings.TrimPrefix(s, "go")
5365-	return s
5366-}
5367-
5368-// CanonicalizeSemverPrefix turns a SEMVER string into the canonical
5369-// representation using the 'v' prefix, as used by the OSV format.
5370-// Input may be a bare SEMVER ("1.2.3"), Go prefixed SEMVER ("go1.2.3"),
5371-// or already canonical SEMVER ("v1.2.3").
5372-func CanonicalizeSemverPrefix(s string) string {
5373-	return addSemverPrefix(removeSemverPrefix(s))
5374-}
5375-
5376-var (
5377-	// Regexp for matching go tags. The groups are:
5378-	// 1  the major.minor version
5379-	// 2  the patch version, or empty if none
5380-	// 3  the entire prerelease, if present
5381-	// 4  the prerelease type ("beta" or "rc")
5382-	// 5  the prerelease number
5383-	tagRegexp = regexp.MustCompile(`^go(\d+\.\d+)(\.\d+|)((beta|rc|-pre)(\d+))?$`)
5384-)
5385diff -urN a/gopls/internal/govulncheck/semver/semver_test.go b/gopls/internal/govulncheck/semver/semver_test.go
5386--- a/gopls/internal/govulncheck/semver/semver_test.go	2000-01-01 00:00:00.000000000 -0000
5387+++ b/gopls/internal/govulncheck/semver/semver_test.go	1970-01-01 00:00:00.000000000 +0000
5388@@ -1,28 +0,0 @@
5389-// Copyright 2022 The Go Authors. All rights reserved.
5390-// Use of this source code is governed by a BSD-style
5391-// license that can be found in the LICENSE file.
5392-
5393-//go:build go1.18
5394-// +build go1.18
5395-
5396-package semver
5397-
5398-import (
5399-	"testing"
5400-)
5401-
5402-func TestCanonicalize(t *testing.T) {
5403-	for _, test := range []struct {
5404-		v    string
5405-		want string
5406-	}{
5407-		{"v1.2.3", "v1.2.3"},
5408-		{"1.2.3", "v1.2.3"},
5409-		{"go1.2.3", "v1.2.3"},
5410-	} {
5411-		got := CanonicalizeSemverPrefix(test.v)
5412-		if got != test.want {
5413-			t.Errorf("want %s; got %s", test.want, got)
5414-		}
5415-	}
5416-}
5417diff -urN a/gopls/internal/govulncheck/types_118.go b/gopls/internal/govulncheck/types_118.go
5418--- a/gopls/internal/govulncheck/types_118.go	2000-01-01 00:00:00.000000000 -0000
5419+++ b/gopls/internal/govulncheck/types_118.go	1970-01-01 00:00:00.000000000 +0000
5420@@ -1,43 +0,0 @@
5421-// Copyright 2022 The Go Authors. All rights reserved.
5422-// Use of this source code is governed by a BSD-style
5423-// license that can be found in the LICENSE file.
5424-
5425-//go:build go1.18
5426-// +build go1.18
5427-
5428-// Package govulncheck provides an experimental govulncheck API.
5429-package govulncheck
5430-
5431-import (
5432-	"golang.org/x/vuln/exp/govulncheck"
5433-)
5434-
5435-var (
5436-	// Source reports vulnerabilities that affect the analyzed packages.
5437-	Source = govulncheck.Source
5438-
5439-	// DefaultCache constructs cache for a vulnerability database client.
5440-	DefaultCache = govulncheck.DefaultCache
5441-)
5442-
5443-type (
5444-	// Config is the configuration for Main.
5445-	Config = govulncheck.Config
5446-
5447-	// Vuln represents a single OSV entry.
5448-	Vuln = govulncheck.Vuln
5449-
5450-	// Module represents a specific vulnerability relevant to a
5451-	// single module or package.
5452-	Module = govulncheck.Module
5453-
5454-	// Package is a Go package with known vulnerable symbols.
5455-	Package = govulncheck.Package
5456-
5457-	// CallStacks contains a representative call stack for each
5458-	// vulnerable symbol that is called.
5459-	CallStack = govulncheck.CallStack
5460-
5461-	// StackFrame represents a call stack entry.
5462-	StackFrame = govulncheck.StackFrame
5463-)
5464diff -urN a/gopls/internal/govulncheck/types.go b/gopls/internal/govulncheck/types.go
5465--- a/gopls/internal/govulncheck/types.go	2000-01-01 00:00:00.000000000 -0000
5466+++ b/gopls/internal/govulncheck/types.go	1970-01-01 00:00:00.000000000 +0000
5467@@ -1,37 +0,0 @@
5468-// Copyright 2022 The Go Authors. All rights reserved.
5469-// Use of this source code is governed by a BSD-style
5470-// license that can be found in the LICENSE file.
5471-
5472-package govulncheck
5473-
5474-import "time"
5475-
5476-// Result is the result of vulnerability scanning.
5477-type Result struct {
5478-	// Vulns contains all vulnerabilities that are called or imported by
5479-	// the analyzed module.
5480-	Vulns []*Vuln `json:",omitempty"`
5481-
5482-	// Mode contains the source of the vulnerability info.
5483-	// Clients of the gopls.fetch_vulncheck_result command may need
5484-	// to interpret the vulnerabilities differently based on the
5485-	// analysis mode. For example, Vuln without callstack traces
5486-	// indicate a vulnerability that is not used if the result was
5487-	// from 'govulncheck' analysis mode. On the other hand, Vuln
5488-	// without callstack traces just implies the package with the
5489-	// vulnerability is known to the workspace and we do not know
5490-	// whether the vulnerable symbols are actually used or not.
5491-	Mode AnalysisMode `json:",omitempty"`
5492-
5493-	// AsOf describes when this Result was computed using govulncheck.
5494-	// It is valid only with the govulncheck analysis mode.
5495-	AsOf time.Time `json:",omitempty"`
5496-}
5497-
5498-type AnalysisMode string
5499-
5500-const (
5501-	ModeInvalid     AnalysisMode = "" // zero value
5502-	ModeGovulncheck AnalysisMode = "govulncheck"
5503-	ModeImports     AnalysisMode = "imports"
5504-)
5505diff -urN a/gopls/internal/govulncheck/types_not118.go b/gopls/internal/govulncheck/types_not118.go
5506--- a/gopls/internal/govulncheck/types_not118.go	2000-01-01 00:00:00.000000000 -0000
5507+++ b/gopls/internal/govulncheck/types_not118.go	1970-01-01 00:00:00.000000000 +0000
5508@@ -1,126 +0,0 @@
5509-// Copyright 2022 The Go Authors. All rights reserved.
5510-// Use of this source code is governed by a BSD-style
5511-// license that can be found in the LICENSE file.
5512-
5513-//go:build !go1.18
5514-// +build !go1.18
5515-
5516-package govulncheck
5517-
5518-import (
5519-	"go/token"
5520-
5521-	"golang.org/x/vuln/osv"
5522-)
5523-
5524-// Vuln represents a single OSV entry.
5525-type Vuln struct {
5526-	// OSV contains all data from the OSV entry for this vulnerability.
5527-	OSV *osv.Entry
5528-
5529-	// Modules contains all of the modules in the OSV entry where a
5530-	// vulnerable package is imported by the target source code or binary.
5531-	//
5532-	// For example, a module M with two packages M/p1 and M/p2, where only p1
5533-	// is vulnerable, will appear in this list if and only if p1 is imported by
5534-	// the target source code or binary.
5535-	Modules []*Module
5536-}
5537-
5538-func (v *Vuln) IsCalled() bool {
5539-	return false
5540-}
5541-
5542-// Module represents a specific vulnerability relevant to a single module.
5543-type Module struct {
5544-	// Path is the module path of the module containing the vulnerability.
5545-	//
5546-	// Importable packages in the standard library will have the path "stdlib".
5547-	Path string
5548-
5549-	// FoundVersion is the module version where the vulnerability was found.
5550-	FoundVersion string
5551-
5552-	// FixedVersion is the module version where the vulnerability was
5553-	// fixed. If there are multiple fixed versions in the OSV report, this will
5554-	// be the latest fixed version.
5555-	//
5556-	// This is empty if a fix is not available.
5557-	FixedVersion string
5558-
5559-	// Packages contains all the vulnerable packages in OSV entry that are
5560-	// imported by the target source code or binary.
5561-	//
5562-	// For example, given a module M with two packages M/p1 and M/p2, where
5563-	// both p1 and p2 are vulnerable, p1 and p2 will each only appear in this
5564-	// list they are individually imported by the target source code or binary.
5565-	Packages []*Package
5566-}
5567-
5568-// Package is a Go package with known vulnerable symbols.
5569-type Package struct {
5570-	// Path is the import path of the package containing the vulnerability.
5571-	Path string
5572-
5573-	// CallStacks contains a representative call stack for each
5574-	// vulnerable symbol that is called.
5575-	//
5576-	// For vulnerabilities found from binary analysis, only CallStack.Symbol
5577-	// will be provided.
5578-	//
5579-	// For non-affecting vulnerabilities reported from the source mode
5580-	// analysis, this will be empty.
5581-	CallStacks []CallStack
5582-}
5583-
5584-// CallStacks contains a representative call stack for a vulnerable
5585-// symbol.
5586-type CallStack struct {
5587-	// Symbol is the name of the detected vulnerable function
5588-	// or method.
5589-	//
5590-	// This follows the naming convention in the OSV report.
5591-	Symbol string
5592-
5593-	// Summary is a one-line description of the callstack, used by the
5594-	// default govulncheck mode.
5595-	//
5596-	// Example: module3.main calls github.com/shiyanhui/dht.DHT.Run
5597-	Summary string
5598-
5599-	// Frames contains an entry for each stack in the call stack.
5600-	//
5601-	// Frames are sorted starting from the entry point to the
5602-	// imported vulnerable symbol. The last frame in Frames should match
5603-	// Symbol.
5604-	Frames []*StackFrame
5605-}
5606-
5607-// StackFrame represents a call stack entry.
5608-type StackFrame struct {
5609-	// PackagePath is the import path.
5610-	PkgPath string
5611-
5612-	// FuncName is the function name.
5613-	FuncName string
5614-
5615-	// RecvType is the fully qualified receiver type,
5616-	// if the called symbol is a method.
5617-	//
5618-	// The client can create the final symbol name by
5619-	// prepending RecvType to FuncName.
5620-	RecvType string
5621-
5622-	// Position describes an arbitrary source position
5623-	// including the file, line, and column location.
5624-	// A Position is valid if the line number is > 0.
5625-	Position token.Position
5626-}
5627-
5628-func (sf *StackFrame) Name() string {
5629-	return ""
5630-}
5631-
5632-func (sf *StackFrame) Pos() string {
5633-	return ""
5634-}
5635diff -urN a/gopls/internal/govulncheck/util.go b/gopls/internal/govulncheck/util.go
5636--- a/gopls/internal/govulncheck/util.go	2000-01-01 00:00:00.000000000 -0000
5637+++ b/gopls/internal/govulncheck/util.go	1970-01-01 00:00:00.000000000 +0000
5638@@ -1,36 +0,0 @@
5639-// Copyright 2022 The Go Authors. All rights reserved.
5640-// Use of this source code is governed by a BSD-style
5641-// license that can be found in the LICENSE file.
5642-
5643-//go:build go1.18
5644-// +build go1.18
5645-
5646-package govulncheck
5647-
5648-import (
5649-	"golang.org/x/mod/semver"
5650-	isem "golang.org/x/tools/gopls/internal/govulncheck/semver"
5651-	"golang.org/x/vuln/osv"
5652-)
5653-
5654-// LatestFixed returns the latest fixed version in the list of affected ranges,
5655-// or the empty string if there are no fixed versions.
5656-func LatestFixed(modulePath string, as []osv.Affected) string {
5657-	v := ""
5658-	for _, a := range as {
5659-		if a.Package.Name != modulePath {
5660-			continue
5661-		}
5662-		for _, r := range a.Ranges {
5663-			if r.Type == osv.TypeSemver {
5664-				for _, e := range r.Events {
5665-					if e.Fixed != "" && (v == "" ||
5666-						semver.Compare(isem.CanonicalizeSemverPrefix(e.Fixed), isem.CanonicalizeSemverPrefix(v)) > 0) {
5667-						v = e.Fixed
5668-					}
5669-				}
5670-			}
5671-		}
5672-	}
5673-	return v
5674-}
5675diff -urN a/gopls/internal/govulncheck/vulncache.go b/gopls/internal/govulncheck/vulncache.go
5676--- a/gopls/internal/govulncheck/vulncache.go	2000-01-01 00:00:00.000000000 -0000
5677+++ b/gopls/internal/govulncheck/vulncache.go	1970-01-01 00:00:00.000000000 +0000
5678@@ -1,105 +0,0 @@
5679-// Copyright 2022 The Go Authors. All rights reserved.
5680-// Use of this source code is governed by a BSD-style
5681-// license that can be found in the LICENSE file.
5682-
5683-//go:build go1.18
5684-// +build go1.18
5685-
5686-package govulncheck
5687-
5688-import (
5689-	"sync"
5690-	"time"
5691-
5692-	vulnc "golang.org/x/vuln/client"
5693-	"golang.org/x/vuln/osv"
5694-)
5695-
5696-// inMemoryCache is an implementation of the [client.Cache] interface
5697-// that "decorates" another instance of that interface to provide
5698-// an additional layer of (memory-based) caching.
5699-type inMemoryCache struct {
5700-	mu         sync.Mutex
5701-	underlying vulnc.Cache
5702-	db         map[string]*db
5703-}
5704-
5705-var _ vulnc.Cache = &inMemoryCache{}
5706-
5707-type db struct {
5708-	retrieved time.Time
5709-	index     vulnc.DBIndex
5710-	entry     map[string][]*osv.Entry
5711-}
5712-
5713-// NewInMemoryCache returns a new memory-based cache that decorates
5714-// the provided cache (file-based, perhaps).
5715-func NewInMemoryCache(underlying vulnc.Cache) *inMemoryCache {
5716-	return &inMemoryCache{
5717-		underlying: underlying,
5718-		db:         make(map[string]*db),
5719-	}
5720-}
5721-
5722-func (c *inMemoryCache) lookupDBLocked(dbName string) *db {
5723-	cached := c.db[dbName]
5724-	if cached == nil {
5725-		cached = &db{entry: make(map[string][]*osv.Entry)}
5726-		c.db[dbName] = cached
5727-	}
5728-	return cached
5729-}
5730-
5731-// ReadIndex returns the index for dbName from the cache, or returns zero values
5732-// if it is not present.
5733-func (c *inMemoryCache) ReadIndex(dbName string) (vulnc.DBIndex, time.Time, error) {
5734-	c.mu.Lock()
5735-	defer c.mu.Unlock()
5736-	cached := c.lookupDBLocked(dbName)
5737-
5738-	if cached.retrieved.IsZero() {
5739-		// First time ReadIndex is called.
5740-		index, retrieved, err := c.underlying.ReadIndex(dbName)
5741-		if err != nil {
5742-			return index, retrieved, err
5743-		}
5744-		cached.index, cached.retrieved = index, retrieved
5745-	}
5746-	return cached.index, cached.retrieved, nil
5747-}
5748-
5749-// WriteIndex puts the index and retrieved time into the cache.
5750-func (c *inMemoryCache) WriteIndex(dbName string, index vulnc.DBIndex, retrieved time.Time) error {
5751-	c.mu.Lock()
5752-	defer c.mu.Unlock()
5753-	cached := c.lookupDBLocked(dbName)
5754-	cached.index, cached.retrieved = index, retrieved
5755-	// TODO(hyangah): shouldn't we invalidate all cached entries?
5756-	return c.underlying.WriteIndex(dbName, index, retrieved)
5757-}
5758-
5759-// ReadEntries returns the vulndb entries for path from the cache.
5760-func (c *inMemoryCache) ReadEntries(dbName, path string) ([]*osv.Entry, error) {
5761-	c.mu.Lock()
5762-	defer c.mu.Unlock()
5763-	cached := c.lookupDBLocked(dbName)
5764-	entries, ok := cached.entry[path]
5765-	if !ok {
5766-		// cache miss
5767-		entries, err := c.underlying.ReadEntries(dbName, path)
5768-		if err != nil {
5769-			return entries, err
5770-		}
5771-		cached.entry[path] = entries
5772-	}
5773-	return entries, nil
5774-}
5775-
5776-// WriteEntries puts the entries for path into the cache.
5777-func (c *inMemoryCache) WriteEntries(dbName, path string, entries []*osv.Entry) error {
5778-	c.mu.Lock()
5779-	defer c.mu.Unlock()
5780-	cached := c.lookupDBLocked(dbName)
5781-	cached.entry[path] = entries
5782-	return c.underlying.WriteEntries(dbName, path, entries)
5783-}
5784diff -urN a/gopls/internal/hooks/analysis_116.go b/gopls/internal/hooks/analysis_116.go
5785--- a/gopls/internal/hooks/analysis_116.go	2000-01-01 00:00:00.000000000 -0000
5786+++ b/gopls/internal/hooks/analysis_116.go	1970-01-01 00:00:00.000000000 +0000
5787@@ -1,14 +0,0 @@
5788-// Copyright 2021 The Go Authors. All rights reserved.
5789-// Use of this source code is governed by a BSD-style
5790-// license that can be found in the LICENSE file.
5791-
5792-//go:build !go1.19
5793-// +build !go1.19
5794-
5795-package hooks
5796-
5797-import "golang.org/x/tools/gopls/internal/lsp/source"
5798-
5799-func updateAnalyzers(options *source.Options) {
5800-	options.StaticcheckSupported = false
5801-}
5802diff -urN a/gopls/internal/hooks/analysis_119.go b/gopls/internal/hooks/analysis_119.go
5803--- a/gopls/internal/hooks/analysis_119.go	2000-01-01 00:00:00.000000000 -0000
5804+++ b/gopls/internal/hooks/analysis_119.go	1970-01-01 00:00:00.000000000 +0000
5805@@ -1,62 +0,0 @@
5806-// Copyright 2019 The Go Authors. All rights reserved.
5807-// Use of this source code is governed by a BSD-style
5808-// license that can be found in the LICENSE file.
5809-
5810-//go:build go1.19
5811-// +build go1.19
5812-
5813-package hooks
5814-
5815-import (
5816-	"golang.org/x/tools/gopls/internal/lsp/protocol"
5817-	"golang.org/x/tools/gopls/internal/lsp/source"
5818-	"honnef.co/go/tools/analysis/lint"
5819-	"honnef.co/go/tools/quickfix"
5820-	"honnef.co/go/tools/simple"
5821-	"honnef.co/go/tools/staticcheck"
5822-	"honnef.co/go/tools/stylecheck"
5823-)
5824-
5825-func updateAnalyzers(options *source.Options) {
5826-	options.StaticcheckSupported = true
5827-
5828-	mapSeverity := func(severity lint.Severity) protocol.DiagnosticSeverity {
5829-		switch severity {
5830-		case lint.SeverityError:
5831-			return protocol.SeverityError
5832-		case lint.SeverityDeprecated:
5833-			// TODO(dh): in LSP, deprecated is a tag, not a severity.
5834-			//   We'll want to support this once we enable SA5011.
5835-			return protocol.SeverityWarning
5836-		case lint.SeverityWarning:
5837-			return protocol.SeverityWarning
5838-		case lint.SeverityInfo:
5839-			return protocol.SeverityInformation
5840-		case lint.SeverityHint:
5841-			return protocol.SeverityHint
5842-		default:
5843-			return protocol.SeverityWarning
5844-		}
5845-	}
5846-	add := func(analyzers []*lint.Analyzer, skip map[string]struct{}) {
5847-		for _, a := range analyzers {
5848-			if _, ok := skip[a.Analyzer.Name]; ok {
5849-				continue
5850-			}
5851-
5852-			enabled := !a.Doc.NonDefault
5853-			options.AddStaticcheckAnalyzer(a.Analyzer, enabled, mapSeverity(a.Doc.Severity))
5854-		}
5855-	}
5856-
5857-	add(simple.Analyzers, nil)
5858-	add(staticcheck.Analyzers, map[string]struct{}{
5859-		// This check conflicts with the vet printf check (golang/go#34494).
5860-		"SA5009": {},
5861-		// This check relies on facts from dependencies, which
5862-		// we don't currently compute.
5863-		"SA5011": {},
5864-	})
5865-	add(stylecheck.Analyzers, nil)
5866-	add(quickfix.Analyzers, nil)
5867-}
5868diff -urN a/gopls/internal/hooks/diff.go b/gopls/internal/hooks/diff.go
5869--- a/gopls/internal/hooks/diff.go	2000-01-01 00:00:00.000000000 -0000
5870+++ b/gopls/internal/hooks/diff.go	1970-01-01 00:00:00.000000000 +0000
5871@@ -1,169 +0,0 @@
5872-// Copyright 2019 The Go Authors. All rights reserved.
5873-// Use of this source code is governed by a BSD-style
5874-// license that can be found in the LICENSE file.
5875-
5876-package hooks
5877-
5878-import (
5879-	"encoding/json"
5880-	"fmt"
5881-	"io/ioutil"
5882-	"log"
5883-	"os"
5884-	"path/filepath"
5885-	"runtime"
5886-	"sync"
5887-	"time"
5888-
5889-	"github.com/sergi/go-diff/diffmatchpatch"
5890-	"golang.org/x/tools/internal/bug"
5891-	"golang.org/x/tools/internal/diff"
5892-)
5893-
5894-// structure for saving information about diffs
5895-// while the new code is being rolled out
5896-type diffstat struct {
5897-	Before, After      int
5898-	Oldedits, Newedits int
5899-	Oldtime, Newtime   time.Duration
5900-	Stack              string
5901-	Msg                string `json:",omitempty"` // for errors
5902-	Ignored            int    `json:",omitempty"` // numbr of skipped records with 0 edits
5903-}
5904-
5905-var (
5906-	ignoredMu sync.Mutex
5907-	ignored   int // counter of diff requests on equal strings
5908-
5909-	diffStatsOnce sync.Once
5910-	diffStats     *os.File // never closed
5911-)
5912-
5913-// save writes a JSON record of statistics about diff requests to a temporary file.
5914-func (s *diffstat) save() {
5915-	diffStatsOnce.Do(func() {
5916-		f, err := ioutil.TempFile("", "gopls-diff-stats-*")
5917-		if err != nil {
5918-			log.Printf("can't create diff stats temp file: %v", err) // e.g. disk full
5919-			return
5920-		}
5921-		diffStats = f
5922-	})
5923-	if diffStats == nil {
5924-		return
5925-	}
5926-
5927-	// diff is frequently called with equal strings,
5928-	// so we count repeated instances but only print every 15th.
5929-	ignoredMu.Lock()
5930-	if s.Oldedits == 0 && s.Newedits == 0 {
5931-		ignored++
5932-		if ignored < 15 {
5933-			ignoredMu.Unlock()
5934-			return
5935-		}
5936-	}
5937-	s.Ignored = ignored
5938-	ignored = 0
5939-	ignoredMu.Unlock()
5940-
5941-	// Record the name of the file in which diff was called.
5942-	// There aren't many calls, so only the base name is needed.
5943-	if _, file, line, ok := runtime.Caller(2); ok {
5944-		s.Stack = fmt.Sprintf("%s:%d", filepath.Base(file), line)
5945-	}
5946-	x, err := json.Marshal(s)
5947-	if err != nil {
5948-		log.Fatalf("internal error marshalling JSON: %v", err)
5949-	}
5950-	fmt.Fprintf(diffStats, "%s\n", x)
5951-}
5952-
5953-// disaster is called when the diff algorithm panics or produces a
5954-// diff that cannot be applied. It saves the broken input in a
5955-// new temporary file and logs the file name, which is returned.
5956-func disaster(before, after string) string {
5957-	// We use the pid to salt the name, not os.TempFile,
5958-	// so that each process creates at most one file.
5959-	// One is sufficient for a bug report.
5960-	filename := fmt.Sprintf("%s/gopls-diff-bug-%x", os.TempDir(), os.Getpid())
5961-
5962-	// We use NUL as a separator: it should never appear in Go source.
5963-	data := before + "\x00" + after
5964-
5965-	if err := ioutil.WriteFile(filename, []byte(data), 0600); err != nil {
5966-		log.Printf("failed to write diff bug report: %v", err)
5967-		return ""
5968-	}
5969-
5970-	bug.Reportf("Bug detected in diff algorithm! Please send file %s to the maintainers of gopls if you are comfortable sharing its contents.", filename)
5971-
5972-	return filename
5973-}
5974-
5975-// BothDiffs edits calls both the new and old diffs, checks that the new diffs
5976-// change before into after, and attempts to preserve some statistics.
5977-func BothDiffs(before, after string) (edits []diff.Edit) {
5978-	// The new diff code contains a lot of internal checks that panic when they
5979-	// fail. This code catches the panics, or other failures, tries to save
5980-	// the failing example (and it would ask the user to send it back to us, and
5981-	// changes options.newDiff to 'old', if only we could figure out how.)
5982-	stat := diffstat{Before: len(before), After: len(after)}
5983-	now := time.Now()
5984-	oldedits := ComputeEdits(before, after)
5985-	stat.Oldedits = len(oldedits)
5986-	stat.Oldtime = time.Since(now)
5987-	defer func() {
5988-		if r := recover(); r != nil {
5989-			disaster(before, after)
5990-			edits = oldedits
5991-		}
5992-	}()
5993-	now = time.Now()
5994-	newedits := diff.Strings(before, after)
5995-	stat.Newedits = len(newedits)
5996-	stat.Newtime = time.Now().Sub(now)
5997-	got, err := diff.Apply(before, newedits)
5998-	if err != nil || got != after {
5999-		stat.Msg += "FAIL"
6000-		disaster(before, after)
6001-		stat.save()
6002-		return oldedits
6003-	}
6004-	stat.save()
6005-	return newedits
6006-}
6007-
6008-// ComputeEdits computes a diff using the github.com/sergi/go-diff implementation.
6009-func ComputeEdits(before, after string) (edits []diff.Edit) {
6010-	// The go-diff library has an unresolved panic (see golang/go#278774).
6011-	// TODO(rstambler): Remove the recover once the issue has been fixed
6012-	// upstream.
6013-	defer func() {
6014-		if r := recover(); r != nil {
6015-			bug.Reportf("unable to compute edits: %s", r)
6016-			// Report one big edit for the whole file.
6017-			edits = []diff.Edit{{
6018-				Start: 0,
6019-				End:   len(before),
6020-				New:   after,
6021-			}}
6022-		}
6023-	}()
6024-	diffs := diffmatchpatch.New().DiffMain(before, after, true)
6025-	edits = make([]diff.Edit, 0, len(diffs))
6026-	offset := 0
6027-	for _, d := range diffs {
6028-		start := offset
6029-		switch d.Type {
6030-		case diffmatchpatch.DiffDelete:
6031-			offset += len(d.Text)
6032-			edits = append(edits, diff.Edit{Start: start, End: offset})
6033-		case diffmatchpatch.DiffEqual:
6034-			offset += len(d.Text)
6035-		case diffmatchpatch.DiffInsert:
6036-			edits = append(edits, diff.Edit{Start: start, End: start, New: d.Text})
6037-		}
6038-	}
6039-	return edits
6040-}
6041diff -urN a/gopls/internal/hooks/diff_test.go b/gopls/internal/hooks/diff_test.go
6042--- a/gopls/internal/hooks/diff_test.go	2000-01-01 00:00:00.000000000 -0000
6043+++ b/gopls/internal/hooks/diff_test.go	1970-01-01 00:00:00.000000000 +0000
6044@@ -1,33 +0,0 @@
6045-// Copyright 2019 The Go Authors. All rights reserved.
6046-// Use of this source code is governed by a BSD-style
6047-// license that can be found in the LICENSE file.
6048-
6049-package hooks
6050-
6051-import (
6052-	"io/ioutil"
6053-	"os"
6054-	"testing"
6055-
6056-	"golang.org/x/tools/internal/diff/difftest"
6057-)
6058-
6059-func TestDiff(t *testing.T) {
6060-	difftest.DiffTest(t, ComputeEdits)
6061-}
6062-
6063-func TestDisaster(t *testing.T) {
6064-	a := "This is a string,(\u0995) just for basic\nfunctionality"
6065-	b := "This is another string, (\u0996) to see if disaster will store stuff correctly"
6066-	fname := disaster(a, b)
6067-	buf, err := ioutil.ReadFile(fname)
6068-	if err != nil {
6069-		t.Fatal(err)
6070-	}
6071-	if string(buf) != a+"\x00"+b {
6072-		t.Error("failed to record original strings")
6073-	}
6074-	if err := os.Remove(fname); err != nil {
6075-		t.Error(err)
6076-	}
6077-}
6078diff -urN a/gopls/internal/hooks/gen-licenses.sh b/gopls/internal/hooks/gen-licenses.sh
6079--- a/gopls/internal/hooks/gen-licenses.sh	2000-01-01 00:00:00.000000000 -0000
6080+++ b/gopls/internal/hooks/gen-licenses.sh	1970-01-01 00:00:00.000000000 +0000
6081@@ -1,38 +0,0 @@
6082-#!/bin/bash -eu
6083-
6084-# Copyright 2020 The Go Authors. All rights reserved.
6085-# Use of this source code is governed by a BSD-style
6086-# license that can be found in the LICENSE file.
6087-
6088-set -o pipefail
6089-
6090-output=$1
6091-tempfile=$(mktemp)
6092-cd $(dirname $0)
6093-
6094-cat > $tempfile <<END
6095-// Copyright 2020 The Go Authors. All rights reserved.
6096-// Use of this source code is governed by a BSD-style
6097-// license that can be found in the LICENSE file.
6098-
6099-//go:generate ./gen-licenses.sh licenses.go
6100-package hooks
6101-
6102-const licensesText = \`
6103-END
6104-
6105-# List all the modules gopls depends on, except other golang.org modules, which
6106-# are known to have the same license.
6107-mods=$(go list -deps -f '{{with .Module}}{{.Path}}{{end}}' golang.org/x/tools/gopls | sort -u | grep -v golang.org)
6108-for mod in $mods; do
6109-  # Find the license file, either LICENSE or COPYING, and add it to the result.
6110-  dir=$(go list -m -f {{.Dir}} $mod)
6111-  license=$(ls -1 $dir | grep -E -i '^(LICENSE|COPYING)$')
6112-  echo "-- $mod $license --" >> $tempfile
6113-  echo >> $tempfile
6114-  sed 's/^-- / &/' $dir/$license >> $tempfile
6115-  echo >> $tempfile
6116-done
6117-
6118-echo "\`" >> $tempfile
6119-mv $tempfile $output
6120\ No newline at end of file
6121diff -urN a/gopls/internal/hooks/gofumpt_117.go b/gopls/internal/hooks/gofumpt_117.go
6122--- a/gopls/internal/hooks/gofumpt_117.go	2000-01-01 00:00:00.000000000 -0000
6123+++ b/gopls/internal/hooks/gofumpt_117.go	1970-01-01 00:00:00.000000000 +0000
6124@@ -1,13 +0,0 @@
6125-// Copyright 2021 The Go Authors. All rights reserved.
6126-// Use of this source code is governed by a BSD-style
6127-// license that can be found in the LICENSE file.
6128-
6129-//go:build !go1.18
6130-// +build !go1.18
6131-
6132-package hooks
6133-
6134-import "golang.org/x/tools/gopls/internal/lsp/source"
6135-
6136-func updateGofumpt(options *source.Options) {
6137-}
6138diff -urN a/gopls/internal/hooks/gofumpt_118.go b/gopls/internal/hooks/gofumpt_118.go
6139--- a/gopls/internal/hooks/gofumpt_118.go	2000-01-01 00:00:00.000000000 -0000
6140+++ b/gopls/internal/hooks/gofumpt_118.go	1970-01-01 00:00:00.000000000 +0000
6141@@ -1,24 +0,0 @@
6142-// Copyright 2022 The Go Authors. All rights reserved.
6143-// Use of this source code is governed by a BSD-style
6144-// license that can be found in the LICENSE file.
6145-
6146-//go:build go1.18
6147-// +build go1.18
6148-
6149-package hooks
6150-
6151-import (
6152-	"context"
6153-
6154-	"golang.org/x/tools/gopls/internal/lsp/source"
6155-	"mvdan.cc/gofumpt/format"
6156-)
6157-
6158-func updateGofumpt(options *source.Options) {
6159-	options.GofumptFormat = func(ctx context.Context, langVersion, modulePath string, src []byte) ([]byte, error) {
6160-		return format.Source(src, format.Options{
6161-			LangVersion: langVersion,
6162-			ModulePath:  modulePath,
6163-		})
6164-	}
6165-}
6166diff -urN a/gopls/internal/hooks/hooks.go b/gopls/internal/hooks/hooks.go
6167--- a/gopls/internal/hooks/hooks.go	2000-01-01 00:00:00.000000000 -0000
6168+++ b/gopls/internal/hooks/hooks.go	1970-01-01 00:00:00.000000000 +0000
6169@@ -1,31 +0,0 @@
6170-// Copyright 2019 The Go Authors. All rights reserved.
6171-// Use of this source code is governed by a BSD-style
6172-// license that can be found in the LICENSE file.
6173-
6174-// Package hooks adds all the standard gopls implementations.
6175-// This can be used in tests without needing to use the gopls main, and is
6176-// also the place to edit for custom builds of gopls.
6177-package hooks // import "golang.org/x/tools/gopls/internal/hooks"
6178-
6179-import (
6180-	"golang.org/x/tools/gopls/internal/lsp/source"
6181-	"golang.org/x/tools/internal/diff"
6182-	"mvdan.cc/xurls/v2"
6183-)
6184-
6185-func Options(options *source.Options) {
6186-	options.LicensesText = licensesText
6187-	if options.GoDiff {
6188-		switch options.NewDiff {
6189-		case "old":
6190-			options.ComputeEdits = ComputeEdits
6191-		case "new":
6192-			options.ComputeEdits = diff.Strings
6193-		default:
6194-			options.ComputeEdits = BothDiffs
6195-		}
6196-	}
6197-	options.URLRegexp = xurls.Relaxed()
6198-	updateAnalyzers(options)
6199-	updateGofumpt(options)
6200-}
6201diff -urN a/gopls/internal/hooks/licenses.go b/gopls/internal/hooks/licenses.go
6202--- a/gopls/internal/hooks/licenses.go	2000-01-01 00:00:00.000000000 -0000
6203+++ b/gopls/internal/hooks/licenses.go	1970-01-01 00:00:00.000000000 +0000
6204@@ -1,169 +0,0 @@
6205-// Copyright 2020 The Go Authors. All rights reserved.
6206-// Use of this source code is governed by a BSD-style
6207-// license that can be found in the LICENSE file.
6208-
6209-//go:generate ./gen-licenses.sh licenses.go
6210-package hooks
6211-
6212-const licensesText = `
6213--- github.com/BurntSushi/toml COPYING --
6214-
6215-The MIT License (MIT)
6216-
6217-Copyright (c) 2013 TOML authors
6218-
6219-Permission is hereby granted, free of charge, to any person obtaining a copy
6220-of this software and associated documentation files (the "Software"), to deal
6221-in the Software without restriction, including without limitation the rights
6222-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6223-copies of the Software, and to permit persons to whom the Software is
6224-furnished to do so, subject to the following conditions:
6225-
6226-The above copyright notice and this permission notice shall be included in
6227-all copies or substantial portions of the Software.
6228-
6229-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6230-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6231-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6232-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6233-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
6234-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
6235-THE SOFTWARE.
6236-
6237--- github.com/google/go-cmp LICENSE --
6238-
6239-Copyright (c) 2017 The Go Authors. All rights reserved.
6240-
6241-Redistribution and use in source and binary forms, with or without
6242-modification, are permitted provided that the following conditions are
6243-met:
6244-
6245-   * Redistributions of source code must retain the above copyright
6246-notice, this list of conditions and the following disclaimer.
6247-   * Redistributions in binary form must reproduce the above
6248-copyright notice, this list of conditions and the following disclaimer
6249-in the documentation and/or other materials provided with the
6250-distribution.
6251-   * Neither the name of Google Inc. nor the names of its
6252-contributors may be used to endorse or promote products derived from
6253-this software without specific prior written permission.
6254-
6255-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6256-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6257-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6258-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
6259-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
6260-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
6261-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
6262-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
6263-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6264-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
6265-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6266-
6267--- github.com/sergi/go-diff LICENSE --
6268-
6269-Copyright (c) 2012-2016 The go-diff Authors. All rights reserved.
6270-
6271-Permission is hereby granted, free of charge, to any person obtaining a
6272-copy of this software and associated documentation files (the "Software"),
6273-to deal in the Software without restriction, including without limitation
6274-the rights to use, copy, modify, merge, publish, distribute, sublicense,
6275-and/or sell copies of the Software, and to permit persons to whom the
6276-Software is furnished to do so, subject to the following conditions:
6277-
6278-The above copyright notice and this permission notice shall be included
6279-in all copies or substantial portions of the Software.
6280-
6281-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6282-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6283-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6284-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6285-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
6286-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
6287-DEALINGS IN THE SOFTWARE.
6288-
6289-
6290--- honnef.co/go/tools LICENSE --
6291-
6292-Copyright (c) 2016 Dominik Honnef
6293-
6294-Permission is hereby granted, free of charge, to any person obtaining
6295-a copy of this software and associated documentation files (the
6296-"Software"), to deal in the Software without restriction, including
6297-without limitation the rights to use, copy, modify, merge, publish,
6298-distribute, sublicense, and/or sell copies of the Software, and to
6299-permit persons to whom the Software is furnished to do so, subject to
6300-the following conditions:
6301-
6302-The above copyright notice and this permission notice shall be
6303-included in all copies or substantial portions of the Software.
6304-
6305-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
6306-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6307-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
6308-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
6309-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
6310-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
6311-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6312-
6313--- mvdan.cc/gofumpt LICENSE --
6314-
6315-Copyright (c) 2019, Daniel Martí. All rights reserved.
6316-
6317-Redistribution and use in source and binary forms, with or without
6318-modification, are permitted provided that the following conditions are
6319-met:
6320-
6321-   * Redistributions of source code must retain the above copyright
6322-notice, this list of conditions and the following disclaimer.
6323-   * Redistributions in binary form must reproduce the above
6324-copyright notice, this list of conditions and the following disclaimer
6325-in the documentation and/or other materials provided with the
6326-distribution.
6327-   * Neither the name of the copyright holder nor the names of its
6328-contributors may be used to endorse or promote products derived from
6329-this software without specific prior written permission.
6330-
6331-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6332-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6333-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6334-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
6335-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
6336-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
6337-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
6338-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
6339-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6340-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
6341-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6342-
6343--- mvdan.cc/xurls/v2 LICENSE --
6344-
6345-Copyright (c) 2015, Daniel Martí. All rights reserved.
6346-
6347-Redistribution and use in source and binary forms, with or without
6348-modification, are permitted provided that the following conditions are
6349-met:
6350-
6351-   * Redistributions of source code must retain the above copyright
6352-notice, this list of conditions and the following disclaimer.
6353-   * Redistributions in binary form must reproduce the above
6354-copyright notice, this list of conditions and the following disclaimer
6355-in the documentation and/or other materials provided with the
6356-distribution.
6357-   * Neither the name of the copyright holder nor the names of its
6358-contributors may be used to endorse or promote products derived from
6359-this software without specific prior written permission.
6360-
6361-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6362-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6363-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6364-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
6365-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
6366-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
6367-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
6368-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
6369-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6370-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
6371-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6372-
6373-`
6374diff -urN a/gopls/internal/hooks/licenses_test.go b/gopls/internal/hooks/licenses_test.go
6375--- a/gopls/internal/hooks/licenses_test.go	2000-01-01 00:00:00.000000000 -0000
6376+++ b/gopls/internal/hooks/licenses_test.go	1970-01-01 00:00:00.000000000 +0000
6377@@ -1,47 +0,0 @@
6378-// Copyright 2020 The Go Authors. All rights reserved.
6379-// Use of this source code is governed by a BSD-style
6380-// license that can be found in the LICENSE file.
6381-
6382-package hooks
6383-
6384-import (
6385-	"bytes"
6386-	"io/ioutil"
6387-	"os/exec"
6388-	"runtime"
6389-	"testing"
6390-
6391-	"golang.org/x/tools/internal/testenv"
6392-)
6393-
6394-func TestLicenses(t *testing.T) {
6395-	// License text differs for older Go versions because staticcheck or gofumpt
6396-	// isn't supported for those versions, and this fails for unknown, unrelated
6397-	// reasons on Kokoro legacy CI.
6398-	testenv.NeedsGo1Point(t, 19)
6399-
6400-	if runtime.GOOS != "linux" && runtime.GOOS != "darwin" {
6401-		t.Skip("generating licenses only works on Unixes")
6402-	}
6403-	tmp, err := ioutil.TempFile("", "")
6404-	if err != nil {
6405-		t.Fatal(err)
6406-	}
6407-	tmp.Close()
6408-
6409-	if out, err := exec.Command("./gen-licenses.sh", tmp.Name()).CombinedOutput(); err != nil {
6410-		t.Fatalf("generating licenses failed: %q, %v", out, err)
6411-	}
6412-
6413-	got, err := ioutil.ReadFile(tmp.Name())
6414-	if err != nil {
6415-		t.Fatal(err)
6416-	}
6417-	want, err := ioutil.ReadFile("licenses.go")
6418-	if err != nil {
6419-		t.Fatal(err)
6420-	}
6421-	if !bytes.Equal(got, want) {
6422-		t.Error("combined license text needs updating. Run: `go generate ./internal/hooks` from the gopls module.")
6423-	}
6424-}
6425diff -urN a/gopls/internal/lsp/analysis/embeddirective/embeddirective.go b/gopls/internal/lsp/analysis/embeddirective/embeddirective.go
6426--- a/gopls/internal/lsp/analysis/embeddirective/embeddirective.go	2000-01-01 00:00:00.000000000 -0000
6427+++ b/gopls/internal/lsp/analysis/embeddirective/embeddirective.go	1970-01-01 00:00:00.000000000 +0000
6428@@ -1,58 +0,0 @@
6429-// Copyright 2022 The Go Authors. All rights reserved.
6430-// Use of this source code is governed by a BSD-style
6431-// license that can be found in the LICENSE file.
6432-
6433-// Package embeddirective defines an Analyzer that validates import for //go:embed directive.
6434-package embeddirective
6435-
6436-import (
6437-	"go/ast"
6438-	"strings"
6439-
6440-	"golang.org/x/tools/go/analysis"
6441-)
6442-
6443-const Doc = `check for //go:embed directive import
6444-
6445-This analyzer checks that the embed package is imported when source code contains //go:embed comment directives.
6446-The embed package must be imported for //go:embed directives to function.import _ "embed".`
6447-
6448-var Analyzer = &analysis.Analyzer{
6449-	Name:             "embed",
6450-	Doc:              Doc,
6451-	Requires:         []*analysis.Analyzer{},
6452-	Run:              run,
6453-	RunDespiteErrors: true,
6454-}
6455-
6456-func run(pass *analysis.Pass) (interface{}, error) {
6457-	for _, f := range pass.Files {
6458-		com := hasEmbedDirectiveComment(f)
6459-		if com != nil {
6460-			assertEmbedImport(pass, com, f)
6461-		}
6462-	}
6463-	return nil, nil
6464-}
6465-
6466-// Check if the comment contains //go:embed directive.
6467-func hasEmbedDirectiveComment(f *ast.File) *ast.Comment {
6468-	for _, cg := range f.Comments {
6469-		for _, c := range cg.List {
6470-			if strings.HasPrefix(c.Text, "//go:embed ") {
6471-				return c
6472-			}
6473-		}
6474-	}
6475-	return nil
6476-}
6477-
6478-// Verifies that "embed" import exists for //go:embed directive.
6479-func assertEmbedImport(pass *analysis.Pass, com *ast.Comment, f *ast.File) {
6480-	for _, imp := range f.Imports {
6481-		if "\"embed\"" == imp.Path.Value {
6482-			return
6483-		}
6484-	}
6485-	pass.Report(analysis.Diagnostic{Pos: com.Pos(), End: com.Pos() + 10, Message: "The \"embed\" package must be imported when using go:embed directives."})
6486-}
6487diff -urN a/gopls/internal/lsp/analysis/embeddirective/embeddirective_test.go b/gopls/internal/lsp/analysis/embeddirective/embeddirective_test.go
6488--- a/gopls/internal/lsp/analysis/embeddirective/embeddirective_test.go	2000-01-01 00:00:00.000000000 -0000
6489+++ b/gopls/internal/lsp/analysis/embeddirective/embeddirective_test.go	1970-01-01 00:00:00.000000000 +0000
6490@@ -1,22 +0,0 @@
6491-// Copyright 2022 The Go Authors. All rights reserved.
6492-// Use of this source code is governed by a BSD-style
6493-// license that can be found in the LICENSE file.
6494-
6495-package embeddirective
6496-
6497-import (
6498-	"testing"
6499-
6500-	"golang.org/x/tools/go/analysis/analysistest"
6501-	"golang.org/x/tools/internal/typeparams"
6502-)
6503-
6504-func Test(t *testing.T) {
6505-	testdata := analysistest.TestData()
6506-	tests := []string{"a"}
6507-	if typeparams.Enabled {
6508-		tests = append(tests)
6509-	}
6510-
6511-	analysistest.RunWithSuggestedFixes(t, testdata, Analyzer, tests...)
6512-}
6513diff -urN a/gopls/internal/lsp/analysis/embeddirective/testdata/src/a/a.go b/gopls/internal/lsp/analysis/embeddirective/testdata/src/a/a.go
6514--- a/gopls/internal/lsp/analysis/embeddirective/testdata/src/a/a.go	2000-01-01 00:00:00.000000000 -0000
6515+++ b/gopls/internal/lsp/analysis/embeddirective/testdata/src/a/a.go	1970-01-01 00:00:00.000000000 +0000
6516@@ -1,13 +0,0 @@
6517-package a
6518-
6519-import (
6520-	"fmt"
6521-)
6522-
6523-//go:embed embedText // want "The \"embed\" package must be imported when using go:embed directives"
6524-var s string
6525-
6526-// This is main function
6527-func main() {
6528-	fmt.Println(s)
6529-}
6530diff -urN a/gopls/internal/lsp/analysis/embeddirective/testdata/src/a/b.go b/gopls/internal/lsp/analysis/embeddirective/testdata/src/a/b.go
6531--- a/gopls/internal/lsp/analysis/embeddirective/testdata/src/a/b.go	2000-01-01 00:00:00.000000000 -0000
6532+++ b/gopls/internal/lsp/analysis/embeddirective/testdata/src/a/b.go	1970-01-01 00:00:00.000000000 +0000
6533@@ -1,14 +0,0 @@
6534-package a
6535-
6536-import (
6537-	_ "embed"
6538-	"fmt"
6539-)
6540-
6541-//go:embed embedText // ok
6542-var s string
6543-
6544-// This is main function
6545-func main() {
6546-	fmt.Println(s)
6547-}
6548diff -urN a/gopls/internal/lsp/analysis/embeddirective/testdata/src/a/embedText b/gopls/internal/lsp/analysis/embeddirective/testdata/src/a/embedText
6549--- a/gopls/internal/lsp/analysis/embeddirective/testdata/src/a/embedText	2000-01-01 00:00:00.000000000 -0000
6550+++ b/gopls/internal/lsp/analysis/embeddirective/testdata/src/a/embedText	1970-01-01 00:00:00.000000000 +0000
6551@@ -1 +0,0 @@
6552-Hello World
6553\ No newline at end of file
6554diff -urN a/gopls/internal/lsp/analysis/fillreturns/fillreturns.go b/gopls/internal/lsp/analysis/fillreturns/fillreturns.go
6555--- a/gopls/internal/lsp/analysis/fillreturns/fillreturns.go	2000-01-01 00:00:00.000000000 -0000
6556+++ b/gopls/internal/lsp/analysis/fillreturns/fillreturns.go	1970-01-01 00:00:00.000000000 +0000
6557@@ -1,279 +0,0 @@
6558-// Copyright 2020 The Go Authors. All rights reserved.
6559-// Use of this source code is governed by a BSD-style
6560-// license that can be found in the LICENSE file.
6561-
6562-// Package fillreturns defines an Analyzer that will attempt to
6563-// automatically fill in a return statement that has missing
6564-// values with zero value elements.
6565-package fillreturns
6566-
6567-import (
6568-	"bytes"
6569-	"fmt"
6570-	"go/ast"
6571-	"go/format"
6572-	"go/types"
6573-	"regexp"
6574-	"strings"
6575-
6576-	"golang.org/x/tools/go/analysis"
6577-	"golang.org/x/tools/go/ast/astutil"
6578-	"golang.org/x/tools/internal/analysisinternal"
6579-	"golang.org/x/tools/internal/fuzzy"
6580-	"golang.org/x/tools/internal/typeparams"
6581-)
6582-
6583-const Doc = `suggest fixes for errors due to an incorrect number of return values
6584-
6585-This checker provides suggested fixes for type errors of the
6586-type "wrong number of return values (want %d, got %d)". For example:
6587-	func m() (int, string, *bool, error) {
6588-		return
6589-	}
6590-will turn into
6591-	func m() (int, string, *bool, error) {
6592-		return 0, "", nil, nil
6593-	}
6594-
6595-This functionality is similar to https://github.com/sqs/goreturns.
6596-`
6597-
6598-var Analyzer = &analysis.Analyzer{
6599-	Name:             "fillreturns",
6600-	Doc:              Doc,
6601-	Requires:         []*analysis.Analyzer{},
6602-	Run:              run,
6603-	RunDespiteErrors: true,
6604-}
6605-
6606-func run(pass *analysis.Pass) (interface{}, error) {
6607-	info := pass.TypesInfo
6608-	if info == nil {
6609-		return nil, fmt.Errorf("nil TypeInfo")
6610-	}
6611-
6612-outer:
6613-	for _, typeErr := range pass.TypeErrors {
6614-		// Filter out the errors that are not relevant to this analyzer.
6615-		if !FixesError(typeErr) {
6616-			continue
6617-		}
6618-		var file *ast.File
6619-		for _, f := range pass.Files {
6620-			if f.Pos() <= typeErr.Pos && typeErr.Pos <= f.End() {
6621-				file = f
6622-				break
6623-			}
6624-		}
6625-		if file == nil {
6626-			continue
6627-		}
6628-
6629-		// Get the end position of the error.
6630-		// (This heuristic assumes that the buffer is formatted,
6631-		// at least up to the end position of the error.)
6632-		var buf bytes.Buffer
6633-		if err := format.Node(&buf, pass.Fset, file); err != nil {
6634-			continue
6635-		}
6636-		typeErrEndPos := analysisinternal.TypeErrorEndPos(pass.Fset, buf.Bytes(), typeErr.Pos)
6637-
6638-		// TODO(rfindley): much of the error handling code below returns, when it
6639-		// should probably continue.
6640-
6641-		// Get the path for the relevant range.
6642-		path, _ := astutil.PathEnclosingInterval(file, typeErr.Pos, typeErrEndPos)
6643-		if len(path) == 0 {
6644-			return nil, nil
6645-		}
6646-
6647-		// Find the enclosing return statement.
6648-		var ret *ast.ReturnStmt
6649-		var retIdx int
6650-		for i, n := range path {
6651-			if r, ok := n.(*ast.ReturnStmt); ok {
6652-				ret = r
6653-				retIdx = i
6654-				break
6655-			}
6656-		}
6657-		if ret == nil {
6658-			return nil, nil
6659-		}
6660-
6661-		// Get the function type that encloses the ReturnStmt.
6662-		var enclosingFunc *ast.FuncType
6663-		for _, n := range path[retIdx+1:] {
6664-			switch node := n.(type) {
6665-			case *ast.FuncLit:
6666-				enclosingFunc = node.Type
6667-			case *ast.FuncDecl:
6668-				enclosingFunc = node.Type
6669-			}
6670-			if enclosingFunc != nil {
6671-				break
6672-			}
6673-		}
6674-		if enclosingFunc == nil || enclosingFunc.Results == nil {
6675-			continue
6676-		}
6677-
6678-		// Skip any generic enclosing functions, since type parameters don't
6679-		// have 0 values.
6680-		// TODO(rfindley): We should be able to handle this if the return
6681-		// values are all concrete types.
6682-		if tparams := typeparams.ForFuncType(enclosingFunc); tparams != nil && tparams.NumFields() > 0 {
6683-			return nil, nil
6684-		}
6685-
6686-		// Find the function declaration that encloses the ReturnStmt.
6687-		var outer *ast.FuncDecl
6688-		for _, p := range path {
6689-			if p, ok := p.(*ast.FuncDecl); ok {
6690-				outer = p
6691-				break
6692-			}
6693-		}
6694-		if outer == nil {
6695-			return nil, nil
6696-		}
6697-
6698-		// Skip any return statements that contain function calls with multiple
6699-		// return values.
6700-		for _, expr := range ret.Results {
6701-			e, ok := expr.(*ast.CallExpr)
6702-			if !ok {
6703-				continue
6704-			}
6705-			if tup, ok := info.TypeOf(e).(*types.Tuple); ok && tup.Len() > 1 {
6706-				continue outer
6707-			}
6708-		}
6709-
6710-		// Duplicate the return values to track which values have been matched.
6711-		remaining := make([]ast.Expr, len(ret.Results))
6712-		copy(remaining, ret.Results)
6713-
6714-		fixed := make([]ast.Expr, len(enclosingFunc.Results.List))
6715-
6716-		// For each value in the return function declaration, find the leftmost element
6717-		// in the return statement that has the desired type. If no such element exists,
6718-		// fill in the missing value with the appropriate "zero" value.
6719-		// Beware that type information may be incomplete.
6720-		var retTyps []types.Type
6721-		for _, ret := range enclosingFunc.Results.List {
6722-			retTyp := info.TypeOf(ret.Type)
6723-			if retTyp == nil {
6724-				return nil, nil
6725-			}
6726-			retTyps = append(retTyps, retTyp)
6727-		}
6728-		matches := analysisinternal.MatchingIdents(retTyps, file, ret.Pos(), info, pass.Pkg)
6729-		for i, retTyp := range retTyps {
6730-			var match ast.Expr
6731-			var idx int
6732-			for j, val := range remaining {
6733-				if t := info.TypeOf(val); t == nil || !matchingTypes(t, retTyp) {
6734-					continue
6735-				}
6736-				if !analysisinternal.IsZeroValue(val) {
6737-					match, idx = val, j
6738-					break
6739-				}
6740-				// If the current match is a "zero" value, we keep searching in
6741-				// case we find a non-"zero" value match. If we do not find a
6742-				// non-"zero" value, we will use the "zero" value.
6743-				match, idx = val, j
6744-			}
6745-
6746-			if match != nil {
6747-				fixed[i] = match
6748-				remaining = append(remaining[:idx], remaining[idx+1:]...)
6749-			} else {
6750-				names, ok := matches[retTyp]
6751-				if !ok {
6752-					return nil, fmt.Errorf("invalid return type: %v", retTyp)
6753-				}
6754-				// Find the identifier most similar to the return type.
6755-				// If no identifier matches the pattern, generate a zero value.
6756-				if best := fuzzy.BestMatch(retTyp.String(), names); best != "" {
6757-					fixed[i] = ast.NewIdent(best)
6758-				} else if zero := analysisinternal.ZeroValue(file, pass.Pkg, retTyp); zero != nil {
6759-					fixed[i] = zero
6760-				} else {
6761-					return nil, nil
6762-				}
6763-			}
6764-		}
6765-
6766-		// Remove any non-matching "zero values" from the leftover values.
6767-		var nonZeroRemaining []ast.Expr
6768-		for _, expr := range remaining {
6769-			if !analysisinternal.IsZeroValue(expr) {
6770-				nonZeroRemaining = append(nonZeroRemaining, expr)
6771-			}
6772-		}
6773-		// Append leftover return values to end of new return statement.
6774-		fixed = append(fixed, nonZeroRemaining...)
6775-
6776-		newRet := &ast.ReturnStmt{
6777-			Return:  ret.Pos(),
6778-			Results: fixed,
6779-		}
6780-
6781-		// Convert the new return statement AST to text.
6782-		var newBuf bytes.Buffer
6783-		if err := format.Node(&newBuf, pass.Fset, newRet); err != nil {
6784-			return nil, err
6785-		}
6786-
6787-		pass.Report(analysis.Diagnostic{
6788-			Pos:     typeErr.Pos,
6789-			End:     typeErrEndPos,
6790-			Message: typeErr.Msg,
6791-			SuggestedFixes: []analysis.SuggestedFix{{
6792-				Message: "Fill in return values",
6793-				TextEdits: []analysis.TextEdit{{
6794-					Pos:     ret.Pos(),
6795-					End:     ret.End(),
6796-					NewText: newBuf.Bytes(),
6797-				}},
6798-			}},
6799-		})
6800-	}
6801-	return nil, nil
6802-}
6803-
6804-func matchingTypes(want, got types.Type) bool {
6805-	if want == got || types.Identical(want, got) {
6806-		return true
6807-	}
6808-	// Code segment to help check for untyped equality from (golang/go#32146).
6809-	if rhs, ok := want.(*types.Basic); ok && rhs.Info()&types.IsUntyped > 0 {
6810-		if lhs, ok := got.Underlying().(*types.Basic); ok {
6811-			return rhs.Info()&types.IsConstType == lhs.Info()&types.IsConstType
6812-		}
6813-	}
6814-	return types.AssignableTo(want, got) || types.ConvertibleTo(want, got)
6815-}
6816-
6817-// Error messages have changed across Go versions. These regexps capture recent
6818-// incarnations.
6819-//
6820-// TODO(rfindley): once error codes are exported and exposed via go/packages,
6821-// use error codes rather than string matching here.
6822-var wrongReturnNumRegexes = []*regexp.Regexp{
6823-	regexp.MustCompile(`wrong number of return values \(want (\d+), got (\d+)\)`),
6824-	regexp.MustCompile(`too many return values`),
6825-	regexp.MustCompile(`not enough return values`),
6826-}
6827-
6828-func FixesError(err types.Error) bool {
6829-	msg := strings.TrimSpace(err.Msg)
6830-	for _, rx := range wrongReturnNumRegexes {
6831-		if rx.MatchString(msg) {
6832-			return true
6833-		}
6834-	}
6835-	return false
6836-}
6837diff -urN a/gopls/internal/lsp/analysis/fillreturns/fillreturns_test.go b/gopls/internal/lsp/analysis/fillreturns/fillreturns_test.go
6838--- a/gopls/internal/lsp/analysis/fillreturns/fillreturns_test.go	2000-01-01 00:00:00.000000000 -0000
6839+++ b/gopls/internal/lsp/analysis/fillreturns/fillreturns_test.go	1970-01-01 00:00:00.000000000 +0000
6840@@ -1,22 +0,0 @@
6841-// Copyright 2020 The Go Authors. All rights reserved.
6842-// Use of this source code is governed by a BSD-style
6843-// license that can be found in the LICENSE file.
6844-
6845-package fillreturns_test
6846-
6847-import (
6848-	"testing"
6849-
6850-	"golang.org/x/tools/go/analysis/analysistest"
6851-	"golang.org/x/tools/gopls/internal/lsp/analysis/fillreturns"
6852-	"golang.org/x/tools/internal/typeparams"
6853-)
6854-
6855-func Test(t *testing.T) {
6856-	testdata := analysistest.TestData()
6857-	tests := []string{"a"}
6858-	if typeparams.Enabled {
6859-		tests = append(tests, "typeparams")
6860-	}
6861-	analysistest.RunWithSuggestedFixes(t, testdata, fillreturns.Analyzer, tests...)
6862-}
6863diff -urN a/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/a.go b/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/a.go
6864--- a/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/a.go	2000-01-01 00:00:00.000000000 -0000
6865+++ b/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/a.go	1970-01-01 00:00:00.000000000 +0000
6866@@ -1,139 +0,0 @@
6867-// Copyright 2020 The Go Authors. All rights reserved.
6868-// Use of this source code is governed by a BSD-style
6869-// license that can be found in the LICENSE file.
6870-
6871-package fillreturns
6872-
6873-import (
6874-	"errors"
6875-	"go/ast"
6876-	ast2 "go/ast"
6877-	"io"
6878-	"net/http"
6879-	. "net/http"
6880-	"net/url"
6881-	"strconv"
6882-)
6883-
6884-type T struct{}
6885-type T1 = T
6886-type I interface{}
6887-type I1 = I
6888-type z func(string, http.Handler) error
6889-
6890-func x() error {
6891-	return errors.New("foo")
6892-}
6893-
6894-// The error messages below changed in 1.18; "return values" covers both forms.
6895-
6896-func b() (string, int, error) {
6897-	return "", errors.New("foo") // want "return values"
6898-}
6899-
6900-func c() (string, int, error) {
6901-	return 7, errors.New("foo") // want "return values"
6902-}
6903-
6904-func d() (string, int, error) {
6905-	return "", 7 // want "return values"
6906-}
6907-
6908-func e() (T, error, *bool) {
6909-	return (z(http.ListenAndServe))("", nil) // want "return values"
6910-}
6911-
6912-func preserveLeft() (int, int, error) {
6913-	return 1, errors.New("foo") // want "return values"
6914-}
6915-
6916-func matchValues() (int, error, string) {
6917-	return errors.New("foo"), 3 // want "return values"
6918-}
6919-
6920-func preventDataOverwrite() (int, string) {
6921-	return errors.New("foo") // want "return values"
6922-}
6923-
6924-func closure() (string, error) {
6925-	_ = func() (int, error) {
6926-		return // want "return values"
6927-	}
6928-	return // want "return values"
6929-}
6930-
6931-func basic() (uint8, uint16, uint32, uint64, int8, int16, int32, int64, float32, float64, complex64, complex128, byte, rune, uint, int, uintptr, string, bool, error) {
6932-	return // want "return values"
6933-}
6934-
6935-func complex() (*int, []int, [2]int, map[int]int) {
6936-	return // want "return values"
6937-}
6938-
6939-func structsAndInterfaces() (T, url.URL, T1, I, I1, io.Reader, Client, ast2.Stmt) {
6940-	return // want "return values"
6941-}
6942-
6943-func m() (int, error) {
6944-	if 1 == 2 {
6945-		return // want "return values"
6946-	} else if 1 == 3 {
6947-		return errors.New("foo") // want "return values"
6948-	} else {
6949-		return 1 // want "return values"
6950-	}
6951-	return // want "return values"
6952-}
6953-
6954-func convertibleTypes() (ast2.Expr, int) {
6955-	return &ast2.ArrayType{} // want "return values"
6956-}
6957-
6958-func assignableTypes() (map[string]int, int) {
6959-	type X map[string]int
6960-	var x X
6961-	return x // want "return values"
6962-}
6963-
6964-func interfaceAndError() (I, int) {
6965-	return errors.New("foo") // want "return values"
6966-}
6967-
6968-func funcOneReturn() (string, error) {
6969-	return strconv.Itoa(1) // want "return values"
6970-}
6971-
6972-func funcMultipleReturn() (int, error, string) {
6973-	return strconv.Atoi("1")
6974-}
6975-
6976-func localFuncMultipleReturn() (string, int, error, string) {
6977-	return b()
6978-}
6979-
6980-func multipleUnused() (int, string, string, string) {
6981-	return 3, 4, 5 // want "return values"
6982-}
6983-
6984-func gotTooMany() int {
6985-	if true {
6986-		return 0, "" // want "return values"
6987-	} else {
6988-		return 1, 0, nil // want "return values"
6989-	}
6990-	return 0, 5, false // want "return values"
6991-}
6992-
6993-func fillVars() (int, string, ast.Node, bool, error) {
6994-	eint := 0
6995-	s := "a"
6996-	var t bool
6997-	if true {
6998-		err := errors.New("fail")
6999-		return // want "return values"
7000-	}
7001-	n := ast.NewIdent("ident")
7002-	int := 3
7003-	var b bool
7004-	return "" // want "return values"
7005-}
7006diff -urN a/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/a.go.golden b/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/a.go.golden
7007--- a/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/a.go.golden	2000-01-01 00:00:00.000000000 -0000
7008+++ b/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/a.go.golden	1970-01-01 00:00:00.000000000 +0000
7009@@ -1,139 +0,0 @@
7010-// Copyright 2020 The Go Authors. All rights reserved.
7011-// Use of this source code is governed by a BSD-style
7012-// license that can be found in the LICENSE file.
7013-
7014-package fillreturns
7015-
7016-import (
7017-	"errors"
7018-	"go/ast"
7019-	ast2 "go/ast"
7020-	"io"
7021-	"net/http"
7022-	. "net/http"
7023-	"net/url"
7024-	"strconv"
7025-)
7026-
7027-type T struct{}
7028-type T1 = T
7029-type I interface{}
7030-type I1 = I
7031-type z func(string, http.Handler) error
7032-
7033-func x() error {
7034-	return errors.New("foo")
7035-}
7036-
7037-// The error messages below changed in 1.18; "return values" covers both forms.
7038-
7039-func b() (string, int, error) {
7040-	return "", 0, errors.New("foo") // want "return values"
7041-}
7042-
7043-func c() (string, int, error) {
7044-	return "", 7, errors.New("foo") // want "return values"
7045-}
7046-
7047-func d() (string, int, error) {
7048-	return "", 7, nil // want "return values"
7049-}
7050-
7051-func e() (T, error, *bool) {
7052-	return T{}, (z(http.ListenAndServe))("", nil), nil // want "return values"
7053-}
7054-
7055-func preserveLeft() (int, int, error) {
7056-	return 1, 0, errors.New("foo") // want "return values"
7057-}
7058-
7059-func matchValues() (int, error, string) {
7060-	return 3, errors.New("foo"), "" // want "return values"
7061-}
7062-
7063-func preventDataOverwrite() (int, string) {
7064-	return 0, "", errors.New("foo") // want "return values"
7065-}
7066-
7067-func closure() (string, error) {
7068-	_ = func() (int, error) {
7069-		return 0, nil // want "return values"
7070-	}
7071-	return "", nil // want "return values"
7072-}
7073-
7074-func basic() (uint8, uint16, uint32, uint64, int8, int16, int32, int64, float32, float64, complex64, complex128, byte, rune, uint, int, uintptr, string, bool, error) {
7075-	return 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", false, nil // want "return values"
7076-}
7077-
7078-func complex() (*int, []int, [2]int, map[int]int) {
7079-	return nil, nil, nil, nil // want "return values"
7080-}
7081-
7082-func structsAndInterfaces() (T, url.URL, T1, I, I1, io.Reader, Client, ast2.Stmt) {
7083-	return T{}, url.URL{}, T{}, nil, nil, nil, Client{}, nil // want "return values"
7084-}
7085-
7086-func m() (int, error) {
7087-	if 1 == 2 {
7088-		return 0, nil // want "return values"
7089-	} else if 1 == 3 {
7090-		return 0, errors.New("foo") // want "return values"
7091-	} else {
7092-		return 1, nil // want "return values"
7093-	}
7094-	return 0, nil // want "return values"
7095-}
7096-
7097-func convertibleTypes() (ast2.Expr, int) {
7098-	return &ast2.ArrayType{}, 0 // want "return values"
7099-}
7100-
7101-func assignableTypes() (map[string]int, int) {
7102-	type X map[string]int
7103-	var x X
7104-	return x, 0 // want "return values"
7105-}
7106-
7107-func interfaceAndError() (I, int) {
7108-	return errors.New("foo"), 0 // want "return values"
7109-}
7110-
7111-func funcOneReturn() (string, error) {
7112-	return strconv.Itoa(1), nil // want "return values"
7113-}
7114-
7115-func funcMultipleReturn() (int, error, string) {
7116-	return strconv.Atoi("1")
7117-}
7118-
7119-func localFuncMultipleReturn() (string, int, error, string) {
7120-	return b()
7121-}
7122-
7123-func multipleUnused() (int, string, string, string) {
7124-	return 3, "", "", "", 4, 5 // want "return values"
7125-}
7126-
7127-func gotTooMany() int {
7128-	if true {
7129-		return 0 // want "return values"
7130-	} else {
7131-		return 1 // want "return values"
7132-	}
7133-	return 5 // want "return values"
7134-}
7135-
7136-func fillVars() (int, string, ast.Node, bool, error) {
7137-	eint := 0
7138-	s := "a"
7139-	var t bool
7140-	if true {
7141-		err := errors.New("fail")
7142-		return eint, s, nil, false, err // want "return values"
7143-	}
7144-	n := ast.NewIdent("ident")
7145-	int := 3
7146-	var b bool
7147-	return int, "", n, b, nil // want "return values"
7148-}
7149diff -urN a/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/typeparams/a.go b/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/typeparams/a.go
7150--- a/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/typeparams/a.go	2000-01-01 00:00:00.000000000 -0000
7151+++ b/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/typeparams/a.go	1970-01-01 00:00:00.000000000 +0000
7152@@ -1,5 +0,0 @@
7153-package fillreturns
7154-
7155-func hello[T any]() int {
7156-	return
7157-}
7158diff -urN a/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/typeparams/a.go.golden b/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/typeparams/a.go.golden
7159--- a/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/typeparams/a.go.golden	2000-01-01 00:00:00.000000000 -0000
7160+++ b/gopls/internal/lsp/analysis/fillreturns/testdata/src/a/typeparams/a.go.golden	1970-01-01 00:00:00.000000000 +0000
7161@@ -1,5 +0,0 @@
7162-package fillreturns
7163-
7164-func hello[T any]() int {
7165-	return
7166-}
7167diff -urN a/gopls/internal/lsp/analysis/fillstruct/fillstruct.go b/gopls/internal/lsp/analysis/fillstruct/fillstruct.go
7168--- a/gopls/internal/lsp/analysis/fillstruct/fillstruct.go	2000-01-01 00:00:00.000000000 -0000
7169+++ b/gopls/internal/lsp/analysis/fillstruct/fillstruct.go	1970-01-01 00:00:00.000000000 +0000
7170@@ -1,506 +0,0 @@
7171-// Copyright 2020 The Go Authors. All rights reserved.
7172-// Use of this source code is governed by a BSD-style
7173-// license that can be found in the LICENSE file.
7174-
7175-// Package fillstruct defines an Analyzer that automatically
7176-// fills in a struct declaration with zero value elements for each field.
7177-//
7178-// The analyzer's diagnostic is merely a prompt.
7179-// The actual fix is created by a separate direct call from gopls to
7180-// the SuggestedFixes function.
7181-// Tests of Analyzer.Run can be found in ./testdata/src.
7182-// Tests of the SuggestedFixes logic live in ../../testdata/fillstruct.
7183-package fillstruct
7184-
7185-import (
7186-	"bytes"
7187-	"fmt"
7188-	"go/ast"
7189-	"go/format"
7190-	"go/token"
7191-	"go/types"
7192-	"strings"
7193-	"unicode"
7194-
7195-	"golang.org/x/tools/go/analysis"
7196-	"golang.org/x/tools/go/analysis/passes/inspect"
7197-	"golang.org/x/tools/go/ast/astutil"
7198-	"golang.org/x/tools/go/ast/inspector"
7199-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
7200-	"golang.org/x/tools/internal/analysisinternal"
7201-	"golang.org/x/tools/internal/fuzzy"
7202-	"golang.org/x/tools/internal/typeparams"
7203-)
7204-
7205-const Doc = `note incomplete struct initializations
7206-
7207-This analyzer provides diagnostics for any struct literals that do not have
7208-any fields initialized. Because the suggested fix for this analysis is
7209-expensive to compute, callers should compute it separately, using the
7210-SuggestedFix function below.
7211-`
7212-
7213-var Analyzer = &analysis.Analyzer{
7214-	Name:             "fillstruct",
7215-	Doc:              Doc,
7216-	Requires:         []*analysis.Analyzer{inspect.Analyzer},
7217-	Run:              run,
7218-	RunDespiteErrors: true,
7219-}
7220-
7221-func run(pass *analysis.Pass) (interface{}, error) {
7222-	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
7223-	nodeFilter := []ast.Node{(*ast.CompositeLit)(nil)}
7224-	inspect.Preorder(nodeFilter, func(n ast.Node) {
7225-		expr := n.(*ast.CompositeLit)
7226-
7227-		// Find enclosing file.
7228-		// TODO(adonovan): use inspect.WithStack?
7229-		var file *ast.File
7230-		for _, f := range pass.Files {
7231-			if f.Pos() <= expr.Pos() && expr.Pos() <= f.End() {
7232-				file = f
7233-				break
7234-			}
7235-		}
7236-		if file == nil {
7237-			return
7238-		}
7239-
7240-		typ := pass.TypesInfo.TypeOf(expr)
7241-		if typ == nil {
7242-			return
7243-		}
7244-
7245-		// Find reference to the type declaration of the struct being initialized.
7246-		typ = deref(typ)
7247-		tStruct, ok := typ.Underlying().(*types.Struct)
7248-		if !ok {
7249-			return
7250-		}
7251-		// Inv: typ is the possibly-named struct type.
7252-
7253-		fieldCount := tStruct.NumFields()
7254-
7255-		// Skip any struct that is already populated or that has no fields.
7256-		if fieldCount == 0 || fieldCount == len(expr.Elts) {
7257-			return
7258-		}
7259-
7260-		// Are any fields in need of filling?
7261-		var fillableFields []string
7262-		for i := 0; i < fieldCount; i++ {
7263-			field := tStruct.Field(i)
7264-			// Ignore fields that are not accessible in the current package.
7265-			if field.Pkg() != nil && field.Pkg() != pass.Pkg && !field.Exported() {
7266-				continue
7267-			}
7268-			fillableFields = append(fillableFields, fmt.Sprintf("%s: %s", field.Name(), field.Type().String()))
7269-		}
7270-		if len(fillableFields) == 0 {
7271-			return
7272-		}
7273-
7274-		// Derive a name for the struct type.
7275-		var name string
7276-		if typ != tStruct {
7277-			// named struct type (e.g. pkg.S[T])
7278-			name = types.TypeString(typ, types.RelativeTo(pass.Pkg))
7279-		} else {
7280-			// anonymous struct type
7281-			totalFields := len(fillableFields)
7282-			const maxLen = 20
7283-			// Find the index to cut off printing of fields.
7284-			var i, fieldLen int
7285-			for i = range fillableFields {
7286-				if fieldLen > maxLen {
7287-					break
7288-				}
7289-				fieldLen += len(fillableFields[i])
7290-			}
7291-			fillableFields = fillableFields[:i]
7292-			if i < totalFields {
7293-				fillableFields = append(fillableFields, "...")
7294-			}
7295-			name = fmt.Sprintf("anonymous struct { %s }", strings.Join(fillableFields, ", "))
7296-		}
7297-		pass.Report(analysis.Diagnostic{
7298-			Message: fmt.Sprintf("Fill %s", name),
7299-			Pos:     expr.Pos(),
7300-			End:     expr.End(),
7301-		})
7302-	})
7303-	return nil, nil
7304-}
7305-
7306-// SuggestedFix computes the suggested fix for the kinds of
7307-// diagnostics produced by the Analyzer above.
7308-func SuggestedFix(fset *token.FileSet, start, end token.Pos, content []byte, file *ast.File, pkg *types.Package, info *types.Info) (*analysis.SuggestedFix, error) {
7309-	if info == nil {
7310-		return nil, fmt.Errorf("nil types.Info")
7311-	}
7312-
7313-	pos := start // don't use the end
7314-
7315-	// TODO(rstambler): Using ast.Inspect would probably be more efficient than
7316-	// calling PathEnclosingInterval. Switch this approach.
7317-	path, _ := astutil.PathEnclosingInterval(file, pos, pos)
7318-	if len(path) == 0 {
7319-		return nil, fmt.Errorf("no enclosing ast.Node")
7320-	}
7321-	var expr *ast.CompositeLit
7322-	for _, n := range path {
7323-		if node, ok := n.(*ast.CompositeLit); ok {
7324-			expr = node
7325-			break
7326-		}
7327-	}
7328-
7329-	typ := info.TypeOf(expr)
7330-	if typ == nil {
7331-		return nil, fmt.Errorf("no composite literal")
7332-	}
7333-
7334-	// Find reference to the type declaration of the struct being initialized.
7335-	typ = deref(typ)
7336-	tStruct, ok := typ.Underlying().(*types.Struct)
7337-	if !ok {
7338-		return nil, fmt.Errorf("%s is not a (pointer to) struct type",
7339-			types.TypeString(typ, types.RelativeTo(pkg)))
7340-	}
7341-	// Inv: typ is the the possibly-named struct type.
7342-
7343-	fieldCount := tStruct.NumFields()
7344-
7345-	// Check which types have already been filled in. (we only want to fill in
7346-	// the unfilled types, or else we'll blat user-supplied details)
7347-	prefilledFields := map[string]ast.Expr{}
7348-	for _, e := range expr.Elts {
7349-		if kv, ok := e.(*ast.KeyValueExpr); ok {
7350-			if key, ok := kv.Key.(*ast.Ident); ok {
7351-				prefilledFields[key.Name] = kv.Value
7352-			}
7353-		}
7354-	}
7355-
7356-	// Use a new fileset to build up a token.File for the new composite
7357-	// literal. We need one line for foo{, one line for }, and one line for
7358-	// each field we're going to set. format.Node only cares about line
7359-	// numbers, so we don't need to set columns, and each line can be
7360-	// 1 byte long.
7361-	// TODO(adonovan): why is this necessary? The position information
7362-	// is going to be wrong for the existing trees in prefilledFields.
7363-	// Can't the formatter just do its best with an empty fileset?
7364-	fakeFset := token.NewFileSet()
7365-	tok := fakeFset.AddFile("", -1, fieldCount+2)
7366-
7367-	line := 2 // account for 1-based lines and the left brace
7368-	var fieldTyps []types.Type
7369-	for i := 0; i < fieldCount; i++ {
7370-		field := tStruct.Field(i)
7371-		// Ignore fields that are not accessible in the current package.
7372-		if field.Pkg() != nil && field.Pkg() != pkg && !field.Exported() {
7373-			fieldTyps = append(fieldTyps, nil)
7374-			continue
7375-		}
7376-		fieldTyps = append(fieldTyps, field.Type())
7377-	}
7378-	matches := analysisinternal.MatchingIdents(fieldTyps, file, start, info, pkg)
7379-	var elts []ast.Expr
7380-	for i, fieldTyp := range fieldTyps {
7381-		if fieldTyp == nil {
7382-			continue // TODO(adonovan): is this reachable?
7383-		}
7384-		fieldName := tStruct.Field(i).Name()
7385-
7386-		tok.AddLine(line - 1) // add 1 byte per line
7387-		if line > tok.LineCount() {
7388-			panic(fmt.Sprintf("invalid line number %v (of %v) for fillstruct", line, tok.LineCount()))
7389-		}
7390-		pos := tok.LineStart(line)
7391-
7392-		kv := &ast.KeyValueExpr{
7393-			Key: &ast.Ident{
7394-				NamePos: pos,
7395-				Name:    fieldName,
7396-			},
7397-			Colon: pos,
7398-		}
7399-		if expr, ok := prefilledFields[fieldName]; ok {
7400-			kv.Value = expr
7401-		} else {
7402-			names, ok := matches[fieldTyp]
7403-			if !ok {
7404-				return nil, fmt.Errorf("invalid struct field type: %v", fieldTyp)
7405-			}
7406-
7407-			// Find the name most similar to the field name.
7408-			// If no name matches the pattern, generate a zero value.
7409-			// NOTE: We currently match on the name of the field key rather than the field type.
7410-			if best := fuzzy.BestMatch(fieldName, names); best != "" {
7411-				kv.Value = ast.NewIdent(best)
7412-			} else if v := populateValue(file, pkg, fieldTyp); v != nil {
7413-				kv.Value = v
7414-			} else {
7415-				return nil, nil
7416-			}
7417-		}
7418-		elts = append(elts, kv)
7419-		line++
7420-	}
7421-
7422-	// If all of the struct's fields are unexported, we have nothing to do.
7423-	if len(elts) == 0 {
7424-		return nil, fmt.Errorf("no elements to fill")
7425-	}
7426-
7427-	// Add the final line for the right brace. Offset is the number of
7428-	// bytes already added plus 1.
7429-	tok.AddLine(len(elts) + 1)
7430-	line = len(elts) + 2
7431-	if line > tok.LineCount() {
7432-		panic(fmt.Sprintf("invalid line number %v (of %v) for fillstruct", line, tok.LineCount()))
7433-	}
7434-
7435-	cl := &ast.CompositeLit{
7436-		Type:   expr.Type,
7437-		Lbrace: tok.LineStart(1),
7438-		Elts:   elts,
7439-		Rbrace: tok.LineStart(line),
7440-	}
7441-
7442-	// Find the line on which the composite literal is declared.
7443-	split := bytes.Split(content, []byte("\n"))
7444-	lineNumber := safetoken.StartPosition(fset, expr.Lbrace).Line
7445-	firstLine := split[lineNumber-1] // lines are 1-indexed
7446-
7447-	// Trim the whitespace from the left of the line, and use the index
7448-	// to get the amount of whitespace on the left.
7449-	trimmed := bytes.TrimLeftFunc(firstLine, unicode.IsSpace)
7450-	index := bytes.Index(firstLine, trimmed)
7451-	whitespace := firstLine[:index]
7452-
7453-	// First pass through the formatter: turn the expr into a string.
7454-	var formatBuf bytes.Buffer
7455-	if err := format.Node(&formatBuf, fakeFset, cl); err != nil {
7456-		return nil, fmt.Errorf("failed to run first format on:\n%s\ngot err: %v", cl.Type, err)
7457-	}
7458-	sug := indent(formatBuf.Bytes(), whitespace)
7459-
7460-	if len(prefilledFields) > 0 {
7461-		// Attempt a second pass through the formatter to line up columns.
7462-		sourced, err := format.Source(sug)
7463-		if err == nil {
7464-			sug = indent(sourced, whitespace)
7465-		}
7466-	}
7467-
7468-	return &analysis.SuggestedFix{
7469-		TextEdits: []analysis.TextEdit{
7470-			{
7471-				Pos:     expr.Pos(),
7472-				End:     expr.End(),
7473-				NewText: sug,
7474-			},
7475-		},
7476-	}, nil
7477-}
7478-
7479-// indent works line by line through str, indenting (prefixing) each line with
7480-// ind.
7481-func indent(str, ind []byte) []byte {
7482-	split := bytes.Split(str, []byte("\n"))
7483-	newText := bytes.NewBuffer(nil)
7484-	for i, s := range split {
7485-		if len(s) == 0 {
7486-			continue
7487-		}
7488-		// Don't add the extra indentation to the first line.
7489-		if i != 0 {
7490-			newText.Write(ind)
7491-		}
7492-		newText.Write(s)
7493-		if i < len(split)-1 {
7494-			newText.WriteByte('\n')
7495-		}
7496-	}
7497-	return newText.Bytes()
7498-}
7499-
7500-// populateValue constructs an expression to fill the value of a struct field.
7501-//
7502-// When the type of a struct field is a basic literal or interface, we return
7503-// default values. For other types, such as maps, slices, and channels, we create
7504-// empty expressions such as []T{} or make(chan T) rather than using default values.
7505-//
7506-// The reasoning here is that users will call fillstruct with the intention of
7507-// initializing the struct, in which case setting these fields to nil has no effect.
7508-func populateValue(f *ast.File, pkg *types.Package, typ types.Type) ast.Expr {
7509-	switch u := typ.Underlying().(type) {
7510-	case *types.Basic:
7511-		switch {
7512-		case u.Info()&types.IsNumeric != 0:
7513-			return &ast.BasicLit{Kind: token.INT, Value: "0"}
7514-		case u.Info()&types.IsBoolean != 0:
7515-			return &ast.Ident{Name: "false"}
7516-		case u.Info()&types.IsString != 0:
7517-			return &ast.BasicLit{Kind: token.STRING, Value: `""`}
7518-		case u.Kind() == types.UnsafePointer:
7519-			return ast.NewIdent("nil")
7520-		default:
7521-			panic("unknown basic type")
7522-		}
7523-
7524-	case *types.Map:
7525-		k := analysisinternal.TypeExpr(f, pkg, u.Key())
7526-		v := analysisinternal.TypeExpr(f, pkg, u.Elem())
7527-		if k == nil || v == nil {
7528-			return nil
7529-		}
7530-		return &ast.CompositeLit{
7531-			Type: &ast.MapType{
7532-				Key:   k,
7533-				Value: v,
7534-			},
7535-		}
7536-	case *types.Slice:
7537-		s := analysisinternal.TypeExpr(f, pkg, u.Elem())
7538-		if s == nil {
7539-			return nil
7540-		}
7541-		return &ast.CompositeLit{
7542-			Type: &ast.ArrayType{
7543-				Elt: s,
7544-			},
7545-		}
7546-
7547-	case *types.Array:
7548-		a := analysisinternal.TypeExpr(f, pkg, u.Elem())
7549-		if a == nil {
7550-			return nil
7551-		}
7552-		return &ast.CompositeLit{
7553-			Type: &ast.ArrayType{
7554-				Elt: a,
7555-				Len: &ast.BasicLit{
7556-					Kind: token.INT, Value: fmt.Sprintf("%v", u.Len()),
7557-				},
7558-			},
7559-		}
7560-
7561-	case *types.Chan:
7562-		v := analysisinternal.TypeExpr(f, pkg, u.Elem())
7563-		if v == nil {
7564-			return nil
7565-		}
7566-		dir := ast.ChanDir(u.Dir())
7567-		if u.Dir() == types.SendRecv {
7568-			dir = ast.SEND | ast.RECV
7569-		}
7570-		return &ast.CallExpr{
7571-			Fun: ast.NewIdent("make"),
7572-			Args: []ast.Expr{
7573-				&ast.ChanType{
7574-					Dir:   dir,
7575-					Value: v,
7576-				},
7577-			},
7578-		}
7579-
7580-	case *types.Struct:
7581-		s := analysisinternal.TypeExpr(f, pkg, typ)
7582-		if s == nil {
7583-			return nil
7584-		}
7585-		return &ast.CompositeLit{
7586-			Type: s,
7587-		}
7588-
7589-	case *types.Signature:
7590-		var params []*ast.Field
7591-		for i := 0; i < u.Params().Len(); i++ {
7592-			p := analysisinternal.TypeExpr(f, pkg, u.Params().At(i).Type())
7593-			if p == nil {
7594-				return nil
7595-			}
7596-			params = append(params, &ast.Field{
7597-				Type: p,
7598-				Names: []*ast.Ident{
7599-					{
7600-						Name: u.Params().At(i).Name(),
7601-					},
7602-				},
7603-			})
7604-		}
7605-		var returns []*ast.Field
7606-		for i := 0; i < u.Results().Len(); i++ {
7607-			r := analysisinternal.TypeExpr(f, pkg, u.Results().At(i).Type())
7608-			if r == nil {
7609-				return nil
7610-			}
7611-			returns = append(returns, &ast.Field{
7612-				Type: r,
7613-			})
7614-		}
7615-		return &ast.FuncLit{
7616-			Type: &ast.FuncType{
7617-				Params: &ast.FieldList{
7618-					List: params,
7619-				},
7620-				Results: &ast.FieldList{
7621-					List: returns,
7622-				},
7623-			},
7624-			Body: &ast.BlockStmt{},
7625-		}
7626-
7627-	case *types.Pointer:
7628-		switch u.Elem().(type) {
7629-		case *types.Basic:
7630-			return &ast.CallExpr{
7631-				Fun: &ast.Ident{
7632-					Name: "new",
7633-				},
7634-				Args: []ast.Expr{
7635-					&ast.Ident{
7636-						Name: u.Elem().String(),
7637-					},
7638-				},
7639-			}
7640-		default:
7641-			return &ast.UnaryExpr{
7642-				Op: token.AND,
7643-				X:  populateValue(f, pkg, u.Elem()),
7644-			}
7645-		}
7646-
7647-	case *types.Interface:
7648-		if param, ok := typ.(*typeparams.TypeParam); ok {
7649-			// *new(T) is the zero value of a type parameter T.
7650-			// TODO(adonovan): one could give a more specific zero
7651-			// value if the type has a core type that is, say,
7652-			// always a number or a pointer. See go/ssa for details.
7653-			return &ast.StarExpr{
7654-				X: &ast.CallExpr{
7655-					Fun: ast.NewIdent("new"),
7656-					Args: []ast.Expr{
7657-						ast.NewIdent(param.Obj().Name()),
7658-					},
7659-				},
7660-			}
7661-		}
7662-
7663-		return ast.NewIdent("nil")
7664-	}
7665-	return nil
7666-}
7667-
7668-func deref(t types.Type) types.Type {
7669-	for {
7670-		ptr, ok := t.Underlying().(*types.Pointer)
7671-		if !ok {
7672-			return t
7673-		}
7674-		t = ptr.Elem()
7675-	}
7676-}
7677diff -urN a/gopls/internal/lsp/analysis/fillstruct/fillstruct_test.go b/gopls/internal/lsp/analysis/fillstruct/fillstruct_test.go
7678--- a/gopls/internal/lsp/analysis/fillstruct/fillstruct_test.go	2000-01-01 00:00:00.000000000 -0000
7679+++ b/gopls/internal/lsp/analysis/fillstruct/fillstruct_test.go	1970-01-01 00:00:00.000000000 +0000
7680@@ -1,22 +0,0 @@
7681-// Copyright 2020 The Go Authors. All rights reserved.
7682-// Use of this source code is governed by a BSD-style
7683-// license that can be found in the LICENSE file.
7684-
7685-package fillstruct_test
7686-
7687-import (
7688-	"testing"
7689-
7690-	"golang.org/x/tools/go/analysis/analysistest"
7691-	"golang.org/x/tools/gopls/internal/lsp/analysis/fillstruct"
7692-	"golang.org/x/tools/internal/typeparams"
7693-)
7694-
7695-func Test(t *testing.T) {
7696-	testdata := analysistest.TestData()
7697-	tests := []string{"a"}
7698-	if typeparams.Enabled {
7699-		tests = append(tests, "typeparams")
7700-	}
7701-	analysistest.Run(t, testdata, fillstruct.Analyzer, tests...)
7702-}
7703diff -urN a/gopls/internal/lsp/analysis/fillstruct/testdata/src/a/a.go b/gopls/internal/lsp/analysis/fillstruct/testdata/src/a/a.go
7704--- a/gopls/internal/lsp/analysis/fillstruct/testdata/src/a/a.go	2000-01-01 00:00:00.000000000 -0000
7705+++ b/gopls/internal/lsp/analysis/fillstruct/testdata/src/a/a.go	1970-01-01 00:00:00.000000000 +0000
7706@@ -1,113 +0,0 @@
7707-// Copyright 2020 The Go Authors. All rights reserved.
7708-// Use of this source code is governed by a BSD-style
7709-// license that can be found in the LICENSE file.
7710-
7711-package fillstruct
7712-
7713-import (
7714-	data "b"
7715-	"go/ast"
7716-	"go/token"
7717-	"unsafe"
7718-)
7719-
7720-type emptyStruct struct{}
7721-
7722-var _ = emptyStruct{}
7723-
7724-type basicStruct struct {
7725-	foo int
7726-}
7727-
7728-var _ = basicStruct{} // want `Fill basicStruct`
7729-
7730-type twoArgStruct struct {
7731-	foo int
7732-	bar string
7733-}
7734-
7735-var _ = twoArgStruct{} // want `Fill twoArgStruct`
7736-
7737-var _ = twoArgStruct{ // want `Fill twoArgStruct`
7738-	bar: "bar",
7739-}
7740-
7741-type nestedStruct struct {
7742-	bar   string
7743-	basic basicStruct
7744-}
7745-
7746-var _ = nestedStruct{} // want `Fill nestedStruct`
7747-
7748-var _ = data.B{} // want `Fill b.B`
7749-
7750-type typedStruct struct {
7751-	m  map[string]int
7752-	s  []int
7753-	c  chan int
7754-	c1 <-chan int
7755-	a  [2]string
7756-}
7757-
7758-var _ = typedStruct{} // want `Fill typedStruct`
7759-
7760-type funStruct struct {
7761-	fn func(i int) int
7762-}
7763-
7764-var _ = funStruct{} // want `Fill funStruct`
7765-
7766-type funStructComplex struct {
7767-	fn func(i int, s string) (string, int)
7768-}
7769-
7770-var _ = funStructComplex{} // want `Fill funStructComplex`
7771-
7772-type funStructEmpty struct {
7773-	fn func()
7774-}
7775-
7776-var _ = funStructEmpty{} // want `Fill funStructEmpty`
7777-
7778-type Foo struct {
7779-	A int
7780-}
7781-
7782-type Bar struct {
7783-	X *Foo
7784-	Y *Foo
7785-}
7786-
7787-var _ = Bar{} // want `Fill Bar`
7788-
7789-type importedStruct struct {
7790-	m  map[*ast.CompositeLit]ast.Field
7791-	s  []ast.BadExpr
7792-	a  [3]token.Token
7793-	c  chan ast.EmptyStmt
7794-	fn func(ast_decl ast.DeclStmt) ast.Ellipsis
7795-	st ast.CompositeLit
7796-}
7797-
7798-var _ = importedStruct{} // want `Fill importedStruct`
7799-
7800-type pointerBuiltinStruct struct {
7801-	b *bool
7802-	s *string
7803-	i *int
7804-}
7805-
7806-var _ = pointerBuiltinStruct{} // want `Fill pointerBuiltinStruct`
7807-
7808-var _ = []ast.BasicLit{
7809-	{}, // want `Fill go/ast.BasicLit`
7810-}
7811-
7812-var _ = []ast.BasicLit{{}, // want "go/ast.BasicLit"
7813-}
7814-
7815-type unsafeStruct struct {
7816-	foo unsafe.Pointer
7817-}
7818-
7819-var _ = unsafeStruct{} // want `Fill unsafeStruct`
7820diff -urN a/gopls/internal/lsp/analysis/fillstruct/testdata/src/b/b.go b/gopls/internal/lsp/analysis/fillstruct/testdata/src/b/b.go
7821--- a/gopls/internal/lsp/analysis/fillstruct/testdata/src/b/b.go	2000-01-01 00:00:00.000000000 -0000
7822+++ b/gopls/internal/lsp/analysis/fillstruct/testdata/src/b/b.go	1970-01-01 00:00:00.000000000 +0000
7823@@ -1,6 +0,0 @@
7824-package fillstruct
7825-
7826-type B struct {
7827-	ExportedInt   int
7828-	unexportedInt int
7829-}
7830diff -urN a/gopls/internal/lsp/analysis/fillstruct/testdata/src/typeparams/typeparams.go b/gopls/internal/lsp/analysis/fillstruct/testdata/src/typeparams/typeparams.go
7831--- a/gopls/internal/lsp/analysis/fillstruct/testdata/src/typeparams/typeparams.go	2000-01-01 00:00:00.000000000 -0000
7832+++ b/gopls/internal/lsp/analysis/fillstruct/testdata/src/typeparams/typeparams.go	1970-01-01 00:00:00.000000000 +0000
7833@@ -1,50 +0,0 @@
7834-// Copyright 2020 The Go Authors. All rights reserved.
7835-// Use of this source code is governed by a BSD-style
7836-// license that can be found in the LICENSE file.
7837-
7838-package fillstruct
7839-
7840-type emptyStruct[A any] struct{}
7841-
7842-var _ = emptyStruct[int]{}
7843-
7844-type basicStruct[T any] struct {
7845-	foo T
7846-}
7847-
7848-var _ = basicStruct[int]{} // want `Fill basicStruct\[int\]`
7849-
7850-type twoArgStruct[F, B any] struct {
7851-	foo F
7852-	bar B
7853-}
7854-
7855-var _ = twoArgStruct[string, int]{} // want `Fill twoArgStruct\[string, int\]`
7856-
7857-var _ = twoArgStruct[int, string]{ // want `Fill twoArgStruct\[int, string\]`
7858-	bar: "bar",
7859-}
7860-
7861-type nestedStruct struct {
7862-	bar   string
7863-	basic basicStruct[int]
7864-}
7865-
7866-var _ = nestedStruct{} // want "Fill nestedStruct"
7867-
7868-func _[T any]() {
7869-	type S struct{ t T }
7870-	x := S{} // want "Fill S"
7871-	_ = x
7872-}
7873-
7874-func Test() {
7875-	var tests = []struct {
7876-		a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p string
7877-	}{
7878-		{}, // want "Fill anonymous struct { a: string, b: string, c: string, ... }"
7879-	}
7880-	for _, test := range tests {
7881-		_ = test
7882-	}
7883-}
7884diff -urN a/gopls/internal/lsp/analysis/infertypeargs/infertypeargs.go b/gopls/internal/lsp/analysis/infertypeargs/infertypeargs.go
7885--- a/gopls/internal/lsp/analysis/infertypeargs/infertypeargs.go	2000-01-01 00:00:00.000000000 -0000
7886+++ b/gopls/internal/lsp/analysis/infertypeargs/infertypeargs.go	1970-01-01 00:00:00.000000000 +0000
7887@@ -1,31 +0,0 @@
7888-// Copyright 2021 The Go Authors. All rights reserved.
7889-// Use of this source code is governed by a BSD-style
7890-// license that can be found in the LICENSE file.
7891-
7892-// Package infertypeargs defines an analyzer that checks for explicit function
7893-// arguments that could be inferred.
7894-package infertypeargs
7895-
7896-import (
7897-	"golang.org/x/tools/go/analysis"
7898-	"golang.org/x/tools/go/analysis/passes/inspect"
7899-)
7900-
7901-const Doc = `check for unnecessary type arguments in call expressions
7902-
7903-Explicit type arguments may be omitted from call expressions if they can be
7904-inferred from function arguments, or from other type arguments:
7905-
7906-	func f[T any](T) {}
7907-
7908-	func _() {
7909-		f[string]("foo") // string could be inferred
7910-	}
7911-`
7912-
7913-var Analyzer = &analysis.Analyzer{
7914-	Name:     "infertypeargs",
7915-	Doc:      Doc,
7916-	Requires: []*analysis.Analyzer{inspect.Analyzer},
7917-	Run:      run,
7918-}
7919diff -urN a/gopls/internal/lsp/analysis/infertypeargs/infertypeargs_test.go b/gopls/internal/lsp/analysis/infertypeargs/infertypeargs_test.go
7920--- a/gopls/internal/lsp/analysis/infertypeargs/infertypeargs_test.go	2000-01-01 00:00:00.000000000 -0000
7921+++ b/gopls/internal/lsp/analysis/infertypeargs/infertypeargs_test.go	1970-01-01 00:00:00.000000000 +0000
7922@@ -1,21 +0,0 @@
7923-// Copyright 2021 The Go Authors. All rights reserved.
7924-// Use of this source code is governed by a BSD-style
7925-// license that can be found in the LICENSE file.
7926-
7927-package infertypeargs_test
7928-
7929-import (
7930-	"testing"
7931-
7932-	"golang.org/x/tools/go/analysis/analysistest"
7933-	"golang.org/x/tools/gopls/internal/lsp/analysis/infertypeargs"
7934-	"golang.org/x/tools/internal/typeparams"
7935-)
7936-
7937-func Test(t *testing.T) {
7938-	if !typeparams.Enabled {
7939-		t.Skip("type params are not enabled")
7940-	}
7941-	testdata := analysistest.TestData()
7942-	analysistest.RunWithSuggestedFixes(t, testdata, infertypeargs.Analyzer, "a")
7943-}
7944diff -urN a/gopls/internal/lsp/analysis/infertypeargs/run_go117.go b/gopls/internal/lsp/analysis/infertypeargs/run_go117.go
7945--- a/gopls/internal/lsp/analysis/infertypeargs/run_go117.go	2000-01-01 00:00:00.000000000 -0000
7946+++ b/gopls/internal/lsp/analysis/infertypeargs/run_go117.go	1970-01-01 00:00:00.000000000 +0000
7947@@ -1,16 +0,0 @@
7948-// Copyright 2021 The Go Authors. All rights reserved.
7949-// Use of this source code is governed by a BSD-style
7950-// license that can be found in the LICENSE file.
7951-
7952-//go:build !go1.18
7953-// +build !go1.18
7954-
7955-package infertypeargs
7956-
7957-import "golang.org/x/tools/go/analysis"
7958-
7959-// This analyzer only relates to go1.18+, and uses the types.CheckExpr API that
7960-// was added in Go 1.13.
7961-func run(pass *analysis.Pass) (interface{}, error) {
7962-	return nil, nil
7963-}
7964diff -urN a/gopls/internal/lsp/analysis/infertypeargs/run_go118.go b/gopls/internal/lsp/analysis/infertypeargs/run_go118.go
7965--- a/gopls/internal/lsp/analysis/infertypeargs/run_go118.go	2000-01-01 00:00:00.000000000 -0000
7966+++ b/gopls/internal/lsp/analysis/infertypeargs/run_go118.go	1970-01-01 00:00:00.000000000 +0000
7967@@ -1,111 +0,0 @@
7968-// Copyright 2021 The Go Authors. All rights reserved.
7969-// Use of this source code is governed by a BSD-style
7970-// license that can be found in the LICENSE file.
7971-
7972-//go:build go1.18
7973-// +build go1.18
7974-
7975-package infertypeargs
7976-
7977-import (
7978-	"go/ast"
7979-	"go/token"
7980-	"go/types"
7981-
7982-	"golang.org/x/tools/go/analysis"
7983-	"golang.org/x/tools/go/analysis/passes/inspect"
7984-	"golang.org/x/tools/go/ast/inspector"
7985-	"golang.org/x/tools/internal/typeparams"
7986-)
7987-
7988-func run(pass *analysis.Pass) (interface{}, error) {
7989-	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
7990-
7991-	nodeFilter := []ast.Node{
7992-		(*ast.CallExpr)(nil),
7993-	}
7994-
7995-	inspect.Preorder(nodeFilter, func(node ast.Node) {
7996-		call := node.(*ast.CallExpr)
7997-		x, lbrack, indices, rbrack := typeparams.UnpackIndexExpr(call.Fun)
7998-		ident := calledIdent(x)
7999-		if ident == nil || len(indices) == 0 {
8000-			return // no explicit args, nothing to do
8001-		}
8002-
8003-		// Confirm that instantiation actually occurred at this ident.
8004-		idata, ok := typeparams.GetInstances(pass.TypesInfo)[ident]
8005-		if !ok {
8006-			return // something went wrong, but fail open
8007-		}
8008-		instance := idata.Type
8009-
8010-		// Start removing argument expressions from the right, and check if we can
8011-		// still infer the call expression.
8012-		required := len(indices) // number of type expressions that are required
8013-		for i := len(indices) - 1; i >= 0; i-- {
8014-			var fun ast.Expr
8015-			if i == 0 {
8016-				// No longer an index expression: just use the parameterized operand.
8017-				fun = x
8018-			} else {
8019-				fun = typeparams.PackIndexExpr(x, lbrack, indices[:i], indices[i-1].End())
8020-			}
8021-			newCall := &ast.CallExpr{
8022-				Fun:      fun,
8023-				Lparen:   call.Lparen,
8024-				Args:     call.Args,
8025-				Ellipsis: call.Ellipsis,
8026-				Rparen:   call.Rparen,
8027-			}
8028-			info := new(types.Info)
8029-			typeparams.InitInstanceInfo(info)
8030-			if err := types.CheckExpr(pass.Fset, pass.Pkg, call.Pos(), newCall, info); err != nil {
8031-				// Most likely inference failed.
8032-				break
8033-			}
8034-			newIData := typeparams.GetInstances(info)[ident]
8035-			newInstance := newIData.Type
8036-			if !types.Identical(instance, newInstance) {
8037-				// The inferred result type does not match the original result type, so
8038-				// this simplification is not valid.
8039-				break
8040-			}
8041-			required = i
8042-		}
8043-		if required < len(indices) {
8044-			var start, end token.Pos
8045-			var edit analysis.TextEdit
8046-			if required == 0 {
8047-				start, end = lbrack, rbrack+1 // erase the entire index
8048-				edit = analysis.TextEdit{Pos: start, End: end}
8049-			} else {
8050-				start = indices[required].Pos()
8051-				end = rbrack
8052-				//  erase from end of last arg to include last comma & white-spaces
8053-				edit = analysis.TextEdit{Pos: indices[required-1].End(), End: end}
8054-			}
8055-			pass.Report(analysis.Diagnostic{
8056-				Pos:     start,
8057-				End:     end,
8058-				Message: "unnecessary type arguments",
8059-				SuggestedFixes: []analysis.SuggestedFix{{
8060-					Message:   "simplify type arguments",
8061-					TextEdits: []analysis.TextEdit{edit},
8062-				}},
8063-			})
8064-		}
8065-	})
8066-
8067-	return nil, nil
8068-}
8069-
8070-func calledIdent(x ast.Expr) *ast.Ident {
8071-	switch x := x.(type) {
8072-	case *ast.Ident:
8073-		return x
8074-	case *ast.SelectorExpr:
8075-		return x.Sel
8076-	}
8077-	return nil
8078-}
8079diff -urN a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/basic.go b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/basic.go
8080--- a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/basic.go	2000-01-01 00:00:00.000000000 -0000
8081+++ b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/basic.go	1970-01-01 00:00:00.000000000 +0000
8082@@ -1,20 +0,0 @@
8083-// Copyright 2021 The Go Authors. All rights reserved.
8084-// Use of this source code is governed by a BSD-style
8085-// license that can be found in the LICENSE file.
8086-
8087-// This file contains tests for the infertyepargs checker.
8088-
8089-package a
8090-
8091-func f[T any](T) {}
8092-
8093-func g[T any]() T { var x T; return x }
8094-
8095-func h[P interface{ ~*T }, T any]() {}
8096-
8097-func _() {
8098-	f[string]("hello") // want "unnecessary type arguments"
8099-	f[int](2)          // want "unnecessary type arguments"
8100-	_ = g[int]()
8101-	h[*int, int]() // want "unnecessary type arguments"
8102-}
8103diff -urN a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/basic.go.golden b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/basic.go.golden
8104--- a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/basic.go.golden	2000-01-01 00:00:00.000000000 -0000
8105+++ b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/basic.go.golden	1970-01-01 00:00:00.000000000 +0000
8106@@ -1,20 +0,0 @@
8107-// Copyright 2021 The Go Authors. All rights reserved.
8108-// Use of this source code is governed by a BSD-style
8109-// license that can be found in the LICENSE file.
8110-
8111-// This file contains tests for the infertyepargs checker.
8112-
8113-package a
8114-
8115-func f[T any](T) {}
8116-
8117-func g[T any]() T { var x T; return x }
8118-
8119-func h[P interface{ ~*T }, T any]() {}
8120-
8121-func _() {
8122-	f("hello") // want "unnecessary type arguments"
8123-	f(2)       // want "unnecessary type arguments"
8124-	_ = g[int]()
8125-	h[*int]() // want "unnecessary type arguments"
8126-}
8127diff -urN a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/imported/imported.go b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/imported/imported.go
8128--- a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/imported/imported.go	2000-01-01 00:00:00.000000000 -0000
8129+++ b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/imported/imported.go	1970-01-01 00:00:00.000000000 +0000
8130@@ -1,7 +0,0 @@
8131-// Copyright 2021 The Go Authors. All rights reserved.
8132-// Use of this source code is governed by a BSD-style
8133-// license that can be found in the LICENSE file.
8134-
8135-package imported
8136-
8137-func F[T any](T) {}
8138diff -urN a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/imported.go b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/imported.go
8139--- a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/imported.go	2000-01-01 00:00:00.000000000 -0000
8140+++ b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/imported.go	1970-01-01 00:00:00.000000000 +0000
8141@@ -1,12 +0,0 @@
8142-// Copyright 2021 The Go Authors. All rights reserved.
8143-// Use of this source code is governed by a BSD-style
8144-// license that can be found in the LICENSE file.
8145-
8146-package a
8147-
8148-import "a/imported"
8149-
8150-func _() {
8151-	var x int
8152-	imported.F[int](x) // want "unnecessary type arguments"
8153-}
8154diff -urN a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/imported.go.golden b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/imported.go.golden
8155--- a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/imported.go.golden	2000-01-01 00:00:00.000000000 -0000
8156+++ b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/imported.go.golden	1970-01-01 00:00:00.000000000 +0000
8157@@ -1,12 +0,0 @@
8158-// Copyright 2021 The Go Authors. All rights reserved.
8159-// Use of this source code is governed by a BSD-style
8160-// license that can be found in the LICENSE file.
8161-
8162-package a
8163-
8164-import "a/imported"
8165-
8166-func _() {
8167-	var x int
8168-	imported.F(x) // want "unnecessary type arguments"
8169-}
8170diff -urN a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/notypechange.go b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/notypechange.go
8171--- a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/notypechange.go	2000-01-01 00:00:00.000000000 -0000
8172+++ b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/notypechange.go	1970-01-01 00:00:00.000000000 +0000
8173@@ -1,26 +0,0 @@
8174-// Copyright 2021 The Go Authors. All rights reserved.
8175-// Use of this source code is governed by a BSD-style
8176-// license that can be found in the LICENSE file.
8177-
8178-// We should not suggest removing type arguments if doing so would change the
8179-// resulting type.
8180-
8181-package a
8182-
8183-func id[T any](t T) T { return t }
8184-
8185-var _ = id[int](1)        // want "unnecessary type arguments"
8186-var _ = id[string]("foo") // want "unnecessary type arguments"
8187-var _ = id[int64](2)
8188-
8189-func pair[T any](t T) (T, T) { return t, t }
8190-
8191-var _, _ = pair[int](3) // want "unnecessary type arguments"
8192-var _, _ = pair[int64](3)
8193-
8194-func noreturn[T any](t T) {}
8195-
8196-func _() {
8197-	noreturn[int64](4)
8198-	noreturn[int](4) // want "unnecessary type arguments"
8199-}
8200diff -urN a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/notypechange.go.golden b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/notypechange.go.golden
8201--- a/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/notypechange.go.golden	2000-01-01 00:00:00.000000000 -0000
8202+++ b/gopls/internal/lsp/analysis/infertypeargs/testdata/src/a/notypechange.go.golden	1970-01-01 00:00:00.000000000 +0000
8203@@ -1,26 +0,0 @@
8204-// Copyright 2021 The Go Authors. All rights reserved.
8205-// Use of this source code is governed by a BSD-style
8206-// license that can be found in the LICENSE file.
8207-
8208-// We should not suggest removing type arguments if doing so would change the
8209-// resulting type.
8210-
8211-package a
8212-
8213-func id[T any](t T) T { return t }
8214-
8215-var _ = id(1)     // want "unnecessary type arguments"
8216-var _ = id("foo") // want "unnecessary type arguments"
8217-var _ = id[int64](2)
8218-
8219-func pair[T any](t T) (T, T) { return t, t }
8220-
8221-var _, _ = pair(3) // want "unnecessary type arguments"
8222-var _, _ = pair[int64](3)
8223-
8224-func noreturn[T any](t T) {}
8225-
8226-func _() {
8227-	noreturn[int64](4)
8228-	noreturn(4) // want "unnecessary type arguments"
8229-}
8230diff -urN a/gopls/internal/lsp/analysis/nonewvars/nonewvars.go b/gopls/internal/lsp/analysis/nonewvars/nonewvars.go
8231--- a/gopls/internal/lsp/analysis/nonewvars/nonewvars.go	2000-01-01 00:00:00.000000000 -0000
8232+++ b/gopls/internal/lsp/analysis/nonewvars/nonewvars.go	1970-01-01 00:00:00.000000000 +0000
8233@@ -1,95 +0,0 @@
8234-// Copyright 2020 The Go Authors. All rights reserved.
8235-// Use of this source code is governed by a BSD-style
8236-// license that can be found in the LICENSE file.
8237-
8238-// Package nonewvars defines an Analyzer that applies suggested fixes
8239-// to errors of the type "no new variables on left side of :=".
8240-package nonewvars
8241-
8242-import (
8243-	"bytes"
8244-	"go/ast"
8245-	"go/format"
8246-	"go/token"
8247-
8248-	"golang.org/x/tools/go/analysis"
8249-	"golang.org/x/tools/go/analysis/passes/inspect"
8250-	"golang.org/x/tools/go/ast/inspector"
8251-	"golang.org/x/tools/internal/analysisinternal"
8252-)
8253-
8254-const Doc = `suggested fixes for "no new vars on left side of :="
8255-
8256-This checker provides suggested fixes for type errors of the
8257-type "no new vars on left side of :=". For example:
8258-	z := 1
8259-	z := 2
8260-will turn into
8261-	z := 1
8262-	z = 2
8263-`
8264-
8265-var Analyzer = &analysis.Analyzer{
8266-	Name:             "nonewvars",
8267-	Doc:              Doc,
8268-	Requires:         []*analysis.Analyzer{inspect.Analyzer},
8269-	Run:              run,
8270-	RunDespiteErrors: true,
8271-}
8272-
8273-func run(pass *analysis.Pass) (interface{}, error) {
8274-	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
8275-	if len(pass.TypeErrors) == 0 {
8276-		return nil, nil
8277-	}
8278-
8279-	nodeFilter := []ast.Node{(*ast.AssignStmt)(nil)}
8280-	inspect.Preorder(nodeFilter, func(n ast.Node) {
8281-		assignStmt, _ := n.(*ast.AssignStmt)
8282-		// We only care about ":=".
8283-		if assignStmt.Tok != token.DEFINE {
8284-			return
8285-		}
8286-
8287-		var file *ast.File
8288-		for _, f := range pass.Files {
8289-			if f.Pos() <= assignStmt.Pos() && assignStmt.Pos() < f.End() {
8290-				file = f
8291-				break
8292-			}
8293-		}
8294-		if file == nil {
8295-			return
8296-		}
8297-
8298-		for _, err := range pass.TypeErrors {
8299-			if !FixesError(err.Msg) {
8300-				continue
8301-			}
8302-			if assignStmt.Pos() > err.Pos || err.Pos >= assignStmt.End() {
8303-				continue
8304-			}
8305-			var buf bytes.Buffer
8306-			if err := format.Node(&buf, pass.Fset, file); err != nil {
8307-				continue
8308-			}
8309-			pass.Report(analysis.Diagnostic{
8310-				Pos:     err.Pos,
8311-				End:     analysisinternal.TypeErrorEndPos(pass.Fset, buf.Bytes(), err.Pos),
8312-				Message: err.Msg,
8313-				SuggestedFixes: []analysis.SuggestedFix{{
8314-					Message: "Change ':=' to '='",
8315-					TextEdits: []analysis.TextEdit{{
8316-						Pos: err.Pos,
8317-						End: err.Pos + 1,
8318-					}},
8319-				}},
8320-			})
8321-		}
8322-	})
8323-	return nil, nil
8324-}
8325-
8326-func FixesError(msg string) bool {
8327-	return msg == "no new variables on left side of :="
8328-}
8329diff -urN a/gopls/internal/lsp/analysis/nonewvars/nonewvars_test.go b/gopls/internal/lsp/analysis/nonewvars/nonewvars_test.go
8330--- a/gopls/internal/lsp/analysis/nonewvars/nonewvars_test.go	2000-01-01 00:00:00.000000000 -0000
8331+++ b/gopls/internal/lsp/analysis/nonewvars/nonewvars_test.go	1970-01-01 00:00:00.000000000 +0000
8332@@ -1,22 +0,0 @@
8333-// Copyright 2020 The Go Authors. All rights reserved.
8334-// Use of this source code is governed by a BSD-style
8335-// license that can be found in the LICENSE file.
8336-
8337-package nonewvars_test
8338-
8339-import (
8340-	"testing"
8341-
8342-	"golang.org/x/tools/go/analysis/analysistest"
8343-	"golang.org/x/tools/gopls/internal/lsp/analysis/nonewvars"
8344-	"golang.org/x/tools/internal/typeparams"
8345-)
8346-
8347-func Test(t *testing.T) {
8348-	testdata := analysistest.TestData()
8349-	tests := []string{"a"}
8350-	if typeparams.Enabled {
8351-		tests = append(tests, "typeparams")
8352-	}
8353-	analysistest.RunWithSuggestedFixes(t, testdata, nonewvars.Analyzer, tests...)
8354-}
8355diff -urN a/gopls/internal/lsp/analysis/nonewvars/testdata/src/a/a.go b/gopls/internal/lsp/analysis/nonewvars/testdata/src/a/a.go
8356--- a/gopls/internal/lsp/analysis/nonewvars/testdata/src/a/a.go	2000-01-01 00:00:00.000000000 -0000
8357+++ b/gopls/internal/lsp/analysis/nonewvars/testdata/src/a/a.go	1970-01-01 00:00:00.000000000 +0000
8358@@ -1,16 +0,0 @@
8359-// Copyright 2020 The Go Authors. All rights reserved.
8360-// Use of this source code is governed by a BSD-style
8361-// license that can be found in the LICENSE file.
8362-
8363-package nonewvars
8364-
8365-import "log"
8366-
8367-func x() {
8368-	z := 1
8369-	z := 2 // want "no new variables on left side of :="
8370-
8371-	_, z := 3, 100 // want "no new variables on left side of :="
8372-
8373-	log.Println(z)
8374-}
8375diff -urN a/gopls/internal/lsp/analysis/nonewvars/testdata/src/a/a.go.golden b/gopls/internal/lsp/analysis/nonewvars/testdata/src/a/a.go.golden
8376--- a/gopls/internal/lsp/analysis/nonewvars/testdata/src/a/a.go.golden	2000-01-01 00:00:00.000000000 -0000
8377+++ b/gopls/internal/lsp/analysis/nonewvars/testdata/src/a/a.go.golden	1970-01-01 00:00:00.000000000 +0000
8378@@ -1,16 +0,0 @@
8379-// Copyright 2020 The Go Authors. All rights reserved.
8380-// Use of this source code is governed by a BSD-style
8381-// license that can be found in the LICENSE file.
8382-
8383-package nonewvars
8384-
8385-import "log"
8386-
8387-func x() {
8388-	z := 1
8389-	z = 2 // want "no new variables on left side of :="
8390-
8391-	_, z = 3, 100 // want "no new variables on left side of :="
8392-
8393-	log.Println(z)
8394-}
8395diff -urN a/gopls/internal/lsp/analysis/nonewvars/testdata/src/typeparams/a.go b/gopls/internal/lsp/analysis/nonewvars/testdata/src/typeparams/a.go
8396--- a/gopls/internal/lsp/analysis/nonewvars/testdata/src/typeparams/a.go	2000-01-01 00:00:00.000000000 -0000
8397+++ b/gopls/internal/lsp/analysis/nonewvars/testdata/src/typeparams/a.go	1970-01-01 00:00:00.000000000 +0000
8398@@ -1,6 +0,0 @@
8399-package nonewvars
8400-
8401-func hello[T any]() int {
8402-	var z T
8403-	z := 1 // want "no new variables on left side of :="
8404-}
8405diff -urN a/gopls/internal/lsp/analysis/nonewvars/testdata/src/typeparams/a.go.golden b/gopls/internal/lsp/analysis/nonewvars/testdata/src/typeparams/a.go.golden
8406--- a/gopls/internal/lsp/analysis/nonewvars/testdata/src/typeparams/a.go.golden	2000-01-01 00:00:00.000000000 -0000
8407+++ b/gopls/internal/lsp/analysis/nonewvars/testdata/src/typeparams/a.go.golden	1970-01-01 00:00:00.000000000 +0000
8408@@ -1,6 +0,0 @@
8409-package nonewvars
8410-
8411-func hello[T any]() int {
8412-	var z T
8413-	z = 1 // want "no new variables on left side of :="
8414-}
8415diff -urN a/gopls/internal/lsp/analysis/noresultvalues/noresultvalues.go b/gopls/internal/lsp/analysis/noresultvalues/noresultvalues.go
8416--- a/gopls/internal/lsp/analysis/noresultvalues/noresultvalues.go	2000-01-01 00:00:00.000000000 -0000
8417+++ b/gopls/internal/lsp/analysis/noresultvalues/noresultvalues.go	1970-01-01 00:00:00.000000000 +0000
8418@@ -1,92 +0,0 @@
8419-// Copyright 2020 The Go Authors. All rights reserved.
8420-// Use of this source code is governed by a BSD-style
8421-// license that can be found in the LICENSE file.
8422-
8423-// Package noresultvalues defines an Analyzer that applies suggested fixes
8424-// to errors of the type "no result values expected".
8425-package noresultvalues
8426-
8427-import (
8428-	"bytes"
8429-	"go/ast"
8430-	"go/format"
8431-	"strings"
8432-
8433-	"golang.org/x/tools/go/analysis"
8434-	"golang.org/x/tools/go/analysis/passes/inspect"
8435-	"golang.org/x/tools/go/ast/inspector"
8436-	"golang.org/x/tools/internal/analysisinternal"
8437-)
8438-
8439-const Doc = `suggested fixes for unexpected return values
8440-
8441-This checker provides suggested fixes for type errors of the
8442-type "no result values expected" or "too many return values".
8443-For example:
8444-	func z() { return nil }
8445-will turn into
8446-	func z() { return }
8447-`
8448-
8449-var Analyzer = &analysis.Analyzer{
8450-	Name:             "noresultvalues",
8451-	Doc:              Doc,
8452-	Requires:         []*analysis.Analyzer{inspect.Analyzer},
8453-	Run:              run,
8454-	RunDespiteErrors: true,
8455-}
8456-
8457-func run(pass *analysis.Pass) (interface{}, error) {
8458-	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
8459-	if len(pass.TypeErrors) == 0 {
8460-		return nil, nil
8461-	}
8462-
8463-	nodeFilter := []ast.Node{(*ast.ReturnStmt)(nil)}
8464-	inspect.Preorder(nodeFilter, func(n ast.Node) {
8465-		retStmt, _ := n.(*ast.ReturnStmt)
8466-
8467-		var file *ast.File
8468-		for _, f := range pass.Files {
8469-			if f.Pos() <= retStmt.Pos() && retStmt.Pos() < f.End() {
8470-				file = f
8471-				break
8472-			}
8473-		}
8474-		if file == nil {
8475-			return
8476-		}
8477-
8478-		for _, err := range pass.TypeErrors {
8479-			if !FixesError(err.Msg) {
8480-				continue
8481-			}
8482-			if retStmt.Pos() >= err.Pos || err.Pos >= retStmt.End() {
8483-				continue
8484-			}
8485-			var buf bytes.Buffer
8486-			if err := format.Node(&buf, pass.Fset, file); err != nil {
8487-				continue
8488-			}
8489-			pass.Report(analysis.Diagnostic{
8490-				Pos:     err.Pos,
8491-				End:     analysisinternal.TypeErrorEndPos(pass.Fset, buf.Bytes(), err.Pos),
8492-				Message: err.Msg,
8493-				SuggestedFixes: []analysis.SuggestedFix{{
8494-					Message: "Delete return values",
8495-					TextEdits: []analysis.TextEdit{{
8496-						Pos:     retStmt.Pos(),
8497-						End:     retStmt.End(),
8498-						NewText: []byte("return"),
8499-					}},
8500-				}},
8501-			})
8502-		}
8503-	})
8504-	return nil, nil
8505-}
8506-
8507-func FixesError(msg string) bool {
8508-	return msg == "no result values expected" ||
8509-		strings.HasPrefix(msg, "too many return values") && strings.Contains(msg, "want ()")
8510-}
8511diff -urN a/gopls/internal/lsp/analysis/noresultvalues/noresultvalues_test.go b/gopls/internal/lsp/analysis/noresultvalues/noresultvalues_test.go
8512--- a/gopls/internal/lsp/analysis/noresultvalues/noresultvalues_test.go	2000-01-01 00:00:00.000000000 -0000
8513+++ b/gopls/internal/lsp/analysis/noresultvalues/noresultvalues_test.go	1970-01-01 00:00:00.000000000 +0000
8514@@ -1,22 +0,0 @@
8515-// Copyright 2020 The Go Authors. All rights reserved.
8516-// Use of this source code is governed by a BSD-style
8517-// license that can be found in the LICENSE file.
8518-
8519-package noresultvalues_test
8520-
8521-import (
8522-	"testing"
8523-
8524-	"golang.org/x/tools/go/analysis/analysistest"
8525-	"golang.org/x/tools/gopls/internal/lsp/analysis/noresultvalues"
8526-	"golang.org/x/tools/internal/typeparams"
8527-)
8528-
8529-func Test(t *testing.T) {
8530-	testdata := analysistest.TestData()
8531-	tests := []string{"a"}
8532-	if typeparams.Enabled {
8533-		tests = append(tests, "typeparams")
8534-	}
8535-	analysistest.RunWithSuggestedFixes(t, testdata, noresultvalues.Analyzer, tests...)
8536-}
8537diff -urN a/gopls/internal/lsp/analysis/noresultvalues/testdata/src/a/a.go b/gopls/internal/lsp/analysis/noresultvalues/testdata/src/a/a.go
8538--- a/gopls/internal/lsp/analysis/noresultvalues/testdata/src/a/a.go	2000-01-01 00:00:00.000000000 -0000
8539+++ b/gopls/internal/lsp/analysis/noresultvalues/testdata/src/a/a.go	1970-01-01 00:00:00.000000000 +0000
8540@@ -1,9 +0,0 @@
8541-// Copyright 2020 The Go Authors. All rights reserved.
8542-// Use of this source code is governed by a BSD-style
8543-// license that can be found in the LICENSE file.
8544-
8545-package noresultvalues
8546-
8547-func x() { return nil } // want `no result values expected|too many return values`
8548-
8549-func y() { return nil, "hello" } // want `no result values expected|too many return values`
8550diff -urN a/gopls/internal/lsp/analysis/noresultvalues/testdata/src/a/a.go.golden b/gopls/internal/lsp/analysis/noresultvalues/testdata/src/a/a.go.golden
8551--- a/gopls/internal/lsp/analysis/noresultvalues/testdata/src/a/a.go.golden	2000-01-01 00:00:00.000000000 -0000
8552+++ b/gopls/internal/lsp/analysis/noresultvalues/testdata/src/a/a.go.golden	1970-01-01 00:00:00.000000000 +0000
8553@@ -1,9 +0,0 @@
8554-// Copyright 2020 The Go Authors. All rights reserved.
8555-// Use of this source code is governed by a BSD-style
8556-// license that can be found in the LICENSE file.
8557-
8558-package noresultvalues
8559-
8560-func x() { return } // want `no result values expected|too many return values`
8561-
8562-func y() { return } // want `no result values expected|too many return values`
8563diff -urN a/gopls/internal/lsp/analysis/noresultvalues/testdata/src/typeparams/a.go b/gopls/internal/lsp/analysis/noresultvalues/testdata/src/typeparams/a.go
8564--- a/gopls/internal/lsp/analysis/noresultvalues/testdata/src/typeparams/a.go	2000-01-01 00:00:00.000000000 -0000
8565+++ b/gopls/internal/lsp/analysis/noresultvalues/testdata/src/typeparams/a.go	1970-01-01 00:00:00.000000000 +0000
8566@@ -1,6 +0,0 @@
8567-package noresult
8568-
8569-func hello[T any]() {
8570-	var z T
8571-	return z // want `no result values expected|too many return values`
8572-}
8573diff -urN a/gopls/internal/lsp/analysis/noresultvalues/testdata/src/typeparams/a.go.golden b/gopls/internal/lsp/analysis/noresultvalues/testdata/src/typeparams/a.go.golden
8574--- a/gopls/internal/lsp/analysis/noresultvalues/testdata/src/typeparams/a.go.golden	2000-01-01 00:00:00.000000000 -0000
8575+++ b/gopls/internal/lsp/analysis/noresultvalues/testdata/src/typeparams/a.go.golden	1970-01-01 00:00:00.000000000 +0000
8576@@ -1,6 +0,0 @@
8577-package noresult
8578-
8579-func hello[T any]() {
8580-	var z T
8581-	return // want `no result values expected|too many return values`
8582-}
8583diff -urN a/gopls/internal/lsp/analysis/simplifycompositelit/simplifycompositelit.go b/gopls/internal/lsp/analysis/simplifycompositelit/simplifycompositelit.go
8584--- a/gopls/internal/lsp/analysis/simplifycompositelit/simplifycompositelit.go	2000-01-01 00:00:00.000000000 -0000
8585+++ b/gopls/internal/lsp/analysis/simplifycompositelit/simplifycompositelit.go	1970-01-01 00:00:00.000000000 +0000
8586@@ -1,196 +0,0 @@
8587-// Copyright 2020 The Go Authors. All rights reserved.
8588-// Use of this source code is governed by a BSD-style
8589-// license that can be found in the LICENSE file.
8590-
8591-// Package simplifycompositelit defines an Analyzer that simplifies composite literals.
8592-// https://github.com/golang/go/blob/master/src/cmd/gofmt/simplify.go
8593-// https://golang.org/cmd/gofmt/#hdr-The_simplify_command
8594-package simplifycompositelit
8595-
8596-import (
8597-	"bytes"
8598-	"fmt"
8599-	"go/ast"
8600-	"go/printer"
8601-	"go/token"
8602-	"reflect"
8603-
8604-	"golang.org/x/tools/go/analysis"
8605-	"golang.org/x/tools/go/analysis/passes/inspect"
8606-	"golang.org/x/tools/go/ast/inspector"
8607-)
8608-
8609-const Doc = `check for composite literal simplifications
8610-
8611-An array, slice, or map composite literal of the form:
8612-	[]T{T{}, T{}}
8613-will be simplified to:
8614-	[]T{{}, {}}
8615-
8616-This is one of the simplifications that "gofmt -s" applies.`
8617-
8618-var Analyzer = &analysis.Analyzer{
8619-	Name:     "simplifycompositelit",
8620-	Doc:      Doc,
8621-	Requires: []*analysis.Analyzer{inspect.Analyzer},
8622-	Run:      run,
8623-}
8624-
8625-func run(pass *analysis.Pass) (interface{}, error) {
8626-	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
8627-	nodeFilter := []ast.Node{(*ast.CompositeLit)(nil)}
8628-	inspect.Preorder(nodeFilter, func(n ast.Node) {
8629-		expr := n.(*ast.CompositeLit)
8630-
8631-		outer := expr
8632-		var keyType, eltType ast.Expr
8633-		switch typ := outer.Type.(type) {
8634-		case *ast.ArrayType:
8635-			eltType = typ.Elt
8636-		case *ast.MapType:
8637-			keyType = typ.Key
8638-			eltType = typ.Value
8639-		}
8640-
8641-		if eltType == nil {
8642-			return
8643-		}
8644-		var ktyp reflect.Value
8645-		if keyType != nil {
8646-			ktyp = reflect.ValueOf(keyType)
8647-		}
8648-		typ := reflect.ValueOf(eltType)
8649-		for _, x := range outer.Elts {
8650-			// look at value of indexed/named elements
8651-			if t, ok := x.(*ast.KeyValueExpr); ok {
8652-				if keyType != nil {
8653-					simplifyLiteral(pass, ktyp, keyType, t.Key)
8654-				}
8655-				x = t.Value
8656-			}
8657-			simplifyLiteral(pass, typ, eltType, x)
8658-		}
8659-	})
8660-	return nil, nil
8661-}
8662-
8663-func simplifyLiteral(pass *analysis.Pass, typ reflect.Value, astType, x ast.Expr) {
8664-	// if the element is a composite literal and its literal type
8665-	// matches the outer literal's element type exactly, the inner
8666-	// literal type may be omitted
8667-	if inner, ok := x.(*ast.CompositeLit); ok && match(typ, reflect.ValueOf(inner.Type)) {
8668-		var b bytes.Buffer
8669-		printer.Fprint(&b, pass.Fset, inner.Type)
8670-		createDiagnostic(pass, inner.Type.Pos(), inner.Type.End(), b.String())
8671-	}
8672-	// if the outer literal's element type is a pointer type *T
8673-	// and the element is & of a composite literal of type T,
8674-	// the inner &T may be omitted.
8675-	if ptr, ok := astType.(*ast.StarExpr); ok {
8676-		if addr, ok := x.(*ast.UnaryExpr); ok && addr.Op == token.AND {
8677-			if inner, ok := addr.X.(*ast.CompositeLit); ok {
8678-				if match(reflect.ValueOf(ptr.X), reflect.ValueOf(inner.Type)) {
8679-					var b bytes.Buffer
8680-					printer.Fprint(&b, pass.Fset, inner.Type)
8681-					// Account for the & by subtracting 1 from typ.Pos().
8682-					createDiagnostic(pass, inner.Type.Pos()-1, inner.Type.End(), "&"+b.String())
8683-				}
8684-			}
8685-		}
8686-	}
8687-}
8688-
8689-func createDiagnostic(pass *analysis.Pass, start, end token.Pos, typ string) {
8690-	pass.Report(analysis.Diagnostic{
8691-		Pos:     start,
8692-		End:     end,
8693-		Message: "redundant type from array, slice, or map composite literal",
8694-		SuggestedFixes: []analysis.SuggestedFix{{
8695-			Message: fmt.Sprintf("Remove '%s'", typ),
8696-			TextEdits: []analysis.TextEdit{{
8697-				Pos:     start,
8698-				End:     end,
8699-				NewText: []byte{},
8700-			}},
8701-		}},
8702-	})
8703-}
8704-
8705-// match reports whether pattern matches val,
8706-// recording wildcard submatches in m.
8707-// If m == nil, match checks whether pattern == val.
8708-// from https://github.com/golang/go/blob/26154f31ad6c801d8bad5ef58df1e9263c6beec7/src/cmd/gofmt/rewrite.go#L160
8709-func match(pattern, val reflect.Value) bool {
8710-	// Otherwise, pattern and val must match recursively.
8711-	if !pattern.IsValid() || !val.IsValid() {
8712-		return !pattern.IsValid() && !val.IsValid()
8713-	}
8714-	if pattern.Type() != val.Type() {
8715-		return false
8716-	}
8717-
8718-	// Special cases.
8719-	switch pattern.Type() {
8720-	case identType:
8721-		// For identifiers, only the names need to match
8722-		// (and none of the other *ast.Object information).
8723-		// This is a common case, handle it all here instead
8724-		// of recursing down any further via reflection.
8725-		p := pattern.Interface().(*ast.Ident)
8726-		v := val.Interface().(*ast.Ident)
8727-		return p == nil && v == nil || p != nil && v != nil && p.Name == v.Name
8728-	case objectPtrType, positionType:
8729-		// object pointers and token positions always match
8730-		return true
8731-	case callExprType:
8732-		// For calls, the Ellipsis fields (token.Position) must
8733-		// match since that is how f(x) and f(x...) are different.
8734-		// Check them here but fall through for the remaining fields.
8735-		p := pattern.Interface().(*ast.CallExpr)
8736-		v := val.Interface().(*ast.CallExpr)
8737-		if p.Ellipsis.IsValid() != v.Ellipsis.IsValid() {
8738-			return false
8739-		}
8740-	}
8741-
8742-	p := reflect.Indirect(pattern)
8743-	v := reflect.Indirect(val)
8744-	if !p.IsValid() || !v.IsValid() {
8745-		return !p.IsValid() && !v.IsValid()
8746-	}
8747-
8748-	switch p.Kind() {
8749-	case reflect.Slice:
8750-		if p.Len() != v.Len() {
8751-			return false
8752-		}
8753-		for i := 0; i < p.Len(); i++ {
8754-			if !match(p.Index(i), v.Index(i)) {
8755-				return false
8756-			}
8757-		}
8758-		return true
8759-
8760-	case reflect.Struct:
8761-		for i := 0; i < p.NumField(); i++ {
8762-			if !match(p.Field(i), v.Field(i)) {
8763-				return false
8764-			}
8765-		}
8766-		return true
8767-
8768-	case reflect.Interface:
8769-		return match(p.Elem(), v.Elem())
8770-	}
8771-
8772-	// Handle token integers, etc.
8773-	return p.Interface() == v.Interface()
8774-}
8775-
8776-// Values/types for special cases.
8777-var (
8778-	identType     = reflect.TypeOf((*ast.Ident)(nil))
8779-	objectPtrType = reflect.TypeOf((*ast.Object)(nil))
8780-	positionType  = reflect.TypeOf(token.NoPos)
8781-	callExprType  = reflect.TypeOf((*ast.CallExpr)(nil))
8782-)
8783diff -urN a/gopls/internal/lsp/analysis/simplifycompositelit/simplifycompositelit_test.go b/gopls/internal/lsp/analysis/simplifycompositelit/simplifycompositelit_test.go
8784--- a/gopls/internal/lsp/analysis/simplifycompositelit/simplifycompositelit_test.go	2000-01-01 00:00:00.000000000 -0000
8785+++ b/gopls/internal/lsp/analysis/simplifycompositelit/simplifycompositelit_test.go	1970-01-01 00:00:00.000000000 +0000
8786@@ -1,17 +0,0 @@
8787-// Copyright 2020 The Go Authors. All rights reserved.
8788-// Use of this source code is governed by a BSD-style
8789-// license that can be found in the LICENSE file.
8790-
8791-package simplifycompositelit_test
8792-
8793-import (
8794-	"testing"
8795-
8796-	"golang.org/x/tools/go/analysis/analysistest"
8797-	"golang.org/x/tools/gopls/internal/lsp/analysis/simplifycompositelit"
8798-)
8799-
8800-func Test(t *testing.T) {
8801-	testdata := analysistest.TestData()
8802-	analysistest.RunWithSuggestedFixes(t, testdata, simplifycompositelit.Analyzer, "a")
8803-}
8804diff -urN a/gopls/internal/lsp/analysis/simplifycompositelit/testdata/src/a/a.go b/gopls/internal/lsp/analysis/simplifycompositelit/testdata/src/a/a.go
8805--- a/gopls/internal/lsp/analysis/simplifycompositelit/testdata/src/a/a.go	2000-01-01 00:00:00.000000000 -0000
8806+++ b/gopls/internal/lsp/analysis/simplifycompositelit/testdata/src/a/a.go	1970-01-01 00:00:00.000000000 +0000
8807@@ -1,234 +0,0 @@
8808-// Copyright 2020 The Go Authors. All rights reserved.
8809-// Use of this source code is governed by a BSD-style
8810-// license that can be found in the LICENSE file.
8811-
8812-package testdata
8813-
8814-type T struct {
8815-	x, y int
8816-}
8817-
8818-type T2 struct {
8819-	w, z int
8820-}
8821-
8822-var _ = [42]T{
8823-	T{},     // want "redundant type from array, slice, or map composite literal"
8824-	T{1, 2}, // want "redundant type from array, slice, or map composite literal"
8825-	T{3, 4}, // want "redundant type from array, slice, or map composite literal"
8826-}
8827-
8828-var _ = [...]T{
8829-	T{},     // want "redundant type from array, slice, or map composite literal"
8830-	T{1, 2}, // want "redundant type from array, slice, or map composite literal"
8831-	T{3, 4}, // want "redundant type from array, slice, or map composite literal"
8832-}
8833-
8834-var _ = []T{
8835-	T{},     // want "redundant type from array, slice, or map composite literal"
8836-	T{1, 2}, // want "redundant type from array, slice, or map composite literal"
8837-	T{3, 4}, // want "redundant type from array, slice, or map composite literal"
8838-}
8839-
8840-var _ = []T{
8841-	T{}, // want "redundant type from array, slice, or map composite literal"
8842-	10:  T{1, 2}, // want "redundant type from array, slice, or map composite literal"
8843-	20:  T{3, 4}, // want "redundant type from array, slice, or map composite literal"
8844-}
8845-
8846-var _ = []struct {
8847-	x, y int
8848-}{
8849-	struct{ x, y int }{}, // want "redundant type from array, slice, or map composite literal"
8850-	10:                   struct{ x, y int }{1, 2}, // want "redundant type from array, slice, or map composite literal"
8851-	20:                   struct{ x, y int }{3, 4}, // want "redundant type from array, slice, or map composite literal"
8852-}
8853-
8854-var _ = []interface{}{
8855-	T{},
8856-	10: T{1, 2},
8857-	20: T{3, 4},
8858-}
8859-
8860-var _ = [][]int{
8861-	[]int{},     // want "redundant type from array, slice, or map composite literal"
8862-	[]int{1, 2}, // want "redundant type from array, slice, or map composite literal"
8863-	[]int{3, 4}, // want "redundant type from array, slice, or map composite literal"
8864-}
8865-
8866-var _ = [][]int{
8867-	([]int{}),
8868-	([]int{1, 2}),
8869-	[]int{3, 4}, // want "redundant type from array, slice, or map composite literal"
8870-}
8871-
8872-var _ = [][][]int{
8873-	[][]int{}, // want "redundant type from array, slice, or map composite literal"
8874-	[][]int{ // want "redundant type from array, slice, or map composite literal"
8875-		[]int{},           // want "redundant type from array, slice, or map composite literal"
8876-		[]int{0, 1, 2, 3}, // want "redundant type from array, slice, or map composite literal"
8877-		[]int{4, 5},       // want "redundant type from array, slice, or map composite literal"
8878-	},
8879-}
8880-
8881-var _ = map[string]T{
8882-	"foo": T{},     // want "redundant type from array, slice, or map composite literal"
8883-	"bar": T{1, 2}, // want "redundant type from array, slice, or map composite literal"
8884-	"bal": T{3, 4}, // want "redundant type from array, slice, or map composite literal"
8885-}
8886-
8887-var _ = map[string]struct {
8888-	x, y int
8889-}{
8890-	"foo": struct{ x, y int }{},     // want "redundant type from array, slice, or map composite literal"
8891-	"bar": struct{ x, y int }{1, 2}, // want "redundant type from array, slice, or map composite literal"
8892-	"bal": struct{ x, y int }{3, 4}, // want "redundant type from array, slice, or map composite literal"
8893-}
8894-
8895-var _ = map[string]interface{}{
8896-	"foo": T{},
8897-	"bar": T{1, 2},
8898-	"bal": T{3, 4},
8899-}
8900-
8901-var _ = map[string][]int{
8902-	"foo": []int{},     // want "redundant type from array, slice, or map composite literal"
8903-	"bar": []int{1, 2}, // want "redundant type from array, slice, or map composite literal"
8904-	"bal": []int{3, 4}, // want "redundant type from array, slice, or map composite literal"
8905-}
8906-
8907-var _ = map[string][]int{
8908-	"foo": ([]int{}),
8909-	"bar": ([]int{1, 2}),
8910-	"bal": []int{3, 4}, // want "redundant type from array, slice, or map composite literal"
8911-}
8912-
8913-type Point struct {
8914-	a int
8915-	b int
8916-}
8917-
8918-type Piece struct {
8919-	a int
8920-	b int
8921-	c Point
8922-	d []Point
8923-	e *Point
8924-	f *Point
8925-}
8926-
8927-// from exp/4s/data.go
8928-var pieces3 = []Piece{
8929-	Piece{0, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
8930-	Piece{1, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
8931-	Piece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
8932-	Piece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
8933-}
8934-
8935-var _ = [42]*T{
8936-	&T{},     // want "redundant type from array, slice, or map composite literal"
8937-	&T{1, 2}, // want "redundant type from array, slice, or map composite literal"
8938-	&T{3, 4}, // want "redundant type from array, slice, or map composite literal"
8939-}
8940-
8941-var _ = [...]*T{
8942-	&T{},     // want "redundant type from array, slice, or map composite literal"
8943-	&T{1, 2}, // want "redundant type from array, slice, or map composite literal"
8944-	&T{3, 4}, // want "redundant type from array, slice, or map composite literal"
8945-}
8946-
8947-var _ = []*T{
8948-	&T{},     // want "redundant type from array, slice, or map composite literal"
8949-	&T{1, 2}, // want "redundant type from array, slice, or map composite literal"
8950-	&T{3, 4}, // want "redundant type from array, slice, or map composite literal"
8951-}
8952-
8953-var _ = []*T{
8954-	&T{}, // want "redundant type from array, slice, or map composite literal"
8955-	10:   &T{1, 2}, // want "redundant type from array, slice, or map composite literal"
8956-	20:   &T{3, 4}, // want "redundant type from array, slice, or map composite literal"
8957-}
8958-
8959-var _ = []*struct {
8960-	x, y int
8961-}{
8962-	&struct{ x, y int }{}, // want "redundant type from array, slice, or map composite literal"
8963-	10:                    &struct{ x, y int }{1, 2}, // want "redundant type from array, slice, or map composite literal"
8964-	20:                    &struct{ x, y int }{3, 4}, // want "redundant type from array, slice, or map composite literal"
8965-}
8966-
8967-var _ = []interface{}{
8968-	&T{},
8969-	10: &T{1, 2},
8970-	20: &T{3, 4},
8971-}
8972-
8973-var _ = []*[]int{
8974-	&[]int{},     // want "redundant type from array, slice, or map composite literal"
8975-	&[]int{1, 2}, // want "redundant type from array, slice, or map composite literal"
8976-	&[]int{3, 4}, // want "redundant type from array, slice, or map composite literal"
8977-}
8978-
8979-var _ = []*[]int{
8980-	(&[]int{}),
8981-	(&[]int{1, 2}),
8982-	&[]int{3, 4}, // want "redundant type from array, slice, or map composite literal"
8983-}
8984-
8985-var _ = []*[]*[]int{
8986-	&[]*[]int{}, // want "redundant type from array, slice, or map composite literal"
8987-	&[]*[]int{ // want "redundant type from array, slice, or map composite literal"
8988-		&[]int{},           // want "redundant type from array, slice, or map composite literal"
8989-		&[]int{0, 1, 2, 3}, // want "redundant type from array, slice, or map composite literal"
8990-		&[]int{4, 5},       // want "redundant type from array, slice, or map composite literal"
8991-	},
8992-}
8993-
8994-var _ = map[string]*T{
8995-	"foo": &T{},     // want "redundant type from array, slice, or map composite literal"
8996-	"bar": &T{1, 2}, // want "redundant type from array, slice, or map composite literal"
8997-	"bal": &T{3, 4}, // want "redundant type from array, slice, or map composite literal"
8998-}
8999-
9000-var _ = map[string]*struct {
9001-	x, y int
9002-}{
9003-	"foo": &struct{ x, y int }{},     // want "redundant type from array, slice, or map composite literal"
9004-	"bar": &struct{ x, y int }{1, 2}, // want "redundant type from array, slice, or map composite literal"
9005-	"bal": &struct{ x, y int }{3, 4}, // want "redundant type from array, slice, or map composite literal"
9006-}
9007-
9008-var _ = map[string]interface{}{
9009-	"foo": &T{},
9010-	"bar": &T{1, 2},
9011-	"bal": &T{3, 4},
9012-}
9013-
9014-var _ = map[string]*[]int{
9015-	"foo": &[]int{},     // want "redundant type from array, slice, or map composite literal"
9016-	"bar": &[]int{1, 2}, // want "redundant type from array, slice, or map composite literal"
9017-	"bal": &[]int{3, 4}, // want "redundant type from array, slice, or map composite literal"
9018-}
9019-
9020-var _ = map[string]*[]int{
9021-	"foo": (&[]int{}),
9022-	"bar": (&[]int{1, 2}),
9023-	"bal": &[]int{3, 4}, // want "redundant type from array, slice, or map composite literal"
9024-}
9025-
9026-var pieces4 = []*Piece{
9027-	&Piece{0, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9028-	&Piece{1, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9029-	&Piece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9030-	&Piece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9031-}
9032-
9033-var _ = map[T]T2{
9034-	T{1, 2}: T2{3, 4}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9035-	T{5, 6}: T2{7, 8}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9036-}
9037-
9038-var _ = map[*T]*T2{
9039-	&T{1, 2}: &T2{3, 4}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9040-	&T{5, 6}: &T2{7, 8}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9041-}
9042diff -urN a/gopls/internal/lsp/analysis/simplifycompositelit/testdata/src/a/a.go.golden b/gopls/internal/lsp/analysis/simplifycompositelit/testdata/src/a/a.go.golden
9043--- a/gopls/internal/lsp/analysis/simplifycompositelit/testdata/src/a/a.go.golden	2000-01-01 00:00:00.000000000 -0000
9044+++ b/gopls/internal/lsp/analysis/simplifycompositelit/testdata/src/a/a.go.golden	1970-01-01 00:00:00.000000000 +0000
9045@@ -1,234 +0,0 @@
9046-// Copyright 2020 The Go Authors. All rights reserved.
9047-// Use of this source code is governed by a BSD-style
9048-// license that can be found in the LICENSE file.
9049-
9050-package testdata
9051-
9052-type T struct {
9053-	x, y int
9054-}
9055-
9056-type T2 struct {
9057-	w, z int
9058-}
9059-
9060-var _ = [42]T{
9061-	{},     // want "redundant type from array, slice, or map composite literal"
9062-	{1, 2}, // want "redundant type from array, slice, or map composite literal"
9063-	{3, 4}, // want "redundant type from array, slice, or map composite literal"
9064-}
9065-
9066-var _ = [...]T{
9067-	{},     // want "redundant type from array, slice, or map composite literal"
9068-	{1, 2}, // want "redundant type from array, slice, or map composite literal"
9069-	{3, 4}, // want "redundant type from array, slice, or map composite literal"
9070-}
9071-
9072-var _ = []T{
9073-	{},     // want "redundant type from array, slice, or map composite literal"
9074-	{1, 2}, // want "redundant type from array, slice, or map composite literal"
9075-	{3, 4}, // want "redundant type from array, slice, or map composite literal"
9076-}
9077-
9078-var _ = []T{
9079-	{}, // want "redundant type from array, slice, or map composite literal"
9080-	10: {1, 2}, // want "redundant type from array, slice, or map composite literal"
9081-	20: {3, 4}, // want "redundant type from array, slice, or map composite literal"
9082-}
9083-
9084-var _ = []struct {
9085-	x, y int
9086-}{
9087-	{}, // want "redundant type from array, slice, or map composite literal"
9088-	10: {1, 2}, // want "redundant type from array, slice, or map composite literal"
9089-	20: {3, 4}, // want "redundant type from array, slice, or map composite literal"
9090-}
9091-
9092-var _ = []interface{}{
9093-	T{},
9094-	10: T{1, 2},
9095-	20: T{3, 4},
9096-}
9097-
9098-var _ = [][]int{
9099-	{},     // want "redundant type from array, slice, or map composite literal"
9100-	{1, 2}, // want "redundant type from array, slice, or map composite literal"
9101-	{3, 4}, // want "redundant type from array, slice, or map composite literal"
9102-}
9103-
9104-var _ = [][]int{
9105-	([]int{}),
9106-	([]int{1, 2}),
9107-	{3, 4}, // want "redundant type from array, slice, or map composite literal"
9108-}
9109-
9110-var _ = [][][]int{
9111-	{}, // want "redundant type from array, slice, or map composite literal"
9112-	{ // want "redundant type from array, slice, or map composite literal"
9113-		{},           // want "redundant type from array, slice, or map composite literal"
9114-		{0, 1, 2, 3}, // want "redundant type from array, slice, or map composite literal"
9115-		{4, 5},       // want "redundant type from array, slice, or map composite literal"
9116-	},
9117-}
9118-
9119-var _ = map[string]T{
9120-	"foo": {},     // want "redundant type from array, slice, or map composite literal"
9121-	"bar": {1, 2}, // want "redundant type from array, slice, or map composite literal"
9122-	"bal": {3, 4}, // want "redundant type from array, slice, or map composite literal"
9123-}
9124-
9125-var _ = map[string]struct {
9126-	x, y int
9127-}{
9128-	"foo": {},     // want "redundant type from array, slice, or map composite literal"
9129-	"bar": {1, 2}, // want "redundant type from array, slice, or map composite literal"
9130-	"bal": {3, 4}, // want "redundant type from array, slice, or map composite literal"
9131-}
9132-
9133-var _ = map[string]interface{}{
9134-	"foo": T{},
9135-	"bar": T{1, 2},
9136-	"bal": T{3, 4},
9137-}
9138-
9139-var _ = map[string][]int{
9140-	"foo": {},     // want "redundant type from array, slice, or map composite literal"
9141-	"bar": {1, 2}, // want "redundant type from array, slice, or map composite literal"
9142-	"bal": {3, 4}, // want "redundant type from array, slice, or map composite literal"
9143-}
9144-
9145-var _ = map[string][]int{
9146-	"foo": ([]int{}),
9147-	"bar": ([]int{1, 2}),
9148-	"bal": {3, 4}, // want "redundant type from array, slice, or map composite literal"
9149-}
9150-
9151-type Point struct {
9152-	a int
9153-	b int
9154-}
9155-
9156-type Piece struct {
9157-	a int
9158-	b int
9159-	c Point
9160-	d []Point
9161-	e *Point
9162-	f *Point
9163-}
9164-
9165-// from exp/4s/data.go
9166-var pieces3 = []Piece{
9167-	{0, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9168-	{1, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9169-	{2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9170-	{3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9171-}
9172-
9173-var _ = [42]*T{
9174-	{},     // want "redundant type from array, slice, or map composite literal"
9175-	{1, 2}, // want "redundant type from array, slice, or map composite literal"
9176-	{3, 4}, // want "redundant type from array, slice, or map composite literal"
9177-}
9178-
9179-var _ = [...]*T{
9180-	{},     // want "redundant type from array, slice, or map composite literal"
9181-	{1, 2}, // want "redundant type from array, slice, or map composite literal"
9182-	{3, 4}, // want "redundant type from array, slice, or map composite literal"
9183-}
9184-
9185-var _ = []*T{
9186-	{},     // want "redundant type from array, slice, or map composite literal"
9187-	{1, 2}, // want "redundant type from array, slice, or map composite literal"
9188-	{3, 4}, // want "redundant type from array, slice, or map composite literal"
9189-}
9190-
9191-var _ = []*T{
9192-	{}, // want "redundant type from array, slice, or map composite literal"
9193-	10: {1, 2}, // want "redundant type from array, slice, or map composite literal"
9194-	20: {3, 4}, // want "redundant type from array, slice, or map composite literal"
9195-}
9196-
9197-var _ = []*struct {
9198-	x, y int
9199-}{
9200-	{}, // want "redundant type from array, slice, or map composite literal"
9201-	10: {1, 2}, // want "redundant type from array, slice, or map composite literal"
9202-	20: {3, 4}, // want "redundant type from array, slice, or map composite literal"
9203-}
9204-
9205-var _ = []interface{}{
9206-	&T{},
9207-	10: &T{1, 2},
9208-	20: &T{3, 4},
9209-}
9210-
9211-var _ = []*[]int{
9212-	{},     // want "redundant type from array, slice, or map composite literal"
9213-	{1, 2}, // want "redundant type from array, slice, or map composite literal"
9214-	{3, 4}, // want "redundant type from array, slice, or map composite literal"
9215-}
9216-
9217-var _ = []*[]int{
9218-	(&[]int{}),
9219-	(&[]int{1, 2}),
9220-	{3, 4}, // want "redundant type from array, slice, or map composite literal"
9221-}
9222-
9223-var _ = []*[]*[]int{
9224-	{}, // want "redundant type from array, slice, or map composite literal"
9225-	{ // want "redundant type from array, slice, or map composite literal"
9226-		{},           // want "redundant type from array, slice, or map composite literal"
9227-		{0, 1, 2, 3}, // want "redundant type from array, slice, or map composite literal"
9228-		{4, 5},       // want "redundant type from array, slice, or map composite literal"
9229-	},
9230-}
9231-
9232-var _ = map[string]*T{
9233-	"foo": {},     // want "redundant type from array, slice, or map composite literal"
9234-	"bar": {1, 2}, // want "redundant type from array, slice, or map composite literal"
9235-	"bal": {3, 4}, // want "redundant type from array, slice, or map composite literal"
9236-}
9237-
9238-var _ = map[string]*struct {
9239-	x, y int
9240-}{
9241-	"foo": {},     // want "redundant type from array, slice, or map composite literal"
9242-	"bar": {1, 2}, // want "redundant type from array, slice, or map composite literal"
9243-	"bal": {3, 4}, // want "redundant type from array, slice, or map composite literal"
9244-}
9245-
9246-var _ = map[string]interface{}{
9247-	"foo": &T{},
9248-	"bar": &T{1, 2},
9249-	"bal": &T{3, 4},
9250-}
9251-
9252-var _ = map[string]*[]int{
9253-	"foo": {},     // want "redundant type from array, slice, or map composite literal"
9254-	"bar": {1, 2}, // want "redundant type from array, slice, or map composite literal"
9255-	"bal": {3, 4}, // want "redundant type from array, slice, or map composite literal"
9256-}
9257-
9258-var _ = map[string]*[]int{
9259-	"foo": (&[]int{}),
9260-	"bar": (&[]int{1, 2}),
9261-	"bal": {3, 4}, // want "redundant type from array, slice, or map composite literal"
9262-}
9263-
9264-var pieces4 = []*Piece{
9265-	{0, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9266-	{1, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9267-	{2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9268-	{3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9269-}
9270-
9271-var _ = map[T]T2{
9272-	{1, 2}: {3, 4}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9273-	{5, 6}: {7, 8}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9274-}
9275-
9276-var _ = map[*T]*T2{
9277-	{1, 2}: {3, 4}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9278-	{5, 6}: {7, 8}, // want "redundant type from array, slice, or map composite literal" "redundant type from array, slice, or map composite literal"
9279-}
9280diff -urN a/gopls/internal/lsp/analysis/simplifyrange/simplifyrange.go b/gopls/internal/lsp/analysis/simplifyrange/simplifyrange.go
9281--- a/gopls/internal/lsp/analysis/simplifyrange/simplifyrange.go	2000-01-01 00:00:00.000000000 -0000
9282+++ b/gopls/internal/lsp/analysis/simplifyrange/simplifyrange.go	1970-01-01 00:00:00.000000000 +0000
9283@@ -1,116 +0,0 @@
9284-// Copyright 2020 The Go Authors. All rights reserved.
9285-// Use of this source code is governed by a BSD-style
9286-// license that can be found in the LICENSE file.
9287-
9288-// Package simplifyrange defines an Analyzer that simplifies range statements.
9289-// https://golang.org/cmd/gofmt/#hdr-The_simplify_command
9290-// https://github.com/golang/go/blob/master/src/cmd/gofmt/simplify.go
9291-package simplifyrange
9292-
9293-import (
9294-	"bytes"
9295-	"go/ast"
9296-	"go/printer"
9297-	"go/token"
9298-
9299-	"golang.org/x/tools/go/analysis"
9300-	"golang.org/x/tools/go/analysis/passes/inspect"
9301-	"golang.org/x/tools/go/ast/inspector"
9302-)
9303-
9304-const Doc = `check for range statement simplifications
9305-
9306-A range of the form:
9307-	for x, _ = range v {...}
9308-will be simplified to:
9309-	for x = range v {...}
9310-
9311-A range of the form:
9312-	for _ = range v {...}
9313-will be simplified to:
9314-	for range v {...}
9315-
9316-This is one of the simplifications that "gofmt -s" applies.`
9317-
9318-var Analyzer = &analysis.Analyzer{
9319-	Name:     "simplifyrange",
9320-	Doc:      Doc,
9321-	Requires: []*analysis.Analyzer{inspect.Analyzer},
9322-	Run:      run,
9323-}
9324-
9325-func run(pass *analysis.Pass) (interface{}, error) {
9326-	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
9327-	nodeFilter := []ast.Node{
9328-		(*ast.RangeStmt)(nil),
9329-	}
9330-	inspect.Preorder(nodeFilter, func(n ast.Node) {
9331-		var copy *ast.RangeStmt
9332-		if stmt, ok := n.(*ast.RangeStmt); ok {
9333-			x := *stmt
9334-			copy = &x
9335-		}
9336-		if copy == nil {
9337-			return
9338-		}
9339-		end := newlineIndex(pass.Fset, copy)
9340-
9341-		// Range statements of the form: for i, _ := range x {}
9342-		var old ast.Expr
9343-		if isBlank(copy.Value) {
9344-			old = copy.Value
9345-			copy.Value = nil
9346-		}
9347-		// Range statements of the form: for _ := range x {}
9348-		if isBlank(copy.Key) && copy.Value == nil {
9349-			old = copy.Key
9350-			copy.Key = nil
9351-		}
9352-		// Return early if neither if condition is met.
9353-		if old == nil {
9354-			return
9355-		}
9356-		pass.Report(analysis.Diagnostic{
9357-			Pos:            old.Pos(),
9358-			End:            old.End(),
9359-			Message:        "simplify range expression",
9360-			SuggestedFixes: suggestedFixes(pass.Fset, copy, end),
9361-		})
9362-	})
9363-	return nil, nil
9364-}
9365-
9366-func suggestedFixes(fset *token.FileSet, rng *ast.RangeStmt, end token.Pos) []analysis.SuggestedFix {
9367-	var b bytes.Buffer
9368-	printer.Fprint(&b, fset, rng)
9369-	stmt := b.Bytes()
9370-	index := bytes.Index(stmt, []byte("\n"))
9371-	// If there is a new line character, then don't replace the body.
9372-	if index != -1 {
9373-		stmt = stmt[:index]
9374-	}
9375-	return []analysis.SuggestedFix{{
9376-		Message: "Remove empty value",
9377-		TextEdits: []analysis.TextEdit{{
9378-			Pos:     rng.Pos(),
9379-			End:     end,
9380-			NewText: stmt[:index],
9381-		}},
9382-	}}
9383-}
9384-
9385-func newlineIndex(fset *token.FileSet, rng *ast.RangeStmt) token.Pos {
9386-	var b bytes.Buffer
9387-	printer.Fprint(&b, fset, rng)
9388-	contents := b.Bytes()
9389-	index := bytes.Index(contents, []byte("\n"))
9390-	if index == -1 {
9391-		return rng.End()
9392-	}
9393-	return rng.Pos() + token.Pos(index)
9394-}
9395-
9396-func isBlank(x ast.Expr) bool {
9397-	ident, ok := x.(*ast.Ident)
9398-	return ok && ident.Name == "_"
9399-}
9400diff -urN a/gopls/internal/lsp/analysis/simplifyrange/simplifyrange_test.go b/gopls/internal/lsp/analysis/simplifyrange/simplifyrange_test.go
9401--- a/gopls/internal/lsp/analysis/simplifyrange/simplifyrange_test.go	2000-01-01 00:00:00.000000000 -0000
9402+++ b/gopls/internal/lsp/analysis/simplifyrange/simplifyrange_test.go	1970-01-01 00:00:00.000000000 +0000
9403@@ -1,17 +0,0 @@
9404-// Copyright 2020 The Go Authors. All rights reserved.
9405-// Use of this source code is governed by a BSD-style
9406-// license that can be found in the LICENSE file.
9407-
9408-package simplifyrange_test
9409-
9410-import (
9411-	"testing"
9412-
9413-	"golang.org/x/tools/go/analysis/analysistest"
9414-	"golang.org/x/tools/gopls/internal/lsp/analysis/simplifyrange"
9415-)
9416-
9417-func Test(t *testing.T) {
9418-	testdata := analysistest.TestData()
9419-	analysistest.RunWithSuggestedFixes(t, testdata, simplifyrange.Analyzer, "a")
9420-}
9421diff -urN a/gopls/internal/lsp/analysis/simplifyrange/testdata/src/a/a.go b/gopls/internal/lsp/analysis/simplifyrange/testdata/src/a/a.go
9422--- a/gopls/internal/lsp/analysis/simplifyrange/testdata/src/a/a.go	2000-01-01 00:00:00.000000000 -0000
9423+++ b/gopls/internal/lsp/analysis/simplifyrange/testdata/src/a/a.go	1970-01-01 00:00:00.000000000 +0000
9424@@ -1,16 +0,0 @@
9425-// Copyright 2020 The Go Authors. All rights reserved.
9426-// Use of this source code is governed by a BSD-style
9427-// license that can be found in the LICENSE file.
9428-
9429-package testdata
9430-
9431-import "log"
9432-
9433-func m() {
9434-	maps := make(map[string]string)
9435-	for k, _ := range maps { // want "simplify range expression"
9436-		log.Println(k)
9437-	}
9438-	for _ = range maps { // want "simplify range expression"
9439-	}
9440-}
9441diff -urN a/gopls/internal/lsp/analysis/simplifyrange/testdata/src/a/a.go.golden b/gopls/internal/lsp/analysis/simplifyrange/testdata/src/a/a.go.golden
9442--- a/gopls/internal/lsp/analysis/simplifyrange/testdata/src/a/a.go.golden	2000-01-01 00:00:00.000000000 -0000
9443+++ b/gopls/internal/lsp/analysis/simplifyrange/testdata/src/a/a.go.golden	1970-01-01 00:00:00.000000000 +0000
9444@@ -1,16 +0,0 @@
9445-// Copyright 2020 The Go Authors. All rights reserved.
9446-// Use of this source code is governed by a BSD-style
9447-// license that can be found in the LICENSE file.
9448-
9449-package testdata
9450-
9451-import "log"
9452-
9453-func m() {
9454-	maps := make(map[string]string)
9455-	for k := range maps { // want "simplify range expression"
9456-		log.Println(k)
9457-	}
9458-	for range maps { // want "simplify range expression"
9459-	}
9460-}
9461diff -urN a/gopls/internal/lsp/analysis/simplifyslice/simplifyslice.go b/gopls/internal/lsp/analysis/simplifyslice/simplifyslice.go
9462--- a/gopls/internal/lsp/analysis/simplifyslice/simplifyslice.go	2000-01-01 00:00:00.000000000 -0000
9463+++ b/gopls/internal/lsp/analysis/simplifyslice/simplifyslice.go	1970-01-01 00:00:00.000000000 +0000
9464@@ -1,94 +0,0 @@
9465-// Copyright 2020 The Go Authors. All rights reserved.
9466-// Use of this source code is governed by a BSD-style
9467-// license that can be found in the LICENSE file.
9468-
9469-// Package simplifyslice defines an Analyzer that simplifies slice statements.
9470-// https://github.com/golang/go/blob/master/src/cmd/gofmt/simplify.go
9471-// https://golang.org/cmd/gofmt/#hdr-The_simplify_command
9472-package simplifyslice
9473-
9474-import (
9475-	"bytes"
9476-	"fmt"
9477-	"go/ast"
9478-	"go/printer"
9479-
9480-	"golang.org/x/tools/go/analysis"
9481-	"golang.org/x/tools/go/analysis/passes/inspect"
9482-	"golang.org/x/tools/go/ast/inspector"
9483-)
9484-
9485-const Doc = `check for slice simplifications
9486-
9487-A slice expression of the form:
9488-	s[a:len(s)]
9489-will be simplified to:
9490-	s[a:]
9491-
9492-This is one of the simplifications that "gofmt -s" applies.`
9493-
9494-var Analyzer = &analysis.Analyzer{
9495-	Name:     "simplifyslice",
9496-	Doc:      Doc,
9497-	Requires: []*analysis.Analyzer{inspect.Analyzer},
9498-	Run:      run,
9499-}
9500-
9501-// Note: We could also simplify slice expressions of the form s[0:b] to s[:b]
9502-//       but we leave them as is since sometimes we want to be very explicit
9503-//       about the lower bound.
9504-// An example where the 0 helps:
9505-//       x, y, z := b[0:2], b[2:4], b[4:6]
9506-// An example where it does not:
9507-//       x, y := b[:n], b[n:]
9508-
9509-func run(pass *analysis.Pass) (interface{}, error) {
9510-	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
9511-	nodeFilter := []ast.Node{
9512-		(*ast.SliceExpr)(nil),
9513-	}
9514-	inspect.Preorder(nodeFilter, func(n ast.Node) {
9515-		expr := n.(*ast.SliceExpr)
9516-		// - 3-index slices always require the 2nd and 3rd index
9517-		if expr.Max != nil {
9518-			return
9519-		}
9520-		s, ok := expr.X.(*ast.Ident)
9521-		// the array/slice object is a single, resolved identifier
9522-		if !ok || s.Obj == nil {
9523-			return
9524-		}
9525-		call, ok := expr.High.(*ast.CallExpr)
9526-		// the high expression is a function call with a single argument
9527-		if !ok || len(call.Args) != 1 || call.Ellipsis.IsValid() {
9528-			return
9529-		}
9530-		fun, ok := call.Fun.(*ast.Ident)
9531-		// the function called is "len" and it is not locally defined; and
9532-		// because we don't have dot imports, it must be the predefined len()
9533-		if !ok || fun.Name != "len" || fun.Obj != nil {
9534-			return
9535-		}
9536-		arg, ok := call.Args[0].(*ast.Ident)
9537-		// the len argument is the array/slice object
9538-		if !ok || arg.Obj != s.Obj {
9539-			return
9540-		}
9541-		var b bytes.Buffer
9542-		printer.Fprint(&b, pass.Fset, expr.High)
9543-		pass.Report(analysis.Diagnostic{
9544-			Pos:     expr.High.Pos(),
9545-			End:     expr.High.End(),
9546-			Message: fmt.Sprintf("unneeded: %s", b.String()),
9547-			SuggestedFixes: []analysis.SuggestedFix{{
9548-				Message: fmt.Sprintf("Remove '%s'", b.String()),
9549-				TextEdits: []analysis.TextEdit{{
9550-					Pos:     expr.High.Pos(),
9551-					End:     expr.High.End(),
9552-					NewText: []byte{},
9553-				}},
9554-			}},
9555-		})
9556-	})
9557-	return nil, nil
9558-}
9559diff -urN a/gopls/internal/lsp/analysis/simplifyslice/simplifyslice_test.go b/gopls/internal/lsp/analysis/simplifyslice/simplifyslice_test.go
9560--- a/gopls/internal/lsp/analysis/simplifyslice/simplifyslice_test.go	2000-01-01 00:00:00.000000000 -0000
9561+++ b/gopls/internal/lsp/analysis/simplifyslice/simplifyslice_test.go	1970-01-01 00:00:00.000000000 +0000
9562@@ -1,22 +0,0 @@
9563-// Copyright 2020 The Go Authors. All rights reserved.
9564-// Use of this source code is governed by a BSD-style
9565-// license that can be found in the LICENSE file.
9566-
9567-package simplifyslice_test
9568-
9569-import (
9570-	"testing"
9571-
9572-	"golang.org/x/tools/go/analysis/analysistest"
9573-	"golang.org/x/tools/gopls/internal/lsp/analysis/simplifyslice"
9574-	"golang.org/x/tools/internal/typeparams"
9575-)
9576-
9577-func Test(t *testing.T) {
9578-	testdata := analysistest.TestData()
9579-	tests := []string{"a"}
9580-	if typeparams.Enabled {
9581-		tests = append(tests, "typeparams")
9582-	}
9583-	analysistest.RunWithSuggestedFixes(t, testdata, simplifyslice.Analyzer, tests...)
9584-}
9585diff -urN a/gopls/internal/lsp/analysis/simplifyslice/testdata/src/a/a.go b/gopls/internal/lsp/analysis/simplifyslice/testdata/src/a/a.go
9586--- a/gopls/internal/lsp/analysis/simplifyslice/testdata/src/a/a.go	2000-01-01 00:00:00.000000000 -0000
9587+++ b/gopls/internal/lsp/analysis/simplifyslice/testdata/src/a/a.go	1970-01-01 00:00:00.000000000 +0000
9588@@ -1,70 +0,0 @@
9589-// Copyright 2020 The Go Authors. All rights reserved.
9590-// Use of this source code is governed by a BSD-style
9591-// license that can be found in the LICENSE file.
9592-
9593-package testdata
9594-
9595-var (
9596-	a [10]byte
9597-	b [20]float32
9598-	s []int
9599-	t struct {
9600-		s []byte
9601-	}
9602-
9603-	_ = a[0:]
9604-	_ = a[1:10]
9605-	_ = a[2:len(a)] // want "unneeded: len\\(a\\)"
9606-	_ = a[3:(len(a))]
9607-	_ = a[len(a)-1 : len(a)] // want "unneeded: len\\(a\\)"
9608-	_ = a[2:len(a):len(a)]
9609-
9610-	_ = a[:]
9611-	_ = a[:10]
9612-	_ = a[:len(a)] // want "unneeded: len\\(a\\)"
9613-	_ = a[:(len(a))]
9614-	_ = a[:len(a)-1]
9615-	_ = a[:len(a):len(a)]
9616-
9617-	_ = s[0:]
9618-	_ = s[1:10]
9619-	_ = s[2:len(s)] // want "unneeded: len\\(s\\)"
9620-	_ = s[3:(len(s))]
9621-	_ = s[len(a) : len(s)-1]
9622-	_ = s[0:len(b)]
9623-	_ = s[2:len(s):len(s)]
9624-
9625-	_ = s[:]
9626-	_ = s[:10]
9627-	_ = s[:len(s)] // want "unneeded: len\\(s\\)"
9628-	_ = s[:(len(s))]
9629-	_ = s[:len(s)-1]
9630-	_ = s[:len(b)]
9631-	_ = s[:len(s):len(s)]
9632-
9633-	_ = t.s[0:]
9634-	_ = t.s[1:10]
9635-	_ = t.s[2:len(t.s)]
9636-	_ = t.s[3:(len(t.s))]
9637-	_ = t.s[len(a) : len(t.s)-1]
9638-	_ = t.s[0:len(b)]
9639-	_ = t.s[2:len(t.s):len(t.s)]
9640-
9641-	_ = t.s[:]
9642-	_ = t.s[:10]
9643-	_ = t.s[:len(t.s)]
9644-	_ = t.s[:(len(t.s))]
9645-	_ = t.s[:len(t.s)-1]
9646-	_ = t.s[:len(b)]
9647-	_ = t.s[:len(t.s):len(t.s)]
9648-)
9649-
9650-func _() {
9651-	s := s[0:len(s)] // want "unneeded: len\\(s\\)"
9652-	_ = s
9653-}
9654-
9655-func m() {
9656-	maps := []int{}
9657-	_ = maps[1:len(maps)] // want "unneeded: len\\(maps\\)"
9658-}
9659diff -urN a/gopls/internal/lsp/analysis/simplifyslice/testdata/src/a/a.go.golden b/gopls/internal/lsp/analysis/simplifyslice/testdata/src/a/a.go.golden
9660--- a/gopls/internal/lsp/analysis/simplifyslice/testdata/src/a/a.go.golden	2000-01-01 00:00:00.000000000 -0000
9661+++ b/gopls/internal/lsp/analysis/simplifyslice/testdata/src/a/a.go.golden	1970-01-01 00:00:00.000000000 +0000
9662@@ -1,70 +0,0 @@
9663-// Copyright 2020 The Go Authors. All rights reserved.
9664-// Use of this source code is governed by a BSD-style
9665-// license that can be found in the LICENSE file.
9666-
9667-package testdata
9668-
9669-var (
9670-	a [10]byte
9671-	b [20]float32
9672-	s []int
9673-	t struct {
9674-		s []byte
9675-	}
9676-
9677-	_ = a[0:]
9678-	_ = a[1:10]
9679-	_ = a[2:] // want "unneeded: len\\(a\\)"
9680-	_ = a[3:(len(a))]
9681-	_ = a[len(a)-1:] // want "unneeded: len\\(a\\)"
9682-	_ = a[2:len(a):len(a)]
9683-
9684-	_ = a[:]
9685-	_ = a[:10]
9686-	_ = a[:] // want "unneeded: len\\(a\\)"
9687-	_ = a[:(len(a))]
9688-	_ = a[:len(a)-1]
9689-	_ = a[:len(a):len(a)]
9690-
9691-	_ = s[0:]
9692-	_ = s[1:10]
9693-	_ = s[2:] // want "unneeded: len\\(s\\)"
9694-	_ = s[3:(len(s))]
9695-	_ = s[len(a) : len(s)-1]
9696-	_ = s[0:len(b)]
9697-	_ = s[2:len(s):len(s)]
9698-
9699-	_ = s[:]
9700-	_ = s[:10]
9701-	_ = s[:] // want "unneeded: len\\(s\\)"
9702-	_ = s[:(len(s))]
9703-	_ = s[:len(s)-1]
9704-	_ = s[:len(b)]
9705-	_ = s[:len(s):len(s)]
9706-
9707-	_ = t.s[0:]
9708-	_ = t.s[1:10]
9709-	_ = t.s[2:len(t.s)]
9710-	_ = t.s[3:(len(t.s))]
9711-	_ = t.s[len(a) : len(t.s)-1]
9712-	_ = t.s[0:len(b)]
9713-	_ = t.s[2:len(t.s):len(t.s)]
9714-
9715-	_ = t.s[:]
9716-	_ = t.s[:10]
9717-	_ = t.s[:len(t.s)]
9718-	_ = t.s[:(len(t.s))]
9719-	_ = t.s[:len(t.s)-1]
9720-	_ = t.s[:len(b)]
9721-	_ = t.s[:len(t.s):len(t.s)]
9722-)
9723-
9724-func _() {
9725-	s := s[0:] // want "unneeded: len\\(s\\)"
9726-	_ = s
9727-}
9728-
9729-func m() {
9730-	maps := []int{}
9731-	_ = maps[1:] // want "unneeded: len\\(maps\\)"
9732-}
9733diff -urN a/gopls/internal/lsp/analysis/simplifyslice/testdata/src/typeparams/typeparams.go b/gopls/internal/lsp/analysis/simplifyslice/testdata/src/typeparams/typeparams.go
9734--- a/gopls/internal/lsp/analysis/simplifyslice/testdata/src/typeparams/typeparams.go	2000-01-01 00:00:00.000000000 -0000
9735+++ b/gopls/internal/lsp/analysis/simplifyslice/testdata/src/typeparams/typeparams.go	1970-01-01 00:00:00.000000000 +0000
9736@@ -1,39 +0,0 @@
9737-// Copyright 2021 The Go Authors. All rights reserved.
9738-// Use of this source code is governed by a BSD-style
9739-// license that can be found in the LICENSE file.
9740-//
9741-//go:build go1.18
9742-// +build go1.18
9743-
9744-package testdata
9745-
9746-type List[E any] []E
9747-
9748-// TODO(suzmue): add a test for generic slice expressions when https://github.com/golang/go/issues/48618 is closed.
9749-// type S interface{ ~[]int }
9750-
9751-var (
9752-	a [10]byte
9753-	b [20]float32
9754-	p List[int]
9755-
9756-	_ = p[0:]
9757-	_ = p[1:10]
9758-	_ = p[2:len(p)] // want "unneeded: len\\(p\\)"
9759-	_ = p[3:(len(p))]
9760-	_ = p[len(a) : len(p)-1]
9761-	_ = p[0:len(b)]
9762-	_ = p[2:len(p):len(p)]
9763-
9764-	_ = p[:]
9765-	_ = p[:10]
9766-	_ = p[:len(p)] // want "unneeded: len\\(p\\)"
9767-	_ = p[:(len(p))]
9768-	_ = p[:len(p)-1]
9769-	_ = p[:len(b)]
9770-	_ = p[:len(p):len(p)]
9771-)
9772-
9773-func foo[E any](a List[E]) {
9774-	_ = a[0:len(a)] // want "unneeded: len\\(a\\)"
9775-}
9776diff -urN a/gopls/internal/lsp/analysis/simplifyslice/testdata/src/typeparams/typeparams.go.golden b/gopls/internal/lsp/analysis/simplifyslice/testdata/src/typeparams/typeparams.go.golden
9777--- a/gopls/internal/lsp/analysis/simplifyslice/testdata/src/typeparams/typeparams.go.golden	2000-01-01 00:00:00.000000000 -0000
9778+++ b/gopls/internal/lsp/analysis/simplifyslice/testdata/src/typeparams/typeparams.go.golden	1970-01-01 00:00:00.000000000 +0000
9779@@ -1,39 +0,0 @@
9780-// Copyright 2021 The Go Authors. All rights reserved.
9781-// Use of this source code is governed by a BSD-style
9782-// license that can be found in the LICENSE file.
9783-//
9784-//go:build go1.18
9785-// +build go1.18
9786-
9787-package testdata
9788-
9789-type List[E any] []E
9790-
9791-// TODO(suzmue): add a test for generic slice expressions when https://github.com/golang/go/issues/48618 is closed.
9792-// type S interface{ ~[]int }
9793-
9794-var (
9795-	a [10]byte
9796-	b [20]float32
9797-	p List[int]
9798-
9799-	_ = p[0:]
9800-	_ = p[1:10]
9801-	_ = p[2:] // want "unneeded: len\\(p\\)"
9802-	_ = p[3:(len(p))]
9803-	_ = p[len(a) : len(p)-1]
9804-	_ = p[0:len(b)]
9805-	_ = p[2:len(p):len(p)]
9806-
9807-	_ = p[:]
9808-	_ = p[:10]
9809-	_ = p[:] // want "unneeded: len\\(p\\)"
9810-	_ = p[:(len(p))]
9811-	_ = p[:len(p)-1]
9812-	_ = p[:len(b)]
9813-	_ = p[:len(p):len(p)]
9814-)
9815-
9816-func foo[E any](a List[E]) {
9817-	_ = a[0:] // want "unneeded: len\\(a\\)"
9818-}
9819diff -urN a/gopls/internal/lsp/analysis/stubmethods/stubmethods.go b/gopls/internal/lsp/analysis/stubmethods/stubmethods.go
9820--- a/gopls/internal/lsp/analysis/stubmethods/stubmethods.go	2000-01-01 00:00:00.000000000 -0000
9821+++ b/gopls/internal/lsp/analysis/stubmethods/stubmethods.go	1970-01-01 00:00:00.000000000 +0000
9822@@ -1,418 +0,0 @@
9823-// Copyright 2022 The Go Authors. All rights reserved.
9824-// Use of this source code is governed by a BSD-style
9825-// license that can be found in the LICENSE file.
9826-
9827-package stubmethods
9828-
9829-import (
9830-	"bytes"
9831-	"fmt"
9832-	"go/ast"
9833-	"go/format"
9834-	"go/token"
9835-	"go/types"
9836-	"strconv"
9837-	"strings"
9838-
9839-	"golang.org/x/tools/go/analysis"
9840-	"golang.org/x/tools/go/analysis/passes/inspect"
9841-	"golang.org/x/tools/go/ast/astutil"
9842-	"golang.org/x/tools/internal/analysisinternal"
9843-	"golang.org/x/tools/internal/typesinternal"
9844-)
9845-
9846-const Doc = `stub methods analyzer
9847-
9848-This analyzer generates method stubs for concrete types
9849-in order to implement a target interface`
9850-
9851-var Analyzer = &analysis.Analyzer{
9852-	Name:             "stubmethods",
9853-	Doc:              Doc,
9854-	Requires:         []*analysis.Analyzer{inspect.Analyzer},
9855-	Run:              run,
9856-	RunDespiteErrors: true,
9857-}
9858-
9859-func run(pass *analysis.Pass) (interface{}, error) {
9860-	for _, err := range pass.TypeErrors {
9861-		ifaceErr := strings.Contains(err.Msg, "missing method") || strings.HasPrefix(err.Msg, "cannot convert")
9862-		if !ifaceErr {
9863-			continue
9864-		}
9865-		var file *ast.File
9866-		for _, f := range pass.Files {
9867-			if f.Pos() <= err.Pos && err.Pos < f.End() {
9868-				file = f
9869-				break
9870-			}
9871-		}
9872-		if file == nil {
9873-			continue
9874-		}
9875-		// Get the end position of the error.
9876-		_, _, endPos, ok := typesinternal.ReadGo116ErrorData(err)
9877-		if !ok {
9878-			var buf bytes.Buffer
9879-			if err := format.Node(&buf, pass.Fset, file); err != nil {
9880-				continue
9881-			}
9882-			endPos = analysisinternal.TypeErrorEndPos(pass.Fset, buf.Bytes(), err.Pos)
9883-		}
9884-		path, _ := astutil.PathEnclosingInterval(file, err.Pos, endPos)
9885-		si := GetStubInfo(pass.Fset, pass.TypesInfo, path, err.Pos)
9886-		if si == nil {
9887-			continue
9888-		}
9889-		qf := RelativeToFiles(si.Concrete.Obj().Pkg(), file, nil, nil)
9890-		pass.Report(analysis.Diagnostic{
9891-			Pos:     err.Pos,
9892-			End:     endPos,
9893-			Message: fmt.Sprintf("Implement %s", types.TypeString(si.Interface.Type(), qf)),
9894-		})
9895-	}
9896-	return nil, nil
9897-}
9898-
9899-// StubInfo represents a concrete type
9900-// that wants to stub out an interface type
9901-type StubInfo struct {
9902-	// Interface is the interface that the client wants to implement.
9903-	// When the interface is defined, the underlying object will be a TypeName.
9904-	// Note that we keep track of types.Object instead of types.Type in order
9905-	// to keep a reference to the declaring object's package and the ast file
9906-	// in the case where the concrete type file requires a new import that happens to be renamed
9907-	// in the interface file.
9908-	// TODO(marwan-at-work): implement interface literals.
9909-	Fset      *token.FileSet // the FileSet used to type-check the types below
9910-	Interface *types.TypeName
9911-	Concrete  *types.Named
9912-	Pointer   bool
9913-}
9914-
9915-// GetStubInfo determines whether the "missing method error"
9916-// can be used to deduced what the concrete and interface types are.
9917-//
9918-// TODO(adonovan): this function (and its following 5 helpers) tries
9919-// to deduce a pair of (concrete, interface) types that are related by
9920-// an assignment, either explictly or through a return statement or
9921-// function call. This is essentially what the refactor/satisfy does,
9922-// more generally. Refactor to share logic, after auditing 'satisfy'
9923-// for safety on ill-typed code.
9924-func GetStubInfo(fset *token.FileSet, ti *types.Info, path []ast.Node, pos token.Pos) *StubInfo {
9925-	for _, n := range path {
9926-		switch n := n.(type) {
9927-		case *ast.ValueSpec:
9928-			return fromValueSpec(fset, ti, n, pos)
9929-		case *ast.ReturnStmt:
9930-			// An error here may not indicate a real error the user should know about, but it may.
9931-			// Therefore, it would be best to log it out for debugging/reporting purposes instead of ignoring
9932-			// it. However, event.Log takes a context which is not passed via the analysis package.
9933-			// TODO(marwan-at-work): properly log this error.
9934-			si, _ := fromReturnStmt(fset, ti, pos, path, n)
9935-			return si
9936-		case *ast.AssignStmt:
9937-			return fromAssignStmt(fset, ti, n, pos)
9938-		case *ast.CallExpr:
9939-			// Note that some call expressions don't carry the interface type
9940-			// because they don't point to a function or method declaration elsewhere.
9941-			// For eaxmple, "var Interface = (*Concrete)(nil)". In that case, continue
9942-			// this loop to encounter other possibilities such as *ast.ValueSpec or others.
9943-			si := fromCallExpr(fset, ti, pos, n)
9944-			if si != nil {
9945-				return si
9946-			}
9947-		}
9948-	}
9949-	return nil
9950-}
9951-
9952-// fromCallExpr tries to find an *ast.CallExpr's function declaration and
9953-// analyzes a function call's signature against the passed in parameter to deduce
9954-// the concrete and interface types.
9955-func fromCallExpr(fset *token.FileSet, ti *types.Info, pos token.Pos, ce *ast.CallExpr) *StubInfo {
9956-	paramIdx := -1
9957-	for i, p := range ce.Args {
9958-		if pos >= p.Pos() && pos <= p.End() {
9959-			paramIdx = i
9960-			break
9961-		}
9962-	}
9963-	if paramIdx == -1 {
9964-		return nil
9965-	}
9966-	p := ce.Args[paramIdx]
9967-	concObj, pointer := concreteType(p, ti)
9968-	if concObj == nil || concObj.Obj().Pkg() == nil {
9969-		return nil
9970-	}
9971-	tv, ok := ti.Types[ce.Fun]
9972-	if !ok {
9973-		return nil
9974-	}
9975-	sig, ok := tv.Type.(*types.Signature)
9976-	if !ok {
9977-		return nil
9978-	}
9979-	sigVar := sig.Params().At(paramIdx)
9980-	iface := ifaceObjFromType(sigVar.Type())
9981-	if iface == nil {
9982-		return nil
9983-	}
9984-	return &StubInfo{
9985-		Fset:      fset,
9986-		Concrete:  concObj,
9987-		Pointer:   pointer,
9988-		Interface: iface,
9989-	}
9990-}
9991-
9992-// fromReturnStmt analyzes a "return" statement to extract
9993-// a concrete type that is trying to be returned as an interface type.
9994-//
9995-// For example, func() io.Writer { return myType{} }
9996-// would return StubInfo with the interface being io.Writer and the concrete type being myType{}.
9997-func fromReturnStmt(fset *token.FileSet, ti *types.Info, pos token.Pos, path []ast.Node, rs *ast.ReturnStmt) (*StubInfo, error) {
9998-	returnIdx := -1
9999-	for i, r := range rs.Results {
10000-		if pos >= r.Pos() && pos <= r.End() {
10001-			returnIdx = i
10002-		}
10003-	}
10004-	if returnIdx == -1 {
10005-		return nil, fmt.Errorf("pos %d not within return statement bounds: [%d-%d]", pos, rs.Pos(), rs.End())
10006-	}
10007-	concObj, pointer := concreteType(rs.Results[returnIdx], ti)
10008-	if concObj == nil || concObj.Obj().Pkg() == nil {
10009-		return nil, nil
10010-	}
10011-	ef := enclosingFunction(path, ti)
10012-	if ef == nil {
10013-		return nil, fmt.Errorf("could not find the enclosing function of the return statement")
10014-	}
10015-	iface := ifaceType(ef.Results.List[returnIdx].Type, ti)
10016-	if iface == nil {
10017-		return nil, nil
10018-	}
10019-	return &StubInfo{
10020-		Fset:      fset,
10021-		Concrete:  concObj,
10022-		Pointer:   pointer,
10023-		Interface: iface,
10024-	}, nil
10025-}
10026-
10027-// fromValueSpec returns *StubInfo from a variable declaration such as
10028-// var x io.Writer = &T{}
10029-func fromValueSpec(fset *token.FileSet, ti *types.Info, vs *ast.ValueSpec, pos token.Pos) *StubInfo {
10030-	var idx int
10031-	for i, vs := range vs.Values {
10032-		if pos >= vs.Pos() && pos <= vs.End() {
10033-			idx = i
10034-			break
10035-		}
10036-	}
10037-
10038-	valueNode := vs.Values[idx]
10039-	ifaceNode := vs.Type
10040-	callExp, ok := valueNode.(*ast.CallExpr)
10041-	// if the ValueSpec is `var _ = myInterface(...)`
10042-	// as opposed to `var _ myInterface = ...`
10043-	if ifaceNode == nil && ok && len(callExp.Args) == 1 {
10044-		ifaceNode = callExp.Fun
10045-		valueNode = callExp.Args[0]
10046-	}
10047-	concObj, pointer := concreteType(valueNode, ti)
10048-	if concObj == nil || concObj.Obj().Pkg() == nil {
10049-		return nil
10050-	}
10051-	ifaceObj := ifaceType(ifaceNode, ti)
10052-	if ifaceObj == nil {
10053-		return nil
10054-	}
10055-	return &StubInfo{
10056-		Fset:      fset,
10057-		Concrete:  concObj,
10058-		Interface: ifaceObj,
10059-		Pointer:   pointer,
10060-	}
10061-}
10062-
10063-// fromAssignStmt returns *StubInfo from a variable re-assignment such as
10064-// var x io.Writer
10065-// x = &T{}
10066-func fromAssignStmt(fset *token.FileSet, ti *types.Info, as *ast.AssignStmt, pos token.Pos) *StubInfo {
10067-	idx := -1
10068-	var lhs, rhs ast.Expr
10069-	// Given a re-assignment interface conversion error,
10070-	// the compiler error shows up on the right hand side of the expression.
10071-	// For example, x = &T{} where x is io.Writer highlights the error
10072-	// under "&T{}" and not "x".
10073-	for i, hs := range as.Rhs {
10074-		if pos >= hs.Pos() && pos <= hs.End() {
10075-			idx = i
10076-			break
10077-		}
10078-	}
10079-	if idx == -1 {
10080-		return nil
10081-	}
10082-	// Technically, this should never happen as
10083-	// we would get a "cannot assign N values to M variables"
10084-	// before we get an interface conversion error. Nonetheless,
10085-	// guard against out of range index errors.
10086-	if idx >= len(as.Lhs) {
10087-		return nil
10088-	}
10089-	lhs, rhs = as.Lhs[idx], as.Rhs[idx]
10090-	ifaceObj := ifaceType(lhs, ti)
10091-	if ifaceObj == nil {
10092-		return nil
10093-	}
10094-	concType, pointer := concreteType(rhs, ti)
10095-	if concType == nil || concType.Obj().Pkg() == nil {
10096-		return nil
10097-	}
10098-	return &StubInfo{
10099-		Fset:      fset,
10100-		Concrete:  concType,
10101-		Interface: ifaceObj,
10102-		Pointer:   pointer,
10103-	}
10104-}
10105-
10106-// RelativeToFiles returns a types.Qualifier that formats package
10107-// names according to the import environments of the files that define
10108-// the concrete type and the interface type. (Only the imports of the
10109-// latter file are provided.)
10110-//
10111-// This is similar to types.RelativeTo except if a file imports the package with a different name,
10112-// then it will use it. And if the file does import the package but it is ignored,
10113-// then it will return the original name. It also prefers package names in importEnv in case
10114-// an import is missing from concFile but is present among importEnv.
10115-//
10116-// Additionally, if missingImport is not nil, the function will be called whenever the concFile
10117-// is presented with a package that is not imported. This is useful so that as types.TypeString is
10118-// formatting a function signature, it is identifying packages that will need to be imported when
10119-// stubbing an interface.
10120-//
10121-// TODO(rfindley): investigate if this can be merged with source.Qualifier.
10122-func RelativeToFiles(concPkg *types.Package, concFile *ast.File, ifaceImports []*ast.ImportSpec, missingImport func(name, path string)) types.Qualifier {
10123-	return func(other *types.Package) string {
10124-		if other == concPkg {
10125-			return ""
10126-		}
10127-
10128-		// Check if the concrete file already has the given import,
10129-		// if so return the default package name or the renamed import statement.
10130-		for _, imp := range concFile.Imports {
10131-			impPath, _ := strconv.Unquote(imp.Path.Value)
10132-			isIgnored := imp.Name != nil && (imp.Name.Name == "." || imp.Name.Name == "_")
10133-			// TODO(adonovan): this comparison disregards a vendor prefix in 'other'.
10134-			if impPath == other.Path() && !isIgnored {
10135-				importName := other.Name()
10136-				if imp.Name != nil {
10137-					importName = imp.Name.Name
10138-				}
10139-				return importName
10140-			}
10141-		}
10142-
10143-		// If the concrete file does not have the import, check if the package
10144-		// is renamed in the interface file and prefer that.
10145-		var importName string
10146-		for _, imp := range ifaceImports {
10147-			impPath, _ := strconv.Unquote(imp.Path.Value)
10148-			isIgnored := imp.Name != nil && (imp.Name.Name == "." || imp.Name.Name == "_")
10149-			// TODO(adonovan): this comparison disregards a vendor prefix in 'other'.
10150-			if impPath == other.Path() && !isIgnored {
10151-				if imp.Name != nil && imp.Name.Name != concPkg.Name() {
10152-					importName = imp.Name.Name
10153-				}
10154-				break
10155-			}
10156-		}
10157-
10158-		if missingImport != nil {
10159-			missingImport(importName, other.Path())
10160-		}
10161-
10162-		// Up until this point, importName must stay empty when calling missingImport,
10163-		// otherwise we'd end up with `import time "time"` which doesn't look idiomatic.
10164-		if importName == "" {
10165-			importName = other.Name()
10166-		}
10167-		return importName
10168-	}
10169-}
10170-
10171-// ifaceType will try to extract the types.Object that defines
10172-// the interface given the ast.Expr where the "missing method"
10173-// or "conversion" errors happen.
10174-func ifaceType(n ast.Expr, ti *types.Info) *types.TypeName {
10175-	tv, ok := ti.Types[n]
10176-	if !ok {
10177-		return nil
10178-	}
10179-	return ifaceObjFromType(tv.Type)
10180-}
10181-
10182-func ifaceObjFromType(t types.Type) *types.TypeName {
10183-	named, ok := t.(*types.Named)
10184-	if !ok {
10185-		return nil
10186-	}
10187-	_, ok = named.Underlying().(*types.Interface)
10188-	if !ok {
10189-		return nil
10190-	}
10191-	// Interfaces defined in the "builtin" package return nil a Pkg().
10192-	// But they are still real interfaces that we need to make a special case for.
10193-	// Therefore, protect gopls from panicking if a new interface type was added in the future.
10194-	if named.Obj().Pkg() == nil && named.Obj().Name() != "error" {
10195-		return nil
10196-	}
10197-	return named.Obj()
10198-}
10199-
10200-// concreteType tries to extract the *types.Named that defines
10201-// the concrete type given the ast.Expr where the "missing method"
10202-// or "conversion" errors happened. If the concrete type is something
10203-// that cannot have methods defined on it (such as basic types), this
10204-// method will return a nil *types.Named. The second return parameter
10205-// is a boolean that indicates whether the concreteType was defined as a
10206-// pointer or value.
10207-func concreteType(n ast.Expr, ti *types.Info) (*types.Named, bool) {
10208-	tv, ok := ti.Types[n]
10209-	if !ok {
10210-		return nil, false
10211-	}
10212-	typ := tv.Type
10213-	ptr, isPtr := typ.(*types.Pointer)
10214-	if isPtr {
10215-		typ = ptr.Elem()
10216-	}
10217-	named, ok := typ.(*types.Named)
10218-	if !ok {
10219-		return nil, false
10220-	}
10221-	return named, isPtr
10222-}
10223-
10224-// enclosingFunction returns the signature and type of the function
10225-// enclosing the given position.
10226-func enclosingFunction(path []ast.Node, info *types.Info) *ast.FuncType {
10227-	for _, node := range path {
10228-		switch t := node.(type) {
10229-		case *ast.FuncDecl:
10230-			if _, ok := info.Defs[t.Name]; ok {
10231-				return t.Type
10232-			}
10233-		case *ast.FuncLit:
10234-			if _, ok := info.Types[t]; ok {
10235-				return t.Type
10236-			}
10237-		}
10238-	}
10239-	return nil
10240-}
10241diff -urN a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/a.go b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/a.go
10242--- a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/a.go	2000-01-01 00:00:00.000000000 -0000
10243+++ b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/a.go	1970-01-01 00:00:00.000000000 +0000
10244@@ -1,28 +0,0 @@
10245-// Copyright 2020 The Go Authors. All rights reserved.
10246-// Use of this source code is governed by a BSD-style
10247-// license that can be found in the LICENSE file.
10248-
10249-package undeclared
10250-
10251-func x() int {
10252-	var z int
10253-	z = y // want "(undeclared name|undefined): y"
10254-
10255-	if z == m { // want "(undeclared name|undefined): m"
10256-		z = 1
10257-	}
10258-
10259-	if z == 1 {
10260-		z = 1
10261-	} else if z == n+1 { // want "(undeclared name|undefined): n"
10262-		z = 1
10263-	}
10264-
10265-	switch z {
10266-	case 10:
10267-		z = 1
10268-	case a: // want "(undeclared name|undefined): a"
10269-		z = 1
10270-	}
10271-	return z
10272-}
10273diff -urN a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/channels.go b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/channels.go
10274--- a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/channels.go	2000-01-01 00:00:00.000000000 -0000
10275+++ b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/channels.go	1970-01-01 00:00:00.000000000 +0000
10276@@ -1,13 +0,0 @@
10277-// Copyright 2021 The Go Authors. All rights reserved.
10278-// Use of this source code is governed by a BSD-style
10279-// license that can be found in the LICENSE file.
10280-
10281-package undeclared
10282-
10283-func channels(s string) {
10284-	undefinedChannels(c()) // want "(undeclared name|undefined): undefinedChannels"
10285-}
10286-
10287-func c() (<-chan string, chan string) {
10288-	return make(<-chan string), make(chan string)
10289-}
10290diff -urN a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/consecutive_params.go b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/consecutive_params.go
10291--- a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/consecutive_params.go	2000-01-01 00:00:00.000000000 -0000
10292+++ b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/consecutive_params.go	1970-01-01 00:00:00.000000000 +0000
10293@@ -1,10 +0,0 @@
10294-// Copyright 2021 The Go Authors. All rights reserved.
10295-// Use of this source code is governed by a BSD-style
10296-// license that can be found in the LICENSE file.
10297-
10298-package undeclared
10299-
10300-func consecutiveParams() {
10301-	var s string
10302-	undefinedConsecutiveParams(s, s) // want "(undeclared name|undefined): undefinedConsecutiveParams"
10303-}
10304diff -urN a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/error_param.go b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/error_param.go
10305--- a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/error_param.go	2000-01-01 00:00:00.000000000 -0000
10306+++ b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/error_param.go	1970-01-01 00:00:00.000000000 +0000
10307@@ -1,10 +0,0 @@
10308-// Copyright 2021 The Go Authors. All rights reserved.
10309-// Use of this source code is governed by a BSD-style
10310-// license that can be found in the LICENSE file.
10311-
10312-package undeclared
10313-
10314-func errorParam() {
10315-	var err error
10316-	undefinedErrorParam(err) // want "(undeclared name|undefined): undefinedErrorParam"
10317-}
10318diff -urN a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/literals.go b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/literals.go
10319--- a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/literals.go	2000-01-01 00:00:00.000000000 -0000
10320+++ b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/literals.go	1970-01-01 00:00:00.000000000 +0000
10321@@ -1,11 +0,0 @@
10322-// Copyright 2021 The Go Authors. All rights reserved.
10323-// Use of this source code is governed by a BSD-style
10324-// license that can be found in the LICENSE file.
10325-
10326-package undeclared
10327-
10328-type T struct{}
10329-
10330-func literals() {
10331-	undefinedLiterals("hey compiler", T{}, &T{}) // want "(undeclared name|undefined): undefinedLiterals"
10332-}
10333diff -urN a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/operation.go b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/operation.go
10334--- a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/operation.go	2000-01-01 00:00:00.000000000 -0000
10335+++ b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/operation.go	1970-01-01 00:00:00.000000000 +0000
10336@@ -1,11 +0,0 @@
10337-// Copyright 2021 The Go Authors. All rights reserved.
10338-// Use of this source code is governed by a BSD-style
10339-// license that can be found in the LICENSE file.
10340-
10341-package undeclared
10342-
10343-import "time"
10344-
10345-func operation() {
10346-	undefinedOperation(10 * time.Second) // want "(undeclared name|undefined): undefinedOperation"
10347-}
10348diff -urN a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/selector.go b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/selector.go
10349--- a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/selector.go	2000-01-01 00:00:00.000000000 -0000
10350+++ b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/selector.go	1970-01-01 00:00:00.000000000 +0000
10351@@ -1,10 +0,0 @@
10352-// Copyright 2021 The Go Authors. All rights reserved.
10353-// Use of this source code is governed by a BSD-style
10354-// license that can be found in the LICENSE file.
10355-
10356-package undeclared
10357-
10358-func selector() {
10359-	m := map[int]bool{}
10360-	undefinedSelector(m[1]) // want "(undeclared name|undefined): undefinedSelector"
10361-}
10362diff -urN a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/slice.go b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/slice.go
10363--- a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/slice.go	2000-01-01 00:00:00.000000000 -0000
10364+++ b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/slice.go	1970-01-01 00:00:00.000000000 +0000
10365@@ -1,9 +0,0 @@
10366-// Copyright 2021 The Go Authors. All rights reserved.
10367-// Use of this source code is governed by a BSD-style
10368-// license that can be found in the LICENSE file.
10369-
10370-package undeclared
10371-
10372-func slice() {
10373-	undefinedSlice([]int{1, 2}) // want "(undeclared name|undefined): undefinedSlice"
10374-}
10375diff -urN a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/tuple.go b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/tuple.go
10376--- a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/tuple.go	2000-01-01 00:00:00.000000000 -0000
10377+++ b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/tuple.go	1970-01-01 00:00:00.000000000 +0000
10378@@ -1,13 +0,0 @@
10379-// Copyright 2021 The Go Authors. All rights reserved.
10380-// Use of this source code is governed by a BSD-style
10381-// license that can be found in the LICENSE file.
10382-
10383-package undeclared
10384-
10385-func tuple() {
10386-	undefinedTuple(b()) // want "(undeclared name|undefined): undefinedTuple"
10387-}
10388-
10389-func b() (string, error) {
10390-	return "", nil
10391-}
10392diff -urN a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/unique_params.go b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/unique_params.go
10393--- a/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/unique_params.go	2000-01-01 00:00:00.000000000 -0000
10394+++ b/gopls/internal/lsp/analysis/undeclaredname/testdata/src/a/unique_params.go	1970-01-01 00:00:00.000000000 +0000
10395@@ -1,11 +0,0 @@
10396-// Copyright 2021 The Go Authors. All rights reserved.
10397-// Use of this source code is governed by a BSD-style
10398-// license that can be found in the LICENSE file.
10399-
10400-package undeclared
10401-
10402-func uniqueArguments() {
10403-	var s string
10404-	var i int
10405-	undefinedUniqueArguments(s, i, s) // want "(undeclared name|undefined): undefinedUniqueArguments"
10406-}
10407diff -urN a/gopls/internal/lsp/analysis/undeclaredname/undeclared.go b/gopls/internal/lsp/analysis/undeclaredname/undeclared.go
10408--- a/gopls/internal/lsp/analysis/undeclaredname/undeclared.go	2000-01-01 00:00:00.000000000 -0000
10409+++ b/gopls/internal/lsp/analysis/undeclaredname/undeclared.go	1970-01-01 00:00:00.000000000 +0000
10410@@ -1,347 +0,0 @@
10411-// Copyright 2020 The Go Authors. All rights reserved.
10412-// Use of this source code is governed by a BSD-style
10413-// license that can be found in the LICENSE file.
10414-
10415-// Package undeclaredname defines an Analyzer that applies suggested fixes
10416-// to errors of the type "undeclared name: %s".
10417-package undeclaredname
10418-
10419-import (
10420-	"bytes"
10421-	"fmt"
10422-	"go/ast"
10423-	"go/format"
10424-	"go/token"
10425-	"go/types"
10426-	"strings"
10427-	"unicode"
10428-
10429-	"golang.org/x/tools/go/analysis"
10430-	"golang.org/x/tools/go/ast/astutil"
10431-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
10432-	"golang.org/x/tools/internal/analysisinternal"
10433-)
10434-
10435-const Doc = `suggested fixes for "undeclared name: <>"
10436-
10437-This checker provides suggested fixes for type errors of the
10438-type "undeclared name: <>". It will either insert a new statement,
10439-such as:
10440-
10441-"<> := "
10442-
10443-or a new function declaration, such as:
10444-
10445-func <>(inferred parameters) {
10446-	panic("implement me!")
10447-}
10448-`
10449-
10450-var Analyzer = &analysis.Analyzer{
10451-	Name:             "undeclaredname",
10452-	Doc:              Doc,
10453-	Requires:         []*analysis.Analyzer{},
10454-	Run:              run,
10455-	RunDespiteErrors: true,
10456-}
10457-
10458-// The prefix for this error message changed in Go 1.20.
10459-var undeclaredNamePrefixes = []string{"undeclared name: ", "undefined: "}
10460-
10461-func run(pass *analysis.Pass) (interface{}, error) {
10462-	for _, err := range pass.TypeErrors {
10463-		runForError(pass, err)
10464-	}
10465-	return nil, nil
10466-}
10467-
10468-func runForError(pass *analysis.Pass, err types.Error) {
10469-	var name string
10470-	for _, prefix := range undeclaredNamePrefixes {
10471-		if !strings.HasPrefix(err.Msg, prefix) {
10472-			continue
10473-		}
10474-		name = strings.TrimPrefix(err.Msg, prefix)
10475-	}
10476-	if name == "" {
10477-		return
10478-	}
10479-	var file *ast.File
10480-	for _, f := range pass.Files {
10481-		if f.Pos() <= err.Pos && err.Pos < f.End() {
10482-			file = f
10483-			break
10484-		}
10485-	}
10486-	if file == nil {
10487-		return
10488-	}
10489-
10490-	// Get the path for the relevant range.
10491-	path, _ := astutil.PathEnclosingInterval(file, err.Pos, err.Pos)
10492-	if len(path) < 2 {
10493-		return
10494-	}
10495-	ident, ok := path[0].(*ast.Ident)
10496-	if !ok || ident.Name != name {
10497-		return
10498-	}
10499-
10500-	// Undeclared quick fixes only work in function bodies.
10501-	inFunc := false
10502-	for i := range path {
10503-		if _, inFunc = path[i].(*ast.FuncDecl); inFunc {
10504-			if i == 0 {
10505-				return
10506-			}
10507-			if _, isBody := path[i-1].(*ast.BlockStmt); !isBody {
10508-				return
10509-			}
10510-			break
10511-		}
10512-	}
10513-	if !inFunc {
10514-		return
10515-	}
10516-	// Skip selector expressions because it might be too complex
10517-	// to try and provide a suggested fix for fields and methods.
10518-	if _, ok := path[1].(*ast.SelectorExpr); ok {
10519-		return
10520-	}
10521-	tok := pass.Fset.File(file.Pos())
10522-	if tok == nil {
10523-		return
10524-	}
10525-	offset := safetoken.StartPosition(pass.Fset, err.Pos).Offset
10526-	end := tok.Pos(offset + len(name)) // TODO(adonovan): dubious! err.Pos + len(name)??
10527-	pass.Report(analysis.Diagnostic{
10528-		Pos:     err.Pos,
10529-		End:     end,
10530-		Message: err.Msg,
10531-	})
10532-}
10533-
10534-func SuggestedFix(fset *token.FileSet, start, end token.Pos, content []byte, file *ast.File, pkg *types.Package, info *types.Info) (*analysis.SuggestedFix, error) {
10535-	pos := start // don't use the end
10536-	path, _ := astutil.PathEnclosingInterval(file, pos, pos)
10537-	if len(path) < 2 {
10538-		return nil, fmt.Errorf("no expression found")
10539-	}
10540-	ident, ok := path[0].(*ast.Ident)
10541-	if !ok {
10542-		return nil, fmt.Errorf("no identifier found")
10543-	}
10544-
10545-	// Check for a possible call expression, in which case we should add a
10546-	// new function declaration.
10547-	if len(path) > 1 {
10548-		if _, ok := path[1].(*ast.CallExpr); ok {
10549-			return newFunctionDeclaration(path, file, pkg, info, fset)
10550-		}
10551-	}
10552-
10553-	// Get the place to insert the new statement.
10554-	insertBeforeStmt := analysisinternal.StmtToInsertVarBefore(path)
10555-	if insertBeforeStmt == nil {
10556-		return nil, fmt.Errorf("could not locate insertion point")
10557-	}
10558-
10559-	insertBefore := safetoken.StartPosition(fset, insertBeforeStmt.Pos()).Offset
10560-
10561-	// Get the indent to add on the line after the new statement.
10562-	// Since this will have a parse error, we can not use format.Source().
10563-	contentBeforeStmt, indent := content[:insertBefore], "\n"
10564-	if nl := bytes.LastIndex(contentBeforeStmt, []byte("\n")); nl != -1 {
10565-		indent = string(contentBeforeStmt[nl:])
10566-	}
10567-
10568-	// Create the new local variable statement.
10569-	newStmt := fmt.Sprintf("%s := %s", ident.Name, indent)
10570-	return &analysis.SuggestedFix{
10571-		Message: fmt.Sprintf("Create variable \"%s\"", ident.Name),
10572-		TextEdits: []analysis.TextEdit{{
10573-			Pos:     insertBeforeStmt.Pos(),
10574-			End:     insertBeforeStmt.Pos(),
10575-			NewText: []byte(newStmt),
10576-		}},
10577-	}, nil
10578-}
10579-
10580-func newFunctionDeclaration(path []ast.Node, file *ast.File, pkg *types.Package, info *types.Info, fset *token.FileSet) (*analysis.SuggestedFix, error) {
10581-	if len(path) < 3 {
10582-		return nil, fmt.Errorf("unexpected set of enclosing nodes: %v", path)
10583-	}
10584-	ident, ok := path[0].(*ast.Ident)
10585-	if !ok {
10586-		return nil, fmt.Errorf("no name for function declaration %v (%T)", path[0], path[0])
10587-	}
10588-	call, ok := path[1].(*ast.CallExpr)
10589-	if !ok {
10590-		return nil, fmt.Errorf("no call expression found %v (%T)", path[1], path[1])
10591-	}
10592-
10593-	// Find the enclosing function, so that we can add the new declaration
10594-	// below.
10595-	var enclosing *ast.FuncDecl
10596-	for _, n := range path {
10597-		if n, ok := n.(*ast.FuncDecl); ok {
10598-			enclosing = n
10599-			break
10600-		}
10601-	}
10602-	// TODO(rstambler): Support the situation when there is no enclosing
10603-	// function.
10604-	if enclosing == nil {
10605-		return nil, fmt.Errorf("no enclosing function found: %v", path)
10606-	}
10607-
10608-	pos := enclosing.End()
10609-
10610-	var paramNames []string
10611-	var paramTypes []types.Type
10612-	// keep track of all param names to later ensure uniqueness
10613-	nameCounts := map[string]int{}
10614-	for _, arg := range call.Args {
10615-		typ := info.TypeOf(arg)
10616-		if typ == nil {
10617-			return nil, fmt.Errorf("unable to determine type for %s", arg)
10618-		}
10619-
10620-		switch t := typ.(type) {
10621-		// this is the case where another function call returning multiple
10622-		// results is used as an argument
10623-		case *types.Tuple:
10624-			n := t.Len()
10625-			for i := 0; i < n; i++ {
10626-				name := typeToArgName(t.At(i).Type())
10627-				nameCounts[name]++
10628-
10629-				paramNames = append(paramNames, name)
10630-				paramTypes = append(paramTypes, types.Default(t.At(i).Type()))
10631-			}
10632-
10633-		default:
10634-			// does the argument have a name we can reuse?
10635-			// only happens in case of a *ast.Ident
10636-			var name string
10637-			if ident, ok := arg.(*ast.Ident); ok {
10638-				name = ident.Name
10639-			}
10640-
10641-			if name == "" {
10642-				name = typeToArgName(typ)
10643-			}
10644-
10645-			nameCounts[name]++
10646-
10647-			paramNames = append(paramNames, name)
10648-			paramTypes = append(paramTypes, types.Default(typ))
10649-		}
10650-	}
10651-
10652-	for n, c := range nameCounts {
10653-		// Any names we saw more than once will need a unique suffix added
10654-		// on. Reset the count to 1 to act as the suffix for the first
10655-		// occurrence of that name.
10656-		if c >= 2 {
10657-			nameCounts[n] = 1
10658-		} else {
10659-			delete(nameCounts, n)
10660-		}
10661-	}
10662-
10663-	params := &ast.FieldList{}
10664-
10665-	for i, name := range paramNames {
10666-		if suffix, repeats := nameCounts[name]; repeats {
10667-			nameCounts[name]++
10668-			name = fmt.Sprintf("%s%d", name, suffix)
10669-		}
10670-
10671-		// only worth checking after previous param in the list
10672-		if i > 0 {
10673-			// if type of parameter at hand is the same as the previous one,
10674-			// add it to the previous param list of identifiers so to have:
10675-			//  (s1, s2 string)
10676-			// and not
10677-			//  (s1 string, s2 string)
10678-			if paramTypes[i] == paramTypes[i-1] {
10679-				params.List[len(params.List)-1].Names = append(params.List[len(params.List)-1].Names, ast.NewIdent(name))
10680-				continue
10681-			}
10682-		}
10683-
10684-		params.List = append(params.List, &ast.Field{
10685-			Names: []*ast.Ident{
10686-				ast.NewIdent(name),
10687-			},
10688-			Type: analysisinternal.TypeExpr(file, pkg, paramTypes[i]),
10689-		})
10690-	}
10691-
10692-	decl := &ast.FuncDecl{
10693-		Name: ast.NewIdent(ident.Name),
10694-		Type: &ast.FuncType{
10695-			Params: params,
10696-			// TODO(rstambler): Also handle result parameters here.
10697-		},
10698-		Body: &ast.BlockStmt{
10699-			List: []ast.Stmt{
10700-				&ast.ExprStmt{
10701-					X: &ast.CallExpr{
10702-						Fun: ast.NewIdent("panic"),
10703-						Args: []ast.Expr{
10704-							&ast.BasicLit{
10705-								Value: `"unimplemented"`,
10706-							},
10707-						},
10708-					},
10709-				},
10710-			},
10711-		},
10712-	}
10713-
10714-	b := bytes.NewBufferString("\n\n")
10715-	if err := format.Node(b, fset, decl); err != nil {
10716-		return nil, err
10717-	}
10718-	return &analysis.SuggestedFix{
10719-		Message: fmt.Sprintf("Create function \"%s\"", ident.Name),
10720-		TextEdits: []analysis.TextEdit{{
10721-			Pos:     pos,
10722-			End:     pos,
10723-			NewText: b.Bytes(),
10724-		}},
10725-	}, nil
10726-}
10727-func typeToArgName(ty types.Type) string {
10728-	s := types.Default(ty).String()
10729-
10730-	switch t := ty.(type) {
10731-	case *types.Basic:
10732-		// use first letter in type name for basic types
10733-		return s[0:1]
10734-	case *types.Slice:
10735-		// use element type to decide var name for slices
10736-		return typeToArgName(t.Elem())
10737-	case *types.Array:
10738-		// use element type to decide var name for arrays
10739-		return typeToArgName(t.Elem())
10740-	case *types.Chan:
10741-		return "ch"
10742-	}
10743-
10744-	s = strings.TrimFunc(s, func(r rune) bool {
10745-		return !unicode.IsLetter(r)
10746-	})
10747-
10748-	if s == "error" {
10749-		return "err"
10750-	}
10751-
10752-	// remove package (if present)
10753-	// and make first letter lowercase
10754-	a := []rune(s[strings.LastIndexByte(s, '.')+1:])
10755-	a[0] = unicode.ToLower(a[0])
10756-	return string(a)
10757-}
10758diff -urN a/gopls/internal/lsp/analysis/undeclaredname/undeclared_test.go b/gopls/internal/lsp/analysis/undeclaredname/undeclared_test.go
10759--- a/gopls/internal/lsp/analysis/undeclaredname/undeclared_test.go	2000-01-01 00:00:00.000000000 -0000
10760+++ b/gopls/internal/lsp/analysis/undeclaredname/undeclared_test.go	1970-01-01 00:00:00.000000000 +0000
10761@@ -1,17 +0,0 @@
10762-// Copyright 2020 The Go Authors. All rights reserved.
10763-// Use of this source code is governed by a BSD-style
10764-// license that can be found in the LICENSE file.
10765-
10766-package undeclaredname_test
10767-
10768-import (
10769-	"testing"
10770-
10771-	"golang.org/x/tools/go/analysis/analysistest"
10772-	"golang.org/x/tools/gopls/internal/lsp/analysis/undeclaredname"
10773-)
10774-
10775-func Test(t *testing.T) {
10776-	testdata := analysistest.TestData()
10777-	analysistest.Run(t, testdata, undeclaredname.Analyzer, "a")
10778-}
10779diff -urN a/gopls/internal/lsp/analysis/unusedparams/testdata/src/a/a.go b/gopls/internal/lsp/analysis/unusedparams/testdata/src/a/a.go
10780--- a/gopls/internal/lsp/analysis/unusedparams/testdata/src/a/a.go	2000-01-01 00:00:00.000000000 -0000
10781+++ b/gopls/internal/lsp/analysis/unusedparams/testdata/src/a/a.go	1970-01-01 00:00:00.000000000 +0000
10782@@ -1,55 +0,0 @@
10783-// Copyright 2022 The Go Authors. All rights reserved.
10784-// Use of this source code is governed by a BSD-style
10785-// license that can be found in the LICENSE file.
10786-
10787-package a
10788-
10789-import (
10790-	"bytes"
10791-	"fmt"
10792-	"net/http"
10793-)
10794-
10795-type parent interface {
10796-	n(f bool)
10797-}
10798-
10799-type yuh struct {
10800-	a int
10801-}
10802-
10803-func (y *yuh) n(f bool) {
10804-	for i := 0; i < 10; i++ {
10805-		fmt.Println(i)
10806-	}
10807-}
10808-
10809-func a(i1 int, i2 int, i3 int) int { // want "potentially unused parameter: 'i2'"
10810-	i3 += i1
10811-	_ = func(z int) int { // want "potentially unused parameter: 'z'"
10812-		_ = 1
10813-		return 1
10814-	}
10815-	return i3
10816-}
10817-
10818-func b(c bytes.Buffer) { // want "potentially unused parameter: 'c'"
10819-	_ = 1
10820-}
10821-
10822-func z(h http.ResponseWriter, _ *http.Request) { // want "potentially unused parameter: 'h'"
10823-	fmt.Println("Before")
10824-}
10825-
10826-func l(h http.Handler) http.Handler {
10827-	return http.HandlerFunc(z)
10828-}
10829-
10830-func mult(a, b int) int { // want "potentially unused parameter: 'b'"
10831-	a += 1
10832-	return a
10833-}
10834-
10835-func y(a int) {
10836-	panic("yo")
10837-}
10838diff -urN a/gopls/internal/lsp/analysis/unusedparams/testdata/src/a/a.go.golden b/gopls/internal/lsp/analysis/unusedparams/testdata/src/a/a.go.golden
10839--- a/gopls/internal/lsp/analysis/unusedparams/testdata/src/a/a.go.golden	2000-01-01 00:00:00.000000000 -0000
10840+++ b/gopls/internal/lsp/analysis/unusedparams/testdata/src/a/a.go.golden	1970-01-01 00:00:00.000000000 +0000
10841@@ -1,55 +0,0 @@
10842-// Copyright 2022 The Go Authors. All rights reserved.
10843-// Use of this source code is governed by a BSD-style
10844-// license that can be found in the LICENSE file.
10845-
10846-package a
10847-
10848-import (
10849-	"bytes"
10850-	"fmt"
10851-	"net/http"
10852-)
10853-
10854-type parent interface {
10855-	n(f bool)
10856-}
10857-
10858-type yuh struct {
10859-	a int
10860-}
10861-
10862-func (y *yuh) n(f bool) {
10863-	for i := 0; i < 10; i++ {
10864-		fmt.Println(i)
10865-	}
10866-}
10867-
10868-func a(i1 int, _ int, i3 int) int { // want "potentially unused parameter: 'i2'"
10869-	i3 += i1
10870-	_ = func(_ int) int { // want "potentially unused parameter: 'z'"
10871-		_ = 1
10872-		return 1
10873-	}
10874-	return i3
10875-}
10876-
10877-func b(_ bytes.Buffer) { // want "potentially unused parameter: 'c'"
10878-	_ = 1
10879-}
10880-
10881-func z(_ http.ResponseWriter, _ *http.Request) { // want "potentially unused parameter: 'h'"
10882-	fmt.Println("Before")
10883-}
10884-
10885-func l(h http.Handler) http.Handler {
10886-	return http.HandlerFunc(z)
10887-}
10888-
10889-func mult(a, _ int) int { // want "potentially unused parameter: 'b'"
10890-	a += 1
10891-	return a
10892-}
10893-
10894-func y(a int) {
10895-	panic("yo")
10896-}
10897diff -urN a/gopls/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go b/gopls/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go
10898--- a/gopls/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go	2000-01-01 00:00:00.000000000 -0000
10899+++ b/gopls/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go	1970-01-01 00:00:00.000000000 +0000
10900@@ -1,55 +0,0 @@
10901-// Copyright 2022 The Go Authors. All rights reserved.
10902-// Use of this source code is governed by a BSD-style
10903-// license that can be found in the LICENSE file.
10904-
10905-package typeparams
10906-
10907-import (
10908-	"bytes"
10909-	"fmt"
10910-	"net/http"
10911-)
10912-
10913-type parent[T any] interface {
10914-	n(f T)
10915-}
10916-
10917-type yuh[T any] struct {
10918-	a T
10919-}
10920-
10921-func (y *yuh[int]) n(f bool) {
10922-	for i := 0; i < 10; i++ {
10923-		fmt.Println(i)
10924-	}
10925-}
10926-
10927-func a[T comparable](i1 int, i2 T, i3 int) int { // want "potentially unused parameter: 'i2'"
10928-	i3 += i1
10929-	_ = func(z int) int { // want "potentially unused parameter: 'z'"
10930-		_ = 1
10931-		return 1
10932-	}
10933-	return i3
10934-}
10935-
10936-func b[T any](c bytes.Buffer) { // want "potentially unused parameter: 'c'"
10937-	_ = 1
10938-}
10939-
10940-func z[T http.ResponseWriter](h T, _ *http.Request) { // want "potentially unused parameter: 'h'"
10941-	fmt.Println("Before")
10942-}
10943-
10944-func l(h http.Handler) http.Handler {
10945-	return http.HandlerFunc(z[http.ResponseWriter])
10946-}
10947-
10948-func mult(a, b int) int { // want "potentially unused parameter: 'b'"
10949-	a += 1
10950-	return a
10951-}
10952-
10953-func y[T any](a T) {
10954-	panic("yo")
10955-}
10956diff -urN a/gopls/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go.golden b/gopls/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go.golden
10957--- a/gopls/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go.golden	2000-01-01 00:00:00.000000000 -0000
10958+++ b/gopls/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go.golden	1970-01-01 00:00:00.000000000 +0000
10959@@ -1,55 +0,0 @@
10960-// Copyright 2022 The Go Authors. All rights reserved.
10961-// Use of this source code is governed by a BSD-style
10962-// license that can be found in the LICENSE file.
10963-
10964-package typeparams
10965-
10966-import (
10967-	"bytes"
10968-	"fmt"
10969-	"net/http"
10970-)
10971-
10972-type parent[T any] interface {
10973-	n(f T)
10974-}
10975-
10976-type yuh[T any] struct {
10977-	a T
10978-}
10979-
10980-func (y *yuh[int]) n(f bool) {
10981-	for i := 0; i < 10; i++ {
10982-		fmt.Println(i)
10983-	}
10984-}
10985-
10986-func a[T comparable](i1 int, _ T, i3 int) int { // want "potentially unused parameter: 'i2'"
10987-	i3 += i1
10988-	_ = func(_ int) int { // want "potentially unused parameter: 'z'"
10989-		_ = 1
10990-		return 1
10991-	}
10992-	return i3
10993-}
10994-
10995-func b[T any](_ bytes.Buffer) { // want "potentially unused parameter: 'c'"
10996-	_ = 1
10997-}
10998-
10999-func z[T http.ResponseWriter](_ T, _ *http.Request) { // want "potentially unused parameter: 'h'"
11000-	fmt.Println("Before")
11001-}
11002-
11003-func l(h http.Handler) http.Handler {
11004-	return http.HandlerFunc(z[http.ResponseWriter])
11005-}
11006-
11007-func mult(a, _ int) int { // want "potentially unused parameter: 'b'"
11008-	a += 1
11009-	return a
11010-}
11011-
11012-func y[T any](a T) {
11013-	panic("yo")
11014-}
11015diff -urN a/gopls/internal/lsp/analysis/unusedparams/unusedparams.go b/gopls/internal/lsp/analysis/unusedparams/unusedparams.go
11016--- a/gopls/internal/lsp/analysis/unusedparams/unusedparams.go	2000-01-01 00:00:00.000000000 -0000
11017+++ b/gopls/internal/lsp/analysis/unusedparams/unusedparams.go	1970-01-01 00:00:00.000000000 +0000
11018@@ -1,152 +0,0 @@
11019-// Copyright 2020 The Go Authors. All rights reserved.
11020-// Use of this source code is governed by a BSD-style
11021-// license that can be found in the LICENSE file.
11022-
11023-// Package unusedparams defines an analyzer that checks for unused
11024-// parameters of functions.
11025-package unusedparams
11026-
11027-import (
11028-	"fmt"
11029-	"go/ast"
11030-	"go/types"
11031-	"strings"
11032-
11033-	"golang.org/x/tools/go/analysis"
11034-	"golang.org/x/tools/go/analysis/passes/inspect"
11035-	"golang.org/x/tools/go/ast/inspector"
11036-)
11037-
11038-const Doc = `check for unused parameters of functions
11039-
11040-The unusedparams analyzer checks functions to see if there are
11041-any parameters that are not being used.
11042-
11043-To reduce false positives it ignores:
11044-- methods
11045-- parameters that do not have a name or are underscored
11046-- functions in test files
11047-- functions with empty bodies or those with just a return stmt`
11048-
11049-var Analyzer = &analysis.Analyzer{
11050-	Name:     "unusedparams",
11051-	Doc:      Doc,
11052-	Requires: []*analysis.Analyzer{inspect.Analyzer},
11053-	Run:      run,
11054-}
11055-
11056-type paramData struct {
11057-	field  *ast.Field
11058-	ident  *ast.Ident
11059-	typObj types.Object
11060-}
11061-
11062-func run(pass *analysis.Pass) (interface{}, error) {
11063-	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
11064-	nodeFilter := []ast.Node{
11065-		(*ast.FuncDecl)(nil),
11066-		(*ast.FuncLit)(nil),
11067-	}
11068-
11069-	inspect.Preorder(nodeFilter, func(n ast.Node) {
11070-		var fieldList *ast.FieldList
11071-		var body *ast.BlockStmt
11072-
11073-		// Get the fieldList and body from the function node.
11074-		switch f := n.(type) {
11075-		case *ast.FuncDecl:
11076-			fieldList, body = f.Type.Params, f.Body
11077-			// TODO(golang/go#36602): add better handling for methods, if we enable methods
11078-			// we will get false positives if a struct is potentially implementing
11079-			// an interface.
11080-			if f.Recv != nil {
11081-				return
11082-			}
11083-			// Ignore functions in _test.go files to reduce false positives.
11084-			if file := pass.Fset.File(n.Pos()); file != nil && strings.HasSuffix(file.Name(), "_test.go") {
11085-				return
11086-			}
11087-		case *ast.FuncLit:
11088-			fieldList, body = f.Type.Params, f.Body
11089-		}
11090-		// If there are no arguments or the function is empty, then return.
11091-		if fieldList.NumFields() == 0 || body == nil || len(body.List) == 0 {
11092-			return
11093-		}
11094-
11095-		switch expr := body.List[0].(type) {
11096-		case *ast.ReturnStmt:
11097-			// Ignore functions that only contain a return statement to reduce false positives.
11098-			return
11099-		case *ast.ExprStmt:
11100-			callExpr, ok := expr.X.(*ast.CallExpr)
11101-			if !ok || len(body.List) > 1 {
11102-				break
11103-			}
11104-			// Ignore functions that only contain a panic statement to reduce false positives.
11105-			if fun, ok := callExpr.Fun.(*ast.Ident); ok && fun.Name == "panic" {
11106-				return
11107-			}
11108-		}
11109-
11110-		// Get the useful data from each field.
11111-		params := make(map[string]*paramData)
11112-		unused := make(map[*paramData]bool)
11113-		for _, f := range fieldList.List {
11114-			for _, i := range f.Names {
11115-				if i.Name == "_" {
11116-					continue
11117-				}
11118-				params[i.Name] = &paramData{
11119-					field:  f,
11120-					ident:  i,
11121-					typObj: pass.TypesInfo.ObjectOf(i),
11122-				}
11123-				unused[params[i.Name]] = true
11124-			}
11125-		}
11126-
11127-		// Traverse through the body of the function and
11128-		// check to see which parameters are unused.
11129-		ast.Inspect(body, func(node ast.Node) bool {
11130-			n, ok := node.(*ast.Ident)
11131-			if !ok {
11132-				return true
11133-			}
11134-			param, ok := params[n.Name]
11135-			if !ok {
11136-				return false
11137-			}
11138-			if nObj := pass.TypesInfo.ObjectOf(n); nObj != param.typObj {
11139-				return false
11140-			}
11141-			delete(unused, param)
11142-			return false
11143-		})
11144-
11145-		// Create the reports for the unused parameters.
11146-		for u := range unused {
11147-			start, end := u.field.Pos(), u.field.End()
11148-			if len(u.field.Names) > 1 {
11149-				start, end = u.ident.Pos(), u.ident.End()
11150-			}
11151-			// TODO(golang/go#36602): Add suggested fixes to automatically
11152-			// remove the unused parameter from every use of this
11153-			// function.
11154-			pass.Report(analysis.Diagnostic{
11155-				Pos:     start,
11156-				End:     end,
11157-				Message: fmt.Sprintf("potentially unused parameter: '%s'", u.ident.Name),
11158-				SuggestedFixes: []analysis.SuggestedFix{{
11159-					Message: `Replace with "_"`,
11160-					TextEdits: []analysis.TextEdit{{
11161-						Pos:     u.ident.Pos(),
11162-						End:     u.ident.End(),
11163-						NewText: []byte("_"),
11164-					}},
11165-				}},
11166-			})
11167-		}
11168-	})
11169-	return nil, nil
11170-}
11171diff -urN a/gopls/internal/lsp/analysis/unusedparams/unusedparams_test.go b/gopls/internal/lsp/analysis/unusedparams/unusedparams_test.go
11172--- a/gopls/internal/lsp/analysis/unusedparams/unusedparams_test.go	2000-01-01 00:00:00.000000000 -0000
11173+++ b/gopls/internal/lsp/analysis/unusedparams/unusedparams_test.go	1970-01-01 00:00:00.000000000 +0000
11174@@ -1,22 +0,0 @@
11175-// Copyright 2020 The Go Authors. All rights reserved.
11176-// Use of this source code is governed by a BSD-style
11177-// license that can be found in the LICENSE file.
11178-
11179-package unusedparams_test
11180-
11181-import (
11182-	"testing"
11183-
11184-	"golang.org/x/tools/go/analysis/analysistest"
11185-	"golang.org/x/tools/gopls/internal/lsp/analysis/unusedparams"
11186-	"golang.org/x/tools/internal/typeparams"
11187-)
11188-
11189-func Test(t *testing.T) {
11190-	testdata := analysistest.TestData()
11191-	tests := []string{"a"}
11192-	if typeparams.Enabled {
11193-		tests = append(tests, "typeparams")
11194-	}
11195-	analysistest.RunWithSuggestedFixes(t, testdata, unusedparams.Analyzer, tests...)
11196-}
11197diff -urN a/gopls/internal/lsp/analysis/unusedvariable/testdata/src/assign/a.go b/gopls/internal/lsp/analysis/unusedvariable/testdata/src/assign/a.go
11198--- a/gopls/internal/lsp/analysis/unusedvariable/testdata/src/assign/a.go	2000-01-01 00:00:00.000000000 -0000
11199+++ b/gopls/internal/lsp/analysis/unusedvariable/testdata/src/assign/a.go	1970-01-01 00:00:00.000000000 +0000
11200@@ -1,74 +0,0 @@
11201-// Copyright 2022 The Go Authors. All rights reserved.
11202-// Use of this source code is governed by a BSD-style
11203-// license that can be found in the LICENSE file.
11204-
11205-package a
11206-
11207-import (
11208-	"fmt"
11209-	"os"
11210-)
11211-
11212-type A struct {
11213-	b int
11214-}
11215-
11216-func singleAssignment() {
11217-	v := "s" // want `v declared (and|but) not used`
11218-
11219-	s := []int{ // want `s declared (and|but) not used`
11220-		1,
11221-		2,
11222-	}
11223-
11224-	a := func(s string) bool { // want `a declared (and|but) not used`
11225-		return false
11226-	}
11227-
11228-	if 1 == 1 {
11229-		s := "v" // want `s declared (and|but) not used`
11230-	}
11231-
11232-	panic("I should survive")
11233-}
11234-
11235-func noOtherStmtsInBlock() {
11236-	v := "s" // want `v declared (and|but) not used`
11237-}
11238-
11239-func partOfMultiAssignment() {
11240-	f, err := os.Open("file") // want `f declared (and|but) not used`
11241-	panic(err)
11242-}
11243-
11244-func sideEffects(cBool chan bool, cInt chan int) {
11245-	b := <-c            // want `b declared (and|but) not used`
11246-	s := fmt.Sprint("") // want `s declared (and|but) not used`
11247-	a := A{             // want `a declared (and|but) not used`
11248-		b: func() int {
11249-			return 1
11250-		}(),
11251-	}
11252-	c := A{<-cInt}          // want `c declared (and|but) not used`
11253-	d := fInt() + <-cInt    // want `d declared (and|but) not used`
11254-	e := fBool() && <-cBool // want `e declared (and|but) not used`
11255-	f := map[int]int{       // want `f declared (and|but) not used`
11256-		fInt(): <-cInt,
11257-	}
11258-	g := []int{<-cInt}       // want `g declared (and|but) not used`
11259-	h := func(s string) {}   // want `h declared (and|but) not used`
11260-	i := func(s string) {}() // want `i declared (and|but) not used`
11261-}
11262-
11263-func commentAbove() {
11264-	// v is a variable
11265-	v := "s" // want `v declared (and|but) not used`
11266-}
11267-
11268-func fBool() bool {
11269-	return true
11270-}
11271-
11272-func fInt() int {
11273-	return 1
11274-}
11275diff -urN a/gopls/internal/lsp/analysis/unusedvariable/testdata/src/assign/a.go.golden b/gopls/internal/lsp/analysis/unusedvariable/testdata/src/assign/a.go.golden
11276--- a/gopls/internal/lsp/analysis/unusedvariable/testdata/src/assign/a.go.golden	2000-01-01 00:00:00.000000000 -0000
11277+++ b/gopls/internal/lsp/analysis/unusedvariable/testdata/src/assign/a.go.golden	1970-01-01 00:00:00.000000000 +0000
11278@@ -1,59 +0,0 @@
11279-// Copyright 2022 The Go Authors. All rights reserved.
11280-// Use of this source code is governed by a BSD-style
11281-// license that can be found in the LICENSE file.
11282-
11283-package a
11284-
11285-import (
11286-	"fmt"
11287-	"os"
11288-)
11289-
11290-type A struct {
11291-	b int
11292-}
11293-
11294-func singleAssignment() {
11295-	if 1 == 1 {
11296-	}
11297-
11298-	panic("I should survive")
11299-}
11300-
11301-func noOtherStmtsInBlock() {
11302-}
11303-
11304-func partOfMultiAssignment() {
11305-	_, err := os.Open("file") // want `f declared (and|but) not used`
11306-	panic(err)
11307-}
11308-
11309-func sideEffects(cBool chan bool, cInt chan int) {
11310-	<-c            // want `b declared (and|but) not used`
11311-	fmt.Sprint("") // want `s declared (and|but) not used`
11312-	A{             // want `a declared (and|but) not used`
11313-		b: func() int {
11314-			return 1
11315-		}(),
11316-	}
11317-	A{<-cInt}          // want `c declared (and|but) not used`
11318-	fInt() + <-cInt    // want `d declared (and|but) not used`
11319-	fBool() && <-cBool // want `e declared (and|but) not used`
11320-	map[int]int{       // want `f declared (and|but) not used`
11321-		fInt(): <-cInt,
11322-	}
11323-	[]int{<-cInt}       // want `g declared (and|but) not used`
11324-	func(s string) {}() // want `i declared (and|but) not used`
11325-}
11326-
11327-func commentAbove() {
11328-	// v is a variable
11329-}
11330-
11331-func fBool() bool {
11332-	return true
11333-}
11334-
11335-func fInt() int {
11336-	return 1
11337-}
11338diff -urN a/gopls/internal/lsp/analysis/unusedvariable/testdata/src/decl/a.go b/gopls/internal/lsp/analysis/unusedvariable/testdata/src/decl/a.go
11339--- a/gopls/internal/lsp/analysis/unusedvariable/testdata/src/decl/a.go	2000-01-01 00:00:00.000000000 -0000
11340+++ b/gopls/internal/lsp/analysis/unusedvariable/testdata/src/decl/a.go	1970-01-01 00:00:00.000000000 +0000
11341@@ -1,30 +0,0 @@
11342-// Copyright 2022 The Go Authors. All rights reserved.
11343-// Use of this source code is governed by a BSD-style
11344-// license that can be found in the LICENSE file.
11345-
11346-package decl
11347-
11348-func a() {
11349-	var b, c bool // want `b declared (and|but) not used`
11350-	panic(c)
11351-
11352-	if 1 == 1 {
11353-		var s string // want `s declared (and|but) not used`
11354-	}
11355-}
11356-
11357-func b() {
11358-	// b is a variable
11359-	var b bool // want `b declared (and|but) not used`
11360-}
11361-
11362-func c() {
11363-	var (
11364-		d string
11365-
11366-		// some comment for c
11367-		c bool // want `c declared (and|but) not used`
11368-	)
11369-
11370-	panic(d)
11371-}
11372diff -urN a/gopls/internal/lsp/analysis/unusedvariable/testdata/src/decl/a.go.golden b/gopls/internal/lsp/analysis/unusedvariable/testdata/src/decl/a.go.golden
11373--- a/gopls/internal/lsp/analysis/unusedvariable/testdata/src/decl/a.go.golden	2000-01-01 00:00:00.000000000 -0000
11374+++ b/gopls/internal/lsp/analysis/unusedvariable/testdata/src/decl/a.go.golden	1970-01-01 00:00:00.000000000 +0000
11375@@ -1,24 +0,0 @@
11376-// Copyright 2022 The Go Authors. All rights reserved.
11377-// Use of this source code is governed by a BSD-style
11378-// license that can be found in the LICENSE file.
11379-
11380-package decl
11381-
11382-func a() {
11383-	var c bool // want `b declared (and|but) not used`
11384-	panic(c)
11385-
11386-	if 1 == 1 {
11387-	}
11388-}
11389-
11390-func b() {
11391-	// b is a variable
11392-}
11393-
11394-func c() {
11395-	var (
11396-		d string
11397-	)
11398-	panic(d)
11399-}
11400diff -urN a/gopls/internal/lsp/analysis/unusedvariable/unusedvariable.go b/gopls/internal/lsp/analysis/unusedvariable/unusedvariable.go
11401--- a/gopls/internal/lsp/analysis/unusedvariable/unusedvariable.go	2000-01-01 00:00:00.000000000 -0000
11402+++ b/gopls/internal/lsp/analysis/unusedvariable/unusedvariable.go	1970-01-01 00:00:00.000000000 +0000
11403@@ -1,300 +0,0 @@
11404-// Copyright 2020 The Go Authors. All rights reserved.
11405-// Use of this source code is governed by a BSD-style
11406-// license that can be found in the LICENSE file.
11407-
11408-// Package unusedvariable defines an analyzer that checks for unused variables.
11409-package unusedvariable
11410-
11411-import (
11412-	"bytes"
11413-	"fmt"
11414-	"go/ast"
11415-	"go/format"
11416-	"go/token"
11417-	"go/types"
11418-	"strings"
11419-
11420-	"golang.org/x/tools/go/analysis"
11421-	"golang.org/x/tools/go/ast/astutil"
11422-)
11423-
11424-const Doc = `check for unused variables
11425-
11426-The unusedvariable analyzer suggests fixes for unused variables errors.
11427-`
11428-
11429-var Analyzer = &analysis.Analyzer{
11430-	Name:             "unusedvariable",
11431-	Doc:              Doc,
11432-	Requires:         []*analysis.Analyzer{},
11433-	Run:              run,
11434-	RunDespiteErrors: true, // an unusedvariable diagnostic is a compile error
11435-}
11436-
11437-// The suffix for this error message changed in Go 1.20.
11438-var unusedVariableSuffixes = []string{" declared and not used", " declared but not used"}
11439-
11440-func run(pass *analysis.Pass) (interface{}, error) {
11441-	for _, typeErr := range pass.TypeErrors {
11442-		for _, suffix := range unusedVariableSuffixes {
11443-			if strings.HasSuffix(typeErr.Msg, suffix) {
11444-				varName := strings.TrimSuffix(typeErr.Msg, suffix)
11445-				err := runForError(pass, typeErr, varName)
11446-				if err != nil {
11447-					return nil, err
11448-				}
11449-			}
11450-		}
11451-	}
11452-
11453-	return nil, nil
11454-}
11455-
11456-func runForError(pass *analysis.Pass, err types.Error, name string) error {
11457-	var file *ast.File
11458-	for _, f := range pass.Files {
11459-		if f.Pos() <= err.Pos && err.Pos < f.End() {
11460-			file = f
11461-			break
11462-		}
11463-	}
11464-	if file == nil {
11465-		return nil
11466-	}
11467-
11468-	path, _ := astutil.PathEnclosingInterval(file, err.Pos, err.Pos)
11469-	if len(path) < 2 {
11470-		return nil
11471-	}
11472-
11473-	ident, ok := path[0].(*ast.Ident)
11474-	if !ok || ident.Name != name {
11475-		return nil
11476-	}
11477-
11478-	diag := analysis.Diagnostic{
11479-		Pos:     ident.Pos(),
11480-		End:     ident.End(),
11481-		Message: err.Msg,
11482-	}
11483-
11484-	for i := range path {
11485-		switch stmt := path[i].(type) {
11486-		case *ast.ValueSpec:
11487-			// Find GenDecl to which offending ValueSpec belongs.
11488-			if decl, ok := path[i+1].(*ast.GenDecl); ok {
11489-				fixes := removeVariableFromSpec(pass, path, stmt, decl, ident)
11490-				// fixes may be nil
11491-				if len(fixes) > 0 {
11492-					diag.SuggestedFixes = fixes
11493-					pass.Report(diag)
11494-				}
11495-			}
11496-
11497-		case *ast.AssignStmt:
11498-			if stmt.Tok != token.DEFINE {
11499-				continue
11500-			}
11501-
11502-			containsIdent := false
11503-			for _, expr := range stmt.Lhs {
11504-				if expr == ident {
11505-					containsIdent = true
11506-				}
11507-			}
11508-			if !containsIdent {
11509-				continue
11510-			}
11511-
11512-			fixes := removeVariableFromAssignment(pass, path, stmt, ident)
11513-			// fixes may be nil
11514-			if len(fixes) > 0 {
11515-				diag.SuggestedFixes = fixes
11516-				pass.Report(diag)
11517-			}
11518-		}
11519-	}
11520-
11521-	return nil
11522-}
11523-
11524-func removeVariableFromSpec(pass *analysis.Pass, path []ast.Node, stmt *ast.ValueSpec, decl *ast.GenDecl, ident *ast.Ident) []analysis.SuggestedFix {
11525-	newDecl := new(ast.GenDecl)
11526-	*newDecl = *decl
11527-	newDecl.Specs = nil
11528-
11529-	for _, spec := range decl.Specs {
11530-		if spec != stmt {
11531-			newDecl.Specs = append(newDecl.Specs, spec)
11532-			continue
11533-		}
11534-
11535-		newSpec := new(ast.ValueSpec)
11536-		*newSpec = *stmt
11537-		newSpec.Names = nil
11538-
11539-		for _, n := range stmt.Names {
11540-			if n != ident {
11541-				newSpec.Names = append(newSpec.Names, n)
11542-			}
11543-		}
11544-
11545-		if len(newSpec.Names) > 0 {
11546-			newDecl.Specs = append(newDecl.Specs, newSpec)
11547-		}
11548-	}
11549-
11550-	// decl.End() does not include any comments, so if a comment is present we
11551-	// need to account for it when we delete the statement
11552-	end := decl.End()
11553-	if stmt.Comment != nil && stmt.Comment.End() > end {
11554-		end = stmt.Comment.End()
11555-	}
11556-
11557-	// There are no other specs left in the declaration, the whole statement can
11558-	// be deleted
11559-	if len(newDecl.Specs) == 0 {
11560-		// Find parent DeclStmt and delete it
11561-		for _, node := range path {
11562-			if declStmt, ok := node.(*ast.DeclStmt); ok {
11563-				return []analysis.SuggestedFix{
11564-					{
11565-						Message:   suggestedFixMessage(ident.Name),
11566-						TextEdits: deleteStmtFromBlock(path, declStmt),
11567-					},
11568-				}
11569-			}
11570-		}
11571-	}
11572-
11573-	var b bytes.Buffer
11574-	if err := format.Node(&b, pass.Fset, newDecl); err != nil {
11575-		return nil
11576-	}
11577-
11578-	return []analysis.SuggestedFix{
11579-		{
11580-			Message: suggestedFixMessage(ident.Name),
11581-			TextEdits: []analysis.TextEdit{
11582-				{
11583-					Pos: decl.Pos(),
11584-					// Avoid adding a new empty line
11585-					End:     end + 1,
11586-					NewText: b.Bytes(),
11587-				},
11588-			},
11589-		},
11590-	}
11591-}
11592-
11593-func removeVariableFromAssignment(pass *analysis.Pass, path []ast.Node, stmt *ast.AssignStmt, ident *ast.Ident) []analysis.SuggestedFix {
11594-	// The only variable in the assignment is unused
11595-	if len(stmt.Lhs) == 1 {
11596-		// If LHS has only one expression to be valid it has to have 1 expression
11597-		// on RHS
11598-		//
11599-		// RHS may have side effects, preserve RHS
11600-		if exprMayHaveSideEffects(stmt.Rhs[0]) {
11601-			// Delete until RHS
11602-			return []analysis.SuggestedFix{
11603-				{
11604-					Message: suggestedFixMessage(ident.Name),
11605-					TextEdits: []analysis.TextEdit{
11606-						{
11607-							Pos: ident.Pos(),
11608-							End: stmt.Rhs[0].Pos(),
11609-						},
11610-					},
11611-				},
11612-			}
11613-		}
11614-
11615-		// RHS does not have any side effects, delete the whole statement
11616-		return []analysis.SuggestedFix{
11617-			{
11618-				Message:   suggestedFixMessage(ident.Name),
11619-				TextEdits: deleteStmtFromBlock(path, stmt),
11620-			},
11621-		}
11622-	}
11623-
11624-	// Otherwise replace ident with `_`
11625-	return []analysis.SuggestedFix{
11626-		{
11627-			Message: suggestedFixMessage(ident.Name),
11628-			TextEdits: []analysis.TextEdit{
11629-				{
11630-					Pos:     ident.Pos(),
11631-					End:     ident.End(),
11632-					NewText: []byte("_"),
11633-				},
11634-			},
11635-		},
11636-	}
11637-}
11638-
11639-func suggestedFixMessage(name string) string {
11640-	return fmt.Sprintf("Remove variable %s", name)
11641-}
11642-
11643-func deleteStmtFromBlock(path []ast.Node, stmt ast.Stmt) []analysis.TextEdit {
11644-	// Find innermost enclosing BlockStmt.
11645-	var block *ast.BlockStmt
11646-	for i := range path {
11647-		if blockStmt, ok := path[i].(*ast.BlockStmt); ok {
11648-			block = blockStmt
11649-			break
11650-		}
11651-	}
11652-
11653-	nodeIndex := -1
11654-	for i, blockStmt := range block.List {
11655-		if blockStmt == stmt {
11656-			nodeIndex = i
11657-			break
11658-		}
11659-	}
11660-
11661-	// The statement we need to delete was not found in BlockStmt
11662-	if nodeIndex == -1 {
11663-		return nil
11664-	}
11665-
11666-	// Delete until the end of the block unless there is another statement after
11667-	// the one we are trying to delete
11668-	end := block.Rbrace
11669-	if nodeIndex < len(block.List)-1 {
11670-		end = block.List[nodeIndex+1].Pos()
11671-	}
11672-
11673-	return []analysis.TextEdit{
11674-		{
11675-			Pos: stmt.Pos(),
11676-			End: end,
11677-		},
11678-	}
11679-}
11680-
11681-// exprMayHaveSideEffects reports whether the expression may have side effects
11682-// (because it contains a function call or channel receive). We disregard
11683-// runtime panics as well written programs should not encounter them.
11684-func exprMayHaveSideEffects(expr ast.Expr) bool {
11685-	var mayHaveSideEffects bool
11686-	ast.Inspect(expr, func(n ast.Node) bool {
11687-		switch n := n.(type) {
11688-		case *ast.CallExpr: // possible function call
11689-			mayHaveSideEffects = true
11690-			return false
11691-		case *ast.UnaryExpr:
11692-			if n.Op == token.ARROW { // channel receive
11693-				mayHaveSideEffects = true
11694-				return false
11695-			}
11696-		case *ast.FuncLit:
11697-			return false // evaluating what's inside a FuncLit has no effect
11698-		}
11699-		return true
11700-	})
11701-
11702-	return mayHaveSideEffects
11703-}
11704diff -urN a/gopls/internal/lsp/analysis/unusedvariable/unusedvariable_test.go b/gopls/internal/lsp/analysis/unusedvariable/unusedvariable_test.go
11705--- a/gopls/internal/lsp/analysis/unusedvariable/unusedvariable_test.go	2000-01-01 00:00:00.000000000 -0000
11706+++ b/gopls/internal/lsp/analysis/unusedvariable/unusedvariable_test.go	1970-01-01 00:00:00.000000000 +0000
11707@@ -1,24 +0,0 @@
11708-// Copyright 2020 The Go Authors. All rights reserved.
11709-// Use of this source code is governed by a BSD-style
11710-// license that can be found in the LICENSE file.
11711-
11712-package unusedvariable_test
11713-
11714-import (
11715-	"testing"
11716-
11717-	"golang.org/x/tools/go/analysis/analysistest"
11718-	"golang.org/x/tools/gopls/internal/lsp/analysis/unusedvariable"
11719-)
11720-
11721-func Test(t *testing.T) {
11722-	testdata := analysistest.TestData()
11723-
11724-	t.Run("decl", func(t *testing.T) {
11725-		analysistest.RunWithSuggestedFixes(t, testdata, unusedvariable.Analyzer, "decl")
11726-	})
11727-
11728-	t.Run("assign", func(t *testing.T) {
11729-		analysistest.RunWithSuggestedFixes(t, testdata, unusedvariable.Analyzer, "assign")
11730-	})
11731-}
11732diff -urN a/gopls/internal/lsp/analysis/useany/testdata/src/a/a.go b/gopls/internal/lsp/analysis/useany/testdata/src/a/a.go
11733--- a/gopls/internal/lsp/analysis/useany/testdata/src/a/a.go	2000-01-01 00:00:00.000000000 -0000
11734+++ b/gopls/internal/lsp/analysis/useany/testdata/src/a/a.go	1970-01-01 00:00:00.000000000 +0000
11735@@ -1,25 +0,0 @@
11736-// Copyright 2021 The Go Authors. All rights reserved.
11737-// Use of this source code is governed by a BSD-style
11738-// license that can be found in the LICENSE file.
11739-
11740-// This file contains tests for the useany checker.
11741-
11742-package a
11743-
11744-type Any interface{}
11745-
11746-func _[T interface{}]()                    {} // want "could use \"any\" for this empty interface"
11747-func _[X any, T interface{}]()             {} // want "could use \"any\" for this empty interface"
11748-func _[any interface{}]()                  {} // want "could use \"any\" for this empty interface"
11749-func _[T Any]()                            {} // want "could use \"any\" for this empty interface"
11750-func _[T interface{ int | interface{} }]() {} // want "could use \"any\" for this empty interface"
11751-func _[T interface{ int | Any }]()         {} // want "could use \"any\" for this empty interface"
11752-func _[T any]()                            {}
11753-
11754-type _[T interface{}] int                    // want "could use \"any\" for this empty interface"
11755-type _[X any, T interface{}] int             // want "could use \"any\" for this empty interface"
11756-type _[any interface{}] int                  // want "could use \"any\" for this empty interface"
11757-type _[T Any] int                            // want "could use \"any\" for this empty interface"
11758-type _[T interface{ int | interface{} }] int // want "could use \"any\" for this empty interface"
11759-type _[T interface{ int | Any }] int         // want "could use \"any\" for this empty interface"
11760-type _[T any] int
11761diff -urN a/gopls/internal/lsp/analysis/useany/testdata/src/a/a.go.golden b/gopls/internal/lsp/analysis/useany/testdata/src/a/a.go.golden
11762--- a/gopls/internal/lsp/analysis/useany/testdata/src/a/a.go.golden	2000-01-01 00:00:00.000000000 -0000
11763+++ b/gopls/internal/lsp/analysis/useany/testdata/src/a/a.go.golden	1970-01-01 00:00:00.000000000 +0000
11764@@ -1,25 +0,0 @@
11765-// Copyright 2021 The Go Authors. All rights reserved.
11766-// Use of this source code is governed by a BSD-style
11767-// license that can be found in the LICENSE file.
11768-
11769-// This file contains tests for the useany checker.
11770-
11771-package a
11772-
11773-type Any interface{}
11774-
11775-func _[T any]()           {} // want "could use \"any\" for this empty interface"
11776-func _[X any, T any]()    {} // want "could use \"any\" for this empty interface"
11777-func _[any interface{}]() {} // want "could use \"any\" for this empty interface"
11778-func _[T any]()           {} // want "could use \"any\" for this empty interface"
11779-func _[T any]()           {} // want "could use \"any\" for this empty interface"
11780-func _[T any]()           {} // want "could use \"any\" for this empty interface"
11781-func _[T any]()           {}
11782-
11783-type _[T any] int           // want "could use \"any\" for this empty interface"
11784-type _[X any, T any] int    // want "could use \"any\" for this empty interface"
11785-type _[any interface{}] int // want "could use \"any\" for this empty interface"
11786-type _[T any] int           // want "could use \"any\" for this empty interface"
11787-type _[T any] int           // want "could use \"any\" for this empty interface"
11788-type _[T any] int           // want "could use \"any\" for this empty interface"
11789-type _[T any] int
11790diff -urN a/gopls/internal/lsp/analysis/useany/useany.go b/gopls/internal/lsp/analysis/useany/useany.go
11791--- a/gopls/internal/lsp/analysis/useany/useany.go	2000-01-01 00:00:00.000000000 -0000
11792+++ b/gopls/internal/lsp/analysis/useany/useany.go	1970-01-01 00:00:00.000000000 +0000
11793@@ -1,102 +0,0 @@
11794-// Copyright 2021 The Go Authors. All rights reserved.
11795-// Use of this source code is governed by a BSD-style
11796-// license that can be found in the LICENSE file.
11797-
11798-// Package useany defines an Analyzer that checks for usage of interface{} in
11799-// constraints, rather than the predeclared any.
11800-package useany
11801-
11802-import (
11803-	"fmt"
11804-	"go/ast"
11805-	"go/token"
11806-	"go/types"
11807-
11808-	"golang.org/x/tools/go/analysis"
11809-	"golang.org/x/tools/go/analysis/passes/inspect"
11810-	"golang.org/x/tools/go/ast/inspector"
11811-	"golang.org/x/tools/internal/typeparams"
11812-)
11813-
11814-const Doc = `check for constraints that could be simplified to "any"`
11815-
11816-var Analyzer = &analysis.Analyzer{
11817-	Name:     "useany",
11818-	Doc:      Doc,
11819-	Requires: []*analysis.Analyzer{inspect.Analyzer},
11820-	Run:      run,
11821-}
11822-
11823-func run(pass *analysis.Pass) (interface{}, error) {
11824-	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
11825-
11826-	universeAny := types.Universe.Lookup("any")
11827-	if universeAny == nil {
11828-		// Go <= 1.17. Nothing to check.
11829-		return nil, nil
11830-	}
11831-
11832-	nodeFilter := []ast.Node{
11833-		(*ast.TypeSpec)(nil),
11834-		(*ast.FuncType)(nil),
11835-	}
11836-
11837-	inspect.Preorder(nodeFilter, func(node ast.Node) {
11838-		var tparams *ast.FieldList
11839-		switch node := node.(type) {
11840-		case *ast.TypeSpec:
11841-			tparams = typeparams.ForTypeSpec(node)
11842-		case *ast.FuncType:
11843-			tparams = typeparams.ForFuncType(node)
11844-		default:
11845-			panic(fmt.Sprintf("unexpected node type %T", node))
11846-		}
11847-		if tparams.NumFields() == 0 {
11848-			return
11849-		}
11850-
11851-		for _, field := range tparams.List {
11852-			typ := pass.TypesInfo.Types[field.Type].Type
11853-			if typ == nil {
11854-				continue // something is wrong, but not our concern
11855-			}
11856-			iface, ok := typ.Underlying().(*types.Interface)
11857-			if !ok {
11858-				continue // invalid constraint
11859-			}
11860-
11861-			// If the constraint is the empty interface, offer a fix to use 'any'
11862-			// instead.
11863-			if iface.Empty() {
11864-				id, _ := field.Type.(*ast.Ident)
11865-				if id != nil && pass.TypesInfo.Uses[id] == universeAny {
11866-					continue
11867-				}
11868-
11869-				diag := analysis.Diagnostic{
11870-					Pos:     field.Type.Pos(),
11871-					End:     field.Type.End(),
11872-					Message: `could use "any" for this empty interface`,
11873-				}
11874-
11875-				// Only suggest a fix to 'any' if we actually resolve the predeclared
11876-				// any in this scope.
11877-				if scope := pass.TypesInfo.Scopes[node]; scope != nil {
11878-					if _, any := scope.LookupParent("any", token.NoPos); any == universeAny {
11879-						diag.SuggestedFixes = []analysis.SuggestedFix{{
11880-							Message: `use "any"`,
11881-							TextEdits: []analysis.TextEdit{{
11882-								Pos:     field.Type.Pos(),
11883-								End:     field.Type.End(),
11884-								NewText: []byte("any"),
11885-							}},
11886-						}}
11887-					}
11888-				}
11889-
11890-				pass.Report(diag)
11891-			}
11892-		}
11893-	})
11894-	return nil, nil
11895-}
11896diff -urN a/gopls/internal/lsp/analysis/useany/useany_test.go b/gopls/internal/lsp/analysis/useany/useany_test.go
11897--- a/gopls/internal/lsp/analysis/useany/useany_test.go	2000-01-01 00:00:00.000000000 -0000
11898+++ b/gopls/internal/lsp/analysis/useany/useany_test.go	1970-01-01 00:00:00.000000000 +0000
11899@@ -1,21 +0,0 @@
11900-// Copyright 2021 The Go Authors. All rights reserved.
11901-// Use of this source code is governed by a BSD-style
11902-// license that can be found in the LICENSE file.
11903-
11904-package useany_test
11905-
11906-import (
11907-	"testing"
11908-
11909-	"golang.org/x/tools/go/analysis/analysistest"
11910-	"golang.org/x/tools/gopls/internal/lsp/analysis/useany"
11911-	"golang.org/x/tools/internal/typeparams"
11912-)
11913-
11914-func Test(t *testing.T) {
11915-	if !typeparams.Enabled {
11916-		t.Skip("type params are not enabled")
11917-	}
11918-	testdata := analysistest.TestData()
11919-	analysistest.RunWithSuggestedFixes(t, testdata, useany.Analyzer, "a")
11920-}
11921diff -urN a/gopls/internal/lsp/browser/browser.go b/gopls/internal/lsp/browser/browser.go
11922--- a/gopls/internal/lsp/browser/browser.go	2000-01-01 00:00:00.000000000 -0000
11923+++ b/gopls/internal/lsp/browser/browser.go	1970-01-01 00:00:00.000000000 +0000
11924@@ -1,67 +0,0 @@
11925-// Copyright 2016 The Go Authors. All rights reserved.
11926-// Use of this source code is governed by a BSD-style
11927-// license that can be found in the LICENSE file.
11928-
11929-// Package browser provides utilities for interacting with users' browsers.
11930-package browser
11931-
11932-import (
11933-	exec "golang.org/x/sys/execabs"
11934-	"os"
11935-	"runtime"
11936-	"time"
11937-)
11938-
11939-// Commands returns a list of possible commands to use to open a url.
11940-func Commands() [][]string {
11941-	var cmds [][]string
11942-	if exe := os.Getenv("BROWSER"); exe != "" {
11943-		cmds = append(cmds, []string{exe})
11944-	}
11945-	switch runtime.GOOS {
11946-	case "darwin":
11947-		cmds = append(cmds, []string{"/usr/bin/open"})
11948-	case "windows":
11949-		cmds = append(cmds, []string{"cmd", "/c", "start"})
11950-	default:
11951-		if os.Getenv("DISPLAY") != "" {
11952-			// xdg-open is only for use in a desktop environment.
11953-			cmds = append(cmds, []string{"xdg-open"})
11954-		}
11955-	}
11956-	cmds = append(cmds,
11957-		[]string{"chrome"},
11958-		[]string{"google-chrome"},
11959-		[]string{"chromium"},
11960-		[]string{"firefox"},
11961-	)
11962-	return cmds
11963-}
11964-
11965-// Open tries to open url in a browser and reports whether it succeeded.
11966-func Open(url string) bool {
11967-	for _, args := range Commands() {
11968-		cmd := exec.Command(args[0], append(args[1:], url)...)
11969-		if cmd.Start() == nil && appearsSuccessful(cmd, 3*time.Second) {
11970-			return true
11971-		}
11972-	}
11973-	return false
11974-}
11975-
11976-// appearsSuccessful reports whether the command appears to have run successfully.
11977-// If the command runs longer than the timeout, it's deemed successful.
11978-// If the command runs within the timeout, it's deemed successful if it exited cleanly.
11979-func appearsSuccessful(cmd *exec.Cmd, timeout time.Duration) bool {
11980-	errc := make(chan error, 1)
11981-	go func() {
11982-		errc <- cmd.Wait()
11983-	}()
11984-
11985-	select {
11986-	case <-time.After(timeout):
11987-		return true
11988-	case err := <-errc:
11989-		return err == nil
11990-	}
11991-}
11992diff -urN a/gopls/internal/lsp/browser/README.md b/gopls/internal/lsp/browser/README.md
11993--- a/gopls/internal/lsp/browser/README.md	2000-01-01 00:00:00.000000000 -0000
11994+++ b/gopls/internal/lsp/browser/README.md	1970-01-01 00:00:00.000000000 +0000
11995@@ -1 +0,0 @@
11996-This package is a copy of cmd/internal/browser from the go distribution
11997\ No newline at end of file
11998diff -urN a/gopls/internal/lsp/cache/analysis.go b/gopls/internal/lsp/cache/analysis.go
11999--- a/gopls/internal/lsp/cache/analysis.go	2000-01-01 00:00:00.000000000 -0000
12000+++ b/gopls/internal/lsp/cache/analysis.go	1970-01-01 00:00:00.000000000 +0000
12001@@ -1,1247 +0,0 @@
12002-// Copyright 2019 The Go Authors. All rights reserved.
12003-// Use of this source code is governed by a BSD-style
12004-// license that can be found in the LICENSE file.
12005-
12006-package cache
12007-
12008-// This file defines gopls' driver for modular static analysis (go/analysis).
12009-
12010-import (
12011-	"bytes"
12012-	"context"
12013-	"crypto/sha256"
12014-	"encoding/gob"
12015-	"encoding/json"
12016-	"errors"
12017-	"fmt"
12018-	"go/ast"
12019-	"go/token"
12020-	"go/types"
12021-	"log"
12022-	"reflect"
12023-	"runtime/debug"
12024-	"sort"
12025-	"strings"
12026-	"sync"
12027-	"time"
12028-
12029-	"golang.org/x/sync/errgroup"
12030-	"golang.org/x/tools/go/analysis"
12031-	"golang.org/x/tools/gopls/internal/lsp/filecache"
12032-	"golang.org/x/tools/gopls/internal/lsp/protocol"
12033-	"golang.org/x/tools/gopls/internal/lsp/source"
12034-	"golang.org/x/tools/internal/bug"
12035-	"golang.org/x/tools/internal/facts"
12036-	"golang.org/x/tools/internal/gcimporter"
12037-	"golang.org/x/tools/internal/memoize"
12038-	"golang.org/x/tools/internal/typeparams"
12039-	"golang.org/x/tools/internal/typesinternal"
12040-)
12041-
12042-/*
12043-
12044-   DESIGN
12045-
12046-   An analysis request is for a set of analyzers and an individual
12047-   package ID, notated (a*, p). The result is the set of diagnostics
12048-   for that package. It could easily be generalized to a set of
12049-   packages, (a*, p*), and perhaps should be, to improve performance
12050-   versus calling it in a loop.
12051-
12052-   The snapshot holds a cache (persistent.Map) of entries keyed by
12053-   (a*, p) pairs ("analysisKey") that have been requested so far. Some
12054-   of these entries may be invalidated during snapshot cloning after a
12055-   modification event.  The cache maps each (a*, p) to a promise of
12056-   the analysis result or "analysisSummary". The summary contains the
12057-   results of analysis (e.g. diagnostics) as well as the intermediate
12058-   results required by the recursion, such as serialized types and
12059-   facts.
12060-
12061-   The promise represents the result of a call to analyzeImpl, which
12062-   type-checks a package and then applies a graph of analyzers to it
12063-   in parallel postorder. (These graph edges are "horizontal": within
12064-   the same package.) First, analyzeImpl reads the source files of
12065-   package p, and obtains (recursively) the results of the "vertical"
12066-   dependencies (i.e. analyzers applied to the packages imported by
12067-   p). Only the subset of analyzers that use facts need be executed
12068-   recursively, but even if this subset is empty, the step is still
12069-   necessary because it provides type information. It is possible that
12070-   a package may need to be type-checked and analyzed twice, for
12071-   different subsets of analyzers, but the overlap is typically
12072-   insignificant.
12073-
12074-   With the file contents and the results of vertical dependencies,
12075-   analyzeImpl is then in a position to produce a key representing the
12076-   unit of work (parsing, type-checking, and analysis) that it has to
12077-   do. The key is a cryptographic hash of the "recipe" for this step,
12078-   including the Metadata, the file contents, the set of analyzers,
12079-   and the type and fact information from the vertical dependencies.
12080-
12081-   The key is sought in a machine-global persistent file-system based
12082-   cache. If this gopls process, or another gopls process on the same
12083-   machine, has already performed this analysis step, analyzeImpl will
12084-   make a cache hit and load the serialized summary of the results. If
12085-   not, it will have to proceed to type-checking and analysis, and
12086-   write a new cache entry. The entry contains serialized types
12087-   (export data) and analysis facts.
12088-
12089-   For types, we use "shallow" export data. Historically, the Go
12090-   compiler always produced a summary of the types for a given package
12091-   that included types from other packages that it indirectly
12092-   referenced: "deep" export data. This had the advantage that the
12093-   compiler (and analogous tools such as gopls) need only load one
12094-   file per direct import.  However, it meant that the files tended to
12095-   get larger based on the level of the package in the import
12096-   graph. For example, higher-level packages in the kubernetes module
12097-   have over 1MB of "deep" export data, even when they have almost no
12098-   content of their own, merely because they mention a major type that
12099-   references many others. In pathological cases the export data was
12100-   300x larger than the source for a package due to this quadratic
12101-   growth.
12102-
12103-   "Shallow" export data means that the serialized types describe only
12104-   a single package. If those types mention types from other packages,
12105-   the type checker may need to request additional packages beyond
12106-   just the direct imports. This means type information for the entire
12107-   transitive closure of imports may need to be available just in
12108-   case. After a cache hit or a cache miss, the summary is
12109-   postprocessed so that it contains the union of export data payloads
12110-   of all its direct dependencies.
12111-
12112-   For correct dependency analysis, the digest used as a cache key
12113-   must reflect the "deep" export data, so it is derived recursively
12114-   from the transitive closure. As an optimization, we needn't include
12115-   every package of the transitive closure in the deep hash, only the
12116-   packages that were actually requested by the type checker. This
12117-   allows changes to a package that have no effect on its export data
12118-   to be "pruned". The direct consumer will need to be re-executed,
12119-   but if its export data is unchanged as a result, then indirect
12120-   consumers may not need to be re-executed.  This allows, for example,
12121-   one to insert a print statement in a function and not "rebuild" the
12122-   whole application (though export data does record line numbers of
12123-   types which may be perturbed by otherwise insignificant changes.)
12124-
12125-   The summary must record whether a package is transitively
12126-   error-free (whether it would compile) because many analyzers are
12127-   not safe to run on packages with inconsistent types.
12128-
12129-   For fact encoding, we use the same fact set as the unitchecker
12130-   (vet) to record and serialize analysis facts. The fact
12131-   serialization mechanism is analogous to "deep" export data.
12132-
12133-*/
12134-
12135-// TODO(adonovan):
12136-// - Profile + optimize:
12137-//   - on a cold run, mostly type checking + export data, unsurprisingly.
12138-//   - on a hot-disk run, mostly type checking the IWL.
12139-//     Would be nice to have a benchmark that separates this out.
12140-//   - measure and record in the code the typical operation times
12141-//     and file sizes (export data + facts = cache entries).
12142-// - Do "port the old logic" tasks (see TODO in actuallyAnalyze).
12143-// - Add a (white-box) test of pruning when a change doesn't affect export data.
12144-// - Optimise pruning based on subset of packages mentioned in exportdata.
12145-// - Better logging so that it is possible to deduce why an analyzer
12146-//   is not being run--often due to very indirect failures.
12147-//   Even if the ultimate consumer decides to ignore errors,
12148-//   tests and other situations want to be assured of freedom from
12149-//   errors, not just missing results. This should be recorded.
12150-// - Check that the event trace is intelligible.
12151-// - Split this into a subpackage, gopls/internal/lsp/cache/driver,
12152-//   consisting of this file and three helpers from errors.go.
12153-//   The (*snapshot).Analyze method would stay behind and make calls
12154-//   to the driver package.
12155-//   Steps:
12156-//   - define a narrow driver.Snapshot interface with only these methods:
12157-//        Metadata(PackageID) source.Metadata
12158-//        GetFile(Context, URI) (source.FileHandle, error)
12159-//        View() *View // for Options
12160-//   - define a State type that encapsulates the persistent map
12161-//     (with its own mutex), and has methods:
12162-//        New() *State
12163-//        Clone(invalidate map[PackageID]bool) *State
12164-//        Destroy()
12165-//   - share cache.{goVersionRx,parseGoImpl}
12166-
12167-var born = time.Now()
12168-
12169-// Analyze applies a set of analyzers to the package denoted by id,
12170-// and returns their diagnostics for that package.
12171-//
12172-// The analyzers list must be duplicate free; order does not matter.
12173-//
12174-// Precondition: all analyzers within the process have distinct names.
12175-// (The names are relied on by the serialization logic.)
12176-func (s *snapshot) Analyze(ctx context.Context, id PackageID, analyzers []*source.Analyzer) ([]*source.Diagnostic, error) {
12177-	if false { // debugging
12178-		log.Println("Analyze@", time.Since(born)) // called after the 7s IWL in k8s
12179-	}
12180-
12181-	// Filter and sort enabled root analyzers.
12182-	// A disabled analyzer may still be run if required by another.
12183-	toSrc := make(map[*analysis.Analyzer]*source.Analyzer)
12184-	var enabled []*analysis.Analyzer
12185-	for _, a := range analyzers {
12186-		if a.IsEnabled(s.view.Options()) {
12187-			toSrc[a.Analyzer] = a
12188-			enabled = append(enabled, a.Analyzer)
12189-		}
12190-	}
12191-	sort.Slice(enabled, func(i, j int) bool {
12192-		return enabled[i].Name < enabled[j].Name
12193-	})
12194-
12195-	// Register fact types of required analyzers.
12196-	for _, a := range requiredAnalyzers(enabled) {
12197-		for _, f := range a.FactTypes {
12198-			gob.Register(f)
12199-		}
12200-	}
12201-
12202-	if false { // debugging
12203-		// TODO(adonovan): use proper tracing.
12204-		t0 := time.Now()
12205-		defer func() {
12206-			log.Printf("%v for analyze(%s, %s)", time.Since(t0), id, enabled)
12207-		}()
12208-	}
12209-
12210-	// Run the analysis.
12211-	res, err := s.analyze(ctx, id, enabled)
12212-	if err != nil {
12213-		return nil, err
12214-	}
12215-
12216-	// Report diagnostics only from enabled actions that succeeded.
12217-	// Errors from creating or analyzing packages are ignored.
12218-	// Diagnostics are reported in the order of the analyzers argument.
12219-	//
12220-	// TODO(adonovan): ignoring action errors gives the caller no way
12221-	// to distinguish "there are no problems in this code" from
12222-	// "the code (or analyzers!) are so broken that we couldn't even
12223-	// begin the analysis you asked for".
12224-	// Even if current callers choose to discard the
12225-	// results, we should propagate the per-action errors.
12226-	var results []*source.Diagnostic
12227-	for _, a := range enabled {
12228-		summary := res.Actions[a.Name]
12229-		if summary.Err != "" {
12230-			continue // action failed
12231-		}
12232-		for _, gobDiag := range summary.Diagnostics {
12233-			results = append(results, toSourceDiagnostic(toSrc[a], &gobDiag))
12234-		}
12235-	}
12236-	return results, nil
12237-}
12238-
12239-// analysisKey is the type of keys in the snapshot.analyses map.
12240-type analysisKey struct {
12241-	analyzerNames string
12242-	pkgid         PackageID
12243-}
12244-
12245-func (key analysisKey) String() string {
12246-	return fmt.Sprintf("%s@%s", key.analyzerNames, key.pkgid)
12247-}
12248-
12249-// analyzeSummary is a gob-serializable summary of successfully
12250-// applying a list of analyzers to a package.
12251-type analyzeSummary struct {
12252-	PkgPath        PackagePath // types.Package.Path() (needed to decode export data)
12253-	Export         []byte
12254-	DeepExportHash source.Hash // hash of reflexive transitive closure of export data
12255-	Compiles       bool        // transitively free of list/parse/type errors
12256-	Actions        actionsMap  // map from analyzer name to analysis results (*actionSummary)
12257-
12258-	// Not serialized: populated after the summary is computed or deserialized.
12259-	allExport map[PackagePath][]byte // transitive export data
12260-}
12261-
12262-// actionsMap defines a stable Gob encoding for a map.
12263-// TODO(adonovan): generalize and move to a library when we can use generics.
12264-type actionsMap map[string]*actionSummary
12265-
12266-var _ gob.GobEncoder = (actionsMap)(nil)
12267-var _ gob.GobDecoder = (*actionsMap)(nil)
12268-
12269-type actionsMapEntry struct {
12270-	K string
12271-	V *actionSummary
12272-}
12273-
12274-func (m actionsMap) GobEncode() ([]byte, error) {
12275-	entries := make([]actionsMapEntry, 0, len(m))
12276-	for k, v := range m {
12277-		entries = append(entries, actionsMapEntry{k, v})
12278-	}
12279-	sort.Slice(entries, func(i, j int) bool {
12280-		return entries[i].K < entries[j].K
12281-	})
12282-	var buf bytes.Buffer
12283-	err := gob.NewEncoder(&buf).Encode(entries)
12284-	return buf.Bytes(), err
12285-}
12286-
12287-func (m *actionsMap) GobDecode(data []byte) error {
12288-	var entries []actionsMapEntry
12289-	if err := gob.NewDecoder(bytes.NewReader(data)).Decode(&entries); err != nil {
12290-		return err
12291-	}
12292-	*m = make(actionsMap, len(entries))
12293-	for _, e := range entries {
12294-		(*m)[e.K] = e.V
12295-	}
12296-	return nil
12297-}
12298-
12299-// actionSummary is a gob-serializable summary of one possibly failed analysis action.
12300-// If Err is non-empty, the other fields are undefined.
12301-type actionSummary struct {
12302-	Facts       []byte      // the encoded facts.Set
12303-	FactsHash   source.Hash // hash(Facts)
12304-	Diagnostics []gobDiagnostic
12305-	Err         string // "" => success
12306-}
12307-
12308-// analyze is a memoization of analyzeImpl.
12309-func (s *snapshot) analyze(ctx context.Context, id PackageID, analyzers []*analysis.Analyzer) (*analyzeSummary, error) {
12310-	// Use the sorted list of names of analyzers in the key.
12311-	//
12312-	// TODO(adonovan): opt: account for analysis results at a
12313-	// finer grain to avoid duplicate work when a
12314-	// a proper subset of analyzers is requested?
12315-	// In particular, TypeErrorAnalyzers don't use facts
12316-	// but need to request vdeps just for type information.
12317-	names := make([]string, 0, len(analyzers))
12318-	for _, a := range analyzers {
12319-		names = append(names, a.Name)
12320-	}
12321-	// This key describes the result of applying a list of analyzers to a package.
12322-	key := analysisKey{strings.Join(names, ","), id}
12323-
12324-	// An analysisPromise represents the result of loading, parsing,
12325-	// type-checking and analyzing a single package.
12326-	type analysisPromise struct {
12327-		promise *memoize.Promise // [analyzeImplResult]
12328-	}
12329-
12330-	type analyzeImplResult struct {
12331-		summary *analyzeSummary
12332-		err     error
12333-	}
12334-
12335-	// Access the map once, briefly, and atomically.
12336-	s.mu.Lock()
12337-	entry, hit := s.analyses.Get(key)
12338-	if !hit {
12339-		entry = analysisPromise{
12340-			promise: memoize.NewPromise("analysis", func(ctx context.Context, arg interface{}) interface{} {
12341-				summary, err := analyzeImpl(ctx, arg.(*snapshot), analyzers, id)
12342-				return analyzeImplResult{summary, err}
12343-			}),
12344-		}
12345-		s.analyses.Set(key, entry, nil) // nothing needs releasing
12346-	}
12347-	s.mu.Unlock()
12348-
12349-	// Await result.
12350-	ap := entry.(analysisPromise)
12351-	v, err := s.awaitPromise(ctx, ap.promise)
12352-	if err != nil {
12353-		return nil, err // e.g. cancelled
12354-	}
12355-	res := v.(analyzeImplResult)
12356-	return res.summary, res.err
12357-}
12358-
12359-// analyzeImpl applies a list of analyzers (plus any others
12360-// transitively required by them) to a package.  It succeeds as long
12361-// as it could produce a types.Package, even if there were direct or
12362-// indirect list/parse/type errors, and even if all the analysis
12363-// actions failed. It usually fails only if the package was unknown,
12364-// a file was missing, or the operation was cancelled.
12365-//
12366-// Postcondition: analyzeImpl must not continue to use the snapshot
12367-// (in background goroutines) after it has returned; see memoize.RefCounted.
12368-func analyzeImpl(ctx context.Context, snapshot *snapshot, analyzers []*analysis.Analyzer, id PackageID) (*analyzeSummary, error) {
12369-	m := snapshot.Metadata(id)
12370-	if m == nil {
12371-		return nil, fmt.Errorf("no metadata for %s", id)
12372-	}
12373-
12374-	// Recursively analyze each "vertical" dependency
12375-	// for its types.Package and (perhaps) analysis.Facts.
12376-	// If any of them fails to produce a package, we cannot continue.
12377-	// We request only the analyzers that produce facts.
12378-	//
12379-	// Also, load the contents of each "compiled" Go file through
12380-	// the snapshot's cache.
12381-	//
12382-	// Both loops occur in parallel, and parallel with each other.
12383-	vdeps := make(map[PackageID]*analyzeSummary)
12384-	compiledGoFiles := make([]source.FileHandle, len(m.CompiledGoFiles))
12385-	{
12386-		var group errgroup.Group
12387-
12388-		// Analyze vertical dependencies.
12389-		// We request only the required analyzers that use facts.
12390-		var useFacts []*analysis.Analyzer
12391-		for _, a := range requiredAnalyzers(analyzers) {
12392-			if len(a.FactTypes) > 0 {
12393-				useFacts = append(useFacts, a)
12394-			}
12395-		}
12396-		var vdepsMu sync.Mutex
12397-		for _, id := range m.DepsByPkgPath {
12398-			id := id
12399-			group.Go(func() error {
12400-				res, err := snapshot.analyze(ctx, id, useFacts)
12401-				if err != nil {
12402-					return err // cancelled, or failed to produce a package
12403-				}
12404-
12405-				vdepsMu.Lock()
12406-				vdeps[id] = res
12407-				vdepsMu.Unlock()
12408-				return nil
12409-			})
12410-		}
12411-
12412-		// Read file contents.
12413-		// (In practice these will be cache hits
12414-		// on reads done by the initial workspace load
12415-		// or after a change modification event.)
12416-		for i, uri := range m.CompiledGoFiles {
12417-			i, uri := i, uri
12418-			group.Go(func() error {
12419-				fh, err := snapshot.GetFile(ctx, uri) // ~25us
12420-				compiledGoFiles[i] = fh
12421-				return err // e.g. cancelled
12422-			})
12423-		}
12424-
12425-		if err := group.Wait(); err != nil {
12426-			return nil, err
12427-		}
12428-	}
12429-
12430-	// Inv: analyze() of all vdeps succeeded (though some actions may have failed).
12431-
12432-	// We no longer depend on the snapshot.
12433-	snapshot = nil
12434-
12435-	// At this point we have the action results (serialized
12436-	// packages and facts) of our immediate dependencies,
12437-	// and the metadata and content of this package.
12438-	//
12439-	// We now compute a hash for all our inputs, and consult a
12440-	// global cache of promised results. If nothing material
12441-	// has changed, we'll make a hit in the shared cache.
12442-	//
12443-	// The hash of our inputs is based on the serialized export
12444-	// data and facts so that immaterial changes can be pruned
12445-	// without decoding.
12446-	key := analysisCacheKey(analyzers, m, compiledGoFiles, vdeps)
12447-
12448-	// Access the cache.
12449-	var summary *analyzeSummary
12450-	const cacheKind = "analysis"
12451-	if data, err := filecache.Get(cacheKind, key); err == nil {
12452-		// cache hit
12453-		mustDecode(data, &summary)
12454-
12455-	} else if err != filecache.ErrNotFound {
12456-		return nil, bug.Errorf("internal error reading shared cache: %v", err)
12457-
12458-	} else {
12459-		// Cache miss: do the work.
12460-		var err error
12461-		summary, err = actuallyAnalyze(ctx, analyzers, m, vdeps, compiledGoFiles)
12462-		if err != nil {
12463-			return nil, err
12464-		}
12465-		data := mustEncode(summary)
12466-		if false {
12467-			log.Printf("Set key=%d value=%d id=%s\n", len(key), len(data), id)
12468-		}
12469-		if err := filecache.Set(cacheKind, key, data); err != nil {
12470-			return nil, fmt.Errorf("internal error updating shared cache: %v", err)
12471-		}
12472-	}
12473-
12474-	// Hit or miss, we need to merge the export data from
12475-	// dependencies so that it includes all the types
12476-	// that might be summoned by the type checker.
12477-	//
12478-	// TODO(adonovan): opt: reduce this set by recording
12479-	// which packages were actually summoned by insert().
12480-	// (Just makes map smaller; probably marginal?)
12481-	allExport := make(map[PackagePath][]byte)
12482-	for _, vdep := range vdeps {
12483-		for k, v := range vdep.allExport {
12484-			allExport[k] = v
12485-		}
12486-	}
12487-	allExport[m.PkgPath] = summary.Export
12488-	summary.allExport = allExport
12489-
12490-	return summary, nil
12491-}
12492-
12493-// analysisCacheKey returns a cache key that is a cryptographic digest
12494-// of the all the values that might affect type checking and analysis:
12495-// the analyzer names, package metadata, names and contents of
12496-// compiled Go files, and vdeps information (export data and facts).
12497-//
12498-// TODO(adonovan): safety: define our own flavor of Metadata
12499-// containing just the fields we need, and using it in the subsequent
12500-// logic, to keep us honest about hashing all parts that matter?
12501-func analysisCacheKey(analyzers []*analysis.Analyzer, m *source.Metadata, compiledGoFiles []source.FileHandle, vdeps map[PackageID]*analyzeSummary) [sha256.Size]byte {
12502-	hasher := sha256.New()
12503-
12504-	// In principle, a key must be the hash of an
12505-	// unambiguous encoding of all the relevant data.
12506-	// If it's ambiguous, we risk collisions.
12507-
12508-	// analyzers
12509-	fmt.Fprintf(hasher, "analyzers: %d\n", len(analyzers))
12510-	for _, a := range analyzers {
12511-		fmt.Fprintln(hasher, a.Name)
12512-	}
12513-
12514-	// package metadata
12515-	fmt.Fprintf(hasher, "package: %s %s %s\n", m.ID, m.Name, m.PkgPath)
12516-	// We can ignore m.DepsBy{Pkg,Import}Path: although the logic
12517-	// uses those fields, we account for them by hashing vdeps.
12518-
12519-	// type sizes
12520-	// This assertion is safe, but if a black-box implementation
12521-	// is ever needed, record Sizeof(*int) and Alignof(int64).
12522-	sz := m.TypesSizes.(*types.StdSizes)
12523-	fmt.Fprintf(hasher, "sizes: %d %d\n", sz.WordSize, sz.MaxAlign)
12524-
12525-	// metadata errors: used for 'compiles' field
12526-	fmt.Fprintf(hasher, "errors: %d", len(m.Errors))
12527-
12528-	// module Go version
12529-	if m.Module != nil && m.Module.GoVersion != "" {
12530-		fmt.Fprintf(hasher, "go %s\n", m.Module.GoVersion)
12531-	}
12532-
12533-	// file names and contents
12534-	fmt.Fprintf(hasher, "files: %d\n", len(compiledGoFiles))
12535-	for _, fh := range compiledGoFiles {
12536-		fmt.Fprintln(hasher, fh.FileIdentity())
12537-	}
12538-
12539-	// vdeps, in PackageID order
12540-	depIDs := make([]string, 0, len(vdeps))
12541-	for depID := range vdeps {
12542-		depIDs = append(depIDs, string(depID))
12543-	}
12544-	sort.Strings(depIDs)
12545-	for _, depID := range depIDs {
12546-		vdep := vdeps[PackageID(depID)]
12547-		fmt.Fprintf(hasher, "dep: %s\n", vdep.PkgPath)
12548-		fmt.Fprintf(hasher, "export: %s\n", vdep.DeepExportHash)
12549-
12550-		// action results: errors and facts
12551-		names := make([]string, 0, len(vdep.Actions))
12552-		for name := range vdep.Actions {
12553-			names = append(names, name)
12554-		}
12555-		sort.Strings(names)
12556-		for _, name := range names {
12557-			summary := vdep.Actions[name]
12558-			fmt.Fprintf(hasher, "action %s\n", name)
12559-			if summary.Err != "" {
12560-				fmt.Fprintf(hasher, "error %s\n", summary.Err)
12561-			} else {
12562-				fmt.Fprintf(hasher, "facts %s\n", summary.FactsHash)
12563-				// We can safely omit summary.diagnostics
12564-				// from the key since they have no downstream effect.
12565-			}
12566-		}
12567-	}
12568-
12569-	var hash [sha256.Size]byte
12570-	hasher.Sum(hash[:0])
12571-	return hash
12572-}
12573-
12574-// actuallyAnalyze implements the cache-miss case.
12575-// This function does not access the snapshot.
12576-func actuallyAnalyze(ctx context.Context, analyzers []*analysis.Analyzer, m *source.Metadata, vdeps map[PackageID]*analyzeSummary, compiledGoFiles []source.FileHandle) (*analyzeSummary, error) {
12577-
12578-	// Create a local FileSet for processing this package only.
12579-	fset := token.NewFileSet()
12580-
12581-	// Parse only the "compiled" Go files.
12582-	// Do the computation in parallel.
12583-	parsed := make([]*source.ParsedGoFile, len(compiledGoFiles))
12584-	{
12585-		var group errgroup.Group
12586-		for i, fh := range compiledGoFiles {
12587-			i, fh := i, fh
12588-			group.Go(func() error {
12589-				// Call parseGoImpl directly, not the caching wrapper,
12590-				// as cached ASTs require the global FileSet.
12591-				pgf, err := parseGoImpl(ctx, fset, fh, source.ParseFull)
12592-				parsed[i] = pgf
12593-				return err
12594-			})
12595-		}
12596-		if err := group.Wait(); err != nil {
12597-			return nil, err // cancelled, or catastrophic error (e.g. missing file)
12598-		}
12599-	}
12600-
12601-	// Type-check the package.
12602-	pkg := typeCheckForAnalysis(fset, parsed, m, vdeps)
12603-
12604-	// Build a map of PkgPath to *Package for all packages mentioned
12605-	// in exportdata for use by facts.
12606-	pkg.factsDecoder = facts.NewDecoder(pkg.types)
12607-
12608-	// Poll cancellation state.
12609-	if err := ctx.Err(); err != nil {
12610-		return nil, err
12611-	}
12612-
12613-	// TODO(adonovan): port the old logic to:
12614-	// - gather go/packages diagnostics from m.Errors? (port goPackagesErrorDiagnostics)
12615-	// - record unparseable file URIs so we can suppress type errors for these files.
12616-	// - gather diagnostics from expandErrors + typeErrorDiagnostics + depsErrors.
12617-
12618-	// -- analysis --
12619-
12620-	// Build action graph for this package.
12621-	// Each graph node (action) is one unit of analysis.
12622-	actions := make(map[*analysis.Analyzer]*action)
12623-	var mkAction func(a *analysis.Analyzer) *action
12624-	mkAction = func(a *analysis.Analyzer) *action {
12625-		act, ok := actions[a]
12626-		if !ok {
12627-			var hdeps []*action
12628-			for _, req := range a.Requires {
12629-				hdeps = append(hdeps, mkAction(req))
12630-			}
12631-			act = &action{a: a, pkg: pkg, vdeps: vdeps, hdeps: hdeps}
12632-			actions[a] = act
12633-		}
12634-		return act
12635-	}
12636-
12637-	// Build actions for initial package.
12638-	var roots []*action
12639-	for _, a := range analyzers {
12640-		roots = append(roots, mkAction(a))
12641-	}
12642-
12643-	// Execute the graph in parallel.
12644-	execActions(roots)
12645-
12646-	// Don't return (or cache) the result in case of cancellation.
12647-	if err := ctx.Err(); err != nil {
12648-		return nil, err // cancelled
12649-	}
12650-
12651-	// Return summaries only for the requested actions.
12652-	summaries := make(map[string]*actionSummary)
12653-	for _, act := range roots {
12654-		summaries[act.a.Name] = act.summary
12655-	}
12656-
12657-	return &analyzeSummary{
12658-		PkgPath:        PackagePath(pkg.types.Path()),
12659-		Export:         pkg.export,
12660-		DeepExportHash: pkg.deepExportHash,
12661-		Compiles:       pkg.compiles,
12662-		Actions:        summaries,
12663-	}, nil
12664-}
12665-
12666-func typeCheckForAnalysis(fset *token.FileSet, parsed []*source.ParsedGoFile, m *source.Metadata, vdeps map[PackageID]*analyzeSummary) *analysisPackage {
12667-	if false { // debugging
12668-		log.Println("typeCheckForAnalysis", m.PkgPath)
12669-	}
12670-
12671-	pkg := &analysisPackage{
12672-		m:        m,
12673-		fset:     fset,
12674-		parsed:   parsed,
12675-		files:    make([]*ast.File, len(parsed)),
12676-		compiles: len(m.Errors) == 0, // false => list error
12677-		types:    types.NewPackage(string(m.PkgPath), string(m.Name)),
12678-		typesInfo: &types.Info{
12679-			Types:      make(map[ast.Expr]types.TypeAndValue),
12680-			Defs:       make(map[*ast.Ident]types.Object),
12681-			Uses:       make(map[*ast.Ident]types.Object),
12682-			Implicits:  make(map[ast.Node]types.Object),
12683-			Selections: make(map[*ast.SelectorExpr]*types.Selection),
12684-			Scopes:     make(map[ast.Node]*types.Scope),
12685-		},
12686-		typesSizes: m.TypesSizes,
12687-	}
12688-	typeparams.InitInstanceInfo(pkg.typesInfo)
12689-
12690-	for i, p := range parsed {
12691-		pkg.files[i] = p.File
12692-		if p.ParseErr != nil {
12693-			pkg.compiles = false // parse error
12694-		}
12695-	}
12696-
12697-	// Unsafe is special.
12698-	if m.PkgPath == "unsafe" {
12699-		pkg.types = types.Unsafe
12700-		return pkg
12701-	}
12702-
12703-	// Compute the union of transitive export data.
12704-	// (The actual values are shared, and not serialized.)
12705-	allExport := make(map[PackagePath][]byte)
12706-	for _, vdep := range vdeps {
12707-		for k, v := range vdep.allExport {
12708-			allExport[k] = v
12709-		}
12710-
12711-		if !vdep.Compiles {
12712-			pkg.compiles = false // transitive error
12713-		}
12714-	}
12715-
12716-	// exportHasher computes a hash of the names and export data of
12717-	// each package that was actually loaded during type checking.
12718-	//
12719-	// Because we use shallow export data, the hash for dependency
12720-	// analysis must incorporate indirect dependencies. As an
12721-	// optimization, we include only those that were actually
12722-	// used, which may be a small subset of those available.
12723-	//
12724-	// TODO(adonovan): opt: even better would be to implement a
12725-	// traversal over the package API like facts.NewDecoder does
12726-	// and only mention that set of packages in the hash.
12727-	// Perhaps there's a way to do that more efficiently.
12728-	//
12729-	// TODO(adonovan): opt: record the shallow hash alongside the
12730-	// shallow export data in the allExport map to avoid repeatedly
12731-	// hashing the export data.
12732-	//
12733-	// The writes to hasher below assume that type checking imports
12734-	// packages in a deterministic order.
12735-	exportHasher := sha256.New()
12736-	hashExport := func(pkgPath PackagePath, export []byte) {
12737-		fmt.Fprintf(exportHasher, "%s %d ", pkgPath, len(export))
12738-		exportHasher.Write(export)
12739-	}
12740-
12741-	// importer state
12742-	var (
12743-		insert    func(p *types.Package, name string)
12744-		importMap = make(map[string]*types.Package) // keys are PackagePaths
12745-	)
12746-	loadFromExportData := func(pkgPath PackagePath) (*types.Package, error) {
12747-		export, ok := allExport[pkgPath]
12748-		if !ok {
12749-			return nil, bug.Errorf("missing export data for %q", pkgPath)
12750-		}
12751-		hashExport(pkgPath, export)
12752-		imported, err := gcimporter.IImportShallow(fset, importMap, export, string(pkgPath), insert)
12753-		if err != nil {
12754-			return nil, bug.Errorf("invalid export data for %q: %v", pkgPath, err)
12755-		}
12756-		return imported, nil
12757-	}
12758-	insert = func(p *types.Package, name string) {
12759-		imported, err := loadFromExportData(PackagePath(p.Path()))
12760-		if err != nil {
12761-			log.Fatalf("internal error: %v", err)
12762-		}
12763-		if imported != p {
12764-			log.Fatalf("internal error: inconsistent packages")
12765-		}
12766-	}
12767-
12768-	cfg := &types.Config{
12769-		Sizes: m.TypesSizes,
12770-		Error: func(e error) {
12771-			pkg.compiles = false // type error
12772-			pkg.typeErrors = append(pkg.typeErrors, e.(types.Error))
12773-		},
12774-		Importer: importerFunc(func(importPath string) (*types.Package, error) {
12775-			if importPath == "unsafe" {
12776-				return types.Unsafe, nil // unsafe has no export data
12777-			}
12778-
12779-			// Beware that returning an error from this function
12780-			// will cause the type checker to synthesize a fake
12781-			// package whose Path is importPath, potentially
12782-			// losing a vendor/ prefix. If type-checking errors
12783-			// are swallowed, these packages may be confusing.
12784-
12785-			id, ok := m.DepsByImpPath[ImportPath(importPath)]
12786-			if !ok {
12787-				// The import syntax is inconsistent with the metadata.
12788-				// This could be because the import declaration was
12789-				// incomplete and the metadata only includes complete
12790-				// imports; or because the metadata ignores import
12791-				// edges that would lead to cycles in the graph.
12792-				return nil, fmt.Errorf("missing metadata for import of %q", importPath)
12793-			}
12794-
12795-			depResult, ok := vdeps[id] // id may be ""
12796-			if !ok {
12797-				// Analogous to (*snapshot).missingPkgError
12798-				// in the logic for regular type-checking,
12799-				// but without a snapshot we can't provide
12800-				// such detail, and anyway most analysis
12801-				// failures aren't surfaced in the UI.
12802-				return nil, fmt.Errorf("no required module provides package %q (id=%q)", importPath, id)
12803-			}
12804-
12805-			// (Duplicates logic from check.go.)
12806-			if !source.IsValidImport(m.PkgPath, depResult.PkgPath) {
12807-				return nil, fmt.Errorf("invalid use of internal package %s", importPath)
12808-			}
12809-
12810-			return loadFromExportData(depResult.PkgPath)
12811-		}),
12812-	}
12813-
12814-	// Set Go dialect.
12815-	if m.Module != nil && m.Module.GoVersion != "" {
12816-		goVersion := "go" + m.Module.GoVersion
12817-		// types.NewChecker panics if GoVersion is invalid.
12818-		// An unparsable mod file should probably stop us
12819-		// before we get here, but double check just in case.
12820-		if goVersionRx.MatchString(goVersion) {
12821-			typesinternal.SetGoVersion(cfg, goVersion)
12822-		}
12823-	}
12824-
12825-	// We want to type check cgo code if go/types supports it.
12826-	// We passed typecheckCgo to go/packages when we Loaded.
12827-	// TODO(adonovan): do we actually need this??
12828-	typesinternal.SetUsesCgo(cfg)
12829-
12830-	check := types.NewChecker(cfg, fset, pkg.types, pkg.typesInfo)
12831-
12832-	// Type checking errors are handled via the config, so ignore them here.
12833-	_ = check.Files(pkg.files)
12834-
12835-	// debugging (type errors are quite normal)
12836-	if false {
12837-		if pkg.typeErrors != nil {
12838-			log.Printf("package %s has type errors: %v", pkg.types.Path(), pkg.typeErrors)
12839-		}
12840-	}
12841-
12842-	// Emit the export data and compute the deep hash.
12843-	export, err := gcimporter.IExportShallow(pkg.fset, pkg.types)
12844-	if err != nil {
12845-		// TODO(adonovan): in light of exporter bugs such as #57729,
12846-		// consider using bug.Report here and retrying the IExportShallow
12847-		// call here using an empty types.Package.
12848-		log.Fatalf("internal error writing shallow export data: %v", err)
12849-	}
12850-	pkg.export = export
12851-	hashExport(m.PkgPath, export)
12852-	exportHasher.Sum(pkg.deepExportHash[:0])
12853-
12854-	return pkg
12855-}
12856-
12857-// analysisPackage contains information about a package, including
12858-// syntax trees, used transiently during its type-checking and analysis.
12859-type analysisPackage struct {
12860-	m              *source.Metadata
12861-	fset           *token.FileSet // local to this package
12862-	parsed         []*source.ParsedGoFile
12863-	files          []*ast.File // same as parsed[i].File
12864-	types          *types.Package
12865-	compiles       bool // package is transitively free of list/parse/type errors
12866-	factsDecoder   *facts.Decoder
12867-	export         []byte      // encoding of types.Package
12868-	deepExportHash source.Hash // reflexive transitive hash of export data
12869-	typesInfo      *types.Info
12870-	typeErrors     []types.Error
12871-	typesSizes     types.Sizes
12872-}
12873-
12874-// An action represents one unit of analysis work: the application of
12875-// one analysis to one package. Actions form a DAG, both within a
12876-// package (as different analyzers are applied, either in sequence or
12877-// parallel), and across packages (as dependencies are analyzed).
12878-type action struct {
12879-	once  sync.Once
12880-	a     *analysis.Analyzer
12881-	pkg   *analysisPackage
12882-	hdeps []*action                     // horizontal dependencies
12883-	vdeps map[PackageID]*analyzeSummary // vertical dependencies
12884-
12885-	// results of action.exec():
12886-	result  interface{} // result of Run function, of type a.ResultType
12887-	summary *actionSummary
12888-	err     error
12889-}
12890-
12891-func (act *action) String() string {
12892-	return fmt.Sprintf("%s@%s", act.a.Name, act.pkg.m.ID)
12893-}
12894-
12895-// execActions executes a set of action graph nodes in parallel.
12896-func execActions(actions []*action) {
12897-	var wg sync.WaitGroup
12898-	for _, act := range actions {
12899-		act := act
12900-		wg.Add(1)
12901-		go func() {
12902-			defer wg.Done()
12903-			act.once.Do(func() {
12904-				execActions(act.hdeps) // analyze "horizontal" dependencies
12905-				act.result, act.summary, act.err = act.exec()
12906-				if act.err != nil {
12907-					act.summary = &actionSummary{Err: act.err.Error()}
12908-					// TODO(adonovan): suppress logging. But
12909-					// shouldn't the root error's causal chain
12910-					// include this information?
12911-					if false { // debugging
12912-						log.Printf("act.exec(%v) failed: %v", act, act.err)
12913-					}
12914-				}
12915-			})
12916-		}()
12917-	}
12918-	wg.Wait()
12919-}
12920-
12921-// exec defines the execution of a single action.
12922-// It returns the (ephemeral) result of the analyzer's Run function,
12923-// along with its (serializable) facts and diagnostics.
12924-// Or it returns an error if the analyzer did not run to
12925-// completion and deliver a valid result.
12926-func (act *action) exec() (interface{}, *actionSummary, error) {
12927-	analyzer := act.a
12928-	pkg := act.pkg
12929-
12930-	hasFacts := len(analyzer.FactTypes) > 0
12931-
12932-	// Report an error if any action dependency (vertical or horizontal) failed.
12933-	// To avoid long error messages describing chains of failure,
12934-	// we return the dependencies' error' unadorned.
12935-	if hasFacts {
12936-		// TODO(adonovan): use deterministic order.
12937-		for _, res := range act.vdeps {
12938-			if vdep := res.Actions[analyzer.Name]; vdep.Err != "" {
12939-				return nil, nil, errors.New(vdep.Err)
12940-			}
12941-		}
12942-	}
12943-	for _, dep := range act.hdeps {
12944-		if dep.err != nil {
12945-			return nil, nil, dep.err
12946-		}
12947-	}
12948-	// Inv: all action dependencies succeeded.
12949-
12950-	// Were there list/parse/type errors that might prevent analysis?
12951-	if !pkg.compiles && !analyzer.RunDespiteErrors {
12952-		return nil, nil, fmt.Errorf("skipping analysis %q because package %q does not compile", analyzer.Name, pkg.m.ID)
12953-	}
12954-	// Inv: package is well-formed enough to proceed with analysis.
12955-
12956-	if false { // debugging
12957-		log.Println("action.exec", act)
12958-	}
12959-
12960-	// Gather analysis Result values from horizontal dependencies.
12961-	var inputs = make(map[*analysis.Analyzer]interface{})
12962-	for _, dep := range act.hdeps {
12963-		inputs[dep.a] = dep.result
12964-	}
12965-
12966-	// TODO(adonovan): opt: facts.Set works but it may be more
12967-	// efficient to fork and tailor it to our precise needs.
12968-	//
12969-	// We've already sharded the fact encoding by action
12970-	// so that it can be done in parallel (hoisting the
12971-	// ImportMap call so that we build the map once per package).
12972-	// We could eliminate locking.
12973-	// We could also dovetail more closely with the export data
12974-	// decoder to obtain a more compact representation of
12975-	// packages and objects (e.g. its internal IDs, instead
12976-	// of PkgPaths and objectpaths.)
12977-
12978-	// Read and decode analysis facts for each imported package.
12979-	factset, err := pkg.factsDecoder.Decode(func(imp *types.Package) ([]byte, error) {
12980-		if !hasFacts {
12981-			return nil, nil // analyzer doesn't use facts, so no vdeps
12982-		}
12983-
12984-		// Package.Imports() may contain a fake "C" package. Ignore it.
12985-		if imp.Path() == "C" {
12986-			return nil, nil
12987-		}
12988-
12989-		id, ok := pkg.m.DepsByPkgPath[PackagePath(imp.Path())]
12990-		if !ok {
12991-			// This may mean imp was synthesized by the type
12992-			// checker because it failed to import it for any reason
12993-			// (e.g. bug processing export data; metadata ignoring
12994-			// a cycle-forming import).
12995-			// In that case, the fake package's imp.Path
12996-			// is set to the failed importPath (and thus
12997-			// it may lack a "vendor/" prefix).
12998-			//
12999-			// For now, silently ignore it on the assumption
13000-			// that the error is already reported elsewhere.
13001-			// return nil, fmt.Errorf("missing metadata")
13002-			return nil, nil
13003-		}
13004-
13005-		vdep, ok := act.vdeps[id]
13006-		if !ok {
13007-			return nil, bug.Errorf("internal error in %s: missing vdep for id=%s", pkg.types.Path(), id)
13008-		}
13009-		return vdep.Actions[analyzer.Name].Facts, nil
13010-	})
13011-	if err != nil {
13012-		return nil, nil, fmt.Errorf("internal error decoding analysis facts: %w", err)
13013-	}
13014-
13015-	// TODO(adonovan): make Export*Fact panic rather than discarding
13016-	// undeclared fact types, so that we discover bugs in analyzers.
13017-	factFilter := make(map[reflect.Type]bool)
13018-	for _, f := range analyzer.FactTypes {
13019-		factFilter[reflect.TypeOf(f)] = true
13020-	}
13021-
13022-	// posToLocation converts from token.Pos to protocol form.
13023-	// TODO(adonovan): improve error messages.
13024-	posToLocation := func(start, end token.Pos) (protocol.Location, error) {
13025-		tokFile := pkg.fset.File(start)
13026-		for _, p := range pkg.parsed {
13027-			if p.Tok == tokFile {
13028-				if end == token.NoPos {
13029-					end = start
13030-				}
13031-				return p.PosLocation(start, end)
13032-			}
13033-		}
13034-		return protocol.Location{},
13035-			bug.Errorf("internal error: token.Pos not within package")
13036-	}
13037-
13038-	// Now run the (pkg, analyzer) action.
13039-	var diagnostics []gobDiagnostic
13040-	pass := &analysis.Pass{
13041-		Analyzer:   analyzer,
13042-		Fset:       pkg.fset,
13043-		Files:      pkg.files,
13044-		Pkg:        pkg.types,
13045-		TypesInfo:  pkg.typesInfo,
13046-		TypesSizes: pkg.typesSizes,
13047-		TypeErrors: pkg.typeErrors,
13048-		ResultOf:   inputs,
13049-		Report: func(d analysis.Diagnostic) {
13050-			// Prefix the diagnostic category with the analyzer's name.
13051-			if d.Category == "" {
13052-				d.Category = analyzer.Name
13053-			} else {
13054-				d.Category = analyzer.Name + "." + d.Category
13055-			}
13056-
13057-			diagnostic, err := toGobDiagnostic(posToLocation, d)
13058-			if err != nil {
13059-				bug.Reportf("internal error converting diagnostic from analyzer %q: %v", analyzer.Name, err)
13060-				return
13061-			}
13062-			diagnostics = append(diagnostics, diagnostic)
13063-		},
13064-		ImportObjectFact:  factset.ImportObjectFact,
13065-		ExportObjectFact:  factset.ExportObjectFact,
13066-		ImportPackageFact: factset.ImportPackageFact,
13067-		ExportPackageFact: factset.ExportPackageFact,
13068-		AllObjectFacts:    func() []analysis.ObjectFact { return factset.AllObjectFacts(factFilter) },
13069-		AllPackageFacts:   func() []analysis.PackageFact { return factset.AllPackageFacts(factFilter) },
13070-	}
13071-
13072-	// Recover from panics (only) within the analyzer logic.
13073-	// (Use an anonymous function to limit the recover scope.)
13074-	var result interface{}
13075-	func() {
13076-		defer func() {
13077-			if r := recover(); r != nil {
13078-				// An Analyzer panicked, likely due to a bug.
13079-				//
13080-				// In general we want to discover and fix such panics quickly,
13081-				// so we don't suppress them, but some bugs in third-party
13082-				// analyzers cannot be quickly fixed, so we use an allowlist
13083-				// to suppress panics.
13084-				const strict = true
13085-				if strict && bug.PanicOnBugs &&
13086-					analyzer.Name != "buildir" { // see https://github.com/dominikh/go-tools/issues/1343
13087-					// Uncomment this when debugging suspected failures
13088-					// in the driver, not the analyzer.
13089-					if false {
13090-						debug.SetTraceback("all") // show all goroutines
13091-					}
13092-					panic(r)
13093-				} else {
13094-					// In production, suppress the panic and press on.
13095-					err = fmt.Errorf("analysis %s for package %s panicked: %v", analyzer.Name, pass.Pkg.Path(), r)
13096-				}
13097-			}
13098-		}()
13099-		result, err = pass.Analyzer.Run(pass)
13100-	}()
13101-	if err != nil {
13102-		return nil, nil, err
13103-	}
13104-
13105-	if got, want := reflect.TypeOf(result), pass.Analyzer.ResultType; got != want {
13106-		return nil, nil, bug.Errorf(
13107-			"internal error: on package %s, analyzer %s returned a result of type %v, but declared ResultType %v",
13108-			pass.Pkg.Path(), pass.Analyzer, got, want)
13109-	}
13110-
13111-	// Disallow Export*Fact calls after Run.
13112-	// (A panic means the Analyzer is abusing concurrency.)
13113-	pass.ExportObjectFact = func(obj types.Object, fact analysis.Fact) {
13114-		panic(fmt.Sprintf("%v: Pass.ExportObjectFact(%s, %T) called after Run", act, obj, fact))
13115-	}
13116-	pass.ExportPackageFact = func(fact analysis.Fact) {
13117-		panic(fmt.Sprintf("%v: Pass.ExportPackageFact(%T) called after Run", act, fact))
13118-	}
13119-
13120-	factsdata := factset.Encode()
13121-	return result, &actionSummary{
13122-		Diagnostics: diagnostics,
13123-		Facts:       factsdata,
13124-		FactsHash:   source.HashOf(factsdata),
13125-	}, nil
13126-}
13127-
13128-// requiredAnalyzers returns the transitive closure of required analyzers in preorder.
13129-func requiredAnalyzers(analyzers []*analysis.Analyzer) []*analysis.Analyzer {
13130-	var result []*analysis.Analyzer
13131-	seen := make(map[*analysis.Analyzer]bool)
13132-	var visitAll func([]*analysis.Analyzer)
13133-	visitAll = func(analyzers []*analysis.Analyzer) {
13134-		for _, a := range analyzers {
13135-			if !seen[a] {
13136-				seen[a] = true
13137-				result = append(result, a)
13138-				visitAll(a.Requires)
13139-			}
13140-		}
13141-	}
13142-	visitAll(analyzers)
13143-	return result
13144-}
13145-
13146-func mustEncode(x interface{}) []byte {
13147-	var buf bytes.Buffer
13148-	if err := gob.NewEncoder(&buf).Encode(x); err != nil {
13149-		log.Fatalf("internal error encoding %T: %v", x, err)
13150-	}
13151-	return buf.Bytes()
13152-}
13153-
13154-func mustDecode(data []byte, ptr interface{}) {
13155-	if err := gob.NewDecoder(bytes.NewReader(data)).Decode(ptr); err != nil {
13156-		log.Fatalf("internal error decoding %T: %v", ptr, err)
13157-	}
13158-}
13159-
13160-// -- data types for serialization of analysis.Diagnostic and source.Diagnostic --
13161-
13162-type gobDiagnostic struct {
13163-	Location       protocol.Location
13164-	Severity       protocol.DiagnosticSeverity
13165-	Code           string
13166-	CodeHref       string
13167-	Source         string
13168-	Message        string
13169-	SuggestedFixes []gobSuggestedFix
13170-	Related        []gobRelatedInformation
13171-	Tags           []protocol.DiagnosticTag
13172-}
13173-
13174-type gobRelatedInformation struct {
13175-	Location protocol.Location
13176-	Message  string
13177-}
13178-
13179-type gobSuggestedFix struct {
13180-	Message    string
13181-	TextEdits  []gobTextEdit
13182-	Command    *gobCommand
13183-	ActionKind protocol.CodeActionKind
13184-}
13185-
13186-type gobCommand struct {
13187-	Title     string
13188-	Command   string
13189-	Arguments []json.RawMessage
13190-}
13191-
13192-type gobTextEdit struct {
13193-	Location protocol.Location
13194-	NewText  []byte
13195-}
13196-
13197-// toGobDiagnostic converts an analysis.Diagnosic to a serializable gobDiagnostic,
13198-// which requires expanding token.Pos positions into protocol.Location form.
13199-func toGobDiagnostic(posToLocation func(start, end token.Pos) (protocol.Location, error), diag analysis.Diagnostic) (gobDiagnostic, error) {
13200-	var fixes []gobSuggestedFix
13201-	for _, fix := range diag.SuggestedFixes {
13202-		var gobEdits []gobTextEdit
13203-		for _, textEdit := range fix.TextEdits {
13204-			loc, err := posToLocation(textEdit.Pos, textEdit.End)
13205-			if err != nil {
13206-				return gobDiagnostic{}, fmt.Errorf("in SuggestedFixes: %w", err)
13207-			}
13208-			gobEdits = append(gobEdits, gobTextEdit{
13209-				Location: loc,
13210-				NewText:  textEdit.NewText,
13211-			})
13212-		}
13213-		fixes = append(fixes, gobSuggestedFix{
13214-			Message:   fix.Message,
13215-			TextEdits: gobEdits,
13216-		})
13217-	}
13218-
13219-	var related []gobRelatedInformation
13220-	for _, r := range diag.Related {
13221-		loc, err := posToLocation(r.Pos, r.End)
13222-		if err != nil {
13223-			return gobDiagnostic{}, fmt.Errorf("in Related: %w", err)
13224-		}
13225-		related = append(related, gobRelatedInformation{
13226-			Location: loc,
13227-			Message:  r.Message,
13228-		})
13229-	}
13230-
13231-	loc, err := posToLocation(diag.Pos, diag.End)
13232-	if err != nil {
13233-		return gobDiagnostic{}, err
13234-	}
13235-
13236-	return gobDiagnostic{
13237-		Location: loc,
13238-		// Severity for analysis diagnostics is dynamic, based on user
13239-		// configuration per analyzer.
13240-		// Code and CodeHref are unset for Analysis diagnostics,
13241-		// TODO(rfindley): set Code fields if/when golang/go#57906 is accepted.
13242-		Source:         diag.Category,
13243-		Message:        diag.Message,
13244-		SuggestedFixes: fixes,
13245-		Related:        related,
13246-		// Analysis diagnostics do not contain tags.
13247-	}, nil
13248-}
13249diff -urN a/gopls/internal/lsp/cache/cache.go b/gopls/internal/lsp/cache/cache.go
13250--- a/gopls/internal/lsp/cache/cache.go	2000-01-01 00:00:00.000000000 -0000
13251+++ b/gopls/internal/lsp/cache/cache.go	1970-01-01 00:00:00.000000000 +0000
13252@@ -1,78 +0,0 @@
13253-// Copyright 2019 The Go Authors. All rights reserved.
13254-// Use of this source code is governed by a BSD-style
13255-// license that can be found in the LICENSE file.
13256-
13257-package cache
13258-
13259-import (
13260-	"context"
13261-	"reflect"
13262-	"strconv"
13263-	"sync/atomic"
13264-
13265-	"golang.org/x/tools/gopls/internal/lsp/source"
13266-	"golang.org/x/tools/internal/event"
13267-	"golang.org/x/tools/internal/gocommand"
13268-	"golang.org/x/tools/internal/memoize"
13269-	"golang.org/x/tools/internal/robustio"
13270-)
13271-
13272-// New Creates a new cache for gopls operation results, using the given file
13273-// set, shared store, and session options.
13274-//
13275-// Both the fset and store may be nil, but if store is non-nil so must be fset
13276-// (and they must always be used together), otherwise it may be possible to get
13277-// cached data referencing token.Pos values not mapped by the FileSet.
13278-func New(store *memoize.Store) *Cache {
13279-	index := atomic.AddInt64(&cacheIndex, 1)
13280-
13281-	if store == nil {
13282-		store = &memoize.Store{}
13283-	}
13284-
13285-	c := &Cache{
13286-		id:         strconv.FormatInt(index, 10),
13287-		store:      store,
13288-		memoizedFS: &memoizedFS{filesByID: map[robustio.FileID][]*DiskFile{}},
13289-	}
13290-	return c
13291-}
13292-
13293-// A Cache holds caching stores that are bundled together for consistency.
13294-//
13295-// TODO(rfindley): once fset and store need not be bundled together, the Cache
13296-// type can be eliminated.
13297-type Cache struct {
13298-	id string
13299-
13300-	store *memoize.Store
13301-
13302-	*memoizedFS // implements source.FileSource
13303-}
13304-
13305-// NewSession creates a new gopls session with the given cache and options overrides.
13306-//
13307-// The provided optionsOverrides may be nil.
13308-//
13309-// TODO(rfindley): move this to session.go.
13310-func NewSession(ctx context.Context, c *Cache, optionsOverrides func(*source.Options)) *Session {
13311-	index := atomic.AddInt64(&sessionIndex, 1)
13312-	options := source.DefaultOptions().Clone()
13313-	if optionsOverrides != nil {
13314-		optionsOverrides(options)
13315-	}
13316-	s := &Session{
13317-		id:          strconv.FormatInt(index, 10),
13318-		cache:       c,
13319-		gocmdRunner: &gocommand.Runner{},
13320-		options:     options,
13321-		overlayFS:   newOverlayFS(c),
13322-	}
13323-	event.Log(ctx, "New session", KeyCreateSession.Of(s))
13324-	return s
13325-}
13326-
13327-var cacheIndex, sessionIndex, viewIndex int64
13328-
13329-func (c *Cache) ID() string                     { return c.id }
13330-func (c *Cache) MemStats() map[reflect.Type]int { return c.store.Stats() }
13331diff -urN a/gopls/internal/lsp/cache/check.go b/gopls/internal/lsp/cache/check.go
13332--- a/gopls/internal/lsp/cache/check.go	2000-01-01 00:00:00.000000000 -0000
13333+++ b/gopls/internal/lsp/cache/check.go	1970-01-01 00:00:00.000000000 +0000
13334@@ -1,1227 +0,0 @@
13335-// Copyright 2019 The Go Authors. All rights reserved.
13336-// Use of this source code is governed by a BSD-style
13337-// license that can be found in the LICENSE file.
13338-
13339-package cache
13340-
13341-import (
13342-	"context"
13343-	"crypto/sha256"
13344-	"fmt"
13345-	"go/ast"
13346-	"go/token"
13347-	"go/types"
13348-	"log"
13349-	"regexp"
13350-	"sort"
13351-	"strings"
13352-	"sync"
13353-
13354-	"golang.org/x/mod/module"
13355-	"golang.org/x/sync/errgroup"
13356-	"golang.org/x/tools/go/ast/astutil"
13357-	"golang.org/x/tools/gopls/internal/lsp/filecache"
13358-	"golang.org/x/tools/gopls/internal/lsp/protocol"
13359-	"golang.org/x/tools/gopls/internal/lsp/source"
13360-	"golang.org/x/tools/gopls/internal/lsp/source/methodsets"
13361-	"golang.org/x/tools/gopls/internal/lsp/source/xrefs"
13362-	"golang.org/x/tools/gopls/internal/span"
13363-	"golang.org/x/tools/internal/bug"
13364-	"golang.org/x/tools/internal/event"
13365-	"golang.org/x/tools/internal/event/tag"
13366-	"golang.org/x/tools/internal/gcimporter"
13367-	"golang.org/x/tools/internal/memoize"
13368-	"golang.org/x/tools/internal/packagesinternal"
13369-	"golang.org/x/tools/internal/typeparams"
13370-	"golang.org/x/tools/internal/typesinternal"
13371-)
13372-
13373-// A typeCheckBatch holds data for a logical type-checking operation, which may
13374-// type-check many unrelated packages.
13375-//
13376-// It shares state such as parsed files and imports, to optimize type-checking
13377-// for packages with overlapping dependency graphs.
13378-type typeCheckBatch struct {
13379-	meta *metadataGraph
13380-
13381-	parsedFiles map[span.URI]*source.ParsedGoFile // parsed files necessary for type-checking
13382-	fset        *token.FileSet                    // FileSet describing all parsed files
13383-
13384-	// Promises holds promises to either read export data for the package, or
13385-	// parse and type-check its syntax.
13386-	//
13387-	// The return value of these promises is not used: after promises are
13388-	// awaited, they must write an entry into the imports map.
13389-	promises map[PackageID]*memoize.Promise
13390-
13391-	mu         sync.Mutex
13392-	needFiles  map[span.URI]source.FileHandle // de-duplicated file handles required for type-checking
13393-	imports    map[PackageID]pkgOrErr         // types.Packages to use for importing
13394-	exportData map[PackageID][]byte
13395-	packages   map[PackageID]*Package
13396-}
13397-
13398-type pkgOrErr struct {
13399-	pkg *types.Package
13400-	err error
13401-}
13402-
13403-// TypeCheck type-checks the specified packages.
13404-//
13405-// The resulting packages slice always contains len(ids) entries, though some
13406-// of them may be nil if (and only if) the resulting error is non-nil.
13407-//
13408-// An error is returned if any of the requested packages fail to type-check.
13409-// This is different from having type-checking errors: a failure to type-check
13410-// indicates context cancellation or otherwise significant failure to perform
13411-// the type-checking operation.
13412-func (s *snapshot) TypeCheck(ctx context.Context, ids ...PackageID) ([]source.Package, error) {
13413-	// Check for existing active packages.
13414-	//
13415-	// Since gopls can't depend on package identity, any instance of the
13416-	// requested package must be ok to return.
13417-	//
13418-	// This is an optimization to avoid redundant type-checking: following
13419-	// changes to an open package many LSP clients send several successive
13420-	// requests for package information for the modified package (semantic
13421-	// tokens, code lens, inlay hints, etc.)
13422-	pkgs := make([]source.Package, len(ids))
13423-	needSyntax := make(map[PackageID]bool)
13424-	for i, id := range ids {
13425-		if pkg := s.getActivePackage(id); pkg != nil {
13426-			pkgs[i] = pkg
13427-		} else {
13428-			needSyntax[id] = true
13429-		}
13430-	}
13431-
13432-	if len(needSyntax) == 0 {
13433-		return pkgs, nil
13434-	}
13435-
13436-	// Build up shared state for efficient type-checking.
13437-	b := &typeCheckBatch{
13438-		parsedFiles: make(map[span.URI]*source.ParsedGoFile),
13439-		// fset is built during the parsing pass.
13440-		needFiles: make(map[span.URI]source.FileHandle),
13441-
13442-		promises:   make(map[PackageID]*memoize.Promise),
13443-		imports:    make(map[PackageID]pkgOrErr),
13444-		exportData: make(map[PackageID][]byte),
13445-		packages:   make(map[PackageID]*Package),
13446-	}
13447-
13448-	// Capture metadata once to ensure a consistent view.
13449-	s.mu.Lock()
13450-	b.meta = s.meta
13451-	s.mu.Unlock()
13452-
13453-	//  -- Step 1: assemble the promises graph --
13454-
13455-	var (
13456-		needExportData = make(map[PackageID]packageHandleKey)
13457-		packageHandles = make(map[PackageID]*packageHandle)
13458-	)
13459-
13460-	// collectPromises collects promises to load packages from export data or
13461-	// type-check.
13462-	var collectPromises func(PackageID) error
13463-	collectPromises = func(id PackageID) error {
13464-		if _, ok := b.promises[id]; ok {
13465-			return nil
13466-		}
13467-		b.promises[id] = nil // break cycles
13468-
13469-		m := b.meta.metadata[id]
13470-		if m == nil {
13471-			return bug.Errorf("missing metadata for %v", id)
13472-		}
13473-		for _, id := range m.DepsByPkgPath {
13474-			if err := collectPromises(id); err != nil {
13475-				return err
13476-			}
13477-		}
13478-
13479-		// Note that we can't reuse active packages here, as they will have the
13480-		// wrong FileSet. Any active packages that exist as dependencies of other
13481-		// packages will need to be loaded from export data.
13482-		ph, err := s.buildPackageHandle(ctx, id)
13483-		if err != nil {
13484-			return err
13485-		}
13486-		packageHandles[id] = ph
13487-
13488-		if needSyntax[id] {
13489-			// We will need to parse and type-check this package.
13490-			//
13491-			// We may also need to parse and type-check if export data is missing,
13492-			// but that is handled after fetching export data below.
13493-			b.addNeededFiles(ph)
13494-		} else if id != "unsafe" { // we can't load export data for unsafe
13495-			needExportData[id] = ph.key
13496-		}
13497-
13498-		debugName := fmt.Sprintf("check(%s)", id)
13499-		b.promises[id] = memoize.NewPromise(debugName, func(ctx context.Context, _ interface{}) interface{} {
13500-			var res pkgOrErr
13501-			if err := b.awaitPredecessors(ctx, ph.m); err != nil {
13502-				res.err = err
13503-			} else {
13504-				b.mu.Lock()
13505-				data, ok := b.exportData[id]
13506-				b.mu.Unlock()
13507-
13508-				if ok {
13509-					// We need export data, and have it.
13510-					res.pkg, res.err = b.importPackage(ctx, m, data)
13511-				} else if !needSyntax[id] {
13512-					// We need only a types.Package, but don't have export data.
13513-					// Type-check as fast as possible (skipping function bodies).
13514-					res.pkg, res.err = b.checkPackageForImport(ctx, ph)
13515-				} else {
13516-					// We need a syntax package.
13517-					var pkg *Package
13518-					pkg, res.err = b.checkPackage(ctx, ph)
13519-					if res.err == nil {
13520-						res.pkg = pkg.pkg.types
13521-						b.mu.Lock()
13522-						b.packages[id] = pkg
13523-						b.mu.Unlock()
13524-					}
13525-				}
13526-			}
13527-
13528-			b.mu.Lock()
13529-			b.imports[m.ID] = res
13530-			b.mu.Unlock()
13531-			return nil
13532-		})
13533-		return nil
13534-	}
13535-	for id := range needSyntax {
13536-		collectPromises(id)
13537-	}
13538-
13539-	// -- Step 2: collect export data --
13540-	//
13541-	// This must be done before parsing in order to determine which files must be
13542-	// parsed.
13543-	{
13544-		var g errgroup.Group
13545-		for id, key := range needExportData {
13546-			id := id
13547-			key := key
13548-			g.Go(func() error {
13549-				data, err := filecache.Get(exportDataKind, key)
13550-				if err != nil {
13551-					if err == filecache.ErrNotFound {
13552-						ph := packageHandles[id]
13553-						b.addNeededFiles(ph) // we will need to parse and type check
13554-						return nil           // ok: we will type check later
13555-					}
13556-					return err
13557-				}
13558-				b.mu.Lock()
13559-				b.exportData[id] = data
13560-				b.mu.Unlock()
13561-				return nil
13562-			})
13563-		}
13564-		if err := g.Wait(); err != nil {
13565-			return pkgs, err
13566-		}
13567-	}
13568-
13569-	// -- Step 3: parse files required for type checking. --
13570-	//
13571-	// Parse all necessary files in parallel. Unfortunately we can't start
13572-	// parsing each package's file as soon as we discover that it is a syntax
13573-	// package, because the parseCache cannot add files to an existing FileSet.
13574-	{
13575-		var fhs []source.FileHandle
13576-		for _, fh := range b.needFiles {
13577-			fhs = append(fhs, fh)
13578-		}
13579-		pgfs, fset, err := s.parseCache.parseFiles(ctx, source.ParseFull, fhs...)
13580-		if err != nil {
13581-			return pkgs, err
13582-		}
13583-		for _, pgf := range pgfs {
13584-			b.parsedFiles[pgf.URI] = pgf
13585-		}
13586-		b.fset = fset
13587-	}
13588-
13589-	// -- Step 4: await type-checking. --
13590-	//
13591-	// Start a single goroutine for each promise.
13592-	{
13593-		var g errgroup.Group
13594-		// TODO(rfindley): find a good way to limit concurrency of type-checking,
13595-		// which is CPU bound at this point.
13596-		//
13597-		// (calling g.SetLimit here is mostly ineffective, as promises are
13598-		// recursively concurrent.)
13599-		for _, promise := range b.promises {
13600-			promise := promise
13601-			g.Go(func() error {
13602-				_, err := promise.Get(ctx, nil)
13603-				return err
13604-			})
13605-		}
13606-		if err := g.Wait(); err != nil {
13607-			return pkgs, err
13608-		}
13609-	}
13610-
13611-	// Fill in the gaps of the results slice.
13612-	var firstErr error
13613-	for i, id := range ids {
13614-		if pkgs[i] != nil {
13615-			continue
13616-		}
13617-		if err := b.imports[id].err; err != nil {
13618-			if firstErr == nil {
13619-				firstErr = err
13620-			}
13621-			continue
13622-		}
13623-		pkg := b.packages[id]
13624-		if pkg == nil {
13625-			panic("nil package")
13626-		}
13627-		if alt := s.memoizeActivePackage(id, pkg); alt != nil && alt != pkg {
13628-			// pkg is an open package, but we've lost a race and an existing package
13629-			// has already been memoized.
13630-			pkg = alt
13631-		}
13632-		pkgs[i] = pkg
13633-	}
13634-
13635-	return pkgs, firstErr
13636-}
13637-
13638-// addNeededFiles records the files necessary for type-checking ph, for later
13639-// parsing.
13640-func (b *typeCheckBatch) addNeededFiles(ph *packageHandle) {
13641-	b.mu.Lock()
13642-	defer b.mu.Unlock()
13643-
13644-	// Technically for export-only packages we only need compiledGoFiles, but
13645-	// these slices are usually redundant.
13646-	for _, fh := range ph.inputs.goFiles {
13647-		b.needFiles[fh.URI()] = fh
13648-	}
13649-	for _, fh := range ph.inputs.compiledGoFiles {
13650-		b.needFiles[fh.URI()] = fh
13651-	}
13652-}
13653-
13654-// importPackage loads the given package from its export data in p.exportData
13655-// (which must already be populated).
13656-func (b *typeCheckBatch) importPackage(ctx context.Context, m *source.Metadata, data []byte) (*types.Package, error) {
13657-	impMap, errMap := b.importMap(m.ID)
13658-	// Any failure to populate an import will cause confusing errors from
13659-	// IImportShallow below.
13660-	for path, err := range errMap {
13661-		return nil, fmt.Errorf("error importing %q for %q: %v", path, m.ID, err)
13662-	}
13663-
13664-	// TODO(rfindley): collect "deep" hashes here using the provided
13665-	// callback, for precise pruning.
13666-	imported, err := gcimporter.IImportShallow(b.fset, impMap, data, string(m.PkgPath), func(*types.Package, string) {})
13667-	if err != nil {
13668-		return nil, bug.Errorf("invalid export data for %q: %v", m.ID, err)
13669-	}
13670-	return imported, nil
13671-}
13672-
13673-// checkPackageForImport type checks, but skips function bodies and does not
13674-// record syntax information.
13675-func (b *typeCheckBatch) checkPackageForImport(ctx context.Context, ph *packageHandle) (*types.Package, error) {
13676-	if ph.m.ID == "unsafe" {
13677-		return types.Unsafe, nil
13678-	}
13679-	impMap, errMap := b.importMap(ph.inputs.id)
13680-	onError := func(e error) {
13681-		// Ignore errors for exporting.
13682-	}
13683-	cfg := b.typesConfig(ph.inputs, onError, impMap, errMap)
13684-	var files []*ast.File
13685-	for _, fh := range ph.inputs.compiledGoFiles {
13686-		pgf := b.parsedFiles[fh.URI()]
13687-		if pgf == nil {
13688-			return nil, fmt.Errorf("compiled go file %q failed to parse", fh.URI().Filename())
13689-		}
13690-		files = append(files, pgf.File)
13691-	}
13692-	cfg.IgnoreFuncBodies = true
13693-	pkg := types.NewPackage(string(ph.inputs.pkgPath), string(ph.inputs.name))
13694-	check := types.NewChecker(cfg, b.fset, pkg, nil)
13695-
13696-	_ = check.Files(files) // ignore errors
13697-
13698-	// If the context was cancelled, we may have returned a ton of transient
13699-	// errors to the type checker. Swallow them.
13700-	if ctx.Err() != nil {
13701-		return nil, ctx.Err()
13702-	}
13703-
13704-	// Asynchronously record export data.
13705-	go func() {
13706-		exportData, err := gcimporter.IExportShallow(b.fset, pkg)
13707-		if err != nil {
13708-			bug.Reportf("exporting package %v: %v", ph.m.ID, err)
13709-			return
13710-		}
13711-		if err := filecache.Set(exportDataKind, ph.key, exportData); err != nil {
13712-			event.Error(ctx, fmt.Sprintf("storing export data for %s", ph.m.ID), err)
13713-		}
13714-	}()
13715-	return pkg, nil
13716-}
13717-
13718-// checkPackage "fully type checks" to produce a syntax package.
13719-func (b *typeCheckBatch) checkPackage(ctx context.Context, ph *packageHandle) (*Package, error) {
13720-	// TODO(rfindley): refactor to inline typeCheckImpl here. There is no need
13721-	// for so many layers to build up the package
13722-	// (checkPackage->typeCheckImpl->doTypeCheck).
13723-	pkg, err := typeCheckImpl(ctx, b, ph.inputs)
13724-
13725-	if err == nil {
13726-		// Write package data to disk asynchronously.
13727-		go func() {
13728-			toCache := map[string][]byte{
13729-				xrefsKind:       pkg.xrefs,
13730-				methodSetsKind:  pkg.methodsets.Encode(),
13731-				diagnosticsKind: encodeDiagnostics(pkg.diagnostics),
13732-			}
13733-
13734-			if ph.m.ID != "unsafe" { // unsafe cannot be exported
13735-				exportData, err := gcimporter.IExportShallow(pkg.fset, pkg.types)
13736-				if err != nil {
13737-					bug.Reportf("exporting package %v: %v", ph.m.ID, err)
13738-				} else {
13739-					toCache[exportDataKind] = exportData
13740-				}
13741-			}
13742-
13743-			for kind, data := range toCache {
13744-				if err := filecache.Set(kind, ph.key, data); err != nil {
13745-					event.Error(ctx, fmt.Sprintf("storing %s data for %s", kind, ph.m.ID), err)
13746-				}
13747-			}
13748-		}()
13749-	}
13750-
13751-	return &Package{ph.m, pkg}, err
13752-}
13753-
13754-// awaitPredecessors awaits all promises for m.DepsByPkgPath, returning an
13755-// error if awaiting failed due to context cancellation or if there was an
13756-// unrecoverable error loading export data.
13757-func (b *typeCheckBatch) awaitPredecessors(ctx context.Context, m *source.Metadata) error {
13758-	for _, depID := range m.DepsByPkgPath {
13759-		depID := depID
13760-		if p, ok := b.promises[depID]; ok {
13761-			if _, err := p.Get(ctx, nil); err != nil {
13762-				return err
13763-			}
13764-		}
13765-	}
13766-	return nil
13767-}
13768-
13769-// importMap returns an import map for the given package ID, populated with
13770-// type-checked packages for its dependencies. It is intended for compatibility
13771-// with gcimporter.IImportShallow, so the first result uses the map signature
13772-// of that API, where keys are package path strings.
13773-//
13774-// importMap must only be used once all promises for dependencies of id have
13775-// been awaited.
13776-//
13777-// For any missing packages, importMap returns an entry in the resulting errMap
13778-// reporting the error for that package.
13779-//
13780-// Invariant: for all recursive dependencies, either impMap[path] or
13781-// errMap[path] is set.
13782-func (b *typeCheckBatch) importMap(id PackageID) (impMap map[string]*types.Package, errMap map[PackagePath]error) {
13783-	impMap = make(map[string]*types.Package)
13784-	outerID := id
13785-	var populateDepsOf func(m *source.Metadata)
13786-	populateDepsOf = func(parent *source.Metadata) {
13787-		for _, id := range parent.DepsByPkgPath {
13788-			m := b.meta.metadata[id]
13789-			if _, ok := impMap[string(m.PkgPath)]; ok {
13790-				continue
13791-			}
13792-			if _, ok := errMap[m.PkgPath]; ok {
13793-				continue
13794-			}
13795-			b.mu.Lock()
13796-			result, ok := b.imports[m.ID]
13797-			b.mu.Unlock()
13798-			if !ok {
13799-				panic(fmt.Sprintf("import map for %q missing package data for %q", outerID, m.ID))
13800-			}
13801-			// We may fail to produce a package due to e.g. context cancellation
13802-			// (handled elsewhere), or some catastrophic failure such as a package with
13803-			// no files.
13804-			switch {
13805-			case result.err != nil:
13806-				if errMap == nil {
13807-					errMap = make(map[PackagePath]error)
13808-				}
13809-				errMap[m.PkgPath] = result.err
13810-			case result.pkg != nil:
13811-				impMap[string(m.PkgPath)] = result.pkg
13812-			default:
13813-				panic("invalid import for " + id)
13814-			}
13815-			populateDepsOf(m)
13816-		}
13817-	}
13818-	m := b.meta.metadata[id]
13819-	populateDepsOf(m)
13820-	return impMap, errMap
13821-}
13822-
13823-// packageData holds binary data (e.g. types, xrefs) extracted from a syntax
13824-// package.
13825-type packageData struct {
13826-	m    *source.Metadata
13827-	data []byte
13828-}
13829-
13830-// getPackageData gets package data (e.g. types, xrefs) for the requested ids,
13831-// either loading from the file-based cache or type-checking and extracting
13832-// data using the provided get function.
13833-func (s *snapshot) getPackageData(ctx context.Context, kind string, ids []PackageID, get func(*syntaxPackage) []byte) ([]*packageData, error) {
13834-	var needIDs []PackageID
13835-	keys := make([]packageHandleKey, len(ids))
13836-	pkgData := make([]*packageData, len(ids))
13837-	var firstErr error
13838-	// Compute package keys and query file cache.
13839-	for i, id := range ids {
13840-		ph, err := s.buildPackageHandle(ctx, id)
13841-		if err != nil {
13842-			if firstErr == nil {
13843-				firstErr = err
13844-			}
13845-			if ctx.Err() != nil {
13846-				return pkgData, firstErr
13847-			}
13848-			continue
13849-		}
13850-		keys[i] = ph.key
13851-		data, err := filecache.Get(kind, ph.key)
13852-		switch err {
13853-		case nil:
13854-			pkgData[i] = &packageData{m: ph.m, data: data}
13855-		case filecache.ErrNotFound:
13856-			needIDs = append(needIDs, id)
13857-		default:
13858-			if firstErr == nil {
13859-				firstErr = err
13860-			}
13861-			if ctx.Err() != nil {
13862-				return pkgData, firstErr
13863-			}
13864-		}
13865-	}
13866-
13867-	// Type-check the packages for which we got file-cache misses.
13868-	pkgs, err := s.TypeCheck(ctx, needIDs...)
13869-	if err != nil {
13870-		return nil, err
13871-	}
13872-
13873-	pkgMap := make(map[PackageID]source.Package)
13874-	for i, id := range needIDs {
13875-		pkgMap[id] = pkgs[i]
13876-	}
13877-
13878-	// Fill in the gaps using data derived from type checking.
13879-	for i, id := range ids {
13880-		if pkgData[i] != nil {
13881-			continue
13882-		}
13883-		result := pkgMap[id]
13884-		if result == nil {
13885-			panic(fmt.Sprintf("missing type-check result for %s", id))
13886-		}
13887-		data := get(result.(*Package).pkg)
13888-		pkgData[i] = &packageData{m: result.Metadata(), data: data}
13889-	}
13890-
13891-	return pkgData, firstErr
13892-}
13893-
13894-type packageHandleKey source.Hash
13895-
13896-// A packageHandle holds package information, some of which may not be fully
13897-// evaluated.
13898-//
13899-// The only methods on packageHandle that are safe to call before calling await
13900-// are Metadata and await itself.
13901-type packageHandle struct {
13902-	m *source.Metadata
13903-
13904-	inputs typeCheckInputs
13905-
13906-	// key is the hashed key for the package.
13907-	//
13908-	// It includes the all bits of the transitive closure of
13909-	// dependencies's sources. This is more than type checking
13910-	// really depends on: export data of direct deps should be
13911-	// enough. (The key for analysis actions could similarly
13912-	// hash only Facts of direct dependencies.)
13913-	key packageHandleKey
13914-
13915-	// Note: as an optimization, we could join in-flight type-checking by
13916-	// recording a transient ref-counted promise here.
13917-	// (This was done previously, but proved to be a premature optimization).
13918-}
13919-
13920-// buildPackageHandle returns a handle for the future results of
13921-// type-checking the package identified by id in the given mode.
13922-// It assumes that the given ID already has metadata available, so it does not
13923-// attempt to reload missing or invalid metadata. The caller must reload
13924-// metadata if needed.
13925-func (s *snapshot) buildPackageHandle(ctx context.Context, id PackageID) (*packageHandle, error) {
13926-	s.mu.Lock()
13927-	entry, hit := s.packages.Get(id)
13928-	m := s.meta.metadata[id]
13929-	s.mu.Unlock()
13930-
13931-	if m == nil {
13932-		return nil, fmt.Errorf("no metadata for %s", id)
13933-	}
13934-
13935-	if hit {
13936-		return entry.(*packageHandle), nil
13937-	}
13938-
13939-	inputs, err := s.typeCheckInputs(ctx, m)
13940-	if err != nil {
13941-		return nil, err
13942-	}
13943-	// All the file reading has now been done.
13944-	// Create a handle for the result of type checking.
13945-	phKey := computePackageKey(s, inputs)
13946-	ph := &packageHandle{
13947-		m:      m,
13948-		inputs: inputs,
13949-		key:    phKey,
13950-	}
13951-
13952-	s.mu.Lock()
13953-	defer s.mu.Unlock()
13954-
13955-	// Check that the metadata has not changed
13956-	// (which should invalidate this handle).
13957-	//
13958-	// (In future, handles should form a graph with edges from a
13959-	// packageHandle to the handles for parsing its files and the
13960-	// handles for type-checking its immediate deps, at which
13961-	// point there will be no need to even access s.meta.)
13962-	if s.meta.metadata[ph.m.ID] != ph.m {
13963-		// TODO(rfindley): this should be bug.Errorf.
13964-		return nil, fmt.Errorf("stale metadata for %s", ph.m.ID)
13965-	}
13966-
13967-	// Check cache again in case another goroutine got there first.
13968-	if prev, ok := s.packages.Get(id); ok {
13969-		prevPH := prev.(*packageHandle)
13970-		if prevPH.m != ph.m {
13971-			return nil, bug.Errorf("existing package handle does not match for %s", ph.m.ID)
13972-		}
13973-		return prevPH, nil
13974-	}
13975-
13976-	s.packages.Set(id, ph, nil)
13977-	return ph, nil
13978-}
13979-
13980-// typeCheckInputs contains the inputs of a call to typeCheckImpl, which
13981-// type-checks a package.
13982-//
13983-// Part of the purpose of this type is to keep type checking in-sync with the
13984-// package handle key, by explicitly identifying the inputs to type checking.
13985-type typeCheckInputs struct {
13986-	id PackageID
13987-
13988-	// Used for type checking:
13989-	pkgPath                  PackagePath
13990-	name                     PackageName
13991-	goFiles, compiledGoFiles []source.FileHandle
13992-	sizes                    types.Sizes
13993-	deps                     map[PackageID]*packageHandle
13994-	depsByImpPath            map[ImportPath]PackageID
13995-	goVersion                string // packages.Module.GoVersion, e.g. "1.18"
13996-
13997-	// Used for type check diagnostics:
13998-	relatedInformation bool
13999-	linkTarget         string
14000-	moduleMode         bool
14001-}
14002-
14003-func (s *snapshot) typeCheckInputs(ctx context.Context, m *source.Metadata) (typeCheckInputs, error) {
14004-	deps := make(map[PackageID]*packageHandle)
14005-	for _, depID := range m.DepsByPkgPath {
14006-		depHandle, err := s.buildPackageHandle(ctx, depID)
14007-		if err != nil {
14008-			// If err is non-nil, we either have an invalid dependency, or a
14009-			// catastrophic failure to read a file (context cancellation or
14010-			// permission issues).
14011-			//
14012-			// We don't want one bad dependency to prevent us from type-checking the
14013-			// package -- we should instead get an import error. So we only abort
14014-			// this operation if the context is cancelled.
14015-			//
14016-			// We could do a better job of handling permission errors on files, but
14017-			// this is rare, and it is reasonable to treat the same an invalid
14018-			// dependency.
14019-			event.Error(ctx, fmt.Sprintf("%s: no dep handle for %s", m.ID, depID), err, source.SnapshotLabels(s)...)
14020-			if ctx.Err() != nil {
14021-				return typeCheckInputs{}, ctx.Err() // cancelled
14022-			}
14023-			continue
14024-		}
14025-		deps[depID] = depHandle
14026-	}
14027-
14028-	// Read both lists of files of this package, in parallel.
14029-	//
14030-	// goFiles aren't presented to the type checker--nor
14031-	// are they included in the key, unsoundly--but their
14032-	// syntax trees are available from (*pkg).File(URI).
14033-	// TODO(adonovan): consider parsing them on demand?
14034-	// The need should be rare.
14035-	goFiles, compiledGoFiles, err := readGoFiles(ctx, s, m)
14036-	if err != nil {
14037-		return typeCheckInputs{}, err
14038-	}
14039-
14040-	goVersion := ""
14041-	if m.Module != nil && m.Module.GoVersion != "" {
14042-		goVersion = m.Module.GoVersion
14043-	}
14044-
14045-	return typeCheckInputs{
14046-		id:              m.ID,
14047-		pkgPath:         m.PkgPath,
14048-		name:            m.Name,
14049-		goFiles:         goFiles,
14050-		compiledGoFiles: compiledGoFiles,
14051-		sizes:           m.TypesSizes,
14052-		deps:            deps,
14053-		depsByImpPath:   m.DepsByImpPath,
14054-		goVersion:       goVersion,
14055-
14056-		relatedInformation: s.view.Options().RelatedInformationSupported,
14057-		linkTarget:         s.view.Options().LinkTarget,
14058-		moduleMode:         s.moduleMode(),
14059-	}, nil
14060-}
14061-
14062-// readGoFiles reads the content of Metadata.GoFiles and
14063-// Metadata.CompiledGoFiles, in parallel.
14064-func readGoFiles(ctx context.Context, s *snapshot, m *source.Metadata) (goFiles, compiledGoFiles []source.FileHandle, err error) {
14065-	var group errgroup.Group
14066-	getFileHandles := func(files []span.URI) []source.FileHandle {
14067-		fhs := make([]source.FileHandle, len(files))
14068-		for i, uri := range files {
14069-			i, uri := i, uri
14070-			group.Go(func() (err error) {
14071-				fhs[i], err = s.GetFile(ctx, uri) // ~25us
14072-				return
14073-			})
14074-		}
14075-		return fhs
14076-	}
14077-	return getFileHandles(m.GoFiles),
14078-		getFileHandles(m.CompiledGoFiles),
14079-		group.Wait()
14080-}
14081-
14082-// computePackageKey returns a key representing the act of type checking
14083-// a package named id containing the specified files, metadata, and
14084-// combined dependency hash.
14085-func computePackageKey(s *snapshot, inputs typeCheckInputs) packageHandleKey {
14086-	hasher := sha256.New()
14087-
14088-	// In principle, a key must be the hash of an
14089-	// unambiguous encoding of all the relevant data.
14090-	// If it's ambiguous, we risk collisions.
14091-
14092-	// package identifiers
14093-	fmt.Fprintf(hasher, "package: %s %s %s\n", inputs.id, inputs.name, inputs.pkgPath)
14094-
14095-	// module Go version
14096-	fmt.Fprintf(hasher, "go %s\n", inputs.goVersion)
14097-
14098-	// import map
14099-	importPaths := make([]string, 0, len(inputs.depsByImpPath))
14100-	for impPath := range inputs.depsByImpPath {
14101-		importPaths = append(importPaths, string(impPath))
14102-	}
14103-	sort.Strings(importPaths)
14104-	for _, impPath := range importPaths {
14105-		fmt.Fprintf(hasher, "import %s %s", impPath, string(inputs.depsByImpPath[ImportPath(impPath)]))
14106-	}
14107-
14108-	// deps, in PackageID order
14109-	depIDs := make([]string, 0, len(inputs.deps))
14110-	for depID := range inputs.deps {
14111-		depIDs = append(depIDs, string(depID))
14112-	}
14113-	sort.Strings(depIDs)
14114-	for _, depID := range depIDs {
14115-		dep := inputs.deps[PackageID(depID)]
14116-		fmt.Fprintf(hasher, "dep: %s key:%s\n", dep.m.PkgPath, dep.key)
14117-	}
14118-
14119-	// file names and contents
14120-	fmt.Fprintf(hasher, "compiledGoFiles: %d\n", len(inputs.compiledGoFiles))
14121-	for _, fh := range inputs.compiledGoFiles {
14122-		fmt.Fprintln(hasher, fh.FileIdentity())
14123-	}
14124-	fmt.Fprintf(hasher, "goFiles: %d\n", len(inputs.goFiles))
14125-	for _, fh := range inputs.goFiles {
14126-		fmt.Fprintln(hasher, fh.FileIdentity())
14127-	}
14128-
14129-	// types sizes
14130-	sz := inputs.sizes.(*types.StdSizes)
14131-	fmt.Fprintf(hasher, "sizes: %d %d\n", sz.WordSize, sz.MaxAlign)
14132-
14133-	fmt.Fprintf(hasher, "relatedInformation: %t\n", inputs.relatedInformation)
14134-	fmt.Fprintf(hasher, "linkTarget: %s\n", inputs.linkTarget)
14135-	fmt.Fprintf(hasher, "moduleMode: %t\n", inputs.moduleMode)
14136-
14137-	var hash [sha256.Size]byte
14138-	hasher.Sum(hash[:0])
14139-	return packageHandleKey(hash)
14140-}
14141-
14142-// typeCheckImpl type checks the parsed source files in compiledGoFiles.
14143-// (The resulting pkg also holds the parsed but not type-checked goFiles.)
14144-// deps holds the future results of type-checking the direct dependencies.
14145-func typeCheckImpl(ctx context.Context, b *typeCheckBatch, inputs typeCheckInputs) (*syntaxPackage, error) {
14146-	ctx, done := event.Start(ctx, "cache.typeCheck", tag.Package.Of(string(inputs.id)))
14147-	defer done()
14148-
14149-	pkg, err := doTypeCheck(ctx, b, inputs)
14150-	if err != nil {
14151-		return nil, err
14152-	}
14153-	pkg.methodsets = methodsets.NewIndex(pkg.fset, pkg.types)
14154-	pkg.xrefs = xrefs.Index(pkg.compiledGoFiles, pkg.types, pkg.typesInfo)
14155-
14156-	// Our heuristic for whether to show type checking errors is:
14157-	//  + If any file was 'fixed', don't show type checking errors as we
14158-	//    can't guarantee that they reference accurate locations in the source.
14159-	//  + If there is a parse error _in the current file_, suppress type
14160-	//    errors in that file.
14161-	//  + Otherwise, show type errors even in the presence of parse errors in
14162-	//    other package files. go/types attempts to suppress follow-on errors
14163-	//    due to bad syntax, so on balance type checking errors still provide
14164-	//    a decent signal/noise ratio as long as the file in question parses.
14165-
14166-	// Track URIs with parse errors so that we can suppress type errors for these
14167-	// files.
14168-	unparseable := map[span.URI]bool{}
14169-	for _, e := range pkg.parseErrors {
14170-		diags, err := parseErrorDiagnostics(pkg, e)
14171-		if err != nil {
14172-			event.Error(ctx, "unable to compute positions for parse errors", err, tag.Package.Of(string(inputs.id)))
14173-			continue
14174-		}
14175-		for _, diag := range diags {
14176-			unparseable[diag.URI] = true
14177-			pkg.diagnostics = append(pkg.diagnostics, diag)
14178-		}
14179-	}
14180-
14181-	if pkg.hasFixedFiles {
14182-		return pkg, nil
14183-	}
14184-
14185-	unexpanded := pkg.typeErrors
14186-	pkg.typeErrors = nil
14187-	for _, e := range expandErrors(unexpanded, inputs.relatedInformation) {
14188-		diags, err := typeErrorDiagnostics(inputs.moduleMode, inputs.linkTarget, pkg, e)
14189-		if err != nil {
14190-			event.Error(ctx, "unable to compute positions for type errors", err, tag.Package.Of(string(inputs.id)))
14191-			continue
14192-		}
14193-		pkg.typeErrors = append(pkg.typeErrors, e.primary)
14194-		for _, diag := range diags {
14195-			// If the file didn't parse cleanly, it is highly likely that type
14196-			// checking errors will be confusing or redundant. But otherwise, type
14197-			// checking usually provides a good enough signal to include.
14198-			if !unparseable[diag.URI] {
14199-				pkg.diagnostics = append(pkg.diagnostics, diag)
14200-			}
14201-		}
14202-	}
14203-
14204-	return pkg, nil
14205-}
14206-
14207-var goVersionRx = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
14208-
14209-func doTypeCheck(ctx context.Context, b *typeCheckBatch, inputs typeCheckInputs) (*syntaxPackage, error) {
14210-	impMap, errMap := b.importMap(inputs.id)
14211-	pkg := &syntaxPackage{
14212-		id:    inputs.id,
14213-		fset:  b.fset, // must match parse call below
14214-		types: types.NewPackage(string(inputs.pkgPath), string(inputs.name)),
14215-		typesInfo: &types.Info{
14216-			Types:      make(map[ast.Expr]types.TypeAndValue),
14217-			Defs:       make(map[*ast.Ident]types.Object),
14218-			Uses:       make(map[*ast.Ident]types.Object),
14219-			Implicits:  make(map[ast.Node]types.Object),
14220-			Selections: make(map[*ast.SelectorExpr]*types.Selection),
14221-			Scopes:     make(map[ast.Node]*types.Scope),
14222-		},
14223-		importMap: impMap,
14224-	}
14225-	typeparams.InitInstanceInfo(pkg.typesInfo)
14226-
14227-	// Collect parsed files from the type check pass, capturing parse errors from
14228-	// compiled files.
14229-	for _, fh := range inputs.goFiles {
14230-		pgf := b.parsedFiles[fh.URI()]
14231-		if pgf == nil {
14232-			// If go/packages told us that a file is in a package, it should be
14233-			// parseable (after all, it was parsed by go list).
14234-			return nil, bug.Errorf("go file %q failed to parse", fh.URI().Filename())
14235-		}
14236-		pkg.goFiles = append(pkg.goFiles, pgf)
14237-	}
14238-	for _, fh := range inputs.compiledGoFiles {
14239-		pgf := b.parsedFiles[fh.URI()]
14240-		if pgf == nil {
14241-			return nil, fmt.Errorf("compiled go file %q failed to parse", fh.URI().Filename())
14242-		}
14243-		if pgf.ParseErr != nil {
14244-			pkg.parseErrors = append(pkg.parseErrors, pgf.ParseErr)
14245-		}
14246-		pkg.compiledGoFiles = append(pkg.compiledGoFiles, pgf)
14247-	}
14248-
14249-	// Use the default type information for the unsafe package.
14250-	if inputs.pkgPath == "unsafe" {
14251-		// Don't type check Unsafe: it's unnecessary, and doing so exposes a data
14252-		// race to Unsafe.completed.
14253-		pkg.types = types.Unsafe
14254-		return pkg, nil
14255-	}
14256-
14257-	if len(pkg.compiledGoFiles) == 0 {
14258-		// No files most likely means go/packages failed.
14259-		//
14260-		// TODO(rfindley): in the past, we would capture go list errors in this
14261-		// case, to present go list errors to the user. However we had no tests for
14262-		// this behavior. It is unclear if anything better can be done here.
14263-		return nil, fmt.Errorf("no parsed files for package %s", inputs.pkgPath)
14264-	}
14265-
14266-	onError := func(e error) {
14267-		pkg.typeErrors = append(pkg.typeErrors, e.(types.Error))
14268-	}
14269-	cfg := b.typesConfig(inputs, onError, impMap, errMap)
14270-
14271-	check := types.NewChecker(cfg, pkg.fset, pkg.types, pkg.typesInfo)
14272-
14273-	var files []*ast.File
14274-	for _, cgf := range pkg.compiledGoFiles {
14275-		files = append(files, cgf.File)
14276-	}
14277-
14278-	// Type checking errors are handled via the config, so ignore them here.
14279-	_ = check.Files(files) // 50us-15ms, depending on size of package
14280-
14281-	// If the context was cancelled, we may have returned a ton of transient
14282-	// errors to the type checker. Swallow them.
14283-	if ctx.Err() != nil {
14284-		return nil, ctx.Err()
14285-	}
14286-	return pkg, nil
14287-}
14288-
14289-func (b *typeCheckBatch) typesConfig(inputs typeCheckInputs, onError func(e error), impMap map[string]*types.Package, errMap map[PackagePath]error) *types.Config {
14290-	cfg := &types.Config{
14291-		Sizes: inputs.sizes,
14292-		Error: onError,
14293-		Importer: importerFunc(func(path string) (*types.Package, error) {
14294-			// While all of the import errors could be reported
14295-			// based on the metadata before we start type checking,
14296-			// reporting them via types.Importer places the errors
14297-			// at the correct source location.
14298-			id, ok := inputs.depsByImpPath[ImportPath(path)]
14299-			if !ok {
14300-				// If the import declaration is broken,
14301-				// go list may fail to report metadata about it.
14302-				// See TestFixImportDecl for an example.
14303-				return nil, fmt.Errorf("missing metadata for import of %q", path)
14304-			}
14305-			depPH := inputs.deps[id]
14306-			if depPH == nil {
14307-				// e.g. missing metadata for dependencies in buildPackageHandle
14308-				return nil, missingPkgError(path, inputs.moduleMode)
14309-			}
14310-			if !source.IsValidImport(inputs.pkgPath, depPH.m.PkgPath) {
14311-				return nil, fmt.Errorf("invalid use of internal package %q", path)
14312-			}
14313-			pkg, ok := impMap[string(depPH.m.PkgPath)]
14314-			if !ok {
14315-				err := errMap[depPH.m.PkgPath]
14316-				if err == nil {
14317-					log.Fatalf("neither pkg nor error is set")
14318-				}
14319-				return nil, err
14320-			}
14321-			return pkg, nil
14322-		}),
14323-	}
14324-
14325-	if inputs.goVersion != "" {
14326-		goVersion := "go" + inputs.goVersion
14327-		// types.NewChecker panics if GoVersion is invalid. An unparsable mod
14328-		// file should probably stop us before we get here, but double check
14329-		// just in case.
14330-		if goVersionRx.MatchString(goVersion) {
14331-			typesinternal.SetGoVersion(cfg, goVersion)
14332-		}
14333-	}
14334-
14335-	// We want to type check cgo code if go/types supports it.
14336-	// We passed typecheckCgo to go/packages when we Loaded.
14337-	typesinternal.SetUsesCgo(cfg)
14338-	return cfg
14339-}
14340-
14341-// depsErrors creates diagnostics for each metadata error (e.g. import cycle).
14342-// These may be attached to import declarations in the transitive source files
14343-// of pkg, or to 'requires' declarations in the package's go.mod file.
14344-//
14345-// TODO(rfindley): move this to load.go
14346-func depsErrors(ctx context.Context, m *source.Metadata, meta *metadataGraph, fs source.FileSource, workspacePackages map[PackageID]PackagePath) ([]*source.Diagnostic, error) {
14347-	// Select packages that can't be found, and were imported in non-workspace packages.
14348-	// Workspace packages already show their own errors.
14349-	var relevantErrors []*packagesinternal.PackageError
14350-	for _, depsError := range m.DepsErrors {
14351-		// Up to Go 1.15, the missing package was included in the stack, which
14352-		// was presumably a bug. We want the next one up.
14353-		directImporterIdx := len(depsError.ImportStack) - 1
14354-		if directImporterIdx < 0 {
14355-			continue
14356-		}
14357-
14358-		directImporter := depsError.ImportStack[directImporterIdx]
14359-		if _, ok := workspacePackages[PackageID(directImporter)]; ok {
14360-			continue
14361-		}
14362-		relevantErrors = append(relevantErrors, depsError)
14363-	}
14364-
14365-	// Don't build the import index for nothing.
14366-	if len(relevantErrors) == 0 {
14367-		return nil, nil
14368-	}
14369-
14370-	// Subsequent checks require Go files.
14371-	if len(m.CompiledGoFiles) == 0 {
14372-		return nil, nil
14373-	}
14374-
14375-	// Build an index of all imports in the package.
14376-	type fileImport struct {
14377-		cgf *source.ParsedGoFile
14378-		imp *ast.ImportSpec
14379-	}
14380-	allImports := map[string][]fileImport{}
14381-	for _, uri := range m.CompiledGoFiles {
14382-		pgf, err := parseGoURI(ctx, fs, uri, source.ParseHeader)
14383-		if err != nil {
14384-			return nil, err
14385-		}
14386-		fset := source.FileSetFor(pgf.Tok)
14387-		// TODO(adonovan): modify Imports() to accept a single token.File (cgf.Tok).
14388-		for _, group := range astutil.Imports(fset, pgf.File) {
14389-			for _, imp := range group {
14390-				if imp.Path == nil {
14391-					continue
14392-				}
14393-				path := strings.Trim(imp.Path.Value, `"`)
14394-				allImports[path] = append(allImports[path], fileImport{pgf, imp})
14395-			}
14396-		}
14397-	}
14398-
14399-	// Apply a diagnostic to any import involved in the error, stopping once
14400-	// we reach the workspace.
14401-	var errors []*source.Diagnostic
14402-	for _, depErr := range relevantErrors {
14403-		for i := len(depErr.ImportStack) - 1; i >= 0; i-- {
14404-			item := depErr.ImportStack[i]
14405-			if _, ok := workspacePackages[PackageID(item)]; ok {
14406-				break
14407-			}
14408-
14409-			for _, imp := range allImports[item] {
14410-				rng, err := imp.cgf.NodeRange(imp.imp)
14411-				if err != nil {
14412-					return nil, err
14413-				}
14414-				fixes, err := goGetQuickFixes(m.Module != nil, imp.cgf.URI, item)
14415-				if err != nil {
14416-					return nil, err
14417-				}
14418-				errors = append(errors, &source.Diagnostic{
14419-					URI:            imp.cgf.URI,
14420-					Range:          rng,
14421-					Severity:       protocol.SeverityError,
14422-					Source:         source.TypeError,
14423-					Message:        fmt.Sprintf("error while importing %v: %v", item, depErr.Err),
14424-					SuggestedFixes: fixes,
14425-				})
14426-			}
14427-		}
14428-	}
14429-
14430-	modFile, err := nearestModFile(ctx, m.CompiledGoFiles[0], fs)
14431-	if err != nil {
14432-		return nil, err
14433-	}
14434-	pm, err := parseModURI(ctx, fs, modFile)
14435-	if err != nil {
14436-		return nil, err
14437-	}
14438-
14439-	// Add a diagnostic to the module that contained the lowest-level import of
14440-	// the missing package.
14441-	for _, depErr := range relevantErrors {
14442-		for i := len(depErr.ImportStack) - 1; i >= 0; i-- {
14443-			item := depErr.ImportStack[i]
14444-			m := meta.metadata[PackageID(item)]
14445-			if m == nil || m.Module == nil {
14446-				continue
14447-			}
14448-			modVer := module.Version{Path: m.Module.Path, Version: m.Module.Version}
14449-			reference := findModuleReference(pm.File, modVer)
14450-			if reference == nil {
14451-				continue
14452-			}
14453-			rng, err := pm.Mapper.OffsetRange(reference.Start.Byte, reference.End.Byte)
14454-			if err != nil {
14455-				return nil, err
14456-			}
14457-			fixes, err := goGetQuickFixes(true, pm.URI, item)
14458-			if err != nil {
14459-				return nil, err
14460-			}
14461-			errors = append(errors, &source.Diagnostic{
14462-				URI:            pm.URI,
14463-				Range:          rng,
14464-				Severity:       protocol.SeverityError,
14465-				Source:         source.TypeError,
14466-				Message:        fmt.Sprintf("error while importing %v: %v", item, depErr.Err),
14467-				SuggestedFixes: fixes,
14468-			})
14469-			break
14470-		}
14471-	}
14472-	return errors, nil
14473-}
14474-
14475-// missingPkgError returns an error message for a missing package that varies
14476-// based on the user's workspace mode.
14477-func missingPkgError(pkgPath string, moduleMode bool) error {
14478-	// TODO(rfindley): improve this error. Previous versions of this error had
14479-	// access to the full snapshot, and could provide more information (such as
14480-	// the initialization error).
14481-	if moduleMode {
14482-		// Previously, we would present the initialization error here.
14483-		return fmt.Errorf("no required module provides package %q", pkgPath)
14484-	} else {
14485-		// Previously, we would list the directories in GOROOT and GOPATH here.
14486-		return fmt.Errorf("cannot find package %q in GOROOT or GOPATH", pkgPath)
14487-	}
14488-}
14489-
14490-type extendedError struct {
14491-	primary     types.Error
14492-	secondaries []types.Error
14493-}
14494-
14495-func (e extendedError) Error() string {
14496-	return e.primary.Error()
14497-}
14498-
14499-// expandErrors duplicates "secondary" errors by mapping them to their main
14500-// error. Some errors returned by the type checker are followed by secondary
14501-// errors which give more information about the error. These are errors in
14502-// their own right, and they are marked by starting with \t. For instance, when
14503-// there is a multiply-defined function, the secondary error points back to the
14504-// definition first noticed.
14505-//
14506-// This function associates the secondary error with its primary error, which can
14507-// then be used as RelatedInformation when the error becomes a diagnostic.
14508-//
14509-// If supportsRelatedInformation is false, the secondary is instead embedded as
14510-// additional context in the primary error.
14511-func expandErrors(errs []types.Error, supportsRelatedInformation bool) []extendedError {
14512-	var result []extendedError
14513-	for i := 0; i < len(errs); {
14514-		original := extendedError{
14515-			primary: errs[i],
14516-		}
14517-		for i++; i < len(errs); i++ {
14518-			spl := errs[i]
14519-			if len(spl.Msg) == 0 || spl.Msg[0] != '\t' {
14520-				break
14521-			}
14522-			spl.Msg = spl.Msg[1:]
14523-			original.secondaries = append(original.secondaries, spl)
14524-		}
14525-
14526-		// Clone the error to all its related locations -- VS Code, at least,
14527-		// doesn't do it for us.
14528-		result = append(result, original)
14529-		for i, mainSecondary := range original.secondaries {
14530-			// Create the new primary error, with a tweaked message, in the
14531-			// secondary's location. We need to start from the secondary to
14532-			// capture its unexported location fields.
14533-			relocatedSecondary := mainSecondary
14534-			if supportsRelatedInformation {
14535-				relocatedSecondary.Msg = fmt.Sprintf("%v (see details)", original.primary.Msg)
14536-			} else {
14537-				relocatedSecondary.Msg = fmt.Sprintf("%v (this error: %v)", original.primary.Msg, mainSecondary.Msg)
14538-			}
14539-			relocatedSecondary.Soft = original.primary.Soft
14540-
14541-			// Copy over the secondary errors, noting the location of the
14542-			// current error we're cloning.
14543-			clonedError := extendedError{primary: relocatedSecondary, secondaries: []types.Error{original.primary}}
14544-			for j, secondary := range original.secondaries {
14545-				if i == j {
14546-					secondary.Msg += " (this error)"
14547-				}
14548-				clonedError.secondaries = append(clonedError.secondaries, secondary)
14549-			}
14550-			result = append(result, clonedError)
14551-		}
14552-
14553-	}
14554-	return result
14555-}
14556-
14557-// An importFunc is an implementation of the single-method
14558-// types.Importer interface based on a function value.
14559-type importerFunc func(path string) (*types.Package, error)
14560-
14561-func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }
14562diff -urN a/gopls/internal/lsp/cache/debug.go b/gopls/internal/lsp/cache/debug.go
14563--- a/gopls/internal/lsp/cache/debug.go	2000-01-01 00:00:00.000000000 -0000
14564+++ b/gopls/internal/lsp/cache/debug.go	1970-01-01 00:00:00.000000000 +0000
14565@@ -1,55 +0,0 @@
14566-// Copyright 2022 The Go Authors. All rights reserved.
14567-// Use of this source code is governed by a BSD-style
14568-// license that can be found in the LICENSE file.
14569-
14570-package cache
14571-
14572-import (
14573-	"fmt"
14574-	"os"
14575-	"sort"
14576-)
14577-
14578-// This file contains helpers that can be used to instrument code while
14579-// debugging.
14580-
14581-// debugEnabled toggles the helpers below.
14582-const debugEnabled = false
14583-
14584-// If debugEnabled is true, debugf formats its arguments and prints to stderr.
14585-// If debugEnabled is false, it is a no-op.
14586-func debugf(format string, args ...interface{}) {
14587-	if !debugEnabled {
14588-		return
14589-	}
14590-	if false {
14591-		_ = fmt.Sprintf(format, args...) // encourage vet to validate format strings
14592-	}
14593-	fmt.Fprintf(os.Stderr, ">>> "+format+"\n", args...)
14594-}
14595-
14596-// If debugEnabled is true, dumpWorkspace prints a summary of workspace
14597-// packages to stderr. If debugEnabled is false, it is a no-op.
14598-//
14599-// TODO(rfindley): this has served its purpose. Delete.
14600-func (s *snapshot) dumpWorkspace(context string) {
14601-	if !debugEnabled {
14602-		return
14603-	}
14604-
14605-	debugf("workspace (after %s):", context)
14606-	var ids []PackageID
14607-	for id := range s.workspacePackages {
14608-		ids = append(ids, id)
14609-	}
14610-
14611-	sort.Slice(ids, func(i, j int) bool {
14612-		return ids[i] < ids[j]
14613-	})
14614-
14615-	for _, id := range ids {
14616-		pkgPath := s.workspacePackages[id]
14617-		_, ok := s.meta.metadata[id]
14618-		debugf("  %s:%s (metadata: %t)", id, pkgPath, ok)
14619-	}
14620-}
14621diff -urN a/gopls/internal/lsp/cache/errors.go b/gopls/internal/lsp/cache/errors.go
14622--- a/gopls/internal/lsp/cache/errors.go	2000-01-01 00:00:00.000000000 -0000
14623+++ b/gopls/internal/lsp/cache/errors.go	1970-01-01 00:00:00.000000000 +0000
14624@@ -1,528 +0,0 @@
14625-// Copyright 2019 The Go Authors. All rights reserved.
14626-// Use of this source code is governed by a BSD-style
14627-// license that can be found in the LICENSE file.
14628-
14629-package cache
14630-
14631-// This file defines routines to convert diagnostics from go list, go
14632-// get, go/packages, parsing, type checking, and analysis into
14633-// source.Diagnostic form, and suggesting quick fixes.
14634-
14635-import (
14636-	"context"
14637-	"fmt"
14638-	"go/scanner"
14639-	"go/token"
14640-	"go/types"
14641-	"log"
14642-	"regexp"
14643-	"strconv"
14644-	"strings"
14645-
14646-	"golang.org/x/tools/go/packages"
14647-	"golang.org/x/tools/gopls/internal/lsp/command"
14648-	"golang.org/x/tools/gopls/internal/lsp/protocol"
14649-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
14650-	"golang.org/x/tools/gopls/internal/lsp/source"
14651-	"golang.org/x/tools/gopls/internal/span"
14652-	"golang.org/x/tools/internal/analysisinternal"
14653-	"golang.org/x/tools/internal/bug"
14654-	"golang.org/x/tools/internal/typesinternal"
14655-)
14656-
14657-// goPackagesErrorDiagnostics translates the given go/packages Error into a
14658-// diagnostic, using the provided metadata and filesource.
14659-//
14660-// The slice of diagnostics may be empty.
14661-func goPackagesErrorDiagnostics(ctx context.Context, e packages.Error, m *source.Metadata, fs source.FileSource) ([]*source.Diagnostic, error) {
14662-	if diag, err := parseGoListImportCycleError(ctx, e, m, fs); err != nil {
14663-		return nil, err
14664-	} else if diag != nil {
14665-		return []*source.Diagnostic{diag}, nil
14666-	}
14667-
14668-	var spn span.Span
14669-	if e.Pos == "" {
14670-		spn = parseGoListError(e.Msg, m.LoadDir)
14671-		// We may not have been able to parse a valid span. Apply the errors to all files.
14672-		if _, err := spanToRange(ctx, fs, spn); err != nil {
14673-			var diags []*source.Diagnostic
14674-			for _, uri := range m.CompiledGoFiles {
14675-				diags = append(diags, &source.Diagnostic{
14676-					URI:      uri,
14677-					Severity: protocol.SeverityError,
14678-					Source:   source.ListError,
14679-					Message:  e.Msg,
14680-				})
14681-			}
14682-			return diags, nil
14683-		}
14684-	} else {
14685-		spn = span.ParseInDir(e.Pos, m.LoadDir)
14686-	}
14687-
14688-	// TODO(rfindley): in some cases the go command outputs invalid spans, for
14689-	// example (from TestGoListErrors):
14690-	//
14691-	//   package a
14692-	//   import
14693-	//
14694-	// In this case, the go command will complain about a.go:2:8, which is after
14695-	// the trailing newline but still considered to be on the second line, most
14696-	// likely because *token.File lacks information about newline termination.
14697-	//
14698-	// We could do better here by handling that case.
14699-	rng, err := spanToRange(ctx, fs, spn)
14700-	if err != nil {
14701-		return nil, err
14702-	}
14703-	return []*source.Diagnostic{{
14704-		URI:      spn.URI(),
14705-		Range:    rng,
14706-		Severity: protocol.SeverityError,
14707-		Source:   source.ListError,
14708-		Message:  e.Msg,
14709-	}}, nil
14710-}
14711-
14712-func parseErrorDiagnostics(pkg *syntaxPackage, errList scanner.ErrorList) ([]*source.Diagnostic, error) {
14713-	// The first parser error is likely the root cause of the problem.
14714-	if errList.Len() <= 0 {
14715-		return nil, fmt.Errorf("no errors in %v", errList)
14716-	}
14717-	e := errList[0]
14718-	pgf, err := pkg.File(span.URIFromPath(e.Pos.Filename))
14719-	if err != nil {
14720-		return nil, err
14721-	}
14722-	rng, err := pgf.Mapper.OffsetRange(e.Pos.Offset, e.Pos.Offset)
14723-	if err != nil {
14724-		return nil, err
14725-	}
14726-	return []*source.Diagnostic{{
14727-		URI:      pgf.URI,
14728-		Range:    rng,
14729-		Severity: protocol.SeverityError,
14730-		Source:   source.ParseError,
14731-		Message:  e.Msg,
14732-	}}, nil
14733-}
14734-
14735-var importErrorRe = regexp.MustCompile(`could not import ([^\s]+)`)
14736-var unsupportedFeatureRe = regexp.MustCompile(`.*require.* go(\d+\.\d+) or later`)
14737-
14738-func typeErrorDiagnostics(moduleMode bool, linkTarget string, pkg *syntaxPackage, e extendedError) ([]*source.Diagnostic, error) {
14739-	code, loc, err := typeErrorData(pkg, e.primary)
14740-	if err != nil {
14741-		return nil, err
14742-	}
14743-	diag := &source.Diagnostic{
14744-		URI:      loc.URI.SpanURI(),
14745-		Range:    loc.Range,
14746-		Severity: protocol.SeverityError,
14747-		Source:   source.TypeError,
14748-		Message:  e.primary.Msg,
14749-	}
14750-	if code != 0 {
14751-		diag.Code = code.String()
14752-		diag.CodeHref = typesCodeHref(linkTarget, code)
14753-	}
14754-	switch code {
14755-	case typesinternal.UnusedVar, typesinternal.UnusedImport:
14756-		diag.Tags = append(diag.Tags, protocol.Unnecessary)
14757-	}
14758-
14759-	for _, secondary := range e.secondaries {
14760-		_, secondaryLoc, err := typeErrorData(pkg, secondary)
14761-		if err != nil {
14762-			return nil, err
14763-		}
14764-		diag.Related = append(diag.Related, protocol.DiagnosticRelatedInformation{
14765-			Location: secondaryLoc,
14766-			Message:  secondary.Msg,
14767-		})
14768-	}
14769-
14770-	if match := importErrorRe.FindStringSubmatch(e.primary.Msg); match != nil {
14771-		diag.SuggestedFixes, err = goGetQuickFixes(moduleMode, loc.URI.SpanURI(), match[1])
14772-		if err != nil {
14773-			return nil, err
14774-		}
14775-	}
14776-	if match := unsupportedFeatureRe.FindStringSubmatch(e.primary.Msg); match != nil {
14777-		diag.SuggestedFixes, err = editGoDirectiveQuickFix(moduleMode, loc.URI.SpanURI(), match[1])
14778-		if err != nil {
14779-			return nil, err
14780-		}
14781-	}
14782-	return []*source.Diagnostic{diag}, nil
14783-}
14784-
14785-func goGetQuickFixes(moduleMode bool, uri span.URI, pkg string) ([]source.SuggestedFix, error) {
14786-	// Go get only supports module mode for now.
14787-	if !moduleMode {
14788-		return nil, nil
14789-	}
14790-	title := fmt.Sprintf("go get package %v", pkg)
14791-	cmd, err := command.NewGoGetPackageCommand(title, command.GoGetPackageArgs{
14792-		URI:        protocol.URIFromSpanURI(uri),
14793-		AddRequire: true,
14794-		Pkg:        pkg,
14795-	})
14796-	if err != nil {
14797-		return nil, err
14798-	}
14799-	return []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)}, nil
14800-}
14801-
14802-func editGoDirectiveQuickFix(moduleMode bool, uri span.URI, version string) ([]source.SuggestedFix, error) {
14803-	// Go mod edit only supports module mode.
14804-	if !moduleMode {
14805-		return nil, nil
14806-	}
14807-	title := fmt.Sprintf("go mod edit -go=%s", version)
14808-	cmd, err := command.NewEditGoDirectiveCommand(title, command.EditGoDirectiveArgs{
14809-		URI:     protocol.URIFromSpanURI(uri),
14810-		Version: version,
14811-	})
14812-	if err != nil {
14813-		return nil, err
14814-	}
14815-	return []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)}, nil
14816-}
14817-
14818-// encodeDiagnostics gob-encodes the given diagnostics.
14819-func encodeDiagnostics(srcDiags []*source.Diagnostic) []byte {
14820-	var gobDiags []gobDiagnostic
14821-	for _, srcDiag := range srcDiags {
14822-		var gobFixes []gobSuggestedFix
14823-		for _, srcFix := range srcDiag.SuggestedFixes {
14824-			gobFix := gobSuggestedFix{
14825-				Message:    srcFix.Title,
14826-				ActionKind: srcFix.ActionKind,
14827-			}
14828-			for uri, srcEdits := range srcFix.Edits {
14829-				for _, srcEdit := range srcEdits {
14830-					gobFix.TextEdits = append(gobFix.TextEdits, gobTextEdit{
14831-						Location: protocol.Location{
14832-							URI:   protocol.URIFromSpanURI(uri),
14833-							Range: srcEdit.Range,
14834-						},
14835-						NewText: []byte(srcEdit.NewText),
14836-					})
14837-				}
14838-			}
14839-			if srcCmd := srcFix.Command; srcCmd != nil {
14840-				gobFix.Command = &gobCommand{
14841-					Title:     srcCmd.Title,
14842-					Command:   srcCmd.Command,
14843-					Arguments: srcCmd.Arguments,
14844-				}
14845-			}
14846-			gobFixes = append(gobFixes, gobFix)
14847-		}
14848-		var gobRelated []gobRelatedInformation
14849-		for _, srcRel := range srcDiag.Related {
14850-			gobRel := gobRelatedInformation(srcRel)
14851-			gobRelated = append(gobRelated, gobRel)
14852-		}
14853-		gobDiag := gobDiagnostic{
14854-			Location: protocol.Location{
14855-				URI:   protocol.URIFromSpanURI(srcDiag.URI),
14856-				Range: srcDiag.Range,
14857-			},
14858-			Severity:       srcDiag.Severity,
14859-			Code:           srcDiag.Code,
14860-			CodeHref:       srcDiag.CodeHref,
14861-			Source:         string(srcDiag.Source),
14862-			Message:        srcDiag.Message,
14863-			SuggestedFixes: gobFixes,
14864-			Related:        gobRelated,
14865-			Tags:           srcDiag.Tags,
14866-		}
14867-		gobDiags = append(gobDiags, gobDiag)
14868-	}
14869-	return mustEncode(gobDiags)
14870-}
14871-
14872-// decodeDiagnostics decodes the given gob-encoded diagnostics.
14873-func decodeDiagnostics(data []byte) []*source.Diagnostic {
14874-	var gobDiags []gobDiagnostic
14875-	mustDecode(data, &gobDiags)
14876-	var srcDiags []*source.Diagnostic
14877-	for _, gobDiag := range gobDiags {
14878-		var srcFixes []source.SuggestedFix
14879-		for _, gobFix := range gobDiag.SuggestedFixes {
14880-			srcFix := source.SuggestedFix{
14881-				Title:      gobFix.Message,
14882-				ActionKind: gobFix.ActionKind,
14883-			}
14884-			for _, gobEdit := range gobFix.TextEdits {
14885-				if srcFix.Edits == nil {
14886-					srcFix.Edits = make(map[span.URI][]protocol.TextEdit)
14887-				}
14888-				srcEdit := protocol.TextEdit{
14889-					Range:   gobEdit.Location.Range,
14890-					NewText: string(gobEdit.NewText),
14891-				}
14892-				uri := gobEdit.Location.URI.SpanURI()
14893-				srcFix.Edits[uri] = append(srcFix.Edits[uri], srcEdit)
14894-			}
14895-			if gobCmd := gobFix.Command; gobCmd != nil {
14896-				gobFix.Command = &gobCommand{
14897-					Title:     gobCmd.Title,
14898-					Command:   gobCmd.Command,
14899-					Arguments: gobCmd.Arguments,
14900-				}
14901-			}
14902-			srcFixes = append(srcFixes, srcFix)
14903-		}
14904-		var srcRelated []protocol.DiagnosticRelatedInformation
14905-		for _, gobRel := range gobDiag.Related {
14906-			srcRel := protocol.DiagnosticRelatedInformation(gobRel)
14907-			srcRelated = append(srcRelated, srcRel)
14908-		}
14909-		srcDiag := &source.Diagnostic{
14910-			URI:            gobDiag.Location.URI.SpanURI(),
14911-			Range:          gobDiag.Location.Range,
14912-			Severity:       gobDiag.Severity,
14913-			Source:         source.AnalyzerErrorKind(gobDiag.Source),
14914-			Message:        gobDiag.Message,
14915-			Tags:           gobDiag.Tags,
14916-			Related:        srcRelated,
14917-			SuggestedFixes: srcFixes,
14918-		}
14919-		srcDiags = append(srcDiags, srcDiag)
14920-	}
14921-	return srcDiags
14922-}
14923-
14924-// toSourceDiagnostic converts a gobDiagnostic to "source" form.
14925-func toSourceDiagnostic(srcAnalyzer *source.Analyzer, gobDiag *gobDiagnostic) *source.Diagnostic {
14926-	var related []protocol.DiagnosticRelatedInformation
14927-	for _, gobRelated := range gobDiag.Related {
14928-		related = append(related, protocol.DiagnosticRelatedInformation(gobRelated))
14929-	}
14930-
14931-	kinds := srcAnalyzer.ActionKind
14932-	if len(srcAnalyzer.ActionKind) == 0 {
14933-		kinds = append(kinds, protocol.QuickFix)
14934-	}
14935-	fixes := suggestedAnalysisFixes(gobDiag, kinds)
14936-	if srcAnalyzer.Fix != "" {
14937-		cmd, err := command.NewApplyFixCommand(gobDiag.Message, command.ApplyFixArgs{
14938-			URI:   gobDiag.Location.URI,
14939-			Range: gobDiag.Location.Range,
14940-			Fix:   srcAnalyzer.Fix,
14941-		})
14942-		if err != nil {
14943-			// JSON marshalling of these argument values cannot fail.
14944-			log.Fatalf("internal error in NewApplyFixCommand: %v", err)
14945-		}
14946-		for _, kind := range kinds {
14947-			fixes = append(fixes, source.SuggestedFixFromCommand(cmd, kind))
14948-		}
14949-	}
14950-
14951-	severity := srcAnalyzer.Severity
14952-	if severity == 0 {
14953-		severity = protocol.SeverityWarning
14954-	}
14955-
14956-	diag := &source.Diagnostic{
14957-		URI:            gobDiag.Location.URI.SpanURI(),
14958-		Range:          gobDiag.Location.Range,
14959-		Severity:       severity,
14960-		Source:         source.AnalyzerErrorKind(gobDiag.Source),
14961-		Message:        gobDiag.Message,
14962-		Related:        related,
14963-		SuggestedFixes: fixes,
14964-	}
14965-	// If the fixes only delete code, assume that the diagnostic is reporting dead code.
14966-	if onlyDeletions(fixes) {
14967-		diag.Tags = []protocol.DiagnosticTag{protocol.Unnecessary}
14968-	}
14969-	return diag
14970-}
14971-
14972-// onlyDeletions returns true if all of the suggested fixes are deletions.
14973-func onlyDeletions(fixes []source.SuggestedFix) bool {
14974-	for _, fix := range fixes {
14975-		if fix.Command != nil {
14976-			return false
14977-		}
14978-		for _, edits := range fix.Edits {
14979-			for _, edit := range edits {
14980-				if edit.NewText != "" {
14981-					return false
14982-				}
14983-				if protocol.ComparePosition(edit.Range.Start, edit.Range.End) == 0 {
14984-					return false
14985-				}
14986-			}
14987-		}
14988-	}
14989-	return len(fixes) > 0
14990-}
14991-
14992-func typesCodeHref(linkTarget string, code typesinternal.ErrorCode) string {
14993-	return source.BuildLink(linkTarget, "golang.org/x/tools/internal/typesinternal", code.String())
14994-}
14995-
14996-func suggestedAnalysisFixes(diag *gobDiagnostic, kinds []protocol.CodeActionKind) []source.SuggestedFix {
14997-	var fixes []source.SuggestedFix
14998-	for _, fix := range diag.SuggestedFixes {
14999-		edits := make(map[span.URI][]protocol.TextEdit)
15000-		for _, e := range fix.TextEdits {
15001-			uri := span.URI(e.Location.URI)
15002-			edits[uri] = append(edits[uri], protocol.TextEdit{
15003-				Range:   e.Location.Range,
15004-				NewText: string(e.NewText),
15005-			})
15006-		}
15007-		for _, kind := range kinds {
15008-			fixes = append(fixes, source.SuggestedFix{
15009-				Title:      fix.Message,
15010-				Edits:      edits,
15011-				ActionKind: kind,
15012-			})
15013-		}
15014-
15015-	}
15016-	return fixes
15017-}
15018-
15019-func typeErrorData(pkg *syntaxPackage, terr types.Error) (typesinternal.ErrorCode, protocol.Location, error) {
15020-	ecode, start, end, ok := typesinternal.ReadGo116ErrorData(terr)
15021-	if !ok {
15022-		start, end = terr.Pos, terr.Pos
15023-		ecode = 0
15024-	}
15025-	// go/types may return invalid positions in some cases, such as
15026-	// in errors on tokens missing from the syntax tree.
15027-	if !start.IsValid() {
15028-		return 0, protocol.Location{}, fmt.Errorf("type error (%q, code %d, go116=%t) without position", terr.Msg, ecode, ok)
15029-	}
15030-	// go/types errors retain their FileSet.
15031-	// Sanity-check that we're using the right one.
15032-	fset := pkg.fset
15033-	if fset != terr.Fset {
15034-		return 0, protocol.Location{}, bug.Errorf("wrong FileSet for type error")
15035-	}
15036-	posn := safetoken.StartPosition(fset, start)
15037-	if !posn.IsValid() {
15038-		return 0, protocol.Location{}, fmt.Errorf("position %d of type error %q (code %q) not found in FileSet", start, start, terr)
15039-	}
15040-	pgf, err := pkg.File(span.URIFromPath(posn.Filename))
15041-	if err != nil {
15042-		return 0, protocol.Location{}, err
15043-	}
15044-	if !end.IsValid() || end == start {
15045-		end = analysisinternal.TypeErrorEndPos(fset, pgf.Src, start)
15046-	}
15047-	loc, err := pgf.Mapper.PosLocation(pgf.Tok, start, end)
15048-	return ecode, loc, err
15049-}
15050-
15051-// spanToRange converts a span.Span to a protocol.Range, by mapping content
15052-// contained in the provided FileSource.
15053-func spanToRange(ctx context.Context, fs source.FileSource, spn span.Span) (protocol.Range, error) {
15054-	uri := spn.URI()
15055-	fh, err := fs.GetFile(ctx, uri)
15056-	if err != nil {
15057-		return protocol.Range{}, err
15058-	}
15059-	content, err := fh.Read()
15060-	if err != nil {
15061-		return protocol.Range{}, err
15062-	}
15063-	mapper := protocol.NewMapper(uri, content)
15064-	return mapper.SpanRange(spn)
15065-}
15066-
15067-// parseGoListError attempts to parse a standard `go list` error message
15068-// by stripping off the trailing error message.
15069-//
15070-// It works only on errors whose message is prefixed by colon,
15071-// followed by a space (": "). For example:
15072-//
15073-//	attributes.go:13:1: expected 'package', found 'type'
15074-func parseGoListError(input, wd string) span.Span {
15075-	input = strings.TrimSpace(input)
15076-	msgIndex := strings.Index(input, ": ")
15077-	if msgIndex < 0 {
15078-		return span.Parse(input)
15079-	}
15080-	return span.ParseInDir(input[:msgIndex], wd)
15081-}
15082-
15083-// parseGoListImportCycleError attempts to parse the given go/packages error as
15084-// an import cycle, returning a diagnostic if successful.
15085-//
15086-// If the error is not detected as an import cycle error, it returns nil, nil.
15087-func parseGoListImportCycleError(ctx context.Context, e packages.Error, m *source.Metadata, fs source.FileSource) (*source.Diagnostic, error) {
15088-	re := regexp.MustCompile(`(.*): import stack: \[(.+)\]`)
15089-	matches := re.FindStringSubmatch(strings.TrimSpace(e.Msg))
15090-	if len(matches) < 3 {
15091-		return nil, nil
15092-	}
15093-	msg := matches[1]
15094-	importList := strings.Split(matches[2], " ")
15095-	// Since the error is relative to the current package. The import that is causing
15096-	// the import cycle error is the second one in the list.
15097-	if len(importList) < 2 {
15098-		return nil, nil
15099-	}
15100-	// Imports have quotation marks around them.
15101-	circImp := strconv.Quote(importList[1])
15102-	for _, uri := range m.CompiledGoFiles {
15103-		pgf, err := parseGoURI(ctx, fs, uri, source.ParseHeader)
15104-		if err != nil {
15105-			return nil, err
15106-		}
15107-		// Search file imports for the import that is causing the import cycle.
15108-		for _, imp := range pgf.File.Imports {
15109-			if imp.Path.Value == circImp {
15110-				rng, err := pgf.NodeMappedRange(imp)
15111-				if err != nil {
15112-					return nil, nil
15113-				}
15114-
15115-				return &source.Diagnostic{
15116-					URI:      pgf.URI,
15117-					Range:    rng.Range(),
15118-					Severity: protocol.SeverityError,
15119-					Source:   source.ListError,
15120-					Message:  msg,
15121-				}, nil
15122-			}
15123-		}
15124-	}
15125-	return nil, nil
15126-}
15127-
15128-// parseGoURI is a helper to parse the Go file at the given URI from the file
15129-// source fs. The resulting syntax and token.File belong to an ephemeral,
15130-// encapsulated FileSet, so this file stands only on its own: it's not suitable
15131-// to use in a list of file of a package, for example.
15132-//
15133-// It returns an error if the file could not be read.
15134-func parseGoURI(ctx context.Context, fs source.FileSource, uri span.URI, mode source.ParseMode) (*source.ParsedGoFile, error) {
15135-	fh, err := fs.GetFile(ctx, uri)
15136-	if err != nil {
15137-		return nil, err
15138-	}
15139-	return parseGoImpl(ctx, token.NewFileSet(), fh, source.ParseHeader)
15140-}
15141-
15142-// parseModURI is a helper to parse the Mod file at the given URI from the file
15143-// source fs.
15144-//
15145-// It returns an error if the file could not be read.
15146-func parseModURI(ctx context.Context, fs source.FileSource, uri span.URI) (*source.ParsedModule, error) {
15147-	fh, err := fs.GetFile(ctx, uri)
15148-	if err != nil {
15149-		return nil, err
15150-	}
15151-	return parseModImpl(ctx, fh)
15152-}
15153diff -urN a/gopls/internal/lsp/cache/errors_test.go b/gopls/internal/lsp/cache/errors_test.go
15154--- a/gopls/internal/lsp/cache/errors_test.go	2000-01-01 00:00:00.000000000 -0000
15155+++ b/gopls/internal/lsp/cache/errors_test.go	1970-01-01 00:00:00.000000000 +0000
15156@@ -1,52 +0,0 @@
15157-// Copyright 2019 The Go Authors. All rights reserved.
15158-// Use of this source code is governed by a BSD-style
15159-// license that can be found in the LICENSE file.
15160-
15161-package cache
15162-
15163-import (
15164-	"strings"
15165-	"testing"
15166-)
15167-
15168-func TestParseErrorMessage(t *testing.T) {
15169-	tests := []struct {
15170-		name             string
15171-		in               string
15172-		expectedFileName string
15173-		expectedLine     int
15174-		expectedColumn   int
15175-	}{
15176-		{
15177-			name:             "from go list output",
15178-			in:               "\nattributes.go:13:1: expected 'package', found 'type'",
15179-			expectedFileName: "attributes.go",
15180-			expectedLine:     13,
15181-			expectedColumn:   1,
15182-		},
15183-	}
15184-
15185-	for _, tt := range tests {
15186-		t.Run(tt.name, func(t *testing.T) {
15187-			spn := parseGoListError(tt.in, ".")
15188-			fn := spn.URI().Filename()
15189-
15190-			if !strings.HasSuffix(fn, tt.expectedFileName) {
15191-				t.Errorf("expected filename with suffix %v but got %v", tt.expectedFileName, fn)
15192-			}
15193-
15194-			if !spn.HasPosition() {
15195-				t.Fatalf("expected span to have position")
15196-			}
15197-
15198-			pos := spn.Start()
15199-			if pos.Line() != tt.expectedLine {
15200-				t.Errorf("expected line %v but got %v", tt.expectedLine, pos.Line())
15201-			}
15202-
15203-			if pos.Column() != tt.expectedColumn {
15204-				t.Errorf("expected line %v but got %v", tt.expectedLine, pos.Line())
15205-			}
15206-		})
15207-	}
15208-}
15209diff -urN a/gopls/internal/lsp/cache/fs_memoized.go b/gopls/internal/lsp/cache/fs_memoized.go
15210--- a/gopls/internal/lsp/cache/fs_memoized.go	2000-01-01 00:00:00.000000000 -0000
15211+++ b/gopls/internal/lsp/cache/fs_memoized.go	1970-01-01 00:00:00.000000000 +0000
15212@@ -1,149 +0,0 @@
15213-// Copyright 2023 The Go Authors. All rights reserved.
15214-// Use of this source code is governed by a BSD-style
15215-// license that can be found in the LICENSE file.
15216-
15217-package cache
15218-
15219-import (
15220-	"context"
15221-	"os"
15222-	"sync"
15223-	"time"
15224-
15225-	"golang.org/x/tools/gopls/internal/lsp/source"
15226-	"golang.org/x/tools/gopls/internal/span"
15227-	"golang.org/x/tools/internal/event"
15228-	"golang.org/x/tools/internal/event/tag"
15229-	"golang.org/x/tools/internal/robustio"
15230-)
15231-
15232-// A memoizedFS is a file source that memoizes reads, to reduce IO.
15233-type memoizedFS struct {
15234-	mu sync.Mutex
15235-
15236-	// filesByID maps existing file inodes to the result of a read.
15237-	// (The read may have failed, e.g. due to EACCES or a delete between stat+read.)
15238-	// Each slice is a non-empty list of aliases: different URIs.
15239-	filesByID map[robustio.FileID][]*DiskFile
15240-}
15241-
15242-func newMemoizedFS() *memoizedFS {
15243-	return &memoizedFS{filesByID: make(map[robustio.FileID][]*DiskFile)}
15244-}
15245-
15246-// A DiskFile is a file on the filesystem, or a failure to read one.
15247-// It implements the source.FileHandle interface.
15248-type DiskFile struct {
15249-	uri     span.URI
15250-	modTime time.Time
15251-	content []byte
15252-	hash    source.Hash
15253-	err     error
15254-}
15255-
15256-func (h *DiskFile) URI() span.URI { return h.uri }
15257-
15258-func (h *DiskFile) FileIdentity() source.FileIdentity {
15259-	return source.FileIdentity{
15260-		URI:  h.uri,
15261-		Hash: h.hash,
15262-	}
15263-}
15264-
15265-func (h *DiskFile) Saved() bool           { return true }
15266-func (h *DiskFile) Version() int32        { return 0 }
15267-func (h *DiskFile) Read() ([]byte, error) { return h.content, h.err }
15268-
15269-// GetFile stats and (maybe) reads the file, updates the cache, and returns it.
15270-func (fs *memoizedFS) GetFile(ctx context.Context, uri span.URI) (source.FileHandle, error) {
15271-	id, mtime, err := robustio.GetFileID(uri.Filename())
15272-	if err != nil {
15273-		// file does not exist
15274-		return &DiskFile{
15275-			err: err,
15276-			uri: uri,
15277-		}, nil
15278-	}
15279-
15280-	// We check if the file has changed by comparing modification times. Notably,
15281-	// this is an imperfect heuristic as various systems have low resolution
15282-	// mtimes (as much as 1s on WSL or s390x builders), so we only cache
15283-	// filehandles if mtime is old enough to be reliable, meaning that we don't
15284-	// expect a subsequent write to have the same mtime.
15285-	//
15286-	// The coarsest mtime precision we've seen in practice is 1s, so consider
15287-	// mtime to be unreliable if it is less than 2s old. Capture this before
15288-	// doing anything else.
15289-	recentlyModified := time.Since(mtime) < 2*time.Second
15290-
15291-	fs.mu.Lock()
15292-	fhs, ok := fs.filesByID[id]
15293-	if ok && fhs[0].modTime.Equal(mtime) {
15294-		var fh *DiskFile
15295-		// We have already seen this file and it has not changed.
15296-		for _, h := range fhs {
15297-			if h.uri == uri {
15298-				fh = h
15299-				break
15300-			}
15301-		}
15302-		// No file handle for this exact URI. Create an alias, but share content.
15303-		if fh == nil {
15304-			newFH := *fhs[0]
15305-			newFH.uri = uri
15306-			fh = &newFH
15307-			fhs = append(fhs, fh)
15308-			fs.filesByID[id] = fhs
15309-		}
15310-		fs.mu.Unlock()
15311-		return fh, nil
15312-	}
15313-	fs.mu.Unlock()
15314-
15315-	// Unknown file, or file has changed. Read (or re-read) it.
15316-	fh, err := readFile(ctx, uri, mtime) // ~25us
15317-	if err != nil {
15318-		return nil, err // e.g. cancelled (not: read failed)
15319-	}
15320-
15321-	fs.mu.Lock()
15322-	if !recentlyModified {
15323-		fs.filesByID[id] = []*DiskFile{fh}
15324-	} else {
15325-		delete(fs.filesByID, id)
15326-	}
15327-	fs.mu.Unlock()
15328-	return fh, nil
15329-}
15330-
15331-// ioLimit limits the number of parallel file reads per process.
15332-var ioLimit = make(chan struct{}, 128)
15333-
15334-func readFile(ctx context.Context, uri span.URI, mtime time.Time) (*DiskFile, error) {
15335-	select {
15336-	case ioLimit <- struct{}{}:
15337-	case <-ctx.Done():
15338-		return nil, ctx.Err()
15339-	}
15340-	defer func() { <-ioLimit }()
15341-
15342-	ctx, done := event.Start(ctx, "cache.readFile", tag.File.Of(uri.Filename()))
15343-	_ = ctx
15344-	defer done()
15345-
15346-	// It is possible that a race causes us to read a file with different file
15347-	// ID, or whose mtime differs from the given mtime. However, in these cases
15348-	// we expect the client to notify of a subsequent file change, and the file
15349-	// content should be eventually consistent.
15350-	content, err := os.ReadFile(uri.Filename()) // ~20us
15351-	if err != nil {
15352-		content = nil // just in case
15353-	}
15354-	return &DiskFile{
15355-		modTime: mtime,
15356-		uri:     uri,
15357-		content: content,
15358-		hash:    source.HashOf(content),
15359-		err:     err,
15360-	}, nil
15361-}
15362diff -urN a/gopls/internal/lsp/cache/fs_overlay.go b/gopls/internal/lsp/cache/fs_overlay.go
15363--- a/gopls/internal/lsp/cache/fs_overlay.go	2000-01-01 00:00:00.000000000 -0000
15364+++ b/gopls/internal/lsp/cache/fs_overlay.go	1970-01-01 00:00:00.000000000 +0000
15365@@ -1,78 +0,0 @@
15366-// Copyright 2023 The Go Authors. All rights reserved.
15367-// Use of this source code is governed by a BSD-style
15368-// license that can be found in the LICENSE file.
15369-
15370-package cache
15371-
15372-import (
15373-	"context"
15374-	"sync"
15375-
15376-	"golang.org/x/tools/gopls/internal/lsp/source"
15377-	"golang.org/x/tools/gopls/internal/span"
15378-)
15379-
15380-// An overlayFS is a source.FileSource that keeps track of overlays on top of a
15381-// delegate FileSource.
15382-type overlayFS struct {
15383-	delegate source.FileSource
15384-
15385-	mu       sync.Mutex
15386-	overlays map[span.URI]*Overlay
15387-}
15388-
15389-func newOverlayFS(delegate source.FileSource) *overlayFS {
15390-	return &overlayFS{
15391-		delegate: delegate,
15392-		overlays: make(map[span.URI]*Overlay),
15393-	}
15394-}
15395-
15396-// Overlays returns a new unordered array of overlays.
15397-func (fs *overlayFS) Overlays() []*Overlay {
15398-	fs.mu.Lock()
15399-	defer fs.mu.Unlock()
15400-	overlays := make([]*Overlay, 0, len(fs.overlays))
15401-	for _, overlay := range fs.overlays {
15402-		overlays = append(overlays, overlay)
15403-	}
15404-	return overlays
15405-}
15406-
15407-func (fs *overlayFS) GetFile(ctx context.Context, uri span.URI) (source.FileHandle, error) {
15408-	fs.mu.Lock()
15409-	overlay, ok := fs.overlays[uri]
15410-	fs.mu.Unlock()
15411-	if ok {
15412-		return overlay, nil
15413-	}
15414-	return fs.delegate.GetFile(ctx, uri)
15415-}
15416-
15417-// An Overlay is a file open in the editor. It may have unsaved edits.
15418-// It implements the source.FileHandle interface.
15419-type Overlay struct {
15420-	uri     span.URI
15421-	content []byte
15422-	hash    source.Hash
15423-	version int32
15424-	kind    source.FileKind
15425-
15426-	// saved is true if a file matches the state on disk,
15427-	// and therefore does not need to be part of the overlay sent to go/packages.
15428-	saved bool
15429-}
15430-
15431-func (o *Overlay) URI() span.URI { return o.uri }
15432-
15433-func (o *Overlay) FileIdentity() source.FileIdentity {
15434-	return source.FileIdentity{
15435-		URI:  o.uri,
15436-		Hash: o.hash,
15437-	}
15438-}
15439-
15440-func (o *Overlay) Read() ([]byte, error) { return o.content, nil }
15441-func (o *Overlay) Version() int32        { return o.version }
15442-func (o *Overlay) Saved() bool           { return o.saved }
15443-func (o *Overlay) Kind() source.FileKind { return o.kind }
15444diff -urN a/gopls/internal/lsp/cache/graph.go b/gopls/internal/lsp/cache/graph.go
15445--- a/gopls/internal/lsp/cache/graph.go	2000-01-01 00:00:00.000000000 -0000
15446+++ b/gopls/internal/lsp/cache/graph.go	1970-01-01 00:00:00.000000000 +0000
15447@@ -1,131 +0,0 @@
15448-// Copyright 2022 The Go Authors. All rights reserved.
15449-// Use of this source code is governed by a BSD-style
15450-// license that can be found in the LICENSE file.
15451-
15452-package cache
15453-
15454-import (
15455-	"sort"
15456-
15457-	"golang.org/x/tools/gopls/internal/lsp/source"
15458-	"golang.org/x/tools/gopls/internal/span"
15459-)
15460-
15461-// A metadataGraph is an immutable and transitively closed import
15462-// graph of Go packages, as obtained from go/packages.
15463-type metadataGraph struct {
15464-	// metadata maps package IDs to their associated metadata.
15465-	metadata map[PackageID]*source.Metadata
15466-
15467-	// importedBy maps package IDs to the list of packages that import them.
15468-	importedBy map[PackageID][]PackageID
15469-
15470-	// ids maps file URIs to package IDs, sorted by (!valid, cli, packageID).
15471-	// A single file may belong to multiple packages due to tests packages.
15472-	ids map[span.URI][]PackageID
15473-}
15474-
15475-// Metadata implements the source.MetadataSource interface.
15476-func (g *metadataGraph) Metadata(id PackageID) *source.Metadata {
15477-	return g.metadata[id]
15478-}
15479-
15480-// Clone creates a new metadataGraph, applying the given updates to the
15481-// receiver.
15482-func (g *metadataGraph) Clone(updates map[PackageID]*source.Metadata) *metadataGraph {
15483-	if len(updates) == 0 {
15484-		// Optimization: since the graph is immutable, we can return the receiver.
15485-		return g
15486-	}
15487-	result := &metadataGraph{metadata: make(map[PackageID]*source.Metadata, len(g.metadata))}
15488-	// Copy metadata.
15489-	for id, m := range g.metadata {
15490-		result.metadata[id] = m
15491-	}
15492-	for id, m := range updates {
15493-		if m == nil {
15494-			delete(result.metadata, id)
15495-		} else {
15496-			result.metadata[id] = m
15497-		}
15498-	}
15499-	result.build()
15500-	return result
15501-}
15502-
15503-// build constructs g.importedBy and g.uris from g.metadata.
15504-//
15505-// TODO(rfindley): we should enforce that the graph is acyclic here.
15506-func (g *metadataGraph) build() {
15507-	// Build the import graph.
15508-	g.importedBy = make(map[PackageID][]PackageID)
15509-	for id, m := range g.metadata {
15510-		for _, depID := range m.DepsByPkgPath {
15511-			g.importedBy[depID] = append(g.importedBy[depID], id)
15512-		}
15513-	}
15514-
15515-	// Collect file associations.
15516-	g.ids = make(map[span.URI][]PackageID)
15517-	for id, m := range g.metadata {
15518-		uris := map[span.URI]struct{}{}
15519-		for _, uri := range m.CompiledGoFiles {
15520-			uris[uri] = struct{}{}
15521-		}
15522-		for _, uri := range m.GoFiles {
15523-			uris[uri] = struct{}{}
15524-		}
15525-		for uri := range uris {
15526-			g.ids[uri] = append(g.ids[uri], id)
15527-		}
15528-	}
15529-
15530-	// Sort and filter file associations.
15531-	for uri, ids := range g.ids {
15532-		sort.Slice(ids, func(i, j int) bool {
15533-			cli := source.IsCommandLineArguments(ids[i])
15534-			clj := source.IsCommandLineArguments(ids[j])
15535-			if cli != clj {
15536-				return clj
15537-			}
15538-
15539-			// 2. packages appear in name order.
15540-			return ids[i] < ids[j]
15541-		})
15542-
15543-		// Choose the best IDs for each URI, according to the following rules:
15544-		//  - If there are any valid real packages, choose them.
15545-		//  - Else, choose the first valid command-line-argument package, if it exists.
15546-		//
15547-		// TODO(rfindley): it might be better to track all IDs here, and exclude
15548-		// them later when type checking, but this is the existing behavior.
15549-		for i, id := range ids {
15550-			// If we've seen *anything* prior to command-line arguments package, take
15551-			// it. Note that ids[0] may itself be command-line-arguments.
15552-			if i > 0 && source.IsCommandLineArguments(id) {
15553-				g.ids[uri] = ids[:i]
15554-				break
15555-			}
15556-		}
15557-	}
15558-}
15559-
15560-// reverseReflexiveTransitiveClosure returns a new mapping containing the
15561-// metadata for the specified packages along with any package that
15562-// transitively imports one of them, keyed by ID, including all the initial packages.
15563-func (g *metadataGraph) reverseReflexiveTransitiveClosure(ids ...PackageID) map[PackageID]*source.Metadata {
15564-	seen := make(map[PackageID]*source.Metadata)
15565-	var visitAll func([]PackageID)
15566-	visitAll = func(ids []PackageID) {
15567-		for _, id := range ids {
15568-			if seen[id] == nil {
15569-				if m := g.metadata[id]; m != nil {
15570-					seen[id] = m
15571-					visitAll(g.importedBy[id])
15572-				}
15573-			}
15574-		}
15575-	}
15576-	visitAll(ids)
15577-	return seen
15578-}
15579diff -urN a/gopls/internal/lsp/cache/imports.go b/gopls/internal/lsp/cache/imports.go
15580--- a/gopls/internal/lsp/cache/imports.go	2000-01-01 00:00:00.000000000 -0000
15581+++ b/gopls/internal/lsp/cache/imports.go	1970-01-01 00:00:00.000000000 +0000
15582@@ -1,188 +0,0 @@
15583-// Copyright 2020 The Go Authors. All rights reserved.
15584-// Use of this source code is governed by a BSD-style
15585-// license that can be found in the LICENSE file.
15586-
15587-package cache
15588-
15589-import (
15590-	"context"
15591-	"fmt"
15592-	"reflect"
15593-	"strings"
15594-	"sync"
15595-	"time"
15596-
15597-	"golang.org/x/tools/gopls/internal/lsp/source"
15598-	"golang.org/x/tools/internal/event"
15599-	"golang.org/x/tools/internal/event/keys"
15600-	"golang.org/x/tools/internal/gocommand"
15601-	"golang.org/x/tools/internal/imports"
15602-)
15603-
15604-type importsState struct {
15605-	ctx context.Context
15606-
15607-	mu                     sync.Mutex
15608-	processEnv             *imports.ProcessEnv
15609-	cacheRefreshDuration   time.Duration
15610-	cacheRefreshTimer      *time.Timer
15611-	cachedModFileHash      source.Hash
15612-	cachedBuildFlags       []string
15613-	cachedDirectoryFilters []string
15614-
15615-	// runOnce records whether runProcessEnvFunc has been called at least once.
15616-	// This is necessary to avoid resetting state before the process env is
15617-	// populated.
15618-	//
15619-	// TODO(rfindley): this shouldn't be necessary.
15620-	runOnce bool
15621-}
15622-
15623-func (s *importsState) runProcessEnvFunc(ctx context.Context, snapshot *snapshot, fn func(*imports.Options) error) error {
15624-	s.mu.Lock()
15625-	defer s.mu.Unlock()
15626-
15627-	// Find the hash of active mod files, if any. Using the unsaved content
15628-	// is slightly wasteful, since we'll drop caches a little too often, but
15629-	// the mod file shouldn't be changing while people are autocompleting.
15630-	//
15631-	// TODO(rfindley): consider instead hashing on-disk modfiles here.
15632-	var modFileHash source.Hash
15633-	for m := range snapshot.workspaceModFiles {
15634-		fh, err := snapshot.GetFile(ctx, m)
15635-		if err != nil {
15636-			return err
15637-		}
15638-		modFileHash.XORWith(fh.FileIdentity().Hash)
15639-	}
15640-
15641-	// view.goEnv is immutable -- changes make a new view. Options can change.
15642-	// We can't compare build flags directly because we may add -modfile.
15643-	snapshot.view.optionsMu.Lock()
15644-	localPrefix := snapshot.view.options.Local
15645-	currentBuildFlags := snapshot.view.options.BuildFlags
15646-	currentDirectoryFilters := snapshot.view.options.DirectoryFilters
15647-	changed := !reflect.DeepEqual(currentBuildFlags, s.cachedBuildFlags) ||
15648-		snapshot.view.options.VerboseOutput != (s.processEnv.Logf != nil) ||
15649-		modFileHash != s.cachedModFileHash ||
15650-		!reflect.DeepEqual(snapshot.view.options.DirectoryFilters, s.cachedDirectoryFilters)
15651-	snapshot.view.optionsMu.Unlock()
15652-
15653-	// If anything relevant to imports has changed, clear caches and
15654-	// update the processEnv. Clearing caches blocks on any background
15655-	// scans.
15656-	if changed {
15657-		// As a special case, skip cleanup the first time -- we haven't fully
15658-		// initialized the environment yet and calling GetResolver will do
15659-		// unnecessary work and potentially mess up the go.mod file.
15660-		if s.runOnce {
15661-			if resolver, err := s.processEnv.GetResolver(); err == nil {
15662-				if modResolver, ok := resolver.(*imports.ModuleResolver); ok {
15663-					modResolver.ClearForNewMod()
15664-				}
15665-			}
15666-		}
15667-
15668-		s.cachedModFileHash = modFileHash
15669-		s.cachedBuildFlags = currentBuildFlags
15670-		s.cachedDirectoryFilters = currentDirectoryFilters
15671-		if err := s.populateProcessEnv(ctx, snapshot); err != nil {
15672-			return err
15673-		}
15674-		s.runOnce = true
15675-	}
15676-
15677-	// Run the user function.
15678-	opts := &imports.Options{
15679-		// Defaults.
15680-		AllErrors:   true,
15681-		Comments:    true,
15682-		Fragment:    true,
15683-		FormatOnly:  false,
15684-		TabIndent:   true,
15685-		TabWidth:    8,
15686-		Env:         s.processEnv,
15687-		LocalPrefix: localPrefix,
15688-	}
15689-
15690-	if err := fn(opts); err != nil {
15691-		return err
15692-	}
15693-
15694-	if s.cacheRefreshTimer == nil {
15695-		// Don't refresh more than twice per minute.
15696-		delay := 30 * time.Second
15697-		// Don't spend more than a couple percent of the time refreshing.
15698-		if adaptive := 50 * s.cacheRefreshDuration; adaptive > delay {
15699-			delay = adaptive
15700-		}
15701-		s.cacheRefreshTimer = time.AfterFunc(delay, s.refreshProcessEnv)
15702-	}
15703-
15704-	return nil
15705-}
15706-
15707-// populateProcessEnv sets the dynamically configurable fields for the view's
15708-// process environment. Assumes that the caller is holding the s.view.importsMu.
15709-func (s *importsState) populateProcessEnv(ctx context.Context, snapshot *snapshot) error {
15710-	pe := s.processEnv
15711-
15712-	if snapshot.view.Options().VerboseOutput {
15713-		pe.Logf = func(format string, args ...interface{}) {
15714-			event.Log(ctx, fmt.Sprintf(format, args...))
15715-		}
15716-	} else {
15717-		pe.Logf = nil
15718-	}
15719-
15720-	// Extract invocation details from the snapshot to use with goimports.
15721-	//
15722-	// TODO(rfindley): refactor to extract the necessary invocation logic into
15723-	// separate functions. Using goCommandInvocation is unnecessarily indirect,
15724-	// and has led to memory leaks in the past, when the snapshot was
15725-	// unintentionally held past its lifetime.
15726-	_, inv, cleanupInvocation, err := snapshot.goCommandInvocation(ctx, source.LoadWorkspace, &gocommand.Invocation{
15727-		WorkingDir: snapshot.view.workingDir().Filename(),
15728-	})
15729-	if err != nil {
15730-		return err
15731-	}
15732-
15733-	pe.BuildFlags = inv.BuildFlags
15734-	pe.ModFlag = "readonly" // processEnv operations should not mutate the modfile
15735-	pe.Env = map[string]string{}
15736-	for _, kv := range inv.Env {
15737-		split := strings.SplitN(kv, "=", 2)
15738-		if len(split) != 2 {
15739-			continue
15740-		}
15741-		pe.Env[split[0]] = split[1]
15742-	}
15743-	// We don't actually use the invocation, so clean it up now.
15744-	cleanupInvocation()
15745-	// TODO(rfindley): should this simply be inv.WorkingDir?
15746-	pe.WorkingDir = snapshot.view.workingDir().Filename()
15747-	return nil
15748-}
15749-
15750-func (s *importsState) refreshProcessEnv() {
15751-	start := time.Now()
15752-
15753-	s.mu.Lock()
15754-	env := s.processEnv
15755-	if resolver, err := s.processEnv.GetResolver(); err == nil {
15756-		resolver.ClearForNewScan()
15757-	}
15758-	s.mu.Unlock()
15759-
15760-	event.Log(s.ctx, "background imports cache refresh starting")
15761-	if err := imports.PrimeCache(context.Background(), env); err == nil {
15762-		event.Log(s.ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start)))
15763-	} else {
15764-		event.Log(s.ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start)), keys.Err.Of(err))
15765-	}
15766-	s.mu.Lock()
15767-	s.cacheRefreshDuration = time.Since(start)
15768-	s.cacheRefreshTimer = nil
15769-	s.mu.Unlock()
15770-}
15771diff -urN a/gopls/internal/lsp/cache/keys.go b/gopls/internal/lsp/cache/keys.go
15772--- a/gopls/internal/lsp/cache/keys.go	2000-01-01 00:00:00.000000000 -0000
15773+++ b/gopls/internal/lsp/cache/keys.go	1970-01-01 00:00:00.000000000 +0000
15774@@ -1,52 +0,0 @@
15775-// Copyright 2020 The Go Authors. All rights reserved.
15776-// Use of this source code is governed by a BSD-style
15777-// license that can be found in the LICENSE file.
15778-
15779-package cache
15780-
15781-import (
15782-	"io"
15783-
15784-	"golang.org/x/tools/internal/event/label"
15785-)
15786-
15787-var (
15788-	KeyCreateSession   = NewSessionKey("create_session", "A new session was added")
15789-	KeyUpdateSession   = NewSessionKey("update_session", "Updated information about a session")
15790-	KeyShutdownSession = NewSessionKey("shutdown_session", "A session was shut down")
15791-)
15792-
15793-// SessionKey represents an event label key that has a *Session value.
15794-type SessionKey struct {
15795-	name        string
15796-	description string
15797-}
15798-
15799-// NewSessionKey creates a new Key for *Session values.
15800-func NewSessionKey(name, description string) *SessionKey {
15801-	return &SessionKey{name: name, description: description}
15802-}
15803-
15804-func (k *SessionKey) Name() string        { return k.name }
15805-func (k *SessionKey) Description() string { return k.description }
15806-
15807-func (k *SessionKey) Format(w io.Writer, buf []byte, l label.Label) {
15808-	io.WriteString(w, k.From(l).ID())
15809-}
15810-
15811-// Of creates a new Label with this key and the supplied session.
15812-func (k *SessionKey) Of(v *Session) label.Label { return label.OfValue(k, v) }
15813-
15814-// Get can be used to get the session for the key from a label.Map.
15815-func (k *SessionKey) Get(lm label.Map) *Session {
15816-	if t := lm.Find(k); t.Valid() {
15817-		return k.From(t)
15818-	}
15819-	return nil
15820-}
15821-
15822-// From can be used to get the session value from a Label.
15823-func (k *SessionKey) From(t label.Label) *Session {
15824-	err, _ := t.UnpackValue().(*Session)
15825-	return err
15826-}
15827diff -urN a/gopls/internal/lsp/cache/load.go b/gopls/internal/lsp/cache/load.go
15828--- a/gopls/internal/lsp/cache/load.go	2000-01-01 00:00:00.000000000 -0000
15829+++ b/gopls/internal/lsp/cache/load.go	1970-01-01 00:00:00.000000000 +0000
15830@@ -1,782 +0,0 @@
15831-// Copyright 2019 The Go Authors. All rights reserved.
15832-// Use of this source code is governed by a BSD-style
15833-// license that can be found in the LICENSE file.
15834-
15835-package cache
15836-
15837-import (
15838-	"bytes"
15839-	"context"
15840-	"errors"
15841-	"fmt"
15842-	"path/filepath"
15843-	"sort"
15844-	"strings"
15845-	"sync/atomic"
15846-	"time"
15847-
15848-	"golang.org/x/tools/go/packages"
15849-	"golang.org/x/tools/gopls/internal/lsp/protocol"
15850-	"golang.org/x/tools/gopls/internal/lsp/source"
15851-	"golang.org/x/tools/gopls/internal/span"
15852-	"golang.org/x/tools/internal/bug"
15853-	"golang.org/x/tools/internal/event"
15854-	"golang.org/x/tools/internal/event/tag"
15855-	"golang.org/x/tools/internal/gocommand"
15856-	"golang.org/x/tools/internal/packagesinternal"
15857-)
15858-
15859-var loadID uint64 // atomic identifier for loads
15860-
15861-// errNoPackages indicates that a load query matched no packages.
15862-var errNoPackages = errors.New("no packages returned")
15863-
15864-// load calls packages.Load for the given scopes, updating package metadata,
15865-// import graph, and mapped files with the result.
15866-//
15867-// The resulting error may wrap the moduleErrorMap error type, representing
15868-// errors associated with specific modules.
15869-func (s *snapshot) load(ctx context.Context, allowNetwork bool, scopes ...loadScope) (err error) {
15870-	id := atomic.AddUint64(&loadID, 1)
15871-	eventName := fmt.Sprintf("go/packages.Load #%d", id) // unique name for logging
15872-
15873-	var query []string
15874-	var containsDir bool // for logging
15875-
15876-	// Keep track of module query -> module path so that we can later correlate query
15877-	// errors with errors.
15878-	moduleQueries := make(map[string]string)
15879-	for _, scope := range scopes {
15880-		switch scope := scope.(type) {
15881-		case packageLoadScope:
15882-			// The only time we pass package paths is when we're doing a
15883-			// partial workspace load. In those cases, the paths came back from
15884-			// go list and should already be GOPATH-vendorized when appropriate.
15885-			query = append(query, string(scope))
15886-
15887-		case fileLoadScope:
15888-			uri := span.URI(scope)
15889-			fh := s.FindFile(uri)
15890-			if fh == nil || s.View().FileKind(fh) != source.Go {
15891-				// Don't try to load a file that doesn't exist, or isn't a go file.
15892-				continue
15893-			}
15894-			contents, err := fh.Read()
15895-			if err != nil {
15896-				continue
15897-			}
15898-			if isStandaloneFile(contents, s.view.Options().StandaloneTags) {
15899-				query = append(query, uri.Filename())
15900-			} else {
15901-				query = append(query, fmt.Sprintf("file=%s", uri.Filename()))
15902-			}
15903-
15904-		case moduleLoadScope:
15905-			switch scope {
15906-			case "std", "cmd":
15907-				query = append(query, string(scope))
15908-			default:
15909-				modQuery := fmt.Sprintf("%s/...", scope)
15910-				query = append(query, modQuery)
15911-				moduleQueries[modQuery] = string(scope)
15912-			}
15913-
15914-		case viewLoadScope:
15915-			// If we are outside of GOPATH, a module, or some other known
15916-			// build system, don't load subdirectories.
15917-			if !s.ValidBuildConfiguration() {
15918-				query = append(query, "./")
15919-			} else {
15920-				query = append(query, "./...")
15921-			}
15922-
15923-		default:
15924-			panic(fmt.Sprintf("unknown scope type %T", scope))
15925-		}
15926-		switch scope.(type) {
15927-		case viewLoadScope, moduleLoadScope:
15928-			containsDir = true
15929-		}
15930-	}
15931-	if len(query) == 0 {
15932-		return nil
15933-	}
15934-	sort.Strings(query) // for determinism
15935-
15936-	ctx, done := event.Start(ctx, "cache.view.load", tag.Query.Of(query))
15937-	defer done()
15938-
15939-	flags := source.LoadWorkspace
15940-	if allowNetwork {
15941-		flags |= source.AllowNetwork
15942-	}
15943-	_, inv, cleanup, err := s.goCommandInvocation(ctx, flags, &gocommand.Invocation{
15944-		WorkingDir: s.view.workingDir().Filename(),
15945-	})
15946-	if err != nil {
15947-		return err
15948-	}
15949-
15950-	// Set a last resort deadline on packages.Load since it calls the go
15951-	// command, which may hang indefinitely if it has a bug. golang/go#42132
15952-	// and golang/go#42255 have more context.
15953-	ctx, cancel := context.WithTimeout(ctx, 10*time.Minute)
15954-	defer cancel()
15955-
15956-	cfg := s.config(ctx, inv)
15957-	pkgs, err := packages.Load(cfg, query...)
15958-	cleanup()
15959-
15960-	// If the context was canceled, return early. Otherwise, we might be
15961-	// type-checking an incomplete result. Check the context directly,
15962-	// because go/packages adds extra information to the error.
15963-	if ctx.Err() != nil {
15964-		return ctx.Err()
15965-	}
15966-
15967-	// This log message is sought for by TestReloadOnlyOnce.
15968-	labels := append(source.SnapshotLabels(s), tag.Query.Of(query), tag.PackageCount.Of(len(pkgs)))
15969-	if err != nil {
15970-		event.Error(ctx, eventName, err, labels...)
15971-	} else {
15972-		event.Log(ctx, eventName, labels...)
15973-	}
15974-
15975-	if len(pkgs) == 0 {
15976-		if err == nil {
15977-			err = errNoPackages
15978-		}
15979-		return fmt.Errorf("packages.Load error: %w", err)
15980-	}
15981-
15982-	moduleErrs := make(map[string][]packages.Error) // module path -> errors
15983-	filterFunc := s.view.filterFunc()
15984-	newMetadata := make(map[PackageID]*source.Metadata)
15985-	for _, pkg := range pkgs {
15986-		// The Go command returns synthetic list results for module queries that
15987-		// encountered module errors.
15988-		//
15989-		// For example, given a module path a.mod, we'll query for "a.mod/..." and
15990-		// the go command will return a package named "a.mod/..." holding this
15991-		// error. Save it for later interpretation.
15992-		//
15993-		// See golang/go#50862 for more details.
15994-		if mod := moduleQueries[pkg.PkgPath]; mod != "" { // a synthetic result for the unloadable module
15995-			if len(pkg.Errors) > 0 {
15996-				moduleErrs[mod] = pkg.Errors
15997-			}
15998-			continue
15999-		}
16000-
16001-		if !containsDir || s.view.Options().VerboseOutput {
16002-			event.Log(ctx, eventName, append(
16003-				source.SnapshotLabels(s),
16004-				tag.Package.Of(pkg.ID),
16005-				tag.Files.Of(pkg.CompiledGoFiles))...)
16006-		}
16007-
16008-		// Ignore packages with no sources, since we will never be able to
16009-		// correctly invalidate that metadata.
16010-		if len(pkg.GoFiles) == 0 && len(pkg.CompiledGoFiles) == 0 {
16011-			continue
16012-		}
16013-		// Special case for the builtin package, as it has no dependencies.
16014-		if pkg.PkgPath == "builtin" {
16015-			if len(pkg.GoFiles) != 1 {
16016-				return fmt.Errorf("only expected 1 file for builtin, got %v", len(pkg.GoFiles))
16017-			}
16018-			s.setBuiltin(pkg.GoFiles[0])
16019-			continue
16020-		}
16021-		// Skip test main packages.
16022-		if isTestMain(pkg, s.view.gocache) {
16023-			continue
16024-		}
16025-		// Skip filtered packages. They may be added anyway if they're
16026-		// dependencies of non-filtered packages.
16027-		//
16028-		// TODO(rfindley): why exclude metadata arbitrarily here? It should be safe
16029-		// to capture all metadata.
16030-		// TODO(rfindley): what about compiled go files?
16031-		if allFilesExcluded(pkg.GoFiles, filterFunc) {
16032-			continue
16033-		}
16034-		if err := buildMetadata(ctx, pkg, cfg, query, newMetadata, nil); err != nil {
16035-			return err
16036-		}
16037-	}
16038-
16039-	s.mu.Lock()
16040-
16041-	// Compute the minimal metadata updates (for Clone)
16042-	// required to preserve this invariant:
16043-	// for all id, s.packages.Get(id).m == s.meta.metadata[id].
16044-	updates := make(map[PackageID]*source.Metadata)
16045-	for _, m := range newMetadata {
16046-		if existing := s.meta.metadata[m.ID]; existing == nil {
16047-			updates[m.ID] = m
16048-			delete(s.shouldLoad, m.ID)
16049-		}
16050-	}
16051-	// Assert the invariant.
16052-	s.packages.Range(func(k, v interface{}) {
16053-		id, ph := k.(PackageID), v.(*packageHandle)
16054-		if s.meta.metadata[id] != ph.m {
16055-			// TODO(adonovan): upgrade to unconditional panic after Jan 2023.
16056-			bug.Reportf("inconsistent metadata")
16057-		}
16058-	})
16059-
16060-	event.Log(ctx, fmt.Sprintf("%s: updating metadata for %d packages", eventName, len(updates)))
16061-
16062-	// Before mutating the snapshot, ensure that we compute load diagnostics
16063-	// successfully. This could fail if the context is cancelled, and we don't
16064-	// want to leave the snapshot metadata in a partial state.
16065-	meta := s.meta.Clone(updates)
16066-	workspacePackages := computeWorkspacePackagesLocked(s, meta)
16067-	for _, update := range updates {
16068-		if err := computeLoadDiagnostics(ctx, update, meta, lockedSnapshot{s}, workspacePackages); err != nil {
16069-			return err
16070-		}
16071-	}
16072-	s.meta = meta
16073-	s.workspacePackages = workspacePackages
16074-	s.resetActivePackagesLocked()
16075-
16076-	s.dumpWorkspace("load")
16077-	s.mu.Unlock()
16078-
16079-	// Recompute the workspace package handle for any packages we invalidated.
16080-	//
16081-	// This is (putatively) an optimization since handle construction prefetches
16082-	// the content of all Go source files.
16083-	//
16084-	// However, one necessary side effect of this operation is that we are
16085-	// guaranteed to visit all package files during load. This is required for
16086-	// e.g. determining the set of directories to watch.
16087-	//
16088-	// TODO(rfindley, golang/go#57558): determine the set of directories based on
16089-	// loaded packages, and skip this precomputation.
16090-	for _, m := range updates {
16091-		s.buildPackageHandle(ctx, m.ID) // ignore error
16092-	}
16093-
16094-	if len(moduleErrs) > 0 {
16095-		return &moduleErrorMap{moduleErrs}
16096-	}
16097-
16098-	return nil
16099-}
16100-
16101-type moduleErrorMap struct {
16102-	errs map[string][]packages.Error // module path -> errors
16103-}
16104-
16105-func (m *moduleErrorMap) Error() string {
16106-	var paths []string // sort for stability
16107-	for path, errs := range m.errs {
16108-		if len(errs) > 0 { // should always be true, but be cautious
16109-			paths = append(paths, path)
16110-		}
16111-	}
16112-	sort.Strings(paths)
16113-
16114-	var buf bytes.Buffer
16115-	fmt.Fprintf(&buf, "%d modules have errors:\n", len(paths))
16116-	for _, path := range paths {
16117-		fmt.Fprintf(&buf, "\t%s:%s\n", path, m.errs[path][0].Msg)
16118-	}
16119-
16120-	return buf.String()
16121-}
16122-
16123-// workspaceLayoutError returns an error describing a misconfiguration of the
16124-// workspace, along with related diagnostic.
16125-//
16126-// The unusual argument ordering of results is intentional: if the resulting
16127-// error is nil, so must be the resulting diagnostics.
16128-//
16129-// If ctx is cancelled, it may return ctx.Err(), nil.
16130-//
16131-// TODO(rfindley): separate workspace diagnostics from critical workspace
16132-// errors.
16133-func (s *snapshot) workspaceLayoutError(ctx context.Context) (error, []*source.Diagnostic) {
16134-	// TODO(rfindley): both of the checks below should be delegated to the workspace.
16135-
16136-	if s.view.effectiveGO111MODULE() == off {
16137-		return nil, nil
16138-	}
16139-
16140-	// If the user is using a go.work file, we assume that they know what they
16141-	// are doing.
16142-	//
16143-	// TODO(golang/go#53880): improve orphaned file diagnostics when using go.work.
16144-	if s.view.gowork != "" {
16145-		return nil, nil
16146-	}
16147-
16148-	// Apply diagnostics about the workspace configuration to relevant open
16149-	// files.
16150-	openFiles := s.openFiles()
16151-
16152-	// If the snapshot does not have a valid build configuration, it may be
16153-	// that the user has opened a directory that contains multiple modules.
16154-	// Check for that an warn about it.
16155-	if !s.ValidBuildConfiguration() {
16156-		var msg string
16157-		if s.view.goversion >= 18 {
16158-			msg = `gopls was not able to find modules in your workspace.
16159-When outside of GOPATH, gopls needs to know which modules you are working on.
16160-You can fix this by opening your workspace to a folder inside a Go module, or
16161-by using a go.work file to specify multiple modules.
16162-See the documentation for more information on setting up your workspace:
16163-https://github.com/golang/tools/blob/master/gopls/doc/workspace.md.`
16164-		} else {
16165-			msg = `gopls requires a module at the root of your workspace.
16166-You can work with multiple modules by upgrading to Go 1.18 or later, and using
16167-go workspaces (go.work files).
16168-See the documentation for more information on setting up your workspace:
16169-https://github.com/golang/tools/blob/master/gopls/doc/workspace.md.`
16170-		}
16171-		return fmt.Errorf(msg), s.applyCriticalErrorToFiles(ctx, msg, openFiles)
16172-	}
16173-
16174-	// If the user has one active go.mod file, they may still be editing files
16175-	// in nested modules. Check the module of each open file and add warnings
16176-	// that the nested module must be opened as a workspace folder.
16177-	if len(s.workspaceModFiles) == 1 {
16178-		// Get the active root go.mod file to compare against.
16179-		var rootMod string
16180-		for uri := range s.workspaceModFiles {
16181-			rootMod = uri.Filename()
16182-		}
16183-		rootDir := filepath.Dir(rootMod)
16184-		nestedModules := make(map[string][]source.FileHandle)
16185-		for _, fh := range openFiles {
16186-			mod, err := findRootPattern(ctx, filepath.Dir(fh.URI().Filename()), "go.mod", s)
16187-			if err != nil {
16188-				if ctx.Err() != nil {
16189-					return ctx.Err(), nil
16190-				}
16191-				continue
16192-			}
16193-			if mod == "" {
16194-				continue
16195-			}
16196-			if mod != rootMod && source.InDir(rootDir, mod) {
16197-				modDir := filepath.Dir(mod)
16198-				nestedModules[modDir] = append(nestedModules[modDir], fh)
16199-			}
16200-		}
16201-		var multiModuleMsg string
16202-		if s.view.goversion >= 18 {
16203-			multiModuleMsg = `To work on multiple modules at once, please use a go.work file.
16204-See https://github.com/golang/tools/blob/master/gopls/doc/workspace.md for more information on using workspaces.`
16205-		} else {
16206-			multiModuleMsg = `To work on multiple modules at once, please upgrade to Go 1.18 and use a go.work file.
16207-See https://github.com/golang/tools/blob/master/gopls/doc/workspace.md for more information on using workspaces.`
16208-		}
16209-		// Add a diagnostic to each file in a nested module to mark it as
16210-		// "orphaned". Don't show a general diagnostic in the progress bar,
16211-		// because the user may still want to edit a file in a nested module.
16212-		var srcDiags []*source.Diagnostic
16213-		for modDir, uris := range nestedModules {
16214-			msg := fmt.Sprintf("This file is in %s, which is a nested module in the %s module.\n%s", modDir, rootMod, multiModuleMsg)
16215-			srcDiags = append(srcDiags, s.applyCriticalErrorToFiles(ctx, msg, uris)...)
16216-		}
16217-		if len(srcDiags) != 0 {
16218-			return fmt.Errorf("You have opened a nested module.\n%s", multiModuleMsg), srcDiags
16219-		}
16220-	}
16221-	return nil, nil
16222-}
16223-
16224-func (s *snapshot) applyCriticalErrorToFiles(ctx context.Context, msg string, files []source.FileHandle) []*source.Diagnostic {
16225-	var srcDiags []*source.Diagnostic
16226-	for _, fh := range files {
16227-		// Place the diagnostics on the package or module declarations.
16228-		var rng protocol.Range
16229-		switch s.view.FileKind(fh) {
16230-		case source.Go:
16231-			if pgf, err := s.ParseGo(ctx, fh, source.ParseHeader); err == nil {
16232-				// Check that we have a valid `package foo` range to use for positioning the error.
16233-				if pgf.File.Package.IsValid() && pgf.File.Name != nil && pgf.File.Name.End().IsValid() {
16234-					rng, _ = pgf.PosRange(pgf.File.Package, pgf.File.Name.End())
16235-				}
16236-			}
16237-		case source.Mod:
16238-			if pmf, err := s.ParseMod(ctx, fh); err == nil {
16239-				if mod := pmf.File.Module; mod != nil && mod.Syntax != nil {
16240-					rng, _ = pmf.Mapper.OffsetRange(mod.Syntax.Start.Byte, mod.Syntax.End.Byte)
16241-				}
16242-			}
16243-		}
16244-		srcDiags = append(srcDiags, &source.Diagnostic{
16245-			URI:      fh.URI(),
16246-			Range:    rng,
16247-			Severity: protocol.SeverityError,
16248-			Source:   source.ListError,
16249-			Message:  msg,
16250-		})
16251-	}
16252-	return srcDiags
16253-}
16254-
16255-// buildMetadata populates the updates map with metadata updates to
16256-// apply, based on the given pkg. It recurs through pkg.Imports to ensure that
16257-// metadata exists for all dependencies.
16258-func buildMetadata(ctx context.Context, pkg *packages.Package, cfg *packages.Config, query []string, updates map[PackageID]*source.Metadata, path []PackageID) error {
16259-	// Allow for multiple ad-hoc packages in the workspace (see #47584).
16260-	pkgPath := PackagePath(pkg.PkgPath)
16261-	id := PackageID(pkg.ID)
16262-	if source.IsCommandLineArguments(id) {
16263-		suffix := ":" + strings.Join(query, ",")
16264-		id = PackageID(pkg.ID + suffix)
16265-		pkgPath = PackagePath(pkg.PkgPath + suffix)
16266-	}
16267-
16268-	if _, ok := updates[id]; ok {
16269-		// If we've already seen this dependency, there may be an import cycle, or
16270-		// we may have reached the same package transitively via distinct paths.
16271-		// Check the path to confirm.
16272-
16273-		// TODO(rfindley): this doesn't look sufficient. Any single piece of new
16274-		// metadata could theoretically introduce import cycles in the metadata
16275-		// graph. What's the point of this limited check here (and is it even
16276-		// possible to get an import cycle in data from go/packages)? Consider
16277-		// simply returning, so that this function need not return an error.
16278-		//
16279-		// We should consider doing a more complete guard against import cycles
16280-		// elsewhere.
16281-		for _, prev := range path {
16282-			if prev == id {
16283-				return fmt.Errorf("import cycle detected: %q", id)
16284-			}
16285-		}
16286-		return nil
16287-	}
16288-
16289-	// Recreate the metadata rather than reusing it to avoid locking.
16290-	m := &source.Metadata{
16291-		ID:         id,
16292-		PkgPath:    pkgPath,
16293-		Name:       PackageName(pkg.Name),
16294-		ForTest:    PackagePath(packagesinternal.GetForTest(pkg)),
16295-		TypesSizes: pkg.TypesSizes,
16296-		LoadDir:    cfg.Dir,
16297-		Module:     pkg.Module,
16298-		Errors:     pkg.Errors,
16299-		DepsErrors: packagesinternal.GetDepsErrors(pkg),
16300-	}
16301-
16302-	updates[id] = m
16303-
16304-	for _, filename := range pkg.CompiledGoFiles {
16305-		uri := span.URIFromPath(filename)
16306-		m.CompiledGoFiles = append(m.CompiledGoFiles, uri)
16307-	}
16308-	for _, filename := range pkg.GoFiles {
16309-		uri := span.URIFromPath(filename)
16310-		m.GoFiles = append(m.GoFiles, uri)
16311-	}
16312-
16313-	depsByImpPath := make(map[ImportPath]PackageID)
16314-	depsByPkgPath := make(map[PackagePath]PackageID)
16315-	for importPath, imported := range pkg.Imports {
16316-		importPath := ImportPath(importPath)
16317-
16318-		// It is not an invariant that importPath == imported.PkgPath.
16319-		// For example, package "net" imports "golang.org/x/net/dns/dnsmessage"
16320-		// which refers to the package whose ID and PkgPath are both
16321-		// "vendor/golang.org/x/net/dns/dnsmessage". Notice the ImportMap,
16322-		// which maps ImportPaths to PackagePaths:
16323-		//
16324-		// $ go list -json net vendor/golang.org/x/net/dns/dnsmessage
16325-		// {
16326-		// 	"ImportPath": "net",
16327-		// 	"Name": "net",
16328-		// 	"Imports": [
16329-		// 		"C",
16330-		// 		"vendor/golang.org/x/net/dns/dnsmessage",
16331-		// 		"vendor/golang.org/x/net/route",
16332-		// 		...
16333-		// 	],
16334-		// 	"ImportMap": {
16335-		// 		"golang.org/x/net/dns/dnsmessage": "vendor/golang.org/x/net/dns/dnsmessage",
16336-		// 		"golang.org/x/net/route": "vendor/golang.org/x/net/route"
16337-		// 	},
16338-		//      ...
16339-		// }
16340-		// {
16341-		// 	"ImportPath": "vendor/golang.org/x/net/dns/dnsmessage",
16342-		// 	"Name": "dnsmessage",
16343-		//      ...
16344-		// }
16345-		//
16346-		// (Beware that, for historical reasons, go list uses
16347-		// the JSON field "ImportPath" for the package's
16348-		// path--effectively the linker symbol prefix.)
16349-		//
16350-		// The example above is slightly special to go list
16351-		// because it's in the std module.  Otherwise,
16352-		// vendored modules are simply modules whose directory
16353-		// is vendor/ instead of GOMODCACHE, and the
16354-		// import path equals the package path.
16355-		//
16356-		// But in GOPATH (non-module) mode, it's possible for
16357-		// package vendoring to cause a non-identity ImportMap,
16358-		// as in this example:
16359-		//
16360-		// $ cd $HOME/src
16361-		// $ find . -type f
16362-		// ./b/b.go
16363-		// ./vendor/example.com/a/a.go
16364-		// $ cat ./b/b.go
16365-		// package b
16366-		// import _ "example.com/a"
16367-		// $ cat ./vendor/example.com/a/a.go
16368-		// package a
16369-		// $ GOPATH=$HOME GO111MODULE=off go list -json ./b | grep -A2 ImportMap
16370-		//     "ImportMap": {
16371-		//         "example.com/a": "vendor/example.com/a"
16372-		//     },
16373-
16374-		// Don't remember any imports with significant errors.
16375-		//
16376-		// The len=0 condition is a heuristic check for imports of
16377-		// non-existent packages (for which go/packages will create
16378-		// an edge to a synthesized node). The heuristic is unsound
16379-		// because some valid packages have zero files, for example,
16380-		// a directory containing only the file p_test.go defines an
16381-		// empty package p.
16382-		// TODO(adonovan): clarify this. Perhaps go/packages should
16383-		// report which nodes were synthesized.
16384-		if importPath != "unsafe" && len(imported.CompiledGoFiles) == 0 {
16385-			depsByImpPath[importPath] = "" // missing
16386-			continue
16387-		}
16388-
16389-		depsByImpPath[importPath] = PackageID(imported.ID)
16390-		depsByPkgPath[PackagePath(imported.PkgPath)] = PackageID(imported.ID)
16391-		if err := buildMetadata(ctx, imported, cfg, query, updates, append(path, id)); err != nil {
16392-			event.Error(ctx, "error in dependency", err)
16393-		}
16394-	}
16395-	m.DepsByImpPath = depsByImpPath
16396-	m.DepsByPkgPath = depsByPkgPath
16397-
16398-	// m.Diagnostics is set later in the loading pass, using
16399-	// computeLoadDiagnostics.
16400-
16401-	return nil
16402-}
16403-
16404-// computeLoadDiagnostics computes and sets m.Diagnostics for the given metadata m.
16405-//
16406-// It should only be called during metadata construction in snapshot.load.
16407-func computeLoadDiagnostics(ctx context.Context, m *source.Metadata, meta *metadataGraph, fs source.FileSource, workspacePackages map[PackageID]PackagePath) error {
16408-	for _, packagesErr := range m.Errors {
16409-		// Filter out parse errors from go list. We'll get them when we
16410-		// actually parse, and buggy overlay support may generate spurious
16411-		// errors. (See TestNewModule_Issue38207.)
16412-		if strings.Contains(packagesErr.Msg, "expected '") {
16413-			continue
16414-		}
16415-		pkgDiags, err := goPackagesErrorDiagnostics(ctx, packagesErr, m, fs)
16416-		if err != nil {
16417-			// There are certain cases where the go command returns invalid
16418-			// positions, so we cannot panic or even bug.Reportf here.
16419-			event.Error(ctx, "unable to compute positions for list errors", err, tag.Package.Of(string(m.ID)))
16420-			continue
16421-		}
16422-		m.Diagnostics = append(m.Diagnostics, pkgDiags...)
16423-	}
16424-
16425-	// TODO(rfindley): this is buggy: an insignificant change to a modfile
16426-	// (or an unsaved modfile) could affect the position of deps errors,
16427-	// without invalidating the package.
16428-	depsDiags, err := depsErrors(ctx, m, meta, fs, workspacePackages)
16429-	if err != nil {
16430-		if ctx.Err() == nil {
16431-			// TODO(rfindley): consider making this a bug.Reportf. depsErrors should
16432-			// not normally fail.
16433-			event.Error(ctx, "unable to compute deps errors", err, tag.Package.Of(string(m.ID)))
16434-		}
16435-		return nil
16436-	}
16437-	m.Diagnostics = append(m.Diagnostics, depsDiags...)
16438-	return nil
16439-}
16440-
16441-// containsPackageLocked reports whether p is a workspace package for the
16442-// snapshot s.
16443-//
16444-// s.mu must be held while calling this function.
16445-func containsPackageLocked(s *snapshot, m *source.Metadata) bool {
16446-	// In legacy workspace mode, or if a package does not have an associated
16447-	// module, a package is considered inside the workspace if any of its files
16448-	// are under the workspace root (and not excluded).
16449-	//
16450-	// Otherwise if the package has a module it must be an active module (as
16451-	// defined by the module root or go.work file) and at least one file must not
16452-	// be filtered out by directoryFilters.
16453-	//
16454-	// TODO(rfindley): revisit this function. We should not need to predicate on
16455-	// gowork != "". It should suffice to consider workspace mod files (also, we
16456-	// will hopefully eliminate the concept of a workspace package soon).
16457-	if m.Module != nil && s.view.gowork != "" {
16458-		modURI := span.URIFromPath(m.Module.GoMod)
16459-		_, ok := s.workspaceModFiles[modURI]
16460-		if !ok {
16461-			return false
16462-		}
16463-
16464-		uris := map[span.URI]struct{}{}
16465-		for _, uri := range m.CompiledGoFiles {
16466-			uris[uri] = struct{}{}
16467-		}
16468-		for _, uri := range m.GoFiles {
16469-			uris[uri] = struct{}{}
16470-		}
16471-
16472-		filterFunc := s.view.filterFunc()
16473-		for uri := range uris {
16474-			// Don't use view.contains here. go.work files may include modules
16475-			// outside of the workspace folder.
16476-			if !strings.Contains(string(uri), "/vendor/") && !filterFunc(uri) {
16477-				return true
16478-			}
16479-		}
16480-		return false
16481-	}
16482-
16483-	return containsFileInWorkspaceLocked(s, m)
16484-}
16485-
16486-// containsOpenFileLocked reports whether any file referenced by m is open in
16487-// the snapshot s.
16488-//
16489-// s.mu must be held while calling this function.
16490-func containsOpenFileLocked(s *snapshot, m *source.Metadata) bool {
16491-	uris := map[span.URI]struct{}{}
16492-	for _, uri := range m.CompiledGoFiles {
16493-		uris[uri] = struct{}{}
16494-	}
16495-	for _, uri := range m.GoFiles {
16496-		uris[uri] = struct{}{}
16497-	}
16498-
16499-	for uri := range uris {
16500-		if s.isOpenLocked(uri) {
16501-			return true
16502-		}
16503-	}
16504-	return false
16505-}
16506-
16507-// containsFileInWorkspaceLocked reports whether m contains any file inside the
16508-// workspace of the snapshot s.
16509-//
16510-// s.mu must be held while calling this function.
16511-func containsFileInWorkspaceLocked(s *snapshot, m *source.Metadata) bool {
16512-	uris := map[span.URI]struct{}{}
16513-	for _, uri := range m.CompiledGoFiles {
16514-		uris[uri] = struct{}{}
16515-	}
16516-	for _, uri := range m.GoFiles {
16517-		uris[uri] = struct{}{}
16518-	}
16519-
16520-	for uri := range uris {
16521-		// In order for a package to be considered for the workspace, at least one
16522-		// file must be contained in the workspace and not vendored.
16523-
16524-		// The package's files are in this view. It may be a workspace package.
16525-		// Vendored packages are not likely to be interesting to the user.
16526-		if !strings.Contains(string(uri), "/vendor/") && s.view.contains(uri) {
16527-			return true
16528-		}
16529-	}
16530-	return false
16531-}
16532-
16533-// computeWorkspacePackagesLocked computes workspace packages in the snapshot s
16534-// for the given metadata graph.
16535-//
16536-// s.mu must be held while calling this function.
16537-func computeWorkspacePackagesLocked(s *snapshot, meta *metadataGraph) map[PackageID]PackagePath {
16538-	workspacePackages := make(map[PackageID]PackagePath)
16539-	for _, m := range meta.metadata {
16540-		if !containsPackageLocked(s, m) {
16541-			continue
16542-		}
16543-
16544-		if source.IsCommandLineArguments(m.ID) {
16545-			// If all the files contained in m have a real package, we don't need to
16546-			// keep m as a workspace package.
16547-			if allFilesHaveRealPackages(meta, m) {
16548-				continue
16549-			}
16550-
16551-			// We only care about command-line-arguments packages if they are still
16552-			// open.
16553-			if !containsOpenFileLocked(s, m) {
16554-				continue
16555-			}
16556-		}
16557-
16558-		switch {
16559-		case m.ForTest == "":
16560-			// A normal package.
16561-			workspacePackages[m.ID] = m.PkgPath
16562-		case m.ForTest == m.PkgPath, m.ForTest+"_test" == m.PkgPath:
16563-			// The test variant of some workspace package or its x_test.
16564-			// To load it, we need to load the non-test variant with -test.
16565-			//
16566-			// Notably, this excludes intermediate test variants from workspace
16567-			// packages.
16568-			workspacePackages[m.ID] = m.ForTest
16569-		}
16570-	}
16571-	return workspacePackages
16572-}
16573-
16574-// allFilesHaveRealPackages reports whether all files referenced by m are
16575-// contained in a "real" package (not command-line-arguments).
16576-//
16577-// If m is valid but all "real" packages containing any file are invalid, this
16578-// function returns false.
16579-//
16580-// If m is not a command-line-arguments package, this is trivially true.
16581-func allFilesHaveRealPackages(g *metadataGraph, m *source.Metadata) bool {
16582-	n := len(m.CompiledGoFiles)
16583-checkURIs:
16584-	for _, uri := range append(m.CompiledGoFiles[0:n:n], m.GoFiles...) {
16585-		for _, id := range g.ids[uri] {
16586-			if !source.IsCommandLineArguments(id) {
16587-				continue checkURIs
16588-			}
16589-		}
16590-		return false
16591-	}
16592-	return true
16593-}
16594-
16595-func isTestMain(pkg *packages.Package, gocache string) bool {
16596-	// Test mains must have an import path that ends with ".test".
16597-	if !strings.HasSuffix(pkg.PkgPath, ".test") {
16598-		return false
16599-	}
16600-	// Test main packages are always named "main".
16601-	if pkg.Name != "main" {
16602-		return false
16603-	}
16604-	// Test mains always have exactly one GoFile that is in the build cache.
16605-	if len(pkg.GoFiles) > 1 {
16606-		return false
16607-	}
16608-	if !source.InDir(gocache, pkg.GoFiles[0]) {
16609-		return false
16610-	}
16611-	return true
16612-}
16613diff -urN a/gopls/internal/lsp/cache/maps.go b/gopls/internal/lsp/cache/maps.go
16614--- a/gopls/internal/lsp/cache/maps.go	2000-01-01 00:00:00.000000000 -0000
16615+++ b/gopls/internal/lsp/cache/maps.go	1970-01-01 00:00:00.000000000 +0000
16616@@ -1,121 +0,0 @@
16617-// Copyright 2022 The Go Authors. All rights reserved.
16618-// Use of this source code is governed by a BSD-style
16619-// license that can be found in the LICENSE file.
16620-
16621-package cache
16622-
16623-import (
16624-	"strings"
16625-
16626-	"golang.org/x/tools/gopls/internal/lsp/source"
16627-	"golang.org/x/tools/gopls/internal/span"
16628-	"golang.org/x/tools/internal/persistent"
16629-)
16630-
16631-// TODO(euroelessar): Use generics once support for go1.17 is dropped.
16632-
16633-type filesMap struct {
16634-	impl *persistent.Map
16635-}
16636-
16637-// uriLessInterface is the < relation for "any" values containing span.URIs.
16638-func uriLessInterface(a, b interface{}) bool {
16639-	return a.(span.URI) < b.(span.URI)
16640-}
16641-
16642-func newFilesMap() filesMap {
16643-	return filesMap{
16644-		impl: persistent.NewMap(uriLessInterface),
16645-	}
16646-}
16647-
16648-func (m filesMap) Clone() filesMap {
16649-	return filesMap{
16650-		impl: m.impl.Clone(),
16651-	}
16652-}
16653-
16654-func (m filesMap) Destroy() {
16655-	m.impl.Destroy()
16656-}
16657-
16658-func (m filesMap) Get(key span.URI) (source.FileHandle, bool) {
16659-	value, ok := m.impl.Get(key)
16660-	if !ok {
16661-		return nil, false
16662-	}
16663-	return value.(source.FileHandle), true
16664-}
16665-
16666-func (m filesMap) Range(do func(key span.URI, value source.FileHandle)) {
16667-	m.impl.Range(func(key, value interface{}) {
16668-		do(key.(span.URI), value.(source.FileHandle))
16669-	})
16670-}
16671-
16672-func (m filesMap) Set(key span.URI, value source.FileHandle) {
16673-	m.impl.Set(key, value, nil)
16674-}
16675-
16676-func (m filesMap) Delete(key span.URI) {
16677-	m.impl.Delete(key)
16678-}
16679-
16680-func packageIDLessInterface(x, y interface{}) bool {
16681-	return x.(PackageID) < y.(PackageID)
16682-}
16683-
16684-type knownDirsSet struct {
16685-	impl *persistent.Map
16686-}
16687-
16688-func newKnownDirsSet() knownDirsSet {
16689-	return knownDirsSet{
16690-		impl: persistent.NewMap(func(a, b interface{}) bool {
16691-			return a.(span.URI) < b.(span.URI)
16692-		}),
16693-	}
16694-}
16695-
16696-func (s knownDirsSet) Clone() knownDirsSet {
16697-	return knownDirsSet{
16698-		impl: s.impl.Clone(),
16699-	}
16700-}
16701-
16702-func (s knownDirsSet) Destroy() {
16703-	s.impl.Destroy()
16704-}
16705-
16706-func (s knownDirsSet) Contains(key span.URI) bool {
16707-	_, ok := s.impl.Get(key)
16708-	return ok
16709-}
16710-
16711-func (s knownDirsSet) Range(do func(key span.URI)) {
16712-	s.impl.Range(func(key, value interface{}) {
16713-		do(key.(span.URI))
16714-	})
16715-}
16716-
16717-func (s knownDirsSet) SetAll(other knownDirsSet) {
16718-	s.impl.SetAll(other.impl)
16719-}
16720-
16721-func (s knownDirsSet) Insert(key span.URI) {
16722-	s.impl.Set(key, nil, nil)
16723-}
16724-
16725-func (s knownDirsSet) Remove(key span.URI) {
16726-	s.impl.Delete(key)
16727-}
16728-
16729-// analysisKeyLessInterface is the less-than relation for analysisKey
16730-// values wrapped in an interface.
16731-func analysisKeyLessInterface(a, b interface{}) bool {
16732-	x, y := a.(analysisKey), b.(analysisKey)
16733-	if cmp := strings.Compare(x.analyzerNames, y.analyzerNames); cmp != 0 {
16734-		return cmp < 0
16735-	}
16736-	return x.pkgid < y.pkgid
16737-}
16738diff -urN a/gopls/internal/lsp/cache/mod.go b/gopls/internal/lsp/cache/mod.go
16739--- a/gopls/internal/lsp/cache/mod.go	2000-01-01 00:00:00.000000000 -0000
16740+++ b/gopls/internal/lsp/cache/mod.go	1970-01-01 00:00:00.000000000 +0000
16741@@ -1,522 +0,0 @@
16742-// Copyright 2019 The Go Authors. All rights reserved.
16743-// Use of this source code is governed by a BSD-style
16744-// license that can be found in the LICENSE file.
16745-
16746-package cache
16747-
16748-import (
16749-	"context"
16750-	"errors"
16751-	"fmt"
16752-	"path/filepath"
16753-	"regexp"
16754-	"strings"
16755-
16756-	"golang.org/x/mod/modfile"
16757-	"golang.org/x/mod/module"
16758-	"golang.org/x/tools/gopls/internal/lsp/command"
16759-	"golang.org/x/tools/gopls/internal/lsp/protocol"
16760-	"golang.org/x/tools/gopls/internal/lsp/source"
16761-	"golang.org/x/tools/gopls/internal/span"
16762-	"golang.org/x/tools/internal/event"
16763-	"golang.org/x/tools/internal/event/tag"
16764-	"golang.org/x/tools/internal/gocommand"
16765-	"golang.org/x/tools/internal/memoize"
16766-)
16767-
16768-// ParseMod parses a go.mod file, using a cache. It may return partial results and an error.
16769-func (s *snapshot) ParseMod(ctx context.Context, fh source.FileHandle) (*source.ParsedModule, error) {
16770-	uri := fh.URI()
16771-
16772-	s.mu.Lock()
16773-	entry, hit := s.parseModHandles.Get(uri)
16774-	s.mu.Unlock()
16775-
16776-	type parseModKey source.FileIdentity
16777-	type parseModResult struct {
16778-		parsed *source.ParsedModule
16779-		err    error
16780-	}
16781-
16782-	// cache miss?
16783-	if !hit {
16784-		promise, release := s.store.Promise(parseModKey(fh.FileIdentity()), func(ctx context.Context, _ interface{}) interface{} {
16785-			parsed, err := parseModImpl(ctx, fh)
16786-			return parseModResult{parsed, err}
16787-		})
16788-
16789-		entry = promise
16790-		s.mu.Lock()
16791-		s.parseModHandles.Set(uri, entry, func(_, _ interface{}) { release() })
16792-		s.mu.Unlock()
16793-	}
16794-
16795-	// Await result.
16796-	v, err := s.awaitPromise(ctx, entry.(*memoize.Promise))
16797-	if err != nil {
16798-		return nil, err
16799-	}
16800-	res := v.(parseModResult)
16801-	return res.parsed, res.err
16802-}
16803-
16804-// parseModImpl parses the go.mod file whose name and contents are in fh.
16805-// It may return partial results and an error.
16806-func parseModImpl(ctx context.Context, fh source.FileHandle) (*source.ParsedModule, error) {
16807-	_, done := event.Start(ctx, "cache.ParseMod", tag.URI.Of(fh.URI()))
16808-	defer done()
16809-
16810-	contents, err := fh.Read()
16811-	if err != nil {
16812-		return nil, err
16813-	}
16814-	m := protocol.NewMapper(fh.URI(), contents)
16815-	file, parseErr := modfile.Parse(fh.URI().Filename(), contents, nil)
16816-	// Attempt to convert the error to a standardized parse error.
16817-	var parseErrors []*source.Diagnostic
16818-	if parseErr != nil {
16819-		mfErrList, ok := parseErr.(modfile.ErrorList)
16820-		if !ok {
16821-			return nil, fmt.Errorf("unexpected parse error type %v", parseErr)
16822-		}
16823-		for _, mfErr := range mfErrList {
16824-			rng, err := m.OffsetRange(mfErr.Pos.Byte, mfErr.Pos.Byte)
16825-			if err != nil {
16826-				return nil, err
16827-			}
16828-			parseErrors = append(parseErrors, &source.Diagnostic{
16829-				URI:      fh.URI(),
16830-				Range:    rng,
16831-				Severity: protocol.SeverityError,
16832-				Source:   source.ParseError,
16833-				Message:  mfErr.Err.Error(),
16834-			})
16835-		}
16836-	}
16837-	return &source.ParsedModule{
16838-		URI:         fh.URI(),
16839-		Mapper:      m,
16840-		File:        file,
16841-		ParseErrors: parseErrors,
16842-	}, parseErr
16843-}
16844-
16845-// ParseWork parses a go.work file, using a cache. It may return partial results and an error.
16846-// TODO(adonovan): move to new work.go file.
16847-func (s *snapshot) ParseWork(ctx context.Context, fh source.FileHandle) (*source.ParsedWorkFile, error) {
16848-	uri := fh.URI()
16849-
16850-	s.mu.Lock()
16851-	entry, hit := s.parseWorkHandles.Get(uri)
16852-	s.mu.Unlock()
16853-
16854-	type parseWorkKey source.FileIdentity
16855-	type parseWorkResult struct {
16856-		parsed *source.ParsedWorkFile
16857-		err    error
16858-	}
16859-
16860-	// cache miss?
16861-	if !hit {
16862-		handle, release := s.store.Promise(parseWorkKey(fh.FileIdentity()), func(ctx context.Context, _ interface{}) interface{} {
16863-			parsed, err := parseWorkImpl(ctx, fh)
16864-			return parseWorkResult{parsed, err}
16865-		})
16866-
16867-		entry = handle
16868-		s.mu.Lock()
16869-		s.parseWorkHandles.Set(uri, entry, func(_, _ interface{}) { release() })
16870-		s.mu.Unlock()
16871-	}
16872-
16873-	// Await result.
16874-	v, err := s.awaitPromise(ctx, entry.(*memoize.Promise))
16875-	if err != nil {
16876-		return nil, err
16877-	}
16878-	res := v.(parseWorkResult)
16879-	return res.parsed, res.err
16880-}
16881-
16882-// parseWorkImpl parses a go.work file. It may return partial results and an error.
16883-func parseWorkImpl(ctx context.Context, fh source.FileHandle) (*source.ParsedWorkFile, error) {
16884-	_, done := event.Start(ctx, "cache.ParseWork", tag.URI.Of(fh.URI()))
16885-	defer done()
16886-
16887-	contents, err := fh.Read()
16888-	if err != nil {
16889-		return nil, err
16890-	}
16891-	m := protocol.NewMapper(fh.URI(), contents)
16892-	file, parseErr := modfile.ParseWork(fh.URI().Filename(), contents, nil)
16893-	// Attempt to convert the error to a standardized parse error.
16894-	var parseErrors []*source.Diagnostic
16895-	if parseErr != nil {
16896-		mfErrList, ok := parseErr.(modfile.ErrorList)
16897-		if !ok {
16898-			return nil, fmt.Errorf("unexpected parse error type %v", parseErr)
16899-		}
16900-		for _, mfErr := range mfErrList {
16901-			rng, err := m.OffsetRange(mfErr.Pos.Byte, mfErr.Pos.Byte)
16902-			if err != nil {
16903-				return nil, err
16904-			}
16905-			parseErrors = append(parseErrors, &source.Diagnostic{
16906-				URI:      fh.URI(),
16907-				Range:    rng,
16908-				Severity: protocol.SeverityError,
16909-				Source:   source.ParseError,
16910-				Message:  mfErr.Err.Error(),
16911-			})
16912-		}
16913-	}
16914-	return &source.ParsedWorkFile{
16915-		URI:         fh.URI(),
16916-		Mapper:      m,
16917-		File:        file,
16918-		ParseErrors: parseErrors,
16919-	}, parseErr
16920-}
16921-
16922-// goSum reads the go.sum file for the go.mod file at modURI, if it exists. If
16923-// it doesn't exist, it returns nil.
16924-func (s *snapshot) goSum(ctx context.Context, modURI span.URI) []byte {
16925-	// Get the go.sum file, either from the snapshot or directly from the
16926-	// cache. Avoid (*snapshot).GetFile here, as we don't want to add
16927-	// nonexistent file handles to the snapshot if the file does not exist.
16928-	//
16929-	// TODO(rfindley): but that's not right. Changes to sum files should
16930-	// invalidate content, even if it's nonexistent content.
16931-	sumURI := span.URIFromPath(sumFilename(modURI))
16932-	var sumFH source.FileHandle = s.FindFile(sumURI)
16933-	if sumFH == nil {
16934-		var err error
16935-		sumFH, err = s.view.fs.GetFile(ctx, sumURI)
16936-		if err != nil {
16937-			return nil
16938-		}
16939-	}
16940-	content, err := sumFH.Read()
16941-	if err != nil {
16942-		return nil
16943-	}
16944-	return content
16945-}
16946-
16947-func sumFilename(modURI span.URI) string {
16948-	return strings.TrimSuffix(modURI.Filename(), ".mod") + ".sum"
16949-}
16950-
16951-// ModWhy returns the "go mod why" result for each module named in a
16952-// require statement in the go.mod file.
16953-// TODO(adonovan): move to new mod_why.go file.
16954-func (s *snapshot) ModWhy(ctx context.Context, fh source.FileHandle) (map[string]string, error) {
16955-	uri := fh.URI()
16956-
16957-	if s.View().FileKind(fh) != source.Mod {
16958-		return nil, fmt.Errorf("%s is not a go.mod file", uri)
16959-	}
16960-
16961-	s.mu.Lock()
16962-	entry, hit := s.modWhyHandles.Get(uri)
16963-	s.mu.Unlock()
16964-
16965-	type modWhyResult struct {
16966-		why map[string]string
16967-		err error
16968-	}
16969-
16970-	// cache miss?
16971-	if !hit {
16972-		handle := memoize.NewPromise("modWhy", func(ctx context.Context, arg interface{}) interface{} {
16973-			why, err := modWhyImpl(ctx, arg.(*snapshot), fh)
16974-			return modWhyResult{why, err}
16975-		})
16976-
16977-		entry = handle
16978-		s.mu.Lock()
16979-		s.modWhyHandles.Set(uri, entry, nil)
16980-		s.mu.Unlock()
16981-	}
16982-
16983-	// Await result.
16984-	v, err := s.awaitPromise(ctx, entry.(*memoize.Promise))
16985-	if err != nil {
16986-		return nil, err
16987-	}
16988-	res := v.(modWhyResult)
16989-	return res.why, res.err
16990-}
16991-
16992-// modWhyImpl returns the result of "go mod why -m" on the specified go.mod file.
16993-func modWhyImpl(ctx context.Context, snapshot *snapshot, fh source.FileHandle) (map[string]string, error) {
16994-	ctx, done := event.Start(ctx, "cache.ModWhy", tag.URI.Of(fh.URI()))
16995-	defer done()
16996-
16997-	pm, err := snapshot.ParseMod(ctx, fh)
16998-	if err != nil {
16999-		return nil, err
17000-	}
17001-	// No requires to explain.
17002-	if len(pm.File.Require) == 0 {
17003-		return nil, nil // empty result
17004-	}
17005-	// Run `go mod why` on all the dependencies.
17006-	inv := &gocommand.Invocation{
17007-		Verb:       "mod",
17008-		Args:       []string{"why", "-m"},
17009-		WorkingDir: filepath.Dir(fh.URI().Filename()),
17010-	}
17011-	for _, req := range pm.File.Require {
17012-		inv.Args = append(inv.Args, req.Mod.Path)
17013-	}
17014-	stdout, err := snapshot.RunGoCommandDirect(ctx, source.Normal, inv)
17015-	if err != nil {
17016-		return nil, err
17017-	}
17018-	whyList := strings.Split(stdout.String(), "\n\n")
17019-	if len(whyList) != len(pm.File.Require) {
17020-		return nil, fmt.Errorf("mismatched number of results: got %v, want %v", len(whyList), len(pm.File.Require))
17021-	}
17022-	why := make(map[string]string, len(pm.File.Require))
17023-	for i, req := range pm.File.Require {
17024-		why[req.Mod.Path] = whyList[i]
17025-	}
17026-	return why, nil
17027-}
17028-
17029-// extractGoCommandErrors tries to parse errors that come from the go command
17030-// and shape them into go.mod diagnostics.
17031-// TODO: rename this to 'load errors'
17032-func (s *snapshot) extractGoCommandErrors(ctx context.Context, goCmdError error) []*source.Diagnostic {
17033-	if goCmdError == nil {
17034-		return nil
17035-	}
17036-
17037-	type locatedErr struct {
17038-		spn span.Span
17039-		msg string
17040-	}
17041-	diagLocations := map[*source.ParsedModule]locatedErr{}
17042-	backupDiagLocations := map[*source.ParsedModule]locatedErr{}
17043-
17044-	// If moduleErrs is non-nil, go command errors are scoped to specific
17045-	// modules.
17046-	var moduleErrs *moduleErrorMap
17047-	_ = errors.As(goCmdError, &moduleErrs)
17048-
17049-	// Match the error against all the mod files in the workspace.
17050-	for _, uri := range s.ModFiles() {
17051-		fh, err := s.GetFile(ctx, uri)
17052-		if err != nil {
17053-			event.Error(ctx, "getting modfile for Go command error", err)
17054-			continue
17055-		}
17056-		pm, err := s.ParseMod(ctx, fh)
17057-		if err != nil {
17058-			// Parsing errors are reported elsewhere
17059-			return nil
17060-		}
17061-		var msgs []string // error messages to consider
17062-		if moduleErrs != nil {
17063-			if pm.File.Module != nil {
17064-				for _, mes := range moduleErrs.errs[pm.File.Module.Mod.Path] {
17065-					msgs = append(msgs, mes.Error())
17066-				}
17067-			}
17068-		} else {
17069-			msgs = append(msgs, goCmdError.Error())
17070-		}
17071-		for _, msg := range msgs {
17072-			if strings.Contains(goCmdError.Error(), "errors parsing go.mod") {
17073-				// The go command emits parse errors for completely invalid go.mod files.
17074-				// Those are reported by our own diagnostics and can be ignored here.
17075-				// As of writing, we are not aware of any other errors that include
17076-				// file/position information, so don't even try to find it.
17077-				continue
17078-			}
17079-			spn, found, err := s.matchErrorToModule(ctx, pm, msg)
17080-			if err != nil {
17081-				event.Error(ctx, "matching error to module", err)
17082-				continue
17083-			}
17084-			le := locatedErr{
17085-				spn: spn,
17086-				msg: msg,
17087-			}
17088-			if found {
17089-				diagLocations[pm] = le
17090-			} else {
17091-				backupDiagLocations[pm] = le
17092-			}
17093-		}
17094-	}
17095-
17096-	// If we didn't find any good matches, assign diagnostics to all go.mod files.
17097-	if len(diagLocations) == 0 {
17098-		diagLocations = backupDiagLocations
17099-	}
17100-
17101-	var srcErrs []*source.Diagnostic
17102-	for pm, le := range diagLocations {
17103-		diag, err := s.goCommandDiagnostic(pm, le.spn, le.msg)
17104-		if err != nil {
17105-			event.Error(ctx, "building go command diagnostic", err)
17106-			continue
17107-		}
17108-		srcErrs = append(srcErrs, diag)
17109-	}
17110-	return srcErrs
17111-}
17112-
17113-var moduleVersionInErrorRe = regexp.MustCompile(`[:\s]([+-._~0-9A-Za-z]+)@([+-._~0-9A-Za-z]+)[:\s]`)
17114-
17115-// matchErrorToModule matches a go command error message to a go.mod file.
17116-// Some examples:
17117-//
17118-//	[email protected]: reading example.com/@v/v1.2.2.mod: no such file or directory
17119-//	go: github.com/cockroachdb/apd/v2@v2.0.72: reading github.com/cockroachdb/apd/go.mod at revision v2.0.72: unknown revision v2.0.72
17120-//	go: [email protected] requires\n\[email protected]: parsing go.mod:\n\tmodule declares its path as: bob.org\n\tbut was required as: random.org
17121-//
17122-// It returns the location of a reference to the one of the modules and true
17123-// if one exists. If none is found it returns a fallback location and false.
17124-func (s *snapshot) matchErrorToModule(ctx context.Context, pm *source.ParsedModule, goCmdError string) (span.Span, bool, error) {
17125-	var reference *modfile.Line
17126-	matches := moduleVersionInErrorRe.FindAllStringSubmatch(goCmdError, -1)
17127-
17128-	for i := len(matches) - 1; i >= 0; i-- {
17129-		ver := module.Version{Path: matches[i][1], Version: matches[i][2]}
17130-		if err := module.Check(ver.Path, ver.Version); err != nil {
17131-			continue
17132-		}
17133-		reference = findModuleReference(pm.File, ver)
17134-		if reference != nil {
17135-			break
17136-		}
17137-	}
17138-
17139-	if reference == nil {
17140-		// No match for the module path was found in the go.mod file.
17141-		// Show the error on the module declaration, if one exists, or
17142-		// just the first line of the file.
17143-		if pm.File.Module == nil {
17144-			return span.New(pm.URI, span.NewPoint(1, 1, 0), span.Point{}), false, nil
17145-		}
17146-		syntax := pm.File.Module.Syntax
17147-		spn, err := pm.Mapper.OffsetSpan(syntax.Start.Byte, syntax.End.Byte)
17148-		return spn, false, err
17149-	}
17150-
17151-	spn, err := pm.Mapper.OffsetSpan(reference.Start.Byte, reference.End.Byte)
17152-	return spn, true, err
17153-}
17154-
17155-// goCommandDiagnostic creates a diagnostic for a given go command error.
17156-func (s *snapshot) goCommandDiagnostic(pm *source.ParsedModule, spn span.Span, goCmdError string) (*source.Diagnostic, error) {
17157-	rng, err := pm.Mapper.SpanRange(spn)
17158-	if err != nil {
17159-		return nil, err
17160-	}
17161-
17162-	matches := moduleVersionInErrorRe.FindAllStringSubmatch(goCmdError, -1)
17163-	var innermost *module.Version
17164-	for i := len(matches) - 1; i >= 0; i-- {
17165-		ver := module.Version{Path: matches[i][1], Version: matches[i][2]}
17166-		if err := module.Check(ver.Path, ver.Version); err != nil {
17167-			continue
17168-		}
17169-		innermost = &ver
17170-		break
17171-	}
17172-
17173-	switch {
17174-	case strings.Contains(goCmdError, "inconsistent vendoring"):
17175-		cmd, err := command.NewVendorCommand("Run go mod vendor", command.URIArg{URI: protocol.URIFromSpanURI(pm.URI)})
17176-		if err != nil {
17177-			return nil, err
17178-		}
17179-		return &source.Diagnostic{
17180-			URI:      pm.URI,
17181-			Range:    rng,
17182-			Severity: protocol.SeverityError,
17183-			Source:   source.ListError,
17184-			Message: `Inconsistent vendoring detected. Please re-run "go mod vendor".
17185-See https://github.com/golang/go/issues/39164 for more detail on this issue.`,
17186-			SuggestedFixes: []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)},
17187-		}, nil
17188-
17189-	case strings.Contains(goCmdError, "updates to go.sum needed"), strings.Contains(goCmdError, "missing go.sum entry"):
17190-		var args []protocol.DocumentURI
17191-		for _, uri := range s.ModFiles() {
17192-			args = append(args, protocol.URIFromSpanURI(uri))
17193-		}
17194-		tidyCmd, err := command.NewTidyCommand("Run go mod tidy", command.URIArgs{URIs: args})
17195-		if err != nil {
17196-			return nil, err
17197-		}
17198-		updateCmd, err := command.NewUpdateGoSumCommand("Update go.sum", command.URIArgs{URIs: args})
17199-		if err != nil {
17200-			return nil, err
17201-		}
17202-		msg := "go.sum is out of sync with go.mod. Please update it by applying the quick fix."
17203-		if innermost != nil {
17204-			msg = fmt.Sprintf("go.sum is out of sync with go.mod: entry for %v is missing. Please updating it by applying the quick fix.", innermost)
17205-		}
17206-		return &source.Diagnostic{
17207-			URI:      pm.URI,
17208-			Range:    rng,
17209-			Severity: protocol.SeverityError,
17210-			Source:   source.ListError,
17211-			Message:  msg,
17212-			SuggestedFixes: []source.SuggestedFix{
17213-				source.SuggestedFixFromCommand(tidyCmd, protocol.QuickFix),
17214-				source.SuggestedFixFromCommand(updateCmd, protocol.QuickFix),
17215-			},
17216-		}, nil
17217-	case strings.Contains(goCmdError, "disabled by GOPROXY=off") && innermost != nil:
17218-		title := fmt.Sprintf("Download %v@%v", innermost.Path, innermost.Version)
17219-		cmd, err := command.NewAddDependencyCommand(title, command.DependencyArgs{
17220-			URI:        protocol.URIFromSpanURI(pm.URI),
17221-			AddRequire: false,
17222-			GoCmdArgs:  []string{fmt.Sprintf("%v@%v", innermost.Path, innermost.Version)},
17223-		})
17224-		if err != nil {
17225-			return nil, err
17226-		}
17227-		return &source.Diagnostic{
17228-			URI:            pm.URI,
17229-			Range:          rng,
17230-			Severity:       protocol.SeverityError,
17231-			Message:        fmt.Sprintf("%v@%v has not been downloaded", innermost.Path, innermost.Version),
17232-			Source:         source.ListError,
17233-			SuggestedFixes: []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)},
17234-		}, nil
17235-	default:
17236-		return &source.Diagnostic{
17237-			URI:      pm.URI,
17238-			Range:    rng,
17239-			Severity: protocol.SeverityError,
17240-			Source:   source.ListError,
17241-			Message:  goCmdError,
17242-		}, nil
17243-	}
17244-}
17245-
17246-func findModuleReference(mf *modfile.File, ver module.Version) *modfile.Line {
17247-	for _, req := range mf.Require {
17248-		if req.Mod == ver {
17249-			return req.Syntax
17250-		}
17251-	}
17252-	for _, ex := range mf.Exclude {
17253-		if ex.Mod == ver {
17254-			return ex.Syntax
17255-		}
17256-	}
17257-	for _, rep := range mf.Replace {
17258-		if rep.New == ver || rep.Old == ver {
17259-			return rep.Syntax
17260-		}
17261-	}
17262-	return nil
17263-}
17264diff -urN a/gopls/internal/lsp/cache/mod_tidy.go b/gopls/internal/lsp/cache/mod_tidy.go
17265--- a/gopls/internal/lsp/cache/mod_tidy.go	2000-01-01 00:00:00.000000000 -0000
17266+++ b/gopls/internal/lsp/cache/mod_tidy.go	1970-01-01 00:00:00.000000000 +0000
17267@@ -1,469 +0,0 @@
17268-// Copyright 2020 The Go Authors. All rights reserved.
17269-// Use of this source code is governed by a BSD-style
17270-// license that can be found in the LICENSE file.
17271-
17272-package cache
17273-
17274-import (
17275-	"context"
17276-	"fmt"
17277-	"go/ast"
17278-	"io/ioutil"
17279-	"os"
17280-	"path/filepath"
17281-	"strconv"
17282-	"strings"
17283-
17284-	"golang.org/x/mod/modfile"
17285-	"golang.org/x/tools/gopls/internal/lsp/command"
17286-	"golang.org/x/tools/gopls/internal/lsp/protocol"
17287-	"golang.org/x/tools/gopls/internal/lsp/source"
17288-	"golang.org/x/tools/gopls/internal/span"
17289-	"golang.org/x/tools/internal/event"
17290-	"golang.org/x/tools/internal/event/tag"
17291-	"golang.org/x/tools/internal/gocommand"
17292-	"golang.org/x/tools/internal/memoize"
17293-)
17294-
17295-// ModTidy returns the go.mod file that would be obtained by running
17296-// "go mod tidy". Concurrent requests are combined into a single command.
17297-func (s *snapshot) ModTidy(ctx context.Context, pm *source.ParsedModule) (*source.TidiedModule, error) {
17298-	uri := pm.URI
17299-	if pm.File == nil {
17300-		return nil, fmt.Errorf("cannot tidy unparseable go.mod file: %v", uri)
17301-	}
17302-
17303-	s.mu.Lock()
17304-	entry, hit := s.modTidyHandles.Get(uri)
17305-	s.mu.Unlock()
17306-
17307-	type modTidyResult struct {
17308-		tidied *source.TidiedModule
17309-		err    error
17310-	}
17311-
17312-	// Cache miss?
17313-	if !hit {
17314-		// If the file handle is an overlay, it may not be written to disk.
17315-		// The go.mod file has to be on disk for `go mod tidy` to work.
17316-		// TODO(rfindley): is this still true with Go 1.16 overlay support?
17317-		fh, err := s.GetFile(ctx, pm.URI)
17318-		if err != nil {
17319-			return nil, err
17320-		}
17321-		if _, ok := fh.(*Overlay); ok {
17322-			if info, _ := os.Stat(uri.Filename()); info == nil {
17323-				return nil, source.ErrNoModOnDisk
17324-			}
17325-		}
17326-
17327-		if criticalErr := s.GetCriticalError(ctx); criticalErr != nil {
17328-			return &source.TidiedModule{
17329-				Diagnostics: criticalErr.Diagnostics,
17330-			}, nil
17331-		}
17332-		if ctx.Err() != nil { // must check ctx after GetCriticalError
17333-			return nil, ctx.Err()
17334-		}
17335-
17336-		if err := s.awaitLoaded(ctx); err != nil {
17337-			return nil, err
17338-		}
17339-
17340-		handle := memoize.NewPromise("modTidy", func(ctx context.Context, arg interface{}) interface{} {
17341-			tidied, err := modTidyImpl(ctx, arg.(*snapshot), uri.Filename(), pm)
17342-			return modTidyResult{tidied, err}
17343-		})
17344-
17345-		entry = handle
17346-		s.mu.Lock()
17347-		s.modTidyHandles.Set(uri, entry, nil)
17348-		s.mu.Unlock()
17349-	}
17350-
17351-	// Await result.
17352-	v, err := s.awaitPromise(ctx, entry.(*memoize.Promise))
17353-	if err != nil {
17354-		return nil, err
17355-	}
17356-	res := v.(modTidyResult)
17357-	return res.tidied, res.err
17358-}
17359-
17360-// modTidyImpl runs "go mod tidy" on a go.mod file.
17361-func modTidyImpl(ctx context.Context, snapshot *snapshot, filename string, pm *source.ParsedModule) (*source.TidiedModule, error) {
17362-	ctx, done := event.Start(ctx, "cache.ModTidy", tag.URI.Of(filename))
17363-	defer done()
17364-
17365-	inv := &gocommand.Invocation{
17366-		Verb:       "mod",
17367-		Args:       []string{"tidy"},
17368-		WorkingDir: filepath.Dir(filename),
17369-	}
17370-	// TODO(adonovan): ensure that unsaved overlays are passed through to 'go'.
17371-	tmpURI, inv, cleanup, err := snapshot.goCommandInvocation(ctx, source.WriteTemporaryModFile, inv)
17372-	if err != nil {
17373-		return nil, err
17374-	}
17375-	// Keep the temporary go.mod file around long enough to parse it.
17376-	defer cleanup()
17377-
17378-	if _, err := snapshot.view.gocmdRunner.Run(ctx, *inv); err != nil {
17379-		return nil, err
17380-	}
17381-
17382-	// Go directly to disk to get the temporary mod file,
17383-	// since it is always on disk.
17384-	tempContents, err := ioutil.ReadFile(tmpURI.Filename())
17385-	if err != nil {
17386-		return nil, err
17387-	}
17388-	ideal, err := modfile.Parse(tmpURI.Filename(), tempContents, nil)
17389-	if err != nil {
17390-		// We do not need to worry about the temporary file's parse errors
17391-		// since it has been "tidied".
17392-		return nil, err
17393-	}
17394-
17395-	// Compare the original and tidied go.mod files to compute errors and
17396-	// suggested fixes.
17397-	diagnostics, err := modTidyDiagnostics(ctx, snapshot, pm, ideal)
17398-	if err != nil {
17399-		return nil, err
17400-	}
17401-
17402-	return &source.TidiedModule{
17403-		Diagnostics:   diagnostics,
17404-		TidiedContent: tempContents,
17405-	}, nil
17406-}
17407-
17408-// modTidyDiagnostics computes the differences between the original and tidied
17409-// go.mod files to produce diagnostic and suggested fixes. Some diagnostics
17410-// may appear on the Go files that import packages from missing modules.
17411-func modTidyDiagnostics(ctx context.Context, snapshot *snapshot, pm *source.ParsedModule, ideal *modfile.File) (diagnostics []*source.Diagnostic, err error) {
17412-	// First, determine which modules are unused and which are missing from the
17413-	// original go.mod file.
17414-	var (
17415-		unused          = make(map[string]*modfile.Require, len(pm.File.Require))
17416-		missing         = make(map[string]*modfile.Require, len(ideal.Require))
17417-		wrongDirectness = make(map[string]*modfile.Require, len(pm.File.Require))
17418-	)
17419-	for _, req := range pm.File.Require {
17420-		unused[req.Mod.Path] = req
17421-	}
17422-	for _, req := range ideal.Require {
17423-		origReq := unused[req.Mod.Path]
17424-		if origReq == nil {
17425-			missing[req.Mod.Path] = req
17426-			continue
17427-		} else if origReq.Indirect != req.Indirect {
17428-			wrongDirectness[req.Mod.Path] = origReq
17429-		}
17430-		delete(unused, req.Mod.Path)
17431-	}
17432-	for _, req := range wrongDirectness {
17433-		// Handle dependencies that are incorrectly labeled indirect and
17434-		// vice versa.
17435-		srcDiag, err := directnessDiagnostic(pm.Mapper, req, snapshot.View().Options().ComputeEdits)
17436-		if err != nil {
17437-			// We're probably in a bad state if we can't compute a
17438-			// directnessDiagnostic, but try to keep going so as to not suppress
17439-			// other, valid diagnostics.
17440-			event.Error(ctx, "computing directness diagnostic", err)
17441-			continue
17442-		}
17443-		diagnostics = append(diagnostics, srcDiag)
17444-	}
17445-	// Next, compute any diagnostics for modules that are missing from the
17446-	// go.mod file. The fixes will be for the go.mod file, but the
17447-	// diagnostics should also appear in both the go.mod file and the import
17448-	// statements in the Go files in which the dependencies are used.
17449-	missingModuleFixes := map[*modfile.Require][]source.SuggestedFix{}
17450-	for _, req := range missing {
17451-		srcDiag, err := missingModuleDiagnostic(pm, req)
17452-		if err != nil {
17453-			return nil, err
17454-		}
17455-		missingModuleFixes[req] = srcDiag.SuggestedFixes
17456-		diagnostics = append(diagnostics, srcDiag)
17457-	}
17458-	// Add diagnostics for missing modules anywhere they are imported in the
17459-	// workspace.
17460-	// TODO(adonovan): opt: opportunities for parallelism abound.
17461-	for _, m := range snapshot.workspaceMetadata() {
17462-		// Read both lists of files of this package, in parallel.
17463-		goFiles, compiledGoFiles, err := readGoFiles(ctx, snapshot, m)
17464-		if err != nil {
17465-			return nil, err
17466-		}
17467-
17468-		missingImports := map[string]*modfile.Require{}
17469-
17470-		// If -mod=readonly is not set we may have successfully imported
17471-		// packages from missing modules. Otherwise they'll be in
17472-		// MissingDependencies. Combine both.
17473-		imps, err := parseImports(ctx, snapshot, goFiles)
17474-		if err != nil {
17475-			return nil, err
17476-		}
17477-		for imp := range imps {
17478-			if req, ok := missing[imp]; ok {
17479-				missingImports[imp] = req
17480-				break
17481-			}
17482-			// If the import is a package of the dependency, then add the
17483-			// package to the map, this will eliminate the need to do this
17484-			// prefix package search on each import for each file.
17485-			// Example:
17486-			//
17487-			// import (
17488-			//   "golang.org/x/tools/go/expect"
17489-			//   "golang.org/x/tools/go/packages"
17490-			// )
17491-			// They both are related to the same module: "golang.org/x/tools".
17492-			var match string
17493-			for _, req := range ideal.Require {
17494-				if strings.HasPrefix(imp, req.Mod.Path) && len(req.Mod.Path) > len(match) {
17495-					match = req.Mod.Path
17496-				}
17497-			}
17498-			if req, ok := missing[match]; ok {
17499-				missingImports[imp] = req
17500-			}
17501-		}
17502-		// None of this package's imports are from missing modules.
17503-		if len(missingImports) == 0 {
17504-			continue
17505-		}
17506-		for _, goFile := range compiledGoFiles {
17507-			pgf, err := snapshot.ParseGo(ctx, goFile, source.ParseHeader)
17508-			if err != nil {
17509-				continue
17510-			}
17511-			file, m := pgf.File, pgf.Mapper
17512-			if file == nil || m == nil {
17513-				continue
17514-			}
17515-			imports := make(map[string]*ast.ImportSpec)
17516-			for _, imp := range file.Imports {
17517-				if imp.Path == nil {
17518-					continue
17519-				}
17520-				if target, err := strconv.Unquote(imp.Path.Value); err == nil {
17521-					imports[target] = imp
17522-				}
17523-			}
17524-			if len(imports) == 0 {
17525-				continue
17526-			}
17527-			for importPath, req := range missingImports {
17528-				imp, ok := imports[importPath]
17529-				if !ok {
17530-					continue
17531-				}
17532-				fixes, ok := missingModuleFixes[req]
17533-				if !ok {
17534-					return nil, fmt.Errorf("no missing module fix for %q (%q)", importPath, req.Mod.Path)
17535-				}
17536-				srcErr, err := missingModuleForImport(pgf, imp, req, fixes)
17537-				if err != nil {
17538-					return nil, err
17539-				}
17540-				diagnostics = append(diagnostics, srcErr)
17541-			}
17542-		}
17543-	}
17544-	// Finally, add errors for any unused dependencies.
17545-	onlyDiagnostic := len(diagnostics) == 0 && len(unused) == 1
17546-	for _, req := range unused {
17547-		srcErr, err := unusedDiagnostic(pm.Mapper, req, onlyDiagnostic)
17548-		if err != nil {
17549-			return nil, err
17550-		}
17551-		diagnostics = append(diagnostics, srcErr)
17552-	}
17553-	return diagnostics, nil
17554-}
17555-
17556-// unusedDiagnostic returns a source.Diagnostic for an unused require.
17557-func unusedDiagnostic(m *protocol.Mapper, req *modfile.Require, onlyDiagnostic bool) (*source.Diagnostic, error) {
17558-	rng, err := m.OffsetRange(req.Syntax.Start.Byte, req.Syntax.End.Byte)
17559-	if err != nil {
17560-		return nil, err
17561-	}
17562-	title := fmt.Sprintf("Remove dependency: %s", req.Mod.Path)
17563-	cmd, err := command.NewRemoveDependencyCommand(title, command.RemoveDependencyArgs{
17564-		URI:            protocol.URIFromSpanURI(m.URI),
17565-		OnlyDiagnostic: onlyDiagnostic,
17566-		ModulePath:     req.Mod.Path,
17567-	})
17568-	if err != nil {
17569-		return nil, err
17570-	}
17571-	return &source.Diagnostic{
17572-		URI:            m.URI,
17573-		Range:          rng,
17574-		Severity:       protocol.SeverityWarning,
17575-		Source:         source.ModTidyError,
17576-		Message:        fmt.Sprintf("%s is not used in this module", req.Mod.Path),
17577-		SuggestedFixes: []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)},
17578-	}, nil
17579-}
17580-
17581-// directnessDiagnostic extracts errors when a dependency is labeled indirect when
17582-// it should be direct and vice versa.
17583-func directnessDiagnostic(m *protocol.Mapper, req *modfile.Require, computeEdits source.DiffFunction) (*source.Diagnostic, error) {
17584-	rng, err := m.OffsetRange(req.Syntax.Start.Byte, req.Syntax.End.Byte)
17585-	if err != nil {
17586-		return nil, err
17587-	}
17588-	direction := "indirect"
17589-	if req.Indirect {
17590-		direction = "direct"
17591-
17592-		// If the dependency should be direct, just highlight the // indirect.
17593-		if comments := req.Syntax.Comment(); comments != nil && len(comments.Suffix) > 0 {
17594-			end := comments.Suffix[0].Start
17595-			end.LineRune += len(comments.Suffix[0].Token)
17596-			end.Byte += len(comments.Suffix[0].Token)
17597-			rng, err = m.OffsetRange(comments.Suffix[0].Start.Byte, end.Byte)
17598-			if err != nil {
17599-				return nil, err
17600-			}
17601-		}
17602-	}
17603-	// If the dependency should be indirect, add the // indirect.
17604-	edits, err := switchDirectness(req, m, computeEdits)
17605-	if err != nil {
17606-		return nil, err
17607-	}
17608-	return &source.Diagnostic{
17609-		URI:      m.URI,
17610-		Range:    rng,
17611-		Severity: protocol.SeverityWarning,
17612-		Source:   source.ModTidyError,
17613-		Message:  fmt.Sprintf("%s should be %s", req.Mod.Path, direction),
17614-		SuggestedFixes: []source.SuggestedFix{{
17615-			Title: fmt.Sprintf("Change %s to %s", req.Mod.Path, direction),
17616-			Edits: map[span.URI][]protocol.TextEdit{
17617-				m.URI: edits,
17618-			},
17619-			ActionKind: protocol.QuickFix,
17620-		}},
17621-	}, nil
17622-}
17623-
17624-func missingModuleDiagnostic(pm *source.ParsedModule, req *modfile.Require) (*source.Diagnostic, error) {
17625-	var rng protocol.Range
17626-	// Default to the start of the file if there is no module declaration.
17627-	if pm.File != nil && pm.File.Module != nil && pm.File.Module.Syntax != nil {
17628-		start, end := pm.File.Module.Syntax.Span()
17629-		var err error
17630-		rng, err = pm.Mapper.OffsetRange(start.Byte, end.Byte)
17631-		if err != nil {
17632-			return nil, err
17633-		}
17634-	}
17635-	title := fmt.Sprintf("Add %s to your go.mod file", req.Mod.Path)
17636-	cmd, err := command.NewAddDependencyCommand(title, command.DependencyArgs{
17637-		URI:        protocol.URIFromSpanURI(pm.Mapper.URI),
17638-		AddRequire: !req.Indirect,
17639-		GoCmdArgs:  []string{req.Mod.Path + "@" + req.Mod.Version},
17640-	})
17641-	if err != nil {
17642-		return nil, err
17643-	}
17644-	return &source.Diagnostic{
17645-		URI:            pm.Mapper.URI,
17646-		Range:          rng,
17647-		Severity:       protocol.SeverityError,
17648-		Source:         source.ModTidyError,
17649-		Message:        fmt.Sprintf("%s is not in your go.mod file", req.Mod.Path),
17650-		SuggestedFixes: []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)},
17651-	}, nil
17652-}
17653-
17654-// switchDirectness gets the edits needed to change an indirect dependency to
17655-// direct and vice versa.
17656-func switchDirectness(req *modfile.Require, m *protocol.Mapper, computeEdits source.DiffFunction) ([]protocol.TextEdit, error) {
17657-	// We need a private copy of the parsed go.mod file, since we're going to
17658-	// modify it.
17659-	copied, err := modfile.Parse("", m.Content, nil)
17660-	if err != nil {
17661-		return nil, err
17662-	}
17663-	// Change the directness in the matching require statement. To avoid
17664-	// reordering the require statements, rewrite all of them.
17665-	var requires []*modfile.Require
17666-	seenVersions := make(map[string]string)
17667-	for _, r := range copied.Require {
17668-		if seen := seenVersions[r.Mod.Path]; seen != "" && seen != r.Mod.Version {
17669-			// Avoid a panic in SetRequire below, which panics on conflicting
17670-			// versions.
17671-			return nil, fmt.Errorf("%q has conflicting versions: %q and %q", r.Mod.Path, seen, r.Mod.Version)
17672-		}
17673-		seenVersions[r.Mod.Path] = r.Mod.Version
17674-		if r.Mod.Path == req.Mod.Path {
17675-			requires = append(requires, &modfile.Require{
17676-				Mod:      r.Mod,
17677-				Syntax:   r.Syntax,
17678-				Indirect: !r.Indirect,
17679-			})
17680-			continue
17681-		}
17682-		requires = append(requires, r)
17683-	}
17684-	copied.SetRequire(requires)
17685-	newContent, err := copied.Format()
17686-	if err != nil {
17687-		return nil, err
17688-	}
17689-	// Calculate the edits to be made due to the change.
17690-	edits := computeEdits(string(m.Content), string(newContent))
17691-	return source.ToProtocolEdits(m, edits)
17692-}
17693-
17694-// missingModuleForImport creates an error for a given import path that comes
17695-// from a missing module.
17696-func missingModuleForImport(pgf *source.ParsedGoFile, imp *ast.ImportSpec, req *modfile.Require, fixes []source.SuggestedFix) (*source.Diagnostic, error) {
17697-	if req.Syntax == nil {
17698-		return nil, fmt.Errorf("no syntax for %v", req)
17699-	}
17700-	rng, err := pgf.NodeRange(imp.Path)
17701-	if err != nil {
17702-		return nil, err
17703-	}
17704-	return &source.Diagnostic{
17705-		URI:            pgf.URI,
17706-		Range:          rng,
17707-		Severity:       protocol.SeverityError,
17708-		Source:         source.ModTidyError,
17709-		Message:        fmt.Sprintf("%s is not in your go.mod file", req.Mod.Path),
17710-		SuggestedFixes: fixes,
17711-	}, nil
17712-}
17713-
17714-// parseImports parses the headers of the specified files and returns
17715-// the set of strings that appear in import declarations within
17716-// GoFiles. Errors are ignored.
17717-//
17718-// (We can't simply use Metadata.Imports because it is based on
17719-// CompiledGoFiles, after cgo processing.)
17720-//
17721-// TODO(rfindley): this should key off source.ImportPath.
17722-func parseImports(ctx context.Context, s *snapshot, files []source.FileHandle) (map[string]bool, error) {
17723-	pgfs, _, err := s.parseCache.parseFiles(ctx, source.ParseHeader, files...)
17724-	if err != nil { // e.g. context cancellation
17725-		return nil, err
17726-	}
17727-
17728-	seen := make(map[string]bool)
17729-	for _, pgf := range pgfs {
17730-		for _, spec := range pgf.File.Imports {
17731-			path, _ := strconv.Unquote(spec.Path.Value)
17732-			seen[path] = true
17733-		}
17734-	}
17735-	return seen, nil
17736-}
17737diff -urN a/gopls/internal/lsp/cache/mod_vuln.go b/gopls/internal/lsp/cache/mod_vuln.go
17738--- a/gopls/internal/lsp/cache/mod_vuln.go	2000-01-01 00:00:00.000000000 -0000
17739+++ b/gopls/internal/lsp/cache/mod_vuln.go	1970-01-01 00:00:00.000000000 +0000
17740@@ -1,75 +0,0 @@
17741-// Copyright 2022 The Go Authors. All rights reserved.
17742-// Use of this source code is governed by a BSD-style
17743-// license that can be found in the LICENSE file.
17744-
17745-package cache
17746-
17747-import (
17748-	"context"
17749-	"os"
17750-
17751-	"golang.org/x/tools/gopls/internal/govulncheck"
17752-	"golang.org/x/tools/gopls/internal/lsp/source"
17753-	"golang.org/x/tools/gopls/internal/span"
17754-	"golang.org/x/tools/gopls/internal/vulncheck"
17755-	"golang.org/x/tools/internal/memoize"
17756-)
17757-
17758-// ModVuln returns import vulnerability analysis for the given go.mod URI.
17759-// Concurrent requests are combined into a single command.
17760-func (s *snapshot) ModVuln(ctx context.Context, modURI span.URI) (*govulncheck.Result, error) {
17761-	s.mu.Lock()
17762-	entry, hit := s.modVulnHandles.Get(modURI)
17763-	s.mu.Unlock()
17764-
17765-	type modVuln struct {
17766-		result *govulncheck.Result
17767-		err    error
17768-	}
17769-
17770-	// Cache miss?
17771-	if !hit {
17772-		// If the file handle is an overlay, it may not be written to disk.
17773-		// The go.mod file has to be on disk for vulncheck to work.
17774-		//
17775-		// TODO(hyangah): use overlays for vulncheck.
17776-		fh, err := s.GetFile(ctx, modURI)
17777-		if err != nil {
17778-			return nil, err
17779-		}
17780-		if _, ok := fh.(*Overlay); ok {
17781-			if info, _ := os.Stat(modURI.Filename()); info == nil {
17782-				return nil, source.ErrNoModOnDisk
17783-			}
17784-		}
17785-
17786-		handle := memoize.NewPromise("modVuln", func(ctx context.Context, arg interface{}) interface{} {
17787-			result, err := modVulnImpl(ctx, arg.(*snapshot), modURI)
17788-			return modVuln{result, err}
17789-		})
17790-
17791-		entry = handle
17792-		s.mu.Lock()
17793-		s.modVulnHandles.Set(modURI, entry, nil)
17794-		s.mu.Unlock()
17795-	}
17796-
17797-	// Await result.
17798-	v, err := s.awaitPromise(ctx, entry.(*memoize.Promise))
17799-	if err != nil {
17800-		return nil, err
17801-	}
17802-	res := v.(modVuln)
17803-	return res.result, res.err
17804-}
17805-
17806-func modVulnImpl(ctx context.Context, s *snapshot, uri span.URI) (*govulncheck.Result, error) {
17807-	if vulncheck.VulnerablePackages == nil {
17808-		return &govulncheck.Result{}, nil
17809-	}
17810-	fh, err := s.GetFile(ctx, uri)
17811-	if err != nil {
17812-		return nil, err
17813-	}
17814-	return vulncheck.VulnerablePackages(ctx, s, fh)
17815-}
17816diff -urN a/gopls/internal/lsp/cache/os_darwin.go b/gopls/internal/lsp/cache/os_darwin.go
17817--- a/gopls/internal/lsp/cache/os_darwin.go	2000-01-01 00:00:00.000000000 -0000
17818+++ b/gopls/internal/lsp/cache/os_darwin.go	1970-01-01 00:00:00.000000000 +0000
17819@@ -1,59 +0,0 @@
17820-// Copyright 2020 The Go Authors. All rights reserved.
17821-// Use of this source code is governed by a BSD-style
17822-// license that can be found in the LICENSE file.
17823-
17824-package cache
17825-
17826-import (
17827-	"bytes"
17828-	"fmt"
17829-	"os"
17830-	"path/filepath"
17831-	"strings"
17832-	"syscall"
17833-	"unsafe"
17834-)
17835-
17836-func init() {
17837-	checkPathCase = darwinCheckPathCase
17838-}
17839-
17840-func darwinCheckPathCase(path string) error {
17841-	// Darwin provides fcntl(F_GETPATH) to get a path for an arbitrary FD.
17842-	// Conveniently for our purposes, it gives the canonical case back. But
17843-	// there's no guarantee that it will follow the same route through the
17844-	// filesystem that the original path did.
17845-
17846-	path, err := filepath.Abs(path)
17847-	if err != nil {
17848-		return err
17849-	}
17850-	fd, err := syscall.Open(path, os.O_RDONLY, 0)
17851-	if err != nil {
17852-		return err
17853-	}
17854-	defer syscall.Close(fd)
17855-	buf := make([]byte, 4096) // No MAXPATHLEN in syscall, I think it's 1024, this is bigger.
17856-
17857-	// Wheeee! syscall doesn't expose a way to call Fcntl except FcntlFlock.
17858-	// As of writing, it just passes the pointer through, so we can just lie.
17859-	if err := syscall.FcntlFlock(uintptr(fd), syscall.F_GETPATH, (*syscall.Flock_t)(unsafe.Pointer(&buf[0]))); err != nil {
17860-		return err
17861-	}
17862-	buf = buf[:bytes.IndexByte(buf, 0)]
17863-
17864-	isRoot := func(p string) bool {
17865-		return p[len(p)-1] == filepath.Separator
17866-	}
17867-	// Darwin seems to like having multiple names for the same folder. Match as much of the suffix as we can.
17868-	for got, want := path, string(buf); !isRoot(got) && !isRoot(want); got, want = filepath.Dir(got), filepath.Dir(want) {
17869-		g, w := filepath.Base(got), filepath.Base(want)
17870-		if !strings.EqualFold(g, w) {
17871-			break
17872-		}
17873-		if g != w {
17874-			return fmt.Errorf("case mismatch in path %q: component %q is listed by macOS as %q", path, g, w)
17875-		}
17876-	}
17877-	return nil
17878-}
17879diff -urN a/gopls/internal/lsp/cache/os_windows.go b/gopls/internal/lsp/cache/os_windows.go
17880--- a/gopls/internal/lsp/cache/os_windows.go	2000-01-01 00:00:00.000000000 -0000
17881+++ b/gopls/internal/lsp/cache/os_windows.go	1970-01-01 00:00:00.000000000 +0000
17882@@ -1,56 +0,0 @@
17883-// Copyright 2020 The Go Authors. All rights reserved.
17884-// Use of this source code is governed by a BSD-style
17885-// license that can be found in the LICENSE file.
17886-
17887-package cache
17888-
17889-import (
17890-	"fmt"
17891-	"path/filepath"
17892-	"syscall"
17893-)
17894-
17895-func init() {
17896-	checkPathCase = windowsCheckPathCase
17897-}
17898-
17899-func windowsCheckPathCase(path string) error {
17900-	// Back in the day, Windows used to have short and long filenames, and
17901-	// it still supports those APIs. GetLongPathName gets the real case for a
17902-	// path, so we can use it here. Inspired by
17903-	// http://stackoverflow.com/q/2113822.
17904-
17905-	// Short paths can be longer than long paths, and unicode, so be generous.
17906-	buflen := 4 * len(path)
17907-	namep, err := syscall.UTF16PtrFromString(path)
17908-	if err != nil {
17909-		return err
17910-	}
17911-	short := make([]uint16, buflen)
17912-	n, err := syscall.GetShortPathName(namep, &short[0], uint32(len(short)*2)) // buflen is in bytes.
17913-	if err != nil {
17914-		return err
17915-	}
17916-	if int(n) > len(short)*2 {
17917-		return fmt.Errorf("short buffer too short: %v vs %v*2", n, len(short))
17918-	}
17919-	long := make([]uint16, buflen)
17920-	n, err = syscall.GetLongPathName(&short[0], &long[0], uint32(len(long)*2))
17921-	if err != nil {
17922-		return err
17923-	}
17924-	if int(n) > len(long)*2 {
17925-		return fmt.Errorf("long buffer too short: %v vs %v*2", n, len(long))
17926-	}
17927-	longstr := syscall.UTF16ToString(long)
17928-
17929-	isRoot := func(p string) bool {
17930-		return p[len(p)-1] == filepath.Separator
17931-	}
17932-	for got, want := path, longstr; !isRoot(got) && !isRoot(want); got, want = filepath.Dir(got), filepath.Dir(want) {
17933-		if g, w := filepath.Base(got), filepath.Base(want); g != w {
17934-			return fmt.Errorf("case mismatch in path %q: component %q is listed by Windows as %q", path, g, w)
17935-		}
17936-	}
17937-	return nil
17938-}
17939diff -urN a/gopls/internal/lsp/cache/parse_cache.go b/gopls/internal/lsp/cache/parse_cache.go
17940--- a/gopls/internal/lsp/cache/parse_cache.go	2000-01-01 00:00:00.000000000 -0000
17941+++ b/gopls/internal/lsp/cache/parse_cache.go	1970-01-01 00:00:00.000000000 +0000
17942@@ -1,298 +0,0 @@
17943-// Copyright 2023 The Go Authors. All rights reserved.
17944-// Use of this source code is governed by a BSD-style
17945-// license that can be found in the LICENSE file.
17946-
17947-package cache
17948-
17949-import (
17950-	"container/heap"
17951-	"context"
17952-	"go/token"
17953-	"runtime"
17954-	"sort"
17955-	"sync"
17956-
17957-	"golang.org/x/sync/errgroup"
17958-	"golang.org/x/tools/gopls/internal/lsp/source"
17959-	"golang.org/x/tools/internal/memoize"
17960-)
17961-
17962-// This file contains an implementation of a bounded-size parse cache, that
17963-// offsets the base token.Pos value of each cached file so that they may be
17964-// later described by a single dedicated FileSet.
17965-//
17966-// This is achieved by tracking a monotonic offset in the token.Pos space, that
17967-// is incremented before parsing allow room for the resulting parsed file.
17968-
17969-// Keep 200 recently parsed files, based on the following rationale:
17970-//   - One of the most important benefits of caching is avoiding re-parsing
17971-//     everything in a package when working on a single file. No packages in
17972-//     Kubernetes have > 200 files (only one has > 100).
17973-//   - Experience has shown that ~1000 parsed files can use noticeable space.
17974-//     200 feels like a sweet spot between limiting cache size and optimizing
17975-//     cache hits for low-latency operations.
17976-const parseCacheMaxFiles = 200
17977-
17978-// parsePadding is additional padding allocated between entries in the parse
17979-// cache to allow for increases in length (such as appending missing braces)
17980-// caused by fixAST.
17981-//
17982-// This is used to mitigate a chicken and egg problem: we must know the base
17983-// offset of the file we're about to parse, before we start parsing, and yet
17984-// src fixups may affect the actual size of the parsed content (and therefore
17985-// the offsets of subsequent files).
17986-//
17987-// When we encounter a file that no longer fits in its allocated space in the
17988-// fileset, we have no choice but to re-parse it. Leaving a generous padding
17989-// reduces the likelihood of this "slow path".
17990-//
17991-// This value is mutable for testing, so that we can exercise the slow path.
17992-var parsePadding = 1000 // mutable for testing
17993-
17994-// A parseCache holds a bounded number of recently accessed parsed Go files. As
17995-// new files are stored, older files may be evicted from the cache.
17996-//
17997-// The parseCache.parseFiles method exposes a batch API for parsing (and
17998-// caching) multiple files. This is necessary for type-checking, where files
17999-// must be parsed in a common fileset.
18000-type parseCache struct {
18001-	mu         sync.Mutex
18002-	m          map[parseKey]*parseCacheEntry
18003-	lru        queue     // min-atime priority queue of *parseCacheEntry
18004-	clock      uint64    // clock time, incremented when the cache is updated
18005-	nextOffset token.Pos // token.Pos offset for the next parsed file
18006-}
18007-
18008-// parseKey uniquely identifies a parsed Go file.
18009-type parseKey struct {
18010-	file source.FileIdentity
18011-	mode source.ParseMode
18012-}
18013-
18014-type parseCacheEntry struct {
18015-	key      parseKey
18016-	promise  *memoize.Promise // memoize.Promise[*source.ParsedGoFile]
18017-	atime    uint64           // clock time of last access
18018-	lruIndex int
18019-}
18020-
18021-// startParse prepares a parsing pass, using the following steps:
18022-//   - search for cache hits
18023-//   - create new promises for cache misses
18024-//   - store as many new promises in the cache as space will allow
18025-//
18026-// The resulting slice has an entry for every given file handle, though some
18027-// entries may be nil if there was an error reading the file (in which case the
18028-// resulting error will be non-nil).
18029-func (c *parseCache) startParse(mode source.ParseMode, fhs ...source.FileHandle) ([]*memoize.Promise, error) {
18030-	c.mu.Lock()
18031-	defer c.mu.Unlock()
18032-
18033-	// Any parsing pass increments the clock, as we'll update access times.
18034-	// (technically, if fhs is empty this isn't necessary, but that's a degenerate case).
18035-	//
18036-	// All entries parsed from a single call get the same access time.
18037-	c.clock++
18038-
18039-	// Read file data and collect cacheable files.
18040-	var (
18041-		data           = make([][]byte, len(fhs)) // file content for each readable file
18042-		promises       = make([]*memoize.Promise, len(fhs))
18043-		firstReadError error // first error from fh.Read, or nil
18044-	)
18045-	for i, fh := range fhs {
18046-		src, err := fh.Read()
18047-		if err != nil {
18048-			if firstReadError == nil {
18049-				firstReadError = err
18050-			}
18051-			continue
18052-		}
18053-		data[i] = src
18054-
18055-		key := parseKey{
18056-			file: fh.FileIdentity(),
18057-			mode: mode,
18058-		}
18059-
18060-		// Check for a cache hit.
18061-		if e, ok := c.m[key]; ok {
18062-			e.atime = c.clock
18063-			heap.Fix(&c.lru, e.lruIndex)
18064-			promises[i] = e.promise
18065-			continue
18066-		}
18067-
18068-		// ...otherwise, create a new promise to parse with a non-overlapping offset
18069-		fset := token.NewFileSet()
18070-		if c.nextOffset > 0 {
18071-			// Add a dummy file so that this parsed file does not overlap with others.
18072-			fset.AddFile("", 1, int(c.nextOffset))
18073-		}
18074-		c.nextOffset += token.Pos(len(src) + parsePadding + 1) // leave room for src fixes
18075-		fh := fh
18076-		promise := memoize.NewPromise(string(fh.URI()), func(ctx context.Context, _ interface{}) interface{} {
18077-			return parseGoSrc(ctx, fset, fh.URI(), src, mode)
18078-		})
18079-		promises[i] = promise
18080-
18081-		var e *parseCacheEntry
18082-		if len(c.lru) < parseCacheMaxFiles {
18083-			// add new entry
18084-			e = new(parseCacheEntry)
18085-			if c.m == nil {
18086-				c.m = make(map[parseKey]*parseCacheEntry)
18087-			}
18088-		} else {
18089-			// evict oldest entry
18090-			e = heap.Pop(&c.lru).(*parseCacheEntry)
18091-			delete(c.m, e.key)
18092-		}
18093-		e.key = key
18094-		e.promise = promise
18095-		e.atime = c.clock
18096-		c.m[e.key] = e
18097-		heap.Push(&c.lru, e)
18098-	}
18099-
18100-	if len(c.m) != len(c.lru) {
18101-		panic("map and LRU are inconsistent")
18102-	}
18103-
18104-	return promises, firstReadError
18105-}
18106-
18107-// parseFiles returns a ParsedGoFile for the given file handles in the
18108-// requested parse mode.
18109-//
18110-// If parseFiles returns an error, it still returns a slice,
18111-// but with a nil entry for each file that could not be parsed.
18112-//
18113-// The second result is a FileSet describing all resulting parsed files.
18114-//
18115-// For parsed files that already exists in the cache, access time will be
18116-// updated. For others, parseFiles will parse and store as many results in the
18117-// cache as space allows.
18118-func (c *parseCache) parseFiles(ctx context.Context, mode source.ParseMode, fhs ...source.FileHandle) ([]*source.ParsedGoFile, *token.FileSet, error) {
18119-	promises, firstReadError := c.startParse(mode, fhs...)
18120-
18121-	// Await all parsing.
18122-	var g errgroup.Group
18123-	g.SetLimit(runtime.GOMAXPROCS(-1)) // parsing is CPU-bound.
18124-	pgfs := make([]*source.ParsedGoFile, len(fhs))
18125-	for i, promise := range promises {
18126-		if promise == nil {
18127-			continue
18128-		}
18129-		i := i
18130-		promise := promise
18131-		g.Go(func() error {
18132-			result, err := promise.Get(ctx, nil)
18133-			if err != nil {
18134-				return err
18135-			}
18136-			pgfs[i] = result.(*source.ParsedGoFile)
18137-			return nil
18138-		})
18139-	}
18140-	if err := g.Wait(); err != nil {
18141-		return nil, nil, err
18142-	}
18143-
18144-	// Construct a token.FileSet mapping all parsed files, and update their
18145-	// Tok to the corresponding file in the new fileset.
18146-	//
18147-	// In the unlikely event that a parsed file no longer fits in its allocated
18148-	// space in the FileSet range, it will need to be re-parsed.
18149-
18150-	var tokenFiles []*token.File
18151-	fileIndex := make(map[*token.File]int) // to look up original indexes after sorting
18152-	for i, pgf := range pgfs {
18153-		if pgf == nil {
18154-			continue
18155-		}
18156-		fileIndex[pgf.Tok] = i
18157-		tokenFiles = append(tokenFiles, pgf.Tok)
18158-	}
18159-
18160-	sort.Slice(tokenFiles, func(i, j int) bool {
18161-		return tokenFiles[i].Base() < tokenFiles[j].Base()
18162-	})
18163-
18164-	var needReparse []int // files requiring reparsing
18165-	out := tokenFiles[:0]
18166-	for i, f := range tokenFiles {
18167-		if i < len(tokenFiles)-1 && f.Base()+f.Size() >= tokenFiles[i+1].Base() {
18168-			if f != tokenFiles[i+1] { // no need to re-parse duplicates
18169-				needReparse = append(needReparse, fileIndex[f])
18170-			}
18171-		} else {
18172-			out = append(out, f)
18173-		}
18174-	}
18175-	fset := source.FileSetFor(out...)
18176-
18177-	// Re-parse any remaining files using the stitched fileSet.
18178-	for _, i := range needReparse {
18179-		// Start from scratch, rather than using ParsedGoFile.Src, so that source
18180-		// fixing operates exactly the same (note that fixing stops after a limited
18181-		// number of tries).
18182-		fh := fhs[i]
18183-		src, err := fh.Read()
18184-		if err != nil {
18185-			if firstReadError == nil {
18186-				firstReadError = err
18187-			}
18188-			continue
18189-		}
18190-		pgfs[i] = parseGoSrc(ctx, fset, fh.URI(), src, mode)
18191-	}
18192-
18193-	// Ensure each PGF refers to a token.File from the new FileSet.
18194-	for i, pgf := range pgfs {
18195-		if pgf == nil {
18196-			continue
18197-		}
18198-		newTok := fset.File(token.Pos(pgf.Tok.Base()))
18199-		if newTok == nil {
18200-			panic("internal error: missing tok for " + pgf.URI)
18201-		}
18202-		if newTok.Base() != pgf.Tok.Base() || newTok.Size() != pgf.Tok.Size() {
18203-			panic("internal error: mismatching token.File in synthetic FileSet")
18204-		}
18205-		pgf2 := *pgf
18206-		pgf2.Tok = newTok
18207-		pgfs[i] = &pgf2
18208-	}
18209-
18210-	return pgfs, fset, firstReadError
18211-}
18212-
18213-// -- priority queue boilerplate --
18214-
18215-// queue is a min-atime prority queue of cache entries.
18216-type queue []*parseCacheEntry
18217-
18218-func (q queue) Len() int { return len(q) }
18219-
18220-func (q queue) Less(i, j int) bool { return q[i].atime < q[j].atime }
18221-
18222-func (q queue) Swap(i, j int) {
18223-	q[i], q[j] = q[j], q[i]
18224-	q[i].lruIndex = i
18225-	q[j].lruIndex = j
18226-}
18227-
18228-func (q *queue) Push(x interface{}) {
18229-	e := x.(*parseCacheEntry)
18230-	e.lruIndex = len(*q)
18231-	*q = append(*q, e)
18232-}
18233-
18234-func (q *queue) Pop() interface{} {
18235-	last := len(*q) - 1
18236-	e := (*q)[last]
18237-	(*q)[last] = nil // aid GC
18238-	*q = (*q)[:last]
18239-	return e
18240-}
18241diff -urN a/gopls/internal/lsp/cache/parse_cache_test.go b/gopls/internal/lsp/cache/parse_cache_test.go
18242--- a/gopls/internal/lsp/cache/parse_cache_test.go	2000-01-01 00:00:00.000000000 -0000
18243+++ b/gopls/internal/lsp/cache/parse_cache_test.go	1970-01-01 00:00:00.000000000 +0000
18244@@ -1,142 +0,0 @@
18245-// Copyright 2023 The Go Authors. All rights reserved.
18246-// Use of this source code is governed by a BSD-style
18247-// license that can be found in the LICENSE file.
18248-
18249-package cache
18250-
18251-import (
18252-	"context"
18253-	"fmt"
18254-	"go/token"
18255-	"testing"
18256-
18257-	"golang.org/x/tools/gopls/internal/lsp/source"
18258-	"golang.org/x/tools/gopls/internal/span"
18259-)
18260-
18261-func TestParseCache(t *testing.T) {
18262-	ctx := context.Background()
18263-	uri := span.URI("file:///myfile")
18264-	fh := makeFakeFileHandle(uri, []byte("package p\n\nconst _ = \"foo\""))
18265-
18266-	var cache parseCache
18267-	pgfs1, _, err := cache.parseFiles(ctx, source.ParseFull, fh)
18268-	if err != nil {
18269-		t.Fatal(err)
18270-	}
18271-	pgf1 := pgfs1[0]
18272-	pgfs2, _, err := cache.parseFiles(ctx, source.ParseFull, fh)
18273-	pgf2 := pgfs2[0]
18274-	if err != nil {
18275-		t.Fatal(err)
18276-	}
18277-	if pgf1.File != pgf2.File {
18278-		t.Errorf("parseFiles(%q): unexpected cache miss on repeated call", uri)
18279-	}
18280-
18281-	// Fill up the cache with other files, but don't evict the file above.
18282-	files := []source.FileHandle{fh}
18283-	files = append(files, dummyFileHandles(parseCacheMaxFiles-1)...)
18284-	pgfs3, fset, err := cache.parseFiles(ctx, source.ParseFull, files...)
18285-	pgf3 := pgfs3[0]
18286-	if pgf3.File != pgf1.File {
18287-		t.Errorf("parseFiles(%q, ...): unexpected cache miss", uri)
18288-	}
18289-	if pgf3.Tok == pgf1.Tok {
18290-		t.Errorf("parseFiles(%q, ...): unexpectedly matching token file", uri)
18291-	}
18292-	if pgf3.Tok.Base() != pgf1.Tok.Base() || pgf3.Tok.Size() != pgf1.Tok.Size() {
18293-		t.Errorf("parseFiles(%q, ...): result.Tok has base: %d, size: %d, want (%d, %d)", uri, pgf3.Tok.Base(), pgf3.Tok.Size(), pgf1.Tok.Base(), pgf1.Tok.Size())
18294-	}
18295-	if tok := fset.File(token.Pos(pgf3.Tok.Base())); tok != pgf3.Tok {
18296-		t.Errorf("parseFiles(%q, ...): result.Tok not contained in FileSet", uri)
18297-	}
18298-
18299-	// Now overwrite the cache, after which we should get new results.
18300-	files = dummyFileHandles(parseCacheMaxFiles)
18301-	_, _, err = cache.parseFiles(ctx, source.ParseFull, files...)
18302-	if err != nil {
18303-		t.Fatal(err)
18304-	}
18305-	pgfs4, _, err := cache.parseFiles(ctx, source.ParseFull, fh)
18306-	if err != nil {
18307-		t.Fatal(err)
18308-	}
18309-	if pgfs4[0].File == pgf1.File {
18310-		t.Errorf("parseFiles(%q): unexpected cache hit after overwriting cache", uri)
18311-	}
18312-}
18313-
18314-func TestParseCache_Reparsing(t *testing.T) {
18315-	defer func(padding int) {
18316-		parsePadding = padding
18317-	}(parsePadding)
18318-	parsePadding = 0
18319-
18320-	files := dummyFileHandles(parseCacheMaxFiles)
18321-	danglingSelector := []byte("package p\nfunc _() {\n\tx.\n}")
18322-	files = append(files, makeFakeFileHandle("file:///bad1", danglingSelector))
18323-	files = append(files, makeFakeFileHandle("file:///bad2", danglingSelector))
18324-
18325-	// Parsing should succeed even though we overflow the padding.
18326-	var cache parseCache
18327-	_, _, err := cache.parseFiles(context.Background(), source.ParseFull, files...)
18328-	if err != nil {
18329-		t.Fatal(err)
18330-	}
18331-}
18332-
18333-func TestParseCache_Duplicates(t *testing.T) {
18334-	ctx := context.Background()
18335-	uri := span.URI("file:///myfile")
18336-	fh := makeFakeFileHandle(uri, []byte("package p\n\nconst _ = \"foo\""))
18337-
18338-	var cache parseCache
18339-	pgfs, _, err := cache.parseFiles(ctx, source.ParseFull, fh, fh)
18340-	if err != nil {
18341-		t.Fatal(err)
18342-	}
18343-	if pgfs[0].File != pgfs[1].File {
18344-		t.Errorf("parseFiles(fh, fh): = [%p, %p], want duplicate files", pgfs[0].File, pgfs[1].File)
18345-	}
18346-}
18347-
18348-func dummyFileHandles(n int) []source.FileHandle {
18349-	var fhs []source.FileHandle
18350-	for i := 0; i < n; i++ {
18351-		uri := span.URI(fmt.Sprintf("file:///_%d", i))
18352-		src := []byte(fmt.Sprintf("package p\nvar _ = %d", i))
18353-		fhs = append(fhs, makeFakeFileHandle(uri, src))
18354-	}
18355-	return fhs
18356-}
18357-
18358-func makeFakeFileHandle(uri span.URI, src []byte) fakeFileHandle {
18359-	return fakeFileHandle{
18360-		uri:  uri,
18361-		data: src,
18362-		hash: source.HashOf(src),
18363-	}
18364-}
18365-
18366-type fakeFileHandle struct {
18367-	source.FileHandle
18368-	uri  span.URI
18369-	data []byte
18370-	hash source.Hash
18371-}
18372-
18373-func (h fakeFileHandle) URI() span.URI {
18374-	return h.uri
18375-}
18376-
18377-func (h fakeFileHandle) Read() ([]byte, error) {
18378-	return h.data, nil
18379-}
18380-
18381-func (h fakeFileHandle) FileIdentity() source.FileIdentity {
18382-	return source.FileIdentity{
18383-		URI:  h.uri,
18384-		Hash: h.hash,
18385-	}
18386-}
18387diff -urN a/gopls/internal/lsp/cache/parse.go b/gopls/internal/lsp/cache/parse.go
18388--- a/gopls/internal/lsp/cache/parse.go	2000-01-01 00:00:00.000000000 -0000
18389+++ b/gopls/internal/lsp/cache/parse.go	1970-01-01 00:00:00.000000000 +0000
18390@@ -1,900 +0,0 @@
18391-// Copyright 2019 The Go Authors. All rights reserved.
18392-// Use of this source code is governed by a BSD-style
18393-// license that can be found in the LICENSE file.
18394-
18395-package cache
18396-
18397-import (
18398-	"bytes"
18399-	"context"
18400-	"fmt"
18401-	"go/ast"
18402-	"go/parser"
18403-	"go/scanner"
18404-	"go/token"
18405-	"path/filepath"
18406-	"reflect"
18407-
18408-	"golang.org/x/tools/gopls/internal/lsp/protocol"
18409-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
18410-	"golang.org/x/tools/gopls/internal/lsp/source"
18411-	"golang.org/x/tools/gopls/internal/span"
18412-	"golang.org/x/tools/internal/diff"
18413-	"golang.org/x/tools/internal/event"
18414-	"golang.org/x/tools/internal/event/tag"
18415-)
18416-
18417-// ParseGo parses the file whose contents are provided by fh, using a cache.
18418-// The resulting tree may have beeen fixed up.
18419-func (s *snapshot) ParseGo(ctx context.Context, fh source.FileHandle, mode source.ParseMode) (*source.ParsedGoFile, error) {
18420-	pgfs, _, err := s.parseCache.parseFiles(ctx, mode, fh)
18421-	if err != nil {
18422-		return nil, err
18423-	}
18424-	return pgfs[0], nil
18425-}
18426-
18427-// parseGoImpl parses the Go source file whose content is provided by fh.
18428-func parseGoImpl(ctx context.Context, fset *token.FileSet, fh source.FileHandle, mode source.ParseMode) (*source.ParsedGoFile, error) {
18429-	ctx, done := event.Start(ctx, "cache.parseGo", tag.File.Of(fh.URI().Filename()))
18430-	defer done()
18431-
18432-	ext := filepath.Ext(fh.URI().Filename())
18433-	if ext != ".go" && ext != "" { // files generated by cgo have no extension
18434-		return nil, fmt.Errorf("cannot parse non-Go file %s", fh.URI())
18435-	}
18436-	src, err := fh.Read()
18437-	if err != nil {
18438-		return nil, err
18439-	}
18440-	return parseGoSrc(ctx, fset, fh.URI(), src, mode), nil
18441-}
18442-
18443-// parseGoSrc parses a buffer of Go source, repairing the tree if necessary.
18444-func parseGoSrc(ctx context.Context, fset *token.FileSet, uri span.URI, src []byte, mode source.ParseMode) (res *source.ParsedGoFile) {
18445-	parserMode := parser.AllErrors | parser.ParseComments
18446-	if mode == source.ParseHeader {
18447-		parserMode = parser.ImportsOnly | parser.ParseComments
18448-	}
18449-
18450-	file, err := parser.ParseFile(fset, uri.Filename(), src, parserMode)
18451-	var parseErr scanner.ErrorList
18452-	if err != nil {
18453-		// We passed a byte slice, so the only possible error is a parse error.
18454-		parseErr = err.(scanner.ErrorList)
18455-	}
18456-
18457-	tok := fset.File(file.Pos())
18458-	if tok == nil {
18459-		// file.Pos is the location of the package declaration (issue #53202). If there was
18460-		// none, we can't find the token.File that ParseFile created, and we
18461-		// have no choice but to recreate it.
18462-		tok = fset.AddFile(uri.Filename(), -1, len(src))
18463-		tok.SetLinesForContent(src)
18464-	}
18465-
18466-	fixed := false
18467-	// If there were parse errors, attempt to fix them up.
18468-	if parseErr != nil {
18469-		// Fix any badly parsed parts of the AST.
18470-		fixed = fixAST(file, tok, src)
18471-
18472-		for i := 0; i < 10; i++ {
18473-			// Fix certain syntax errors that render the file unparseable.
18474-			newSrc := fixSrc(file, tok, src)
18475-			if newSrc == nil {
18476-				break
18477-			}
18478-
18479-			// If we thought there was something to fix 10 times in a row,
18480-			// it is likely we got stuck in a loop somehow. Log out a diff
18481-			// of the last changes we made to aid in debugging.
18482-			if i == 9 {
18483-				unified := diff.Unified("before", "after", string(src), string(newSrc))
18484-				event.Log(ctx, fmt.Sprintf("fixSrc loop - last diff:\n%v", unified), tag.File.Of(tok.Name()))
18485-			}
18486-
18487-			newFile, _ := parser.ParseFile(fset, uri.Filename(), newSrc, parserMode)
18488-			if newFile != nil {
18489-				// Maintain the original parseError so we don't try formatting the doctored file.
18490-				file = newFile
18491-				src = newSrc
18492-				tok = fset.File(file.Pos())
18493-
18494-				fixed = fixAST(file, tok, src)
18495-			}
18496-		}
18497-	}
18498-
18499-	return &source.ParsedGoFile{
18500-		URI:      uri,
18501-		Mode:     mode,
18502-		Src:      src,
18503-		Fixed:    fixed,
18504-		File:     file,
18505-		Tok:      tok,
18506-		Mapper:   protocol.NewMapper(uri, src),
18507-		ParseErr: parseErr,
18508-	}
18509-}
18510-
18511-// fixAST inspects the AST and potentially modifies any *ast.BadStmts so that it can be
18512-// type-checked more effectively.
18513-//
18514-// If fixAST returns true, the resulting AST is considered "fixed", meaning
18515-// positions have been mangled, and type checker errors may not make sense.
18516-func fixAST(n ast.Node, tok *token.File, src []byte) (fixed bool) {
18517-	var err error
18518-	walkASTWithParent(n, func(n, parent ast.Node) bool {
18519-		switch n := n.(type) {
18520-		case *ast.BadStmt:
18521-			if fixed = fixDeferOrGoStmt(n, parent, tok, src); fixed {
18522-				// Recursively fix in our fixed node.
18523-				_ = fixAST(parent, tok, src)
18524-			} else {
18525-				err = fmt.Errorf("unable to parse defer or go from *ast.BadStmt: %v", err)
18526-			}
18527-			return false
18528-		case *ast.BadExpr:
18529-			if fixed = fixArrayType(n, parent, tok, src); fixed {
18530-				// Recursively fix in our fixed node.
18531-				_ = fixAST(parent, tok, src)
18532-				return false
18533-			}
18534-
18535-			// Fix cases where parser interprets if/for/switch "init"
18536-			// statement as "cond" expression, e.g.:
18537-			//
18538-			//   // "i := foo" is init statement, not condition.
18539-			//   for i := foo
18540-			//
18541-			fixInitStmt(n, parent, tok, src)
18542-
18543-			return false
18544-		case *ast.SelectorExpr:
18545-			// Fix cases where a keyword prefix results in a phantom "_" selector, e.g.:
18546-			//
18547-			//   foo.var<> // want to complete to "foo.variance"
18548-			//
18549-			fixPhantomSelector(n, tok, src)
18550-			return true
18551-
18552-		case *ast.BlockStmt:
18553-			switch parent.(type) {
18554-			case *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt:
18555-				// Adjust closing curly brace of empty switch/select
18556-				// statements so we can complete inside them.
18557-				fixEmptySwitch(n, tok, src)
18558-			}
18559-
18560-			return true
18561-		default:
18562-			return true
18563-		}
18564-	})
18565-	return fixed
18566-}
18567-
18568-// walkASTWithParent walks the AST rooted at n. The semantics are
18569-// similar to ast.Inspect except it does not call f(nil).
18570-func walkASTWithParent(n ast.Node, f func(n ast.Node, parent ast.Node) bool) {
18571-	var ancestors []ast.Node
18572-	ast.Inspect(n, func(n ast.Node) (recurse bool) {
18573-		defer func() {
18574-			if recurse {
18575-				ancestors = append(ancestors, n)
18576-			}
18577-		}()
18578-
18579-		if n == nil {
18580-			ancestors = ancestors[:len(ancestors)-1]
18581-			return false
18582-		}
18583-
18584-		var parent ast.Node
18585-		if len(ancestors) > 0 {
18586-			parent = ancestors[len(ancestors)-1]
18587-		}
18588-
18589-		return f(n, parent)
18590-	})
18591-}
18592-
18593-// fixSrc attempts to modify the file's source code to fix certain
18594-// syntax errors that leave the rest of the file unparsed.
18595-func fixSrc(f *ast.File, tf *token.File, src []byte) (newSrc []byte) {
18596-	walkASTWithParent(f, func(n, parent ast.Node) bool {
18597-		if newSrc != nil {
18598-			return false
18599-		}
18600-
18601-		switch n := n.(type) {
18602-		case *ast.BlockStmt:
18603-			newSrc = fixMissingCurlies(f, n, parent, tf, src)
18604-		case *ast.SelectorExpr:
18605-			newSrc = fixDanglingSelector(n, tf, src)
18606-		}
18607-
18608-		return newSrc == nil
18609-	})
18610-
18611-	return newSrc
18612-}
18613-
18614-// fixMissingCurlies adds in curly braces for block statements that
18615-// are missing curly braces. For example:
18616-//
18617-//	if foo
18618-//
18619-// becomes
18620-//
18621-//	if foo {}
18622-func fixMissingCurlies(f *ast.File, b *ast.BlockStmt, parent ast.Node, tok *token.File, src []byte) []byte {
18623-	// If the "{" is already in the source code, there isn't anything to
18624-	// fix since we aren't missing curlies.
18625-	if b.Lbrace.IsValid() {
18626-		braceOffset, err := safetoken.Offset(tok, b.Lbrace)
18627-		if err != nil {
18628-			return nil
18629-		}
18630-		if braceOffset < len(src) && src[braceOffset] == '{' {
18631-			return nil
18632-		}
18633-	}
18634-
18635-	parentLine := tok.Line(parent.Pos())
18636-
18637-	if parentLine >= tok.LineCount() {
18638-		// If we are the last line in the file, no need to fix anything.
18639-		return nil
18640-	}
18641-
18642-	// Insert curlies at the end of parent's starting line. The parent
18643-	// is the statement that contains the block, e.g. *ast.IfStmt. The
18644-	// block's Pos()/End() can't be relied upon because they are based
18645-	// on the (missing) curly braces. We assume the statement is a
18646-	// single line for now and try sticking the curly braces at the end.
18647-	insertPos := tok.LineStart(parentLine+1) - 1
18648-
18649-	// Scootch position backwards until it's not in a comment. For example:
18650-	//
18651-	// if foo<> // some amazing comment |
18652-	// someOtherCode()
18653-	//
18654-	// insertPos will be located at "|", so we back it out of the comment.
18655-	didSomething := true
18656-	for didSomething {
18657-		didSomething = false
18658-		for _, c := range f.Comments {
18659-			if c.Pos() < insertPos && insertPos <= c.End() {
18660-				insertPos = c.Pos()
18661-				didSomething = true
18662-			}
18663-		}
18664-	}
18665-
18666-	// Bail out if line doesn't end in an ident or ".". This is to avoid
18667-	// cases like below where we end up making things worse by adding
18668-	// curlies:
18669-	//
18670-	//   if foo &&
18671-	//     bar<>
18672-	switch precedingToken(insertPos, tok, src) {
18673-	case token.IDENT, token.PERIOD:
18674-		// ok
18675-	default:
18676-		return nil
18677-	}
18678-
18679-	var buf bytes.Buffer
18680-	buf.Grow(len(src) + 3)
18681-	offset, err := safetoken.Offset(tok, insertPos)
18682-	if err != nil {
18683-		return nil
18684-	}
18685-	buf.Write(src[:offset])
18686-
18687-	// Detect if we need to insert a semicolon to fix "for" loop situations like:
18688-	//
18689-	//   for i := foo(); foo<>
18690-	//
18691-	// Just adding curlies is not sufficient to make things parse well.
18692-	if fs, ok := parent.(*ast.ForStmt); ok {
18693-		if _, ok := fs.Cond.(*ast.BadExpr); !ok {
18694-			if xs, ok := fs.Post.(*ast.ExprStmt); ok {
18695-				if _, ok := xs.X.(*ast.BadExpr); ok {
18696-					buf.WriteByte(';')
18697-				}
18698-			}
18699-		}
18700-	}
18701-
18702-	// Insert "{}" at insertPos.
18703-	buf.WriteByte('{')
18704-	buf.WriteByte('}')
18705-	buf.Write(src[offset:])
18706-	return buf.Bytes()
18707-}
18708-
18709-// fixEmptySwitch moves empty switch/select statements' closing curly
18710-// brace down one line. This allows us to properly detect incomplete
18711-// "case" and "default" keywords as inside the switch statement. For
18712-// example:
18713-//
18714-//	switch {
18715-//	def<>
18716-//	}
18717-//
18718-// gets parsed like:
18719-//
18720-//	switch {
18721-//	}
18722-//
18723-// Later we manually pull out the "def" token, but we need to detect
18724-// that our "<>" position is inside the switch block. To do that we
18725-// move the curly brace so it looks like:
18726-//
18727-//	switch {
18728-//
18729-//	}
18730-func fixEmptySwitch(body *ast.BlockStmt, tok *token.File, src []byte) {
18731-	// We only care about empty switch statements.
18732-	if len(body.List) > 0 || !body.Rbrace.IsValid() {
18733-		return
18734-	}
18735-
18736-	// If the right brace is actually in the source code at the
18737-	// specified position, don't mess with it.
18738-	braceOffset, err := safetoken.Offset(tok, body.Rbrace)
18739-	if err != nil {
18740-		return
18741-	}
18742-	if braceOffset < len(src) && src[braceOffset] == '}' {
18743-		return
18744-	}
18745-
18746-	braceLine := tok.Line(body.Rbrace)
18747-	if braceLine >= tok.LineCount() {
18748-		// If we are the last line in the file, no need to fix anything.
18749-		return
18750-	}
18751-
18752-	// Move the right brace down one line.
18753-	body.Rbrace = tok.LineStart(braceLine + 1)
18754-}
18755-
18756-// fixDanglingSelector inserts real "_" selector expressions in place
18757-// of phantom "_" selectors. For example:
18758-//
18759-//	func _() {
18760-//		x.<>
18761-//	}
18762-//
18763-// var x struct { i int }
18764-//
18765-// To fix completion at "<>", we insert a real "_" after the "." so the
18766-// following declaration of "x" can be parsed and type checked
18767-// normally.
18768-func fixDanglingSelector(s *ast.SelectorExpr, tf *token.File, src []byte) []byte {
18769-	if !isPhantomUnderscore(s.Sel, tf, src) {
18770-		return nil
18771-	}
18772-
18773-	if !s.X.End().IsValid() {
18774-		return nil
18775-	}
18776-
18777-	insertOffset, err := safetoken.Offset(tf, s.X.End())
18778-	if err != nil {
18779-		return nil
18780-	}
18781-	// Insert directly after the selector's ".".
18782-	insertOffset++
18783-	if src[insertOffset-1] != '.' {
18784-		return nil
18785-	}
18786-
18787-	var buf bytes.Buffer
18788-	buf.Grow(len(src) + 1)
18789-	buf.Write(src[:insertOffset])
18790-	buf.WriteByte('_')
18791-	buf.Write(src[insertOffset:])
18792-	return buf.Bytes()
18793-}
18794-
18795-// fixPhantomSelector tries to fix selector expressions with phantom
18796-// "_" selectors. In particular, we check if the selector is a
18797-// keyword, and if so we swap in an *ast.Ident with the keyword text. For example:
18798-//
18799-// foo.var
18800-//
18801-// yields a "_" selector instead of "var" since "var" is a keyword.
18802-//
18803-// TODO(rfindley): should this constitute an ast 'fix'?
18804-func fixPhantomSelector(sel *ast.SelectorExpr, tf *token.File, src []byte) {
18805-	if !isPhantomUnderscore(sel.Sel, tf, src) {
18806-		return
18807-	}
18808-
18809-	// Only consider selectors directly abutting the selector ".". This
18810-	// avoids false positives in cases like:
18811-	//
18812-	//   foo. // don't think "var" is our selector
18813-	//   var bar = 123
18814-	//
18815-	if sel.Sel.Pos() != sel.X.End()+1 {
18816-		return
18817-	}
18818-
18819-	maybeKeyword := readKeyword(sel.Sel.Pos(), tf, src)
18820-	if maybeKeyword == "" {
18821-		return
18822-	}
18823-
18824-	replaceNode(sel, sel.Sel, &ast.Ident{
18825-		Name:    maybeKeyword,
18826-		NamePos: sel.Sel.Pos(),
18827-	})
18828-}
18829-
18830-// isPhantomUnderscore reports whether the given ident is a phantom
18831-// underscore. The parser sometimes inserts phantom underscores when
18832-// it encounters otherwise unparseable situations.
18833-func isPhantomUnderscore(id *ast.Ident, tok *token.File, src []byte) bool {
18834-	if id == nil || id.Name != "_" {
18835-		return false
18836-	}
18837-
18838-	// Phantom underscore means the underscore is not actually in the
18839-	// program text.
18840-	offset, err := safetoken.Offset(tok, id.Pos())
18841-	if err != nil {
18842-		return false
18843-	}
18844-	return len(src) <= offset || src[offset] != '_'
18845-}
18846-
18847-// fixInitStmt fixes cases where the parser misinterprets an
18848-// if/for/switch "init" statement as the "cond" conditional. In cases
18849-// like "if i := 0" the user hasn't typed the semicolon yet so the
18850-// parser is looking for the conditional expression. However, "i := 0"
18851-// are not valid expressions, so we get a BadExpr.
18852-//
18853-// fixInitStmt returns valid AST for the original source.
18854-func fixInitStmt(bad *ast.BadExpr, parent ast.Node, tok *token.File, src []byte) {
18855-	if !bad.Pos().IsValid() || !bad.End().IsValid() {
18856-		return
18857-	}
18858-
18859-	// Try to extract a statement from the BadExpr.
18860-	start, end, err := safetoken.Offsets(tok, bad.Pos(), bad.End()-1)
18861-	if err != nil {
18862-		return
18863-	}
18864-	stmtBytes := src[start : end+1]
18865-	stmt, err := parseStmt(bad.Pos(), stmtBytes)
18866-	if err != nil {
18867-		return
18868-	}
18869-
18870-	// If the parent statement doesn't already have an "init" statement,
18871-	// move the extracted statement into the "init" field and insert a
18872-	// dummy expression into the required "cond" field.
18873-	switch p := parent.(type) {
18874-	case *ast.IfStmt:
18875-		if p.Init != nil {
18876-			return
18877-		}
18878-		p.Init = stmt
18879-		p.Cond = &ast.Ident{
18880-			Name:    "_",
18881-			NamePos: stmt.End(),
18882-		}
18883-	case *ast.ForStmt:
18884-		if p.Init != nil {
18885-			return
18886-		}
18887-		p.Init = stmt
18888-		p.Cond = &ast.Ident{
18889-			Name:    "_",
18890-			NamePos: stmt.End(),
18891-		}
18892-	case *ast.SwitchStmt:
18893-		if p.Init != nil {
18894-			return
18895-		}
18896-		p.Init = stmt
18897-		p.Tag = nil
18898-	}
18899-}
18900-
18901-// readKeyword reads the keyword starting at pos, if any.
18902-func readKeyword(pos token.Pos, tok *token.File, src []byte) string {
18903-	var kwBytes []byte
18904-	offset, err := safetoken.Offset(tok, pos)
18905-	if err != nil {
18906-		return ""
18907-	}
18908-	for i := offset; i < len(src); i++ {
18909-		// Use a simplified identifier check since keywords are always lowercase ASCII.
18910-		if src[i] < 'a' || src[i] > 'z' {
18911-			break
18912-		}
18913-		kwBytes = append(kwBytes, src[i])
18914-
18915-		// Stop search at arbitrarily chosen too-long-for-a-keyword length.
18916-		if len(kwBytes) > 15 {
18917-			return ""
18918-		}
18919-	}
18920-
18921-	if kw := string(kwBytes); token.Lookup(kw).IsKeyword() {
18922-		return kw
18923-	}
18924-
18925-	return ""
18926-}
18927-
18928-// fixArrayType tries to parse an *ast.BadExpr into an *ast.ArrayType.
18929-// go/parser often turns lone array types like "[]int" into BadExprs
18930-// if it isn't expecting a type.
18931-func fixArrayType(bad *ast.BadExpr, parent ast.Node, tok *token.File, src []byte) bool {
18932-	// Our expected input is a bad expression that looks like "[]someExpr".
18933-
18934-	from := bad.Pos()
18935-	to := bad.End()
18936-
18937-	if !from.IsValid() || !to.IsValid() {
18938-		return false
18939-	}
18940-
18941-	exprBytes := make([]byte, 0, int(to-from)+3)
18942-	// Avoid doing tok.Offset(to) since that panics if badExpr ends at EOF.
18943-	// It also panics if the position is not in the range of the file, and
18944-	// badExprs may not necessarily have good positions, so check first.
18945-	fromOffset, toOffset, err := safetoken.Offsets(tok, from, to-1)
18946-	if err != nil {
18947-		return false
18948-	}
18949-	exprBytes = append(exprBytes, src[fromOffset:toOffset+1]...)
18950-	exprBytes = bytes.TrimSpace(exprBytes)
18951-
18952-	// If our expression ends in "]" (e.g. "[]"), add a phantom selector
18953-	// so we can complete directly after the "[]".
18954-	if len(exprBytes) > 0 && exprBytes[len(exprBytes)-1] == ']' {
18955-		exprBytes = append(exprBytes, '_')
18956-	}
18957-
18958-	// Add "{}" to turn our ArrayType into a CompositeLit. This is to
18959-	// handle the case of "[...]int" where we must make it a composite
18960-	// literal to be parseable.
18961-	exprBytes = append(exprBytes, '{', '}')
18962-
18963-	expr, err := parseExpr(from, exprBytes)
18964-	if err != nil {
18965-		return false
18966-	}
18967-
18968-	cl, _ := expr.(*ast.CompositeLit)
18969-	if cl == nil {
18970-		return false
18971-	}
18972-
18973-	at, _ := cl.Type.(*ast.ArrayType)
18974-	if at == nil {
18975-		return false
18976-	}
18977-
18978-	return replaceNode(parent, bad, at)
18979-}
18980-
18981-// precedingToken scans src to find the token preceding pos.
18982-func precedingToken(pos token.Pos, tok *token.File, src []byte) token.Token {
18983-	s := &scanner.Scanner{}
18984-	s.Init(tok, src, nil, 0)
18985-
18986-	var lastTok token.Token
18987-	for {
18988-		p, t, _ := s.Scan()
18989-		if t == token.EOF || p >= pos {
18990-			break
18991-		}
18992-
18993-		lastTok = t
18994-	}
18995-	return lastTok
18996-}
18997-
18998-// fixDeferOrGoStmt tries to parse an *ast.BadStmt into a defer or a go statement.
18999-//
19000-// go/parser packages a statement of the form "defer x." as an *ast.BadStmt because
19001-// it does not include a call expression. This means that go/types skips type-checking
19002-// this statement entirely, and we can't use the type information when completing.
19003-// Here, we try to generate a fake *ast.DeferStmt or *ast.GoStmt to put into the AST,
19004-// instead of the *ast.BadStmt.
19005-func fixDeferOrGoStmt(bad *ast.BadStmt, parent ast.Node, tok *token.File, src []byte) bool {
19006-	// Check if we have a bad statement containing either a "go" or "defer".
19007-	s := &scanner.Scanner{}
19008-	s.Init(tok, src, nil, 0)
19009-
19010-	var (
19011-		pos token.Pos
19012-		tkn token.Token
19013-	)
19014-	for {
19015-		if tkn == token.EOF {
19016-			return false
19017-		}
19018-		if pos >= bad.From {
19019-			break
19020-		}
19021-		pos, tkn, _ = s.Scan()
19022-	}
19023-
19024-	var stmt ast.Stmt
19025-	switch tkn {
19026-	case token.DEFER:
19027-		stmt = &ast.DeferStmt{
19028-			Defer: pos,
19029-		}
19030-	case token.GO:
19031-		stmt = &ast.GoStmt{
19032-			Go: pos,
19033-		}
19034-	default:
19035-		return false
19036-	}
19037-
19038-	var (
19039-		from, to, last   token.Pos
19040-		lastToken        token.Token
19041-		braceDepth       int
19042-		phantomSelectors []token.Pos
19043-	)
19044-FindTo:
19045-	for {
19046-		to, tkn, _ = s.Scan()
19047-
19048-		if from == token.NoPos {
19049-			from = to
19050-		}
19051-
19052-		switch tkn {
19053-		case token.EOF:
19054-			break FindTo
19055-		case token.SEMICOLON:
19056-			// If we aren't in nested braces, end of statement means
19057-			// end of expression.
19058-			if braceDepth == 0 {
19059-				break FindTo
19060-			}
19061-		case token.LBRACE:
19062-			braceDepth++
19063-		}
19064-
19065-		// This handles the common dangling selector case. For example in
19066-		//
19067-		// defer fmt.
19068-		// y := 1
19069-		//
19070-		// we notice the dangling period and end our expression.
19071-		//
19072-		// If the previous token was a "." and we are looking at a "}",
19073-		// the period is likely a dangling selector and needs a phantom
19074-		// "_". Likewise if the current token is on a different line than
19075-		// the period, the period is likely a dangling selector.
19076-		if lastToken == token.PERIOD && (tkn == token.RBRACE || tok.Line(to) > tok.Line(last)) {
19077-			// Insert phantom "_" selector after the dangling ".".
19078-			phantomSelectors = append(phantomSelectors, last+1)
19079-			// If we aren't in a block then end the expression after the ".".
19080-			if braceDepth == 0 {
19081-				to = last + 1
19082-				break
19083-			}
19084-		}
19085-
19086-		lastToken = tkn
19087-		last = to
19088-
19089-		switch tkn {
19090-		case token.RBRACE:
19091-			braceDepth--
19092-			if braceDepth <= 0 {
19093-				if braceDepth == 0 {
19094-					// +1 to include the "}" itself.
19095-					to += 1
19096-				}
19097-				break FindTo
19098-			}
19099-		}
19100-	}
19101-
19102-	fromOffset, toOffset, err := safetoken.Offsets(tok, from, to)
19103-	if err != nil {
19104-		return false
19105-	}
19106-	if !from.IsValid() || fromOffset >= len(src) {
19107-		return false
19108-	}
19109-	if !to.IsValid() || toOffset >= len(src) {
19110-		return false
19111-	}
19112-
19113-	// Insert any phantom selectors needed to prevent dangling "." from messing
19114-	// up the AST.
19115-	exprBytes := make([]byte, 0, int(to-from)+len(phantomSelectors))
19116-	for i, b := range src[fromOffset:toOffset] {
19117-		if len(phantomSelectors) > 0 && from+token.Pos(i) == phantomSelectors[0] {
19118-			exprBytes = append(exprBytes, '_')
19119-			phantomSelectors = phantomSelectors[1:]
19120-		}
19121-		exprBytes = append(exprBytes, b)
19122-	}
19123-
19124-	if len(phantomSelectors) > 0 {
19125-		exprBytes = append(exprBytes, '_')
19126-	}
19127-
19128-	expr, err := parseExpr(from, exprBytes)
19129-	if err != nil {
19130-		return false
19131-	}
19132-
19133-	// Package the expression into a fake *ast.CallExpr and re-insert
19134-	// into the function.
19135-	call := &ast.CallExpr{
19136-		Fun:    expr,
19137-		Lparen: to,
19138-		Rparen: to,
19139-	}
19140-
19141-	switch stmt := stmt.(type) {
19142-	case *ast.DeferStmt:
19143-		stmt.Call = call
19144-	case *ast.GoStmt:
19145-		stmt.Call = call
19146-	}
19147-
19148-	return replaceNode(parent, bad, stmt)
19149-}
19150-
19151-// parseStmt parses the statement in src and updates its position to
19152-// start at pos.
19153-func parseStmt(pos token.Pos, src []byte) (ast.Stmt, error) {
19154-	// Wrap our expression to make it a valid Go file we can pass to ParseFile.
19155-	fileSrc := bytes.Join([][]byte{
19156-		[]byte("package fake;func _(){"),
19157-		src,
19158-		[]byte("}"),
19159-	}, nil)
19160-
19161-	// Use ParseFile instead of ParseExpr because ParseFile has
19162-	// best-effort behavior, whereas ParseExpr fails hard on any error.
19163-	fakeFile, err := parser.ParseFile(token.NewFileSet(), "", fileSrc, 0)
19164-	if fakeFile == nil {
19165-		return nil, fmt.Errorf("error reading fake file source: %v", err)
19166-	}
19167-
19168-	// Extract our expression node from inside the fake file.
19169-	if len(fakeFile.Decls) == 0 {
19170-		return nil, fmt.Errorf("error parsing fake file: %v", err)
19171-	}
19172-
19173-	fakeDecl, _ := fakeFile.Decls[0].(*ast.FuncDecl)
19174-	if fakeDecl == nil || len(fakeDecl.Body.List) == 0 {
19175-		return nil, fmt.Errorf("no statement in %s: %v", src, err)
19176-	}
19177-
19178-	stmt := fakeDecl.Body.List[0]
19179-
19180-	// parser.ParseFile returns undefined positions.
19181-	// Adjust them for the current file.
19182-	offsetPositions(stmt, pos-1-(stmt.Pos()-1))
19183-
19184-	return stmt, nil
19185-}
19186-
19187-// parseExpr parses the expression in src and updates its position to
19188-// start at pos.
19189-func parseExpr(pos token.Pos, src []byte) (ast.Expr, error) {
19190-	stmt, err := parseStmt(pos, src)
19191-	if err != nil {
19192-		return nil, err
19193-	}
19194-
19195-	exprStmt, ok := stmt.(*ast.ExprStmt)
19196-	if !ok {
19197-		return nil, fmt.Errorf("no expr in %s: %v", src, err)
19198-	}
19199-
19200-	return exprStmt.X, nil
19201-}
19202-
19203-var tokenPosType = reflect.TypeOf(token.NoPos)
19204-
19205-// offsetPositions applies an offset to the positions in an ast.Node.
19206-func offsetPositions(n ast.Node, offset token.Pos) {
19207-	ast.Inspect(n, func(n ast.Node) bool {
19208-		if n == nil {
19209-			return false
19210-		}
19211-
19212-		v := reflect.ValueOf(n).Elem()
19213-
19214-		switch v.Kind() {
19215-		case reflect.Struct:
19216-			for i := 0; i < v.NumField(); i++ {
19217-				f := v.Field(i)
19218-				if f.Type() != tokenPosType {
19219-					continue
19220-				}
19221-
19222-				if !f.CanSet() {
19223-					continue
19224-				}
19225-
19226-				// Don't offset invalid positions: they should stay invalid.
19227-				if !token.Pos(f.Int()).IsValid() {
19228-					continue
19229-				}
19230-
19231-				f.SetInt(f.Int() + int64(offset))
19232-			}
19233-		}
19234-
19235-		return true
19236-	})
19237-}
19238-
19239-// replaceNode updates parent's child oldChild to be newChild. It
19240-// returns whether it replaced successfully.
19241-func replaceNode(parent, oldChild, newChild ast.Node) bool {
19242-	if parent == nil || oldChild == nil || newChild == nil {
19243-		return false
19244-	}
19245-
19246-	parentVal := reflect.ValueOf(parent).Elem()
19247-	if parentVal.Kind() != reflect.Struct {
19248-		return false
19249-	}
19250-
19251-	newChildVal := reflect.ValueOf(newChild)
19252-
19253-	tryReplace := func(v reflect.Value) bool {
19254-		if !v.CanSet() || !v.CanInterface() {
19255-			return false
19256-		}
19257-
19258-		// If the existing value is oldChild, we found our child. Make
19259-		// sure our newChild is assignable and then make the swap.
19260-		if v.Interface() == oldChild && newChildVal.Type().AssignableTo(v.Type()) {
19261-			v.Set(newChildVal)
19262-			return true
19263-		}
19264-
19265-		return false
19266-	}
19267-
19268-	// Loop over parent's struct fields.
19269-	for i := 0; i < parentVal.NumField(); i++ {
19270-		f := parentVal.Field(i)
19271-
19272-		switch f.Kind() {
19273-		// Check interface and pointer fields.
19274-		case reflect.Interface, reflect.Ptr:
19275-			if tryReplace(f) {
19276-				return true
19277-			}
19278-
19279-		// Search through any slice fields.
19280-		case reflect.Slice:
19281-			for i := 0; i < f.Len(); i++ {
19282-				if tryReplace(f.Index(i)) {
19283-					return true
19284-				}
19285-			}
19286-		}
19287-	}
19288-
19289-	return false
19290-}
19291diff -urN a/gopls/internal/lsp/cache/parsemode_go116.go b/gopls/internal/lsp/cache/parsemode_go116.go
19292--- a/gopls/internal/lsp/cache/parsemode_go116.go	2000-01-01 00:00:00.000000000 -0000
19293+++ b/gopls/internal/lsp/cache/parsemode_go116.go	1970-01-01 00:00:00.000000000 +0000
19294@@ -1,11 +0,0 @@
19295-// Copyright 2022 The Go Authors. All rights reserved.
19296-// Use of this source code is governed by a BSD-style
19297-// license that can be found in the LICENSE file.
19298-
19299-//go:build !go1.17
19300-// +build !go1.17
19301-
19302-package cache
19303-
19304-// The parser.SkipObjectResolution mode flag is not supported before Go 1.17.
19305-const skipObjectResolution = 0
19306diff -urN a/gopls/internal/lsp/cache/parsemode_go117.go b/gopls/internal/lsp/cache/parsemode_go117.go
19307--- a/gopls/internal/lsp/cache/parsemode_go117.go	2000-01-01 00:00:00.000000000 -0000
19308+++ b/gopls/internal/lsp/cache/parsemode_go117.go	1970-01-01 00:00:00.000000000 +0000
19309@@ -1,12 +0,0 @@
19310-// Copyright 2022 The Go Authors. All rights reserved.
19311-// Use of this source code is governed by a BSD-style
19312-// license that can be found in the LICENSE file.
19313-
19314-//go:build go1.17
19315-// +build go1.17
19316-
19317-package cache
19318-
19319-import "go/parser"
19320-
19321-const skipObjectResolution = parser.SkipObjectResolution
19322diff -urN a/gopls/internal/lsp/cache/pkg.go b/gopls/internal/lsp/cache/pkg.go
19323--- a/gopls/internal/lsp/cache/pkg.go	2000-01-01 00:00:00.000000000 -0000
19324+++ b/gopls/internal/lsp/cache/pkg.go	1970-01-01 00:00:00.000000000 +0000
19325@@ -1,165 +0,0 @@
19326-// Copyright 2019 The Go Authors. All rights reserved.
19327-// Use of this source code is governed by a BSD-style
19328-// license that can be found in the LICENSE file.
19329-
19330-package cache
19331-
19332-import (
19333-	"context"
19334-	"fmt"
19335-	"go/ast"
19336-	"go/scanner"
19337-	"go/token"
19338-	"go/types"
19339-
19340-	"golang.org/x/tools/gopls/internal/lsp/source"
19341-	"golang.org/x/tools/gopls/internal/lsp/source/methodsets"
19342-	"golang.org/x/tools/gopls/internal/span"
19343-	"golang.org/x/tools/internal/memoize"
19344-)
19345-
19346-// Convenient local aliases for typed strings.
19347-type (
19348-	PackageID   = source.PackageID
19349-	PackagePath = source.PackagePath
19350-	PackageName = source.PackageName
19351-	ImportPath  = source.ImportPath
19352-)
19353-
19354-// A Package is the union of snapshot-local information (Metadata) and shared
19355-// type-checking information (a syntaxPackage).
19356-//
19357-// TODO(rfindley): for now, we do not persist the post-processing of
19358-// loadDiagnostics, because the value of the snapshot.packages map  is just the
19359-// package handle. Fix this.
19360-type Package struct {
19361-	m   *source.Metadata
19362-	pkg *syntaxPackage
19363-}
19364-
19365-// syntaxPackage contains parse trees and type information for a package.
19366-type syntaxPackage struct {
19367-	// -- identifiers --
19368-	id   PackageID
19369-	mode source.ParseMode
19370-
19371-	// -- outputs --
19372-	fset            *token.FileSet // for now, same as the snapshot's FileSet
19373-	goFiles         []*source.ParsedGoFile
19374-	compiledGoFiles []*source.ParsedGoFile
19375-	diagnostics     []*source.Diagnostic
19376-	parseErrors     []scanner.ErrorList
19377-	typeErrors      []types.Error
19378-	types           *types.Package
19379-	typesInfo       *types.Info
19380-	importMap       map[string]*types.Package // keys are PackagePaths
19381-	hasFixedFiles   bool                      // if true, AST was sufficiently mangled that we should hide type errors
19382-	analyses        memoize.Store             // maps analyzer.Name to Promise[actionResult]
19383-	xrefs           []byte
19384-	methodsets      *methodsets.Index
19385-}
19386-
19387-func (p *Package) String() string { return string(p.m.ID) }
19388-
19389-func (p *Package) Metadata() *source.Metadata { return p.m }
19390-
19391-// A loadScope defines a package loading scope for use with go/packages.
19392-//
19393-// TODO(rfindley): move this to load.go.
19394-type loadScope interface {
19395-	aScope()
19396-}
19397-
19398-type (
19399-	fileLoadScope    span.URI // load packages containing a file (including command-line-arguments)
19400-	packageLoadScope string   // load a specific package (the value is its PackageID)
19401-	moduleLoadScope  string   // load packages in a specific module
19402-	viewLoadScope    span.URI // load the workspace
19403-)
19404-
19405-// Implement the loadScope interface.
19406-func (fileLoadScope) aScope()    {}
19407-func (packageLoadScope) aScope() {}
19408-func (moduleLoadScope) aScope()  {}
19409-func (viewLoadScope) aScope()    {}
19410-
19411-func (p *Package) ParseMode() source.ParseMode {
19412-	return p.pkg.mode
19413-}
19414-
19415-func (p *Package) CompiledGoFiles() []*source.ParsedGoFile {
19416-	return p.pkg.compiledGoFiles
19417-}
19418-
19419-func (p *Package) File(uri span.URI) (*source.ParsedGoFile, error) {
19420-	return p.pkg.File(uri)
19421-}
19422-
19423-func (pkg *syntaxPackage) File(uri span.URI) (*source.ParsedGoFile, error) {
19424-	for _, cgf := range pkg.compiledGoFiles {
19425-		if cgf.URI == uri {
19426-			return cgf, nil
19427-		}
19428-	}
19429-	for _, gf := range pkg.goFiles {
19430-		if gf.URI == uri {
19431-			return gf, nil
19432-		}
19433-	}
19434-	return nil, fmt.Errorf("no parsed file for %s in %v", uri, pkg.id)
19435-}
19436-
19437-func (p *Package) GetSyntax() []*ast.File {
19438-	var syntax []*ast.File
19439-	for _, pgf := range p.pkg.compiledGoFiles {
19440-		syntax = append(syntax, pgf.File)
19441-	}
19442-	return syntax
19443-}
19444-
19445-func (p *Package) FileSet() *token.FileSet {
19446-	return p.pkg.fset
19447-}
19448-
19449-func (p *Package) GetTypes() *types.Package {
19450-	return p.pkg.types
19451-}
19452-
19453-func (p *Package) GetTypesInfo() *types.Info {
19454-	return p.pkg.typesInfo
19455-}
19456-
19457-// DependencyTypes returns the type checker's symbol for the specified
19458-// package. It returns nil if path is not among the transitive
19459-// dependencies of p, or if no symbols from that package were
19460-// referenced during the type-checking of p.
19461-func (p *Package) DependencyTypes(path source.PackagePath) *types.Package {
19462-	if path == p.m.PkgPath {
19463-		return p.pkg.types
19464-	}
19465-	return p.pkg.importMap[string(path)]
19466-}
19467-
19468-func (p *Package) HasParseErrors() bool {
19469-	return len(p.pkg.parseErrors) != 0
19470-}
19471-
19472-func (p *Package) HasTypeErrors() bool {
19473-	return len(p.pkg.typeErrors) != 0
19474-}
19475-
19476-func (p *Package) DiagnosticsForFile(ctx context.Context, s source.Snapshot, uri span.URI) ([]*source.Diagnostic, error) {
19477-	var diags []*source.Diagnostic
19478-	for _, diag := range p.m.Diagnostics {
19479-		if diag.URI == uri {
19480-			diags = append(diags, diag)
19481-		}
19482-	}
19483-	for _, diag := range p.pkg.diagnostics {
19484-		if diag.URI == uri {
19485-			diags = append(diags, diag)
19486-		}
19487-	}
19488-
19489-	return diags, nil
19490-}
19491diff -urN a/gopls/internal/lsp/cache/session.go b/gopls/internal/lsp/cache/session.go
19492--- a/gopls/internal/lsp/cache/session.go	2000-01-01 00:00:00.000000000 -0000
19493+++ b/gopls/internal/lsp/cache/session.go	1970-01-01 00:00:00.000000000 +0000
19494@@ -1,730 +0,0 @@
19495-// Copyright 2019 The Go Authors. All rights reserved.
19496-// Use of this source code is governed by a BSD-style
19497-// license that can be found in the LICENSE file.
19498-
19499-package cache
19500-
19501-import (
19502-	"context"
19503-	"fmt"
19504-	"strconv"
19505-	"strings"
19506-	"sync"
19507-	"sync/atomic"
19508-
19509-	"golang.org/x/tools/gopls/internal/govulncheck"
19510-	"golang.org/x/tools/gopls/internal/lsp/source"
19511-	"golang.org/x/tools/gopls/internal/span"
19512-	"golang.org/x/tools/internal/bug"
19513-	"golang.org/x/tools/internal/event"
19514-	"golang.org/x/tools/internal/gocommand"
19515-	"golang.org/x/tools/internal/imports"
19516-	"golang.org/x/tools/internal/persistent"
19517-	"golang.org/x/tools/internal/xcontext"
19518-)
19519-
19520-type Session struct {
19521-	// Unique identifier for this session.
19522-	id string
19523-
19524-	// Immutable attributes shared across views.
19525-	cache       *Cache            // shared cache
19526-	gocmdRunner *gocommand.Runner // limits go command concurrency
19527-
19528-	optionsMu sync.Mutex
19529-	options   *source.Options
19530-
19531-	viewMu  sync.Mutex
19532-	views   []*View
19533-	viewMap map[span.URI]*View // map of URI->best view
19534-
19535-	*overlayFS
19536-}
19537-
19538-// ID returns the unique identifier for this session on this server.
19539-func (s *Session) ID() string     { return s.id }
19540-func (s *Session) String() string { return s.id }
19541-
19542-// Options returns a copy of the SessionOptions for this session.
19543-func (s *Session) Options() *source.Options {
19544-	s.optionsMu.Lock()
19545-	defer s.optionsMu.Unlock()
19546-	return s.options
19547-}
19548-
19549-// SetOptions sets the options of this session to new values.
19550-func (s *Session) SetOptions(options *source.Options) {
19551-	s.optionsMu.Lock()
19552-	defer s.optionsMu.Unlock()
19553-	s.options = options
19554-}
19555-
19556-// Shutdown the session and all views it has created.
19557-func (s *Session) Shutdown(ctx context.Context) {
19558-	var views []*View
19559-	s.viewMu.Lock()
19560-	views = append(views, s.views...)
19561-	s.views = nil
19562-	s.viewMap = nil
19563-	s.viewMu.Unlock()
19564-	for _, view := range views {
19565-		view.shutdown()
19566-	}
19567-	event.Log(ctx, "Shutdown session", KeyShutdownSession.Of(s))
19568-}
19569-
19570-// Cache returns the cache that created this session, for debugging only.
19571-func (s *Session) Cache() *Cache {
19572-	return s.cache
19573-}
19574-
19575-// NewView creates a new View, returning it and its first snapshot. If a
19576-// non-empty tempWorkspace directory is provided, the View will record a copy
19577-// of its gopls workspace module in that directory, so that client tooling
19578-// can execute in the same main module.  On success it also returns a release
19579-// function that must be called when the Snapshot is no longer needed.
19580-func (s *Session) NewView(ctx context.Context, name string, folder span.URI, options *source.Options) (*View, source.Snapshot, func(), error) {
19581-	s.viewMu.Lock()
19582-	defer s.viewMu.Unlock()
19583-	for _, view := range s.views {
19584-		if span.SameExistingFile(view.folder, folder) {
19585-			return nil, nil, nil, source.ErrViewExists
19586-		}
19587-	}
19588-	view, snapshot, release, err := s.createView(ctx, name, folder, options, 0)
19589-	if err != nil {
19590-		return nil, nil, nil, err
19591-	}
19592-	s.views = append(s.views, view)
19593-	// we always need to drop the view map
19594-	s.viewMap = make(map[span.URI]*View)
19595-	return view, snapshot, release, nil
19596-}
19597-
19598-// TODO(rfindley): clarify that createView can never be cancelled (with the
19599-// possible exception of server shutdown).
19600-func (s *Session) createView(ctx context.Context, name string, folder span.URI, options *source.Options, seqID uint64) (*View, *snapshot, func(), error) {
19601-	index := atomic.AddInt64(&viewIndex, 1)
19602-
19603-	// Get immutable workspace information.
19604-	info, err := s.getWorkspaceInformation(ctx, folder, options)
19605-	if err != nil {
19606-		return nil, nil, func() {}, err
19607-	}
19608-
19609-	wsModFiles, wsModFilesErr := computeWorkspaceModFiles(ctx, info.gomod, info.effectiveGOWORK(), info.effectiveGO111MODULE(), s)
19610-
19611-	// We want a true background context and not a detached context here
19612-	// the spans need to be unrelated and no tag values should pollute it.
19613-	baseCtx := event.Detach(xcontext.Detach(ctx))
19614-	backgroundCtx, cancel := context.WithCancel(baseCtx)
19615-
19616-	v := &View{
19617-		id:                   strconv.FormatInt(index, 10),
19618-		gocmdRunner:          s.gocmdRunner,
19619-		initialWorkspaceLoad: make(chan struct{}),
19620-		initializationSema:   make(chan struct{}, 1),
19621-		options:              options,
19622-		baseCtx:              baseCtx,
19623-		name:                 name,
19624-		folder:               folder,
19625-		moduleUpgrades:       map[span.URI]map[string]string{},
19626-		vulns:                map[span.URI]*govulncheck.Result{},
19627-		fs:                   s.overlayFS,
19628-		workspaceInformation: info,
19629-	}
19630-	v.importsState = &importsState{
19631-		ctx: backgroundCtx,
19632-		processEnv: &imports.ProcessEnv{
19633-			GocmdRunner: s.gocmdRunner,
19634-			SkipPathInScan: func(dir string) bool {
19635-				prefix := strings.TrimSuffix(string(v.folder), "/") + "/"
19636-				uri := strings.TrimSuffix(string(span.URIFromPath(dir)), "/")
19637-				if !strings.HasPrefix(uri+"/", prefix) {
19638-					return false
19639-				}
19640-				filterer := source.NewFilterer(options.DirectoryFilters)
19641-				rel := strings.TrimPrefix(uri, prefix)
19642-				disallow := filterer.Disallow(rel)
19643-				return disallow
19644-			},
19645-		},
19646-	}
19647-	v.snapshot = &snapshot{
19648-		sequenceID:           seqID,
19649-		globalID:             nextSnapshotID(),
19650-		view:                 v,
19651-		backgroundCtx:        backgroundCtx,
19652-		cancel:               cancel,
19653-		store:                s.cache.store,
19654-		packages:             persistent.NewMap(packageIDLessInterface),
19655-		meta:                 new(metadataGraph),
19656-		files:                newFilesMap(),
19657-		parseCache:           new(parseCache),
19658-		activePackages:       persistent.NewMap(packageIDLessInterface),
19659-		symbolizeHandles:     persistent.NewMap(uriLessInterface),
19660-		analyses:             persistent.NewMap(analysisKeyLessInterface),
19661-		workspacePackages:    make(map[PackageID]PackagePath),
19662-		unloadableFiles:      make(map[span.URI]struct{}),
19663-		parseModHandles:      persistent.NewMap(uriLessInterface),
19664-		parseWorkHandles:     persistent.NewMap(uriLessInterface),
19665-		modTidyHandles:       persistent.NewMap(uriLessInterface),
19666-		modVulnHandles:       persistent.NewMap(uriLessInterface),
19667-		modWhyHandles:        persistent.NewMap(uriLessInterface),
19668-		knownSubdirs:         newKnownDirsSet(),
19669-		workspaceModFiles:    wsModFiles,
19670-		workspaceModFilesErr: wsModFilesErr,
19671-	}
19672-	// Save one reference in the view.
19673-	v.releaseSnapshot = v.snapshot.Acquire()
19674-
19675-	// Record the environment of the newly created view in the log.
19676-	event.Log(ctx, viewEnv(v))
19677-
19678-	// Initialize the view without blocking.
19679-	initCtx, initCancel := context.WithCancel(xcontext.Detach(ctx))
19680-	v.initCancelFirstAttempt = initCancel
19681-	snapshot := v.snapshot
19682-
19683-	// Pass a second reference to the background goroutine.
19684-	bgRelease := snapshot.Acquire()
19685-	go func() {
19686-		defer bgRelease()
19687-		snapshot.initialize(initCtx, true)
19688-	}()
19689-
19690-	// Return a third reference to the caller.
19691-	return v, snapshot, snapshot.Acquire(), nil
19692-}
19693-
19694-// View returns a view with a matching name, if the session has one.
19695-func (s *Session) View(name string) *View {
19696-	s.viewMu.Lock()
19697-	defer s.viewMu.Unlock()
19698-	for _, view := range s.views {
19699-		if view.Name() == name {
19700-			return view
19701-		}
19702-	}
19703-	return nil
19704-}
19705-
19706-// ViewOf returns a view corresponding to the given URI.
19707-// If the file is not already associated with a view, pick one using some heuristics.
19708-func (s *Session) ViewOf(uri span.URI) (*View, error) {
19709-	s.viewMu.Lock()
19710-	defer s.viewMu.Unlock()
19711-	return s.viewOfLocked(uri)
19712-}
19713-
19714-// Precondition: caller holds s.viewMu lock.
19715-func (s *Session) viewOfLocked(uri span.URI) (*View, error) {
19716-	// Check if we already know this file.
19717-	if v, found := s.viewMap[uri]; found {
19718-		return v, nil
19719-	}
19720-	// Pick the best view for this file and memoize the result.
19721-	if len(s.views) == 0 {
19722-		return nil, fmt.Errorf("no views in session")
19723-	}
19724-	s.viewMap[uri] = bestViewForURI(uri, s.views)
19725-	return s.viewMap[uri], nil
19726-}
19727-
19728-func (s *Session) Views() []*View {
19729-	s.viewMu.Lock()
19730-	defer s.viewMu.Unlock()
19731-	result := make([]*View, len(s.views))
19732-	copy(result, s.views)
19733-	return result
19734-}
19735-
19736-// bestViewForURI returns the most closely matching view for the given URI
19737-// out of the given set of views.
19738-func bestViewForURI(uri span.URI, views []*View) *View {
19739-	// we need to find the best view for this file
19740-	var longest *View
19741-	for _, view := range views {
19742-		if longest != nil && len(longest.Folder()) > len(view.Folder()) {
19743-			continue
19744-		}
19745-		// TODO(rfindley): this should consider the workspace layout (i.e.
19746-		// go.work).
19747-		if view.contains(uri) {
19748-			longest = view
19749-		}
19750-	}
19751-	if longest != nil {
19752-		return longest
19753-	}
19754-	// Try our best to return a view that knows the file.
19755-	for _, view := range views {
19756-		if view.knownFile(uri) {
19757-			return view
19758-		}
19759-	}
19760-	// TODO: are there any more heuristics we can use?
19761-	return views[0]
19762-}
19763-
19764-// RemoveView removes the view v from the session
19765-func (s *Session) RemoveView(view *View) {
19766-	s.viewMu.Lock()
19767-	defer s.viewMu.Unlock()
19768-	i := s.dropView(view)
19769-	if i == -1 { // error reported elsewhere
19770-		return
19771-	}
19772-	// delete this view... we don't care about order but we do want to make
19773-	// sure we can garbage collect the view
19774-	s.views = removeElement(s.views, i)
19775-}
19776-
19777-// updateView recreates the view with the given options.
19778-//
19779-// If the resulting error is non-nil, the view may or may not have already been
19780-// dropped from the session.
19781-func (s *Session) updateView(ctx context.Context, view *View, options *source.Options) (*View, error) {
19782-	s.viewMu.Lock()
19783-	defer s.viewMu.Unlock()
19784-
19785-	return s.updateViewLocked(ctx, view, options)
19786-}
19787-
19788-func (s *Session) updateViewLocked(ctx context.Context, view *View, options *source.Options) (*View, error) {
19789-	// Preserve the snapshot ID if we are recreating the view.
19790-	view.snapshotMu.Lock()
19791-	if view.snapshot == nil {
19792-		view.snapshotMu.Unlock()
19793-		panic("updateView called after View was already shut down")
19794-	}
19795-	seqID := view.snapshot.sequenceID // Preserve sequence IDs when updating a view in place.
19796-	view.snapshotMu.Unlock()
19797-
19798-	i := s.dropView(view)
19799-	if i == -1 {
19800-		return nil, fmt.Errorf("view %q not found", view.id)
19801-	}
19802-
19803-	v, _, release, err := s.createView(ctx, view.name, view.folder, options, seqID)
19804-	release()
19805-
19806-	if err != nil {
19807-		// we have dropped the old view, but could not create the new one
19808-		// this should not happen and is very bad, but we still need to clean
19809-		// up the view array if it happens
19810-		s.views = removeElement(s.views, i)
19811-		return nil, err
19812-	}
19813-	// substitute the new view into the array where the old view was
19814-	s.views[i] = v
19815-	return v, nil
19816-}
19817-
19818-// removeElement removes the ith element from the slice replacing it with the last element.
19819-// TODO(adonovan): generics, someday.
19820-func removeElement(slice []*View, index int) []*View {
19821-	last := len(slice) - 1
19822-	slice[index] = slice[last]
19823-	slice[last] = nil // aid GC
19824-	return slice[:last]
19825-}
19826-
19827-// dropView removes v from the set of views for the receiver s and calls
19828-// v.shutdown, returning the index of v in s.views (if found), or -1 if v was
19829-// not found. s.viewMu must be held while calling this function.
19830-func (s *Session) dropView(v *View) int {
19831-	// we always need to drop the view map
19832-	s.viewMap = make(map[span.URI]*View)
19833-	for i := range s.views {
19834-		if v == s.views[i] {
19835-			// we found the view, drop it and return the index it was found at
19836-			s.views[i] = nil
19837-			v.shutdown()
19838-			return i
19839-		}
19840-	}
19841-	// TODO(rfindley): it looks wrong that we don't shutdown v in this codepath.
19842-	// We should never get here.
19843-	bug.Reportf("tried to drop nonexistent view %q", v.id)
19844-	return -1
19845-}
19846-
19847-func (s *Session) ModifyFiles(ctx context.Context, changes []source.FileModification) error {
19848-	_, release, err := s.DidModifyFiles(ctx, changes)
19849-	release()
19850-	return err
19851-}
19852-
19853-// TODO(rfindley): fileChange seems redundant with source.FileModification.
19854-// De-dupe into a common representation for changes.
19855-type fileChange struct {
19856-	content    []byte
19857-	exists     bool
19858-	fileHandle source.FileHandle
19859-
19860-	// isUnchanged indicates whether the file action is one that does not
19861-	// change the actual contents of the file. Opens and closes should not
19862-	// be treated like other changes, since the file content doesn't change.
19863-	isUnchanged bool
19864-}
19865-
19866-// DidModifyFiles reports a file modification to the session. It returns
19867-// the new snapshots after the modifications have been applied, paired with
19868-// the affected file URIs for those snapshots.
19869-// On success, it returns a release function that
19870-// must be called when the snapshots are no longer needed.
19871-//
19872-// TODO(rfindley): what happens if this function fails? It must leave us in a
19873-// broken state, which we should surface to the user, probably as a request to
19874-// restart gopls.
19875-func (s *Session) DidModifyFiles(ctx context.Context, changes []source.FileModification) (map[source.Snapshot][]span.URI, func(), error) {
19876-	s.viewMu.Lock()
19877-	defer s.viewMu.Unlock()
19878-
19879-	// Update overlays.
19880-	//
19881-	// TODO(rfindley): I think we do this while holding viewMu to prevent views
19882-	// from seeing the updated file content before they have processed
19883-	// invalidations, which could lead to a partial view of the changes (i.e.
19884-	// spurious diagnostics). However, any such view would immediately be
19885-	// invalidated here, so it is possible that we could update overlays before
19886-	// acquiring viewMu.
19887-	if err := s.updateOverlays(ctx, changes); err != nil {
19888-		return nil, nil, err
19889-	}
19890-
19891-	// Re-create views whose definition may have changed.
19892-	//
19893-	// checkViews controls whether to re-evaluate view definitions when
19894-	// collecting views below. Any addition or deletion of a go.mod or go.work
19895-	// file may have affected the definition of the view.
19896-	checkViews := false
19897-
19898-	for _, c := range changes {
19899-		if isGoMod(c.URI) || isGoWork(c.URI) {
19900-			// Change, InvalidateMetadata, and UnknownFileAction actions do not cause
19901-			// us to re-evaluate views.
19902-			redoViews := (c.Action != source.Change &&
19903-				c.Action != source.InvalidateMetadata &&
19904-				c.Action != source.UnknownFileAction)
19905-
19906-			if redoViews {
19907-				checkViews = true
19908-				break
19909-			}
19910-		}
19911-	}
19912-
19913-	if checkViews {
19914-		for _, view := range s.views {
19915-			// TODO(rfindley): can we avoid running the go command (go env)
19916-			// synchronously to change processing? Can we assume that the env did not
19917-			// change, and derive go.work using a combination of the configured
19918-			// GOWORK value and filesystem?
19919-			info, err := s.getWorkspaceInformation(ctx, view.folder, view.Options())
19920-			if err != nil {
19921-				// Catastrophic failure, equivalent to a failure of session
19922-				// initialization and therefore should almost never happen. One
19923-				// scenario where this failure mode could occur is if some file
19924-				// permissions have changed preventing us from reading go.mod
19925-				// files.
19926-				//
19927-				// TODO(rfindley): consider surfacing this error more loudly. We
19928-				// could report a bug, but it's not really a bug.
19929-				event.Error(ctx, "fetching workspace information", err)
19930-			}
19931-
19932-			if info != view.workspaceInformation {
19933-				_, err := s.updateViewLocked(ctx, view, view.Options())
19934-				if err != nil {
19935-					// More catastrophic failure. The view may or may not still exist.
19936-					// The best we can do is log and move on.
19937-					event.Error(ctx, "recreating view", err)
19938-				}
19939-			}
19940-		}
19941-	}
19942-
19943-	// Collect information about views affected by these changes.
19944-	views := make(map[*View]map[span.URI]*fileChange)
19945-	affectedViews := map[span.URI][]*View{}
19946-	// forceReloadMetadata records whether any change is the magic
19947-	// source.InvalidateMetadata action.
19948-	forceReloadMetadata := false
19949-	for _, c := range changes {
19950-		if c.Action == source.InvalidateMetadata {
19951-			forceReloadMetadata = true
19952-		}
19953-		// Build the list of affected views.
19954-		var changedViews []*View
19955-		for _, view := range s.views {
19956-			// Don't propagate changes that are outside of the view's scope
19957-			// or knowledge.
19958-			if !view.relevantChange(c) {
19959-				continue
19960-			}
19961-			changedViews = append(changedViews, view)
19962-		}
19963-		// If the change is not relevant to any view, but the change is
19964-		// happening in the editor, assign it the most closely matching view.
19965-		if len(changedViews) == 0 {
19966-			if c.OnDisk {
19967-				continue
19968-			}
19969-			bestView, err := s.viewOfLocked(c.URI)
19970-			if err != nil {
19971-				return nil, nil, err
19972-			}
19973-			changedViews = append(changedViews, bestView)
19974-		}
19975-		affectedViews[c.URI] = changedViews
19976-
19977-		isUnchanged := c.Action == source.Open || c.Action == source.Close
19978-
19979-		// Apply the changes to all affected views.
19980-		for _, view := range changedViews {
19981-			// Make sure that the file is added to the view's seenFiles set.
19982-			view.markKnown(c.URI)
19983-			if _, ok := views[view]; !ok {
19984-				views[view] = make(map[span.URI]*fileChange)
19985-			}
19986-			fh, err := s.GetFile(ctx, c.URI)
19987-			if err != nil {
19988-				return nil, nil, err
19989-			}
19990-			content, err := fh.Read()
19991-			if err != nil {
19992-				// Ignore the error: the file may be deleted.
19993-				content = nil
19994-			}
19995-			views[view][c.URI] = &fileChange{
19996-				content:     content,
19997-				exists:      err == nil,
19998-				fileHandle:  fh,
19999-				isUnchanged: isUnchanged,
20000-			}
20001-		}
20002-	}
20003-
20004-	var releases []func()
20005-	viewToSnapshot := map[*View]*snapshot{}
20006-	for view, changed := range views {
20007-		snapshot, release := view.invalidateContent(ctx, changed, forceReloadMetadata)
20008-		releases = append(releases, release)
20009-		viewToSnapshot[view] = snapshot
20010-	}
20011-
20012-	// The release function is called when the
20013-	// returned URIs no longer need to be valid.
20014-	release := func() {
20015-		for _, release := range releases {
20016-			release()
20017-		}
20018-	}
20019-
20020-	// We only want to diagnose each changed file once, in the view to which
20021-	// it "most" belongs. We do this by picking the best view for each URI,
20022-	// and then aggregating the set of snapshots and their URIs (to avoid
20023-	// diagnosing the same snapshot multiple times).
20024-	snapshotURIs := map[source.Snapshot][]span.URI{}
20025-	for _, mod := range changes {
20026-		viewSlice, ok := affectedViews[mod.URI]
20027-		if !ok || len(viewSlice) == 0 {
20028-			continue
20029-		}
20030-		view := bestViewForURI(mod.URI, viewSlice)
20031-		snapshot, ok := viewToSnapshot[view]
20032-		if !ok {
20033-			panic(fmt.Sprintf("no snapshot for view %s", view.Folder()))
20034-		}
20035-		snapshotURIs[snapshot] = append(snapshotURIs[snapshot], mod.URI)
20036-	}
20037-
20038-	return snapshotURIs, release, nil
20039-}
20040-
20041-// ExpandModificationsToDirectories returns the set of changes with the
20042-// directory changes removed and expanded to include all of the files in
20043-// the directory.
20044-func (s *Session) ExpandModificationsToDirectories(ctx context.Context, changes []source.FileModification) []source.FileModification {
20045-	var snapshots []*snapshot
20046-	s.viewMu.Lock()
20047-	for _, v := range s.views {
20048-		snapshot, release, err := v.getSnapshot()
20049-		if err != nil {
20050-			continue // view is shut down; continue with others
20051-		}
20052-		defer release()
20053-		snapshots = append(snapshots, snapshot)
20054-	}
20055-	s.viewMu.Unlock()
20056-
20057-	knownDirs := knownDirectories(ctx, snapshots)
20058-	defer knownDirs.Destroy()
20059-
20060-	var result []source.FileModification
20061-	for _, c := range changes {
20062-		if !knownDirs.Contains(c.URI) {
20063-			result = append(result, c)
20064-			continue
20065-		}
20066-		affectedFiles := knownFilesInDir(ctx, snapshots, c.URI)
20067-		var fileChanges []source.FileModification
20068-		for uri := range affectedFiles {
20069-			fileChanges = append(fileChanges, source.FileModification{
20070-				URI:        uri,
20071-				Action:     c.Action,
20072-				LanguageID: "",
20073-				OnDisk:     c.OnDisk,
20074-				// changes to directories cannot include text or versions
20075-			})
20076-		}
20077-		result = append(result, fileChanges...)
20078-	}
20079-	return result
20080-}
20081-
20082-// knownDirectories returns all of the directories known to the given
20083-// snapshots, including workspace directories and their subdirectories.
20084-// It is responsibility of the caller to destroy the returned set.
20085-func knownDirectories(ctx context.Context, snapshots []*snapshot) knownDirsSet {
20086-	result := newKnownDirsSet()
20087-	for _, snapshot := range snapshots {
20088-		dirs := snapshot.dirs(ctx)
20089-		for _, dir := range dirs {
20090-			result.Insert(dir)
20091-		}
20092-		knownSubdirs := snapshot.getKnownSubdirs(dirs)
20093-		result.SetAll(knownSubdirs)
20094-		knownSubdirs.Destroy()
20095-	}
20096-	return result
20097-}
20098-
20099-// knownFilesInDir returns the files known to the snapshots in the session.
20100-// It does not respect symlinks.
20101-func knownFilesInDir(ctx context.Context, snapshots []*snapshot, dir span.URI) map[span.URI]struct{} {
20102-	files := map[span.URI]struct{}{}
20103-
20104-	for _, snapshot := range snapshots {
20105-		for _, uri := range snapshot.knownFilesInDir(ctx, dir) {
20106-			files[uri] = struct{}{}
20107-		}
20108-	}
20109-	return files
20110-}
20111-
20112-// Precondition: caller holds s.viewMu lock.
20113-// TODO(rfindley): move this to fs_overlay.go.
20114-func (fs *overlayFS) updateOverlays(ctx context.Context, changes []source.FileModification) error {
20115-	fs.mu.Lock()
20116-	defer fs.mu.Unlock()
20117-
20118-	for _, c := range changes {
20119-		// Don't update overlays for metadata invalidations.
20120-		if c.Action == source.InvalidateMetadata {
20121-			continue
20122-		}
20123-
20124-		o, ok := fs.overlays[c.URI]
20125-
20126-		// If the file is not opened in an overlay and the change is on disk,
20127-		// there's no need to update an overlay. If there is an overlay, we
20128-		// may need to update the overlay's saved value.
20129-		if !ok && c.OnDisk {
20130-			continue
20131-		}
20132-
20133-		// Determine the file kind on open, otherwise, assume it has been cached.
20134-		var kind source.FileKind
20135-		switch c.Action {
20136-		case source.Open:
20137-			kind = source.FileKindForLang(c.LanguageID)
20138-		default:
20139-			if !ok {
20140-				return fmt.Errorf("updateOverlays: modifying unopened overlay %v", c.URI)
20141-			}
20142-			kind = o.kind
20143-		}
20144-
20145-		// Closing a file just deletes its overlay.
20146-		if c.Action == source.Close {
20147-			delete(fs.overlays, c.URI)
20148-			continue
20149-		}
20150-
20151-		// If the file is on disk, check if its content is the same as in the
20152-		// overlay. Saves and on-disk file changes don't come with the file's
20153-		// content.
20154-		text := c.Text
20155-		if text == nil && (c.Action == source.Save || c.OnDisk) {
20156-			if !ok {
20157-				return fmt.Errorf("no known content for overlay for %s", c.Action)
20158-			}
20159-			text = o.content
20160-		}
20161-		// On-disk changes don't come with versions.
20162-		version := c.Version
20163-		if c.OnDisk || c.Action == source.Save {
20164-			version = o.version
20165-		}
20166-		hash := source.HashOf(text)
20167-		var sameContentOnDisk bool
20168-		switch c.Action {
20169-		case source.Delete:
20170-			// Do nothing. sameContentOnDisk should be false.
20171-		case source.Save:
20172-			// Make sure the version and content (if present) is the same.
20173-			if false && o.version != version { // Client no longer sends the version
20174-				return fmt.Errorf("updateOverlays: saving %s at version %v, currently at %v", c.URI, c.Version, o.version)
20175-			}
20176-			if c.Text != nil && o.hash != hash {
20177-				return fmt.Errorf("updateOverlays: overlay %s changed on save", c.URI)
20178-			}
20179-			sameContentOnDisk = true
20180-		default:
20181-			fh, err := fs.delegate.GetFile(ctx, c.URI)
20182-			if err != nil {
20183-				return err
20184-			}
20185-			_, readErr := fh.Read()
20186-			sameContentOnDisk = (readErr == nil && fh.FileIdentity().Hash == hash)
20187-		}
20188-		o = &Overlay{
20189-			uri:     c.URI,
20190-			version: version,
20191-			content: text,
20192-			kind:    kind,
20193-			hash:    hash,
20194-			saved:   sameContentOnDisk,
20195-		}
20196-
20197-		// NOTE: previous versions of this code checked here that the overlay had a
20198-		// view and file kind (but we don't know why).
20199-
20200-		fs.overlays[c.URI] = o
20201-	}
20202-
20203-	return nil
20204-}
20205-
20206-// FileWatchingGlobPatterns returns glob patterns to watch every directory
20207-// known by the view. For views within a module, this is the module root,
20208-// any directory in the module root, and any replace targets.
20209-func (s *Session) FileWatchingGlobPatterns(ctx context.Context) map[string]struct{} {
20210-	s.viewMu.Lock()
20211-	defer s.viewMu.Unlock()
20212-	patterns := map[string]struct{}{}
20213-	for _, view := range s.views {
20214-		snapshot, release, err := view.getSnapshot()
20215-		if err != nil {
20216-			continue // view is shut down; continue with others
20217-		}
20218-		for k, v := range snapshot.fileWatchingGlobPatterns(ctx) {
20219-			patterns[k] = v
20220-		}
20221-		release()
20222-	}
20223-	return patterns
20224-}
20225diff -urN a/gopls/internal/lsp/cache/snapshot.go b/gopls/internal/lsp/cache/snapshot.go
20226--- a/gopls/internal/lsp/cache/snapshot.go	2000-01-01 00:00:00.000000000 -0000
20227+++ b/gopls/internal/lsp/cache/snapshot.go	1970-01-01 00:00:00.000000000 +0000
20228@@ -1,2214 +0,0 @@
20229-// Copyright 2019 The Go Authors. All rights reserved.
20230-// Use of this source code is governed by a BSD-style
20231-// license that can be found in the LICENSE file.
20232-
20233-package cache
20234-
20235-import (
20236-	"bytes"
20237-	"context"
20238-	"errors"
20239-	"fmt"
20240-	"go/ast"
20241-	"go/token"
20242-	"go/types"
20243-	"io"
20244-	"io/ioutil"
20245-	"log"
20246-	"os"
20247-	"path/filepath"
20248-	"regexp"
20249-	"runtime"
20250-	"sort"
20251-	"strconv"
20252-	"strings"
20253-	"sync"
20254-	"sync/atomic"
20255-	"unsafe"
20256-
20257-	"golang.org/x/sync/errgroup"
20258-	"golang.org/x/tools/go/packages"
20259-	"golang.org/x/tools/go/types/objectpath"
20260-	"golang.org/x/tools/gopls/internal/lsp/protocol"
20261-	"golang.org/x/tools/gopls/internal/lsp/source"
20262-	"golang.org/x/tools/gopls/internal/lsp/source/methodsets"
20263-	"golang.org/x/tools/gopls/internal/lsp/source/xrefs"
20264-	"golang.org/x/tools/gopls/internal/span"
20265-	"golang.org/x/tools/internal/bug"
20266-	"golang.org/x/tools/internal/event"
20267-	"golang.org/x/tools/internal/event/tag"
20268-	"golang.org/x/tools/internal/gocommand"
20269-	"golang.org/x/tools/internal/memoize"
20270-	"golang.org/x/tools/internal/packagesinternal"
20271-	"golang.org/x/tools/internal/persistent"
20272-	"golang.org/x/tools/internal/typesinternal"
20273-)
20274-
20275-type snapshot struct {
20276-	sequenceID uint64
20277-	globalID   source.GlobalSnapshotID
20278-
20279-	// TODO(rfindley): the snapshot holding a reference to the view poses
20280-	// lifecycle problems: a view may be shut down and waiting for work
20281-	// associated with this snapshot to complete. While most accesses of the view
20282-	// are benign (options or workspace information), this is not formalized and
20283-	// it is wrong for the snapshot to use a shutdown view.
20284-	//
20285-	// Fix this by passing options and workspace information to the snapshot,
20286-	// both of which should be immutable for the snapshot.
20287-	view *View
20288-
20289-	cancel        func()
20290-	backgroundCtx context.Context
20291-
20292-	store *memoize.Store // cache of handles shared by all snapshots
20293-
20294-	refcount    sync.WaitGroup // number of references
20295-	destroyedBy *string        // atomically set to non-nil in Destroy once refcount = 0
20296-
20297-	// initialized reports whether the snapshot has been initialized. Concurrent
20298-	// initialization is guarded by the view.initializationSema. Each snapshot is
20299-	// initialized at most once: concurrent initialization is guarded by
20300-	// view.initializationSema.
20301-	initialized bool
20302-	// initializedErr holds the last error resulting from initialization. If
20303-	// initialization fails, we only retry when the the workspace modules change,
20304-	// to avoid too many go/packages calls.
20305-	initializedErr *source.CriticalError
20306-
20307-	// mu guards all of the maps in the snapshot, as well as the builtin URI.
20308-	mu sync.Mutex
20309-
20310-	// builtin pins the AST and package for builtin.go in memory.
20311-	builtin span.URI
20312-
20313-	// meta holds loaded metadata.
20314-	//
20315-	// meta is guarded by mu, but the metadataGraph itself is immutable.
20316-	// TODO(rfindley): in many places we hold mu while operating on meta, even
20317-	// though we only need to hold mu while reading the pointer.
20318-	meta *metadataGraph
20319-
20320-	// files maps file URIs to their corresponding FileHandles.
20321-	// It may invalidated when a file's content changes.
20322-	files filesMap
20323-
20324-	// parseCache holds an LRU cache of recently parsed files.
20325-	parseCache *parseCache
20326-
20327-	// symbolizeHandles maps each file URI to a handle for the future
20328-	// result of computing the symbols declared in that file.
20329-	symbolizeHandles *persistent.Map // from span.URI to *memoize.Promise[symbolizeResult]
20330-
20331-	// packages maps a packageKey to a *packageHandle.
20332-	// It may be invalidated when a file's content changes.
20333-	//
20334-	// Invariants to preserve:
20335-	//  - packages.Get(id).meta == meta.metadata[id] for all ids
20336-	//  - if a package is in packages, then all of its dependencies should also
20337-	//    be in packages, unless there is a missing import
20338-	packages *persistent.Map // from packageID to *packageHandle
20339-
20340-	// activePackages maps a package ID to a memoized active package, or nil if
20341-	// the package is known not to be open.
20342-	//
20343-	// IDs not contained in the map are not known to be open or not open.
20344-	activePackages *persistent.Map // from packageID to *Package
20345-
20346-	// analyses maps an analysisKey (which identifies a package
20347-	// and a set of analyzers) to the handle for the future result
20348-	// of loading the package and analyzing it.
20349-	analyses *persistent.Map // from analysisKey to analysisPromise
20350-
20351-	// workspacePackages contains the workspace's packages, which are loaded
20352-	// when the view is created.
20353-	workspacePackages map[PackageID]PackagePath
20354-
20355-	// shouldLoad tracks packages that need to be reloaded, mapping a PackageID
20356-	// to the package paths that should be used to reload it
20357-	//
20358-	// When we try to load a package, we clear it from the shouldLoad map
20359-	// regardless of whether the load succeeded, to prevent endless loads.
20360-	shouldLoad map[PackageID][]PackagePath
20361-
20362-	// unloadableFiles keeps track of files that we've failed to load.
20363-	unloadableFiles map[span.URI]struct{}
20364-
20365-	// TODO(rfindley): rename the handles below to "promises". A promise is
20366-	// different from a handle (we mutate the package handle.)
20367-
20368-	// parseModHandles keeps track of any parseModHandles for the snapshot.
20369-	// The handles need not refer to only the view's go.mod file.
20370-	parseModHandles *persistent.Map // from span.URI to *memoize.Promise[parseModResult]
20371-
20372-	// parseWorkHandles keeps track of any parseWorkHandles for the snapshot.
20373-	// The handles need not refer to only the view's go.work file.
20374-	parseWorkHandles *persistent.Map // from span.URI to *memoize.Promise[parseWorkResult]
20375-
20376-	// Preserve go.mod-related handles to avoid garbage-collecting the results
20377-	// of various calls to the go command. The handles need not refer to only
20378-	// the view's go.mod file.
20379-	modTidyHandles *persistent.Map // from span.URI to *memoize.Promise[modTidyResult]
20380-	modWhyHandles  *persistent.Map // from span.URI to *memoize.Promise[modWhyResult]
20381-	modVulnHandles *persistent.Map // from span.URI to *memoize.Promise[modVulnResult]
20382-
20383-	// knownSubdirs is the set of subdirectories in the workspace, used to
20384-	// create glob patterns for file watching.
20385-	knownSubdirs             knownDirsSet
20386-	knownSubdirsPatternCache string
20387-	// unprocessedSubdirChanges are any changes that might affect the set of
20388-	// subdirectories in the workspace. They are not reflected to knownSubdirs
20389-	// during the snapshot cloning step as it can slow down cloning.
20390-	unprocessedSubdirChanges []*fileChange
20391-
20392-	// workspaceModFiles holds the set of mod files active in this snapshot.
20393-	//
20394-	// This is either empty, a single entry for the workspace go.mod file, or the
20395-	// set of mod files used by the workspace go.work file.
20396-	//
20397-	// This set is immutable inside the snapshot, and therefore is not guarded by mu.
20398-	workspaceModFiles    map[span.URI]struct{}
20399-	workspaceModFilesErr error // error encountered computing workspaceModFiles
20400-}
20401-
20402-var globalSnapshotID uint64
20403-
20404-func nextSnapshotID() source.GlobalSnapshotID {
20405-	return source.GlobalSnapshotID(atomic.AddUint64(&globalSnapshotID, 1))
20406-}
20407-
20408-var _ memoize.RefCounted = (*snapshot)(nil) // snapshots are reference-counted
20409-
20410-// Acquire prevents the snapshot from being destroyed until the returned function is called.
20411-//
20412-// (s.Acquire().release() could instead be expressed as a pair of
20413-// method calls s.IncRef(); s.DecRef(). The latter has the advantage
20414-// that the DecRefs are fungible and don't require holding anything in
20415-// addition to the refcounted object s, but paradoxically that is also
20416-// an advantage of the current approach, which forces the caller to
20417-// consider the release function at every stage, making a reference
20418-// leak more obvious.)
20419-func (s *snapshot) Acquire() func() {
20420-	type uP = unsafe.Pointer
20421-	if destroyedBy := atomic.LoadPointer((*uP)(uP(&s.destroyedBy))); destroyedBy != nil {
20422-		log.Panicf("%d: acquire() after Destroy(%q)", s.globalID, *(*string)(destroyedBy))
20423-	}
20424-	s.refcount.Add(1)
20425-	return s.refcount.Done
20426-}
20427-
20428-func (s *snapshot) awaitPromise(ctx context.Context, p *memoize.Promise) (interface{}, error) {
20429-	return p.Get(ctx, s)
20430-}
20431-
20432-// destroy waits for all leases on the snapshot to expire then releases
20433-// any resources (reference counts and files) associated with it.
20434-// Snapshots being destroyed can be awaited using v.destroyWG.
20435-//
20436-// TODO(adonovan): move this logic into the release function returned
20437-// by Acquire when the reference count becomes zero. (This would cost
20438-// us the destroyedBy debug info, unless we add it to the signature of
20439-// memoize.RefCounted.Acquire.)
20440-//
20441-// The destroyedBy argument is used for debugging.
20442-//
20443-// v.snapshotMu must be held while calling this function, in order to preserve
20444-// the invariants described by the the docstring for v.snapshot.
20445-func (v *View) destroy(s *snapshot, destroyedBy string) {
20446-	v.snapshotWG.Add(1)
20447-	go func() {
20448-		defer v.snapshotWG.Done()
20449-		s.destroy(destroyedBy)
20450-	}()
20451-}
20452-
20453-func (s *snapshot) destroy(destroyedBy string) {
20454-	// Wait for all leases to end before commencing destruction.
20455-	s.refcount.Wait()
20456-
20457-	// Report bad state as a debugging aid.
20458-	// Not foolproof: another thread could acquire() at this moment.
20459-	type uP = unsafe.Pointer // looking forward to generics...
20460-	if old := atomic.SwapPointer((*uP)(uP(&s.destroyedBy)), uP(&destroyedBy)); old != nil {
20461-		log.Panicf("%d: Destroy(%q) after Destroy(%q)", s.globalID, destroyedBy, *(*string)(old))
20462-	}
20463-
20464-	s.packages.Destroy()
20465-	s.activePackages.Destroy()
20466-	s.analyses.Destroy()
20467-	s.files.Destroy()
20468-	s.knownSubdirs.Destroy()
20469-	s.symbolizeHandles.Destroy()
20470-	s.parseModHandles.Destroy()
20471-	s.parseWorkHandles.Destroy()
20472-	s.modTidyHandles.Destroy()
20473-	s.modVulnHandles.Destroy()
20474-	s.modWhyHandles.Destroy()
20475-}
20476-
20477-func (s *snapshot) SequenceID() uint64 {
20478-	return s.sequenceID
20479-}
20480-
20481-func (s *snapshot) GlobalID() source.GlobalSnapshotID {
20482-	return s.globalID
20483-}
20484-
20485-func (s *snapshot) View() source.View {
20486-	return s.view
20487-}
20488-
20489-func (s *snapshot) BackgroundContext() context.Context {
20490-	return s.backgroundCtx
20491-}
20492-
20493-func (s *snapshot) ModFiles() []span.URI {
20494-	var uris []span.URI
20495-	for modURI := range s.workspaceModFiles {
20496-		uris = append(uris, modURI)
20497-	}
20498-	return uris
20499-}
20500-
20501-func (s *snapshot) WorkFile() span.URI {
20502-	return s.view.effectiveGOWORK()
20503-}
20504-
20505-func (s *snapshot) Templates() map[span.URI]source.FileHandle {
20506-	s.mu.Lock()
20507-	defer s.mu.Unlock()
20508-
20509-	tmpls := map[span.URI]source.FileHandle{}
20510-	s.files.Range(func(k span.URI, fh source.FileHandle) {
20511-		if s.view.FileKind(fh) == source.Tmpl {
20512-			tmpls[k] = fh
20513-		}
20514-	})
20515-	return tmpls
20516-}
20517-
20518-func (s *snapshot) ValidBuildConfiguration() bool {
20519-	// Since we only really understand the `go` command, if the user has a
20520-	// different GOPACKAGESDRIVER, assume that their configuration is valid.
20521-	if s.view.hasGopackagesDriver {
20522-		return true
20523-	}
20524-	// Check if the user is working within a module or if we have found
20525-	// multiple modules in the workspace.
20526-	if len(s.workspaceModFiles) > 0 {
20527-		return true
20528-	}
20529-	// The user may have a multiple directories in their GOPATH.
20530-	// Check if the workspace is within any of them.
20531-	// TODO(rfindley): this should probably be subject to "if GO111MODULES = off {...}".
20532-	for _, gp := range filepath.SplitList(s.view.gopath) {
20533-		if source.InDir(filepath.Join(gp, "src"), s.view.folder.Filename()) {
20534-			return true
20535-		}
20536-	}
20537-	return false
20538-}
20539-
20540-// moduleMode reports whether the current snapshot uses Go modules.
20541-//
20542-// From https://go.dev/ref/mod, module mode is active if either of the
20543-// following hold:
20544-//   - GO111MODULE=on
20545-//   - GO111MODULE=auto and we are inside a module or have a GOWORK value.
20546-//
20547-// Additionally, this method returns false if GOPACKAGESDRIVER is set.
20548-//
20549-// TODO(rfindley): use this more widely.
20550-func (s *snapshot) moduleMode() bool {
20551-	// Since we only really understand the `go` command, if the user has a
20552-	// different GOPACKAGESDRIVER, assume that their configuration is valid.
20553-	if s.view.hasGopackagesDriver {
20554-		return false
20555-	}
20556-
20557-	switch s.view.effectiveGO111MODULE() {
20558-	case on:
20559-		return true
20560-	case off:
20561-		return false
20562-	default:
20563-		return len(s.workspaceModFiles) > 0 || s.view.gowork != ""
20564-	}
20565-}
20566-
20567-// workspaceMode describes the way in which the snapshot's workspace should
20568-// be loaded.
20569-//
20570-// TODO(rfindley): remove this, in favor of specific methods.
20571-func (s *snapshot) workspaceMode() workspaceMode {
20572-	var mode workspaceMode
20573-
20574-	// If the view has an invalid configuration, don't build the workspace
20575-	// module.
20576-	validBuildConfiguration := s.ValidBuildConfiguration()
20577-	if !validBuildConfiguration {
20578-		return mode
20579-	}
20580-	// If the view is not in a module and contains no modules, but still has a
20581-	// valid workspace configuration, do not create the workspace module.
20582-	// It could be using GOPATH or a different build system entirely.
20583-	if len(s.workspaceModFiles) == 0 && validBuildConfiguration {
20584-		return mode
20585-	}
20586-	mode |= moduleMode
20587-	options := s.view.Options()
20588-	if options.TempModfile {
20589-		mode |= tempModfile
20590-	}
20591-	return mode
20592-}
20593-
20594-// config returns the configuration used for the snapshot's interaction with
20595-// the go/packages API. It uses the given working directory.
20596-//
20597-// TODO(rstambler): go/packages requires that we do not provide overlays for
20598-// multiple modules in on config, so buildOverlay needs to filter overlays by
20599-// module.
20600-func (s *snapshot) config(ctx context.Context, inv *gocommand.Invocation) *packages.Config {
20601-	s.view.optionsMu.Lock()
20602-	verboseOutput := s.view.options.VerboseOutput
20603-	s.view.optionsMu.Unlock()
20604-
20605-	cfg := &packages.Config{
20606-		Context:    ctx,
20607-		Dir:        inv.WorkingDir,
20608-		Env:        inv.Env,
20609-		BuildFlags: inv.BuildFlags,
20610-		Mode: packages.NeedName |
20611-			packages.NeedFiles |
20612-			packages.NeedCompiledGoFiles |
20613-			packages.NeedImports |
20614-			packages.NeedDeps |
20615-			packages.NeedTypesSizes |
20616-			packages.NeedModule |
20617-			packages.NeedEmbedFiles |
20618-			packages.LoadMode(packagesinternal.DepsErrors) |
20619-			packages.LoadMode(packagesinternal.ForTest),
20620-		Fset:    nil, // we do our own parsing
20621-		Overlay: s.buildOverlay(),
20622-		ParseFile: func(*token.FileSet, string, []byte) (*ast.File, error) {
20623-			panic("go/packages must not be used to parse files")
20624-		},
20625-		Logf: func(format string, args ...interface{}) {
20626-			if verboseOutput {
20627-				event.Log(ctx, fmt.Sprintf(format, args...))
20628-			}
20629-		},
20630-		Tests: true,
20631-	}
20632-	packagesinternal.SetModFile(cfg, inv.ModFile)
20633-	packagesinternal.SetModFlag(cfg, inv.ModFlag)
20634-	// We want to type check cgo code if go/types supports it.
20635-	if typesinternal.SetUsesCgo(&types.Config{}) {
20636-		cfg.Mode |= packages.LoadMode(packagesinternal.TypecheckCgo)
20637-	}
20638-	packagesinternal.SetGoCmdRunner(cfg, s.view.gocmdRunner)
20639-	return cfg
20640-}
20641-
20642-func (s *snapshot) RunGoCommandDirect(ctx context.Context, mode source.InvocationFlags, inv *gocommand.Invocation) (*bytes.Buffer, error) {
20643-	_, inv, cleanup, err := s.goCommandInvocation(ctx, mode, inv)
20644-	if err != nil {
20645-		return nil, err
20646-	}
20647-	defer cleanup()
20648-
20649-	return s.view.gocmdRunner.Run(ctx, *inv)
20650-}
20651-
20652-func (s *snapshot) RunGoCommandPiped(ctx context.Context, mode source.InvocationFlags, inv *gocommand.Invocation, stdout, stderr io.Writer) error {
20653-	_, inv, cleanup, err := s.goCommandInvocation(ctx, mode, inv)
20654-	if err != nil {
20655-		return err
20656-	}
20657-	defer cleanup()
20658-	return s.view.gocmdRunner.RunPiped(ctx, *inv, stdout, stderr)
20659-}
20660-
20661-func (s *snapshot) RunGoCommands(ctx context.Context, allowNetwork bool, wd string, run func(invoke func(...string) (*bytes.Buffer, error)) error) (bool, []byte, []byte, error) {
20662-	var flags source.InvocationFlags
20663-	if s.workspaceMode()&tempModfile != 0 {
20664-		flags = source.WriteTemporaryModFile
20665-	} else {
20666-		flags = source.Normal
20667-	}
20668-	if allowNetwork {
20669-		flags |= source.AllowNetwork
20670-	}
20671-	tmpURI, inv, cleanup, err := s.goCommandInvocation(ctx, flags, &gocommand.Invocation{WorkingDir: wd})
20672-	if err != nil {
20673-		return false, nil, nil, err
20674-	}
20675-	defer cleanup()
20676-	invoke := func(args ...string) (*bytes.Buffer, error) {
20677-		inv.Verb = args[0]
20678-		inv.Args = args[1:]
20679-		return s.view.gocmdRunner.Run(ctx, *inv)
20680-	}
20681-	if err := run(invoke); err != nil {
20682-		return false, nil, nil, err
20683-	}
20684-	if flags.Mode() != source.WriteTemporaryModFile {
20685-		return false, nil, nil, nil
20686-	}
20687-	var modBytes, sumBytes []byte
20688-	modBytes, err = ioutil.ReadFile(tmpURI.Filename())
20689-	if err != nil && !os.IsNotExist(err) {
20690-		return false, nil, nil, err
20691-	}
20692-	sumBytes, err = ioutil.ReadFile(strings.TrimSuffix(tmpURI.Filename(), ".mod") + ".sum")
20693-	if err != nil && !os.IsNotExist(err) {
20694-		return false, nil, nil, err
20695-	}
20696-	return true, modBytes, sumBytes, nil
20697-}
20698-
20699-// goCommandInvocation populates inv with configuration for running go commands on the snapshot.
20700-//
20701-// TODO(rfindley): refactor this function to compose the required configuration
20702-// explicitly, rather than implicitly deriving it from flags and inv.
20703-//
20704-// TODO(adonovan): simplify cleanup mechanism. It's hard to see, but
20705-// it used only after call to tempModFile. Clarify that it is only
20706-// non-nil on success.
20707-func (s *snapshot) goCommandInvocation(ctx context.Context, flags source.InvocationFlags, inv *gocommand.Invocation) (tmpURI span.URI, updatedInv *gocommand.Invocation, cleanup func(), err error) {
20708-	s.view.optionsMu.Lock()
20709-	allowModfileModificationOption := s.view.options.AllowModfileModifications
20710-	allowNetworkOption := s.view.options.AllowImplicitNetworkAccess
20711-
20712-	// TODO(rfindley): this is very hard to follow, and may not even be doing the
20713-	// right thing: should inv.Env really trample view.options? Do we ever invoke
20714-	// this with a non-empty inv.Env?
20715-	//
20716-	// We should refactor to make it clearer that the correct env is being used.
20717-	inv.Env = append(append(append(os.Environ(), s.view.options.EnvSlice()...), inv.Env...), "GO111MODULE="+s.view.GO111MODULE())
20718-	inv.BuildFlags = append([]string{}, s.view.options.BuildFlags...)
20719-	s.view.optionsMu.Unlock()
20720-	cleanup = func() {} // fallback
20721-
20722-	// All logic below is for module mode.
20723-	if s.workspaceMode()&moduleMode == 0 {
20724-		return "", inv, cleanup, nil
20725-	}
20726-
20727-	mode, allowNetwork := flags.Mode(), flags.AllowNetwork()
20728-	if !allowNetwork && !allowNetworkOption {
20729-		inv.Env = append(inv.Env, "GOPROXY=off")
20730-	}
20731-
20732-	// What follows is rather complicated logic for how to actually run the go
20733-	// command. A word of warning: this is the result of various incremental
20734-	// features added to gopls, and varying behavior of the Go command across Go
20735-	// versions. It can surely be cleaned up significantly, but tread carefully.
20736-	//
20737-	// Roughly speaking we need to resolve four things:
20738-	//  - the working directory.
20739-	//  - the -mod flag
20740-	//  - the -modfile flag
20741-	//
20742-	// These are dependent on a number of factors: whether we need to run in a
20743-	// synthetic workspace, whether flags are supported at the current go
20744-	// version, and what we're actually trying to achieve (the
20745-	// source.InvocationFlags).
20746-
20747-	var modURI span.URI
20748-	// Select the module context to use.
20749-	// If we're type checking, we need to use the workspace context, meaning
20750-	// the main (workspace) module. Otherwise, we should use the module for
20751-	// the passed-in working dir.
20752-	if mode == source.LoadWorkspace {
20753-		if s.view.effectiveGOWORK() == "" && s.view.gomod != "" {
20754-			modURI = s.view.gomod
20755-		}
20756-	} else {
20757-		modURI = s.GoModForFile(span.URIFromPath(inv.WorkingDir))
20758-	}
20759-
20760-	var modContent []byte
20761-	if modURI != "" {
20762-		modFH, err := s.GetFile(ctx, modURI)
20763-		if err != nil {
20764-			return "", nil, cleanup, err
20765-		}
20766-		modContent, err = modFH.Read()
20767-		if err != nil {
20768-			return "", nil, cleanup, err
20769-		}
20770-	}
20771-
20772-	// TODO(rfindley): in the case of go.work mode, modURI is empty and we fall
20773-	// back on the default behavior of vendorEnabled with an empty modURI. Figure
20774-	// out what is correct here and implement it explicitly.
20775-	vendorEnabled, err := s.vendorEnabled(ctx, modURI, modContent)
20776-	if err != nil {
20777-		return "", nil, cleanup, err
20778-	}
20779-
20780-	const mutableModFlag = "mod"
20781-	// If the mod flag isn't set, populate it based on the mode and workspace.
20782-	// TODO(rfindley): this doesn't make sense if we're not in module mode
20783-	if inv.ModFlag == "" {
20784-		switch mode {
20785-		case source.LoadWorkspace, source.Normal:
20786-			if vendorEnabled {
20787-				inv.ModFlag = "vendor"
20788-			} else if !allowModfileModificationOption {
20789-				inv.ModFlag = "readonly"
20790-			} else {
20791-				inv.ModFlag = mutableModFlag
20792-			}
20793-		case source.WriteTemporaryModFile:
20794-			inv.ModFlag = mutableModFlag
20795-			// -mod must be readonly when using go.work files - see issue #48941
20796-			inv.Env = append(inv.Env, "GOWORK=off")
20797-		}
20798-	}
20799-
20800-	// Only use a temp mod file if the modfile can actually be mutated.
20801-	needTempMod := inv.ModFlag == mutableModFlag
20802-	useTempMod := s.workspaceMode()&tempModfile != 0
20803-	if needTempMod && !useTempMod {
20804-		return "", nil, cleanup, source.ErrTmpModfileUnsupported
20805-	}
20806-
20807-	// We should use -modfile if:
20808-	//  - the workspace mode supports it
20809-	//  - we're using a go.work file on go1.18+, or we need a temp mod file (for
20810-	//    example, if running go mod tidy in a go.work workspace)
20811-	//
20812-	// TODO(rfindley): this is very hard to follow. Refactor.
20813-	if !needTempMod && s.view.gowork != "" {
20814-		// Since we're running in the workspace root, the go command will resolve GOWORK automatically.
20815-	} else if useTempMod {
20816-		if modURI == "" {
20817-			return "", nil, cleanup, fmt.Errorf("no go.mod file found in %s", inv.WorkingDir)
20818-		}
20819-		modFH, err := s.GetFile(ctx, modURI)
20820-		if err != nil {
20821-			return "", nil, cleanup, err
20822-		}
20823-		// Use the go.sum if it happens to be available.
20824-		gosum := s.goSum(ctx, modURI)
20825-		tmpURI, cleanup, err = tempModFile(modFH, gosum)
20826-		if err != nil {
20827-			return "", nil, cleanup, err
20828-		}
20829-		inv.ModFile = tmpURI.Filename()
20830-	}
20831-
20832-	return tmpURI, inv, cleanup, nil
20833-}
20834-
20835-func (s *snapshot) buildOverlay() map[string][]byte {
20836-	s.mu.Lock()
20837-	defer s.mu.Unlock()
20838-
20839-	overlays := make(map[string][]byte)
20840-	s.files.Range(func(uri span.URI, fh source.FileHandle) {
20841-		overlay, ok := fh.(*Overlay)
20842-		if !ok {
20843-			return
20844-		}
20845-		if overlay.saved {
20846-			return
20847-		}
20848-		// TODO(rstambler): Make sure not to send overlays outside of the current view.
20849-		overlays[uri.Filename()] = overlay.content
20850-	})
20851-	return overlays
20852-}
20853-
20854-// Package data kinds, identifying various package data that may be stored in
20855-// the file cache.
20856-const (
20857-	xrefsKind       = "xrefs"
20858-	methodSetsKind  = "methodsets"
20859-	exportDataKind  = "export"
20860-	diagnosticsKind = "diagnostics"
20861-)
20862-
20863-func (s *snapshot) PackageDiagnostics(ctx context.Context, ids ...PackageID) (map[span.URI][]*source.Diagnostic, error) {
20864-	// TODO(rfindley): opt: avoid unnecessary encode->decode after type-checking.
20865-	data, err := s.getPackageData(ctx, diagnosticsKind, ids, func(p *syntaxPackage) []byte {
20866-		return encodeDiagnostics(p.diagnostics)
20867-	})
20868-	perFile := make(map[span.URI][]*source.Diagnostic)
20869-	for _, data := range data {
20870-		if data != nil {
20871-			for _, diag := range data.m.Diagnostics {
20872-				perFile[diag.URI] = append(perFile[diag.URI], diag)
20873-			}
20874-			diags := decodeDiagnostics(data.data)
20875-			for _, diag := range diags {
20876-				perFile[diag.URI] = append(perFile[diag.URI], diag)
20877-			}
20878-		}
20879-	}
20880-	return perFile, err
20881-}
20882-
20883-func (s *snapshot) References(ctx context.Context, ids ...PackageID) ([]source.XrefIndex, error) {
20884-	data, err := s.getPackageData(ctx, xrefsKind, ids, func(p *syntaxPackage) []byte { return p.xrefs })
20885-	indexes := make([]source.XrefIndex, len(ids))
20886-	for i, data := range data {
20887-		if data != nil {
20888-			indexes[i] = XrefIndex{m: data.m, data: data.data}
20889-		}
20890-	}
20891-	return indexes, err
20892-}
20893-
20894-// An XrefIndex is a helper for looking up a package in a given package.
20895-type XrefIndex struct {
20896-	m    *source.Metadata
20897-	data []byte
20898-}
20899-
20900-func (index XrefIndex) Lookup(targets map[PackagePath]map[objectpath.Path]struct{}) []protocol.Location {
20901-	return xrefs.Lookup(index.m, index.data, targets)
20902-}
20903-
20904-func (s *snapshot) MethodSets(ctx context.Context, ids ...PackageID) ([]*methodsets.Index, error) {
20905-	// TODO(rfindley): opt: avoid unnecessary encode->decode after type-checking.
20906-	data, err := s.getPackageData(ctx, methodSetsKind, ids, func(p *syntaxPackage) []byte {
20907-		return p.methodsets.Encode()
20908-	})
20909-	indexes := make([]*methodsets.Index, len(ids))
20910-	for i, data := range data {
20911-		if data != nil {
20912-			indexes[i] = methodsets.Decode(data.data)
20913-		} else if ids[i] == "unsafe" {
20914-			indexes[i] = &methodsets.Index{}
20915-		} else {
20916-			panic(fmt.Sprintf("nil data for %s", ids[i]))
20917-		}
20918-	}
20919-	return indexes, err
20920-}
20921-
20922-func (s *snapshot) MetadataForFile(ctx context.Context, uri span.URI) ([]*source.Metadata, error) {
20923-	s.mu.Lock()
20924-
20925-	// Start with the set of package associations derived from the last load.
20926-	ids := s.meta.ids[uri]
20927-
20928-	shouldLoad := false // whether any packages containing uri are marked 'shouldLoad'
20929-	for _, id := range ids {
20930-		if len(s.shouldLoad[id]) > 0 {
20931-			shouldLoad = true
20932-		}
20933-	}
20934-
20935-	// Check if uri is known to be unloadable.
20936-	_, unloadable := s.unloadableFiles[uri]
20937-
20938-	s.mu.Unlock()
20939-
20940-	// Reload if loading is likely to improve the package associations for uri:
20941-	//  - uri is not contained in any valid packages
20942-	//  - ...or one of the packages containing uri is marked 'shouldLoad'
20943-	//  - ...but uri is not unloadable
20944-	if (shouldLoad || len(ids) == 0) && !unloadable {
20945-		scope := fileLoadScope(uri)
20946-		err := s.load(ctx, false, scope)
20947-
20948-		// Guard against failed loads due to context cancellation.
20949-		//
20950-		// Return the context error here as the current operation is no longer
20951-		// valid.
20952-		if ctxErr := ctx.Err(); ctxErr != nil {
20953-			return nil, ctxErr
20954-		}
20955-
20956-		// We must clear scopes after loading.
20957-		//
20958-		// TODO(rfindley): unlike reloadWorkspace, this is simply marking loaded
20959-		// packages as loaded. We could do this from snapshot.load and avoid
20960-		// raciness.
20961-		s.clearShouldLoad(scope)
20962-
20963-		// Don't return an error here, as we may still return stale IDs.
20964-		// Furthermore, the result of MetadataForFile should be consistent upon
20965-		// subsequent calls, even if the file is marked as unloadable.
20966-		if err != nil && !errors.Is(err, errNoPackages) {
20967-			event.Error(ctx, "MetadataForFile", err)
20968-		}
20969-	}
20970-
20971-	// Retrieve the metadata.
20972-	s.mu.Lock()
20973-	defer s.mu.Unlock()
20974-	ids = s.meta.ids[uri]
20975-	metas := make([]*source.Metadata, len(ids))
20976-	for i, id := range ids {
20977-		metas[i] = s.meta.metadata[id]
20978-		if metas[i] == nil {
20979-			panic("nil metadata")
20980-		}
20981-	}
20982-	// Metadata is only ever added by loading,
20983-	// so if we get here and still have
20984-	// no IDs, uri is unloadable.
20985-	if !unloadable && len(ids) == 0 {
20986-		s.unloadableFiles[uri] = struct{}{}
20987-	}
20988-
20989-	// Sort packages "narrowest" to "widest" (in practice: non-tests before tests).
20990-	sort.Slice(metas, func(i, j int) bool {
20991-		return len(metas[i].CompiledGoFiles) < len(metas[j].CompiledGoFiles)
20992-	})
20993-
20994-	return metas, nil
20995-}
20996-
20997-func (s *snapshot) ReverseDependencies(ctx context.Context, id PackageID, transitive bool) (map[PackageID]*source.Metadata, error) {
20998-	if err := s.awaitLoaded(ctx); err != nil {
20999-		return nil, err
21000-	}
21001-	s.mu.Lock()
21002-	meta := s.meta
21003-	s.mu.Unlock()
21004-
21005-	var rdeps map[PackageID]*source.Metadata
21006-	if transitive {
21007-		rdeps = meta.reverseReflexiveTransitiveClosure(id)
21008-
21009-		// Remove the original package ID from the map.
21010-		// (Callers all want irreflexivity but it's easier
21011-		// to compute reflexively then subtract.)
21012-		delete(rdeps, id)
21013-
21014-	} else {
21015-		// direct reverse dependencies
21016-		rdeps = make(map[PackageID]*source.Metadata)
21017-		for _, rdepID := range meta.importedBy[id] {
21018-			if rdep := meta.metadata[rdepID]; rdep != nil {
21019-				rdeps[rdepID] = rdep
21020-			}
21021-		}
21022-	}
21023-
21024-	return rdeps, nil
21025-}
21026-
21027-func (s *snapshot) workspaceMetadata() (meta []*source.Metadata) {
21028-	s.mu.Lock()
21029-	defer s.mu.Unlock()
21030-
21031-	for id := range s.workspacePackages {
21032-		meta = append(meta, s.meta.metadata[id])
21033-	}
21034-	return meta
21035-}
21036-
21037-// -- Active package tracking --
21038-//
21039-// We say a package is "active" if any of its files are open. After
21040-// type-checking we keep active packages in memory. The activePackages
21041-// peristent map does bookkeeping for the set of active packages.
21042-
21043-// getActivePackage returns a the memoized active package for id, if it exists.
21044-// If id is not active or has not yet been type-checked, it returns nil.
21045-func (s *snapshot) getActivePackage(id PackageID) *Package {
21046-	s.mu.Lock()
21047-	defer s.mu.Unlock()
21048-
21049-	if value, ok := s.activePackages.Get(id); ok {
21050-		return value.(*Package) // possibly nil, if we have already checked this id.
21051-	}
21052-	return nil
21053-}
21054-
21055-// memoizeActivePackage checks if pkg is active, and if so either records it in
21056-// the active packages map or returns the existing memoized active package for id.
21057-//
21058-// The resulting package is non-nil if and only if the specified package is open.
21059-func (s *snapshot) memoizeActivePackage(id PackageID, pkg *Package) (active *Package) {
21060-	s.mu.Lock()
21061-	defer s.mu.Unlock()
21062-
21063-	if value, ok := s.activePackages.Get(id); ok {
21064-		return value.(*Package) // possibly nil, if we have already checked this id.
21065-	}
21066-
21067-	defer func() {
21068-		s.activePackages.Set(id, active, nil) // store the result either way: remember that pkg is not open
21069-	}()
21070-	for _, cgf := range pkg.Metadata().GoFiles {
21071-		if s.isOpenLocked(cgf) {
21072-			return pkg
21073-		}
21074-	}
21075-	for _, cgf := range pkg.Metadata().CompiledGoFiles {
21076-		if s.isOpenLocked(cgf) {
21077-			return pkg
21078-		}
21079-	}
21080-	return nil
21081-}
21082-
21083-func (s *snapshot) resetActivePackagesLocked() {
21084-	s.activePackages.Destroy()
21085-	s.activePackages = persistent.NewMap(packageIDLessInterface)
21086-}
21087-
21088-const fileExtensions = "go,mod,sum,work"
21089-
21090-func (s *snapshot) fileWatchingGlobPatterns(ctx context.Context) map[string]struct{} {
21091-	extensions := fileExtensions
21092-	for _, ext := range s.View().Options().TemplateExtensions {
21093-		extensions += "," + ext
21094-	}
21095-	// Work-around microsoft/vscode#100870 by making sure that we are,
21096-	// at least, watching the user's entire workspace. This will still be
21097-	// applied to every folder in the workspace.
21098-	patterns := map[string]struct{}{
21099-		fmt.Sprintf("**/*.{%s}", extensions): {},
21100-	}
21101-
21102-	// If GOWORK is outside the folder, ensure we are watching it.
21103-	gowork := s.view.effectiveGOWORK()
21104-	if gowork != "" && !source.InDir(s.view.folder.Filename(), gowork.Filename()) {
21105-		patterns[gowork.Filename()] = struct{}{}
21106-	}
21107-
21108-	// Add a pattern for each Go module in the workspace that is not within the view.
21109-	dirs := s.dirs(ctx)
21110-	for _, dir := range dirs {
21111-		dirName := dir.Filename()
21112-
21113-		// If the directory is within the view's folder, we're already watching
21114-		// it with the first pattern above.
21115-		if source.InDir(s.view.folder.Filename(), dirName) {
21116-			continue
21117-		}
21118-		// TODO(rstambler): If microsoft/vscode#3025 is resolved before
21119-		// microsoft/vscode#101042, we will need a work-around for Windows
21120-		// drive letter casing.
21121-		patterns[fmt.Sprintf("%s/**/*.{%s}", dirName, extensions)] = struct{}{}
21122-	}
21123-
21124-	// Some clients do not send notifications for changes to directories that
21125-	// contain Go code (golang/go#42348). To handle this, explicitly watch all
21126-	// of the directories in the workspace. We find them by adding the
21127-	// directories of every file in the snapshot's workspace directories.
21128-	// There may be thousands.
21129-	if pattern := s.getKnownSubdirsPattern(dirs); pattern != "" {
21130-		patterns[pattern] = struct{}{}
21131-	}
21132-
21133-	return patterns
21134-}
21135-
21136-func (s *snapshot) getKnownSubdirsPattern(wsDirs []span.URI) string {
21137-	s.mu.Lock()
21138-	defer s.mu.Unlock()
21139-
21140-	// First, process any pending changes and update the set of known
21141-	// subdirectories.
21142-	// It may change list of known subdirs and therefore invalidate the cache.
21143-	s.applyKnownSubdirsChangesLocked(wsDirs)
21144-
21145-	if s.knownSubdirsPatternCache == "" {
21146-		var builder strings.Builder
21147-		s.knownSubdirs.Range(func(uri span.URI) {
21148-			if builder.Len() == 0 {
21149-				builder.WriteString("{")
21150-			} else {
21151-				builder.WriteString(",")
21152-			}
21153-			builder.WriteString(uri.Filename())
21154-		})
21155-		if builder.Len() > 0 {
21156-			builder.WriteString("}")
21157-			s.knownSubdirsPatternCache = builder.String()
21158-		}
21159-	}
21160-
21161-	return s.knownSubdirsPatternCache
21162-}
21163-
21164-// collectAllKnownSubdirs collects all of the subdirectories within the
21165-// snapshot's workspace directories. None of the workspace directories are
21166-// included.
21167-func (s *snapshot) collectAllKnownSubdirs(ctx context.Context) {
21168-	dirs := s.dirs(ctx)
21169-
21170-	s.mu.Lock()
21171-	defer s.mu.Unlock()
21172-
21173-	s.knownSubdirs.Destroy()
21174-	s.knownSubdirs = newKnownDirsSet()
21175-	s.knownSubdirsPatternCache = ""
21176-	s.files.Range(func(uri span.URI, fh source.FileHandle) {
21177-		s.addKnownSubdirLocked(uri, dirs)
21178-	})
21179-}
21180-
21181-func (s *snapshot) getKnownSubdirs(wsDirs []span.URI) knownDirsSet {
21182-	s.mu.Lock()
21183-	defer s.mu.Unlock()
21184-
21185-	// First, process any pending changes and update the set of known
21186-	// subdirectories.
21187-	s.applyKnownSubdirsChangesLocked(wsDirs)
21188-
21189-	return s.knownSubdirs.Clone()
21190-}
21191-
21192-func (s *snapshot) applyKnownSubdirsChangesLocked(wsDirs []span.URI) {
21193-	for _, c := range s.unprocessedSubdirChanges {
21194-		if c.isUnchanged {
21195-			continue
21196-		}
21197-		if !c.exists {
21198-			s.removeKnownSubdirLocked(c.fileHandle.URI())
21199-		} else {
21200-			s.addKnownSubdirLocked(c.fileHandle.URI(), wsDirs)
21201-		}
21202-	}
21203-	s.unprocessedSubdirChanges = nil
21204-}
21205-
21206-func (s *snapshot) addKnownSubdirLocked(uri span.URI, dirs []span.URI) {
21207-	dir := filepath.Dir(uri.Filename())
21208-	// First check if the directory is already known, because then we can
21209-	// return early.
21210-	if s.knownSubdirs.Contains(span.URIFromPath(dir)) {
21211-		return
21212-	}
21213-	var matched span.URI
21214-	for _, wsDir := range dirs {
21215-		if source.InDir(wsDir.Filename(), dir) {
21216-			matched = wsDir
21217-			break
21218-		}
21219-	}
21220-	// Don't watch any directory outside of the workspace directories.
21221-	if matched == "" {
21222-		return
21223-	}
21224-	for {
21225-		if dir == "" || dir == matched.Filename() {
21226-			break
21227-		}
21228-		uri := span.URIFromPath(dir)
21229-		if s.knownSubdirs.Contains(uri) {
21230-			break
21231-		}
21232-		s.knownSubdirs.Insert(uri)
21233-		dir = filepath.Dir(dir)
21234-		s.knownSubdirsPatternCache = ""
21235-	}
21236-}
21237-
21238-func (s *snapshot) removeKnownSubdirLocked(uri span.URI) {
21239-	dir := filepath.Dir(uri.Filename())
21240-	for dir != "" {
21241-		uri := span.URIFromPath(dir)
21242-		if !s.knownSubdirs.Contains(uri) {
21243-			break
21244-		}
21245-		if info, _ := os.Stat(dir); info == nil {
21246-			s.knownSubdirs.Remove(uri)
21247-			s.knownSubdirsPatternCache = ""
21248-		}
21249-		dir = filepath.Dir(dir)
21250-	}
21251-}
21252-
21253-// knownFilesInDir returns the files known to the given snapshot that are in
21254-// the given directory. It does not respect symlinks.
21255-func (s *snapshot) knownFilesInDir(ctx context.Context, dir span.URI) []span.URI {
21256-	var files []span.URI
21257-	s.mu.Lock()
21258-	defer s.mu.Unlock()
21259-
21260-	s.files.Range(func(uri span.URI, fh source.FileHandle) {
21261-		if source.InDir(dir.Filename(), uri.Filename()) {
21262-			files = append(files, uri)
21263-		}
21264-	})
21265-	return files
21266-}
21267-
21268-func (s *snapshot) ActiveMetadata(ctx context.Context) ([]*source.Metadata, error) {
21269-	if err := s.awaitLoaded(ctx); err != nil {
21270-		return nil, err
21271-	}
21272-	return s.workspaceMetadata(), nil
21273-}
21274-
21275-// Symbols extracts and returns symbol information for every file contained in
21276-// a loaded package. It awaits snapshot loading.
21277-//
21278-// TODO(rfindley): move this to the top of cache/symbols.go
21279-func (s *snapshot) Symbols(ctx context.Context) (map[span.URI][]source.Symbol, error) {
21280-	if err := s.awaitLoaded(ctx); err != nil {
21281-		return nil, err
21282-	}
21283-
21284-	// Build symbols for all loaded Go files.
21285-	s.mu.Lock()
21286-	meta := s.meta
21287-	s.mu.Unlock()
21288-
21289-	goFiles := make(map[span.URI]struct{})
21290-	for _, m := range meta.metadata {
21291-		for _, uri := range m.GoFiles {
21292-			goFiles[uri] = struct{}{}
21293-		}
21294-		for _, uri := range m.CompiledGoFiles {
21295-			goFiles[uri] = struct{}{}
21296-		}
21297-	}
21298-
21299-	// Symbolize them in parallel.
21300-	var (
21301-		group    errgroup.Group
21302-		nprocs   = 2 * runtime.GOMAXPROCS(-1) // symbolize is a mix of I/O and CPU
21303-		resultMu sync.Mutex
21304-		result   = make(map[span.URI][]source.Symbol)
21305-	)
21306-	group.SetLimit(nprocs)
21307-	for uri := range goFiles {
21308-		uri := uri
21309-		group.Go(func() error {
21310-			symbols, err := s.symbolize(ctx, uri)
21311-			if err != nil {
21312-				return err
21313-			}
21314-			resultMu.Lock()
21315-			result[uri] = symbols
21316-			resultMu.Unlock()
21317-			return nil
21318-		})
21319-	}
21320-	// Keep going on errors, but log the first failure.
21321-	// Partial results are better than no symbol results.
21322-	if err := group.Wait(); err != nil {
21323-		event.Error(ctx, "getting snapshot symbols", err)
21324-	}
21325-	return result, nil
21326-}
21327-
21328-func (s *snapshot) AllMetadata(ctx context.Context) ([]*source.Metadata, error) {
21329-	if err := s.awaitLoaded(ctx); err != nil {
21330-		return nil, err
21331-	}
21332-
21333-	s.mu.Lock()
21334-	g := s.meta
21335-	s.mu.Unlock()
21336-
21337-	meta := make([]*source.Metadata, 0, len(g.metadata))
21338-	for _, m := range g.metadata {
21339-		meta = append(meta, m)
21340-	}
21341-	return meta, nil
21342-}
21343-
21344-// TODO(rfindley): clarify that this is only active modules. Or update to just
21345-// use findRootPattern.
21346-func (s *snapshot) GoModForFile(uri span.URI) span.URI {
21347-	return moduleForURI(s.workspaceModFiles, uri)
21348-}
21349-
21350-func moduleForURI(modFiles map[span.URI]struct{}, uri span.URI) span.URI {
21351-	var match span.URI
21352-	for modURI := range modFiles {
21353-		if !source.InDir(span.Dir(modURI).Filename(), uri.Filename()) {
21354-			continue
21355-		}
21356-		if len(modURI) > len(match) {
21357-			match = modURI
21358-		}
21359-	}
21360-	return match
21361-}
21362-
21363-// nearestModFile finds the nearest go.mod file contained in the directory
21364-// containing uri, or a parent of that directory.
21365-//
21366-// The given uri must be a file, not a directory.
21367-func nearestModFile(ctx context.Context, uri span.URI, fs source.FileSource) (span.URI, error) {
21368-	// TODO(rfindley)
21369-	dir := filepath.Dir(uri.Filename())
21370-	mod, err := findRootPattern(ctx, dir, "go.mod", fs)
21371-	if err != nil {
21372-		return "", err
21373-	}
21374-	return span.URIFromPath(mod), nil
21375-}
21376-
21377-func (s *snapshot) Metadata(id PackageID) *source.Metadata {
21378-	s.mu.Lock()
21379-	defer s.mu.Unlock()
21380-	return s.meta.metadata[id]
21381-}
21382-
21383-// clearShouldLoad clears package IDs that no longer need to be reloaded after
21384-// scopes has been loaded.
21385-func (s *snapshot) clearShouldLoad(scopes ...loadScope) {
21386-	s.mu.Lock()
21387-	defer s.mu.Unlock()
21388-
21389-	for _, scope := range scopes {
21390-		switch scope := scope.(type) {
21391-		case packageLoadScope:
21392-			scopePath := PackagePath(scope)
21393-			var toDelete []PackageID
21394-			for id, pkgPaths := range s.shouldLoad {
21395-				for _, pkgPath := range pkgPaths {
21396-					if pkgPath == scopePath {
21397-						toDelete = append(toDelete, id)
21398-					}
21399-				}
21400-			}
21401-			for _, id := range toDelete {
21402-				delete(s.shouldLoad, id)
21403-			}
21404-		case fileLoadScope:
21405-			uri := span.URI(scope)
21406-			ids := s.meta.ids[uri]
21407-			for _, id := range ids {
21408-				delete(s.shouldLoad, id)
21409-			}
21410-		}
21411-	}
21412-}
21413-
21414-// noValidMetadataForURILocked reports whether there is any valid metadata for
21415-// the given URI.
21416-func (s *snapshot) noValidMetadataForURILocked(uri span.URI) bool {
21417-	for _, id := range s.meta.ids[uri] {
21418-		if _, ok := s.meta.metadata[id]; ok {
21419-			return false
21420-		}
21421-	}
21422-	return true
21423-}
21424-
21425-func (s *snapshot) isWorkspacePackage(id PackageID) bool {
21426-	s.mu.Lock()
21427-	defer s.mu.Unlock()
21428-
21429-	_, ok := s.workspacePackages[id]
21430-	return ok
21431-}
21432-
21433-func (s *snapshot) FindFile(uri span.URI) source.FileHandle {
21434-	s.view.markKnown(uri)
21435-
21436-	s.mu.Lock()
21437-	defer s.mu.Unlock()
21438-
21439-	result, _ := s.files.Get(uri)
21440-	return result
21441-}
21442-
21443-// GetFile returns a File for the given URI. If the file is unknown it is added
21444-// to the managed set.
21445-//
21446-// GetFile succeeds even if the file does not exist. A non-nil error return
21447-// indicates some type of internal error, for example if ctx is cancelled.
21448-func (s *snapshot) GetFile(ctx context.Context, uri span.URI) (source.FileHandle, error) {
21449-	s.mu.Lock()
21450-	defer s.mu.Unlock()
21451-
21452-	return lockedSnapshot{s}.GetFile(ctx, uri)
21453-}
21454-
21455-// A lockedSnapshot implements the source.FileSource interface while holding
21456-// the lock for the wrapped snapshot.
21457-type lockedSnapshot struct{ wrapped *snapshot }
21458-
21459-func (s lockedSnapshot) GetFile(ctx context.Context, uri span.URI) (source.FileHandle, error) {
21460-	s.wrapped.view.markKnown(uri)
21461-	if fh, ok := s.wrapped.files.Get(uri); ok {
21462-		return fh, nil
21463-	}
21464-
21465-	fh, err := s.wrapped.view.fs.GetFile(ctx, uri) // read the file
21466-	if err != nil {
21467-		return nil, err
21468-	}
21469-	s.wrapped.files.Set(uri, fh)
21470-	return fh, nil
21471-}
21472-
21473-func (s *snapshot) IsOpen(uri span.URI) bool {
21474-	s.mu.Lock()
21475-	defer s.mu.Unlock()
21476-	return s.isOpenLocked(uri)
21477-
21478-}
21479-
21480-func (s *snapshot) openFiles() []source.FileHandle {
21481-	s.mu.Lock()
21482-	defer s.mu.Unlock()
21483-
21484-	var open []source.FileHandle
21485-	s.files.Range(func(uri span.URI, fh source.FileHandle) {
21486-		if isFileOpen(fh) {
21487-			open = append(open, fh)
21488-		}
21489-	})
21490-	return open
21491-}
21492-
21493-func (s *snapshot) isOpenLocked(uri span.URI) bool {
21494-	fh, _ := s.files.Get(uri)
21495-	return isFileOpen(fh)
21496-}
21497-
21498-func isFileOpen(fh source.FileHandle) bool {
21499-	_, open := fh.(*Overlay)
21500-	return open
21501-}
21502-
21503-func (s *snapshot) awaitLoaded(ctx context.Context) error {
21504-	loadErr := s.awaitLoadedAllErrors(ctx)
21505-
21506-	// TODO(rfindley): eliminate this function as part of simplifying
21507-	// CriticalErrors.
21508-	if loadErr != nil {
21509-		return loadErr.MainError
21510-	}
21511-	return nil
21512-}
21513-
21514-func (s *snapshot) GetCriticalError(ctx context.Context) *source.CriticalError {
21515-	// If we couldn't compute workspace mod files, then the load below is
21516-	// invalid.
21517-	//
21518-	// TODO(rfindley): is this a clear error to present to the user?
21519-	if s.workspaceModFilesErr != nil {
21520-		return &source.CriticalError{MainError: s.workspaceModFilesErr}
21521-	}
21522-
21523-	loadErr := s.awaitLoadedAllErrors(ctx)
21524-	if loadErr != nil && errors.Is(loadErr.MainError, context.Canceled) {
21525-		return nil
21526-	}
21527-
21528-	// Even if packages didn't fail to load, we still may want to show
21529-	// additional warnings.
21530-	if loadErr == nil {
21531-		active, _ := s.ActiveMetadata(ctx)
21532-		if msg := shouldShowAdHocPackagesWarning(s, active); msg != "" {
21533-			return &source.CriticalError{
21534-				MainError: errors.New(msg),
21535-			}
21536-		}
21537-		// Even if workspace packages were returned, there still may be an error
21538-		// with the user's workspace layout. Workspace packages that only have the
21539-		// ID "command-line-arguments" are usually a symptom of a bad workspace
21540-		// configuration.
21541-		//
21542-		// This heuristic is path-dependent: we only get command-line-arguments
21543-		// packages when we've loaded using file scopes, which only occurs
21544-		// on-demand or via orphaned file reloading.
21545-		//
21546-		// TODO(rfindley): re-evaluate this heuristic.
21547-		if containsCommandLineArguments(active) {
21548-			err, diags := s.workspaceLayoutError(ctx)
21549-			if err != nil {
21550-				if ctx.Err() != nil {
21551-					return nil // see the API documentation for source.Snapshot
21552-				}
21553-				return &source.CriticalError{
21554-					MainError:   err,
21555-					Diagnostics: diags,
21556-				}
21557-			}
21558-		}
21559-		return nil
21560-	}
21561-
21562-	if errMsg := loadErr.MainError.Error(); strings.Contains(errMsg, "cannot find main module") || strings.Contains(errMsg, "go.mod file not found") {
21563-		err, diags := s.workspaceLayoutError(ctx)
21564-		if err != nil {
21565-			if ctx.Err() != nil {
21566-				return nil // see the API documentation for source.Snapshot
21567-			}
21568-			return &source.CriticalError{
21569-				MainError:   err,
21570-				Diagnostics: diags,
21571-			}
21572-		}
21573-	}
21574-	return loadErr
21575-}
21576-
21577-// A portion of this text is expected by TestBrokenWorkspace_OutsideModule.
21578-const adHocPackagesWarning = `You are outside of a module and outside of $GOPATH/src.
21579-If you are using modules, please open your editor to a directory in your module.
21580-If you believe this warning is incorrect, please file an issue: https://github.com/golang/go/issues/new.`
21581-
21582-func shouldShowAdHocPackagesWarning(snapshot source.Snapshot, active []*source.Metadata) string {
21583-	if !snapshot.ValidBuildConfiguration() {
21584-		for _, m := range active {
21585-			// A blank entry in DepsByImpPath
21586-			// indicates a missing dependency.
21587-			for _, importID := range m.DepsByImpPath {
21588-				if importID == "" {
21589-					return adHocPackagesWarning
21590-				}
21591-			}
21592-		}
21593-	}
21594-	return ""
21595-}
21596-
21597-func containsCommandLineArguments(metas []*source.Metadata) bool {
21598-	for _, m := range metas {
21599-		if source.IsCommandLineArguments(m.ID) {
21600-			return true
21601-		}
21602-	}
21603-	return false
21604-}
21605-
21606-func (s *snapshot) awaitLoadedAllErrors(ctx context.Context) *source.CriticalError {
21607-	// Do not return results until the snapshot's view has been initialized.
21608-	s.AwaitInitialized(ctx)
21609-
21610-	// TODO(rfindley): Should we be more careful about returning the
21611-	// initialization error? Is it possible for the initialization error to be
21612-	// corrected without a successful reinitialization?
21613-	if err := s.getInitializationError(); err != nil {
21614-		return err
21615-	}
21616-
21617-	// TODO(rfindley): revisit this handling. Calling reloadWorkspace with a
21618-	// cancelled context should have the same effect, so this preemptive handling
21619-	// should not be necessary.
21620-	//
21621-	// Also: GetCriticalError ignores context cancellation errors. Should we be
21622-	// returning nil here?
21623-	if ctx.Err() != nil {
21624-		return &source.CriticalError{MainError: ctx.Err()}
21625-	}
21626-
21627-	// TODO(rfindley): reloading is not idempotent: if we try to reload or load
21628-	// orphaned files below and fail, we won't try again. For that reason, we
21629-	// could get different results from subsequent calls to this function, which
21630-	// may cause critical errors to be suppressed.
21631-
21632-	if err := s.reloadWorkspace(ctx); err != nil {
21633-		diags := s.extractGoCommandErrors(ctx, err)
21634-		return &source.CriticalError{
21635-			MainError:   err,
21636-			Diagnostics: diags,
21637-		}
21638-	}
21639-
21640-	if err := s.reloadOrphanedOpenFiles(ctx); err != nil {
21641-		diags := s.extractGoCommandErrors(ctx, err)
21642-		return &source.CriticalError{
21643-			MainError:   err,
21644-			Diagnostics: diags,
21645-		}
21646-	}
21647-	return nil
21648-}
21649-
21650-func (s *snapshot) getInitializationError() *source.CriticalError {
21651-	s.mu.Lock()
21652-	defer s.mu.Unlock()
21653-
21654-	return s.initializedErr
21655-}
21656-
21657-func (s *snapshot) AwaitInitialized(ctx context.Context) {
21658-	select {
21659-	case <-ctx.Done():
21660-		return
21661-	case <-s.view.initialWorkspaceLoad:
21662-	}
21663-	// We typically prefer to run something as intensive as the IWL without
21664-	// blocking. I'm not sure if there is a way to do that here.
21665-	s.initialize(ctx, false)
21666-}
21667-
21668-// reloadWorkspace reloads the metadata for all invalidated workspace packages.
21669-func (s *snapshot) reloadWorkspace(ctx context.Context) error {
21670-	var scopes []loadScope
21671-	var seen map[PackagePath]bool
21672-	s.mu.Lock()
21673-	for _, pkgPaths := range s.shouldLoad {
21674-		for _, pkgPath := range pkgPaths {
21675-			if seen == nil {
21676-				seen = make(map[PackagePath]bool)
21677-			}
21678-			if seen[pkgPath] {
21679-				continue
21680-			}
21681-			seen[pkgPath] = true
21682-			scopes = append(scopes, packageLoadScope(pkgPath))
21683-		}
21684-	}
21685-	s.mu.Unlock()
21686-
21687-	if len(scopes) == 0 {
21688-		return nil
21689-	}
21690-
21691-	// If the view's build configuration is invalid, we cannot reload by
21692-	// package path. Just reload the directory instead.
21693-	if !s.ValidBuildConfiguration() {
21694-		scopes = []loadScope{viewLoadScope("LOAD_INVALID_VIEW")}
21695-	}
21696-
21697-	err := s.load(ctx, false, scopes...)
21698-
21699-	// Unless the context was canceled, set "shouldLoad" to false for all
21700-	// of the metadata we attempted to load.
21701-	if !errors.Is(err, context.Canceled) {
21702-		s.clearShouldLoad(scopes...)
21703-	}
21704-
21705-	return err
21706-}
21707-
21708-func (s *snapshot) reloadOrphanedOpenFiles(ctx context.Context) error {
21709-	// When we load ./... or a package path directly, we may not get packages
21710-	// that exist only in overlays. As a workaround, we search all of the files
21711-	// available in the snapshot and reload their metadata individually using a
21712-	// file= query if the metadata is unavailable.
21713-	files := s.orphanedOpenFiles()
21714-
21715-	// Files without a valid package declaration can't be loaded. Don't try.
21716-	var scopes []loadScope
21717-	for _, file := range files {
21718-		pgf, err := s.ParseGo(ctx, file, source.ParseHeader)
21719-		if err != nil {
21720-			continue
21721-		}
21722-		if !pgf.File.Package.IsValid() {
21723-			continue
21724-		}
21725-
21726-		scopes = append(scopes, fileLoadScope(file.URI()))
21727-	}
21728-
21729-	if len(scopes) == 0 {
21730-		return nil
21731-	}
21732-
21733-	// The regtests match this exact log message, keep them in sync.
21734-	event.Log(ctx, "reloadOrphanedFiles reloading", tag.Query.Of(scopes))
21735-	err := s.load(ctx, false, scopes...)
21736-
21737-	// If we failed to load some files, i.e. they have no metadata,
21738-	// mark the failures so we don't bother retrying until the file's
21739-	// content changes.
21740-	//
21741-	// TODO(rstambler): This may be an overestimate if the load stopped
21742-	// early for an unrelated errors. Add a fallback?
21743-	//
21744-	// Check for context cancellation so that we don't incorrectly mark files
21745-	// as unloadable, but don't return before setting all workspace packages.
21746-	if ctx.Err() == nil && err != nil {
21747-		event.Error(ctx, "reloadOrphanedFiles: failed to load", err, tag.Query.Of(scopes))
21748-		s.mu.Lock()
21749-		for _, scope := range scopes {
21750-			uri := span.URI(scope.(fileLoadScope))
21751-			if s.noValidMetadataForURILocked(uri) {
21752-				s.unloadableFiles[uri] = struct{}{}
21753-			}
21754-		}
21755-		s.mu.Unlock()
21756-	}
21757-	return nil
21758-}
21759-
21760-func (s *snapshot) orphanedOpenFiles() []source.FileHandle {
21761-	s.mu.Lock()
21762-	defer s.mu.Unlock()
21763-
21764-	var files []source.FileHandle
21765-	s.files.Range(func(uri span.URI, fh source.FileHandle) {
21766-		// Only consider open files, which will be represented as overlays.
21767-		if _, isOverlay := fh.(*Overlay); !isOverlay {
21768-			return
21769-		}
21770-		// Don't try to reload metadata for go.mod files.
21771-		if s.view.FileKind(fh) != source.Go {
21772-			return
21773-		}
21774-		// If the URI doesn't belong to this view, then it's not in a workspace
21775-		// package and should not be reloaded directly.
21776-		if !source.InDir(s.view.folder.Filename(), uri.Filename()) {
21777-			return
21778-		}
21779-		// Don't reload metadata for files we've already deemed unloadable.
21780-		if _, ok := s.unloadableFiles[uri]; ok {
21781-			return
21782-		}
21783-		if s.noValidMetadataForURILocked(uri) {
21784-			files = append(files, fh)
21785-		}
21786-	})
21787-	return files
21788-}
21789-
21790-// TODO(golang/go#53756): this function needs to consider more than just the
21791-// absolute URI, for example:
21792-//   - the position of /vendor/ with respect to the relevant module root
21793-//   - whether or not go.work is in use (as vendoring isn't supported in workspace mode)
21794-//
21795-// Most likely, each call site of inVendor needs to be reconsidered to
21796-// understand and correctly implement the desired behavior.
21797-func inVendor(uri span.URI) bool {
21798-	_, after, found := cut(string(uri), "/vendor/")
21799-	// Only subdirectories of /vendor/ are considered vendored
21800-	// (/vendor/a/foo.go is vendored, /vendor/foo.go is not).
21801-	return found && strings.Contains(after, "/")
21802-}
21803-
21804-// TODO(adonovan): replace with strings.Cut when we can assume go1.18.
21805-func cut(s, sep string) (before, after string, found bool) {
21806-	if i := strings.Index(s, sep); i >= 0 {
21807-		return s[:i], s[i+len(sep):], true
21808-	}
21809-	return s, "", false
21810-}
21811-
21812-// unappliedChanges is a file source that handles an uncloned snapshot.
21813-type unappliedChanges struct {
21814-	originalSnapshot *snapshot
21815-	changes          map[span.URI]*fileChange
21816-}
21817-
21818-func (ac *unappliedChanges) GetFile(ctx context.Context, uri span.URI) (source.FileHandle, error) {
21819-	if c, ok := ac.changes[uri]; ok {
21820-		return c.fileHandle, nil
21821-	}
21822-	return ac.originalSnapshot.GetFile(ctx, uri)
21823-}
21824-
21825-func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileChange, forceReloadMetadata bool) (*snapshot, func()) {
21826-	ctx, done := event.Start(ctx, "snapshot.clone")
21827-	defer done()
21828-
21829-	reinit := false
21830-	wsModFiles, wsModFilesErr := s.workspaceModFiles, s.workspaceModFilesErr
21831-
21832-	if workURI := s.view.effectiveGOWORK(); workURI != "" {
21833-		if change, ok := changes[workURI]; ok {
21834-			wsModFiles, wsModFilesErr = computeWorkspaceModFiles(ctx, s.view.gomod, workURI, s.view.effectiveGO111MODULE(), &unappliedChanges{
21835-				originalSnapshot: s,
21836-				changes:          changes,
21837-			})
21838-			// TODO(rfindley): don't rely on 'isUnchanged' here. Use a content hash instead.
21839-			reinit = change.fileHandle.Saved() && !change.isUnchanged
21840-		}
21841-	}
21842-
21843-	// Reinitialize if any workspace mod file has changed on disk.
21844-	for uri, change := range changes {
21845-		if _, ok := wsModFiles[uri]; ok && change.fileHandle.Saved() && !change.isUnchanged {
21846-			reinit = true
21847-		}
21848-	}
21849-
21850-	// Finally, process sumfile changes that may affect loading.
21851-	for uri, change := range changes {
21852-		if !change.fileHandle.Saved() {
21853-			continue // like with go.mod files, we only reinit when things are saved
21854-		}
21855-		if filepath.Base(uri.Filename()) == "go.work.sum" && s.view.gowork != "" {
21856-			if filepath.Dir(uri.Filename()) == filepath.Dir(s.view.gowork) {
21857-				reinit = true
21858-			}
21859-		}
21860-		if filepath.Base(uri.Filename()) == "go.sum" {
21861-			dir := filepath.Dir(uri.Filename())
21862-			modURI := span.URIFromPath(filepath.Join(dir, "go.mod"))
21863-			if _, active := wsModFiles[modURI]; active {
21864-				reinit = true
21865-			}
21866-		}
21867-	}
21868-
21869-	s.mu.Lock()
21870-	defer s.mu.Unlock()
21871-
21872-	// Changes to vendor tree may require reinitialization,
21873-	// either because of an initialization error
21874-	// (e.g. "inconsistent vendoring detected"), or because
21875-	// one or more modules may have moved into or out of the
21876-	// vendor tree after 'go mod vendor' or 'rm -fr vendor/'.
21877-	for uri := range changes {
21878-		if inVendor(uri) && s.initializedErr != nil ||
21879-			strings.HasSuffix(string(uri), "/vendor/modules.txt") {
21880-			reinit = true
21881-			break
21882-		}
21883-	}
21884-
21885-	bgCtx, cancel := context.WithCancel(bgCtx)
21886-	result := &snapshot{
21887-		sequenceID:           s.sequenceID + 1,
21888-		globalID:             nextSnapshotID(),
21889-		store:                s.store,
21890-		view:                 s.view,
21891-		backgroundCtx:        bgCtx,
21892-		cancel:               cancel,
21893-		builtin:              s.builtin,
21894-		initialized:          s.initialized,
21895-		initializedErr:       s.initializedErr,
21896-		packages:             s.packages.Clone(),
21897-		activePackages:       s.activePackages.Clone(),
21898-		analyses:             s.analyses.Clone(),
21899-		files:                s.files.Clone(),
21900-		parseCache:           s.parseCache,
21901-		symbolizeHandles:     s.symbolizeHandles.Clone(),
21902-		workspacePackages:    make(map[PackageID]PackagePath, len(s.workspacePackages)),
21903-		unloadableFiles:      make(map[span.URI]struct{}, len(s.unloadableFiles)),
21904-		parseModHandles:      s.parseModHandles.Clone(),
21905-		parseWorkHandles:     s.parseWorkHandles.Clone(),
21906-		modTidyHandles:       s.modTidyHandles.Clone(),
21907-		modWhyHandles:        s.modWhyHandles.Clone(),
21908-		modVulnHandles:       s.modVulnHandles.Clone(),
21909-		knownSubdirs:         s.knownSubdirs.Clone(),
21910-		workspaceModFiles:    wsModFiles,
21911-		workspaceModFilesErr: wsModFilesErr,
21912-	}
21913-
21914-	// The snapshot should be initialized if either s was uninitialized, or we've
21915-	// detected a change that triggers reinitialization.
21916-	if reinit {
21917-		result.initialized = false
21918-	}
21919-
21920-	// Create a lease on the new snapshot.
21921-	// (Best to do this early in case the code below hides an
21922-	// incref/decref operation that might destroy it prematurely.)
21923-	release := result.Acquire()
21924-
21925-	// Copy the set of unloadable files.
21926-	//
21927-	// TODO(rfindley): this looks wrong. Shouldn't we clear unloadableFiles on
21928-	// changes to environment or workspace layout, or more generally on any
21929-	// metadata change?
21930-	//
21931-	// Maybe not, as major configuration changes cause a new view.
21932-	for k, v := range s.unloadableFiles {
21933-		result.unloadableFiles[k] = v
21934-	}
21935-
21936-	// Add all of the known subdirectories, but don't update them for the
21937-	// changed files. We need to rebuild the workspace module to know the
21938-	// true set of known subdirectories, but we don't want to do that in clone.
21939-	result.knownSubdirs = s.knownSubdirs.Clone()
21940-	result.knownSubdirsPatternCache = s.knownSubdirsPatternCache
21941-	for _, c := range changes {
21942-		result.unprocessedSubdirChanges = append(result.unprocessedSubdirChanges, c)
21943-	}
21944-
21945-	// directIDs keeps track of package IDs that have directly changed.
21946-	// Note: this is not a set, it's a map from id to invalidateMetadata.
21947-	directIDs := map[PackageID]bool{}
21948-
21949-	// Invalidate all package metadata if the workspace module has changed.
21950-	if reinit {
21951-		for k := range s.meta.metadata {
21952-			directIDs[k] = true
21953-		}
21954-	}
21955-
21956-	// Compute invalidations based on file changes.
21957-	anyImportDeleted := false      // import deletions can resolve cycles
21958-	anyFileOpenedOrClosed := false // opened files affect workspace packages
21959-	anyFileAdded := false          // adding a file can resolve missing dependencies
21960-
21961-	for uri, change := range changes {
21962-		// Invalidate go.mod-related handles.
21963-		result.modTidyHandles.Delete(uri)
21964-		result.modWhyHandles.Delete(uri)
21965-		result.modVulnHandles.Delete(uri)
21966-
21967-		// Invalidate handles for cached symbols.
21968-		result.symbolizeHandles.Delete(uri)
21969-
21970-		// The original FileHandle for this URI is cached on the snapshot.
21971-		originalFH, _ := s.files.Get(uri)
21972-		var originalOpen, newOpen bool
21973-		_, originalOpen = originalFH.(*Overlay)
21974-		_, newOpen = change.fileHandle.(*Overlay)
21975-		anyFileOpenedOrClosed = anyFileOpenedOrClosed || (originalOpen != newOpen)
21976-		anyFileAdded = anyFileAdded || (originalFH == nil && change.fileHandle != nil)
21977-
21978-		// If uri is a Go file, check if it has changed in a way that would
21979-		// invalidate metadata. Note that we can't use s.view.FileKind here,
21980-		// because the file type that matters is not what the *client* tells us,
21981-		// but what the Go command sees.
21982-		var invalidateMetadata, pkgFileChanged, importDeleted bool
21983-		if strings.HasSuffix(uri.Filename(), ".go") {
21984-			invalidateMetadata, pkgFileChanged, importDeleted = metadataChanges(ctx, s, originalFH, change.fileHandle)
21985-		}
21986-
21987-		invalidateMetadata = invalidateMetadata || forceReloadMetadata || reinit
21988-		anyImportDeleted = anyImportDeleted || importDeleted
21989-
21990-		// Mark all of the package IDs containing the given file.
21991-		filePackageIDs := invalidatedPackageIDs(uri, s.meta.ids, pkgFileChanged)
21992-		for id := range filePackageIDs {
21993-			directIDs[id] = directIDs[id] || invalidateMetadata // may insert 'false'
21994-		}
21995-
21996-		// Invalidate the previous modTidyHandle if any of the files have been
21997-		// saved or if any of the metadata has been invalidated.
21998-		if invalidateMetadata || fileWasSaved(originalFH, change.fileHandle) {
21999-			// TODO(maybe): Only delete mod handles for
22000-			// which the withoutURI is relevant.
22001-			// Requires reverse-engineering the go command. (!)
22002-			result.modTidyHandles.Clear()
22003-			result.modWhyHandles.Clear()
22004-			result.modVulnHandles.Clear()
22005-		}
22006-
22007-		result.parseModHandles.Delete(uri)
22008-		result.parseWorkHandles.Delete(uri)
22009-		// Handle the invalidated file; it may have new contents or not exist.
22010-		if !change.exists {
22011-			result.files.Delete(uri)
22012-		} else {
22013-			result.files.Set(uri, change.fileHandle)
22014-		}
22015-
22016-		// Make sure to remove the changed file from the unloadable set.
22017-		delete(result.unloadableFiles, uri)
22018-	}
22019-
22020-	// Deleting an import can cause list errors due to import cycles to be
22021-	// resolved. The best we can do without parsing the list error message is to
22022-	// hope that list errors may have been resolved by a deleted import.
22023-	//
22024-	// We could do better by parsing the list error message. We already do this
22025-	// to assign a better range to the list error, but for such critical
22026-	// functionality as metadata, it's better to be conservative until it proves
22027-	// impractical.
22028-	//
22029-	// We could also do better by looking at which imports were deleted and
22030-	// trying to find cycles they are involved in. This fails when the file goes
22031-	// from an unparseable state to a parseable state, as we don't have a
22032-	// starting point to compare with.
22033-	if anyImportDeleted {
22034-		for id, metadata := range s.meta.metadata {
22035-			if len(metadata.Errors) > 0 {
22036-				directIDs[id] = true
22037-			}
22038-		}
22039-	}
22040-
22041-	// Adding a file can resolve missing dependencies from existing packages.
22042-	//
22043-	// We could be smart here and try to guess which packages may have been
22044-	// fixed, but until that proves necessary, just invalidate metadata for any
22045-	// package with missing dependencies.
22046-	if anyFileAdded {
22047-		for id, metadata := range s.meta.metadata {
22048-			for _, impID := range metadata.DepsByImpPath {
22049-				if impID == "" { // missing import
22050-					directIDs[id] = true
22051-					break
22052-				}
22053-			}
22054-		}
22055-	}
22056-
22057-	// Invalidate reverse dependencies too.
22058-	// idsToInvalidate keeps track of transitive reverse dependencies.
22059-	// If an ID is present in the map, invalidate its types.
22060-	// If an ID's value is true, invalidate its metadata too.
22061-	idsToInvalidate := map[PackageID]bool{}
22062-	var addRevDeps func(PackageID, bool)
22063-	addRevDeps = func(id PackageID, invalidateMetadata bool) {
22064-		current, seen := idsToInvalidate[id]
22065-		newInvalidateMetadata := current || invalidateMetadata
22066-
22067-		// If we've already seen this ID, and the value of invalidate
22068-		// metadata has not changed, we can return early.
22069-		if seen && current == newInvalidateMetadata {
22070-			return
22071-		}
22072-		idsToInvalidate[id] = newInvalidateMetadata
22073-		for _, rid := range s.meta.importedBy[id] {
22074-			addRevDeps(rid, invalidateMetadata)
22075-		}
22076-	}
22077-	for id, invalidateMetadata := range directIDs {
22078-		addRevDeps(id, invalidateMetadata)
22079-	}
22080-
22081-	// Delete invalidated package type information.
22082-	for id := range idsToInvalidate {
22083-		result.packages.Delete(id)
22084-		result.activePackages.Delete(id)
22085-	}
22086-
22087-	// Delete invalidated analysis actions.
22088-	var actionsToDelete []analysisKey
22089-	result.analyses.Range(func(k, _ interface{}) {
22090-		key := k.(analysisKey)
22091-		if _, ok := idsToInvalidate[key.pkgid]; ok {
22092-			actionsToDelete = append(actionsToDelete, key)
22093-		}
22094-	})
22095-	for _, key := range actionsToDelete {
22096-		result.analyses.Delete(key)
22097-	}
22098-
22099-	// If a file has been deleted, we must delete metadata for all packages
22100-	// containing that file.
22101-	//
22102-	// TODO(rfindley): why not keep invalid metadata in this case? If we
22103-	// otherwise allow operate on invalid metadata, why not continue to do so,
22104-	// skipping the missing file?
22105-	skipID := map[PackageID]bool{}
22106-	for _, c := range changes {
22107-		if c.exists {
22108-			continue
22109-		}
22110-		// The file has been deleted.
22111-		if ids, ok := s.meta.ids[c.fileHandle.URI()]; ok {
22112-			for _, id := range ids {
22113-				skipID[id] = true
22114-			}
22115-		}
22116-	}
22117-
22118-	// Any packages that need loading in s still need loading in the new
22119-	// snapshot.
22120-	for k, v := range s.shouldLoad {
22121-		if result.shouldLoad == nil {
22122-			result.shouldLoad = make(map[PackageID][]PackagePath)
22123-		}
22124-		result.shouldLoad[k] = v
22125-	}
22126-
22127-	// Compute which metadata updates are required. We only need to invalidate
22128-	// packages directly containing the affected file, and only if it changed in
22129-	// a relevant way.
22130-	metadataUpdates := make(map[PackageID]*source.Metadata)
22131-	for k, v := range s.meta.metadata {
22132-		invalidateMetadata := idsToInvalidate[k]
22133-
22134-		// For metadata that has been newly invalidated, capture package paths
22135-		// requiring reloading in the shouldLoad map.
22136-		if invalidateMetadata && !source.IsCommandLineArguments(v.ID) {
22137-			if result.shouldLoad == nil {
22138-				result.shouldLoad = make(map[PackageID][]PackagePath)
22139-			}
22140-			needsReload := []PackagePath{v.PkgPath}
22141-			if v.ForTest != "" && v.ForTest != v.PkgPath {
22142-				// When reloading test variants, always reload their ForTest package as
22143-				// well. Otherwise, we may miss test variants in the resulting load.
22144-				//
22145-				// TODO(rfindley): is this actually sufficient? Is it possible that
22146-				// other test variants may be invalidated? Either way, we should
22147-				// determine exactly what needs to be reloaded here.
22148-				needsReload = append(needsReload, v.ForTest)
22149-			}
22150-			result.shouldLoad[k] = needsReload
22151-		}
22152-
22153-		// Check whether the metadata should be deleted.
22154-		if skipID[k] || invalidateMetadata {
22155-			metadataUpdates[k] = nil
22156-			continue
22157-		}
22158-	}
22159-
22160-	// Update metadata, if necessary.
22161-	result.meta = s.meta.Clone(metadataUpdates)
22162-
22163-	// Update workspace and active packages, if necessary.
22164-	if result.meta != s.meta || anyFileOpenedOrClosed {
22165-		result.workspacePackages = computeWorkspacePackagesLocked(result, result.meta)
22166-		result.resetActivePackagesLocked()
22167-	} else {
22168-		result.workspacePackages = s.workspacePackages
22169-	}
22170-
22171-	// Don't bother copying the importedBy graph,
22172-	// as it changes each time we update metadata.
22173-
22174-	// TODO(rfindley): consolidate the this workspace mode detection with
22175-	// workspace invalidation.
22176-	workspaceModeChanged := s.workspaceMode() != result.workspaceMode()
22177-
22178-	// If the snapshot's workspace mode has changed, the packages loaded using
22179-	// the previous mode are no longer relevant, so clear them out.
22180-	if workspaceModeChanged {
22181-		result.workspacePackages = map[PackageID]PackagePath{}
22182-	}
22183-	result.dumpWorkspace("clone")
22184-	return result, release
22185-}
22186-
22187-// invalidatedPackageIDs returns all packages invalidated by a change to uri.
22188-// If we haven't seen this URI before, we guess based on files in the same
22189-// directory. This is of course incorrect in build systems where packages are
22190-// not organized by directory.
22191-//
22192-// If packageFileChanged is set, the file is either a new file, or has a new
22193-// package name. In this case, all known packages in the directory will be
22194-// invalidated.
22195-func invalidatedPackageIDs(uri span.URI, known map[span.URI][]PackageID, packageFileChanged bool) map[PackageID]struct{} {
22196-	invalidated := make(map[PackageID]struct{})
22197-
22198-	// At a minimum, we invalidate packages known to contain uri.
22199-	for _, id := range known[uri] {
22200-		invalidated[id] = struct{}{}
22201-	}
22202-
22203-	// If the file didn't move to a new package, we should only invalidate the
22204-	// packages it is currently contained inside.
22205-	if !packageFileChanged && len(invalidated) > 0 {
22206-		return invalidated
22207-	}
22208-
22209-	// This is a file we don't yet know about, or which has moved packages. Guess
22210-	// relevant packages by considering files in the same directory.
22211-
22212-	// Cache of FileInfo to avoid unnecessary stats for multiple files in the
22213-	// same directory.
22214-	stats := make(map[string]struct {
22215-		os.FileInfo
22216-		error
22217-	})
22218-	getInfo := func(dir string) (os.FileInfo, error) {
22219-		if res, ok := stats[dir]; ok {
22220-			return res.FileInfo, res.error
22221-		}
22222-		fi, err := os.Stat(dir)
22223-		stats[dir] = struct {
22224-			os.FileInfo
22225-			error
22226-		}{fi, err}
22227-		return fi, err
22228-	}
22229-	dir := filepath.Dir(uri.Filename())
22230-	fi, err := getInfo(dir)
22231-	if err == nil {
22232-		// Aggregate all possibly relevant package IDs.
22233-		for knownURI, ids := range known {
22234-			knownDir := filepath.Dir(knownURI.Filename())
22235-			knownFI, err := getInfo(knownDir)
22236-			if err != nil {
22237-				continue
22238-			}
22239-			if os.SameFile(fi, knownFI) {
22240-				for _, id := range ids {
22241-					invalidated[id] = struct{}{}
22242-				}
22243-			}
22244-		}
22245-	}
22246-	return invalidated
22247-}
22248-
22249-// fileWasSaved reports whether the FileHandle passed in has been saved. It
22250-// accomplishes this by checking to see if the original and current FileHandles
22251-// are both overlays, and if the current FileHandle is saved while the original
22252-// FileHandle was not saved.
22253-func fileWasSaved(originalFH, currentFH source.FileHandle) bool {
22254-	c, ok := currentFH.(*Overlay)
22255-	if !ok || c == nil {
22256-		return true
22257-	}
22258-	o, ok := originalFH.(*Overlay)
22259-	if !ok || o == nil {
22260-		return c.saved
22261-	}
22262-	return !o.saved && c.saved
22263-}
22264-
22265-// metadataChanges detects features of the change from oldFH->newFH that may
22266-// affect package metadata.
22267-//
22268-// It uses lockedSnapshot to access cached parse information. lockedSnapshot
22269-// must be locked.
22270-//
22271-// The result parameters have the following meaning:
22272-//   - invalidate means that package metadata for packages containing the file
22273-//     should be invalidated.
22274-//   - pkgFileChanged means that the file->package associates for the file have
22275-//     changed (possibly because the file is new, or because its package name has
22276-//     changed).
22277-//   - importDeleted means that an import has been deleted, or we can't
22278-//     determine if an import was deleted due to errors.
22279-func metadataChanges(ctx context.Context, lockedSnapshot *snapshot, oldFH, newFH source.FileHandle) (invalidate, pkgFileChanged, importDeleted bool) {
22280-	if oldFH == nil || newFH == nil { // existential changes
22281-		changed := (oldFH == nil) != (newFH == nil)
22282-		return changed, changed, (newFH == nil) // we don't know if an import was deleted
22283-	}
22284-
22285-	// If the file hasn't changed, there's no need to reload.
22286-	if oldFH.FileIdentity() == newFH.FileIdentity() {
22287-		return false, false, false
22288-	}
22289-
22290-	// Parse headers to compare package names and imports.
22291-	oldHeads, _, oldErr := lockedSnapshot.parseCache.parseFiles(ctx, source.ParseHeader, oldFH)
22292-	newHeads, _, newErr := lockedSnapshot.parseCache.parseFiles(ctx, source.ParseHeader, newFH)
22293-
22294-	if oldErr != nil || newErr != nil {
22295-		// TODO(rfindley): we can get here if newFH does not exist. There is
22296-		// asymmetry, in that newFH may be non-nil even if the underlying file does
22297-		// not exist.
22298-		//
22299-		// We should not produce a non-nil filehandle for a file that does not exist.
22300-		errChanged := (oldErr == nil) != (newErr == nil)
22301-		return errChanged, errChanged, (newErr != nil) // we don't know if an import was deleted
22302-	}
22303-
22304-	oldHead := oldHeads[0]
22305-	newHead := newHeads[0]
22306-
22307-	// `go list` fails completely if the file header cannot be parsed. If we go
22308-	// from a non-parsing state to a parsing state, we should reload.
22309-	if oldHead.ParseErr != nil && newHead.ParseErr == nil {
22310-		return true, true, true // We don't know what changed, so fall back on full invalidation.
22311-	}
22312-
22313-	// If a package name has changed, the set of package imports may have changed
22314-	// in ways we can't detect here. Assume an import has been deleted.
22315-	if oldHead.File.Name.Name != newHead.File.Name.Name {
22316-		return true, true, true
22317-	}
22318-
22319-	// Check whether package imports have changed. Only consider potentially
22320-	// valid imports paths.
22321-	oldImports := validImports(oldHead.File.Imports)
22322-	newImports := validImports(newHead.File.Imports)
22323-
22324-	for path := range newImports {
22325-		if _, ok := oldImports[path]; ok {
22326-			delete(oldImports, path)
22327-		} else {
22328-			invalidate = true // a new, potentially valid import was added
22329-		}
22330-	}
22331-
22332-	if len(oldImports) > 0 {
22333-		invalidate = true
22334-		importDeleted = true
22335-	}
22336-
22337-	// If the change does not otherwise invalidate metadata, get the full ASTs in
22338-	// order to check magic comments.
22339-	//
22340-	// Note: if this affects performance we can probably avoid parsing in the
22341-	// common case by first scanning the source for potential comments.
22342-	if !invalidate {
22343-		origFulls, _, oldErr := lockedSnapshot.parseCache.parseFiles(ctx, source.ParseFull, oldFH)
22344-		newFulls, _, newErr := lockedSnapshot.parseCache.parseFiles(ctx, source.ParseFull, newFH)
22345-		if oldErr == nil && newErr == nil {
22346-			invalidate = magicCommentsChanged(origFulls[0].File, newFulls[0].File)
22347-		} else {
22348-			// At this point, we shouldn't ever fail to produce a ParsedGoFile, as
22349-			// we're already past header parsing.
22350-			bug.Reportf("metadataChanges: unparseable file %v (old error: %v, new error: %v)", oldFH.URI(), oldErr, newErr)
22351-		}
22352-	}
22353-
22354-	return invalidate, pkgFileChanged, importDeleted
22355-}
22356-
22357-func magicCommentsChanged(original *ast.File, current *ast.File) bool {
22358-	oldComments := extractMagicComments(original)
22359-	newComments := extractMagicComments(current)
22360-	if len(oldComments) != len(newComments) {
22361-		return true
22362-	}
22363-	for i := range oldComments {
22364-		if oldComments[i] != newComments[i] {
22365-			return true
22366-		}
22367-	}
22368-	return false
22369-}
22370-
22371-// validImports extracts the set of valid import paths from imports.
22372-func validImports(imports []*ast.ImportSpec) map[string]struct{} {
22373-	m := make(map[string]struct{})
22374-	for _, spec := range imports {
22375-		if path := spec.Path.Value; validImportPath(path) {
22376-			m[path] = struct{}{}
22377-		}
22378-	}
22379-	return m
22380-}
22381-
22382-func validImportPath(path string) bool {
22383-	path, err := strconv.Unquote(path)
22384-	if err != nil {
22385-		return false
22386-	}
22387-	if path == "" {
22388-		return false
22389-	}
22390-	if path[len(path)-1] == '/' {
22391-		return false
22392-	}
22393-	return true
22394-}
22395-
22396-var buildConstraintOrEmbedRe = regexp.MustCompile(`^//(go:embed|go:build|\s*\+build).*`)
22397-
22398-// extractMagicComments finds magic comments that affect metadata in f.
22399-func extractMagicComments(f *ast.File) []string {
22400-	var results []string
22401-	for _, cg := range f.Comments {
22402-		for _, c := range cg.List {
22403-			if buildConstraintOrEmbedRe.MatchString(c.Text) {
22404-				results = append(results, c.Text)
22405-			}
22406-		}
22407-	}
22408-	return results
22409-}
22410-
22411-func (s *snapshot) BuiltinFile(ctx context.Context) (*source.ParsedGoFile, error) {
22412-	s.AwaitInitialized(ctx)
22413-
22414-	s.mu.Lock()
22415-	builtin := s.builtin
22416-	s.mu.Unlock()
22417-
22418-	if builtin == "" {
22419-		return nil, fmt.Errorf("no builtin package for view %s", s.view.name)
22420-	}
22421-
22422-	fh, err := s.GetFile(ctx, builtin)
22423-	if err != nil {
22424-		return nil, err
22425-	}
22426-	return s.ParseGo(ctx, fh, source.ParseFull)
22427-}
22428-
22429-func (s *snapshot) IsBuiltin(ctx context.Context, uri span.URI) bool {
22430-	s.mu.Lock()
22431-	defer s.mu.Unlock()
22432-	// We should always get the builtin URI in a canonical form, so use simple
22433-	// string comparison here. span.CompareURI is too expensive.
22434-	return uri == s.builtin
22435-}
22436-
22437-func (s *snapshot) setBuiltin(path string) {
22438-	s.mu.Lock()
22439-	defer s.mu.Unlock()
22440-
22441-	s.builtin = span.URIFromPath(path)
22442-}
22443diff -urN a/gopls/internal/lsp/cache/standalone_go115.go b/gopls/internal/lsp/cache/standalone_go115.go
22444--- a/gopls/internal/lsp/cache/standalone_go115.go	2000-01-01 00:00:00.000000000 -0000
22445+++ b/gopls/internal/lsp/cache/standalone_go115.go	1970-01-01 00:00:00.000000000 +0000
22446@@ -1,14 +0,0 @@
22447-// Copyright 2022 The Go Authors. All rights reserved.
22448-// Use of this source code is governed by a BSD-style
22449-// license that can be found in the LICENSE file.
22450-
22451-//go:build !go1.16
22452-// +build !go1.16
22453-
22454-package cache
22455-
22456-// isStandaloneFile returns false, as the 'standaloneTags' setting is
22457-// unsupported on Go 1.15 and earlier.
22458-func isStandaloneFile(src []byte, standaloneTags []string) bool {
22459-	return false
22460-}
22461diff -urN a/gopls/internal/lsp/cache/standalone_go116.go b/gopls/internal/lsp/cache/standalone_go116.go
22462--- a/gopls/internal/lsp/cache/standalone_go116.go	2000-01-01 00:00:00.000000000 -0000
22463+++ b/gopls/internal/lsp/cache/standalone_go116.go	1970-01-01 00:00:00.000000000 +0000
22464@@ -1,50 +0,0 @@
22465-// Copyright 2022 The Go Authors. All rights reserved.
22466-// Use of this source code is governed by a BSD-style
22467-// license that can be found in the LICENSE file.
22468-
22469-//go:build go1.16
22470-// +build go1.16
22471-
22472-package cache
22473-
22474-import (
22475-	"go/build/constraint"
22476-	"go/parser"
22477-	"go/token"
22478-)
22479-
22480-// isStandaloneFile reports whether a file with the given contents should be
22481-// considered a 'standalone main file', meaning a package that consists of only
22482-// a single file.
22483-func isStandaloneFile(src []byte, standaloneTags []string) bool {
22484-	f, err := parser.ParseFile(token.NewFileSet(), "", src, parser.PackageClauseOnly|parser.ParseComments)
22485-	if err != nil {
22486-		return false
22487-	}
22488-
22489-	if f.Name == nil || f.Name.Name != "main" {
22490-		return false
22491-	}
22492-
22493-	for _, cg := range f.Comments {
22494-		// Even with PackageClauseOnly the parser consumes the semicolon following
22495-		// the package clause, so we must guard against comments that come after
22496-		// the package name.
22497-		if cg.Pos() > f.Name.Pos() {
22498-			continue
22499-		}
22500-		for _, comment := range cg.List {
22501-			if c, err := constraint.Parse(comment.Text); err == nil {
22502-				if tag, ok := c.(*constraint.TagExpr); ok {
22503-					for _, t := range standaloneTags {
22504-						if t == tag.Tag {
22505-							return true
22506-						}
22507-					}
22508-				}
22509-			}
22510-		}
22511-	}
22512-
22513-	return false
22514-}
22515diff -urN a/gopls/internal/lsp/cache/standalone_go116_test.go b/gopls/internal/lsp/cache/standalone_go116_test.go
22516--- a/gopls/internal/lsp/cache/standalone_go116_test.go	2000-01-01 00:00:00.000000000 -0000
22517+++ b/gopls/internal/lsp/cache/standalone_go116_test.go	1970-01-01 00:00:00.000000000 +0000
22518@@ -1,96 +0,0 @@
22519-// Copyright 2022 The Go Authors. All rights reserved.
22520-// Use of this source code is governed by a BSD-style
22521-// license that can be found in the LICENSE file.
22522-
22523-//go:build go1.16
22524-// +build go1.16
22525-
22526-package cache
22527-
22528-import (
22529-	"testing"
22530-)
22531-
22532-func TestIsStandaloneFile(t *testing.T) {
22533-	tests := []struct {
22534-		desc           string
22535-		contents       string
22536-		standaloneTags []string
22537-		want           bool
22538-	}{
22539-		{
22540-			"new syntax",
22541-			"//go:build ignore\n\npackage main\n",
22542-			[]string{"ignore"},
22543-			true,
22544-		},
22545-		{
22546-			"legacy syntax",
22547-			"// +build ignore\n\npackage main\n",
22548-			[]string{"ignore"},
22549-			true,
22550-		},
22551-		{
22552-			"multiple tags",
22553-			"//go:build ignore\n\npackage main\n",
22554-			[]string{"exclude", "ignore"},
22555-			true,
22556-		},
22557-		{
22558-			"invalid tag",
22559-			"// +build ignore\n\npackage main\n",
22560-			[]string{"script"},
22561-			false,
22562-		},
22563-		{
22564-			"non-main package",
22565-			"//go:build ignore\n\npackage p\n",
22566-			[]string{"ignore"},
22567-			false,
22568-		},
22569-		{
22570-			"alternate tag",
22571-			"// +build script\n\npackage main\n",
22572-			[]string{"script"},
22573-			true,
22574-		},
22575-		{
22576-			"both syntax",
22577-			"//go:build ignore\n// +build ignore\n\npackage main\n",
22578-			[]string{"ignore"},
22579-			true,
22580-		},
22581-		{
22582-			"after comments",
22583-			"// A non-directive comment\n//go:build ignore\n\npackage main\n",
22584-			[]string{"ignore"},
22585-			true,
22586-		},
22587-		{
22588-			"after package decl",
22589-			"package main //go:build ignore\n",
22590-			[]string{"ignore"},
22591-			false,
22592-		},
22593-		{
22594-			"on line after package decl",
22595-			"package main\n\n//go:build ignore\n",
22596-			[]string{"ignore"},
22597-			false,
22598-		},
22599-		{
22600-			"combined with other expressions",
22601-			"\n\n//go:build ignore || darwin\n\npackage main\n",
22602-			[]string{"ignore"},
22603-			false,
22604-		},
22605-	}
22606-
22607-	for _, test := range tests {
22608-		t.Run(test.desc, func(t *testing.T) {
22609-			if got := isStandaloneFile([]byte(test.contents), test.standaloneTags); got != test.want {
22610-				t.Errorf("isStandaloneFile(%q, %v) = %t, want %t", test.contents, test.standaloneTags, got, test.want)
22611-			}
22612-		})
22613-	}
22614-}
22615diff -urN a/gopls/internal/lsp/cache/symbols.go b/gopls/internal/lsp/cache/symbols.go
22616--- a/gopls/internal/lsp/cache/symbols.go	2000-01-01 00:00:00.000000000 -0000
22617+++ b/gopls/internal/lsp/cache/symbols.go	1970-01-01 00:00:00.000000000 +0000
22618@@ -1,213 +0,0 @@
22619-// Copyright 2021 The Go Authors. All rights reserved.
22620-// Use of this source code is governed by a BSD-style
22621-// license that can be found in the LICENSE file.
22622-
22623-package cache
22624-
22625-import (
22626-	"context"
22627-	"go/ast"
22628-	"go/token"
22629-	"go/types"
22630-	"strings"
22631-
22632-	"golang.org/x/tools/gopls/internal/lsp/protocol"
22633-	"golang.org/x/tools/gopls/internal/lsp/source"
22634-	"golang.org/x/tools/gopls/internal/span"
22635-	"golang.org/x/tools/internal/memoize"
22636-)
22637-
22638-// symbolize returns the result of symbolizing the file identified by uri, using a cache.
22639-func (s *snapshot) symbolize(ctx context.Context, uri span.URI) ([]source.Symbol, error) {
22640-
22641-	s.mu.Lock()
22642-	entry, hit := s.symbolizeHandles.Get(uri)
22643-	s.mu.Unlock()
22644-
22645-	type symbolizeResult struct {
22646-		symbols []source.Symbol
22647-		err     error
22648-	}
22649-
22650-	// Cache miss?
22651-	if !hit {
22652-		fh, err := s.GetFile(ctx, uri)
22653-		if err != nil {
22654-			return nil, err
22655-		}
22656-		type symbolHandleKey source.Hash
22657-		key := symbolHandleKey(fh.FileIdentity().Hash)
22658-		promise, release := s.store.Promise(key, func(ctx context.Context, arg interface{}) interface{} {
22659-			symbols, err := symbolizeImpl(ctx, arg.(*snapshot), fh)
22660-			return symbolizeResult{symbols, err}
22661-		})
22662-
22663-		entry = promise
22664-
22665-		s.mu.Lock()
22666-		s.symbolizeHandles.Set(uri, entry, func(_, _ interface{}) { release() })
22667-		s.mu.Unlock()
22668-	}
22669-
22670-	// Await result.
22671-	v, err := s.awaitPromise(ctx, entry.(*memoize.Promise))
22672-	if err != nil {
22673-		return nil, err
22674-	}
22675-	res := v.(symbolizeResult)
22676-	return res.symbols, res.err
22677-}
22678-
22679-// symbolizeImpl reads and parses a file and extracts symbols from it.
22680-// It may use a parsed file already present in the cache but
22681-// otherwise does not populate the cache.
22682-func symbolizeImpl(ctx context.Context, snapshot *snapshot, fh source.FileHandle) ([]source.Symbol, error) {
22683-	pgfs, _, err := snapshot.parseCache.parseFiles(ctx, source.ParseFull, fh)
22684-	if err != nil {
22685-		return nil, err
22686-	}
22687-
22688-	w := &symbolWalker{
22689-		tokFile: pgfs[0].Tok,
22690-		mapper:  pgfs[0].Mapper,
22691-	}
22692-	w.fileDecls(pgfs[0].File.Decls)
22693-
22694-	return w.symbols, w.firstError
22695-}
22696-
22697-type symbolWalker struct {
22698-	// for computing positions
22699-	tokFile *token.File
22700-	mapper  *protocol.Mapper
22701-
22702-	symbols    []source.Symbol
22703-	firstError error
22704-}
22705-
22706-func (w *symbolWalker) atNode(node ast.Node, name string, kind protocol.SymbolKind, path ...*ast.Ident) {
22707-	var b strings.Builder
22708-	for _, ident := range path {
22709-		if ident != nil {
22710-			b.WriteString(ident.Name)
22711-			b.WriteString(".")
22712-		}
22713-	}
22714-	b.WriteString(name)
22715-
22716-	rng, err := w.mapper.NodeRange(w.tokFile, node)
22717-	if err != nil {
22718-		w.error(err)
22719-		return
22720-	}
22721-	sym := source.Symbol{
22722-		Name:  b.String(),
22723-		Kind:  kind,
22724-		Range: rng,
22725-	}
22726-	w.symbols = append(w.symbols, sym)
22727-}
22728-
22729-func (w *symbolWalker) error(err error) {
22730-	if err != nil && w.firstError == nil {
22731-		w.firstError = err
22732-	}
22733-}
22734-
22735-func (w *symbolWalker) fileDecls(decls []ast.Decl) {
22736-	for _, decl := range decls {
22737-		switch decl := decl.(type) {
22738-		case *ast.FuncDecl:
22739-			kind := protocol.Function
22740-			var recv *ast.Ident
22741-			if decl.Recv.NumFields() > 0 {
22742-				kind = protocol.Method
22743-				recv = unpackRecv(decl.Recv.List[0].Type)
22744-			}
22745-			w.atNode(decl.Name, decl.Name.Name, kind, recv)
22746-		case *ast.GenDecl:
22747-			for _, spec := range decl.Specs {
22748-				switch spec := spec.(type) {
22749-				case *ast.TypeSpec:
22750-					kind := guessKind(spec)
22751-					w.atNode(spec.Name, spec.Name.Name, kind)
22752-					w.walkType(spec.Type, spec.Name)
22753-				case *ast.ValueSpec:
22754-					for _, name := range spec.Names {
22755-						kind := protocol.Variable
22756-						if decl.Tok == token.CONST {
22757-							kind = protocol.Constant
22758-						}
22759-						w.atNode(name, name.Name, kind)
22760-					}
22761-				}
22762-			}
22763-		}
22764-	}
22765-}
22766-
22767-func guessKind(spec *ast.TypeSpec) protocol.SymbolKind {
22768-	switch spec.Type.(type) {
22769-	case *ast.InterfaceType:
22770-		return protocol.Interface
22771-	case *ast.StructType:
22772-		return protocol.Struct
22773-	case *ast.FuncType:
22774-		return protocol.Function
22775-	}
22776-	return protocol.Class
22777-}
22778-
22779-func unpackRecv(rtyp ast.Expr) *ast.Ident {
22780-	// Extract the receiver identifier. Lifted from go/types/resolver.go
22781-L:
22782-	for {
22783-		switch t := rtyp.(type) {
22784-		case *ast.ParenExpr:
22785-			rtyp = t.X
22786-		case *ast.StarExpr:
22787-			rtyp = t.X
22788-		default:
22789-			break L
22790-		}
22791-	}
22792-	if name, _ := rtyp.(*ast.Ident); name != nil {
22793-		return name
22794-	}
22795-	return nil
22796-}
22797-
22798-// walkType processes symbols related to a type expression. path is path of
22799-// nested type identifiers to the type expression.
22800-func (w *symbolWalker) walkType(typ ast.Expr, path ...*ast.Ident) {
22801-	switch st := typ.(type) {
22802-	case *ast.StructType:
22803-		for _, field := range st.Fields.List {
22804-			w.walkField(field, protocol.Field, protocol.Field, path...)
22805-		}
22806-	case *ast.InterfaceType:
22807-		for _, field := range st.Methods.List {
22808-			w.walkField(field, protocol.Interface, protocol.Method, path...)
22809-		}
22810-	}
22811-}
22812-
22813-// walkField processes symbols related to the struct field or interface method.
22814-//
22815-// unnamedKind and namedKind are the symbol kinds if the field is resp. unnamed
22816-// or named. path is the path of nested identifiers containing the field.
22817-func (w *symbolWalker) walkField(field *ast.Field, unnamedKind, namedKind protocol.SymbolKind, path ...*ast.Ident) {
22818-	if len(field.Names) == 0 {
22819-		switch typ := field.Type.(type) {
22820-		case *ast.SelectorExpr:
22821-			// embedded qualified type
22822-			w.atNode(field, typ.Sel.Name, unnamedKind, path...)
22823-		default:
22824-			w.atNode(field, types.ExprString(field.Type), unnamedKind, path...)
22825-		}
22826-	}
22827-	for _, name := range field.Names {
22828-		w.atNode(name, name.Name, namedKind, path...)
22829-		w.walkType(field.Type, append(path, name)...)
22830-	}
22831-}
22832diff -urN a/gopls/internal/lsp/cache/view.go b/gopls/internal/lsp/cache/view.go
22833--- a/gopls/internal/lsp/cache/view.go	2000-01-01 00:00:00.000000000 -0000
22834+++ b/gopls/internal/lsp/cache/view.go	1970-01-01 00:00:00.000000000 +0000
22835@@ -1,1142 +0,0 @@
22836-// Copyright 2018 The Go Authors. All rights reserved.
22837-// Use of this source code is governed by a BSD-style
22838-// license that can be found in the LICENSE file.
22839-
22840-// Package cache implements the caching layer for gopls.
22841-package cache
22842-
22843-import (
22844-	"bytes"
22845-	"context"
22846-	"encoding/json"
22847-	"errors"
22848-	"fmt"
22849-	"io/ioutil"
22850-	"os"
22851-	"path"
22852-	"path/filepath"
22853-	"reflect"
22854-	"regexp"
22855-	"sort"
22856-	"strings"
22857-	"sync"
22858-	"time"
22859-
22860-	"golang.org/x/mod/modfile"
22861-	"golang.org/x/mod/semver"
22862-	exec "golang.org/x/sys/execabs"
22863-	"golang.org/x/tools/gopls/internal/govulncheck"
22864-	"golang.org/x/tools/gopls/internal/lsp/protocol"
22865-	"golang.org/x/tools/gopls/internal/lsp/source"
22866-	"golang.org/x/tools/gopls/internal/span"
22867-	"golang.org/x/tools/internal/event"
22868-	"golang.org/x/tools/internal/gocommand"
22869-	"golang.org/x/tools/internal/imports"
22870-	"golang.org/x/tools/internal/xcontext"
22871-)
22872-
22873-type View struct {
22874-	id string
22875-
22876-	gocmdRunner *gocommand.Runner // limits go command concurrency
22877-
22878-	// baseCtx is the context handed to NewView. This is the parent of all
22879-	// background contexts created for this view.
22880-	baseCtx context.Context
22881-
22882-	// name is the user-specified name of this view.
22883-	name string
22884-
22885-	optionsMu sync.Mutex
22886-	options   *source.Options
22887-
22888-	// Workspace information. The fields below are immutable, and together with
22889-	// options define the build list. Any change to these fields results in a new
22890-	// View.
22891-	folder               span.URI // user-specified workspace folder
22892-	workspaceInformation          // Go environment information
22893-
22894-	importsState *importsState
22895-
22896-	// moduleUpgrades tracks known upgrades for module paths in each modfile.
22897-	// Each modfile has a map of module name to upgrade version.
22898-	moduleUpgradesMu sync.Mutex
22899-	moduleUpgrades   map[span.URI]map[string]string
22900-
22901-	// vulns maps each go.mod file's URI to its known vulnerabilities.
22902-	vulnsMu sync.Mutex
22903-	vulns   map[span.URI]*govulncheck.Result
22904-
22905-	// fs is the file source used to populate this view.
22906-	fs source.FileSource
22907-
22908-	// seenFiles tracks files that the view has accessed.
22909-	// TODO(golang/go#57558): this notion is fundamentally problematic, and
22910-	// should be removed.
22911-	knownFilesMu sync.Mutex
22912-	knownFiles   map[span.URI]bool
22913-
22914-	// initCancelFirstAttempt can be used to terminate the view's first
22915-	// attempt at initialization.
22916-	initCancelFirstAttempt context.CancelFunc
22917-
22918-	// Track the latest snapshot via the snapshot field, guarded by snapshotMu.
22919-	//
22920-	// Invariant: whenever the snapshot field is overwritten, destroy(snapshot)
22921-	// is called on the previous (overwritten) snapshot while snapshotMu is held,
22922-	// incrementing snapshotWG. During shutdown the final snapshot is
22923-	// overwritten with nil and destroyed, guaranteeing that all observed
22924-	// snapshots have been destroyed via the destroy method, and snapshotWG may
22925-	// be waited upon to let these destroy operations complete.
22926-	snapshotMu      sync.Mutex
22927-	snapshot        *snapshot      // latest snapshot; nil after shutdown has been called
22928-	releaseSnapshot func()         // called when snapshot is no longer needed
22929-	snapshotWG      sync.WaitGroup // refcount for pending destroy operations
22930-
22931-	// initialWorkspaceLoad is closed when the first workspace initialization has
22932-	// completed. If we failed to load, we only retry if the go.mod file changes,
22933-	// to avoid too many go/packages calls.
22934-	initialWorkspaceLoad chan struct{}
22935-
22936-	// initializationSema is used limit concurrent initialization of snapshots in
22937-	// the view. We use a channel instead of a mutex to avoid blocking when a
22938-	// context is canceled.
22939-	//
22940-	// This field (along with snapshot.initialized) guards against duplicate
22941-	// initialization of snapshots. Do not change it without adjusting snapshot
22942-	// accordingly.
22943-	initializationSema chan struct{}
22944-}
22945-
22946-// workspaceInformation holds the defining features of the View workspace.
22947-//
22948-// This type is compared to see if the View needs to be reconstructed.
22949-type workspaceInformation struct {
22950-	// `go env` variables that need to be tracked by gopls.
22951-	goEnv
22952-
22953-	// gomod holds the relevant go.mod file for this workspace.
22954-	gomod span.URI
22955-
22956-	// The Go version in use: X in Go 1.X.
22957-	goversion int
22958-
22959-	// The complete output of the go version command.
22960-	// (Call gocommand.ParseGoVersionOutput to extract a version
22961-	// substring such as go1.19.1 or go1.20-rc.1, go1.21-abcdef01.)
22962-	goversionOutput string
22963-
22964-	// hasGopackagesDriver is true if the user has a value set for the
22965-	// GOPACKAGESDRIVER environment variable or a gopackagesdriver binary on
22966-	// their machine.
22967-	hasGopackagesDriver bool
22968-}
22969-
22970-// effectiveGO111MODULE reports the value of GO111MODULE effective in the go
22971-// command at this go version, assuming at least Go 1.16.
22972-func (w workspaceInformation) effectiveGO111MODULE() go111module {
22973-	switch w.GO111MODULE() {
22974-	case "off":
22975-		return off
22976-	case "on", "":
22977-		return on
22978-	default:
22979-		return auto
22980-	}
22981-}
22982-
22983-// effectiveGOWORK returns the effective GOWORK value for this workspace, if
22984-// any, in URI form.
22985-func (w workspaceInformation) effectiveGOWORK() span.URI {
22986-	if w.gowork == "off" || w.gowork == "" {
22987-		return ""
22988-	}
22989-	return span.URIFromPath(w.gowork)
22990-}
22991-
22992-// GO111MODULE returns the value of GO111MODULE to use for running the go
22993-// command. It differs from the user's environment in order to allow for the
22994-// more forgiving default value "auto" when using recent go versions.
22995-//
22996-// TODO(rfindley): it is probably not worthwhile diverging from the go command
22997-// here. The extra forgiveness may be nice, but breaks the invariant that
22998-// running the go command from the command line produces the same build list.
22999-//
23000-// Put differently: we shouldn't go out of our way to make GOPATH work, when
23001-// the go command does not.
23002-func (w workspaceInformation) GO111MODULE() string {
23003-	if w.go111module == "" {
23004-		return "auto"
23005-	}
23006-	return w.go111module
23007-}
23008-
23009-type go111module int
23010-
23011-const (
23012-	off = go111module(iota)
23013-	auto
23014-	on
23015-)
23016-
23017-// goEnv holds important environment variables that gopls cares about.
23018-type goEnv struct {
23019-	gocache, gopath, goroot, goprivate, gomodcache, gowork, goflags string
23020-
23021-	// go111module holds the value of GO111MODULE as reported by go env.
23022-	//
23023-	// Don't use this value directly, because we choose to use a different
23024-	// default (auto) on Go 1.16 and later, to avoid spurious errors. Use
23025-	// the effectiveGO111MODULE method instead.
23026-	go111module string
23027-}
23028-
23029-// loadGoEnv loads `go env` values into the receiver, using the provided user
23030-// environment and go command runner.
23031-func (env *goEnv) load(ctx context.Context, folder string, configEnv []string, runner *gocommand.Runner) error {
23032-	vars := env.vars()
23033-
23034-	// We can save ~200 ms by requesting only the variables we care about.
23035-	args := []string{"-json"}
23036-	for k := range vars {
23037-		args = append(args, k)
23038-	}
23039-
23040-	inv := gocommand.Invocation{
23041-		Verb:       "env",
23042-		Args:       args,
23043-		Env:        configEnv,
23044-		WorkingDir: folder,
23045-	}
23046-	stdout, err := runner.Run(ctx, inv)
23047-	if err != nil {
23048-		return err
23049-	}
23050-	envMap := make(map[string]string)
23051-	if err := json.Unmarshal(stdout.Bytes(), &envMap); err != nil {
23052-		return fmt.Errorf("internal error unmarshaling JSON from 'go env': %w", err)
23053-	}
23054-	for key, ptr := range vars {
23055-		*ptr = envMap[key]
23056-	}
23057-
23058-	return nil
23059-}
23060-
23061-func (env goEnv) String() string {
23062-	var vars []string
23063-	for govar, ptr := range env.vars() {
23064-		vars = append(vars, fmt.Sprintf("%s=%s", govar, *ptr))
23065-	}
23066-	sort.Strings(vars)
23067-	return "[" + strings.Join(vars, ", ") + "]"
23068-}
23069-
23070-// vars returns a map from Go environment variable to field value containing it.
23071-func (env *goEnv) vars() map[string]*string {
23072-	return map[string]*string{
23073-		"GOCACHE":     &env.gocache,
23074-		"GOPATH":      &env.gopath,
23075-		"GOROOT":      &env.goroot,
23076-		"GOPRIVATE":   &env.goprivate,
23077-		"GOMODCACHE":  &env.gomodcache,
23078-		"GO111MODULE": &env.go111module,
23079-		"GOWORK":      &env.gowork,
23080-		"GOFLAGS":     &env.goflags,
23081-	}
23082-}
23083-
23084-// workspaceMode holds various flags defining how the gopls workspace should
23085-// behave. They may be derived from the environment, user configuration, or
23086-// depend on the Go version.
23087-//
23088-// TODO(rfindley): remove workspace mode, in favor of explicit checks.
23089-type workspaceMode int
23090-
23091-const (
23092-	moduleMode workspaceMode = 1 << iota
23093-
23094-	// tempModfile indicates whether or not the -modfile flag should be used.
23095-	tempModfile
23096-)
23097-
23098-func (v *View) ID() string { return v.id }
23099-
23100-// tempModFile creates a temporary go.mod file based on the contents
23101-// of the given go.mod file. On success, it is the caller's
23102-// responsibility to call the cleanup function when the file is no
23103-// longer needed.
23104-func tempModFile(modFh source.FileHandle, gosum []byte) (tmpURI span.URI, cleanup func(), err error) {
23105-	filenameHash := source.Hashf("%s", modFh.URI().Filename())
23106-	tmpMod, err := ioutil.TempFile("", fmt.Sprintf("go.%s.*.mod", filenameHash))
23107-	if err != nil {
23108-		return "", nil, err
23109-	}
23110-	defer tmpMod.Close()
23111-
23112-	tmpURI = span.URIFromPath(tmpMod.Name())
23113-	tmpSumName := sumFilename(tmpURI)
23114-
23115-	content, err := modFh.Read()
23116-	if err != nil {
23117-		return "", nil, err
23118-	}
23119-
23120-	if _, err := tmpMod.Write(content); err != nil {
23121-		return "", nil, err
23122-	}
23123-
23124-	// We use a distinct name here to avoid subtlety around the fact
23125-	// that both 'return' and 'defer' update the "cleanup" variable.
23126-	doCleanup := func() {
23127-		_ = os.Remove(tmpSumName)
23128-		_ = os.Remove(tmpURI.Filename())
23129-	}
23130-
23131-	// Be careful to clean up if we return an error from this function.
23132-	defer func() {
23133-		if err != nil {
23134-			doCleanup()
23135-			cleanup = nil
23136-		}
23137-	}()
23138-
23139-	// Create an analogous go.sum, if one exists.
23140-	if gosum != nil {
23141-		if err := ioutil.WriteFile(tmpSumName, gosum, 0655); err != nil {
23142-			return "", nil, err
23143-		}
23144-	}
23145-
23146-	return tmpURI, doCleanup, nil
23147-}
23148-
23149-// Name returns the user visible name of this view.
23150-func (v *View) Name() string {
23151-	return v.name
23152-}
23153-
23154-// Folder returns the folder at the base of this view.
23155-func (v *View) Folder() span.URI {
23156-	return v.folder
23157-}
23158-
23159-func (v *View) Options() *source.Options {
23160-	v.optionsMu.Lock()
23161-	defer v.optionsMu.Unlock()
23162-	return v.options
23163-}
23164-
23165-func (v *View) FileKind(fh source.FileHandle) source.FileKind {
23166-	// The kind of an unsaved buffer comes from the
23167-	// TextDocumentItem.LanguageID field in the didChange event,
23168-	// not from the file name. They may differ.
23169-	if o, ok := fh.(*Overlay); ok {
23170-		if o.kind != source.UnknownKind {
23171-			return o.kind
23172-		}
23173-	}
23174-
23175-	fext := filepath.Ext(fh.URI().Filename())
23176-	switch fext {
23177-	case ".go":
23178-		return source.Go
23179-	case ".mod":
23180-		return source.Mod
23181-	case ".sum":
23182-		return source.Sum
23183-	case ".work":
23184-		return source.Work
23185-	}
23186-	exts := v.Options().TemplateExtensions
23187-	for _, ext := range exts {
23188-		if fext == ext || fext == "."+ext {
23189-			return source.Tmpl
23190-		}
23191-	}
23192-	// and now what? This should never happen, but it does for cgo before go1.15
23193-	return source.Go
23194-}
23195-
23196-func minorOptionsChange(a, b *source.Options) bool {
23197-	// Check if any of the settings that modify our understanding of files have
23198-	// been changed.
23199-	if !reflect.DeepEqual(a.Env, b.Env) {
23200-		return false
23201-	}
23202-	if !reflect.DeepEqual(a.DirectoryFilters, b.DirectoryFilters) {
23203-		return false
23204-	}
23205-	if !reflect.DeepEqual(a.StandaloneTags, b.StandaloneTags) {
23206-		return false
23207-	}
23208-	if a.ExpandWorkspaceToModule != b.ExpandWorkspaceToModule {
23209-		return false
23210-	}
23211-	if a.MemoryMode != b.MemoryMode {
23212-		return false
23213-	}
23214-	aBuildFlags := make([]string, len(a.BuildFlags))
23215-	bBuildFlags := make([]string, len(b.BuildFlags))
23216-	copy(aBuildFlags, a.BuildFlags)
23217-	copy(bBuildFlags, b.BuildFlags)
23218-	sort.Strings(aBuildFlags)
23219-	sort.Strings(bBuildFlags)
23220-	// the rest of the options are benign
23221-	return reflect.DeepEqual(aBuildFlags, bBuildFlags)
23222-}
23223-
23224-// SetViewOptions sets the options of the given view to new values. Calling
23225-// this may cause the view to be invalidated and a replacement view added to
23226-// the session. If so the new view will be returned, otherwise the original one
23227-// will be returned.
23228-func (s *Session) SetViewOptions(ctx context.Context, v *View, options *source.Options) (*View, error) {
23229-	// no need to rebuild the view if the options were not materially changed
23230-	v.optionsMu.Lock()
23231-	if minorOptionsChange(v.options, options) {
23232-		v.options = options
23233-		v.optionsMu.Unlock()
23234-		return v, nil
23235-	}
23236-	v.optionsMu.Unlock()
23237-	newView, err := s.updateView(ctx, v, options)
23238-	return newView, err
23239-}
23240-
23241-// viewEnv returns a string describing the environment of a newly created view.
23242-//
23243-// It must not be called concurrently with any other view methods.
23244-func viewEnv(v *View) string {
23245-	env := v.options.EnvSlice()
23246-	buildFlags := append([]string{}, v.options.BuildFlags...)
23247-
23248-	var buf bytes.Buffer
23249-	fmt.Fprintf(&buf, `go info for %v
23250-(go dir %s)
23251-(go version %s)
23252-(valid build configuration = %v)
23253-(build flags: %v)
23254-(selected go env: %v)
23255-`,
23256-		v.folder.Filename(),
23257-		v.workingDir().Filename(),
23258-		strings.TrimRight(v.workspaceInformation.goversionOutput, "\n"),
23259-		v.snapshot.ValidBuildConfiguration(),
23260-		buildFlags,
23261-		v.goEnv,
23262-	)
23263-
23264-	for _, v := range env {
23265-		s := strings.SplitN(v, "=", 2)
23266-		if len(s) != 2 {
23267-			continue
23268-		}
23269-	}
23270-
23271-	return buf.String()
23272-}
23273-
23274-func (s *snapshot) RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options) error) error {
23275-	return s.view.importsState.runProcessEnvFunc(ctx, s, fn)
23276-}
23277-
23278-// separated out from its sole use in locateTemplateFiles for testability
23279-func fileHasExtension(path string, suffixes []string) bool {
23280-	ext := filepath.Ext(path)
23281-	if ext != "" && ext[0] == '.' {
23282-		ext = ext[1:]
23283-	}
23284-	for _, s := range suffixes {
23285-		if s != "" && ext == s {
23286-			return true
23287-		}
23288-	}
23289-	return false
23290-}
23291-
23292-// locateTemplateFiles ensures that the snapshot has mapped template files
23293-// within the workspace folder.
23294-func (s *snapshot) locateTemplateFiles(ctx context.Context) {
23295-	if len(s.view.Options().TemplateExtensions) == 0 {
23296-		return
23297-	}
23298-	suffixes := s.view.Options().TemplateExtensions
23299-
23300-	searched := 0
23301-	filterFunc := s.view.filterFunc()
23302-	err := filepath.WalkDir(s.view.folder.Filename(), func(path string, entry os.DirEntry, err error) error {
23303-		if err != nil {
23304-			return err
23305-		}
23306-		if entry.IsDir() {
23307-			return nil
23308-		}
23309-		if fileLimit > 0 && searched > fileLimit {
23310-			return errExhausted
23311-		}
23312-		searched++
23313-		if !fileHasExtension(path, suffixes) {
23314-			return nil
23315-		}
23316-		uri := span.URIFromPath(path)
23317-		if filterFunc(uri) {
23318-			return nil
23319-		}
23320-		// Get the file in order to include it in the snapshot.
23321-		// TODO(golang/go#57558): it is fundamentally broken to track files in this
23322-		// way; we may lose them if configuration or layout changes cause a view to
23323-		// be recreated.
23324-		//
23325-		// Furthermore, this operation must ignore errors, including context
23326-		// cancellation, or risk leaving the snapshot in an undefined state.
23327-		s.GetFile(ctx, uri)
23328-		return nil
23329-	})
23330-	if err != nil {
23331-		event.Error(ctx, "searching for template files failed", err)
23332-	}
23333-}
23334-
23335-func (v *View) contains(uri span.URI) bool {
23336-	// If we've expanded the go dir to a parent directory, consider if the
23337-	// expanded dir contains the uri.
23338-	// TODO(rfindley): should we ignore the root here? It is not provided by the
23339-	// user. It would be better to explicitly consider the set of active modules
23340-	// wherever relevant.
23341-	inGoDir := false
23342-	if source.InDir(v.workingDir().Filename(), v.folder.Filename()) {
23343-		inGoDir = source.InDir(v.workingDir().Filename(), uri.Filename())
23344-	}
23345-	inFolder := source.InDir(v.folder.Filename(), uri.Filename())
23346-
23347-	if !inGoDir && !inFolder {
23348-		return false
23349-	}
23350-
23351-	return !v.filterFunc()(uri)
23352-}
23353-
23354-// filterFunc returns a func that reports whether uri is filtered by the currently configured
23355-// directoryFilters.
23356-func (v *View) filterFunc() func(span.URI) bool {
23357-	filterer := buildFilterer(v.folder.Filename(), v.gomodcache, v.Options())
23358-	return func(uri span.URI) bool {
23359-		// Only filter relative to the configured root directory.
23360-		if source.InDir(v.folder.Filename(), uri.Filename()) {
23361-			return pathExcludedByFilter(strings.TrimPrefix(uri.Filename(), v.folder.Filename()), filterer)
23362-		}
23363-		return false
23364-	}
23365-}
23366-
23367-func (v *View) relevantChange(c source.FileModification) bool {
23368-	// If the file is known to the view, the change is relevant.
23369-	if v.knownFile(c.URI) {
23370-		return true
23371-	}
23372-	// The go.work file may not be "known" because we first access it through the
23373-	// session. As a result, treat changes to the view's go.work file as always
23374-	// relevant, even if they are only on-disk changes.
23375-	//
23376-	// TODO(rfindley): Make sure the go.work files are always known
23377-	// to the view.
23378-	if c.URI == v.effectiveGOWORK() {
23379-		return true
23380-	}
23381-
23382-	// Note: CL 219202 filtered out on-disk changes here that were not known to
23383-	// the view, but this introduces a race when changes arrive before the view
23384-	// is initialized (and therefore, before it knows about files). Since that CL
23385-	// had neither test nor associated issue, and cited only emacs behavior, this
23386-	// logic was deleted.
23387-
23388-	return v.contains(c.URI)
23389-}
23390-
23391-func (v *View) markKnown(uri span.URI) {
23392-	v.knownFilesMu.Lock()
23393-	defer v.knownFilesMu.Unlock()
23394-	if v.knownFiles == nil {
23395-		v.knownFiles = make(map[span.URI]bool)
23396-	}
23397-	v.knownFiles[uri] = true
23398-}
23399-
23400-// knownFile reports whether the specified valid URI (or an alias) is known to the view.
23401-func (v *View) knownFile(uri span.URI) bool {
23402-	v.knownFilesMu.Lock()
23403-	defer v.knownFilesMu.Unlock()
23404-	return v.knownFiles[uri]
23405-}
23406-
23407-// shutdown releases resources associated with the view, and waits for ongoing
23408-// work to complete.
23409-func (v *View) shutdown() {
23410-	// Cancel the initial workspace load if it is still running.
23411-	v.initCancelFirstAttempt()
23412-
23413-	v.snapshotMu.Lock()
23414-	if v.snapshot != nil {
23415-		v.releaseSnapshot()
23416-		v.destroy(v.snapshot, "View.shutdown")
23417-		v.snapshot = nil
23418-		v.releaseSnapshot = nil
23419-	}
23420-	v.snapshotMu.Unlock()
23421-
23422-	v.snapshotWG.Wait()
23423-}
23424-
23425-func (s *snapshot) IgnoredFile(uri span.URI) bool {
23426-	filename := uri.Filename()
23427-	var prefixes []string
23428-	if len(s.workspaceModFiles) == 0 {
23429-		for _, entry := range filepath.SplitList(s.view.gopath) {
23430-			prefixes = append(prefixes, filepath.Join(entry, "src"))
23431-		}
23432-	} else {
23433-		prefixes = append(prefixes, s.view.gomodcache)
23434-		for m := range s.workspaceModFiles {
23435-			prefixes = append(prefixes, span.Dir(m).Filename())
23436-		}
23437-	}
23438-	for _, prefix := range prefixes {
23439-		if strings.HasPrefix(filename, prefix) {
23440-			return checkIgnored(filename[len(prefix):])
23441-		}
23442-	}
23443-	return false
23444-}
23445-
23446-// checkIgnored implements go list's exclusion rules.
23447-// Quoting “go help list”:
23448-//
23449-//	Directory and file names that begin with "." or "_" are ignored
23450-//	by the go tool, as are directories named "testdata".
23451-func checkIgnored(suffix string) bool {
23452-	for _, component := range strings.Split(suffix, string(filepath.Separator)) {
23453-		if len(component) == 0 {
23454-			continue
23455-		}
23456-		if component[0] == '.' || component[0] == '_' || component == "testdata" {
23457-			return true
23458-		}
23459-	}
23460-	return false
23461-}
23462-
23463-func (v *View) Snapshot() (source.Snapshot, func(), error) {
23464-	return v.getSnapshot()
23465-}
23466-
23467-func (v *View) getSnapshot() (*snapshot, func(), error) {
23468-	v.snapshotMu.Lock()
23469-	defer v.snapshotMu.Unlock()
23470-	if v.snapshot == nil {
23471-		return nil, nil, errors.New("view is shutdown")
23472-	}
23473-	return v.snapshot, v.snapshot.Acquire(), nil
23474-}
23475-
23476-func (s *snapshot) initialize(ctx context.Context, firstAttempt bool) {
23477-	select {
23478-	case <-ctx.Done():
23479-		return
23480-	case s.view.initializationSema <- struct{}{}:
23481-	}
23482-
23483-	defer func() {
23484-		<-s.view.initializationSema
23485-	}()
23486-
23487-	s.mu.Lock()
23488-	initialized := s.initialized
23489-	s.mu.Unlock()
23490-
23491-	if initialized {
23492-		return
23493-	}
23494-
23495-	s.loadWorkspace(ctx, firstAttempt)
23496-	s.collectAllKnownSubdirs(ctx)
23497-}
23498-
23499-func (s *snapshot) loadWorkspace(ctx context.Context, firstAttempt bool) (loadErr error) {
23500-	// A failure is retryable if it may have been due to context cancellation,
23501-	// and this is not the initial workspace load (firstAttempt==true).
23502-	//
23503-	// The IWL runs on a detached context with a long (~10m) timeout, so
23504-	// if the context was canceled we consider loading to have failed
23505-	// permanently.
23506-	retryableFailure := func() bool {
23507-		return loadErr != nil && ctx.Err() != nil && !firstAttempt
23508-	}
23509-	defer func() {
23510-		if !retryableFailure() {
23511-			s.mu.Lock()
23512-			s.initialized = true
23513-			s.mu.Unlock()
23514-		}
23515-		if firstAttempt {
23516-			close(s.view.initialWorkspaceLoad)
23517-		}
23518-	}()
23519-
23520-	// TODO(rFindley): we should only locate template files on the first attempt,
23521-	// or guard it via a different mechanism.
23522-	s.locateTemplateFiles(ctx)
23523-
23524-	// Collect module paths to load by parsing go.mod files. If a module fails to
23525-	// parse, capture the parsing failure as a critical diagnostic.
23526-	var scopes []loadScope                  // scopes to load
23527-	var modDiagnostics []*source.Diagnostic // diagnostics for broken go.mod files
23528-	addError := func(uri span.URI, err error) {
23529-		modDiagnostics = append(modDiagnostics, &source.Diagnostic{
23530-			URI:      uri,
23531-			Severity: protocol.SeverityError,
23532-			Source:   source.ListError,
23533-			Message:  err.Error(),
23534-		})
23535-	}
23536-
23537-	if len(s.workspaceModFiles) > 0 {
23538-		for modURI := range s.workspaceModFiles {
23539-			// Be careful not to add context cancellation errors as critical module
23540-			// errors.
23541-			fh, err := s.GetFile(ctx, modURI)
23542-			if err != nil {
23543-				if ctx.Err() == nil {
23544-					addError(modURI, err)
23545-				}
23546-				continue
23547-			}
23548-			parsed, err := s.ParseMod(ctx, fh)
23549-			if err != nil {
23550-				if ctx.Err() == nil {
23551-					addError(modURI, err)
23552-				}
23553-				continue
23554-			}
23555-			if parsed.File == nil || parsed.File.Module == nil {
23556-				addError(modURI, fmt.Errorf("no module path for %s", modURI))
23557-				continue
23558-			}
23559-			path := parsed.File.Module.Mod.Path
23560-			scopes = append(scopes, moduleLoadScope(path))
23561-		}
23562-	} else {
23563-		scopes = append(scopes, viewLoadScope("LOAD_VIEW"))
23564-	}
23565-
23566-	// If we're loading anything, ensure we also load builtin,
23567-	// since it provides fake definitions (and documentation)
23568-	// for types like int that are used everywhere.
23569-	if len(scopes) > 0 {
23570-		scopes = append(scopes, packageLoadScope("builtin"))
23571-	}
23572-	loadErr = s.load(ctx, true, scopes...)
23573-
23574-	if retryableFailure() {
23575-		return loadErr
23576-	}
23577-
23578-	var criticalErr *source.CriticalError
23579-	switch {
23580-	case loadErr != nil && ctx.Err() != nil:
23581-		event.Error(ctx, fmt.Sprintf("initial workspace load: %v", loadErr), loadErr)
23582-		criticalErr = &source.CriticalError{
23583-			MainError: loadErr,
23584-		}
23585-	case loadErr != nil:
23586-		event.Error(ctx, "initial workspace load failed", loadErr)
23587-		extractedDiags := s.extractGoCommandErrors(ctx, loadErr)
23588-		criticalErr = &source.CriticalError{
23589-			MainError:   loadErr,
23590-			Diagnostics: append(modDiagnostics, extractedDiags...),
23591-		}
23592-	case len(modDiagnostics) == 1:
23593-		criticalErr = &source.CriticalError{
23594-			MainError:   fmt.Errorf(modDiagnostics[0].Message),
23595-			Diagnostics: modDiagnostics,
23596-		}
23597-	case len(modDiagnostics) > 1:
23598-		criticalErr = &source.CriticalError{
23599-			MainError:   fmt.Errorf("error loading module names"),
23600-			Diagnostics: modDiagnostics,
23601-		}
23602-	}
23603-
23604-	// Lock the snapshot when setting the initialized error.
23605-	s.mu.Lock()
23606-	defer s.mu.Unlock()
23607-	s.initializedErr = criticalErr
23608-	return loadErr
23609-}
23610-
23611-// invalidateContent invalidates the content of a Go file,
23612-// including any position and type information that depends on it.
23613-//
23614-// invalidateContent returns a non-nil snapshot for the new content, along with
23615-// a callback which the caller must invoke to release that snapshot.
23616-func (v *View) invalidateContent(ctx context.Context, changes map[span.URI]*fileChange, forceReloadMetadata bool) (*snapshot, func()) {
23617-	// Detach the context so that content invalidation cannot be canceled.
23618-	ctx = xcontext.Detach(ctx)
23619-
23620-	// This should be the only time we hold the view's snapshot lock for any period of time.
23621-	v.snapshotMu.Lock()
23622-	defer v.snapshotMu.Unlock()
23623-
23624-	prevSnapshot, prevReleaseSnapshot := v.snapshot, v.releaseSnapshot
23625-
23626-	if prevSnapshot == nil {
23627-		panic("invalidateContent called after shutdown")
23628-	}
23629-
23630-	// Cancel all still-running previous requests, since they would be
23631-	// operating on stale data.
23632-	prevSnapshot.cancel()
23633-
23634-	// Do not clone a snapshot until its view has finished initializing.
23635-	prevSnapshot.AwaitInitialized(ctx)
23636-
23637-	// Save one lease of the cloned snapshot in the view.
23638-	v.snapshot, v.releaseSnapshot = prevSnapshot.clone(ctx, v.baseCtx, changes, forceReloadMetadata)
23639-
23640-	prevReleaseSnapshot()
23641-	v.destroy(prevSnapshot, "View.invalidateContent")
23642-
23643-	// Return a second lease to the caller.
23644-	return v.snapshot, v.snapshot.Acquire()
23645-}
23646-
23647-func (s *Session) getWorkspaceInformation(ctx context.Context, folder span.URI, options *source.Options) (workspaceInformation, error) {
23648-	if err := checkPathCase(folder.Filename()); err != nil {
23649-		return workspaceInformation{}, fmt.Errorf("invalid workspace folder path: %w; check that the casing of the configured workspace folder path agrees with the casing reported by the operating system", err)
23650-	}
23651-	var err error
23652-	var info workspaceInformation
23653-	inv := gocommand.Invocation{
23654-		WorkingDir: folder.Filename(),
23655-		Env:        options.EnvSlice(),
23656-	}
23657-	info.goversion, err = gocommand.GoVersion(ctx, inv, s.gocmdRunner)
23658-	if err != nil {
23659-		return info, err
23660-	}
23661-	info.goversionOutput, err = gocommand.GoVersionOutput(ctx, inv, s.gocmdRunner)
23662-	if err != nil {
23663-		return info, err
23664-	}
23665-	if err := info.goEnv.load(ctx, folder.Filename(), options.EnvSlice(), s.gocmdRunner); err != nil {
23666-		return info, err
23667-	}
23668-	// The value of GOPACKAGESDRIVER is not returned through the go command.
23669-	gopackagesdriver := os.Getenv("GOPACKAGESDRIVER")
23670-	// A user may also have a gopackagesdriver binary on their machine, which
23671-	// works the same way as setting GOPACKAGESDRIVER.
23672-	tool, _ := exec.LookPath("gopackagesdriver")
23673-	info.hasGopackagesDriver = gopackagesdriver != "off" && (gopackagesdriver != "" || tool != "")
23674-
23675-	// filterFunc is the path filter function for this workspace folder. Notably,
23676-	// it is relative to folder (which is specified by the user), not root.
23677-	filterFunc := pathExcludedByFilterFunc(folder.Filename(), info.gomodcache, options)
23678-	info.gomod, err = findWorkspaceModFile(ctx, folder, s, filterFunc)
23679-	if err != nil {
23680-		return info, err
23681-	}
23682-
23683-	return info, nil
23684-}
23685-
23686-// findWorkspaceModFile searches for a single go.mod file relative to the given
23687-// folder URI, using the following algorithm:
23688-//  1. if there is a go.mod file in a parent directory, return it
23689-//  2. else, if there is exactly one nested module, return it
23690-//  3. else, return ""
23691-func findWorkspaceModFile(ctx context.Context, folderURI span.URI, fs source.FileSource, excludePath func(string) bool) (span.URI, error) {
23692-	folder := folderURI.Filename()
23693-	match, err := findRootPattern(ctx, folder, "go.mod", fs)
23694-	if err != nil {
23695-		if ctxErr := ctx.Err(); ctxErr != nil {
23696-			return "", ctxErr
23697-		}
23698-		return "", err
23699-	}
23700-	if match != "" {
23701-		return span.URIFromPath(match), nil
23702-	}
23703-
23704-	// ...else we should check if there's exactly one nested module.
23705-	all, err := findModules(folderURI, excludePath, 2)
23706-	if err == errExhausted {
23707-		// Fall-back behavior: if we don't find any modules after searching 10000
23708-		// files, assume there are none.
23709-		event.Log(ctx, fmt.Sprintf("stopped searching for modules after %d files", fileLimit))
23710-		return "", nil
23711-	}
23712-	if err != nil {
23713-		return "", err
23714-	}
23715-	if len(all) == 1 {
23716-		// range to access first element.
23717-		for uri := range all {
23718-			return uri, nil
23719-		}
23720-	}
23721-	return "", nil
23722-}
23723-
23724-// workingDir returns the directory from which to run Go commands.
23725-//
23726-// The only case where this should matter is if we've narrowed the workspace to
23727-// a singular nested module. In that case, the go command won't be able to find
23728-// the module unless we tell it the nested directory.
23729-func (v *View) workingDir() span.URI {
23730-	// Note: if gowork is in use, this will default to the workspace folder. In
23731-	// the past, we would instead use the folder containing go.work. This should
23732-	// not make a difference, and in fact may improve go list error messages.
23733-	//
23734-	// TODO(golang/go#57514): eliminate the expandWorkspaceToModule setting
23735-	// entirely.
23736-	if v.Options().ExpandWorkspaceToModule && v.gomod != "" {
23737-		return span.Dir(v.gomod)
23738-	}
23739-	return v.folder
23740-}
23741-
23742-// findRootPattern looks for files with the given basename in dir or any parent
23743-// directory of dir, using the provided FileSource. It returns the first match,
23744-// starting from dir and search parents.
23745-//
23746-// The resulting string is either the file path of a matching file with the
23747-// given basename, or "" if none was found.
23748-func findRootPattern(ctx context.Context, dir, basename string, fs source.FileSource) (string, error) {
23749-	for dir != "" {
23750-		target := filepath.Join(dir, basename)
23751-		exists, err := fileExists(ctx, span.URIFromPath(target), fs)
23752-		if err != nil {
23753-			return "", err // not readable or context cancelled
23754-		}
23755-		if exists {
23756-			return target, nil
23757-		}
23758-		// Trailing separators must be trimmed, otherwise filepath.Split is a noop.
23759-		next, _ := filepath.Split(strings.TrimRight(dir, string(filepath.Separator)))
23760-		if next == dir {
23761-			break
23762-		}
23763-		dir = next
23764-	}
23765-	return "", nil
23766-}
23767-
23768-// OS-specific path case check, for case-insensitive filesystems.
23769-var checkPathCase = defaultCheckPathCase
23770-
23771-func defaultCheckPathCase(path string) error {
23772-	return nil
23773-}
23774-
23775-func (v *View) IsGoPrivatePath(target string) bool {
23776-	return globsMatchPath(v.goprivate, target)
23777-}
23778-
23779-func (v *View) ModuleUpgrades(modfile span.URI) map[string]string {
23780-	v.moduleUpgradesMu.Lock()
23781-	defer v.moduleUpgradesMu.Unlock()
23782-
23783-	upgrades := map[string]string{}
23784-	for mod, ver := range v.moduleUpgrades[modfile] {
23785-		upgrades[mod] = ver
23786-	}
23787-	return upgrades
23788-}
23789-
23790-func (v *View) RegisterModuleUpgrades(modfile span.URI, upgrades map[string]string) {
23791-	// Return early if there are no upgrades.
23792-	if len(upgrades) == 0 {
23793-		return
23794-	}
23795-
23796-	v.moduleUpgradesMu.Lock()
23797-	defer v.moduleUpgradesMu.Unlock()
23798-
23799-	m := v.moduleUpgrades[modfile]
23800-	if m == nil {
23801-		m = make(map[string]string)
23802-		v.moduleUpgrades[modfile] = m
23803-	}
23804-	for mod, ver := range upgrades {
23805-		m[mod] = ver
23806-	}
23807-}
23808-
23809-func (v *View) ClearModuleUpgrades(modfile span.URI) {
23810-	v.moduleUpgradesMu.Lock()
23811-	defer v.moduleUpgradesMu.Unlock()
23812-
23813-	delete(v.moduleUpgrades, modfile)
23814-}
23815-
23816-const maxGovulncheckResultAge = 1 * time.Hour // Invalidate results older than this limit.
23817-var timeNow = time.Now                        // for testing
23818-
23819-func (v *View) Vulnerabilities(modfiles ...span.URI) map[span.URI]*govulncheck.Result {
23820-	m := make(map[span.URI]*govulncheck.Result)
23821-	now := timeNow()
23822-	v.vulnsMu.Lock()
23823-	defer v.vulnsMu.Unlock()
23824-
23825-	if len(modfiles) == 0 { // empty means all modfiles
23826-		for modfile := range v.vulns {
23827-			modfiles = append(modfiles, modfile)
23828-		}
23829-	}
23830-	for _, modfile := range modfiles {
23831-		vuln := v.vulns[modfile]
23832-		if vuln != nil && now.Sub(vuln.AsOf) > maxGovulncheckResultAge {
23833-			v.vulns[modfile] = nil // same as SetVulnerabilities(modfile, nil)
23834-			vuln = nil
23835-		}
23836-		m[modfile] = vuln
23837-	}
23838-	return m
23839-}
23840-
23841-func (v *View) SetVulnerabilities(modfile span.URI, vulns *govulncheck.Result) {
23842-	v.vulnsMu.Lock()
23843-	defer v.vulnsMu.Unlock()
23844-
23845-	v.vulns[modfile] = vulns
23846-}
23847-
23848-func (v *View) GoVersion() int {
23849-	return v.workspaceInformation.goversion
23850-}
23851-
23852-func (v *View) GoVersionString() string {
23853-	return gocommand.ParseGoVersionOutput(v.workspaceInformation.goversionOutput)
23854-}
23855-
23856-// Copied from
23857-// https://cs.opensource.google/go/go/+/master:src/cmd/go/internal/str/path.go;l=58;drc=2910c5b4a01a573ebc97744890a07c1a3122c67a
23858-func globsMatchPath(globs, target string) bool {
23859-	for globs != "" {
23860-		// Extract next non-empty glob in comma-separated list.
23861-		var glob string
23862-		if i := strings.Index(globs, ","); i >= 0 {
23863-			glob, globs = globs[:i], globs[i+1:]
23864-		} else {
23865-			glob, globs = globs, ""
23866-		}
23867-		if glob == "" {
23868-			continue
23869-		}
23870-
23871-		// A glob with N+1 path elements (N slashes) needs to be matched
23872-		// against the first N+1 path elements of target,
23873-		// which end just before the N+1'th slash.
23874-		n := strings.Count(glob, "/")
23875-		prefix := target
23876-		// Walk target, counting slashes, truncating at the N+1'th slash.
23877-		for i := 0; i < len(target); i++ {
23878-			if target[i] == '/' {
23879-				if n == 0 {
23880-					prefix = target[:i]
23881-					break
23882-				}
23883-				n--
23884-			}
23885-		}
23886-		if n > 0 {
23887-			// Not enough prefix elements.
23888-			continue
23889-		}
23890-		matched, _ := path.Match(glob, prefix)
23891-		if matched {
23892-			return true
23893-		}
23894-	}
23895-	return false
23896-}
23897-
23898-var modFlagRegexp = regexp.MustCompile(`-mod[ =](\w+)`)
23899-
23900-// TODO(rstambler): Consolidate modURI and modContent back into a FileHandle
23901-// after we have a version of the workspace go.mod file on disk. Getting a
23902-// FileHandle from the cache for temporary files is problematic, since we
23903-// cannot delete it.
23904-func (s *snapshot) vendorEnabled(ctx context.Context, modURI span.URI, modContent []byte) (bool, error) {
23905-	// Legacy GOPATH workspace?
23906-	if s.workspaceMode()&moduleMode == 0 {
23907-		return false, nil
23908-	}
23909-
23910-	// Explicit -mod flag?
23911-	matches := modFlagRegexp.FindStringSubmatch(s.view.goflags)
23912-	if len(matches) != 0 {
23913-		modFlag := matches[1]
23914-		if modFlag != "" {
23915-			// Don't override an explicit '-mod=vendor' argument.
23916-			// We do want to override '-mod=readonly': it would break various module code lenses,
23917-			// and on 1.16 we know -modfile is available, so we won't mess with go.mod anyway.
23918-			return modFlag == "vendor", nil
23919-		}
23920-	}
23921-
23922-	modFile, err := modfile.Parse(modURI.Filename(), modContent, nil)
23923-	if err != nil {
23924-		return false, err
23925-	}
23926-
23927-	// No vendor directory?
23928-	// TODO(golang/go#57514): this is wrong if the working dir is not the module
23929-	// root.
23930-	if fi, err := os.Stat(filepath.Join(s.view.workingDir().Filename(), "vendor")); err != nil || !fi.IsDir() {
23931-		return false, nil
23932-	}
23933-
23934-	// Vendoring enabled by default by go declaration in go.mod?
23935-	vendorEnabled := modFile.Go != nil && modFile.Go.Version != "" && semver.Compare("v"+modFile.Go.Version, "v1.14") >= 0
23936-	return vendorEnabled, nil
23937-}
23938-
23939-// TODO(rfindley): clean up the redundancy of allFilesExcluded,
23940-// pathExcludedByFilterFunc, pathExcludedByFilter, view.filterFunc...
23941-func allFilesExcluded(files []string, filterFunc func(span.URI) bool) bool {
23942-	for _, f := range files {
23943-		uri := span.URIFromPath(f)
23944-		if !filterFunc(uri) {
23945-			return false
23946-		}
23947-	}
23948-	return true
23949-}
23950-
23951-func pathExcludedByFilterFunc(folder, gomodcache string, opts *source.Options) func(string) bool {
23952-	filterer := buildFilterer(folder, gomodcache, opts)
23953-	return func(path string) bool {
23954-		return pathExcludedByFilter(path, filterer)
23955-	}
23956-}
23957-
23958-// pathExcludedByFilter reports whether the path (relative to the workspace
23959-// folder) should be excluded by the configured directory filters.
23960-//
23961-// TODO(rfindley): passing root and gomodcache here makes it confusing whether
23962-// path should be absolute or relative, and has already caused at least one
23963-// bug.
23964-func pathExcludedByFilter(path string, filterer *source.Filterer) bool {
23965-	path = strings.TrimPrefix(filepath.ToSlash(path), "/")
23966-	return filterer.Disallow(path)
23967-}
23968-
23969-func buildFilterer(folder, gomodcache string, opts *source.Options) *source.Filterer {
23970-	filters := opts.DirectoryFilters
23971-
23972-	if pref := strings.TrimPrefix(gomodcache, folder); pref != gomodcache {
23973-		modcacheFilter := "-" + strings.TrimPrefix(filepath.ToSlash(pref), "/")
23974-		filters = append(filters, modcacheFilter)
23975-	}
23976-	return source.NewFilterer(filters)
23977-}
23978diff -urN a/gopls/internal/lsp/cache/view_test.go b/gopls/internal/lsp/cache/view_test.go
23979--- a/gopls/internal/lsp/cache/view_test.go	2000-01-01 00:00:00.000000000 -0000
23980+++ b/gopls/internal/lsp/cache/view_test.go	1970-01-01 00:00:00.000000000 +0000
23981@@ -1,278 +0,0 @@
23982-// Copyright 2020 The Go Authors. All rights reserved.
23983-// Use of this source code is governed by a BSD-style
23984-// license that can be found in the LICENSE file.
23985-package cache
23986-
23987-import (
23988-	"context"
23989-	"encoding/json"
23990-	"io/ioutil"
23991-	"os"
23992-	"path/filepath"
23993-	"testing"
23994-	"time"
23995-
23996-	"github.com/google/go-cmp/cmp"
23997-	"golang.org/x/tools/gopls/internal/govulncheck"
23998-	"golang.org/x/tools/gopls/internal/lsp/fake"
23999-	"golang.org/x/tools/gopls/internal/lsp/source"
24000-	"golang.org/x/tools/gopls/internal/span"
24001-)
24002-
24003-func TestCaseInsensitiveFilesystem(t *testing.T) {
24004-	base, err := ioutil.TempDir("", t.Name())
24005-	if err != nil {
24006-		t.Fatal(err)
24007-	}
24008-
24009-	inner := filepath.Join(base, "a/B/c/DEFgh")
24010-	if err := os.MkdirAll(inner, 0777); err != nil {
24011-		t.Fatal(err)
24012-	}
24013-	file := filepath.Join(inner, "f.go")
24014-	if err := ioutil.WriteFile(file, []byte("hi"), 0777); err != nil {
24015-		t.Fatal(err)
24016-	}
24017-	if _, err := os.Stat(filepath.Join(inner, "F.go")); err != nil {
24018-		t.Skip("filesystem is case-sensitive")
24019-	}
24020-
24021-	tests := []struct {
24022-		path string
24023-		err  bool
24024-	}{
24025-		{file, false},
24026-		{filepath.Join(inner, "F.go"), true},
24027-		{filepath.Join(base, "a/b/c/defgh/f.go"), true},
24028-	}
24029-	for _, tt := range tests {
24030-		err := checkPathCase(tt.path)
24031-		if err != nil != tt.err {
24032-			t.Errorf("checkPathCase(%q) = %v, wanted error: %v", tt.path, err, tt.err)
24033-		}
24034-	}
24035-}
24036-
24037-func TestFindWorkspaceModFile(t *testing.T) {
24038-	workspace := `
24039--- a/go.mod --
24040-module a
24041--- a/x/x.go
24042-package x
24043--- a/x/y/y.go
24044-package x
24045--- b/go.mod --
24046-module b
24047--- b/c/go.mod --
24048-module bc
24049--- d/gopls.mod --
24050-module d-goplsworkspace
24051--- d/e/go.mod --
24052-module de
24053--- f/g/go.mod --
24054-module fg
24055-`
24056-	dir, err := fake.Tempdir(fake.UnpackTxt(workspace))
24057-	if err != nil {
24058-		t.Fatal(err)
24059-	}
24060-	defer os.RemoveAll(dir)
24061-
24062-	tests := []struct {
24063-		folder, want string
24064-	}{
24065-		{"", ""}, // no module at root, and more than one nested module
24066-		{"a", "a/go.mod"},
24067-		{"a/x", "a/go.mod"},
24068-		{"a/x/y", "a/go.mod"},
24069-		{"b/c", "b/c/go.mod"},
24070-		{"d", "d/e/go.mod"},
24071-		{"d/e", "d/e/go.mod"},
24072-		{"f", "f/g/go.mod"},
24073-	}
24074-
24075-	for _, test := range tests {
24076-		ctx := context.Background()
24077-		rel := fake.RelativeTo(dir)
24078-		folderURI := span.URIFromPath(rel.AbsPath(test.folder))
24079-		excludeNothing := func(string) bool { return false }
24080-		got, err := findWorkspaceModFile(ctx, folderURI, New(nil), excludeNothing)
24081-		if err != nil {
24082-			t.Fatal(err)
24083-		}
24084-		want := span.URI("")
24085-		if test.want != "" {
24086-			want = span.URIFromPath(rel.AbsPath(test.want))
24087-		}
24088-		if got != want {
24089-			t.Errorf("findWorkspaceModFile(%q) = %q, want %q", test.folder, got, want)
24090-		}
24091-	}
24092-}
24093-
24094-func TestInVendor(t *testing.T) {
24095-	for _, tt := range []struct {
24096-		path     string
24097-		inVendor bool
24098-	}{
24099-		{"foo/vendor/x.go", false},
24100-		{"foo/vendor/x/x.go", true},
24101-		{"foo/x.go", false},
24102-		{"foo/vendor/foo.txt", false},
24103-		{"foo/vendor/modules.txt", false},
24104-	} {
24105-		if got := inVendor(span.URIFromPath(tt.path)); got != tt.inVendor {
24106-			t.Errorf("expected %s inVendor %v, got %v", tt.path, tt.inVendor, got)
24107-		}
24108-	}
24109-}
24110-
24111-func TestFilters(t *testing.T) {
24112-	tests := []struct {
24113-		filters  []string
24114-		included []string
24115-		excluded []string
24116-	}{
24117-		{
24118-			included: []string{"x"},
24119-		},
24120-		{
24121-			filters:  []string{"-"},
24122-			excluded: []string{"x", "x/a"},
24123-		},
24124-		{
24125-			filters:  []string{"-x", "+y"},
24126-			included: []string{"y", "y/a", "z"},
24127-			excluded: []string{"x", "x/a"},
24128-		},
24129-		{
24130-			filters:  []string{"-x", "+x/y", "-x/y/z"},
24131-			included: []string{"x/y", "x/y/a", "a"},
24132-			excluded: []string{"x", "x/a", "x/y/z/a"},
24133-		},
24134-		{
24135-			filters:  []string{"+foobar", "-foo"},
24136-			included: []string{"foobar", "foobar/a"},
24137-			excluded: []string{"foo", "foo/a"},
24138-		},
24139-	}
24140-
24141-	for _, tt := range tests {
24142-		filterer := source.NewFilterer(tt.filters)
24143-		for _, inc := range tt.included {
24144-			if pathExcludedByFilter(inc, filterer) {
24145-				t.Errorf("filters %q excluded %v, wanted included", tt.filters, inc)
24146-			}
24147-		}
24148-		for _, exc := range tt.excluded {
24149-			if !pathExcludedByFilter(exc, filterer) {
24150-				t.Errorf("filters %q included %v, wanted excluded", tt.filters, exc)
24151-			}
24152-		}
24153-	}
24154-}
24155-
24156-func TestSuffixes(t *testing.T) {
24157-	type file struct {
24158-		path string
24159-		want bool
24160-	}
24161-	type cases struct {
24162-		option []string
24163-		files  []file
24164-	}
24165-	tests := []cases{
24166-		{[]string{"tmpl", "gotmpl"}, []file{ // default
24167-			{"foo", false},
24168-			{"foo.tmpl", true},
24169-			{"foo.gotmpl", true},
24170-			{"tmpl", false},
24171-			{"tmpl.go", false}},
24172-		},
24173-		{[]string{"tmpl", "gotmpl", "html", "gohtml"}, []file{
24174-			{"foo.gotmpl", true},
24175-			{"foo.html", true},
24176-			{"foo.gohtml", true},
24177-			{"html", false}},
24178-		},
24179-		{[]string{"tmpl", "gotmpl", ""}, []file{ // possible user mistake
24180-			{"foo.gotmpl", true},
24181-			{"foo.go", false},
24182-			{"foo", false}},
24183-		},
24184-	}
24185-	for _, a := range tests {
24186-		suffixes := a.option
24187-		for _, b := range a.files {
24188-			got := fileHasExtension(b.path, suffixes)
24189-			if got != b.want {
24190-				t.Errorf("got %v, want %v, option %q, file %q (%+v)",
24191-					got, b.want, a.option, b.path, b)
24192-			}
24193-		}
24194-	}
24195-}
24196-
24197-func TestView_Vulnerabilities(t *testing.T) {
24198-	// TODO(hyangah): use t.Cleanup when we get rid of go1.13 legacy CI.
24199-	defer func() { timeNow = time.Now }()
24200-
24201-	now := time.Now()
24202-
24203-	view := &View{
24204-		vulns: make(map[span.URI]*govulncheck.Result),
24205-	}
24206-	file1, file2 := span.URIFromPath("f1/go.mod"), span.URIFromPath("f2/go.mod")
24207-
24208-	vuln1 := &govulncheck.Result{AsOf: now.Add(-(maxGovulncheckResultAge * 3) / 4)} // already ~3/4*maxGovulncheckResultAge old
24209-	view.SetVulnerabilities(file1, vuln1)
24210-
24211-	vuln2 := &govulncheck.Result{AsOf: now} // fresh.
24212-	view.SetVulnerabilities(file2, vuln2)
24213-
24214-	t.Run("fresh", func(t *testing.T) {
24215-		got := view.Vulnerabilities()
24216-		want := map[span.URI]*govulncheck.Result{
24217-			file1: vuln1,
24218-			file2: vuln2,
24219-		}
24220-
24221-		if diff := cmp.Diff(toJSON(want), toJSON(got)); diff != "" {
24222-			t.Errorf("view.Vulnerabilities() mismatch (-want +got):\n%s", diff)
24223-		}
24224-	})
24225-
24226-	// maxGovulncheckResultAge/2 later
24227-	timeNow = func() time.Time { return now.Add(maxGovulncheckResultAge / 2) }
24228-	t.Run("after30min", func(t *testing.T) {
24229-		got := view.Vulnerabilities()
24230-		want := map[span.URI]*govulncheck.Result{
24231-			file1: nil, // expired.
24232-			file2: vuln2,
24233-		}
24234-
24235-		if diff := cmp.Diff(toJSON(want), toJSON(got)); diff != "" {
24236-			t.Errorf("view.Vulnerabilities() mismatch (-want +got):\n%s", diff)
24237-		}
24238-	})
24239-
24240-	// maxGovulncheckResultAge later
24241-	timeNow = func() time.Time { return now.Add(maxGovulncheckResultAge + time.Minute) }
24242-
24243-	t.Run("after1hr", func(t *testing.T) {
24244-		got := view.Vulnerabilities()
24245-		want := map[span.URI]*govulncheck.Result{
24246-			file1: nil,
24247-			file2: nil,
24248-		}
24249-
24250-		if diff := cmp.Diff(toJSON(want), toJSON(got)); diff != "" {
24251-			t.Errorf("view.Vulnerabilities() mismatch (-want +got):\n%s", diff)
24252-		}
24253-	})
24254-}
24255-
24256-func toJSON(x interface{}) string {
24257-	b, _ := json.MarshalIndent(x, "", " ")
24258-	return string(b)
24259-}
24260diff -urN a/gopls/internal/lsp/cache/workspace.go b/gopls/internal/lsp/cache/workspace.go
24261--- a/gopls/internal/lsp/cache/workspace.go	2000-01-01 00:00:00.000000000 -0000
24262+++ b/gopls/internal/lsp/cache/workspace.go	1970-01-01 00:00:00.000000000 +0000
24263@@ -1,177 +0,0 @@
24264-// Copyright 2020 The Go Authors. All rights reserved.
24265-// Use of this source code is governed by a BSD-style
24266-// license that can be found in the LICENSE file.
24267-
24268-package cache
24269-
24270-import (
24271-	"context"
24272-	"errors"
24273-	"fmt"
24274-	"os"
24275-	"path/filepath"
24276-	"sort"
24277-	"strings"
24278-
24279-	"golang.org/x/mod/modfile"
24280-	"golang.org/x/tools/gopls/internal/lsp/source"
24281-	"golang.org/x/tools/gopls/internal/span"
24282-)
24283-
24284-// TODO(rfindley): now that experimentalWorkspaceModule is gone, this file can
24285-// be massively cleaned up and/or removed.
24286-
24287-// computeWorkspaceModFiles computes the set of workspace mod files based on the
24288-// value of go.mod, go.work, and GO111MODULE.
24289-func computeWorkspaceModFiles(ctx context.Context, gomod, gowork span.URI, go111module go111module, fs source.FileSource) (map[span.URI]struct{}, error) {
24290-	if go111module == off {
24291-		return nil, nil
24292-	}
24293-	if gowork != "" {
24294-		fh, err := fs.GetFile(ctx, gowork)
24295-		if err != nil {
24296-			return nil, err
24297-		}
24298-		content, err := fh.Read()
24299-		if err != nil {
24300-			return nil, err
24301-		}
24302-		filename := gowork.Filename()
24303-		dir := filepath.Dir(filename)
24304-		workFile, err := modfile.ParseWork(filename, content, nil)
24305-		if err != nil {
24306-			return nil, fmt.Errorf("parsing go.work: %w", err)
24307-		}
24308-		modFiles := make(map[span.URI]struct{})
24309-		for _, use := range workFile.Use {
24310-			modDir := filepath.FromSlash(use.Path)
24311-			if !filepath.IsAbs(modDir) {
24312-				modDir = filepath.Join(dir, modDir)
24313-			}
24314-			modURI := span.URIFromPath(filepath.Join(modDir, "go.mod"))
24315-			modFiles[modURI] = struct{}{}
24316-		}
24317-		return modFiles, nil
24318-	}
24319-	if gomod != "" {
24320-		return map[span.URI]struct{}{gomod: {}}, nil
24321-	}
24322-	return nil, nil
24323-}
24324-
24325-// dirs returns the workspace directories for the loaded modules.
24326-//
24327-// A workspace directory is, roughly speaking, a directory for which we care
24328-// about file changes. This is used for the purpose of registering file
24329-// watching patterns, and expanding directory modifications to their adjacent
24330-// files.
24331-//
24332-// TODO(rfindley): move this to snapshot.go.
24333-// TODO(rfindley): can we make this abstraction simpler and/or more accurate?
24334-func (s *snapshot) dirs(ctx context.Context) []span.URI {
24335-	dirSet := make(map[span.URI]struct{})
24336-
24337-	// Dirs should, at the very least, contain the working directory and folder.
24338-	dirSet[s.view.workingDir()] = struct{}{}
24339-	dirSet[s.view.folder] = struct{}{}
24340-
24341-	// Additionally, if e.g. go.work indicates other workspace modules, we should
24342-	// include their directories too.
24343-	if s.workspaceModFilesErr == nil {
24344-		for modFile := range s.workspaceModFiles {
24345-			dir := filepath.Dir(modFile.Filename())
24346-			dirSet[span.URIFromPath(dir)] = struct{}{}
24347-		}
24348-	}
24349-	var dirs []span.URI
24350-	for d := range dirSet {
24351-		dirs = append(dirs, d)
24352-	}
24353-	sort.Slice(dirs, func(i, j int) bool { return dirs[i] < dirs[j] })
24354-	return dirs
24355-}
24356-
24357-// isGoMod reports if uri is a go.mod file.
24358-func isGoMod(uri span.URI) bool {
24359-	return filepath.Base(uri.Filename()) == "go.mod"
24360-}
24361-
24362-// isGoWork reports if uri is a go.work file.
24363-func isGoWork(uri span.URI) bool {
24364-	return filepath.Base(uri.Filename()) == "go.work"
24365-}
24366-
24367-// fileExists reports if the file uri exists within source.
24368-func fileExists(ctx context.Context, uri span.URI, source source.FileSource) (bool, error) {
24369-	fh, err := source.GetFile(ctx, uri)
24370-	if err != nil {
24371-		return false, err
24372-	}
24373-	return fileHandleExists(fh)
24374-}
24375-
24376-// fileHandleExists reports if the file underlying fh actually exits.
24377-func fileHandleExists(fh source.FileHandle) (bool, error) {
24378-	_, err := fh.Read()
24379-	if err == nil {
24380-		return true, nil
24381-	}
24382-	if os.IsNotExist(err) {
24383-		return false, nil
24384-	}
24385-	return false, err
24386-}
24387-
24388-// errExhausted is returned by findModules if the file scan limit is reached.
24389-var errExhausted = errors.New("exhausted")
24390-
24391-// Limit go.mod search to 1 million files. As a point of reference,
24392-// Kubernetes has 22K files (as of 2020-11-24).
24393-const fileLimit = 1000000
24394-
24395-// findModules recursively walks the root directory looking for go.mod files,
24396-// returning the set of modules it discovers. If modLimit is non-zero,
24397-// searching stops once modLimit modules have been found.
24398-//
24399-// TODO(rfindley): consider overlays.
24400-func findModules(root span.URI, excludePath func(string) bool, modLimit int) (map[span.URI]struct{}, error) {
24401-	// Walk the view's folder to find all modules in the view.
24402-	modFiles := make(map[span.URI]struct{})
24403-	searched := 0
24404-	errDone := errors.New("done")
24405-	err := filepath.Walk(root.Filename(), func(path string, info os.FileInfo, err error) error {
24406-		if err != nil {
24407-			// Probably a permission error. Keep looking.
24408-			return filepath.SkipDir
24409-		}
24410-		// For any path that is not the workspace folder, check if the path
24411-		// would be ignored by the go command. Vendor directories also do not
24412-		// contain workspace modules.
24413-		if info.IsDir() && path != root.Filename() {
24414-			suffix := strings.TrimPrefix(path, root.Filename())
24415-			switch {
24416-			case checkIgnored(suffix),
24417-				strings.Contains(filepath.ToSlash(suffix), "/vendor/"),
24418-				excludePath(suffix):
24419-				return filepath.SkipDir
24420-			}
24421-		}
24422-		// We're only interested in go.mod files.
24423-		uri := span.URIFromPath(path)
24424-		if isGoMod(uri) {
24425-			modFiles[uri] = struct{}{}
24426-		}
24427-		if modLimit > 0 && len(modFiles) >= modLimit {
24428-			return errDone
24429-		}
24430-		searched++
24431-		if fileLimit > 0 && searched >= fileLimit {
24432-			return errExhausted
24433-		}
24434-		return nil
24435-	})
24436-	if err == errDone {
24437-		return modFiles, nil
24438-	}
24439-	return modFiles, err
24440-}
24441diff -urN a/gopls/internal/lsp/call_hierarchy.go b/gopls/internal/lsp/call_hierarchy.go
24442--- a/gopls/internal/lsp/call_hierarchy.go	2000-01-01 00:00:00.000000000 -0000
24443+++ b/gopls/internal/lsp/call_hierarchy.go	1970-01-01 00:00:00.000000000 +0000
24444@@ -1,42 +0,0 @@
24445-// Copyright 2020 The Go Authors. All rights reserved.
24446-// Use of this source code is governed by a BSD-style
24447-// license that can be found in the LICENSE file.
24448-
24449-package lsp
24450-
24451-import (
24452-	"context"
24453-
24454-	"golang.org/x/tools/gopls/internal/lsp/protocol"
24455-	"golang.org/x/tools/gopls/internal/lsp/source"
24456-)
24457-
24458-func (s *Server) prepareCallHierarchy(ctx context.Context, params *protocol.CallHierarchyPrepareParams) ([]protocol.CallHierarchyItem, error) {
24459-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.Go)
24460-	defer release()
24461-	if !ok {
24462-		return nil, err
24463-	}
24464-
24465-	return source.PrepareCallHierarchy(ctx, snapshot, fh, params.Position)
24466-}
24467-
24468-func (s *Server) incomingCalls(ctx context.Context, params *protocol.CallHierarchyIncomingCallsParams) ([]protocol.CallHierarchyIncomingCall, error) {
24469-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.Item.URI, source.Go)
24470-	defer release()
24471-	if !ok {
24472-		return nil, err
24473-	}
24474-
24475-	return source.IncomingCalls(ctx, snapshot, fh, params.Item.Range.Start)
24476-}
24477-
24478-func (s *Server) outgoingCalls(ctx context.Context, params *protocol.CallHierarchyOutgoingCallsParams) ([]protocol.CallHierarchyOutgoingCall, error) {
24479-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.Item.URI, source.Go)
24480-	defer release()
24481-	if !ok {
24482-		return nil, err
24483-	}
24484-
24485-	return source.OutgoingCalls(ctx, snapshot, fh, params.Item.Range.Start)
24486-}
24487diff -urN a/gopls/internal/lsp/cmd/call_hierarchy.go b/gopls/internal/lsp/cmd/call_hierarchy.go
24488--- a/gopls/internal/lsp/cmd/call_hierarchy.go	2000-01-01 00:00:00.000000000 -0000
24489+++ b/gopls/internal/lsp/cmd/call_hierarchy.go	1970-01-01 00:00:00.000000000 +0000
24490@@ -1,142 +0,0 @@
24491-// Copyright 2020 The Go Authors. All rights reserved.
24492-// Use of this source code is governed by a BSD-style
24493-// license that can be found in the LICENSE file.
24494-
24495-package cmd
24496-
24497-import (
24498-	"context"
24499-	"flag"
24500-	"fmt"
24501-	"strings"
24502-
24503-	"golang.org/x/tools/gopls/internal/lsp/protocol"
24504-	"golang.org/x/tools/gopls/internal/span"
24505-	"golang.org/x/tools/internal/tool"
24506-)
24507-
24508-// callHierarchy implements the callHierarchy verb for gopls.
24509-type callHierarchy struct {
24510-	app *Application
24511-}
24512-
24513-func (c *callHierarchy) Name() string      { return "call_hierarchy" }
24514-func (c *callHierarchy) Parent() string    { return c.app.Name() }
24515-func (c *callHierarchy) Usage() string     { return "<position>" }
24516-func (c *callHierarchy) ShortHelp() string { return "display selected identifier's call hierarchy" }
24517-func (c *callHierarchy) DetailedHelp(f *flag.FlagSet) {
24518-	fmt.Fprint(f.Output(), `
24519-Example:
24520-
24521-	$ # 1-indexed location (:line:column or :#offset) of the target identifier
24522-	$ gopls call_hierarchy helper/helper.go:8:6
24523-	$ gopls call_hierarchy helper/helper.go:#53
24524-`)
24525-	printFlagDefaults(f)
24526-}
24527-
24528-func (c *callHierarchy) Run(ctx context.Context, args ...string) error {
24529-	if len(args) != 1 {
24530-		return tool.CommandLineErrorf("call_hierarchy expects 1 argument (position)")
24531-	}
24532-
24533-	conn, err := c.app.connect(ctx)
24534-	if err != nil {
24535-		return err
24536-	}
24537-	defer conn.terminate(ctx)
24538-
24539-	from := span.Parse(args[0])
24540-	file := conn.openFile(ctx, from.URI())
24541-	if file.err != nil {
24542-		return file.err
24543-	}
24544-
24545-	loc, err := file.mapper.SpanLocation(from)
24546-	if err != nil {
24547-		return err
24548-	}
24549-
24550-	p := protocol.CallHierarchyPrepareParams{
24551-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
24552-	}
24553-
24554-	callItems, err := conn.PrepareCallHierarchy(ctx, &p)
24555-	if err != nil {
24556-		return err
24557-	}
24558-	if len(callItems) == 0 {
24559-		return fmt.Errorf("function declaration identifier not found at %v", args[0])
24560-	}
24561-
24562-	for _, item := range callItems {
24563-		incomingCalls, err := conn.IncomingCalls(ctx, &protocol.CallHierarchyIncomingCallsParams{Item: item})
24564-		if err != nil {
24565-			return err
24566-		}
24567-		for i, call := range incomingCalls {
24568-			// From the spec: CallHierarchyIncomingCall.FromRanges is relative to
24569-			// the caller denoted by CallHierarchyIncomingCall.from.
24570-			printString, err := callItemPrintString(ctx, conn, call.From, call.From.URI, call.FromRanges)
24571-			if err != nil {
24572-				return err
24573-			}
24574-			fmt.Printf("caller[%d]: %s\n", i, printString)
24575-		}
24576-
24577-		printString, err := callItemPrintString(ctx, conn, item, "", nil)
24578-		if err != nil {
24579-			return err
24580-		}
24581-		fmt.Printf("identifier: %s\n", printString)
24582-
24583-		outgoingCalls, err := conn.OutgoingCalls(ctx, &protocol.CallHierarchyOutgoingCallsParams{Item: item})
24584-		if err != nil {
24585-			return err
24586-		}
24587-		for i, call := range outgoingCalls {
24588-			// From the spec: CallHierarchyOutgoingCall.FromRanges is the range
24589-			// relative to the caller, e.g the item passed to
24590-			printString, err := callItemPrintString(ctx, conn, call.To, item.URI, call.FromRanges)
24591-			if err != nil {
24592-				return err
24593-			}
24594-			fmt.Printf("callee[%d]: %s\n", i, printString)
24595-		}
24596-	}
24597-
24598-	return nil
24599-}
24600-
24601-// callItemPrintString returns a protocol.CallHierarchyItem object represented as a string.
24602-// item and call ranges (protocol.Range) are converted to user friendly spans (1-indexed).
24603-func callItemPrintString(ctx context.Context, conn *connection, item protocol.CallHierarchyItem, callsURI protocol.DocumentURI, calls []protocol.Range) (string, error) {
24604-	itemFile := conn.openFile(ctx, item.URI.SpanURI())
24605-	if itemFile.err != nil {
24606-		return "", itemFile.err
24607-	}
24608-	itemSpan, err := itemFile.mapper.LocationSpan(protocol.Location{URI: item.URI, Range: item.Range})
24609-	if err != nil {
24610-		return "", err
24611-	}
24612-
24613-	callsFile := conn.openFile(ctx, callsURI.SpanURI())
24614-	if callsURI != "" && callsFile.err != nil {
24615-		return "", callsFile.err
24616-	}
24617-	var callRanges []string
24618-	for _, rng := range calls {
24619-		call, err := callsFile.mapper.RangeSpan(rng)
24620-		if err != nil {
24621-			return "", err
24622-		}
24623-		callRange := fmt.Sprintf("%d:%d-%d", call.Start().Line(), call.Start().Column(), call.End().Column())
24624-		callRanges = append(callRanges, callRange)
24625-	}
24626-
24627-	printString := fmt.Sprintf("function %s in %v", item.Name, itemSpan)
24628-	if len(calls) > 0 {
24629-		printString = fmt.Sprintf("ranges %s in %s from/to %s", strings.Join(callRanges, ", "), callsURI.SpanURI().Filename(), printString)
24630-	}
24631-	return printString, nil
24632-}
24633diff -urN a/gopls/internal/lsp/cmd/capabilities_test.go b/gopls/internal/lsp/cmd/capabilities_test.go
24634--- a/gopls/internal/lsp/cmd/capabilities_test.go	2000-01-01 00:00:00.000000000 -0000
24635+++ b/gopls/internal/lsp/cmd/capabilities_test.go	1970-01-01 00:00:00.000000000 +0000
24636@@ -1,166 +0,0 @@
24637-// Copyright 2019 The Go Authors. All rights reserved.
24638-// Use of this source code is governed by a BSD-style
24639-// license that can be found in the LICENSE file.
24640-
24641-package cmd
24642-
24643-import (
24644-	"context"
24645-	"fmt"
24646-	"io/ioutil"
24647-	"os"
24648-	"path/filepath"
24649-	"testing"
24650-
24651-	"golang.org/x/tools/gopls/internal/lsp"
24652-	"golang.org/x/tools/gopls/internal/lsp/cache"
24653-	"golang.org/x/tools/gopls/internal/lsp/protocol"
24654-)
24655-
24656-// TestCapabilities does some minimal validation of the server's adherence to the LSP.
24657-// The checks in the test are added as changes are made and errors noticed.
24658-func TestCapabilities(t *testing.T) {
24659-	tmpDir, err := ioutil.TempDir("", "fake")
24660-	if err != nil {
24661-		t.Fatal(err)
24662-	}
24663-	tmpFile := filepath.Join(tmpDir, "fake.go")
24664-	if err := ioutil.WriteFile(tmpFile, []byte(""), 0775); err != nil {
24665-		t.Fatal(err)
24666-	}
24667-	if err := ioutil.WriteFile(filepath.Join(tmpDir, "go.mod"), []byte("module fake\n\ngo 1.12\n"), 0775); err != nil {
24668-		t.Fatal(err)
24669-	}
24670-	defer os.RemoveAll(tmpDir)
24671-
24672-	app := New("gopls-test", tmpDir, os.Environ(), nil)
24673-	c := newConnection(app)
24674-	ctx := context.Background()
24675-	defer c.terminate(ctx)
24676-
24677-	params := &protocol.ParamInitialize{}
24678-	params.RootURI = protocol.URIFromPath(c.Client.app.wd)
24679-	params.Capabilities.Workspace.Configuration = true
24680-
24681-	// Send an initialize request to the server.
24682-	c.Server = lsp.NewServer(cache.NewSession(ctx, cache.New(nil), app.options), c.Client)
24683-	result, err := c.Server.Initialize(ctx, params)
24684-	if err != nil {
24685-		t.Fatal(err)
24686-	}
24687-	// Validate initialization result.
24688-	if err := validateCapabilities(result); err != nil {
24689-		t.Error(err)
24690-	}
24691-	// Complete initialization of server.
24692-	if err := c.Server.Initialized(ctx, &protocol.InitializedParams{}); err != nil {
24693-		t.Fatal(err)
24694-	}
24695-
24696-	// Open the file on the server side.
24697-	uri := protocol.URIFromPath(tmpFile)
24698-	if err := c.Server.DidOpen(ctx, &protocol.DidOpenTextDocumentParams{
24699-		TextDocument: protocol.TextDocumentItem{
24700-			URI:        uri,
24701-			LanguageID: "go",
24702-			Version:    1,
24703-			Text:       `package main; func main() {};`,
24704-		},
24705-	}); err != nil {
24706-		t.Fatal(err)
24707-	}
24708-
24709-	// If we are sending a full text change, the change.Range must be nil.
24710-	// It is not enough for the Change to be empty, as that is ambiguous.
24711-	if err := c.Server.DidChange(ctx, &protocol.DidChangeTextDocumentParams{
24712-		TextDocument: protocol.VersionedTextDocumentIdentifier{
24713-			TextDocumentIdentifier: protocol.TextDocumentIdentifier{
24714-				URI: uri,
24715-			},
24716-			Version: 2,
24717-		},
24718-		ContentChanges: []protocol.TextDocumentContentChangeEvent{
24719-			{
24720-				Range: nil,
24721-				Text:  `package main; func main() { fmt.Println("") }`,
24722-			},
24723-		},
24724-	}); err != nil {
24725-		t.Fatal(err)
24726-	}
24727-
24728-	// Send a code action request to validate expected types.
24729-	actions, err := c.Server.CodeAction(ctx, &protocol.CodeActionParams{
24730-		TextDocument: protocol.TextDocumentIdentifier{
24731-			URI: uri,
24732-		},
24733-	})
24734-	if err != nil {
24735-		t.Fatal(err)
24736-	}
24737-	for _, action := range actions {
24738-		// Validate that an empty command is sent along with import organization responses.
24739-		if action.Kind == protocol.SourceOrganizeImports && action.Command != nil {
24740-			t.Errorf("unexpected command for import organization")
24741-		}
24742-	}
24743-
24744-	if err := c.Server.DidSave(ctx, &protocol.DidSaveTextDocumentParams{
24745-		TextDocument: protocol.TextDocumentIdentifier{
24746-			URI: uri,
24747-		},
24748-		// LSP specifies that a file can be saved with optional text, so this field must be nil.
24749-		Text: nil,
24750-	}); err != nil {
24751-		t.Fatal(err)
24752-	}
24753-
24754-	// Send a completion request to validate expected types.
24755-	list, err := c.Server.Completion(ctx, &protocol.CompletionParams{
24756-		TextDocumentPositionParams: protocol.TextDocumentPositionParams{
24757-			TextDocument: protocol.TextDocumentIdentifier{
24758-				URI: uri,
24759-			},
24760-			Position: protocol.Position{
24761-				Line:      0,
24762-				Character: 28,
24763-			},
24764-		},
24765-	})
24766-	if err != nil {
24767-		t.Fatal(err)
24768-	}
24769-	for _, item := range list.Items {
24770-		// All other completion items should have nil commands.
24771-		// An empty command will be treated as a command with the name '' by VS Code.
24772-		// This causes VS Code to report errors to users about invalid commands.
24773-		if item.Command != nil {
24774-			t.Errorf("unexpected command for completion item")
24775-		}
24776-		// The item's TextEdit must be a pointer, as VS Code considers TextEdits
24777-		// that don't contain the cursor position to be invalid.
24778-		var textEdit interface{} = item.TextEdit
24779-		if _, ok := textEdit.(*protocol.TextEdit); !ok {
24780-			t.Errorf("textEdit is not a *protocol.TextEdit, instead it is %T", textEdit)
24781-		}
24782-	}
24783-	if err := c.Server.Shutdown(ctx); err != nil {
24784-		t.Fatal(err)
24785-	}
24786-	if err := c.Server.Exit(ctx); err != nil {
24787-		t.Fatal(err)
24788-	}
24789-}
24790-
24791-func validateCapabilities(result *protocol.InitializeResult) error {
24792-	// If the client sends "false" for RenameProvider.PrepareSupport,
24793-	// the server must respond with a boolean.
24794-	if v, ok := result.Capabilities.RenameProvider.(bool); !ok {
24795-		return fmt.Errorf("RenameProvider must be a boolean if PrepareSupport is false (got %T)", v)
24796-	}
24797-	// The same goes for CodeActionKind.ValueSet.
24798-	if v, ok := result.Capabilities.CodeActionProvider.(bool); !ok {
24799-		return fmt.Errorf("CodeActionSupport must be a boolean if CodeActionKind.ValueSet has length 0 (got %T)", v)
24800-	}
24801-	return nil
24802-}
24803diff -urN a/gopls/internal/lsp/cmd/check.go b/gopls/internal/lsp/cmd/check.go
24804--- a/gopls/internal/lsp/cmd/check.go	2000-01-01 00:00:00.000000000 -0000
24805+++ b/gopls/internal/lsp/cmd/check.go	1970-01-01 00:00:00.000000000 +0000
24806@@ -1,73 +0,0 @@
24807-// Copyright 2019 The Go Authors. All rights reserved.
24808-// Use of this source code is governed by a BSD-style
24809-// license that can be found in the LICENSE file.
24810-
24811-package cmd
24812-
24813-import (
24814-	"context"
24815-	"flag"
24816-	"fmt"
24817-
24818-	"golang.org/x/tools/gopls/internal/span"
24819-)
24820-
24821-// check implements the check verb for gopls.
24822-type check struct {
24823-	app *Application
24824-}
24825-
24826-func (c *check) Name() string      { return "check" }
24827-func (c *check) Parent() string    { return c.app.Name() }
24828-func (c *check) Usage() string     { return "<filename>" }
24829-func (c *check) ShortHelp() string { return "show diagnostic results for the specified file" }
24830-func (c *check) DetailedHelp(f *flag.FlagSet) {
24831-	fmt.Fprint(f.Output(), `
24832-Example: show the diagnostic results of this file:
24833-
24834-	$ gopls check internal/lsp/cmd/check.go
24835-`)
24836-	printFlagDefaults(f)
24837-}
24838-
24839-// Run performs the check on the files specified by args and prints the
24840-// results to stdout.
24841-func (c *check) Run(ctx context.Context, args ...string) error {
24842-	if len(args) == 0 {
24843-		// no files, so no results
24844-		return nil
24845-	}
24846-	checking := map[span.URI]*cmdFile{}
24847-	var uris []span.URI
24848-	// now we ready to kick things off
24849-	conn, err := c.app.connect(ctx)
24850-	if err != nil {
24851-		return err
24852-	}
24853-	defer conn.terminate(ctx)
24854-	for _, arg := range args {
24855-		uri := span.URIFromPath(arg)
24856-		uris = append(uris, uri)
24857-		file := conn.openFile(ctx, uri)
24858-		if file.err != nil {
24859-			return file.err
24860-		}
24861-		checking[uri] = file
24862-	}
24863-	if err := conn.diagnoseFiles(ctx, uris); err != nil {
24864-		return err
24865-	}
24866-	conn.Client.filesMu.Lock()
24867-	defer conn.Client.filesMu.Unlock()
24868-
24869-	for _, file := range checking {
24870-		for _, d := range file.diagnostics {
24871-			spn, err := file.mapper.RangeSpan(d.Range)
24872-			if err != nil {
24873-				return fmt.Errorf("Could not convert position %v for %q", d.Range, d.Message)
24874-			}
24875-			fmt.Printf("%v: %v\n", spn, d.Message)
24876-		}
24877-	}
24878-	return nil
24879-}
24880diff -urN a/gopls/internal/lsp/cmd/cmd.go b/gopls/internal/lsp/cmd/cmd.go
24881--- a/gopls/internal/lsp/cmd/cmd.go	2000-01-01 00:00:00.000000000 -0000
24882+++ b/gopls/internal/lsp/cmd/cmd.go	1970-01-01 00:00:00.000000000 +0000
24883@@ -1,640 +0,0 @@
24884-// Copyright 2018 The Go Authors. All rights reserved.
24885-// Use of this source code is governed by a BSD-style
24886-// license that can be found in the LICENSE file.
24887-
24888-// Package cmd handles the gopls command line.
24889-// It contains a handler for each of the modes, along with all the flag handling
24890-// and the command line output format.
24891-package cmd
24892-
24893-import (
24894-	"context"
24895-	"flag"
24896-	"fmt"
24897-	"io/ioutil"
24898-	"log"
24899-	"os"
24900-	"reflect"
24901-	"sort"
24902-	"strings"
24903-	"sync"
24904-	"text/tabwriter"
24905-	"time"
24906-
24907-	"golang.org/x/tools/gopls/internal/lsp"
24908-	"golang.org/x/tools/gopls/internal/lsp/cache"
24909-	"golang.org/x/tools/gopls/internal/lsp/debug"
24910-	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
24911-	"golang.org/x/tools/gopls/internal/lsp/protocol"
24912-	"golang.org/x/tools/gopls/internal/lsp/source"
24913-	"golang.org/x/tools/gopls/internal/span"
24914-	"golang.org/x/tools/internal/jsonrpc2"
24915-	"golang.org/x/tools/internal/tool"
24916-	"golang.org/x/tools/internal/xcontext"
24917-)
24918-
24919-// Application is the main application as passed to tool.Main
24920-// It handles the main command line parsing and dispatch to the sub commands.
24921-type Application struct {
24922-	// Core application flags
24923-
24924-	// Embed the basic profiling flags supported by the tool package
24925-	tool.Profile
24926-
24927-	// We include the server configuration directly for now, so the flags work
24928-	// even without the verb.
24929-	// TODO: Remove this when we stop allowing the serve verb by default.
24930-	Serve Serve
24931-
24932-	// the options configuring function to invoke when building a server
24933-	options func(*source.Options)
24934-
24935-	// The name of the binary, used in help and telemetry.
24936-	name string
24937-
24938-	// The working directory to run commands in.
24939-	wd string
24940-
24941-	// The environment variables to use.
24942-	env []string
24943-
24944-	// Support for remote LSP server.
24945-	Remote string `flag:"remote" help:"forward all commands to a remote lsp specified by this flag. With no special prefix, this is assumed to be a TCP address. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. If 'auto', or prefixed by 'auto;', the remote address is automatically resolved based on the executing environment."`
24946-
24947-	// Verbose enables verbose logging.
24948-	Verbose bool `flag:"v,verbose" help:"verbose output"`
24949-
24950-	// VeryVerbose enables a higher level of verbosity in logging output.
24951-	VeryVerbose bool `flag:"vv,veryverbose" help:"very verbose output"`
24952-
24953-	// Control ocagent export of telemetry
24954-	OCAgent string `flag:"ocagent" help:"the address of the ocagent (e.g. http://localhost:55678), or off"`
24955-
24956-	// PrepareOptions is called to update the options when a new view is built.
24957-	// It is primarily to allow the behavior of gopls to be modified by hooks.
24958-	PrepareOptions func(*source.Options)
24959-}
24960-
24961-func (app *Application) verbose() bool {
24962-	return app.Verbose || app.VeryVerbose
24963-}
24964-
24965-// New returns a new Application ready to run.
24966-func New(name, wd string, env []string, options func(*source.Options)) *Application {
24967-	if wd == "" {
24968-		wd, _ = os.Getwd()
24969-	}
24970-	app := &Application{
24971-		options: options,
24972-		name:    name,
24973-		wd:      wd,
24974-		env:     env,
24975-		OCAgent: "off", //TODO: Remove this line to default the exporter to on
24976-
24977-		Serve: Serve{
24978-			RemoteListenTimeout: 1 * time.Minute,
24979-		},
24980-	}
24981-	app.Serve.app = app
24982-	return app
24983-}
24984-
24985-// Name implements tool.Application returning the binary name.
24986-func (app *Application) Name() string { return app.name }
24987-
24988-// Usage implements tool.Application returning empty extra argument usage.
24989-func (app *Application) Usage() string { return "" }
24990-
24991-// ShortHelp implements tool.Application returning the main binary help.
24992-func (app *Application) ShortHelp() string {
24993-	return ""
24994-}
24995-
24996-// DetailedHelp implements tool.Application returning the main binary help.
24997-// This includes the short help for all the sub commands.
24998-func (app *Application) DetailedHelp(f *flag.FlagSet) {
24999-	w := tabwriter.NewWriter(f.Output(), 0, 0, 2, ' ', 0)
25000-	defer w.Flush()
25001-
25002-	fmt.Fprint(w, `
25003-gopls is a Go language server.
25004-
25005-It is typically used with an editor to provide language features. When no
25006-command is specified, gopls will default to the 'serve' command. The language
25007-features can also be accessed via the gopls command-line interface.
25008-
25009-Usage:
25010-  gopls help [<subject>]
25011-
25012-Command:
25013-`)
25014-	fmt.Fprint(w, "\nMain\t\n")
25015-	for _, c := range app.mainCommands() {
25016-		fmt.Fprintf(w, "  %s\t%s\n", c.Name(), c.ShortHelp())
25017-	}
25018-	fmt.Fprint(w, "\t\nFeatures\t\n")
25019-	for _, c := range app.featureCommands() {
25020-		fmt.Fprintf(w, "  %s\t%s\n", c.Name(), c.ShortHelp())
25021-	}
25022-	fmt.Fprint(w, "\nflags:\n")
25023-	printFlagDefaults(f)
25024-}
25025-
25026-// this is a slightly modified version of flag.PrintDefaults to give us control
25027-func printFlagDefaults(s *flag.FlagSet) {
25028-	var flags [][]*flag.Flag
25029-	seen := map[flag.Value]int{}
25030-	s.VisitAll(func(f *flag.Flag) {
25031-		if i, ok := seen[f.Value]; !ok {
25032-			seen[f.Value] = len(flags)
25033-			flags = append(flags, []*flag.Flag{f})
25034-		} else {
25035-			flags[i] = append(flags[i], f)
25036-		}
25037-	})
25038-	for _, entry := range flags {
25039-		sort.SliceStable(entry, func(i, j int) bool {
25040-			return len(entry[i].Name) < len(entry[j].Name)
25041-		})
25042-		var b strings.Builder
25043-		for i, f := range entry {
25044-			switch i {
25045-			case 0:
25046-				b.WriteString("  -")
25047-			default:
25048-				b.WriteString(",-")
25049-			}
25050-			b.WriteString(f.Name)
25051-		}
25052-
25053-		f := entry[0]
25054-		name, usage := flag.UnquoteUsage(f)
25055-		if len(name) > 0 {
25056-			b.WriteString("=")
25057-			b.WriteString(name)
25058-		}
25059-		// Boolean flags of one ASCII letter are so common we
25060-		// treat them specially, putting their usage on the same line.
25061-		if b.Len() <= 4 { // space, space, '-', 'x'.
25062-			b.WriteString("\t")
25063-		} else {
25064-			// Four spaces before the tab triggers good alignment
25065-			// for both 4- and 8-space tab stops.
25066-			b.WriteString("\n    \t")
25067-		}
25068-		b.WriteString(strings.ReplaceAll(usage, "\n", "\n    \t"))
25069-		if !isZeroValue(f, f.DefValue) {
25070-			if reflect.TypeOf(f.Value).Elem().Name() == "stringValue" {
25071-				fmt.Fprintf(&b, " (default %q)", f.DefValue)
25072-			} else {
25073-				fmt.Fprintf(&b, " (default %v)", f.DefValue)
25074-			}
25075-		}
25076-		fmt.Fprint(s.Output(), b.String(), "\n")
25077-	}
25078-}
25079-
25080-// isZeroValue is copied from the flags package
25081-func isZeroValue(f *flag.Flag, value string) bool {
25082-	// Build a zero value of the flag's Value type, and see if the
25083-	// result of calling its String method equals the value passed in.
25084-	// This works unless the Value type is itself an interface type.
25085-	typ := reflect.TypeOf(f.Value)
25086-	var z reflect.Value
25087-	if typ.Kind() == reflect.Ptr {
25088-		z = reflect.New(typ.Elem())
25089-	} else {
25090-		z = reflect.Zero(typ)
25091-	}
25092-	return value == z.Interface().(flag.Value).String()
25093-}
25094-
25095-// Run takes the args after top level flag processing, and invokes the correct
25096-// sub command as specified by the first argument.
25097-// If no arguments are passed it will invoke the server sub command, as a
25098-// temporary measure for compatibility.
25099-func (app *Application) Run(ctx context.Context, args ...string) error {
25100-	ctx = debug.WithInstance(ctx, app.wd, app.OCAgent)
25101-	if len(args) == 0 {
25102-		s := flag.NewFlagSet(app.Name(), flag.ExitOnError)
25103-		return tool.Run(ctx, s, &app.Serve, args)
25104-	}
25105-	command, args := args[0], args[1:]
25106-	for _, c := range app.Commands() {
25107-		if c.Name() == command {
25108-			s := flag.NewFlagSet(app.Name(), flag.ExitOnError)
25109-			return tool.Run(ctx, s, c, args)
25110-		}
25111-	}
25112-	return tool.CommandLineErrorf("Unknown command %v", command)
25113-}
25114-
25115-// Commands returns the set of commands supported by the gopls tool on the
25116-// command line.
25117-// The command is specified by the first non flag argument.
25118-func (app *Application) Commands() []tool.Application {
25119-	var commands []tool.Application
25120-	commands = append(commands, app.mainCommands()...)
25121-	commands = append(commands, app.featureCommands()...)
25122-	return commands
25123-}
25124-
25125-func (app *Application) mainCommands() []tool.Application {
25126-	return []tool.Application{
25127-		&app.Serve,
25128-		&version{app: app},
25129-		&bug{app: app},
25130-		&help{app: app},
25131-		&apiJSON{app: app},
25132-		&licenses{app: app},
25133-	}
25134-}
25135-
25136-func (app *Application) featureCommands() []tool.Application {
25137-	return []tool.Application{
25138-		&callHierarchy{app: app},
25139-		&check{app: app},
25140-		&definition{app: app},
25141-		&foldingRanges{app: app},
25142-		&format{app: app},
25143-		&highlight{app: app},
25144-		&implementation{app: app},
25145-		&imports{app: app},
25146-		newRemote(app, ""),
25147-		newRemote(app, "inspect"),
25148-		&links{app: app},
25149-		&prepareRename{app: app},
25150-		&references{app: app},
25151-		&rename{app: app},
25152-		&semtok{app: app},
25153-		&signature{app: app},
25154-		&suggestedFix{app: app},
25155-		&symbols{app: app},
25156-		&workspaceSymbol{app: app},
25157-		&vulncheck{app: app},
25158-	}
25159-}
25160-
25161-var (
25162-	internalMu          sync.Mutex
25163-	internalConnections = make(map[string]*connection)
25164-)
25165-
25166-func (app *Application) connect(ctx context.Context) (*connection, error) {
25167-	switch {
25168-	case app.Remote == "":
25169-		connection := newConnection(app)
25170-		connection.Server = lsp.NewServer(cache.NewSession(ctx, cache.New(nil), app.options), connection.Client)
25171-		ctx = protocol.WithClient(ctx, connection.Client)
25172-		return connection, connection.initialize(ctx, app.options)
25173-	case strings.HasPrefix(app.Remote, "internal@"):
25174-		internalMu.Lock()
25175-		defer internalMu.Unlock()
25176-		opts := source.DefaultOptions().Clone()
25177-		if app.options != nil {
25178-			app.options(opts)
25179-		}
25180-		key := fmt.Sprintf("%s %v %v %v", app.wd, opts.PreferredContentFormat, opts.HierarchicalDocumentSymbolSupport, opts.SymbolMatcher)
25181-		if c := internalConnections[key]; c != nil {
25182-			return c, nil
25183-		}
25184-		remote := app.Remote[len("internal@"):]
25185-		ctx := xcontext.Detach(ctx) //TODO:a way of shutting down the internal server
25186-		connection, err := app.connectRemote(ctx, remote)
25187-		if err != nil {
25188-			return nil, err
25189-		}
25190-		internalConnections[key] = connection
25191-		return connection, nil
25192-	default:
25193-		return app.connectRemote(ctx, app.Remote)
25194-	}
25195-}
25196-
25197-// CloseTestConnections terminates shared connections used in command tests. It
25198-// should only be called from tests.
25199-func CloseTestConnections(ctx context.Context) {
25200-	for _, c := range internalConnections {
25201-		c.Shutdown(ctx)
25202-		c.Exit(ctx)
25203-	}
25204-}
25205-
25206-func (app *Application) connectRemote(ctx context.Context, remote string) (*connection, error) {
25207-	connection := newConnection(app)
25208-	conn, err := lsprpc.ConnectToRemote(ctx, remote)
25209-	if err != nil {
25210-		return nil, err
25211-	}
25212-	stream := jsonrpc2.NewHeaderStream(conn)
25213-	cc := jsonrpc2.NewConn(stream)
25214-	connection.Server = protocol.ServerDispatcher(cc)
25215-	ctx = protocol.WithClient(ctx, connection.Client)
25216-	cc.Go(ctx,
25217-		protocol.Handlers(
25218-			protocol.ClientHandler(connection.Client,
25219-				jsonrpc2.MethodNotFound)))
25220-	return connection, connection.initialize(ctx, app.options)
25221-}
25222-
25223-var matcherString = map[source.SymbolMatcher]string{
25224-	source.SymbolFuzzy:           "fuzzy",
25225-	source.SymbolCaseSensitive:   "caseSensitive",
25226-	source.SymbolCaseInsensitive: "caseInsensitive",
25227-}
25228-
25229-func (c *connection) initialize(ctx context.Context, options func(*source.Options)) error {
25230-	params := &protocol.ParamInitialize{}
25231-	params.RootURI = protocol.URIFromPath(c.Client.app.wd)
25232-	params.Capabilities.Workspace.Configuration = true
25233-
25234-	// Make sure to respect configured options when sending initialize request.
25235-	opts := source.DefaultOptions().Clone()
25236-	if options != nil {
25237-		options(opts)
25238-	}
25239-	// If you add an additional option here, you must update the map key in connect.
25240-	params.Capabilities.TextDocument.Hover = &protocol.HoverClientCapabilities{
25241-		ContentFormat: []protocol.MarkupKind{opts.PreferredContentFormat},
25242-	}
25243-	params.Capabilities.TextDocument.DocumentSymbol.HierarchicalDocumentSymbolSupport = opts.HierarchicalDocumentSymbolSupport
25244-	params.Capabilities.TextDocument.SemanticTokens = protocol.SemanticTokensClientCapabilities{}
25245-	params.Capabilities.TextDocument.SemanticTokens.Formats = []protocol.TokenFormat{"relative"}
25246-	params.Capabilities.TextDocument.SemanticTokens.Requests.Range.Value = true
25247-	params.Capabilities.TextDocument.SemanticTokens.Requests.Full.Value = true
25248-	params.Capabilities.TextDocument.SemanticTokens.TokenTypes = lsp.SemanticTypes()
25249-	params.Capabilities.TextDocument.SemanticTokens.TokenModifiers = lsp.SemanticModifiers()
25250-	params.InitializationOptions = map[string]interface{}{
25251-		"symbolMatcher": matcherString[opts.SymbolMatcher],
25252-	}
25253-	if _, err := c.Server.Initialize(ctx, params); err != nil {
25254-		return err
25255-	}
25256-	if err := c.Server.Initialized(ctx, &protocol.InitializedParams{}); err != nil {
25257-		return err
25258-	}
25259-	return nil
25260-}
25261-
25262-type connection struct {
25263-	protocol.Server
25264-	Client *cmdClient
25265-}
25266-
25267-type cmdClient struct {
25268-	protocol.Server
25269-	app *Application
25270-
25271-	diagnosticsMu   sync.Mutex
25272-	diagnosticsDone chan struct{}
25273-
25274-	filesMu sync.Mutex
25275-	files   map[span.URI]*cmdFile
25276-}
25277-
25278-type cmdFile struct {
25279-	uri         span.URI
25280-	mapper      *protocol.Mapper
25281-	err         error
25282-	open        bool
25283-	diagnostics []protocol.Diagnostic
25284-}
25285-
25286-func newConnection(app *Application) *connection {
25287-	return &connection{
25288-		Client: &cmdClient{
25289-			app:   app,
25290-			files: make(map[span.URI]*cmdFile),
25291-		},
25292-	}
25293-}
25294-
25295-// fileURI converts a DocumentURI to a file:// span.URI, panicking if it's not a file.
25296-func fileURI(uri protocol.DocumentURI) span.URI {
25297-	sURI := uri.SpanURI()
25298-	if !sURI.IsFile() {
25299-		panic(fmt.Sprintf("%q is not a file URI", uri))
25300-	}
25301-	return sURI
25302-}
25303-
25304-func (c *cmdClient) CodeLensRefresh(context.Context) error { return nil }
25305-
25306-func (c *cmdClient) LogTrace(context.Context, *protocol.LogTraceParams) error { return nil }
25307-
25308-func (c *cmdClient) ShowMessage(ctx context.Context, p *protocol.ShowMessageParams) error { return nil }
25309-
25310-func (c *cmdClient) ShowMessageRequest(ctx context.Context, p *protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error) {
25311-	return nil, nil
25312-}
25313-
25314-func (c *cmdClient) LogMessage(ctx context.Context, p *protocol.LogMessageParams) error {
25315-	switch p.Type {
25316-	case protocol.Error:
25317-		log.Print("Error:", p.Message)
25318-	case protocol.Warning:
25319-		log.Print("Warning:", p.Message)
25320-	case protocol.Info:
25321-		if c.app.verbose() {
25322-			log.Print("Info:", p.Message)
25323-		}
25324-	case protocol.Log:
25325-		if c.app.verbose() {
25326-			log.Print("Log:", p.Message)
25327-		}
25328-	default:
25329-		if c.app.verbose() {
25330-			log.Print(p.Message)
25331-		}
25332-	}
25333-	return nil
25334-}
25335-
25336-func (c *cmdClient) Event(ctx context.Context, t *interface{}) error { return nil }
25337-
25338-func (c *cmdClient) RegisterCapability(ctx context.Context, p *protocol.RegistrationParams) error {
25339-	return nil
25340-}
25341-
25342-func (c *cmdClient) UnregisterCapability(ctx context.Context, p *protocol.UnregistrationParams) error {
25343-	return nil
25344-}
25345-
25346-func (c *cmdClient) WorkspaceFolders(ctx context.Context) ([]protocol.WorkspaceFolder, error) {
25347-	return nil, nil
25348-}
25349-
25350-func (c *cmdClient) Configuration(ctx context.Context, p *protocol.ParamConfiguration) ([]interface{}, error) {
25351-	results := make([]interface{}, len(p.Items))
25352-	for i, item := range p.Items {
25353-		if item.Section != "gopls" {
25354-			continue
25355-		}
25356-		env := map[string]interface{}{}
25357-		for _, value := range c.app.env {
25358-			l := strings.SplitN(value, "=", 2)
25359-			if len(l) != 2 {
25360-				continue
25361-			}
25362-			env[l[0]] = l[1]
25363-		}
25364-		m := map[string]interface{}{
25365-			"env": env,
25366-			"analyses": map[string]bool{
25367-				"fillreturns":    true,
25368-				"nonewvars":      true,
25369-				"noresultvalues": true,
25370-				"undeclaredname": true,
25371-			},
25372-		}
25373-		if c.app.VeryVerbose {
25374-			m["verboseOutput"] = true
25375-		}
25376-		results[i] = m
25377-	}
25378-	return results, nil
25379-}
25380-
25381-func (c *cmdClient) ApplyEdit(ctx context.Context, p *protocol.ApplyWorkspaceEditParams) (*protocol.ApplyWorkspaceEditResult, error) {
25382-	return &protocol.ApplyWorkspaceEditResult{Applied: false, FailureReason: "not implemented"}, nil
25383-}
25384-
25385-func (c *cmdClient) PublishDiagnostics(ctx context.Context, p *protocol.PublishDiagnosticsParams) error {
25386-	if p.URI == "gopls://diagnostics-done" {
25387-		close(c.diagnosticsDone)
25388-	}
25389-	// Don't worry about diagnostics without versions.
25390-	if p.Version == 0 {
25391-		return nil
25392-	}
25393-
25394-	c.filesMu.Lock()
25395-	defer c.filesMu.Unlock()
25396-
25397-	file := c.getFile(ctx, fileURI(p.URI))
25398-	file.diagnostics = p.Diagnostics
25399-	return nil
25400-}
25401-
25402-func (c *cmdClient) Progress(context.Context, *protocol.ProgressParams) error {
25403-	return nil
25404-}
25405-
25406-func (c *cmdClient) ShowDocument(context.Context, *protocol.ShowDocumentParams) (*protocol.ShowDocumentResult, error) {
25407-	return nil, nil
25408-}
25409-
25410-func (c *cmdClient) WorkDoneProgressCreate(context.Context, *protocol.WorkDoneProgressCreateParams) error {
25411-	return nil
25412-}
25413-
25414-func (c *cmdClient) DiagnosticRefresh(context.Context) error {
25415-	return nil
25416-}
25417-
25418-func (c *cmdClient) InlayHintRefresh(context.Context) error {
25419-	return nil
25420-}
25421-
25422-func (c *cmdClient) SemanticTokensRefresh(context.Context) error {
25423-	return nil
25424-}
25425-
25426-func (c *cmdClient) InlineValueRefresh(context.Context) error {
25427-	return nil
25428-}
25429-
25430-func (c *cmdClient) getFile(ctx context.Context, uri span.URI) *cmdFile {
25431-	file, found := c.files[uri]
25432-	if !found || file.err != nil {
25433-		file = &cmdFile{
25434-			uri: uri,
25435-		}
25436-		c.files[uri] = file
25437-	}
25438-	if file.mapper == nil {
25439-		content, err := ioutil.ReadFile(uri.Filename())
25440-		if err != nil {
25441-			file.err = fmt.Errorf("getFile: %v: %v", uri, err)
25442-			return file
25443-		}
25444-		file.mapper = protocol.NewMapper(uri, content)
25445-	}
25446-	return file
25447-}
25448-
25449-func (c *cmdClient) openFile(ctx context.Context, uri span.URI) *cmdFile {
25450-	c.filesMu.Lock()
25451-	defer c.filesMu.Unlock()
25452-
25453-	file := c.getFile(ctx, uri)
25454-	if file.err != nil || file.open {
25455-		return file
25456-	}
25457-	file.open = true
25458-	return file
25459-}
25460-
25461-func (c *connection) openFile(ctx context.Context, uri span.URI) *cmdFile {
25462-	file := c.Client.openFile(ctx, uri)
25463-	if file.err != nil {
25464-		return file
25465-	}
25466-
25467-	p := &protocol.DidOpenTextDocumentParams{
25468-		TextDocument: protocol.TextDocumentItem{
25469-			URI:        protocol.URIFromSpanURI(uri),
25470-			LanguageID: "go",
25471-			Version:    1,
25472-			Text:       string(file.mapper.Content),
25473-		},
25474-	}
25475-	if err := c.Server.DidOpen(ctx, p); err != nil {
25476-		file.err = fmt.Errorf("%v: %v", uri, err)
25477-	}
25478-	return file
25479-}
25480-
25481-func (c *connection) semanticTokens(ctx context.Context, p *protocol.SemanticTokensRangeParams) (*protocol.SemanticTokens, error) {
25482-	// use range to avoid limits on full
25483-	resp, err := c.Server.SemanticTokensRange(ctx, p)
25484-	if err != nil {
25485-		return nil, err
25486-	}
25487-	return resp, nil
25488-}
25489-
25490-func (c *connection) diagnoseFiles(ctx context.Context, files []span.URI) error {
25491-	var untypedFiles []interface{}
25492-	for _, file := range files {
25493-		untypedFiles = append(untypedFiles, string(file))
25494-	}
25495-	c.Client.diagnosticsMu.Lock()
25496-	defer c.Client.diagnosticsMu.Unlock()
25497-
25498-	c.Client.diagnosticsDone = make(chan struct{})
25499-	_, err := c.Server.NonstandardRequest(ctx, "gopls/diagnoseFiles", map[string]interface{}{"files": untypedFiles})
25500-	if err != nil {
25501-		close(c.Client.diagnosticsDone)
25502-		return err
25503-	}
25504-
25505-	<-c.Client.diagnosticsDone
25506-	return nil
25507-}
25508-
25509-func (c *connection) terminate(ctx context.Context) {
25510-	if strings.HasPrefix(c.Client.app.Remote, "internal@") {
25511-		// internal connections need to be left alive for the next test
25512-		return
25513-	}
25514-	//TODO: do we need to handle errors on these calls?
25515-	c.Shutdown(ctx)
25516-	//TODO: right now calling exit terminates the process, we should rethink that
25517-	//server.Exit(ctx)
25518-}
25519-
25520-// Implement io.Closer.
25521-func (c *cmdClient) Close() error {
25522-	return nil
25523-}
25524diff -urN a/gopls/internal/lsp/cmd/definition.go b/gopls/internal/lsp/cmd/definition.go
25525--- a/gopls/internal/lsp/cmd/definition.go	2000-01-01 00:00:00.000000000 -0000
25526+++ b/gopls/internal/lsp/cmd/definition.go	1970-01-01 00:00:00.000000000 +0000
25527@@ -1,132 +0,0 @@
25528-// Copyright 2019 The Go Authors. All rights reserved.
25529-// Use of this source code is governed by a BSD-style
25530-// license that can be found in the LICENSE file.
25531-
25532-package cmd
25533-
25534-import (
25535-	"context"
25536-	"encoding/json"
25537-	"flag"
25538-	"fmt"
25539-	"os"
25540-	"strings"
25541-
25542-	"golang.org/x/tools/gopls/internal/lsp/protocol"
25543-	"golang.org/x/tools/gopls/internal/lsp/source"
25544-	"golang.org/x/tools/gopls/internal/span"
25545-	"golang.org/x/tools/internal/tool"
25546-)
25547-
25548-// A Definition is the result of a 'definition' query.
25549-type Definition struct {
25550-	Span        span.Span `json:"span"`        // span of the definition
25551-	Description string    `json:"description"` // description of the denoted object
25552-}
25553-
25554-// These constant is printed in the help, and then used in a test to verify the
25555-// help is still valid.
25556-// They refer to "Set" in "flag.FlagSet" from the DetailedHelp method below.
25557-const (
25558-	exampleLine   = 44
25559-	exampleColumn = 47
25560-	exampleOffset = 1270
25561-)
25562-
25563-// definition implements the definition verb for gopls.
25564-type definition struct {
25565-	app *Application
25566-
25567-	JSON              bool `flag:"json" help:"emit output in JSON format"`
25568-	MarkdownSupported bool `flag:"markdown" help:"support markdown in responses"`
25569-}
25570-
25571-func (d *definition) Name() string      { return "definition" }
25572-func (d *definition) Parent() string    { return d.app.Name() }
25573-func (d *definition) Usage() string     { return "[definition-flags] <position>" }
25574-func (d *definition) ShortHelp() string { return "show declaration of selected identifier" }
25575-func (d *definition) DetailedHelp(f *flag.FlagSet) {
25576-	fmt.Fprintf(f.Output(), `
25577-Example: show the definition of the identifier at syntax at offset %[1]v in this file (flag.FlagSet):
25578-
25579-	$ gopls definition internal/lsp/cmd/definition.go:%[1]v:%[2]v
25580-	$ gopls definition internal/lsp/cmd/definition.go:#%[3]v
25581-
25582-definition-flags:
25583-`, exampleLine, exampleColumn, exampleOffset)
25584-	printFlagDefaults(f)
25585-}
25586-
25587-// Run performs the definition query as specified by args and prints the
25588-// results to stdout.
25589-func (d *definition) Run(ctx context.Context, args ...string) error {
25590-	if len(args) != 1 {
25591-		return tool.CommandLineErrorf("definition expects 1 argument")
25592-	}
25593-	// Plaintext makes more sense for the command line.
25594-	opts := d.app.options
25595-	d.app.options = func(o *source.Options) {
25596-		if opts != nil {
25597-			opts(o)
25598-		}
25599-		o.PreferredContentFormat = protocol.PlainText
25600-		if d.MarkdownSupported {
25601-			o.PreferredContentFormat = protocol.Markdown
25602-		}
25603-	}
25604-	conn, err := d.app.connect(ctx)
25605-	if err != nil {
25606-		return err
25607-	}
25608-	defer conn.terminate(ctx)
25609-	from := span.Parse(args[0])
25610-	file := conn.openFile(ctx, from.URI())
25611-	if file.err != nil {
25612-		return file.err
25613-	}
25614-	loc, err := file.mapper.SpanLocation(from)
25615-	if err != nil {
25616-		return err
25617-	}
25618-	p := protocol.DefinitionParams{
25619-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
25620-	}
25621-	locs, err := conn.Definition(ctx, &p)
25622-	if err != nil {
25623-		return fmt.Errorf("%v: %v", from, err)
25624-	}
25625-
25626-	if len(locs) == 0 {
25627-		return fmt.Errorf("%v: not an identifier", from)
25628-	}
25629-	q := protocol.HoverParams{
25630-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
25631-	}
25632-	hover, err := conn.Hover(ctx, &q)
25633-	if err != nil {
25634-		return fmt.Errorf("%v: %v", from, err)
25635-	}
25636-	if hover == nil {
25637-		return fmt.Errorf("%v: not an identifier", from)
25638-	}
25639-	file = conn.openFile(ctx, fileURI(locs[0].URI))
25640-	if file.err != nil {
25641-		return fmt.Errorf("%v: %v", from, file.err)
25642-	}
25643-	definition, err := file.mapper.LocationSpan(locs[0])
25644-	if err != nil {
25645-		return fmt.Errorf("%v: %v", from, err)
25646-	}
25647-	description := strings.TrimSpace(hover.Contents.Value)
25648-	result := &Definition{
25649-		Span:        definition,
25650-		Description: description,
25651-	}
25652-	if d.JSON {
25653-		enc := json.NewEncoder(os.Stdout)
25654-		enc.SetIndent("", "\t")
25655-		return enc.Encode(result)
25656-	}
25657-	fmt.Printf("%v: defined here as %s", result.Span, result.Description)
25658-	return nil
25659-}
25660diff -urN a/gopls/internal/lsp/cmd/folding_range.go b/gopls/internal/lsp/cmd/folding_range.go
25661--- a/gopls/internal/lsp/cmd/folding_range.go	2000-01-01 00:00:00.000000000 -0000
25662+++ b/gopls/internal/lsp/cmd/folding_range.go	1970-01-01 00:00:00.000000000 +0000
25663@@ -1,73 +0,0 @@
25664-// Copyright 2019 The Go Authors. All rights reserved.
25665-// Use of this source code is governed by a BSD-style
25666-// license that can be found in the LICENSE file.
25667-
25668-package cmd
25669-
25670-import (
25671-	"context"
25672-	"flag"
25673-	"fmt"
25674-
25675-	"golang.org/x/tools/gopls/internal/lsp/protocol"
25676-	"golang.org/x/tools/gopls/internal/span"
25677-	"golang.org/x/tools/internal/tool"
25678-)
25679-
25680-// foldingRanges implements the folding_ranges verb for gopls
25681-type foldingRanges struct {
25682-	app *Application
25683-}
25684-
25685-func (r *foldingRanges) Name() string      { return "folding_ranges" }
25686-func (r *foldingRanges) Parent() string    { return r.app.Name() }
25687-func (r *foldingRanges) Usage() string     { return "<file>" }
25688-func (r *foldingRanges) ShortHelp() string { return "display selected file's folding ranges" }
25689-func (r *foldingRanges) DetailedHelp(f *flag.FlagSet) {
25690-	fmt.Fprint(f.Output(), `
25691-Example:
25692-
25693-	$ gopls folding_ranges helper/helper.go
25694-`)
25695-	printFlagDefaults(f)
25696-}
25697-
25698-func (r *foldingRanges) Run(ctx context.Context, args ...string) error {
25699-	if len(args) != 1 {
25700-		return tool.CommandLineErrorf("folding_ranges expects 1 argument (file)")
25701-	}
25702-
25703-	conn, err := r.app.connect(ctx)
25704-	if err != nil {
25705-		return err
25706-	}
25707-	defer conn.terminate(ctx)
25708-
25709-	from := span.Parse(args[0])
25710-	file := conn.openFile(ctx, from.URI())
25711-	if file.err != nil {
25712-		return file.err
25713-	}
25714-
25715-	p := protocol.FoldingRangeParams{
25716-		TextDocument: protocol.TextDocumentIdentifier{
25717-			URI: protocol.URIFromSpanURI(from.URI()),
25718-		},
25719-	}
25720-
25721-	ranges, err := conn.FoldingRange(ctx, &p)
25722-	if err != nil {
25723-		return err
25724-	}
25725-
25726-	for _, r := range ranges {
25727-		fmt.Printf("%v:%v-%v:%v\n",
25728-			r.StartLine+1,
25729-			r.StartCharacter+1,
25730-			r.EndLine+1,
25731-			r.EndCharacter+1,
25732-		)
25733-	}
25734-
25735-	return nil
25736-}
25737diff -urN a/gopls/internal/lsp/cmd/format.go b/gopls/internal/lsp/cmd/format.go
25738--- a/gopls/internal/lsp/cmd/format.go	2000-01-01 00:00:00.000000000 -0000
25739+++ b/gopls/internal/lsp/cmd/format.go	1970-01-01 00:00:00.000000000 +0000
25740@@ -1,110 +0,0 @@
25741-// Copyright 2019 The Go Authors. All rights reserved.
25742-// Use of this source code is governed by a BSD-style
25743-// license that can be found in the LICENSE file.
25744-
25745-package cmd
25746-
25747-import (
25748-	"context"
25749-	"flag"
25750-	"fmt"
25751-	"io/ioutil"
25752-	"os"
25753-
25754-	"golang.org/x/tools/gopls/internal/lsp/protocol"
25755-	"golang.org/x/tools/gopls/internal/lsp/source"
25756-	"golang.org/x/tools/gopls/internal/span"
25757-	"golang.org/x/tools/internal/diff"
25758-)
25759-
25760-// format implements the format verb for gopls.
25761-type format struct {
25762-	Diff  bool `flag:"d,diff" help:"display diffs instead of rewriting files"`
25763-	Write bool `flag:"w,write" help:"write result to (source) file instead of stdout"`
25764-	List  bool `flag:"l,list" help:"list files whose formatting differs from gofmt's"`
25765-
25766-	app *Application
25767-}
25768-
25769-func (c *format) Name() string      { return "format" }
25770-func (c *format) Parent() string    { return c.app.Name() }
25771-func (c *format) Usage() string     { return "[format-flags] <filerange>" }
25772-func (c *format) ShortHelp() string { return "format the code according to the go standard" }
25773-func (c *format) DetailedHelp(f *flag.FlagSet) {
25774-	fmt.Fprint(f.Output(), `
25775-The arguments supplied may be simple file names, or ranges within files.
25776-
25777-Example: reformat this file:
25778-
25779-	$ gopls format -w internal/lsp/cmd/check.go
25780-
25781-format-flags:
25782-`)
25783-	printFlagDefaults(f)
25784-}
25785-
25786-// Run performs the check on the files specified by args and prints the
25787-// results to stdout.
25788-func (c *format) Run(ctx context.Context, args ...string) error {
25789-	if len(args) == 0 {
25790-		// no files, so no results
25791-		return nil
25792-	}
25793-	// now we ready to kick things off
25794-	conn, err := c.app.connect(ctx)
25795-	if err != nil {
25796-		return err
25797-	}
25798-	defer conn.terminate(ctx)
25799-	for _, arg := range args {
25800-		spn := span.Parse(arg)
25801-		file := conn.openFile(ctx, spn.URI())
25802-		if file.err != nil {
25803-			return file.err
25804-		}
25805-		filename := spn.URI().Filename()
25806-		loc, err := file.mapper.SpanLocation(spn)
25807-		if err != nil {
25808-			return err
25809-		}
25810-		if loc.Range.Start != loc.Range.End {
25811-			return fmt.Errorf("only full file formatting supported")
25812-		}
25813-		p := protocol.DocumentFormattingParams{
25814-			TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI},
25815-		}
25816-		edits, err := conn.Formatting(ctx, &p)
25817-		if err != nil {
25818-			return fmt.Errorf("%v: %v", spn, err)
25819-		}
25820-		formatted, sedits, err := source.ApplyProtocolEdits(file.mapper, edits)
25821-		if err != nil {
25822-			return fmt.Errorf("%v: %v", spn, err)
25823-		}
25824-		printIt := true
25825-		if c.List {
25826-			printIt = false
25827-			if len(edits) > 0 {
25828-				fmt.Println(filename)
25829-			}
25830-		}
25831-		if c.Write {
25832-			printIt = false
25833-			if len(edits) > 0 {
25834-				ioutil.WriteFile(filename, formatted, 0644)
25835-			}
25836-		}
25837-		if c.Diff {
25838-			printIt = false
25839-			unified, err := diff.ToUnified(filename+".orig", filename, string(file.mapper.Content), sedits)
25840-			if err != nil {
25841-				return err
25842-			}
25843-			fmt.Print(unified)
25844-		}
25845-		if printIt {
25846-			os.Stdout.Write(formatted)
25847-		}
25848-	}
25849-	return nil
25850-}
25851diff -urN a/gopls/internal/lsp/cmd/help_test.go b/gopls/internal/lsp/cmd/help_test.go
25852--- a/gopls/internal/lsp/cmd/help_test.go	2000-01-01 00:00:00.000000000 -0000
25853+++ b/gopls/internal/lsp/cmd/help_test.go	1970-01-01 00:00:00.000000000 +0000
25854@@ -1,58 +0,0 @@
25855-// Copyright 2019 The Go Authors. All rights reserved.
25856-// Use of this source code is governed by a BSD-style
25857-// license that can be found in the LICENSE file.
25858-
25859-package cmd_test
25860-
25861-import (
25862-	"bytes"
25863-	"context"
25864-	"flag"
25865-	"io/ioutil"
25866-	"path/filepath"
25867-	"testing"
25868-
25869-	"github.com/google/go-cmp/cmp"
25870-	"golang.org/x/tools/gopls/internal/lsp/cmd"
25871-	"golang.org/x/tools/internal/testenv"
25872-	"golang.org/x/tools/internal/tool"
25873-)
25874-
25875-//go:generate go test -run Help -update-help-files
25876-
25877-var updateHelpFiles = flag.Bool("update-help-files", false, "Write out the help files instead of checking them")
25878-
25879-const appName = "gopls"
25880-
25881-func TestHelpFiles(t *testing.T) {
25882-	testenv.NeedsGoBuild(t) // This is a lie. We actually need the source code.
25883-	app := cmd.New(appName, "", nil, nil)
25884-	ctx := context.Background()
25885-	for _, page := range append(app.Commands(), app) {
25886-		t.Run(page.Name(), func(t *testing.T) {
25887-			var buf bytes.Buffer
25888-			s := flag.NewFlagSet(page.Name(), flag.ContinueOnError)
25889-			s.SetOutput(&buf)
25890-			tool.Run(ctx, s, page, []string{"-h"})
25891-			name := page.Name()
25892-			if name == appName {
25893-				name = "usage"
25894-			}
25895-			helpFile := filepath.Join("usage", name+".hlp")
25896-			got := buf.Bytes()
25897-			if *updateHelpFiles {
25898-				if err := ioutil.WriteFile(helpFile, got, 0666); err != nil {
25899-					t.Errorf("Failed writing %v: %v", helpFile, err)
25900-				}
25901-				return
25902-			}
25903-			want, err := ioutil.ReadFile(helpFile)
25904-			if err != nil {
25905-				t.Fatalf("Missing help file %q", helpFile)
25906-			}
25907-			if diff := cmp.Diff(string(want), string(got)); diff != "" {
25908-				t.Errorf("Help file %q did not match, run with -update-help-files to fix (-want +got)\n%s", helpFile, diff)
25909-			}
25910-		})
25911-	}
25912-}
25913diff -urN a/gopls/internal/lsp/cmd/highlight.go b/gopls/internal/lsp/cmd/highlight.go
25914--- a/gopls/internal/lsp/cmd/highlight.go	2000-01-01 00:00:00.000000000 -0000
25915+++ b/gopls/internal/lsp/cmd/highlight.go	1970-01-01 00:00:00.000000000 +0000
25916@@ -1,82 +0,0 @@
25917-// Copyright 2019 The Go Authors. All rights reserved.
25918-// Use of this source code is governed by a BSD-style
25919-// license that can be found in the LICENSE file.
25920-
25921-package cmd
25922-
25923-import (
25924-	"context"
25925-	"flag"
25926-	"fmt"
25927-
25928-	"golang.org/x/tools/gopls/internal/lsp/protocol"
25929-	"golang.org/x/tools/gopls/internal/span"
25930-	"golang.org/x/tools/internal/tool"
25931-)
25932-
25933-// highlight implements the highlight verb for gopls.
25934-type highlight struct {
25935-	app *Application
25936-}
25937-
25938-func (r *highlight) Name() string      { return "highlight" }
25939-func (r *highlight) Parent() string    { return r.app.Name() }
25940-func (r *highlight) Usage() string     { return "<position>" }
25941-func (r *highlight) ShortHelp() string { return "display selected identifier's highlights" }
25942-func (r *highlight) DetailedHelp(f *flag.FlagSet) {
25943-	fmt.Fprint(f.Output(), `
25944-Example:
25945-
25946-	$ # 1-indexed location (:line:column or :#offset) of the target identifier
25947-	$ gopls highlight helper/helper.go:8:6
25948-	$ gopls highlight helper/helper.go:#53
25949-`)
25950-	printFlagDefaults(f)
25951-}
25952-
25953-func (r *highlight) Run(ctx context.Context, args ...string) error {
25954-	if len(args) != 1 {
25955-		return tool.CommandLineErrorf("highlight expects 1 argument (position)")
25956-	}
25957-
25958-	conn, err := r.app.connect(ctx)
25959-	if err != nil {
25960-		return err
25961-	}
25962-	defer conn.terminate(ctx)
25963-
25964-	from := span.Parse(args[0])
25965-	file := conn.openFile(ctx, from.URI())
25966-	if file.err != nil {
25967-		return file.err
25968-	}
25969-
25970-	loc, err := file.mapper.SpanLocation(from)
25971-	if err != nil {
25972-		return err
25973-	}
25974-
25975-	p := protocol.DocumentHighlightParams{
25976-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
25977-	}
25978-	highlights, err := conn.DocumentHighlight(ctx, &p)
25979-	if err != nil {
25980-		return err
25981-	}
25982-
25983-	var results []span.Span
25984-	for _, h := range highlights {
25985-		s, err := file.mapper.RangeSpan(h.Range)
25986-		if err != nil {
25987-			return err
25988-		}
25989-		results = append(results, s)
25990-	}
25991-	// Sort results to make tests deterministic since DocumentHighlight uses a map.
25992-	span.SortSpans(results)
25993-
25994-	for _, s := range results {
25995-		fmt.Println(s)
25996-	}
25997-	return nil
25998-}
25999diff -urN a/gopls/internal/lsp/cmd/implementation.go b/gopls/internal/lsp/cmd/implementation.go
26000--- a/gopls/internal/lsp/cmd/implementation.go	2000-01-01 00:00:00.000000000 -0000
26001+++ b/gopls/internal/lsp/cmd/implementation.go	1970-01-01 00:00:00.000000000 +0000
26002@@ -1,84 +0,0 @@
26003-// Copyright 2019 The Go Authors. All rights reserved.
26004-// Use of this source code is governed by a BSD-style
26005-// license that can be found in the LICENSE file.
26006-
26007-package cmd
26008-
26009-import (
26010-	"context"
26011-	"flag"
26012-	"fmt"
26013-	"sort"
26014-
26015-	"golang.org/x/tools/gopls/internal/lsp/protocol"
26016-	"golang.org/x/tools/gopls/internal/span"
26017-	"golang.org/x/tools/internal/tool"
26018-)
26019-
26020-// implementation implements the implementation verb for gopls
26021-type implementation struct {
26022-	app *Application
26023-}
26024-
26025-func (i *implementation) Name() string      { return "implementation" }
26026-func (i *implementation) Parent() string    { return i.app.Name() }
26027-func (i *implementation) Usage() string     { return "<position>" }
26028-func (i *implementation) ShortHelp() string { return "display selected identifier's implementation" }
26029-func (i *implementation) DetailedHelp(f *flag.FlagSet) {
26030-	fmt.Fprint(f.Output(), `
26031-Example:
26032-
26033-	$ # 1-indexed location (:line:column or :#offset) of the target identifier
26034-	$ gopls implementation helper/helper.go:8:6
26035-	$ gopls implementation helper/helper.go:#53
26036-`)
26037-	printFlagDefaults(f)
26038-}
26039-
26040-func (i *implementation) Run(ctx context.Context, args ...string) error {
26041-	if len(args) != 1 {
26042-		return tool.CommandLineErrorf("implementation expects 1 argument (position)")
26043-	}
26044-
26045-	conn, err := i.app.connect(ctx)
26046-	if err != nil {
26047-		return err
26048-	}
26049-	defer conn.terminate(ctx)
26050-
26051-	from := span.Parse(args[0])
26052-	file := conn.openFile(ctx, from.URI())
26053-	if file.err != nil {
26054-		return file.err
26055-	}
26056-
26057-	loc, err := file.mapper.SpanLocation(from)
26058-	if err != nil {
26059-		return err
26060-	}
26061-
26062-	p := protocol.ImplementationParams{
26063-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
26064-	}
26065-	implementations, err := conn.Implementation(ctx, &p)
26066-	if err != nil {
26067-		return err
26068-	}
26069-
26070-	var spans []string
26071-	for _, impl := range implementations {
26072-		f := conn.openFile(ctx, fileURI(impl.URI))
26073-		span, err := f.mapper.LocationSpan(impl)
26074-		if err != nil {
26075-			return err
26076-		}
26077-		spans = append(spans, fmt.Sprint(span))
26078-	}
26079-	sort.Strings(spans)
26080-
26081-	for _, s := range spans {
26082-		fmt.Println(s)
26083-	}
26084-
26085-	return nil
26086-}
26087diff -urN a/gopls/internal/lsp/cmd/imports.go b/gopls/internal/lsp/cmd/imports.go
26088--- a/gopls/internal/lsp/cmd/imports.go	2000-01-01 00:00:00.000000000 -0000
26089+++ b/gopls/internal/lsp/cmd/imports.go	1970-01-01 00:00:00.000000000 +0000
26090@@ -1,105 +0,0 @@
26091-// Copyright 2019 The Go Authors. All rights reserved.
26092-// Use of this source code is governed by a BSD-style
26093-// license that can be found in the LICENSE file.
26094-
26095-package cmd
26096-
26097-import (
26098-	"context"
26099-	"flag"
26100-	"fmt"
26101-	"io/ioutil"
26102-	"os"
26103-
26104-	"golang.org/x/tools/gopls/internal/lsp/protocol"
26105-	"golang.org/x/tools/gopls/internal/lsp/source"
26106-	"golang.org/x/tools/gopls/internal/span"
26107-	"golang.org/x/tools/internal/diff"
26108-	"golang.org/x/tools/internal/tool"
26109-)
26110-
26111-// imports implements the import verb for gopls.
26112-type imports struct {
26113-	Diff  bool `flag:"d,diff" help:"display diffs instead of rewriting files"`
26114-	Write bool `flag:"w,write" help:"write result to (source) file instead of stdout"`
26115-
26116-	app *Application
26117-}
26118-
26119-func (t *imports) Name() string      { return "imports" }
26120-func (t *imports) Parent() string    { return t.app.Name() }
26121-func (t *imports) Usage() string     { return "[imports-flags] <filename>" }
26122-func (t *imports) ShortHelp() string { return "updates import statements" }
26123-func (t *imports) DetailedHelp(f *flag.FlagSet) {
26124-	fmt.Fprintf(f.Output(), `
26125-Example: update imports statements in a file:
26126-
26127-	$ gopls imports -w internal/lsp/cmd/check.go
26128-
26129-imports-flags:
26130-`)
26131-	printFlagDefaults(f)
26132-}
26133-
26134-// Run performs diagnostic checks on the file specified and either;
26135-// - if -w is specified, updates the file in place;
26136-// - if -d is specified, prints out unified diffs of the changes; or
26137-// - otherwise, prints the new versions to stdout.
26138-func (t *imports) Run(ctx context.Context, args ...string) error {
26139-	if len(args) != 1 {
26140-		return tool.CommandLineErrorf("imports expects 1 argument")
26141-	}
26142-	conn, err := t.app.connect(ctx)
26143-	if err != nil {
26144-		return err
26145-	}
26146-	defer conn.terminate(ctx)
26147-
26148-	from := span.Parse(args[0])
26149-	uri := from.URI()
26150-	file := conn.openFile(ctx, uri)
26151-	if file.err != nil {
26152-		return file.err
26153-	}
26154-	actions, err := conn.CodeAction(ctx, &protocol.CodeActionParams{
26155-		TextDocument: protocol.TextDocumentIdentifier{
26156-			URI: protocol.URIFromSpanURI(uri),
26157-		},
26158-	})
26159-	if err != nil {
26160-		return fmt.Errorf("%v: %v", from, err)
26161-	}
26162-	var edits []protocol.TextEdit
26163-	for _, a := range actions {
26164-		if a.Title != "Organize Imports" {
26165-			continue
26166-		}
26167-		for _, c := range a.Edit.DocumentChanges {
26168-			if c.TextDocumentEdit != nil {
26169-				if fileURI(c.TextDocumentEdit.TextDocument.URI) == uri {
26170-					edits = append(edits, c.TextDocumentEdit.Edits...)
26171-				}
26172-			}
26173-		}
26174-	}
26175-	newContent, sedits, err := source.ApplyProtocolEdits(file.mapper, edits)
26176-	if err != nil {
26177-		return fmt.Errorf("%v: %v", edits, err)
26178-	}
26179-	filename := file.uri.Filename()
26180-	switch {
26181-	case t.Write:
26182-		if len(edits) > 0 {
26183-			ioutil.WriteFile(filename, newContent, 0644)
26184-		}
26185-	case t.Diff:
26186-		unified, err := diff.ToUnified(filename+".orig", filename, string(file.mapper.Content), sedits)
26187-		if err != nil {
26188-			return err
26189-		}
26190-		fmt.Print(unified)
26191-	default:
26192-		os.Stdout.Write(newContent)
26193-	}
26194-	return nil
26195-}
26196diff -urN a/gopls/internal/lsp/cmd/info.go b/gopls/internal/lsp/cmd/info.go
26197--- a/gopls/internal/lsp/cmd/info.go	2000-01-01 00:00:00.000000000 -0000
26198+++ b/gopls/internal/lsp/cmd/info.go	1970-01-01 00:00:00.000000000 +0000
26199@@ -1,246 +0,0 @@
26200-// Copyright 2019 The Go Authors. All rights reserved.
26201-// Use of this source code is governed by a BSD-style
26202-// license that can be found in the LICENSE file.
26203-
26204-package cmd
26205-
26206-import (
26207-	"bytes"
26208-	"context"
26209-	"encoding/json"
26210-	"flag"
26211-	"fmt"
26212-	"net/url"
26213-	"os"
26214-	"strings"
26215-
26216-	"golang.org/x/tools/gopls/internal/lsp/browser"
26217-	"golang.org/x/tools/gopls/internal/lsp/debug"
26218-	"golang.org/x/tools/gopls/internal/lsp/source"
26219-	"golang.org/x/tools/internal/tool"
26220-)
26221-
26222-// help implements the help command.
26223-type help struct {
26224-	app *Application
26225-}
26226-
26227-func (h *help) Name() string      { return "help" }
26228-func (h *help) Parent() string    { return h.app.Name() }
26229-func (h *help) Usage() string     { return "" }
26230-func (h *help) ShortHelp() string { return "print usage information for subcommands" }
26231-func (h *help) DetailedHelp(f *flag.FlagSet) {
26232-	fmt.Fprint(f.Output(), `
26233-
26234-Examples:
26235-$ gopls help                         # main gopls help message
26236-$ gopls help remote                  # help on 'remote' command
26237-$ gopls help remote sessions         # help on 'remote sessions' subcommand
26238-`)
26239-	printFlagDefaults(f)
26240-}
26241-
26242-// Run prints help information about a subcommand.
26243-func (h *help) Run(ctx context.Context, args ...string) error {
26244-	find := func(cmds []tool.Application, name string) tool.Application {
26245-		for _, cmd := range cmds {
26246-			if cmd.Name() == name {
26247-				return cmd
26248-			}
26249-		}
26250-		return nil
26251-	}
26252-
26253-	// Find the subcommand denoted by args (empty => h.app).
26254-	var cmd tool.Application = h.app
26255-	for i, arg := range args {
26256-		cmd = find(getSubcommands(cmd), arg)
26257-		if cmd == nil {
26258-			return tool.CommandLineErrorf(
26259-				"no such subcommand: %s", strings.Join(args[:i+1], " "))
26260-		}
26261-	}
26262-
26263-	// 'gopls help cmd subcmd' is equivalent to 'gopls cmd subcmd -h'.
26264-	// The flag package prints the usage information (defined by tool.Run)
26265-	// when it sees the -h flag.
26266-	fs := flag.NewFlagSet(cmd.Name(), flag.ExitOnError)
26267-	return tool.Run(ctx, fs, h.app, append(args[:len(args):len(args)], "-h"))
26268-}
26269-
26270-// version implements the version command.
26271-type version struct {
26272-	JSON bool `flag:"json" help:"outputs in json format."`
26273-
26274-	app *Application
26275-}
26276-
26277-func (v *version) Name() string      { return "version" }
26278-func (v *version) Parent() string    { return v.app.Name() }
26279-func (v *version) Usage() string     { return "" }
26280-func (v *version) ShortHelp() string { return "print the gopls version information" }
26281-func (v *version) DetailedHelp(f *flag.FlagSet) {
26282-	fmt.Fprint(f.Output(), ``)
26283-	printFlagDefaults(f)
26284-}
26285-
26286-// Run prints version information to stdout.
26287-func (v *version) Run(ctx context.Context, args ...string) error {
26288-	var mode = debug.PlainText
26289-	if v.JSON {
26290-		mode = debug.JSON
26291-	}
26292-
26293-	return debug.PrintVersionInfo(ctx, os.Stdout, v.app.verbose(), mode)
26294-}
26295-
26296-// bug implements the bug command.
26297-type bug struct {
26298-	app *Application
26299-}
26300-
26301-func (b *bug) Name() string      { return "bug" }
26302-func (b *bug) Parent() string    { return b.app.Name() }
26303-func (b *bug) Usage() string     { return "" }
26304-func (b *bug) ShortHelp() string { return "report a bug in gopls" }
26305-func (b *bug) DetailedHelp(f *flag.FlagSet) {
26306-	fmt.Fprint(f.Output(), ``)
26307-	printFlagDefaults(f)
26308-}
26309-
26310-const goplsBugPrefix = "x/tools/gopls: <DESCRIBE THE PROBLEM>"
26311-const goplsBugHeader = `ATTENTION: Please answer these questions BEFORE submitting your issue. Thanks!
26312-
26313-#### What did you do?
26314-If possible, provide a recipe for reproducing the error.
26315-A complete runnable program is good.
26316-A link on play.golang.org is better.
26317-A failing unit test is the best.
26318-
26319-#### What did you expect to see?
26320-
26321-
26322-#### What did you see instead?
26323-
26324-
26325-`
26326-
26327-// Run collects some basic information and then prepares an issue ready to
26328-// be reported.
26329-func (b *bug) Run(ctx context.Context, args ...string) error {
26330-	buf := &bytes.Buffer{}
26331-	fmt.Fprint(buf, goplsBugHeader)
26332-	debug.PrintVersionInfo(ctx, buf, true, debug.Markdown)
26333-	body := buf.String()
26334-	title := strings.Join(args, " ")
26335-	if !strings.HasPrefix(title, goplsBugPrefix) {
26336-		title = goplsBugPrefix + title
26337-	}
26338-	if !browser.Open("https://github.com/golang/go/issues/new?title=" + url.QueryEscape(title) + "&body=" + url.QueryEscape(body)) {
26339-		fmt.Print("Please file a new issue at golang.org/issue/new using this template:\n\n")
26340-		fmt.Print(body)
26341-	}
26342-	return nil
26343-}
26344-
26345-type apiJSON struct {
26346-	app *Application
26347-}
26348-
26349-func (j *apiJSON) Name() string      { return "api-json" }
26350-func (j *apiJSON) Parent() string    { return j.app.Name() }
26351-func (j *apiJSON) Usage() string     { return "" }
26352-func (j *apiJSON) ShortHelp() string { return "print json describing gopls API" }
26353-func (j *apiJSON) DetailedHelp(f *flag.FlagSet) {
26354-	fmt.Fprint(f.Output(), ``)
26355-	printFlagDefaults(f)
26356-}
26357-
26358-func (j *apiJSON) Run(ctx context.Context, args ...string) error {
26359-	js, err := json.MarshalIndent(source.GeneratedAPIJSON, "", "\t")
26360-	if err != nil {
26361-		return err
26362-	}
26363-	fmt.Fprint(os.Stdout, string(js))
26364-	return nil
26365-}
26366-
26367-type licenses struct {
26368-	app *Application
26369-}
26370-
26371-func (l *licenses) Name() string      { return "licenses" }
26372-func (l *licenses) Parent() string    { return l.app.Name() }
26373-func (l *licenses) Usage() string     { return "" }
26374-func (l *licenses) ShortHelp() string { return "print licenses of included software" }
26375-func (l *licenses) DetailedHelp(f *flag.FlagSet) {
26376-	fmt.Fprint(f.Output(), ``)
26377-	printFlagDefaults(f)
26378-}
26379-
26380-const licensePreamble = `
26381-gopls is made available under the following BSD-style license:
26382-
26383-Copyright (c) 2009 The Go Authors. All rights reserved.
26384-
26385-Redistribution and use in source and binary forms, with or without
26386-modification, are permitted provided that the following conditions are
26387-met:
26388-
26389-   * Redistributions of source code must retain the above copyright
26390-notice, this list of conditions and the following disclaimer.
26391-   * Redistributions in binary form must reproduce the above
26392-copyright notice, this list of conditions and the following disclaimer
26393-in the documentation and/or other materials provided with the
26394-distribution.
26395-   * Neither the name of Google Inc. nor the names of its
26396-contributors may be used to endorse or promote products derived from
26397-this software without specific prior written permission.
26398-
26399-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26400-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26401-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26402-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26403-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26404-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26405-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26406-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26407-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26408-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26409-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26410-
26411-gopls implements the LSP specification, which is made available under the following license:
26412-
26413-Copyright (c) Microsoft Corporation
26414-
26415-All rights reserved.
26416-
26417-MIT License
26418-
26419-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
26420-files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
26421-modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
26422-is furnished to do so, subject to the following conditions:
26423-
26424-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
26425-
26426-THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
26427-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
26428-BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
26429-OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26430-
26431-gopls also includes software made available under these licenses:
26432-`
26433-
26434-func (l *licenses) Run(ctx context.Context, args ...string) error {
26435-	opts := source.DefaultOptions()
26436-	l.app.options(opts)
26437-	txt := licensePreamble
26438-	if opts.LicensesText == "" {
26439-		txt += "(development gopls, license information not available)"
26440-	} else {
26441-		txt += opts.LicensesText
26442-	}
26443-	fmt.Fprint(os.Stdout, txt)
26444-	return nil
26445-}
26446diff -urN a/gopls/internal/lsp/cmd/links.go b/gopls/internal/lsp/cmd/links.go
26447--- a/gopls/internal/lsp/cmd/links.go	2000-01-01 00:00:00.000000000 -0000
26448+++ b/gopls/internal/lsp/cmd/links.go	1970-01-01 00:00:00.000000000 +0000
26449@@ -1,77 +0,0 @@
26450-// Copyright 2019 The Go Authors. All rights reserved.
26451-// Use of this source code is governed by a BSD-style
26452-// license that can be found in the LICENSE file.
26453-
26454-package cmd
26455-
26456-import (
26457-	"context"
26458-	"encoding/json"
26459-	"flag"
26460-	"fmt"
26461-	"os"
26462-
26463-	"golang.org/x/tools/gopls/internal/lsp/protocol"
26464-	"golang.org/x/tools/gopls/internal/span"
26465-	"golang.org/x/tools/internal/tool"
26466-)
26467-
26468-// links implements the links verb for gopls.
26469-type links struct {
26470-	JSON bool `flag:"json" help:"emit document links in JSON format"`
26471-
26472-	app *Application
26473-}
26474-
26475-func (l *links) Name() string      { return "links" }
26476-func (l *links) Parent() string    { return l.app.Name() }
26477-func (l *links) Usage() string     { return "[links-flags] <filename>" }
26478-func (l *links) ShortHelp() string { return "list links in a file" }
26479-func (l *links) DetailedHelp(f *flag.FlagSet) {
26480-	fmt.Fprintf(f.Output(), `
26481-Example: list links contained within a file:
26482-
26483-	$ gopls links internal/lsp/cmd/check.go
26484-
26485-links-flags:
26486-`)
26487-	printFlagDefaults(f)
26488-}
26489-
26490-// Run finds all the links within a document
26491-// - if -json is specified, outputs location range and uri
26492-// - otherwise, prints the a list of unique links
26493-func (l *links) Run(ctx context.Context, args ...string) error {
26494-	if len(args) != 1 {
26495-		return tool.CommandLineErrorf("links expects 1 argument")
26496-	}
26497-	conn, err := l.app.connect(ctx)
26498-	if err != nil {
26499-		return err
26500-	}
26501-	defer conn.terminate(ctx)
26502-
26503-	from := span.Parse(args[0])
26504-	uri := from.URI()
26505-	file := conn.openFile(ctx, uri)
26506-	if file.err != nil {
26507-		return file.err
26508-	}
26509-	results, err := conn.DocumentLink(ctx, &protocol.DocumentLinkParams{
26510-		TextDocument: protocol.TextDocumentIdentifier{
26511-			URI: protocol.URIFromSpanURI(uri),
26512-		},
26513-	})
26514-	if err != nil {
26515-		return fmt.Errorf("%v: %v", from, err)
26516-	}
26517-	if l.JSON {
26518-		enc := json.NewEncoder(os.Stdout)
26519-		enc.SetIndent("", "\t")
26520-		return enc.Encode(results)
26521-	}
26522-	for _, v := range results {
26523-		fmt.Println(v.Target)
26524-	}
26525-	return nil
26526-}
26527diff -urN a/gopls/internal/lsp/cmd/prepare_rename.go b/gopls/internal/lsp/cmd/prepare_rename.go
26528--- a/gopls/internal/lsp/cmd/prepare_rename.go	2000-01-01 00:00:00.000000000 -0000
26529+++ b/gopls/internal/lsp/cmd/prepare_rename.go	1970-01-01 00:00:00.000000000 +0000
26530@@ -1,80 +0,0 @@
26531-// Copyright 2019 The Go Authors. All rights reserved.
26532-// Use of this source code is governed by a BSD-style
26533-// license that can be found in the LICENSE file.
26534-
26535-package cmd
26536-
26537-import (
26538-	"context"
26539-	"errors"
26540-	"flag"
26541-	"fmt"
26542-
26543-	"golang.org/x/tools/gopls/internal/lsp/protocol"
26544-	"golang.org/x/tools/gopls/internal/span"
26545-	"golang.org/x/tools/internal/tool"
26546-)
26547-
26548-// prepareRename implements the prepare_rename verb for gopls.
26549-type prepareRename struct {
26550-	app *Application
26551-}
26552-
26553-func (r *prepareRename) Name() string      { return "prepare_rename" }
26554-func (r *prepareRename) Parent() string    { return r.app.Name() }
26555-func (r *prepareRename) Usage() string     { return "<position>" }
26556-func (r *prepareRename) ShortHelp() string { return "test validity of a rename operation at location" }
26557-func (r *prepareRename) DetailedHelp(f *flag.FlagSet) {
26558-	fmt.Fprint(f.Output(), `
26559-Example:
26560-
26561-	$ # 1-indexed location (:line:column or :#offset) of the target identifier
26562-	$ gopls prepare_rename helper/helper.go:8:6
26563-	$ gopls prepare_rename helper/helper.go:#53
26564-`)
26565-	printFlagDefaults(f)
26566-}
26567-
26568-// ErrInvalidRenamePosition is returned when prepareRename is run at a position that
26569-// is not a candidate for renaming.
26570-var ErrInvalidRenamePosition = errors.New("request is not valid at the given position")
26571-
26572-func (r *prepareRename) Run(ctx context.Context, args ...string) error {
26573-	if len(args) != 1 {
26574-		return tool.CommandLineErrorf("prepare_rename expects 1 argument (file)")
26575-	}
26576-
26577-	conn, err := r.app.connect(ctx)
26578-	if err != nil {
26579-		return err
26580-	}
26581-	defer conn.terminate(ctx)
26582-
26583-	from := span.Parse(args[0])
26584-	file := conn.openFile(ctx, from.URI())
26585-	if file.err != nil {
26586-		return file.err
26587-	}
26588-	loc, err := file.mapper.SpanLocation(from)
26589-	if err != nil {
26590-		return err
26591-	}
26592-	p := protocol.PrepareRenameParams{
26593-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
26594-	}
26595-	result, err := conn.PrepareRename(ctx, &p)
26596-	if err != nil {
26597-		return fmt.Errorf("prepare_rename failed: %w", err)
26598-	}
26599-	if result == nil {
26600-		return ErrInvalidRenamePosition
26601-	}
26602-
26603-	s, err := file.mapper.RangeSpan(result.Range)
26604-	if err != nil {
26605-		return err
26606-	}
26607-
26608-	fmt.Println(s)
26609-	return nil
26610-}
26611diff -urN a/gopls/internal/lsp/cmd/references.go b/gopls/internal/lsp/cmd/references.go
26612--- a/gopls/internal/lsp/cmd/references.go	2000-01-01 00:00:00.000000000 -0000
26613+++ b/gopls/internal/lsp/cmd/references.go	1970-01-01 00:00:00.000000000 +0000
26614@@ -1,89 +0,0 @@
26615-// Copyright 2019 The Go Authors. All rights reserved.
26616-// Use of this source code is governed by a BSD-style
26617-// license that can be found in the LICENSE file.
26618-
26619-package cmd
26620-
26621-import (
26622-	"context"
26623-	"flag"
26624-	"fmt"
26625-	"sort"
26626-
26627-	"golang.org/x/tools/gopls/internal/lsp/protocol"
26628-	"golang.org/x/tools/gopls/internal/span"
26629-	"golang.org/x/tools/internal/tool"
26630-)
26631-
26632-// references implements the references verb for gopls
26633-type references struct {
26634-	IncludeDeclaration bool `flag:"d,declaration" help:"include the declaration of the specified identifier in the results"`
26635-
26636-	app *Application
26637-}
26638-
26639-func (r *references) Name() string      { return "references" }
26640-func (r *references) Parent() string    { return r.app.Name() }
26641-func (r *references) Usage() string     { return "[references-flags] <position>" }
26642-func (r *references) ShortHelp() string { return "display selected identifier's references" }
26643-func (r *references) DetailedHelp(f *flag.FlagSet) {
26644-	fmt.Fprint(f.Output(), `
26645-Example:
26646-
26647-	$ # 1-indexed location (:line:column or :#offset) of the target identifier
26648-	$ gopls references helper/helper.go:8:6
26649-	$ gopls references helper/helper.go:#53
26650-
26651-references-flags:
26652-`)
26653-	printFlagDefaults(f)
26654-}
26655-
26656-func (r *references) Run(ctx context.Context, args ...string) error {
26657-	if len(args) != 1 {
26658-		return tool.CommandLineErrorf("references expects 1 argument (position)")
26659-	}
26660-
26661-	conn, err := r.app.connect(ctx)
26662-	if err != nil {
26663-		return err
26664-	}
26665-	defer conn.terminate(ctx)
26666-
26667-	from := span.Parse(args[0])
26668-	file := conn.openFile(ctx, from.URI())
26669-	if file.err != nil {
26670-		return file.err
26671-	}
26672-	loc, err := file.mapper.SpanLocation(from)
26673-	if err != nil {
26674-		return err
26675-	}
26676-	p := protocol.ReferenceParams{
26677-		Context: protocol.ReferenceContext{
26678-			IncludeDeclaration: r.IncludeDeclaration,
26679-		},
26680-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
26681-	}
26682-	locations, err := conn.References(ctx, &p)
26683-	if err != nil {
26684-		return err
26685-	}
26686-	var spans []string
26687-	for _, l := range locations {
26688-		f := conn.openFile(ctx, fileURI(l.URI))
26689-		// convert location to span for user-friendly 1-indexed line
26690-		// and column numbers
26691-		span, err := f.mapper.LocationSpan(l)
26692-		if err != nil {
26693-			return err
26694-		}
26695-		spans = append(spans, fmt.Sprint(span))
26696-	}
26697-
26698-	sort.Strings(spans)
26699-	for _, s := range spans {
26700-		fmt.Println(s)
26701-	}
26702-	return nil
26703-}
26704diff -urN a/gopls/internal/lsp/cmd/remote.go b/gopls/internal/lsp/cmd/remote.go
26705--- a/gopls/internal/lsp/cmd/remote.go	2000-01-01 00:00:00.000000000 -0000
26706+++ b/gopls/internal/lsp/cmd/remote.go	1970-01-01 00:00:00.000000000 +0000
26707@@ -1,164 +0,0 @@
26708-// Copyright 2020 The Go Authors. All rights reserved.
26709-// Use of this source code is governed by a BSD-style
26710-// license that can be found in the LICENSE file.
26711-
26712-package cmd
26713-
26714-import (
26715-	"context"
26716-	"encoding/json"
26717-	"errors"
26718-	"flag"
26719-	"fmt"
26720-	"log"
26721-	"os"
26722-
26723-	"golang.org/x/tools/gopls/internal/lsp/command"
26724-	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
26725-)
26726-
26727-type remote struct {
26728-	app *Application
26729-	subcommands
26730-
26731-	// For backward compatibility, allow aliasing this command (it was previously
26732-	// called 'inspect').
26733-	//
26734-	// TODO(rFindley): delete this after allowing some transition time in case
26735-	//                 there were any users of 'inspect' (I suspect not).
26736-	alias string
26737-}
26738-
26739-func newRemote(app *Application, alias string) *remote {
26740-	return &remote{
26741-		app: app,
26742-		subcommands: subcommands{
26743-			&listSessions{app: app},
26744-			&startDebugging{app: app},
26745-		},
26746-		alias: alias,
26747-	}
26748-}
26749-
26750-func (r *remote) Name() string {
26751-	if r.alias != "" {
26752-		return r.alias
26753-	}
26754-	return "remote"
26755-}
26756-
26757-func (r *remote) Parent() string { return r.app.Name() }
26758-
26759-func (r *remote) ShortHelp() string {
26760-	short := "interact with the gopls daemon"
26761-	if r.alias != "" {
26762-		short += " (deprecated: use 'remote')"
26763-	}
26764-	return short
26765-}
26766-
26767-// listSessions is an inspect subcommand to list current sessions.
26768-type listSessions struct {
26769-	app *Application
26770-}
26771-
26772-func (c *listSessions) Name() string   { return "sessions" }
26773-func (c *listSessions) Parent() string { return c.app.Name() }
26774-func (c *listSessions) Usage() string  { return "" }
26775-func (c *listSessions) ShortHelp() string {
26776-	return "print information about current gopls sessions"
26777-}
26778-
26779-const listSessionsExamples = `
26780-Examples:
26781-
26782-1) list sessions for the default daemon:
26783-
26784-$ gopls -remote=auto remote sessions
26785-or just
26786-$ gopls remote sessions
26787-
26788-2) list sessions for a specific daemon:
26789-
26790-$ gopls -remote=localhost:8082 remote sessions
26791-`
26792-
26793-func (c *listSessions) DetailedHelp(f *flag.FlagSet) {
26794-	fmt.Fprint(f.Output(), listSessionsExamples)
26795-	printFlagDefaults(f)
26796-}
26797-
26798-func (c *listSessions) Run(ctx context.Context, args ...string) error {
26799-	remote := c.app.Remote
26800-	if remote == "" {
26801-		remote = "auto"
26802-	}
26803-	state, err := lsprpc.QueryServerState(ctx, remote)
26804-	if err != nil {
26805-		return err
26806-	}
26807-	v, err := json.MarshalIndent(state, "", "\t")
26808-	if err != nil {
26809-		log.Fatal(err)
26810-	}
26811-	os.Stdout.Write(v)
26812-	return nil
26813-}
26814-
26815-type startDebugging struct {
26816-	app *Application
26817-}
26818-
26819-func (c *startDebugging) Name() string  { return "debug" }
26820-func (c *startDebugging) Usage() string { return "[host:port]" }
26821-func (c *startDebugging) ShortHelp() string {
26822-	return "start the debug server"
26823-}
26824-
26825-const startDebuggingExamples = `
26826-Examples:
26827-
26828-1) start a debug server for the default daemon, on an arbitrary port:
26829-
26830-$ gopls -remote=auto remote debug
26831-or just
26832-$ gopls remote debug
26833-
26834-2) start for a specific daemon, on a specific port:
26835-
26836-$ gopls -remote=localhost:8082 remote debug localhost:8083
26837-`
26838-
26839-func (c *startDebugging) DetailedHelp(f *flag.FlagSet) {
26840-	fmt.Fprint(f.Output(), startDebuggingExamples)
26841-	printFlagDefaults(f)
26842-}
26843-
26844-func (c *startDebugging) Run(ctx context.Context, args ...string) error {
26845-	if len(args) > 1 {
26846-		fmt.Fprintln(os.Stderr, c.Usage())
26847-		return errors.New("invalid usage")
26848-	}
26849-	remote := c.app.Remote
26850-	if remote == "" {
26851-		remote = "auto"
26852-	}
26853-	debugAddr := ""
26854-	if len(args) > 0 {
26855-		debugAddr = args[0]
26856-	}
26857-	debugArgs := command.DebuggingArgs{
26858-		Addr: debugAddr,
26859-	}
26860-	var result command.DebuggingResult
26861-	if err := lsprpc.ExecuteCommand(ctx, remote, command.StartDebugging.ID(), debugArgs, &result); err != nil {
26862-		return err
26863-	}
26864-	if len(result.URLs) == 0 {
26865-		return errors.New("no debugging URLs")
26866-	}
26867-	for _, url := range result.URLs {
26868-		fmt.Printf("debugging on %s\n", url)
26869-	}
26870-	return nil
26871-}
26872diff -urN a/gopls/internal/lsp/cmd/rename.go b/gopls/internal/lsp/cmd/rename.go
26873--- a/gopls/internal/lsp/cmd/rename.go	2000-01-01 00:00:00.000000000 -0000
26874+++ b/gopls/internal/lsp/cmd/rename.go	1970-01-01 00:00:00.000000000 +0000
26875@@ -1,130 +0,0 @@
26876-// Copyright 2019 The Go Authors. All rights reserved.
26877-// Use of this source code is governed by a BSD-style
26878-// license that can be found in the LICENSE file.
26879-
26880-package cmd
26881-
26882-import (
26883-	"context"
26884-	"flag"
26885-	"fmt"
26886-	"io/ioutil"
26887-	"os"
26888-	"path/filepath"
26889-	"sort"
26890-
26891-	"golang.org/x/tools/gopls/internal/lsp/protocol"
26892-	"golang.org/x/tools/gopls/internal/lsp/source"
26893-	"golang.org/x/tools/gopls/internal/span"
26894-	"golang.org/x/tools/internal/diff"
26895-	"golang.org/x/tools/internal/tool"
26896-)
26897-
26898-// rename implements the rename verb for gopls.
26899-type rename struct {
26900-	Diff     bool `flag:"d,diff" help:"display diffs instead of rewriting files"`
26901-	Write    bool `flag:"w,write" help:"write result to (source) file instead of stdout"`
26902-	Preserve bool `flag:"preserve" help:"preserve original files"`
26903-
26904-	app *Application
26905-}
26906-
26907-func (r *rename) Name() string      { return "rename" }
26908-func (r *rename) Parent() string    { return r.app.Name() }
26909-func (r *rename) Usage() string     { return "[rename-flags] <position> <name>" }
26910-func (r *rename) ShortHelp() string { return "rename selected identifier" }
26911-func (r *rename) DetailedHelp(f *flag.FlagSet) {
26912-	fmt.Fprint(f.Output(), `
26913-Example:
26914-
26915-	$ # 1-based location (:line:column or :#position) of the thing to change
26916-	$ gopls rename helper/helper.go:8:6 Foo
26917-	$ gopls rename helper/helper.go:#53 Foo
26918-
26919-rename-flags:
26920-`)
26921-	printFlagDefaults(f)
26922-}
26923-
26924-// Run renames the specified identifier and either;
26925-// - if -w is specified, updates the file(s) in place;
26926-// - if -d is specified, prints out unified diffs of the changes; or
26927-// - otherwise, prints the new versions to stdout.
26928-func (r *rename) Run(ctx context.Context, args ...string) error {
26929-	if len(args) != 2 {
26930-		return tool.CommandLineErrorf("definition expects 2 arguments (position, new name)")
26931-	}
26932-	conn, err := r.app.connect(ctx)
26933-	if err != nil {
26934-		return err
26935-	}
26936-	defer conn.terminate(ctx)
26937-
26938-	from := span.Parse(args[0])
26939-	file := conn.openFile(ctx, from.URI())
26940-	if file.err != nil {
26941-		return file.err
26942-	}
26943-	loc, err := file.mapper.SpanLocation(from)
26944-	if err != nil {
26945-		return err
26946-	}
26947-	p := protocol.RenameParams{
26948-		TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI},
26949-		Position:     loc.Range.Start,
26950-		NewName:      args[1],
26951-	}
26952-	edit, err := conn.Rename(ctx, &p)
26953-	if err != nil {
26954-		return err
26955-	}
26956-	var orderedURIs []string
26957-	edits := map[span.URI][]protocol.TextEdit{}
26958-	for _, c := range edit.DocumentChanges {
26959-		if c.TextDocumentEdit != nil {
26960-			uri := fileURI(c.TextDocumentEdit.TextDocument.URI)
26961-			edits[uri] = append(edits[uri], c.TextDocumentEdit.Edits...)
26962-			orderedURIs = append(orderedURIs, string(uri))
26963-		}
26964-	}
26965-	sort.Strings(orderedURIs)
26966-	changeCount := len(orderedURIs)
26967-
26968-	for _, u := range orderedURIs {
26969-		uri := span.URIFromURI(u)
26970-		cmdFile := conn.openFile(ctx, uri)
26971-		filename := cmdFile.uri.Filename()
26972-
26973-		newContent, renameEdits, err := source.ApplyProtocolEdits(cmdFile.mapper, edits[uri])
26974-		if err != nil {
26975-			return fmt.Errorf("%v: %v", edits, err)
26976-		}
26977-
26978-		switch {
26979-		case r.Write:
26980-			fmt.Fprintln(os.Stderr, filename)
26981-			if r.Preserve {
26982-				if err := os.Rename(filename, filename+".orig"); err != nil {
26983-					return fmt.Errorf("%v: %v", edits, err)
26984-				}
26985-			}
26986-			ioutil.WriteFile(filename, newContent, 0644)
26987-		case r.Diff:
26988-			unified, err := diff.ToUnified(filename+".orig", filename, string(cmdFile.mapper.Content), renameEdits)
26989-			if err != nil {
26990-				return err
26991-			}
26992-			fmt.Print(unified)
26993-		default:
26994-			if len(orderedURIs) > 1 {
26995-				fmt.Printf("%s:\n", filepath.Base(filename))
26996-			}
26997-			os.Stdout.Write(newContent)
26998-			if changeCount > 1 { // if this wasn't last change, print newline
26999-				fmt.Println()
27000-			}
27001-			changeCount -= 1
27002-		}
27003-	}
27004-	return nil
27005-}
27006diff -urN a/gopls/internal/lsp/cmd/semantictokens.go b/gopls/internal/lsp/cmd/semantictokens.go
27007--- a/gopls/internal/lsp/cmd/semantictokens.go	2000-01-01 00:00:00.000000000 -0000
27008+++ b/gopls/internal/lsp/cmd/semantictokens.go	1970-01-01 00:00:00.000000000 +0000
27009@@ -1,225 +0,0 @@
27010-// Copyright 2020 The Go Authors. All rights reserved.
27011-// Use of this source code is governed by a BSD-style
27012-// license that can be found in the LICENSE file.
27013-
27014-package cmd
27015-
27016-import (
27017-	"bytes"
27018-	"context"
27019-	"flag"
27020-	"fmt"
27021-	"go/parser"
27022-	"go/token"
27023-	"io/ioutil"
27024-	"log"
27025-	"os"
27026-	"unicode/utf8"
27027-
27028-	"golang.org/x/tools/gopls/internal/lsp"
27029-	"golang.org/x/tools/gopls/internal/lsp/protocol"
27030-	"golang.org/x/tools/gopls/internal/lsp/source"
27031-	"golang.org/x/tools/gopls/internal/span"
27032-)
27033-
27034-// generate semantic tokens and interpolate them in the file
27035-
27036-// The output is the input file decorated with comments showing the
27037-// syntactic tokens. The comments are stylized:
27038-//   /*<arrow><length>,<token type>,[<modifiers]*/
27039-// For most occurrences, the comment comes just before the token it
27040-// describes, and arrow is a right arrow. If the token is inside a string
27041-// the comment comes just after the string, and the arrow is a left arrow.
27042-// <length> is the length of the token in runes, <token type> is one
27043-// of the supported semantic token types, and <modifiers. is a
27044-// (possibly empty) list of token type modifiers.
27045-
27046-// There are 3 coordinate systems for lines and character offsets in lines
27047-// LSP (what's returned from semanticTokens()):
27048-//    0-based: the first line is line 0, the first character of a line
27049-//      is character 0, and characters are counted as UTF-16 code points
27050-// gopls (and Go error messages):
27051-//    1-based: the first line is line1, the first character of a line
27052-//      is character 0, and characters are counted as bytes
27053-// internal (as used in marks, and lines:=bytes.Split(buf, '\n'))
27054-//    0-based: lines and character positions are 1 less than in
27055-//      the gopls coordinate system
27056-
27057-type semtok struct {
27058-	app *Application
27059-}
27060-
27061-var colmap *protocol.Mapper
27062-
27063-func (c *semtok) Name() string      { return "semtok" }
27064-func (c *semtok) Parent() string    { return c.app.Name() }
27065-func (c *semtok) Usage() string     { return "<filename>" }
27066-func (c *semtok) ShortHelp() string { return "show semantic tokens for the specified file" }
27067-func (c *semtok) DetailedHelp(f *flag.FlagSet) {
27068-	fmt.Fprint(f.Output(), `
27069-Example: show the semantic tokens for this file:
27070-
27071-	$ gopls semtok internal/lsp/cmd/semtok.go
27072-`)
27073-	printFlagDefaults(f)
27074-}
27075-
27076-// Run performs the semtok on the files specified by args and prints the
27077-// results to stdout in the format described above.
27078-func (c *semtok) Run(ctx context.Context, args ...string) error {
27079-	if len(args) != 1 {
27080-		return fmt.Errorf("expected one file name, got %d", len(args))
27081-	}
27082-	// perhaps simpler if app had just had a FlagSet member
27083-	origOptions := c.app.options
27084-	c.app.options = func(opts *source.Options) {
27085-		origOptions(opts)
27086-		opts.SemanticTokens = true
27087-	}
27088-	conn, err := c.app.connect(ctx)
27089-	if err != nil {
27090-		return err
27091-	}
27092-	defer conn.terminate(ctx)
27093-	uri := span.URIFromPath(args[0])
27094-	file := conn.openFile(ctx, uri)
27095-	if file.err != nil {
27096-		return file.err
27097-	}
27098-
27099-	buf, err := ioutil.ReadFile(args[0])
27100-	if err != nil {
27101-		return err
27102-	}
27103-	lines := bytes.Split(buf, []byte{'\n'})
27104-	p := &protocol.SemanticTokensRangeParams{
27105-		TextDocument: protocol.TextDocumentIdentifier{
27106-			URI: protocol.URIFromSpanURI(uri),
27107-		},
27108-		Range: protocol.Range{Start: protocol.Position{Line: 0, Character: 0},
27109-			End: protocol.Position{
27110-				Line:      uint32(len(lines) - 1),
27111-				Character: uint32(len(lines[len(lines)-1]))},
27112-		},
27113-	}
27114-	resp, err := conn.semanticTokens(ctx, p)
27115-	if err != nil {
27116-		return err
27117-	}
27118-	fset := token.NewFileSet()
27119-	f, err := parser.ParseFile(fset, args[0], buf, 0)
27120-	if err != nil {
27121-		log.Printf("parsing %s failed %v", args[0], err)
27122-		return err
27123-	}
27124-	tok := fset.File(f.Pos())
27125-	if tok == nil {
27126-		// can't happen; just parsed this file
27127-		return fmt.Errorf("can't find %s in fset", args[0])
27128-	}
27129-	colmap = protocol.NewMapper(uri, buf)
27130-	err = decorate(file.uri.Filename(), resp.Data)
27131-	if err != nil {
27132-		return err
27133-	}
27134-	return nil
27135-}
27136-
27137-type mark struct {
27138-	line, offset int // 1-based, from RangeSpan
27139-	len          int // bytes, not runes
27140-	typ          string
27141-	mods         []string
27142-}
27143-
27144-// prefixes for semantic token comments
27145-const (
27146-	SemanticLeft  = "/*⇐"
27147-	SemanticRight = "/*⇒"
27148-)
27149-
27150-func markLine(m mark, lines [][]byte) {
27151-	l := lines[m.line-1] // mx is 1-based
27152-	length := utf8.RuneCount(l[m.offset-1 : m.offset-1+m.len])
27153-	splitAt := m.offset - 1
27154-	insert := ""
27155-	if m.typ == "namespace" && m.offset-1+m.len < len(l) && l[m.offset-1+m.len] == '"' {
27156-		// it is the last component of an import spec
27157-		// cannot put a comment inside a string
27158-		insert = fmt.Sprintf("%s%d,namespace,[]*/", SemanticLeft, length)
27159-		splitAt = m.offset + m.len
27160-	} else {
27161-		// be careful not to generate //*
27162-		spacer := ""
27163-		if splitAt-1 >= 0 && l[splitAt-1] == '/' {
27164-			spacer = " "
27165-		}
27166-		insert = fmt.Sprintf("%s%s%d,%s,%v*/", spacer, SemanticRight, length, m.typ, m.mods)
27167-	}
27168-	x := append([]byte(insert), l[splitAt:]...)
27169-	l = append(l[:splitAt], x...)
27170-	lines[m.line-1] = l
27171-}
27172-
27173-func decorate(file string, result []uint32) error {
27174-	buf, err := ioutil.ReadFile(file)
27175-	if err != nil {
27176-		return err
27177-	}
27178-	marks := newMarks(result)
27179-	if len(marks) == 0 {
27180-		return nil
27181-	}
27182-	lines := bytes.Split(buf, []byte{'\n'})
27183-	for i := len(marks) - 1; i >= 0; i-- {
27184-		mx := marks[i]
27185-		markLine(mx, lines)
27186-	}
27187-	os.Stdout.Write(bytes.Join(lines, []byte{'\n'}))
27188-	return nil
27189-}
27190-
27191-func newMarks(d []uint32) []mark {
27192-	ans := []mark{}
27193-	// the following two loops could be merged, at the cost
27194-	// of making the logic slightly more complicated to understand
27195-	// first, convert from deltas to absolute, in LSP coordinates
27196-	lspLine := make([]uint32, len(d)/5)
27197-	lspChar := make([]uint32, len(d)/5)
27198-	var line, char uint32
27199-	for i := 0; 5*i < len(d); i++ {
27200-		lspLine[i] = line + d[5*i+0]
27201-		if d[5*i+0] > 0 {
27202-			char = 0
27203-		}
27204-		lspChar[i] = char + d[5*i+1]
27205-		char = lspChar[i]
27206-		line = lspLine[i]
27207-	}
27208-	// second, convert to gopls coordinates
27209-	for i := 0; 5*i < len(d); i++ {
27210-		pr := protocol.Range{
27211-			Start: protocol.Position{
27212-				Line:      lspLine[i],
27213-				Character: lspChar[i],
27214-			},
27215-			End: protocol.Position{
27216-				Line:      lspLine[i],
27217-				Character: lspChar[i] + d[5*i+2],
27218-			},
27219-		}
27220-		spn, err := colmap.RangeSpan(pr)
27221-		if err != nil {
27222-			log.Fatal(err)
27223-		}
27224-		m := mark{
27225-			line:   spn.Start().Line(),
27226-			offset: spn.Start().Column(),
27227-			len:    spn.End().Column() - spn.Start().Column(),
27228-			typ:    lsp.SemType(int(d[5*i+3])),
27229-			mods:   lsp.SemMods(int(d[5*i+4])),
27230-		}
27231-		ans = append(ans, m)
27232-	}
27233-	return ans
27234-}
27235diff -urN a/gopls/internal/lsp/cmd/serve.go b/gopls/internal/lsp/cmd/serve.go
27236--- a/gopls/internal/lsp/cmd/serve.go	2000-01-01 00:00:00.000000000 -0000
27237+++ b/gopls/internal/lsp/cmd/serve.go	1970-01-01 00:00:00.000000000 +0000
27238@@ -1,130 +0,0 @@
27239-// Copyright 2018 The Go Authors. All rights reserved.
27240-// Use of this source code is governed by a BSD-style
27241-// license that can be found in the LICENSE file.
27242-
27243-package cmd
27244-
27245-import (
27246-	"context"
27247-	"errors"
27248-	"flag"
27249-	"fmt"
27250-	"io"
27251-	"log"
27252-	"os"
27253-	"time"
27254-
27255-	"golang.org/x/tools/gopls/internal/lsp/cache"
27256-	"golang.org/x/tools/gopls/internal/lsp/debug"
27257-	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
27258-	"golang.org/x/tools/gopls/internal/lsp/protocol"
27259-	"golang.org/x/tools/internal/fakenet"
27260-	"golang.org/x/tools/internal/jsonrpc2"
27261-	"golang.org/x/tools/internal/tool"
27262-)
27263-
27264-// Serve is a struct that exposes the configurable parts of the LSP server as
27265-// flags, in the right form for tool.Main to consume.
27266-type Serve struct {
27267-	Logfile     string        `flag:"logfile" help:"filename to log to. if value is \"auto\", then logging to a default output file is enabled"`
27268-	Mode        string        `flag:"mode" help:"no effect"`
27269-	Port        int           `flag:"port" help:"port on which to run gopls for debugging purposes"`
27270-	Address     string        `flag:"listen" help:"address on which to listen for remote connections. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. Otherwise, TCP is used."`
27271-	IdleTimeout time.Duration `flag:"listen.timeout" help:"when used with -listen, shut down the server when there are no connected clients for this duration"`
27272-	Trace       bool          `flag:"rpc.trace" help:"print the full rpc trace in lsp inspector format"`
27273-	Debug       string        `flag:"debug" help:"serve debug information on the supplied address"`
27274-
27275-	RemoteListenTimeout time.Duration `flag:"remote.listen.timeout" help:"when used with -remote=auto, the -listen.timeout value used to start the daemon"`
27276-	RemoteDebug         string        `flag:"remote.debug" help:"when used with -remote=auto, the -debug value used to start the daemon"`
27277-	RemoteLogfile       string        `flag:"remote.logfile" help:"when used with -remote=auto, the -logfile value used to start the daemon"`
27278-
27279-	app *Application
27280-}
27281-
27282-func (s *Serve) Name() string   { return "serve" }
27283-func (s *Serve) Parent() string { return s.app.Name() }
27284-func (s *Serve) Usage() string  { return "[server-flags]" }
27285-func (s *Serve) ShortHelp() string {
27286-	return "run a server for Go code using the Language Server Protocol"
27287-}
27288-func (s *Serve) DetailedHelp(f *flag.FlagSet) {
27289-	fmt.Fprint(f.Output(), `  gopls [flags] [server-flags]
27290-
27291-The server communicates using JSONRPC2 on stdin and stdout, and is intended to be run directly as
27292-a child of an editor process.
27293-
27294-server-flags:
27295-`)
27296-	printFlagDefaults(f)
27297-}
27298-
27299-func (s *Serve) remoteArgs(network, address string) []string {
27300-	args := []string{"serve",
27301-		"-listen", fmt.Sprintf(`%s;%s`, network, address),
27302-	}
27303-	if s.RemoteDebug != "" {
27304-		args = append(args, "-debug", s.RemoteDebug)
27305-	}
27306-	if s.RemoteListenTimeout != 0 {
27307-		args = append(args, "-listen.timeout", s.RemoteListenTimeout.String())
27308-	}
27309-	if s.RemoteLogfile != "" {
27310-		args = append(args, "-logfile", s.RemoteLogfile)
27311-	}
27312-	return args
27313-}
27314-
27315-// Run configures a server based on the flags, and then runs it.
27316-// It blocks until the server shuts down.
27317-func (s *Serve) Run(ctx context.Context, args ...string) error {
27318-	if len(args) > 0 {
27319-		return tool.CommandLineErrorf("server does not take arguments, got %v", args)
27320-	}
27321-
27322-	di := debug.GetInstance(ctx)
27323-	isDaemon := s.Address != "" || s.Port != 0
27324-	if di != nil {
27325-		closeLog, err := di.SetLogFile(s.Logfile, isDaemon)
27326-		if err != nil {
27327-			return err
27328-		}
27329-		defer closeLog()
27330-		di.ServerAddress = s.Address
27331-		di.MonitorMemory(ctx)
27332-		di.Serve(ctx, s.Debug)
27333-	}
27334-	var ss jsonrpc2.StreamServer
27335-	if s.app.Remote != "" {
27336-		var err error
27337-		ss, err = lsprpc.NewForwarder(s.app.Remote, s.remoteArgs)
27338-		if err != nil {
27339-			return fmt.Errorf("creating forwarder: %w", err)
27340-		}
27341-	} else {
27342-		ss = lsprpc.NewStreamServer(cache.New(nil), isDaemon, s.app.options)
27343-	}
27344-
27345-	var network, addr string
27346-	if s.Address != "" {
27347-		network, addr = lsprpc.ParseAddr(s.Address)
27348-	}
27349-	if s.Port != 0 {
27350-		network = "tcp"
27351-		addr = fmt.Sprintf(":%v", s.Port)
27352-	}
27353-	if addr != "" {
27354-		log.Printf("Gopls daemon: listening on %s network, address %s...", network, addr)
27355-		defer log.Printf("Gopls daemon: exiting")
27356-		return jsonrpc2.ListenAndServe(ctx, network, addr, ss, s.IdleTimeout)
27357-	}
27358-	stream := jsonrpc2.NewHeaderStream(fakenet.NewConn("stdio", os.Stdin, os.Stdout))
27359-	if s.Trace && di != nil {
27360-		stream = protocol.LoggingStream(stream, di.LogWriter)
27361-	}
27362-	conn := jsonrpc2.NewConn(stream)
27363-	err := ss.ServeStream(ctx, conn)
27364-	if errors.Is(err, io.EOF) {
27365-		return nil
27366-	}
27367-	return err
27368-}
27369diff -urN a/gopls/internal/lsp/cmd/signature.go b/gopls/internal/lsp/cmd/signature.go
27370--- a/gopls/internal/lsp/cmd/signature.go	2000-01-01 00:00:00.000000000 -0000
27371+++ b/gopls/internal/lsp/cmd/signature.go	1970-01-01 00:00:00.000000000 +0000
27372@@ -1,88 +0,0 @@
27373-// Copyright 2019 The Go Authors. All rights reserved.
27374-// Use of this source code is governed by a BSD-style
27375-// license that can be found in the LICENSE file.
27376-
27377-package cmd
27378-
27379-import (
27380-	"context"
27381-	"flag"
27382-	"fmt"
27383-
27384-	"golang.org/x/tools/gopls/internal/lsp/protocol"
27385-	"golang.org/x/tools/gopls/internal/span"
27386-	"golang.org/x/tools/internal/tool"
27387-)
27388-
27389-// signature implements the signature verb for gopls
27390-type signature struct {
27391-	app *Application
27392-}
27393-
27394-func (r *signature) Name() string      { return "signature" }
27395-func (r *signature) Parent() string    { return r.app.Name() }
27396-func (r *signature) Usage() string     { return "<position>" }
27397-func (r *signature) ShortHelp() string { return "display selected identifier's signature" }
27398-func (r *signature) DetailedHelp(f *flag.FlagSet) {
27399-	fmt.Fprint(f.Output(), `
27400-Example:
27401-
27402-	$ # 1-indexed location (:line:column or :#offset) of the target identifier
27403-	$ gopls signature helper/helper.go:8:6
27404-	$ gopls signature helper/helper.go:#53
27405-`)
27406-	printFlagDefaults(f)
27407-}
27408-
27409-func (r *signature) Run(ctx context.Context, args ...string) error {
27410-	if len(args) != 1 {
27411-		return tool.CommandLineErrorf("signature expects 1 argument (position)")
27412-	}
27413-
27414-	conn, err := r.app.connect(ctx)
27415-	if err != nil {
27416-		return err
27417-	}
27418-	defer conn.terminate(ctx)
27419-
27420-	from := span.Parse(args[0])
27421-	file := conn.openFile(ctx, from.URI())
27422-	if file.err != nil {
27423-		return file.err
27424-	}
27425-
27426-	loc, err := file.mapper.SpanLocation(from)
27427-	if err != nil {
27428-		return err
27429-	}
27430-
27431-	p := protocol.SignatureHelpParams{
27432-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
27433-	}
27434-
27435-	s, err := conn.SignatureHelp(ctx, &p)
27436-	if err != nil {
27437-		return err
27438-	}
27439-
27440-	if s == nil || len(s.Signatures) == 0 {
27441-		return tool.CommandLineErrorf("%v: not a function", from)
27442-	}
27443-
27444-	// there is only ever one possible signature,
27445-	// see toProtocolSignatureHelp in lsp/signature_help.go
27446-	signature := s.Signatures[0]
27447-	fmt.Printf("%s\n", signature.Label)
27448-	switch x := signature.Documentation.Value.(type) {
27449-	case string:
27450-		if x != "" {
27451-			fmt.Printf("\n%s\n", x)
27452-		}
27453-	case protocol.MarkupContent:
27454-		if x.Value != "" {
27455-			fmt.Printf("\n%s\n", x.Value)
27456-		}
27457-	}
27458-
27459-	return nil
27460-}
27461diff -urN a/gopls/internal/lsp/cmd/subcommands.go b/gopls/internal/lsp/cmd/subcommands.go
27462--- a/gopls/internal/lsp/cmd/subcommands.go	2000-01-01 00:00:00.000000000 -0000
27463+++ b/gopls/internal/lsp/cmd/subcommands.go	1970-01-01 00:00:00.000000000 +0000
27464@@ -1,59 +0,0 @@
27465-// Copyright 2021 The Go Authors. All rights reserved.
27466-// Use of this source code is governed by a BSD-style
27467-// license that can be found in the LICENSE file.
27468-
27469-package cmd
27470-
27471-import (
27472-	"context"
27473-	"flag"
27474-	"fmt"
27475-	"text/tabwriter"
27476-
27477-	"golang.org/x/tools/internal/tool"
27478-)
27479-
27480-// subcommands is a helper that may be embedded for commands that delegate to
27481-// subcommands.
27482-type subcommands []tool.Application
27483-
27484-func (s subcommands) DetailedHelp(f *flag.FlagSet) {
27485-	w := tabwriter.NewWriter(f.Output(), 0, 0, 2, ' ', 0)
27486-	defer w.Flush()
27487-	fmt.Fprint(w, "\nSubcommand:\n")
27488-	for _, c := range s {
27489-		fmt.Fprintf(w, "  %s\t%s\n", c.Name(), c.ShortHelp())
27490-	}
27491-	printFlagDefaults(f)
27492-}
27493-
27494-func (s subcommands) Usage() string { return "<subcommand> [arg]..." }
27495-
27496-func (s subcommands) Run(ctx context.Context, args ...string) error {
27497-	if len(args) == 0 {
27498-		return tool.CommandLineErrorf("must provide subcommand")
27499-	}
27500-	command, args := args[0], args[1:]
27501-	for _, c := range s {
27502-		if c.Name() == command {
27503-			s := flag.NewFlagSet(c.Name(), flag.ExitOnError)
27504-			return tool.Run(ctx, s, c, args)
27505-		}
27506-	}
27507-	return tool.CommandLineErrorf("unknown subcommand %v", command)
27508-}
27509-
27510-func (s subcommands) Commands() []tool.Application { return s }
27511-
27512-// getSubcommands returns the subcommands of a given Application.
27513-func getSubcommands(a tool.Application) []tool.Application {
27514-	// This interface is satisfied both by tool.Applications
27515-	// that embed subcommands, and by *cmd.Application.
27516-	type hasCommands interface {
27517-		Commands() []tool.Application
27518-	}
27519-	if sub, ok := a.(hasCommands); ok {
27520-		return sub.Commands()
27521-	}
27522-	return nil
27523-}
27524diff -urN a/gopls/internal/lsp/cmd/suggested_fix.go b/gopls/internal/lsp/cmd/suggested_fix.go
27525--- a/gopls/internal/lsp/cmd/suggested_fix.go	2000-01-01 00:00:00.000000000 -0000
27526+++ b/gopls/internal/lsp/cmd/suggested_fix.go	1970-01-01 00:00:00.000000000 +0000
27527@@ -1,167 +0,0 @@
27528-// Copyright 2019 The Go Authors. All rights reserved.
27529-// Use of this source code is governed by a BSD-style
27530-// license that can be found in the LICENSE file.
27531-
27532-package cmd
27533-
27534-import (
27535-	"context"
27536-	"flag"
27537-	"fmt"
27538-	"io/ioutil"
27539-	"os"
27540-
27541-	"golang.org/x/tools/gopls/internal/lsp/protocol"
27542-	"golang.org/x/tools/gopls/internal/lsp/source"
27543-	"golang.org/x/tools/gopls/internal/span"
27544-	"golang.org/x/tools/internal/diff"
27545-	"golang.org/x/tools/internal/tool"
27546-)
27547-
27548-// suggestedFix implements the fix verb for gopls.
27549-type suggestedFix struct {
27550-	Diff  bool `flag:"d,diff" help:"display diffs instead of rewriting files"`
27551-	Write bool `flag:"w,write" help:"write result to (source) file instead of stdout"`
27552-	All   bool `flag:"a,all" help:"apply all fixes, not just preferred fixes"`
27553-
27554-	app *Application
27555-}
27556-
27557-func (s *suggestedFix) Name() string      { return "fix" }
27558-func (s *suggestedFix) Parent() string    { return s.app.Name() }
27559-func (s *suggestedFix) Usage() string     { return "[fix-flags] <filename>" }
27560-func (s *suggestedFix) ShortHelp() string { return "apply suggested fixes" }
27561-func (s *suggestedFix) DetailedHelp(f *flag.FlagSet) {
27562-	fmt.Fprintf(f.Output(), `
27563-Example: apply suggested fixes for this file
27564-	$ gopls fix -w internal/lsp/cmd/check.go
27565-
27566-fix-flags:
27567-`)
27568-	printFlagDefaults(f)
27569-}
27570-
27571-// Run performs diagnostic checks on the file specified and either;
27572-// - if -w is specified, updates the file in place;
27573-// - if -d is specified, prints out unified diffs of the changes; or
27574-// - otherwise, prints the new versions to stdout.
27575-func (s *suggestedFix) Run(ctx context.Context, args ...string) error {
27576-	if len(args) < 1 {
27577-		return tool.CommandLineErrorf("fix expects at least 1 argument")
27578-	}
27579-	conn, err := s.app.connect(ctx)
27580-	if err != nil {
27581-		return err
27582-	}
27583-	defer conn.terminate(ctx)
27584-
27585-	from := span.Parse(args[0])
27586-	uri := from.URI()
27587-	file := conn.openFile(ctx, uri)
27588-	if file.err != nil {
27589-		return file.err
27590-	}
27591-
27592-	if err := conn.diagnoseFiles(ctx, []span.URI{uri}); err != nil {
27593-		return err
27594-	}
27595-	conn.Client.filesMu.Lock()
27596-	defer conn.Client.filesMu.Unlock()
27597-
27598-	codeActionKinds := []protocol.CodeActionKind{protocol.QuickFix}
27599-	if len(args) > 1 {
27600-		codeActionKinds = []protocol.CodeActionKind{}
27601-		for _, k := range args[1:] {
27602-			codeActionKinds = append(codeActionKinds, protocol.CodeActionKind(k))
27603-		}
27604-	}
27605-
27606-	rng, err := file.mapper.SpanRange(from)
27607-	if err != nil {
27608-		return err
27609-	}
27610-	p := protocol.CodeActionParams{
27611-		TextDocument: protocol.TextDocumentIdentifier{
27612-			URI: protocol.URIFromSpanURI(uri),
27613-		},
27614-		Context: protocol.CodeActionContext{
27615-			Only:        codeActionKinds,
27616-			Diagnostics: file.diagnostics,
27617-		},
27618-		Range: rng,
27619-	}
27620-	actions, err := conn.CodeAction(ctx, &p)
27621-	if err != nil {
27622-		return fmt.Errorf("%v: %v", from, err)
27623-	}
27624-	var edits []protocol.TextEdit
27625-	for _, a := range actions {
27626-		if a.Command != nil {
27627-			return fmt.Errorf("ExecuteCommand is not yet supported on the command line")
27628-		}
27629-		if !a.IsPreferred && !s.All {
27630-			continue
27631-		}
27632-		if !from.HasPosition() {
27633-			for _, c := range a.Edit.DocumentChanges {
27634-				if c.TextDocumentEdit != nil {
27635-					if fileURI(c.TextDocumentEdit.TextDocument.URI) == uri {
27636-						edits = append(edits, c.TextDocumentEdit.Edits...)
27637-					}
27638-				}
27639-			}
27640-			continue
27641-		}
27642-		// If the span passed in has a position, then we need to find
27643-		// the codeaction that has the same range as the passed in span.
27644-		for _, diag := range a.Diagnostics {
27645-			spn, err := file.mapper.RangeSpan(diag.Range)
27646-			if err != nil {
27647-				continue
27648-			}
27649-			if span.ComparePoint(from.Start(), spn.Start()) == 0 {
27650-				for _, c := range a.Edit.DocumentChanges {
27651-					if c.TextDocumentEdit != nil {
27652-						if fileURI(c.TextDocumentEdit.TextDocument.URI) == uri {
27653-							edits = append(edits, c.TextDocumentEdit.Edits...)
27654-						}
27655-					}
27656-				}
27657-				break
27658-			}
27659-		}
27660-
27661-		// If suggested fix is not a diagnostic, still must collect edits.
27662-		if len(a.Diagnostics) == 0 {
27663-			for _, c := range a.Edit.DocumentChanges {
27664-				if c.TextDocumentEdit != nil {
27665-					if fileURI(c.TextDocumentEdit.TextDocument.URI) == uri {
27666-						edits = append(edits, c.TextDocumentEdit.Edits...)
27667-					}
27668-				}
27669-			}
27670-		}
27671-	}
27672-
27673-	newContent, sedits, err := source.ApplyProtocolEdits(file.mapper, edits)
27674-	if err != nil {
27675-		return fmt.Errorf("%v: %v", edits, err)
27676-	}
27677-
27678-	filename := file.uri.Filename()
27679-	switch {
27680-	case s.Write:
27681-		if len(edits) > 0 {
27682-			ioutil.WriteFile(filename, newContent, 0644)
27683-		}
27684-	case s.Diff:
27685-		diffs, err := diff.ToUnified(filename+".orig", filename, string(file.mapper.Content), sedits)
27686-		if err != nil {
27687-			return err
27688-		}
27689-		fmt.Print(diffs)
27690-	default:
27691-		os.Stdout.Write(newContent)
27692-	}
27693-	return nil
27694-}
27695diff -urN a/gopls/internal/lsp/cmd/symbols.go b/gopls/internal/lsp/cmd/symbols.go
27696--- a/gopls/internal/lsp/cmd/symbols.go	2000-01-01 00:00:00.000000000 -0000
27697+++ b/gopls/internal/lsp/cmd/symbols.go	1970-01-01 00:00:00.000000000 +0000
27698@@ -1,116 +0,0 @@
27699-// Copyright 2019 The Go Authors. All rights reserved.
27700-// Use of this source code is governed by a BSD-style
27701-// license that can be found in the LICENSE file.
27702-
27703-package cmd
27704-
27705-import (
27706-	"context"
27707-	"encoding/json"
27708-	"flag"
27709-	"fmt"
27710-	"sort"
27711-
27712-	"golang.org/x/tools/gopls/internal/lsp/protocol"
27713-	"golang.org/x/tools/gopls/internal/span"
27714-	"golang.org/x/tools/internal/tool"
27715-)
27716-
27717-// symbols implements the symbols verb for gopls
27718-type symbols struct {
27719-	app *Application
27720-}
27721-
27722-func (r *symbols) Name() string      { return "symbols" }
27723-func (r *symbols) Parent() string    { return r.app.Name() }
27724-func (r *symbols) Usage() string     { return "<file>" }
27725-func (r *symbols) ShortHelp() string { return "display selected file's symbols" }
27726-func (r *symbols) DetailedHelp(f *flag.FlagSet) {
27727-	fmt.Fprint(f.Output(), `
27728-Example:
27729-	$ gopls symbols helper/helper.go
27730-`)
27731-	printFlagDefaults(f)
27732-}
27733-func (r *symbols) Run(ctx context.Context, args ...string) error {
27734-	if len(args) != 1 {
27735-		return tool.CommandLineErrorf("symbols expects 1 argument (position)")
27736-	}
27737-
27738-	conn, err := r.app.connect(ctx)
27739-	if err != nil {
27740-		return err
27741-	}
27742-	defer conn.terminate(ctx)
27743-
27744-	from := span.Parse(args[0])
27745-	p := protocol.DocumentSymbolParams{
27746-		TextDocument: protocol.TextDocumentIdentifier{
27747-			URI: protocol.URIFromSpanURI(from.URI()),
27748-		},
27749-	}
27750-	symbols, err := conn.DocumentSymbol(ctx, &p)
27751-	if err != nil {
27752-		return err
27753-	}
27754-	for _, s := range symbols {
27755-		if m, ok := s.(map[string]interface{}); ok {
27756-			s, err = mapToSymbol(m)
27757-			if err != nil {
27758-				return err
27759-			}
27760-		}
27761-		switch t := s.(type) {
27762-		case protocol.DocumentSymbol:
27763-			printDocumentSymbol(t)
27764-		case protocol.SymbolInformation:
27765-			printSymbolInformation(t)
27766-		}
27767-	}
27768-	return nil
27769-}
27770-
27771-func mapToSymbol(m map[string]interface{}) (interface{}, error) {
27772-	b, err := json.Marshal(m)
27773-	if err != nil {
27774-		return nil, err
27775-	}
27776-
27777-	if _, ok := m["selectionRange"]; ok {
27778-		var s protocol.DocumentSymbol
27779-		if err := json.Unmarshal(b, &s); err != nil {
27780-			return nil, err
27781-		}
27782-		return s, nil
27783-	}
27784-
27785-	var s protocol.SymbolInformation
27786-	if err := json.Unmarshal(b, &s); err != nil {
27787-		return nil, err
27788-	}
27789-	return s, nil
27790-}
27791-
27792-func printDocumentSymbol(s protocol.DocumentSymbol) {
27793-	fmt.Printf("%s %s %s\n", s.Name, s.Kind, positionToString(s.SelectionRange))
27794-	// Sort children for consistency
27795-	sort.Slice(s.Children, func(i, j int) bool {
27796-		return s.Children[i].Name < s.Children[j].Name
27797-	})
27798-	for _, c := range s.Children {
27799-		fmt.Printf("\t%s %s %s\n", c.Name, c.Kind, positionToString(c.SelectionRange))
27800-	}
27801-}
27802-
27803-func printSymbolInformation(s protocol.SymbolInformation) {
27804-	fmt.Printf("%s %s %s\n", s.Name, s.Kind, positionToString(s.Location.Range))
27805-}
27806-
27807-func positionToString(r protocol.Range) string {
27808-	return fmt.Sprintf("%v:%v-%v:%v",
27809-		r.Start.Line+1,
27810-		r.Start.Character+1,
27811-		r.End.Line+1,
27812-		r.End.Character+1,
27813-	)
27814-}
27815diff -urN a/gopls/internal/lsp/cmd/test/cmdtest.go b/gopls/internal/lsp/cmd/test/cmdtest.go
27816--- a/gopls/internal/lsp/cmd/test/cmdtest.go	2000-01-01 00:00:00.000000000 -0000
27817+++ b/gopls/internal/lsp/cmd/test/cmdtest.go	1970-01-01 00:00:00.000000000 +0000
27818@@ -1,6 +0,0 @@
27819-// Copyright 2023 The Go Authors. All rights reserved.
27820-// Use of this source code is governed by a BSD-style
27821-// license that can be found in the LICENSE file.
27822-
27823-// Package cmdtest contains the test suite for the command line behavior of gopls.
27824-package cmdtest
27825diff -urN a/gopls/internal/lsp/cmd/test/integration_test.go b/gopls/internal/lsp/cmd/test/integration_test.go
27826--- a/gopls/internal/lsp/cmd/test/integration_test.go	2000-01-01 00:00:00.000000000 -0000
27827+++ b/gopls/internal/lsp/cmd/test/integration_test.go	1970-01-01 00:00:00.000000000 +0000
27828@@ -1,898 +0,0 @@
27829-// Copyright 2023 The Go Authors. All rights reserved.
27830-// Use of this source code is governed by a BSD-style
27831-// license that can be found in the LICENSE file.
27832-package cmdtest
27833-
27834-// This file defines integration tests of each gopls subcommand that
27835-// fork+exec the command in a separate process.
27836-//
27837-// (Rather than execute 'go build gopls' during the test, we reproduce
27838-// the main entrypoint in the test executable.)
27839-//
27840-// The purpose of this test is to exercise client-side logic such as
27841-// argument parsing and formatting of LSP RPC responses, not server
27842-// behavior; see lsp_test for that.
27843-//
27844-// All tests run in parallel.
27845-//
27846-// TODO(adonovan):
27847-// - Use markers to represent positions in the input and in assertions.
27848-// - Coverage of cross-cutting things like cwd, enviro, span parsing, etc.
27849-// - Subcommands that accept -write and -diff flags should implement
27850-//   them consistently wrt the default behavior; factor their tests.
27851-// - Add missing test for 'vulncheck' subcommand.
27852-// - Add tests for client-only commands: serve, bug, help, api-json, licenses.
27853-
27854-import (
27855-	"bytes"
27856-	"context"
27857-	"encoding/json"
27858-	"fmt"
27859-	"os"
27860-	"path/filepath"
27861-	"regexp"
27862-	"strings"
27863-	"testing"
27864-
27865-	exec "golang.org/x/sys/execabs"
27866-	"golang.org/x/tools/gopls/internal/hooks"
27867-	"golang.org/x/tools/gopls/internal/lsp/cmd"
27868-	"golang.org/x/tools/gopls/internal/lsp/debug"
27869-	"golang.org/x/tools/gopls/internal/lsp/protocol"
27870-	"golang.org/x/tools/internal/bug"
27871-	"golang.org/x/tools/internal/testenv"
27872-	"golang.org/x/tools/internal/tool"
27873-	"golang.org/x/tools/txtar"
27874-)
27875-
27876-// TestVersion tests the 'version' subcommand (../info.go).
27877-func TestVersion(t *testing.T) {
27878-	t.Parallel()
27879-
27880-	tree := writeTree(t, "")
27881-
27882-	// There's not much we can robustly assert about the actual version.
27883-	const want = debug.Version // e.g. "master"
27884-
27885-	// basic
27886-	{
27887-		res := gopls(t, tree, "version")
27888-		res.checkExit(true)
27889-		res.checkStdout(want)
27890-	}
27891-
27892-	// -json flag
27893-	{
27894-		res := gopls(t, tree, "version", "-json")
27895-		res.checkExit(true)
27896-		var v debug.ServerVersion
27897-		if res.toJSON(&v) {
27898-			if v.Version != want {
27899-				t.Errorf("expected Version %q, got %q (%v)", want, v.Version, res)
27900-			}
27901-		}
27902-	}
27903-}
27904-
27905-// TestCheck tests the 'check' subcommand (../check.go).
27906-func TestCheck(t *testing.T) {
27907-	t.Parallel()
27908-
27909-	tree := writeTree(t, `
27910--- go.mod --
27911-module example.com
27912-go 1.18
27913-
27914--- a.go --
27915-package a
27916-import "fmt"
27917-var _ = fmt.Sprintf("%s", 123)
27918-
27919--- b.go --
27920-package a
27921-import "fmt"
27922-var _ = fmt.Sprintf("%d", "123")
27923-`)
27924-
27925-	// no files
27926-	{
27927-		res := gopls(t, tree, "check")
27928-		res.checkExit(true)
27929-		if res.stdout != "" {
27930-			t.Errorf("unexpected output: %v", res)
27931-		}
27932-	}
27933-
27934-	// one file
27935-	{
27936-		res := gopls(t, tree, "check", "./a.go")
27937-		res.checkExit(true)
27938-		res.checkStdout("fmt.Sprintf format %s has arg 123 of wrong type int")
27939-	}
27940-
27941-	// two files
27942-	{
27943-		res := gopls(t, tree, "check", "./a.go", "./b.go")
27944-		res.checkExit(true)
27945-		res.checkStdout(`a.go:.* fmt.Sprintf format %s has arg 123 of wrong type int`)
27946-		res.checkStdout(`b.go:.* fmt.Sprintf format %d has arg "123" of wrong type string`)
27947-	}
27948-}
27949-
27950-// TestCallHierarchy tests the 'call_hierarchy' subcommand (../call_hierarchy.go).
27951-func TestCallHierarchy(t *testing.T) {
27952-	t.Parallel()
27953-
27954-	tree := writeTree(t, `
27955--- go.mod --
27956-module example.com
27957-go 1.18
27958-
27959--- a.go --
27960-package a
27961-func f() {}
27962-func g() {
27963-	f()
27964-}
27965-func h() {
27966-	f()
27967-	f()
27968-}
27969-`)
27970-	// missing position
27971-	{
27972-		res := gopls(t, tree, "call_hierarchy")
27973-		res.checkExit(false)
27974-		res.checkStderr("expects 1 argument")
27975-	}
27976-	// wrong place
27977-	{
27978-		res := gopls(t, tree, "call_hierarchy", "a.go:1")
27979-		res.checkExit(false)
27980-		res.checkStderr("identifier not found")
27981-	}
27982-	// f is called once from g and twice from h.
27983-	{
27984-		res := gopls(t, tree, "call_hierarchy", "a.go:2:6")
27985-		res.checkExit(true)
27986-		// We use regexp '.' as an OS-agnostic path separator.
27987-		res.checkStdout("ranges 7:2-3, 8:2-3 in ..a.go from/to function h in ..a.go:6:6-7")
27988-		res.checkStdout("ranges 4:2-3 in ..a.go from/to function g in ..a.go:3:6-7")
27989-		res.checkStdout("identifier: function f in ..a.go:2:6-7")
27990-	}
27991-}
27992-
27993-// TestDefinition tests the 'definition' subcommand (../definition.go).
27994-func TestDefinition(t *testing.T) {
27995-	t.Parallel()
27996-
27997-	tree := writeTree(t, `
27998--- go.mod --
27999-module example.com
28000-go 1.18
28001-
28002--- a.go --
28003-package a
28004-import "fmt"
28005-func f() {
28006-	fmt.Println()
28007-}
28008-func g() {
28009-	f()
28010-}
28011-`)
28012-	// missing position
28013-	{
28014-		res := gopls(t, tree, "definition")
28015-		res.checkExit(false)
28016-		res.checkStderr("expects 1 argument")
28017-	}
28018-	// intra-package
28019-	{
28020-		res := gopls(t, tree, "definition", "a.go:7:2") // "f()"
28021-		res.checkExit(true)
28022-		res.checkStdout("a.go:3:6-7: defined here as func f")
28023-	}
28024-	// cross-package
28025-	{
28026-		res := gopls(t, tree, "definition", "a.go:4:7") // "Println"
28027-		res.checkExit(true)
28028-		res.checkStdout("print.go.* defined here as func fmt.Println")
28029-		res.checkStdout("Println formats using the default formats for its operands")
28030-	}
28031-	// -json and -markdown
28032-	{
28033-		res := gopls(t, tree, "definition", "-json", "-markdown", "a.go:4:7")
28034-		res.checkExit(true)
28035-		var defn cmd.Definition
28036-		if res.toJSON(&defn) {
28037-			if !strings.HasPrefix(defn.Description, "```go\nfunc fmt.Println") {
28038-				t.Errorf("Description does not start with markdown code block. Got: %s", defn.Description)
28039-			}
28040-		}
28041-	}
28042-}
28043-
28044-// TestFoldingRanges tests the 'folding_ranges' subcommand (../folding_range.go).
28045-func TestFoldingRanges(t *testing.T) {
28046-	t.Parallel()
28047-
28048-	tree := writeTree(t, `
28049--- go.mod --
28050-module example.com
28051-go 1.18
28052-
28053--- a.go --
28054-package a
28055-func f(x int) {
28056-	// hello
28057-}
28058-`)
28059-	// missing filename
28060-	{
28061-		res := gopls(t, tree, "folding_ranges")
28062-		res.checkExit(false)
28063-		res.checkStderr("expects 1 argument")
28064-	}
28065-	// success
28066-	{
28067-		res := gopls(t, tree, "folding_ranges", "a.go")
28068-		res.checkExit(true)
28069-		res.checkStdout("2:8-2:13") // params (x int)
28070-		res.checkStdout("2:16-4:1") //   body { ... }
28071-	}
28072-}
28073-
28074-// TestFormat tests the 'format' subcommand (../format.go).
28075-func TestFormat(t *testing.T) {
28076-	t.Parallel()
28077-
28078-	tree := writeTree(t, `
28079--- a.go --
28080-package a ;  func f ( ) { }
28081-`)
28082-	const want = `package a
28083-
28084-func f() {}
28085-`
28086-
28087-	// no files => nop
28088-	{
28089-		res := gopls(t, tree, "format")
28090-		res.checkExit(true)
28091-	}
28092-	// default => print formatted result
28093-	{
28094-		res := gopls(t, tree, "format", "a.go")
28095-		res.checkExit(true)
28096-		if res.stdout != want {
28097-			t.Errorf("format: got <<%s>>, want <<%s>>", res.stdout, want)
28098-		}
28099-	}
28100-	// start/end position not supported (unless equal to start/end of file)
28101-	{
28102-		res := gopls(t, tree, "format", "a.go:1-2")
28103-		res.checkExit(false)
28104-		res.checkStderr("only full file formatting supported")
28105-	}
28106-	// -list: show only file names
28107-	{
28108-		res := gopls(t, tree, "format", "-list", "a.go")
28109-		res.checkExit(true)
28110-		res.checkStdout("a.go")
28111-	}
28112-	// -diff prints a unified diff
28113-	{
28114-		res := gopls(t, tree, "format", "-diff", "a.go")
28115-		res.checkExit(true)
28116-		// We omit the filenames as they vary by OS.
28117-		want := `
28118--package a ;  func f ( ) { }
28119-+package a
28120-+
28121-+func f() {}
28122-`
28123-		res.checkStdout(regexp.QuoteMeta(want))
28124-	}
28125-	// -write updates the file
28126-	{
28127-		res := gopls(t, tree, "format", "-write", "a.go")
28128-		res.checkExit(true)
28129-		res.checkStdout("^$") // empty
28130-		checkContent(t, filepath.Join(tree, "a.go"), want)
28131-	}
28132-}
28133-
28134-// TestHighlight tests the 'highlight' subcommand (../highlight.go).
28135-func TestHighlight(t *testing.T) {
28136-	t.Parallel()
28137-
28138-	tree := writeTree(t, `
28139--- a.go --
28140-package a
28141-import "fmt"
28142-func f() {
28143-	fmt.Println()
28144-	fmt.Println()
28145-}
28146-`)
28147-
28148-	// no arguments
28149-	{
28150-		res := gopls(t, tree, "highlight")
28151-		res.checkExit(false)
28152-		res.checkStderr("expects 1 argument")
28153-	}
28154-	// all occurrences of Println
28155-	{
28156-		res := gopls(t, tree, "highlight", "a.go:4:7")
28157-		res.checkExit(true)
28158-		res.checkStdout("a.go:4:6-13")
28159-		res.checkStdout("a.go:5:6-13")
28160-	}
28161-}
28162-
28163-// TestImplementations tests the 'implementation' subcommand (../implementation.go).
28164-func TestImplementations(t *testing.T) {
28165-	t.Parallel()
28166-
28167-	tree := writeTree(t, `
28168--- a.go --
28169-package a
28170-import "fmt"
28171-type T int
28172-func (T) String() string { return "" }
28173-`)
28174-
28175-	// no arguments
28176-	{
28177-		res := gopls(t, tree, "implementation")
28178-		res.checkExit(false)
28179-		res.checkStderr("expects 1 argument")
28180-	}
28181-	// T.String
28182-	{
28183-		res := gopls(t, tree, "implementation", "a.go:4:10")
28184-		res.checkExit(true)
28185-		// TODO(adonovan): extract and check the content of the reported ranges?
28186-		// We use regexp '.' as an OS-agnostic path separator.
28187-		res.checkStdout("fmt.print.go:")     // fmt.Stringer.String
28188-		res.checkStdout("runtime.error.go:") // runtime.stringer.String
28189-	}
28190-}
28191-
28192-// TestImports tests the 'imports' subcommand (../imports.go).
28193-func TestImports(t *testing.T) {
28194-	t.Parallel()
28195-
28196-	tree := writeTree(t, `
28197--- a.go --
28198-package a
28199-func _() {
28200-	fmt.Println()
28201-}
28202-`)
28203-
28204-	want := `
28205-package a
28206-
28207-import "fmt"
28208-func _() {
28209-	fmt.Println()
28210-}
28211-`[1:]
28212-
28213-	// no arguments
28214-	{
28215-		res := gopls(t, tree, "imports")
28216-		res.checkExit(false)
28217-		res.checkStderr("expects 1 argument")
28218-	}
28219-	// default: print with imports
28220-	{
28221-		res := gopls(t, tree, "imports", "a.go")
28222-		res.checkExit(true)
28223-		if res.stdout != want {
28224-			t.Errorf("format: got <<%s>>, want <<%s>>", res.stdout, want)
28225-		}
28226-	}
28227-	// -diff: show a unified diff
28228-	{
28229-		res := gopls(t, tree, "imports", "-diff", "a.go")
28230-		res.checkExit(true)
28231-		res.checkStdout(regexp.QuoteMeta(`+import "fmt"`))
28232-	}
28233-	// -write: update file
28234-	{
28235-		res := gopls(t, tree, "imports", "-write", "a.go")
28236-		res.checkExit(true)
28237-		checkContent(t, filepath.Join(tree, "a.go"), want)
28238-	}
28239-}
28240-
28241-// TestLinks tests the 'links' subcommand (../links.go).
28242-func TestLinks(t *testing.T) {
28243-	t.Parallel()
28244-
28245-	tree := writeTree(t, `
28246--- a.go --
28247-// Link in package doc: https://pkg.go.dev/
28248-package a
28249-
28250-// Link in internal comment: https://go.dev/cl
28251-
28252-// Doc comment link: https://blog.go.dev/
28253-func f() {}
28254-`)
28255-	// no arguments
28256-	{
28257-		res := gopls(t, tree, "links")
28258-		res.checkExit(false)
28259-		res.checkStderr("expects 1 argument")
28260-	}
28261-	// success
28262-	{
28263-		res := gopls(t, tree, "links", "a.go")
28264-		res.checkExit(true)
28265-		res.checkStdout("https://go.dev/cl")
28266-		res.checkStdout("https://pkg.go.dev")
28267-		res.checkStdout("https://blog.go.dev/")
28268-	}
28269-	// -json
28270-	{
28271-		res := gopls(t, tree, "links", "-json", "a.go")
28272-		res.checkExit(true)
28273-		res.checkStdout("https://pkg.go.dev")
28274-		res.checkStdout("https://go.dev/cl")
28275-		res.checkStdout("https://blog.go.dev/") // at 5:21-5:41
28276-		var links []protocol.DocumentLink
28277-		if res.toJSON(&links) {
28278-			// Check just one of the three locations.
28279-			if got, want := fmt.Sprint(links[2].Range), "5:21-5:41"; got != want {
28280-				t.Errorf("wrong link location: got %v, want %v", got, want)
28281-			}
28282-		}
28283-	}
28284-}
28285-
28286-// TestReferences tests the 'references' subcommand (../references.go).
28287-func TestReferences(t *testing.T) {
28288-	t.Parallel()
28289-
28290-	tree := writeTree(t, `
28291--- go.mod --
28292-module example.com
28293-go 1.18
28294-
28295--- a.go --
28296-package a
28297-import "fmt"
28298-func f() {
28299-	fmt.Println()
28300-}
28301-
28302--- b.go --
28303-package a
28304-import "fmt"
28305-func g() {
28306-	fmt.Println()
28307-}
28308-`)
28309-	// no arguments
28310-	{
28311-		res := gopls(t, tree, "references")
28312-		res.checkExit(false)
28313-		res.checkStderr("expects 1 argument")
28314-	}
28315-	// fmt.Println
28316-	{
28317-		res := gopls(t, tree, "references", "a.go:4:10")
28318-		res.checkExit(true)
28319-		res.checkStdout("a.go:4:6-13")
28320-		res.checkStdout("b.go:4:6-13")
28321-	}
28322-}
28323-
28324-// TestSignature tests the 'signature' subcommand (../signature.go).
28325-func TestSignature(t *testing.T) {
28326-	t.Parallel()
28327-
28328-	tree := writeTree(t, `
28329--- go.mod --
28330-module example.com
28331-go 1.18
28332-
28333--- a.go --
28334-package a
28335-import "fmt"
28336-func f() {
28337-	fmt.Println(123)
28338-}
28339-`)
28340-	// no arguments
28341-	{
28342-		res := gopls(t, tree, "signature")
28343-		res.checkExit(false)
28344-		res.checkStderr("expects 1 argument")
28345-	}
28346-	// at 123 inside fmt.Println() call
28347-	{
28348-		res := gopls(t, tree, "signature", "a.go:4:15")
28349-		res.checkExit(true)
28350-		res.checkStdout("Println\\(a ...")
28351-		res.checkStdout("Println formats using the default formats...")
28352-	}
28353-}
28354-
28355-// TestPrepareRename tests the 'prepare_rename' subcommand (../prepare_rename.go).
28356-func TestPrepareRename(t *testing.T) {
28357-	t.Parallel()
28358-
28359-	tree := writeTree(t, `
28360--- go.mod --
28361-module example.com
28362-go 1.18
28363-
28364--- a.go --
28365-package a
28366-func oldname() {}
28367-`)
28368-	// no arguments
28369-	{
28370-		res := gopls(t, tree, "prepare_rename")
28371-		res.checkExit(false)
28372-		res.checkStderr("expects 1 argument")
28373-	}
28374-	// in 'package' keyword
28375-	{
28376-		res := gopls(t, tree, "prepare_rename", "a.go:1:3")
28377-		res.checkExit(false)
28378-		res.checkStderr("request is not valid at the given position")
28379-	}
28380-	// in 'package' identifier (not supported by client)
28381-	{
28382-		res := gopls(t, tree, "prepare_rename", "a.go:1:9")
28383-		res.checkExit(false)
28384-		res.checkStderr("can't rename package")
28385-	}
28386-	// in func oldname
28387-	{
28388-		res := gopls(t, tree, "prepare_rename", "a.go:2:9")
28389-		res.checkExit(true)
28390-		res.checkStdout("a.go:2:6-13") // all of "oldname"
28391-	}
28392-}
28393-
28394-// TestRename tests the 'rename' subcommand (../rename.go).
28395-func TestRename(t *testing.T) {
28396-	t.Parallel()
28397-
28398-	tree := writeTree(t, `
28399--- go.mod --
28400-module example.com
28401-go 1.18
28402-
28403--- a.go --
28404-package a
28405-func oldname() {}
28406-`)
28407-	// no arguments
28408-	{
28409-		res := gopls(t, tree, "rename")
28410-		res.checkExit(false)
28411-		res.checkStderr("expects 2 arguments")
28412-	}
28413-	// missing newname
28414-	{
28415-		res := gopls(t, tree, "rename", "a.go:1:3")
28416-		res.checkExit(false)
28417-		res.checkStderr("expects 2 arguments")
28418-	}
28419-	// in 'package' keyword
28420-	{
28421-		res := gopls(t, tree, "rename", "a.go:1:3", "newname")
28422-		res.checkExit(false)
28423-		res.checkStderr("no identifier found")
28424-	}
28425-	// in 'package' identifier
28426-	{
28427-		res := gopls(t, tree, "rename", "a.go:1:9", "newname")
28428-		res.checkExit(false)
28429-		res.checkStderr(`cannot rename package: module path .* same as the package path, so .* no effect`)
28430-	}
28431-	// success, func oldname (and -diff)
28432-	{
28433-		res := gopls(t, tree, "rename", "-diff", "a.go:2:9", "newname")
28434-		res.checkExit(true)
28435-		res.checkStdout(regexp.QuoteMeta("-func oldname() {}"))
28436-		res.checkStdout(regexp.QuoteMeta("+func newname() {}"))
28437-	}
28438-}
28439-
28440-// TestSymbols tests the 'symbols' subcommand (../symbols.go).
28441-func TestSymbols(t *testing.T) {
28442-	t.Parallel()
28443-
28444-	tree := writeTree(t, `
28445--- go.mod --
28446-module example.com
28447-go 1.18
28448-
28449--- a.go --
28450-package a
28451-func f()
28452-var v int
28453-const c = 0
28454-`)
28455-	// no files
28456-	{
28457-		res := gopls(t, tree, "symbols")
28458-		res.checkExit(false)
28459-		res.checkStderr("expects 1 argument")
28460-	}
28461-	// success
28462-	{
28463-		res := gopls(t, tree, "symbols", "a.go:123:456") // (line/col ignored)
28464-		res.checkExit(true)
28465-		res.checkStdout("f Function 2:6-2:7")
28466-		res.checkStdout("v Variable 3:5-3:6")
28467-		res.checkStdout("c Constant 4:7-4:8")
28468-	}
28469-}
28470-
28471-// TestSemtok tests the 'semtok' subcommand (../semantictokens.go).
28472-func TestSemtok(t *testing.T) {
28473-	t.Parallel()
28474-
28475-	tree := writeTree(t, `
28476--- go.mod --
28477-module example.com
28478-go 1.18
28479-
28480--- a.go --
28481-package a
28482-func f()
28483-var v int
28484-const c = 0
28485-`)
28486-	// no files
28487-	{
28488-		res := gopls(t, tree, "semtok")
28489-		res.checkExit(false)
28490-		res.checkStderr("expected one file name")
28491-	}
28492-	// success
28493-	{
28494-		res := gopls(t, tree, "semtok", "a.go")
28495-		res.checkExit(true)
28496-		got := res.stdout
28497-		want := `
28498-/*⇒7,keyword,[]*/package /*⇒1,namespace,[]*/a
28499-/*⇒4,keyword,[]*/func /*⇒1,function,[definition]*/f()
28500-/*⇒3,keyword,[]*/var /*⇒1,variable,[definition]*/v /*⇒3,type,[defaultLibrary]*/int
28501-/*⇒5,keyword,[]*/const /*⇒1,variable,[definition readonly]*/c = /*⇒1,number,[]*/0
28502-`[1:]
28503-		if got != want {
28504-			t.Errorf("semtok: got <<%s>>, want <<%s>>", got, want)
28505-		}
28506-	}
28507-}
28508-
28509-// TestFix tests the 'fix' subcommand (../suggested_fix.go).
28510-func TestFix(t *testing.T) {
28511-	t.Parallel()
28512-
28513-	tree := writeTree(t, `
28514--- go.mod --
28515-module example.com
28516-go 1.18
28517-
28518--- a.go --
28519-package a
28520-var _ error = T(0)
28521-type T int
28522-func f() (int, string) { return }
28523-`)
28524-	want := `
28525-package a
28526-var _ error = T(0)
28527-type T int
28528-func f() (int, string) { return 0, "" }
28529-`[1:]
28530-
28531-	// no arguments
28532-	{
28533-		res := gopls(t, tree, "fix")
28534-		res.checkExit(false)
28535-		res.checkStderr("expects at least 1 argument")
28536-	}
28537-	// success (-a enables fillreturns)
28538-	{
28539-		res := gopls(t, tree, "fix", "-a", "a.go")
28540-		res.checkExit(true)
28541-		got := res.stdout
28542-		if got != want {
28543-			t.Errorf("fix: got <<%s>>, want <<%s>>", got, want)
28544-		}
28545-	}
28546-	// TODO(adonovan): more tests:
28547-	// - -write, -diff: factor with imports, format, rename.
28548-	// - without -all flag
28549-	// - args[2:] is an optional list of protocol.CodeActionKind enum values.
28550-	// - a span argument with a range causes filtering.
28551-}
28552-
28553-// TestWorkspaceSymbol tests the 'workspace_symbol' subcommand (../workspace_symbol.go).
28554-func TestWorkspaceSymbol(t *testing.T) {
28555-	t.Parallel()
28556-
28557-	tree := writeTree(t, `
28558--- go.mod --
28559-module example.com
28560-go 1.18
28561-
28562--- a.go --
28563-package a
28564-func someFunctionName()
28565-`)
28566-	// no files
28567-	{
28568-		res := gopls(t, tree, "workspace_symbol")
28569-		res.checkExit(false)
28570-		res.checkStderr("expects 1 argument")
28571-	}
28572-	// success
28573-	{
28574-		res := gopls(t, tree, "workspace_symbol", "meFun")
28575-		res.checkExit(true)
28576-		res.checkStdout("a.go:2:6-22 someFunctionName Function")
28577-	}
28578-}
28579-
28580-// -- test framework --
28581-
28582-func TestMain(m *testing.M) {
28583-	switch os.Getenv("ENTRYPOINT") {
28584-	case "goplsMain":
28585-		goplsMain()
28586-	default:
28587-		os.Exit(m.Run())
28588-	}
28589-}
28590-
28591-// This function is a stand-in for gopls.main in ../../../../main.go.
28592-func goplsMain() {
28593-	bug.PanicOnBugs = true // (not in the production command)
28594-	tool.Main(context.Background(), cmd.New("gopls", "", nil, hooks.Options), os.Args[1:])
28595-}
28596-
28597-// writeTree extracts a txtar archive into a new directory and returns its path.
28598-func writeTree(t *testing.T, archive string) string {
28599-	root := t.TempDir()
28600-
28601-	// This unfortunate step is required because gopls output
28602-	// expands symbolic links it its input file names (arguably it
28603-	// should not), and on macOS the temp dir is in /var -> private/var.
28604-	root, err := filepath.EvalSymlinks(root)
28605-	if err != nil {
28606-		t.Fatal(err)
28607-	}
28608-
28609-	for _, f := range txtar.Parse([]byte(archive)).Files {
28610-		filename := filepath.Join(root, f.Name)
28611-		if err := os.MkdirAll(filepath.Dir(filename), 0777); err != nil {
28612-			t.Fatal(err)
28613-		}
28614-		if err := os.WriteFile(filename, f.Data, 0666); err != nil {
28615-			t.Fatal(err)
28616-		}
28617-	}
28618-	return root
28619-}
28620-
28621-// gopls executes gopls in a child process.
28622-func gopls(t *testing.T, dir string, args ...string) *result {
28623-	testenv.NeedsTool(t, "go")
28624-
28625-	// Catch inadvertent use of dir=".", which would make
28626-	// the ReplaceAll below unpredictable.
28627-	if !filepath.IsAbs(dir) {
28628-		t.Fatalf("dir is not absolute: %s", dir)
28629-	}
28630-
28631-	cmd := exec.Command(os.Args[0], args...)
28632-	cmd.Env = append(os.Environ(), "ENTRYPOINT=goplsMain")
28633-	cmd.Dir = dir
28634-	cmd.Stdout = new(bytes.Buffer)
28635-	cmd.Stderr = new(bytes.Buffer)
28636-
28637-	cmdErr := cmd.Run()
28638-
28639-	stdout := strings.ReplaceAll(fmt.Sprint(cmd.Stdout), dir, ".")
28640-	stderr := strings.ReplaceAll(fmt.Sprint(cmd.Stderr), dir, ".")
28641-	exitcode := 0
28642-	if cmdErr != nil {
28643-		if exitErr, ok := cmdErr.(*exec.ExitError); ok {
28644-			exitcode = exitErr.ExitCode()
28645-		} else {
28646-			stderr = cmdErr.Error() // (execve failure)
28647-			exitcode = -1
28648-		}
28649-	}
28650-	res := &result{
28651-		t:        t,
28652-		command:  "gopls " + strings.Join(args, " "),
28653-		exitcode: exitcode,
28654-		stdout:   stdout,
28655-		stderr:   stderr,
28656-	}
28657-	if false {
28658-		t.Log(res)
28659-	}
28660-	return res
28661-}
28662-
28663-// A result holds the result of a gopls invocation, and provides assertion helpers.
28664-type result struct {
28665-	t              *testing.T
28666-	command        string
28667-	exitcode       int
28668-	stdout, stderr string
28669-}
28670-
28671-func (res *result) String() string {
28672-	return fmt.Sprintf("%s: exit=%d stdout=<<%s>> stderr=<<%s>>",
28673-		res.command, res.exitcode, res.stdout, res.stderr)
28674-}
28675-
28676-// checkExit asserts that gopls returned the expected exit code.
28677-func (res *result) checkExit(success bool) {
28678-	res.t.Helper()
28679-	if (res.exitcode == 0) != success {
28680-		res.t.Errorf("%s: exited with code %d, want success: %t (%s)",
28681-			res.command, res.exitcode, success, res)
28682-	}
28683-}
28684-
28685-// checkStdout asserts that the gopls standard output matches the pattern.
28686-func (res *result) checkStdout(pattern string) {
28687-	res.t.Helper()
28688-	res.checkOutput(pattern, "stdout", res.stdout)
28689-}
28690-
28691-// checkStderr asserts that the gopls standard error matches the pattern.
28692-func (res *result) checkStderr(pattern string) {
28693-	res.t.Helper()
28694-	res.checkOutput(pattern, "stderr", res.stderr)
28695-}
28696-
28697-func (res *result) checkOutput(pattern, name, content string) {
28698-	res.t.Helper()
28699-	if match, err := regexp.MatchString(pattern, content); err != nil {
28700-		res.t.Errorf("invalid regexp: %v", err)
28701-	} else if !match {
28702-		res.t.Errorf("%s: %s does not match [%s]; got <<%s>>",
28703-			res.command, name, pattern, content)
28704-	}
28705-}
28706-
28707-// toJSON decodes res.stdout as JSON into to *ptr and reports its success.
28708-func (res *result) toJSON(ptr interface{}) bool {
28709-	if err := json.Unmarshal([]byte(res.stdout), ptr); err != nil {
28710-		res.t.Errorf("invalid JSON %v", err)
28711-		return false
28712-	}
28713-	return true
28714-}
28715-
28716-// checkContent checks that the contents of the file are as expected.
28717-func checkContent(t *testing.T, filename, want string) {
28718-	data, err := os.ReadFile(filename)
28719-	if err != nil {
28720-		t.Error(err)
28721-		return
28722-	}
28723-	if got := string(data); got != want {
28724-		t.Errorf("content of %s is <<%s>>, want <<%s>>", filename, got, want)
28725-	}
28726-}
28727diff -urN a/gopls/internal/lsp/cmd/usage/api-json.hlp b/gopls/internal/lsp/cmd/usage/api-json.hlp
28728--- a/gopls/internal/lsp/cmd/usage/api-json.hlp	2000-01-01 00:00:00.000000000 -0000
28729+++ b/gopls/internal/lsp/cmd/usage/api-json.hlp	1970-01-01 00:00:00.000000000 +0000
28730@@ -1,4 +0,0 @@
28731-print json describing gopls API
28732-
28733-Usage:
28734-  gopls [flags] api-json
28735diff -urN a/gopls/internal/lsp/cmd/usage/bug.hlp b/gopls/internal/lsp/cmd/usage/bug.hlp
28736--- a/gopls/internal/lsp/cmd/usage/bug.hlp	2000-01-01 00:00:00.000000000 -0000
28737+++ b/gopls/internal/lsp/cmd/usage/bug.hlp	1970-01-01 00:00:00.000000000 +0000
28738@@ -1,4 +0,0 @@
28739-report a bug in gopls
28740-
28741-Usage:
28742-  gopls [flags] bug
28743diff -urN a/gopls/internal/lsp/cmd/usage/call_hierarchy.hlp b/gopls/internal/lsp/cmd/usage/call_hierarchy.hlp
28744--- a/gopls/internal/lsp/cmd/usage/call_hierarchy.hlp	2000-01-01 00:00:00.000000000 -0000
28745+++ b/gopls/internal/lsp/cmd/usage/call_hierarchy.hlp	1970-01-01 00:00:00.000000000 +0000
28746@@ -1,10 +0,0 @@
28747-display selected identifier's call hierarchy
28748-
28749-Usage:
28750-  gopls [flags] call_hierarchy <position>
28751-
28752-Example:
28753-
28754-	$ # 1-indexed location (:line:column or :#offset) of the target identifier
28755-	$ gopls call_hierarchy helper/helper.go:8:6
28756-	$ gopls call_hierarchy helper/helper.go:#53
28757diff -urN a/gopls/internal/lsp/cmd/usage/check.hlp b/gopls/internal/lsp/cmd/usage/check.hlp
28758--- a/gopls/internal/lsp/cmd/usage/check.hlp	2000-01-01 00:00:00.000000000 -0000
28759+++ b/gopls/internal/lsp/cmd/usage/check.hlp	1970-01-01 00:00:00.000000000 +0000
28760@@ -1,8 +0,0 @@
28761-show diagnostic results for the specified file
28762-
28763-Usage:
28764-  gopls [flags] check <filename>
28765-
28766-Example: show the diagnostic results of this file:
28767-
28768-	$ gopls check internal/lsp/cmd/check.go
28769diff -urN a/gopls/internal/lsp/cmd/usage/definition.hlp b/gopls/internal/lsp/cmd/usage/definition.hlp
28770--- a/gopls/internal/lsp/cmd/usage/definition.hlp	2000-01-01 00:00:00.000000000 -0000
28771+++ b/gopls/internal/lsp/cmd/usage/definition.hlp	1970-01-01 00:00:00.000000000 +0000
28772@@ -1,15 +0,0 @@
28773-show declaration of selected identifier
28774-
28775-Usage:
28776-  gopls [flags] definition [definition-flags] <position>
28777-
28778-Example: show the definition of the identifier at syntax at offset 44 in this file (flag.FlagSet):
28779-
28780-	$ gopls definition internal/lsp/cmd/definition.go:44:47
28781-	$ gopls definition internal/lsp/cmd/definition.go:#1270
28782-
28783-definition-flags:
28784-  -json
28785-    	emit output in JSON format
28786-  -markdown
28787-    	support markdown in responses
28788diff -urN a/gopls/internal/lsp/cmd/usage/fix.hlp b/gopls/internal/lsp/cmd/usage/fix.hlp
28789--- a/gopls/internal/lsp/cmd/usage/fix.hlp	2000-01-01 00:00:00.000000000 -0000
28790+++ b/gopls/internal/lsp/cmd/usage/fix.hlp	1970-01-01 00:00:00.000000000 +0000
28791@@ -1,15 +0,0 @@
28792-apply suggested fixes
28793-
28794-Usage:
28795-  gopls [flags] fix [fix-flags] <filename>
28796-
28797-Example: apply suggested fixes for this file
28798-	$ gopls fix -w internal/lsp/cmd/check.go
28799-
28800-fix-flags:
28801-  -a,-all
28802-    	apply all fixes, not just preferred fixes
28803-  -d,-diff
28804-    	display diffs instead of rewriting files
28805-  -w,-write
28806-    	write result to (source) file instead of stdout
28807diff -urN a/gopls/internal/lsp/cmd/usage/folding_ranges.hlp b/gopls/internal/lsp/cmd/usage/folding_ranges.hlp
28808--- a/gopls/internal/lsp/cmd/usage/folding_ranges.hlp	2000-01-01 00:00:00.000000000 -0000
28809+++ b/gopls/internal/lsp/cmd/usage/folding_ranges.hlp	1970-01-01 00:00:00.000000000 +0000
28810@@ -1,8 +0,0 @@
28811-display selected file's folding ranges
28812-
28813-Usage:
28814-  gopls [flags] folding_ranges <file>
28815-
28816-Example:
28817-
28818-	$ gopls folding_ranges helper/helper.go
28819diff -urN a/gopls/internal/lsp/cmd/usage/format.hlp b/gopls/internal/lsp/cmd/usage/format.hlp
28820--- a/gopls/internal/lsp/cmd/usage/format.hlp	2000-01-01 00:00:00.000000000 -0000
28821+++ b/gopls/internal/lsp/cmd/usage/format.hlp	1970-01-01 00:00:00.000000000 +0000
28822@@ -1,18 +0,0 @@
28823-format the code according to the go standard
28824-
28825-Usage:
28826-  gopls [flags] format [format-flags] <filerange>
28827-
28828-The arguments supplied may be simple file names, or ranges within files.
28829-
28830-Example: reformat this file:
28831-
28832-	$ gopls format -w internal/lsp/cmd/check.go
28833-
28834-format-flags:
28835-  -d,-diff
28836-    	display diffs instead of rewriting files
28837-  -l,-list
28838-    	list files whose formatting differs from gofmt's
28839-  -w,-write
28840-    	write result to (source) file instead of stdout
28841diff -urN a/gopls/internal/lsp/cmd/usage/help.hlp b/gopls/internal/lsp/cmd/usage/help.hlp
28842--- a/gopls/internal/lsp/cmd/usage/help.hlp	2000-01-01 00:00:00.000000000 -0000
28843+++ b/gopls/internal/lsp/cmd/usage/help.hlp	1970-01-01 00:00:00.000000000 +0000
28844@@ -1,10 +0,0 @@
28845-print usage information for subcommands
28846-
28847-Usage:
28848-  gopls [flags] help
28849-
28850-
28851-Examples:
28852-$ gopls help                         # main gopls help message
28853-$ gopls help remote                  # help on 'remote' command
28854-$ gopls help remote sessions         # help on 'remote sessions' subcommand
28855diff -urN a/gopls/internal/lsp/cmd/usage/highlight.hlp b/gopls/internal/lsp/cmd/usage/highlight.hlp
28856--- a/gopls/internal/lsp/cmd/usage/highlight.hlp	2000-01-01 00:00:00.000000000 -0000
28857+++ b/gopls/internal/lsp/cmd/usage/highlight.hlp	1970-01-01 00:00:00.000000000 +0000
28858@@ -1,10 +0,0 @@
28859-display selected identifier's highlights
28860-
28861-Usage:
28862-  gopls [flags] highlight <position>
28863-
28864-Example:
28865-
28866-	$ # 1-indexed location (:line:column or :#offset) of the target identifier
28867-	$ gopls highlight helper/helper.go:8:6
28868-	$ gopls highlight helper/helper.go:#53
28869diff -urN a/gopls/internal/lsp/cmd/usage/implementation.hlp b/gopls/internal/lsp/cmd/usage/implementation.hlp
28870--- a/gopls/internal/lsp/cmd/usage/implementation.hlp	2000-01-01 00:00:00.000000000 -0000
28871+++ b/gopls/internal/lsp/cmd/usage/implementation.hlp	1970-01-01 00:00:00.000000000 +0000
28872@@ -1,10 +0,0 @@
28873-display selected identifier's implementation
28874-
28875-Usage:
28876-  gopls [flags] implementation <position>
28877-
28878-Example:
28879-
28880-	$ # 1-indexed location (:line:column or :#offset) of the target identifier
28881-	$ gopls implementation helper/helper.go:8:6
28882-	$ gopls implementation helper/helper.go:#53
28883diff -urN a/gopls/internal/lsp/cmd/usage/imports.hlp b/gopls/internal/lsp/cmd/usage/imports.hlp
28884--- a/gopls/internal/lsp/cmd/usage/imports.hlp	2000-01-01 00:00:00.000000000 -0000
28885+++ b/gopls/internal/lsp/cmd/usage/imports.hlp	1970-01-01 00:00:00.000000000 +0000
28886@@ -1,14 +0,0 @@
28887-updates import statements
28888-
28889-Usage:
28890-  gopls [flags] imports [imports-flags] <filename>
28891-
28892-Example: update imports statements in a file:
28893-
28894-	$ gopls imports -w internal/lsp/cmd/check.go
28895-
28896-imports-flags:
28897-  -d,-diff
28898-    	display diffs instead of rewriting files
28899-  -w,-write
28900-    	write result to (source) file instead of stdout
28901diff -urN a/gopls/internal/lsp/cmd/usage/inspect.hlp b/gopls/internal/lsp/cmd/usage/inspect.hlp
28902--- a/gopls/internal/lsp/cmd/usage/inspect.hlp	2000-01-01 00:00:00.000000000 -0000
28903+++ b/gopls/internal/lsp/cmd/usage/inspect.hlp	1970-01-01 00:00:00.000000000 +0000
28904@@ -1,8 +0,0 @@
28905-interact with the gopls daemon (deprecated: use 'remote')
28906-
28907-Usage:
28908-  gopls [flags] inspect <subcommand> [arg]...
28909-
28910-Subcommand:
28911-  sessions  print information about current gopls sessions
28912-  debug     start the debug server
28913diff -urN a/gopls/internal/lsp/cmd/usage/licenses.hlp b/gopls/internal/lsp/cmd/usage/licenses.hlp
28914--- a/gopls/internal/lsp/cmd/usage/licenses.hlp	2000-01-01 00:00:00.000000000 -0000
28915+++ b/gopls/internal/lsp/cmd/usage/licenses.hlp	1970-01-01 00:00:00.000000000 +0000
28916@@ -1,4 +0,0 @@
28917-print licenses of included software
28918-
28919-Usage:
28920-  gopls [flags] licenses
28921diff -urN a/gopls/internal/lsp/cmd/usage/links.hlp b/gopls/internal/lsp/cmd/usage/links.hlp
28922--- a/gopls/internal/lsp/cmd/usage/links.hlp	2000-01-01 00:00:00.000000000 -0000
28923+++ b/gopls/internal/lsp/cmd/usage/links.hlp	1970-01-01 00:00:00.000000000 +0000
28924@@ -1,12 +0,0 @@
28925-list links in a file
28926-
28927-Usage:
28928-  gopls [flags] links [links-flags] <filename>
28929-
28930-Example: list links contained within a file:
28931-
28932-	$ gopls links internal/lsp/cmd/check.go
28933-
28934-links-flags:
28935-  -json
28936-    	emit document links in JSON format
28937diff -urN a/gopls/internal/lsp/cmd/usage/prepare_rename.hlp b/gopls/internal/lsp/cmd/usage/prepare_rename.hlp
28938--- a/gopls/internal/lsp/cmd/usage/prepare_rename.hlp	2000-01-01 00:00:00.000000000 -0000
28939+++ b/gopls/internal/lsp/cmd/usage/prepare_rename.hlp	1970-01-01 00:00:00.000000000 +0000
28940@@ -1,10 +0,0 @@
28941-test validity of a rename operation at location
28942-
28943-Usage:
28944-  gopls [flags] prepare_rename <position>
28945-
28946-Example:
28947-
28948-	$ # 1-indexed location (:line:column or :#offset) of the target identifier
28949-	$ gopls prepare_rename helper/helper.go:8:6
28950-	$ gopls prepare_rename helper/helper.go:#53
28951diff -urN a/gopls/internal/lsp/cmd/usage/references.hlp b/gopls/internal/lsp/cmd/usage/references.hlp
28952--- a/gopls/internal/lsp/cmd/usage/references.hlp	2000-01-01 00:00:00.000000000 -0000
28953+++ b/gopls/internal/lsp/cmd/usage/references.hlp	1970-01-01 00:00:00.000000000 +0000
28954@@ -1,14 +0,0 @@
28955-display selected identifier's references
28956-
28957-Usage:
28958-  gopls [flags] references [references-flags] <position>
28959-
28960-Example:
28961-
28962-	$ # 1-indexed location (:line:column or :#offset) of the target identifier
28963-	$ gopls references helper/helper.go:8:6
28964-	$ gopls references helper/helper.go:#53
28965-
28966-references-flags:
28967-  -d,-declaration
28968-    	include the declaration of the specified identifier in the results
28969diff -urN a/gopls/internal/lsp/cmd/usage/remote.hlp b/gopls/internal/lsp/cmd/usage/remote.hlp
28970--- a/gopls/internal/lsp/cmd/usage/remote.hlp	2000-01-01 00:00:00.000000000 -0000
28971+++ b/gopls/internal/lsp/cmd/usage/remote.hlp	1970-01-01 00:00:00.000000000 +0000
28972@@ -1,8 +0,0 @@
28973-interact with the gopls daemon
28974-
28975-Usage:
28976-  gopls [flags] remote <subcommand> [arg]...
28977-
28978-Subcommand:
28979-  sessions  print information about current gopls sessions
28980-  debug     start the debug server
28981diff -urN a/gopls/internal/lsp/cmd/usage/rename.hlp b/gopls/internal/lsp/cmd/usage/rename.hlp
28982--- a/gopls/internal/lsp/cmd/usage/rename.hlp	2000-01-01 00:00:00.000000000 -0000
28983+++ b/gopls/internal/lsp/cmd/usage/rename.hlp	1970-01-01 00:00:00.000000000 +0000
28984@@ -1,18 +0,0 @@
28985-rename selected identifier
28986-
28987-Usage:
28988-  gopls [flags] rename [rename-flags] <position> <name>
28989-
28990-Example:
28991-
28992-	$ # 1-based location (:line:column or :#position) of the thing to change
28993-	$ gopls rename helper/helper.go:8:6 Foo
28994-	$ gopls rename helper/helper.go:#53 Foo
28995-
28996-rename-flags:
28997-  -d,-diff
28998-    	display diffs instead of rewriting files
28999-  -preserve
29000-    	preserve original files
29001-  -w,-write
29002-    	write result to (source) file instead of stdout
29003diff -urN a/gopls/internal/lsp/cmd/usage/semtok.hlp b/gopls/internal/lsp/cmd/usage/semtok.hlp
29004--- a/gopls/internal/lsp/cmd/usage/semtok.hlp	2000-01-01 00:00:00.000000000 -0000
29005+++ b/gopls/internal/lsp/cmd/usage/semtok.hlp	1970-01-01 00:00:00.000000000 +0000
29006@@ -1,8 +0,0 @@
29007-show semantic tokens for the specified file
29008-
29009-Usage:
29010-  gopls [flags] semtok <filename>
29011-
29012-Example: show the semantic tokens for this file:
29013-
29014-	$ gopls semtok internal/lsp/cmd/semtok.go
29015diff -urN a/gopls/internal/lsp/cmd/usage/serve.hlp b/gopls/internal/lsp/cmd/usage/serve.hlp
29016--- a/gopls/internal/lsp/cmd/usage/serve.hlp	2000-01-01 00:00:00.000000000 -0000
29017+++ b/gopls/internal/lsp/cmd/usage/serve.hlp	1970-01-01 00:00:00.000000000 +0000
29018@@ -1,30 +0,0 @@
29019-run a server for Go code using the Language Server Protocol
29020-
29021-Usage:
29022-  gopls [flags] serve [server-flags]
29023-  gopls [flags] [server-flags]
29024-
29025-The server communicates using JSONRPC2 on stdin and stdout, and is intended to be run directly as
29026-a child of an editor process.
29027-
29028-server-flags:
29029-  -debug=string
29030-    	serve debug information on the supplied address
29031-  -listen=string
29032-    	address on which to listen for remote connections. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. Otherwise, TCP is used.
29033-  -listen.timeout=duration
29034-    	when used with -listen, shut down the server when there are no connected clients for this duration
29035-  -logfile=string
29036-    	filename to log to. if value is "auto", then logging to a default output file is enabled
29037-  -mode=string
29038-    	no effect
29039-  -port=int
29040-    	port on which to run gopls for debugging purposes
29041-  -remote.debug=string
29042-    	when used with -remote=auto, the -debug value used to start the daemon
29043-  -remote.listen.timeout=duration
29044-    	when used with -remote=auto, the -listen.timeout value used to start the daemon (default 1m0s)
29045-  -remote.logfile=string
29046-    	when used with -remote=auto, the -logfile value used to start the daemon
29047-  -rpc.trace
29048-    	print the full rpc trace in lsp inspector format
29049diff -urN a/gopls/internal/lsp/cmd/usage/signature.hlp b/gopls/internal/lsp/cmd/usage/signature.hlp
29050--- a/gopls/internal/lsp/cmd/usage/signature.hlp	2000-01-01 00:00:00.000000000 -0000
29051+++ b/gopls/internal/lsp/cmd/usage/signature.hlp	1970-01-01 00:00:00.000000000 +0000
29052@@ -1,10 +0,0 @@
29053-display selected identifier's signature
29054-
29055-Usage:
29056-  gopls [flags] signature <position>
29057-
29058-Example:
29059-
29060-	$ # 1-indexed location (:line:column or :#offset) of the target identifier
29061-	$ gopls signature helper/helper.go:8:6
29062-	$ gopls signature helper/helper.go:#53
29063diff -urN a/gopls/internal/lsp/cmd/usage/symbols.hlp b/gopls/internal/lsp/cmd/usage/symbols.hlp
29064--- a/gopls/internal/lsp/cmd/usage/symbols.hlp	2000-01-01 00:00:00.000000000 -0000
29065+++ b/gopls/internal/lsp/cmd/usage/symbols.hlp	1970-01-01 00:00:00.000000000 +0000
29066@@ -1,7 +0,0 @@
29067-display selected file's symbols
29068-
29069-Usage:
29070-  gopls [flags] symbols <file>
29071-
29072-Example:
29073-	$ gopls symbols helper/helper.go
29074diff -urN a/gopls/internal/lsp/cmd/usage/usage.hlp b/gopls/internal/lsp/cmd/usage/usage.hlp
29075--- a/gopls/internal/lsp/cmd/usage/usage.hlp	2000-01-01 00:00:00.000000000 -0000
29076+++ b/gopls/internal/lsp/cmd/usage/usage.hlp	1970-01-01 00:00:00.000000000 +0000
29077@@ -1,77 +0,0 @@
29078-
29079-gopls is a Go language server.
29080-
29081-It is typically used with an editor to provide language features. When no
29082-command is specified, gopls will default to the 'serve' command. The language
29083-features can also be accessed via the gopls command-line interface.
29084-
29085-Usage:
29086-  gopls help [<subject>]
29087-
29088-Command:
29089-
29090-Main
29091-  serve             run a server for Go code using the Language Server Protocol
29092-  version           print the gopls version information
29093-  bug               report a bug in gopls
29094-  help              print usage information for subcommands
29095-  api-json          print json describing gopls API
29096-  licenses          print licenses of included software
29097-
29098-Features
29099-  call_hierarchy    display selected identifier's call hierarchy
29100-  check             show diagnostic results for the specified file
29101-  definition        show declaration of selected identifier
29102-  folding_ranges    display selected file's folding ranges
29103-  format            format the code according to the go standard
29104-  highlight         display selected identifier's highlights
29105-  implementation    display selected identifier's implementation
29106-  imports           updates import statements
29107-  remote            interact with the gopls daemon
29108-  inspect           interact with the gopls daemon (deprecated: use 'remote')
29109-  links             list links in a file
29110-  prepare_rename    test validity of a rename operation at location
29111-  references        display selected identifier's references
29112-  rename            rename selected identifier
29113-  semtok            show semantic tokens for the specified file
29114-  signature         display selected identifier's signature
29115-  fix               apply suggested fixes
29116-  symbols           display selected file's symbols
29117-  workspace_symbol  search symbols in workspace
29118-  vulncheck         run experimental vulncheck analysis (experimental: under development)
29119-
29120-flags:
29121-  -debug=string
29122-    	serve debug information on the supplied address
29123-  -listen=string
29124-    	address on which to listen for remote connections. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. Otherwise, TCP is used.
29125-  -listen.timeout=duration
29126-    	when used with -listen, shut down the server when there are no connected clients for this duration
29127-  -logfile=string
29128-    	filename to log to. if value is "auto", then logging to a default output file is enabled
29129-  -mode=string
29130-    	no effect
29131-  -ocagent=string
29132-    	the address of the ocagent (e.g. http://localhost:55678), or off (default "off")
29133-  -port=int
29134-    	port on which to run gopls for debugging purposes
29135-  -profile.cpu=string
29136-    	write CPU profile to this file
29137-  -profile.mem=string
29138-    	write memory profile to this file
29139-  -profile.trace=string
29140-    	write trace log to this file
29141-  -remote=string
29142-    	forward all commands to a remote lsp specified by this flag. With no special prefix, this is assumed to be a TCP address. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. If 'auto', or prefixed by 'auto;', the remote address is automatically resolved based on the executing environment.
29143-  -remote.debug=string
29144-    	when used with -remote=auto, the -debug value used to start the daemon
29145-  -remote.listen.timeout=duration
29146-    	when used with -remote=auto, the -listen.timeout value used to start the daemon (default 1m0s)
29147-  -remote.logfile=string
29148-    	when used with -remote=auto, the -logfile value used to start the daemon
29149-  -rpc.trace
29150-    	print the full rpc trace in lsp inspector format
29151-  -v,-verbose
29152-    	verbose output
29153-  -vv,-veryverbose
29154-    	very verbose output
29155diff -urN a/gopls/internal/lsp/cmd/usage/version.hlp b/gopls/internal/lsp/cmd/usage/version.hlp
29156--- a/gopls/internal/lsp/cmd/usage/version.hlp	2000-01-01 00:00:00.000000000 -0000
29157+++ b/gopls/internal/lsp/cmd/usage/version.hlp	1970-01-01 00:00:00.000000000 +0000
29158@@ -1,6 +0,0 @@
29159-print the gopls version information
29160-
29161-Usage:
29162-  gopls [flags] version
29163-  -json
29164-    	outputs in json format.
29165diff -urN a/gopls/internal/lsp/cmd/usage/vulncheck.hlp b/gopls/internal/lsp/cmd/usage/vulncheck.hlp
29166--- a/gopls/internal/lsp/cmd/usage/vulncheck.hlp	2000-01-01 00:00:00.000000000 -0000
29167+++ b/gopls/internal/lsp/cmd/usage/vulncheck.hlp	1970-01-01 00:00:00.000000000 +0000
29168@@ -1,17 +0,0 @@
29169-run experimental vulncheck analysis (experimental: under development)
29170-
29171-Usage:
29172-  gopls [flags] vulncheck
29173-
29174-	WARNING: this command is experimental.
29175-
29176-	By default, the command outputs a JSON-encoded
29177-	golang.org/x/tools/gopls/internal/lsp/command.VulncheckResult
29178-	message.
29179-	Example:
29180-	$ gopls vulncheck <packages>
29181-
29182-  -config
29183-    	If true, the command reads a JSON-encoded package load configuration from stdin
29184-  -summary
29185-    	If true, outputs a JSON-encoded govulnchecklib.Summary JSON
29186diff -urN a/gopls/internal/lsp/cmd/usage/workspace_symbol.hlp b/gopls/internal/lsp/cmd/usage/workspace_symbol.hlp
29187--- a/gopls/internal/lsp/cmd/usage/workspace_symbol.hlp	2000-01-01 00:00:00.000000000 -0000
29188+++ b/gopls/internal/lsp/cmd/usage/workspace_symbol.hlp	1970-01-01 00:00:00.000000000 +0000
29189@@ -1,13 +0,0 @@
29190-search symbols in workspace
29191-
29192-Usage:
29193-  gopls [flags] workspace_symbol [workspace_symbol-flags] <query>
29194-
29195-Example:
29196-
29197-	$ gopls workspace_symbol -matcher fuzzy 'wsymbols'
29198-
29199-workspace_symbol-flags:
29200-  -matcher=string
29201-    	specifies the type of matcher: fuzzy, caseSensitive, or caseInsensitive.
29202-    	The default is caseInsensitive.
29203diff -urN a/gopls/internal/lsp/cmd/vulncheck.go b/gopls/internal/lsp/cmd/vulncheck.go
29204--- a/gopls/internal/lsp/cmd/vulncheck.go	2000-01-01 00:00:00.000000000 -0000
29205+++ b/gopls/internal/lsp/cmd/vulncheck.go	1970-01-01 00:00:00.000000000 +0000
29206@@ -1,84 +0,0 @@
29207-// Copyright 2022 The Go Authors. All rights reserved.
29208-// Use of this source code is governed by a BSD-style
29209-// license that can be found in the LICENSE file.
29210-
29211-package cmd
29212-
29213-import (
29214-	"context"
29215-	"encoding/json"
29216-	"flag"
29217-	"fmt"
29218-	"os"
29219-
29220-	"golang.org/x/tools/go/packages"
29221-	vulnchecklib "golang.org/x/tools/gopls/internal/vulncheck"
29222-	"golang.org/x/tools/internal/tool"
29223-)
29224-
29225-// vulncheck implements the vulncheck command.
29226-type vulncheck struct {
29227-	Config    bool `flag:"config" help:"If true, the command reads a JSON-encoded package load configuration from stdin"`
29228-	AsSummary bool `flag:"summary" help:"If true, outputs a JSON-encoded govulnchecklib.Summary JSON"`
29229-	app       *Application
29230-}
29231-
29232-type pkgLoadConfig struct {
29233-	// BuildFlags is a list of command-line flags to be passed through to
29234-	// the build system's query tool.
29235-	BuildFlags []string
29236-
29237-	// If Tests is set, the loader includes related test packages.
29238-	Tests bool
29239-}
29240-
29241-// TODO(hyangah): document pkgLoadConfig
29242-
29243-func (v *vulncheck) Name() string   { return "vulncheck" }
29244-func (v *vulncheck) Parent() string { return v.app.Name() }
29245-func (v *vulncheck) Usage() string  { return "" }
29246-func (v *vulncheck) ShortHelp() string {
29247-	return "run experimental vulncheck analysis (experimental: under development)"
29248-}
29249-func (v *vulncheck) DetailedHelp(f *flag.FlagSet) {
29250-	fmt.Fprint(f.Output(), `
29251-	WARNING: this command is experimental.
29252-
29253-	By default, the command outputs a JSON-encoded
29254-	golang.org/x/tools/gopls/internal/lsp/command.VulncheckResult
29255-	message.
29256-	Example:
29257-	$ gopls vulncheck <packages>
29258-
29259-`)
29260-	printFlagDefaults(f)
29261-}
29262-
29263-func (v *vulncheck) Run(ctx context.Context, args ...string) error {
29264-	if vulnchecklib.Main == nil {
29265-		return fmt.Errorf("vulncheck command is available only in gopls compiled with go1.18 or newer")
29266-	}
29267-
29268-	// TODO(hyangah): what's wrong with allowing multiple targets?
29269-	if len(args) > 1 {
29270-		return tool.CommandLineErrorf("vulncheck accepts at most one package pattern")
29271-	}
29272-	var cfg pkgLoadConfig
29273-	if v.Config {
29274-		if err := json.NewDecoder(os.Stdin).Decode(&cfg); err != nil {
29275-			return tool.CommandLineErrorf("failed to parse cfg: %v", err)
29276-		}
29277-	}
29278-	loadCfg := packages.Config{
29279-		Context:    ctx,
29280-		Tests:      cfg.Tests,
29281-		BuildFlags: cfg.BuildFlags,
29282-		// inherit the current process's cwd and env.
29283-	}
29284-
29285-	if err := vulnchecklib.Main(loadCfg, args...); err != nil {
29286-		fmt.Fprintln(os.Stderr, err)
29287-		os.Exit(1)
29288-	}
29289-	return nil
29290-}
29291diff -urN a/gopls/internal/lsp/cmd/workspace_symbol.go b/gopls/internal/lsp/cmd/workspace_symbol.go
29292--- a/gopls/internal/lsp/cmd/workspace_symbol.go	2000-01-01 00:00:00.000000000 -0000
29293+++ b/gopls/internal/lsp/cmd/workspace_symbol.go	1970-01-01 00:00:00.000000000 +0000
29294@@ -1,85 +0,0 @@
29295-// Copyright 2020 The Go Authors. All rights reserved.
29296-// Use of this source code is governed by a BSD-style
29297-// license that can be found in the LICENSE file.
29298-
29299-package cmd
29300-
29301-import (
29302-	"context"
29303-	"flag"
29304-	"fmt"
29305-
29306-	"golang.org/x/tools/gopls/internal/lsp/protocol"
29307-	"golang.org/x/tools/gopls/internal/lsp/source"
29308-	"golang.org/x/tools/internal/tool"
29309-)
29310-
29311-// workspaceSymbol implements the workspace_symbol verb for gopls.
29312-type workspaceSymbol struct {
29313-	Matcher string `flag:"matcher" help:"specifies the type of matcher: fuzzy, caseSensitive, or caseInsensitive.\nThe default is caseInsensitive."`
29314-
29315-	app *Application
29316-}
29317-
29318-func (r *workspaceSymbol) Name() string      { return "workspace_symbol" }
29319-func (r *workspaceSymbol) Parent() string    { return r.app.Name() }
29320-func (r *workspaceSymbol) Usage() string     { return "[workspace_symbol-flags] <query>" }
29321-func (r *workspaceSymbol) ShortHelp() string { return "search symbols in workspace" }
29322-func (r *workspaceSymbol) DetailedHelp(f *flag.FlagSet) {
29323-	fmt.Fprint(f.Output(), `
29324-Example:
29325-
29326-	$ gopls workspace_symbol -matcher fuzzy 'wsymbols'
29327-
29328-workspace_symbol-flags:
29329-`)
29330-	printFlagDefaults(f)
29331-}
29332-
29333-func (r *workspaceSymbol) Run(ctx context.Context, args ...string) error {
29334-	if len(args) != 1 {
29335-		return tool.CommandLineErrorf("workspace_symbol expects 1 argument")
29336-	}
29337-
29338-	opts := r.app.options
29339-	r.app.options = func(o *source.Options) {
29340-		if opts != nil {
29341-			opts(o)
29342-		}
29343-		switch r.Matcher {
29344-		case "fuzzy":
29345-			o.SymbolMatcher = source.SymbolFuzzy
29346-		case "caseSensitive":
29347-			o.SymbolMatcher = source.SymbolCaseSensitive
29348-		case "fastfuzzy":
29349-			o.SymbolMatcher = source.SymbolFastFuzzy
29350-		default:
29351-			o.SymbolMatcher = source.SymbolCaseInsensitive
29352-		}
29353-	}
29354-
29355-	conn, err := r.app.connect(ctx)
29356-	if err != nil {
29357-		return err
29358-	}
29359-	defer conn.terminate(ctx)
29360-
29361-	p := protocol.WorkspaceSymbolParams{
29362-		Query: args[0],
29363-	}
29364-
29365-	symbols, err := conn.Symbol(ctx, &p)
29366-	if err != nil {
29367-		return err
29368-	}
29369-	for _, s := range symbols {
29370-		f := conn.openFile(ctx, fileURI(s.Location.URI))
29371-		span, err := f.mapper.LocationSpan(s.Location)
29372-		if err != nil {
29373-			return err
29374-		}
29375-		fmt.Printf("%s %s %s\n", span, s.Name, s.Kind)
29376-	}
29377-
29378-	return nil
29379-}
29380diff -urN a/gopls/internal/lsp/code_action.go b/gopls/internal/lsp/code_action.go
29381--- a/gopls/internal/lsp/code_action.go	2000-01-01 00:00:00.000000000 -0000
29382+++ b/gopls/internal/lsp/code_action.go	1970-01-01 00:00:00.000000000 +0000
29383@@ -1,481 +0,0 @@
29384-// Copyright 2018 The Go Authors. All rights reserved.
29385-// Use of this source code is governed by a BSD-style
29386-// license that can be found in the LICENSE file.
29387-
29388-package lsp
29389-
29390-import (
29391-	"context"
29392-	"fmt"
29393-	"sort"
29394-	"strings"
29395-
29396-	"golang.org/x/tools/gopls/internal/lsp/command"
29397-	"golang.org/x/tools/gopls/internal/lsp/mod"
29398-	"golang.org/x/tools/gopls/internal/lsp/protocol"
29399-	"golang.org/x/tools/gopls/internal/lsp/source"
29400-	"golang.org/x/tools/gopls/internal/span"
29401-	"golang.org/x/tools/internal/event"
29402-	"golang.org/x/tools/internal/event/tag"
29403-	"golang.org/x/tools/internal/imports"
29404-)
29405-
29406-func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionParams) ([]protocol.CodeAction, error) {
29407-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.UnknownKind)
29408-	defer release()
29409-	if !ok {
29410-		return nil, err
29411-	}
29412-	uri := fh.URI()
29413-
29414-	// Determine the supported actions for this file kind.
29415-	kind := snapshot.View().FileKind(fh)
29416-	supportedCodeActions, ok := snapshot.View().Options().SupportedCodeActions[kind]
29417-	if !ok {
29418-		return nil, fmt.Errorf("no supported code actions for %v file kind", kind)
29419-	}
29420-
29421-	// The Only field of the context specifies which code actions the client wants.
29422-	// If Only is empty, assume that the client wants all of the non-explicit code actions.
29423-	var wanted map[protocol.CodeActionKind]bool
29424-
29425-	// Explicit Code Actions are opt-in and shouldn't be returned to the client unless
29426-	// requested using Only.
29427-	// TODO: Add other CodeLenses such as GoGenerate, RegenerateCgo, etc..
29428-	explicit := map[protocol.CodeActionKind]bool{
29429-		protocol.GoTest: true,
29430-	}
29431-
29432-	if len(params.Context.Only) == 0 {
29433-		wanted = supportedCodeActions
29434-	} else {
29435-		wanted = make(map[protocol.CodeActionKind]bool)
29436-		for _, only := range params.Context.Only {
29437-			for k, v := range supportedCodeActions {
29438-				if only == k || strings.HasPrefix(string(k), string(only)+".") {
29439-					wanted[k] = wanted[k] || v
29440-				}
29441-			}
29442-			wanted[only] = wanted[only] || explicit[only]
29443-		}
29444-	}
29445-	if len(supportedCodeActions) == 0 {
29446-		return nil, nil // not an error if there are none supported
29447-	}
29448-	if len(wanted) == 0 {
29449-		return nil, fmt.Errorf("no supported code action to execute for %s, wanted %v", uri, params.Context.Only)
29450-	}
29451-
29452-	var codeActions []protocol.CodeAction
29453-	switch kind {
29454-	case source.Mod:
29455-		if diagnostics := params.Context.Diagnostics; len(diagnostics) > 0 {
29456-			diags, err := mod.ModDiagnostics(ctx, snapshot, fh)
29457-			if source.IsNonFatalGoModError(err) {
29458-				return nil, nil
29459-			}
29460-			if err != nil {
29461-				return nil, err
29462-			}
29463-			udiags, err := mod.ModUpgradeDiagnostics(ctx, snapshot, fh)
29464-			if err != nil {
29465-				return nil, err
29466-			}
29467-			quickFixes, err := codeActionsMatchingDiagnostics(ctx, snapshot, diagnostics, append(diags, udiags...))
29468-			if err != nil {
29469-				return nil, err
29470-			}
29471-			codeActions = append(codeActions, quickFixes...)
29472-
29473-			vdiags, err := mod.ModVulnerabilityDiagnostics(ctx, snapshot, fh)
29474-			if err != nil {
29475-				return nil, err
29476-			}
29477-			// Group vulnerabilities by location and then limit which code actions we return
29478-			// for each location.
29479-			m := make(map[protocol.Range][]*source.Diagnostic)
29480-			for _, v := range vdiags {
29481-				m[v.Range] = append(m[v.Range], v)
29482-			}
29483-			for _, sdiags := range m {
29484-				quickFixes, err = codeActionsMatchingDiagnostics(ctx, snapshot, diagnostics, sdiags)
29485-				if err != nil {
29486-					return nil, err
29487-				}
29488-				quickFixes = mod.SelectUpgradeCodeActions(quickFixes)
29489-				codeActions = append(codeActions, quickFixes...)
29490-			}
29491-		}
29492-	case source.Go:
29493-		// Don't suggest fixes for generated files, since they are generally
29494-		// not useful and some editors may apply them automatically on save.
29495-		if source.IsGenerated(ctx, snapshot, uri) {
29496-			return nil, nil
29497-		}
29498-		diagnostics := params.Context.Diagnostics
29499-
29500-		// First, process any missing imports and pair them with the
29501-		// diagnostics they fix.
29502-		if wantQuickFixes := wanted[protocol.QuickFix] && len(diagnostics) > 0; wantQuickFixes || wanted[protocol.SourceOrganizeImports] {
29503-			importEdits, importEditsPerFix, err := source.AllImportsFixes(ctx, snapshot, fh)
29504-			if err != nil {
29505-				event.Error(ctx, "imports fixes", err, tag.File.Of(fh.URI().Filename()))
29506-			}
29507-			// Separate this into a set of codeActions per diagnostic, where
29508-			// each action is the addition, removal, or renaming of one import.
29509-			if wantQuickFixes {
29510-				for _, importFix := range importEditsPerFix {
29511-					fixes := importDiagnostics(importFix.Fix, diagnostics)
29512-					if len(fixes) == 0 {
29513-						continue
29514-					}
29515-					codeActions = append(codeActions, protocol.CodeAction{
29516-						Title: importFixTitle(importFix.Fix),
29517-						Kind:  protocol.QuickFix,
29518-						Edit: &protocol.WorkspaceEdit{
29519-							DocumentChanges: documentChanges(fh, importFix.Edits),
29520-						},
29521-						Diagnostics: fixes,
29522-					})
29523-				}
29524-			}
29525-
29526-			// Send all of the import edits as one code action if the file is
29527-			// being organized.
29528-			if wanted[protocol.SourceOrganizeImports] && len(importEdits) > 0 {
29529-				codeActions = append(codeActions, protocol.CodeAction{
29530-					Title: "Organize Imports",
29531-					Kind:  protocol.SourceOrganizeImports,
29532-					Edit: &protocol.WorkspaceEdit{
29533-						DocumentChanges: documentChanges(fh, importEdits),
29534-					},
29535-				})
29536-			}
29537-		}
29538-		if ctx.Err() != nil {
29539-			return nil, ctx.Err()
29540-		}
29541-
29542-		// Type-check the package and also run analysis,
29543-		// then combine their diagnostics.
29544-		pkg, _, err := source.PackageForFile(ctx, snapshot, fh.URI(), source.NarrowestPackage)
29545-		if err != nil {
29546-			return nil, err
29547-		}
29548-		pkgDiags, err := pkg.DiagnosticsForFile(ctx, snapshot, uri)
29549-		if err != nil {
29550-			return nil, err
29551-		}
29552-		analysisDiags, err := source.Analyze(ctx, snapshot, pkg.Metadata().ID, true)
29553-		if err != nil {
29554-			return nil, err
29555-		}
29556-		var fileDiags []*source.Diagnostic
29557-		source.CombineDiagnostics(pkgDiags, analysisDiags[uri], &fileDiags, &fileDiags)
29558-
29559-		// Split diagnostics into fixes, which must match incoming diagnostics,
29560-		// and non-fixes, which must match the requested range. Build actions
29561-		// for all of them.
29562-		var fixDiags, nonFixDiags []*source.Diagnostic
29563-		for _, d := range fileDiags {
29564-			if len(d.SuggestedFixes) == 0 {
29565-				continue
29566-			}
29567-			var isFix bool
29568-			for _, fix := range d.SuggestedFixes {
29569-				if fix.ActionKind == protocol.QuickFix || fix.ActionKind == protocol.SourceFixAll {
29570-					isFix = true
29571-					break
29572-				}
29573-			}
29574-			if isFix {
29575-				fixDiags = append(fixDiags, d)
29576-			} else {
29577-				nonFixDiags = append(nonFixDiags, d)
29578-			}
29579-		}
29580-
29581-		fixActions, err := codeActionsMatchingDiagnostics(ctx, snapshot, diagnostics, fixDiags)
29582-		if err != nil {
29583-			return nil, err
29584-		}
29585-		codeActions = append(codeActions, fixActions...)
29586-
29587-		for _, nonfix := range nonFixDiags {
29588-			// For now, only show diagnostics for matching lines. Maybe we should
29589-			// alter this behavior in the future, depending on the user experience.
29590-			if !protocol.Intersect(nonfix.Range, params.Range) {
29591-				continue
29592-			}
29593-			actions, err := codeActionsForDiagnostic(ctx, snapshot, nonfix, nil)
29594-			if err != nil {
29595-				return nil, err
29596-			}
29597-			codeActions = append(codeActions, actions...)
29598-		}
29599-
29600-		if wanted[protocol.RefactorExtract] {
29601-			fixes, err := extractionFixes(ctx, snapshot, uri, params.Range)
29602-			if err != nil {
29603-				return nil, err
29604-			}
29605-			codeActions = append(codeActions, fixes...)
29606-		}
29607-
29608-		if wanted[protocol.GoTest] {
29609-			fixes, err := goTest(ctx, snapshot, uri, params.Range)
29610-			if err != nil {
29611-				return nil, err
29612-			}
29613-			codeActions = append(codeActions, fixes...)
29614-		}
29615-
29616-	default:
29617-		// Unsupported file kind for a code action.
29618-		return nil, nil
29619-	}
29620-
29621-	var filtered []protocol.CodeAction
29622-	for _, action := range codeActions {
29623-		if wanted[action.Kind] {
29624-			filtered = append(filtered, action)
29625-		}
29626-	}
29627-	return filtered, nil
29628-}
29629-
29630-func (s *Server) getSupportedCodeActions() []protocol.CodeActionKind {
29631-	allCodeActionKinds := make(map[protocol.CodeActionKind]struct{})
29632-	for _, kinds := range s.session.Options().SupportedCodeActions {
29633-		for kind := range kinds {
29634-			allCodeActionKinds[kind] = struct{}{}
29635-		}
29636-	}
29637-	var result []protocol.CodeActionKind
29638-	for kind := range allCodeActionKinds {
29639-		result = append(result, kind)
29640-	}
29641-	sort.Slice(result, func(i, j int) bool {
29642-		return result[i] < result[j]
29643-	})
29644-	return result
29645-}
29646-
29647-func importFixTitle(fix *imports.ImportFix) string {
29648-	var str string
29649-	switch fix.FixType {
29650-	case imports.AddImport:
29651-		str = fmt.Sprintf("Add import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
29652-	case imports.DeleteImport:
29653-		str = fmt.Sprintf("Delete import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
29654-	case imports.SetImportName:
29655-		str = fmt.Sprintf("Rename import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
29656-	}
29657-	return str
29658-}
29659-
29660-func importDiagnostics(fix *imports.ImportFix, diagnostics []protocol.Diagnostic) (results []protocol.Diagnostic) {
29661-	for _, diagnostic := range diagnostics {
29662-		switch {
29663-		// "undeclared name: X" may be an unresolved import.
29664-		case strings.HasPrefix(diagnostic.Message, "undeclared name: "):
29665-			ident := strings.TrimPrefix(diagnostic.Message, "undeclared name: ")
29666-			if ident == fix.IdentName {
29667-				results = append(results, diagnostic)
29668-			}
29669-		// "undefined: X" may be an unresolved import at Go 1.20+.
29670-		case strings.HasPrefix(diagnostic.Message, "undefined: "):
29671-			ident := strings.TrimPrefix(diagnostic.Message, "undefined: ")
29672-			if ident == fix.IdentName {
29673-				results = append(results, diagnostic)
29674-			}
29675-		// "could not import: X" may be an invalid import.
29676-		case strings.HasPrefix(diagnostic.Message, "could not import: "):
29677-			ident := strings.TrimPrefix(diagnostic.Message, "could not import: ")
29678-			if ident == fix.IdentName {
29679-				results = append(results, diagnostic)
29680-			}
29681-		// "X imported but not used" is an unused import.
29682-		// "X imported but not used as Y" is an unused import.
29683-		case strings.Contains(diagnostic.Message, " imported but not used"):
29684-			idx := strings.Index(diagnostic.Message, " imported but not used")
29685-			importPath := diagnostic.Message[:idx]
29686-			if importPath == fmt.Sprintf("%q", fix.StmtInfo.ImportPath) {
29687-				results = append(results, diagnostic)
29688-			}
29689-		}
29690-	}
29691-	return results
29692-}
29693-
29694-func extractionFixes(ctx context.Context, snapshot source.Snapshot, uri span.URI, rng protocol.Range) ([]protocol.CodeAction, error) {
29695-	if rng.Start == rng.End {
29696-		return nil, nil
29697-	}
29698-	fh, err := snapshot.GetFile(ctx, uri)
29699-	if err != nil {
29700-		return nil, err
29701-	}
29702-	pgf, err := snapshot.ParseGo(ctx, fh, source.ParseFull)
29703-	if err != nil {
29704-		return nil, fmt.Errorf("getting file for Identifier: %w", err)
29705-	}
29706-	start, end, err := pgf.RangePos(rng)
29707-	if err != nil {
29708-		return nil, err
29709-	}
29710-	puri := protocol.URIFromSpanURI(uri)
29711-	var commands []protocol.Command
29712-	if _, ok, methodOk, _ := source.CanExtractFunction(pgf.Tok, start, end, pgf.Src, pgf.File); ok {
29713-		cmd, err := command.NewApplyFixCommand("Extract function", command.ApplyFixArgs{
29714-			URI:   puri,
29715-			Fix:   source.ExtractFunction,
29716-			Range: rng,
29717-		})
29718-		if err != nil {
29719-			return nil, err
29720-		}
29721-		commands = append(commands, cmd)
29722-		if methodOk {
29723-			cmd, err := command.NewApplyFixCommand("Extract method", command.ApplyFixArgs{
29724-				URI:   puri,
29725-				Fix:   source.ExtractMethod,
29726-				Range: rng,
29727-			})
29728-			if err != nil {
29729-				return nil, err
29730-			}
29731-			commands = append(commands, cmd)
29732-		}
29733-	}
29734-	if _, _, ok, _ := source.CanExtractVariable(start, end, pgf.File); ok {
29735-		cmd, err := command.NewApplyFixCommand("Extract variable", command.ApplyFixArgs{
29736-			URI:   puri,
29737-			Fix:   source.ExtractVariable,
29738-			Range: rng,
29739-		})
29740-		if err != nil {
29741-			return nil, err
29742-		}
29743-		commands = append(commands, cmd)
29744-	}
29745-	var actions []protocol.CodeAction
29746-	for i := range commands {
29747-		actions = append(actions, protocol.CodeAction{
29748-			Title:   commands[i].Title,
29749-			Kind:    protocol.RefactorExtract,
29750-			Command: &commands[i],
29751-		})
29752-	}
29753-	return actions, nil
29754-}
29755-
29756-func documentChanges(fh source.FileHandle, edits []protocol.TextEdit) []protocol.DocumentChanges {
29757-	return []protocol.DocumentChanges{
29758-		{
29759-			TextDocumentEdit: &protocol.TextDocumentEdit{
29760-				TextDocument: protocol.OptionalVersionedTextDocumentIdentifier{
29761-					Version: fh.Version(),
29762-					TextDocumentIdentifier: protocol.TextDocumentIdentifier{
29763-						URI: protocol.URIFromSpanURI(fh.URI()),
29764-					},
29765-				},
29766-				Edits: edits,
29767-			},
29768-		},
29769-	}
29770-}
29771-
29772-func codeActionsMatchingDiagnostics(ctx context.Context, snapshot source.Snapshot, pdiags []protocol.Diagnostic, sdiags []*source.Diagnostic) ([]protocol.CodeAction, error) {
29773-	var actions []protocol.CodeAction
29774-	for _, sd := range sdiags {
29775-		var diag *protocol.Diagnostic
29776-		for _, pd := range pdiags {
29777-			if sameDiagnostic(pd, sd) {
29778-				diag = &pd
29779-				break
29780-			}
29781-		}
29782-		if diag == nil {
29783-			continue
29784-		}
29785-		diagActions, err := codeActionsForDiagnostic(ctx, snapshot, sd, diag)
29786-		if err != nil {
29787-			return nil, err
29788-		}
29789-		actions = append(actions, diagActions...)
29790-
29791-	}
29792-	return actions, nil
29793-}
29794-
29795-func codeActionsForDiagnostic(ctx context.Context, snapshot source.Snapshot, sd *source.Diagnostic, pd *protocol.Diagnostic) ([]protocol.CodeAction, error) {
29796-	var actions []protocol.CodeAction
29797-	for _, fix := range sd.SuggestedFixes {
29798-		var changes []protocol.DocumentChanges
29799-		for uri, edits := range fix.Edits {
29800-			fh, err := snapshot.GetFile(ctx, uri)
29801-			if err != nil {
29802-				return nil, err
29803-			}
29804-			changes = append(changes, documentChanges(fh, edits)...)
29805-		}
29806-		action := protocol.CodeAction{
29807-			Title: fix.Title,
29808-			Kind:  fix.ActionKind,
29809-			Edit: &protocol.WorkspaceEdit{
29810-				DocumentChanges: changes,
29811-			},
29812-			Command: fix.Command,
29813-		}
29814-		if pd != nil {
29815-			action.Diagnostics = []protocol.Diagnostic{*pd}
29816-		}
29817-		actions = append(actions, action)
29818-	}
29819-	return actions, nil
29820-}
29821-
29822-func sameDiagnostic(pd protocol.Diagnostic, sd *source.Diagnostic) bool {
29823-	return pd.Message == strings.TrimSpace(sd.Message) && // extra space may have been trimmed when converting to protocol.Diagnostic
29824-		protocol.CompareRange(pd.Range, sd.Range) == 0 && pd.Source == string(sd.Source)
29825-}
29826-
29827-func goTest(ctx context.Context, snapshot source.Snapshot, uri span.URI, rng protocol.Range) ([]protocol.CodeAction, error) {
29828-	fh, err := snapshot.GetFile(ctx, uri)
29829-	if err != nil {
29830-		return nil, err
29831-	}
29832-	fns, err := source.TestsAndBenchmarks(ctx, snapshot, fh)
29833-	if err != nil {
29834-		return nil, err
29835-	}
29836-
29837-	var tests, benchmarks []string
29838-	for _, fn := range fns.Tests {
29839-		if !protocol.Intersect(fn.Rng, rng) {
29840-			continue
29841-		}
29842-		tests = append(tests, fn.Name)
29843-	}
29844-	for _, fn := range fns.Benchmarks {
29845-		if !protocol.Intersect(fn.Rng, rng) {
29846-			continue
29847-		}
29848-		benchmarks = append(benchmarks, fn.Name)
29849-	}
29850-
29851-	if len(tests) == 0 && len(benchmarks) == 0 {
29852-		return nil, nil
29853-	}
29854-
29855-	cmd, err := command.NewTestCommand("Run tests and benchmarks", protocol.URIFromSpanURI(uri), tests, benchmarks)
29856-	if err != nil {
29857-		return nil, err
29858-	}
29859-	return []protocol.CodeAction{{
29860-		Title:   cmd.Title,
29861-		Kind:    protocol.GoTest,
29862-		Command: &cmd,
29863-	}}, nil
29864-}
29865diff -urN a/gopls/internal/lsp/code_lens.go b/gopls/internal/lsp/code_lens.go
29866--- a/gopls/internal/lsp/code_lens.go	2000-01-01 00:00:00.000000000 -0000
29867+++ b/gopls/internal/lsp/code_lens.go	1970-01-01 00:00:00.000000000 +0000
29868@@ -1,57 +0,0 @@
29869-// Copyright 2020 The Go Authors. All rights reserved.
29870-// Use of this source code is governed by a BSD-style
29871-// license that can be found in the LICENSE file.
29872-
29873-package lsp
29874-
29875-import (
29876-	"context"
29877-	"fmt"
29878-	"sort"
29879-
29880-	"golang.org/x/tools/gopls/internal/lsp/command"
29881-	"golang.org/x/tools/gopls/internal/lsp/mod"
29882-	"golang.org/x/tools/gopls/internal/lsp/protocol"
29883-	"golang.org/x/tools/gopls/internal/lsp/source"
29884-	"golang.org/x/tools/internal/event"
29885-)
29886-
29887-func (s *Server) codeLens(ctx context.Context, params *protocol.CodeLensParams) ([]protocol.CodeLens, error) {
29888-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.UnknownKind)
29889-	defer release()
29890-	if !ok {
29891-		return nil, err
29892-	}
29893-	var lenses map[command.Command]source.LensFunc
29894-	switch snapshot.View().FileKind(fh) {
29895-	case source.Mod:
29896-		lenses = mod.LensFuncs()
29897-	case source.Go:
29898-		lenses = source.LensFuncs()
29899-	default:
29900-		// Unsupported file kind for a code lens.
29901-		return nil, nil
29902-	}
29903-	var result []protocol.CodeLens
29904-	for cmd, lf := range lenses {
29905-		if !snapshot.View().Options().Codelenses[string(cmd)] {
29906-			continue
29907-		}
29908-		added, err := lf(ctx, snapshot, fh)
29909-		// Code lens is called on every keystroke, so we should just operate in
29910-		// a best-effort mode, ignoring errors.
29911-		if err != nil {
29912-			event.Error(ctx, fmt.Sprintf("code lens %s failed", cmd), err)
29913-			continue
29914-		}
29915-		result = append(result, added...)
29916-	}
29917-	sort.Slice(result, func(i, j int) bool {
29918-		a, b := result[i], result[j]
29919-		if cmp := protocol.CompareRange(a.Range, b.Range); cmp != 0 {
29920-			return cmp < 0
29921-		}
29922-		return a.Command.Command < b.Command.Command
29923-	})
29924-	return result, nil
29925-}
29926diff -urN a/gopls/internal/lsp/command/command_gen.go b/gopls/internal/lsp/command/command_gen.go
29927--- a/gopls/internal/lsp/command/command_gen.go	2000-01-01 00:00:00.000000000 -0000
29928+++ b/gopls/internal/lsp/command/command_gen.go	1970-01-01 00:00:00.000000000 +0000
29929@@ -1,509 +0,0 @@
29930-// Copyright 2021 The Go Authors. All rights reserved.
29931-// Use of this source code is governed by a BSD-style
29932-// license that can be found in the LICENSE file.
29933-
29934-// Don't include this file during code generation, or it will break the build
29935-// if existing interface methods have been modified.
29936-//go:build !generate
29937-// +build !generate
29938-
29939-package command
29940-
29941-// Code generated by generate.go. DO NOT EDIT.
29942-
29943-import (
29944-	"context"
29945-	"fmt"
29946-
29947-	"golang.org/x/tools/gopls/internal/lsp/protocol"
29948-)
29949-
29950-const (
29951-	AddDependency         Command = "add_dependency"
29952-	AddImport             Command = "add_import"
29953-	ApplyFix              Command = "apply_fix"
29954-	CheckUpgrades         Command = "check_upgrades"
29955-	EditGoDirective       Command = "edit_go_directive"
29956-	FetchVulncheckResult  Command = "fetch_vulncheck_result"
29957-	GCDetails             Command = "gc_details"
29958-	Generate              Command = "generate"
29959-	GoGetPackage          Command = "go_get_package"
29960-	ListImports           Command = "list_imports"
29961-	ListKnownPackages     Command = "list_known_packages"
29962-	MemStats              Command = "mem_stats"
29963-	RegenerateCgo         Command = "regenerate_cgo"
29964-	RemoveDependency      Command = "remove_dependency"
29965-	ResetGoModDiagnostics Command = "reset_go_mod_diagnostics"
29966-	RunGovulncheck        Command = "run_govulncheck"
29967-	RunTests              Command = "run_tests"
29968-	StartDebugging        Command = "start_debugging"
29969-	Test                  Command = "test"
29970-	Tidy                  Command = "tidy"
29971-	ToggleGCDetails       Command = "toggle_gc_details"
29972-	UpdateGoSum           Command = "update_go_sum"
29973-	UpgradeDependency     Command = "upgrade_dependency"
29974-	Vendor                Command = "vendor"
29975-)
29976-
29977-var Commands = []Command{
29978-	AddDependency,
29979-	AddImport,
29980-	ApplyFix,
29981-	CheckUpgrades,
29982-	EditGoDirective,
29983-	FetchVulncheckResult,
29984-	GCDetails,
29985-	Generate,
29986-	GoGetPackage,
29987-	ListImports,
29988-	ListKnownPackages,
29989-	MemStats,
29990-	RegenerateCgo,
29991-	RemoveDependency,
29992-	ResetGoModDiagnostics,
29993-	RunGovulncheck,
29994-	RunTests,
29995-	StartDebugging,
29996-	Test,
29997-	Tidy,
29998-	ToggleGCDetails,
29999-	UpdateGoSum,
30000-	UpgradeDependency,
30001-	Vendor,
30002-}
30003-
30004-func Dispatch(ctx context.Context, params *protocol.ExecuteCommandParams, s Interface) (interface{}, error) {
30005-	switch params.Command {
30006-	case "gopls.add_dependency":
30007-		var a0 DependencyArgs
30008-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30009-			return nil, err
30010-		}
30011-		return nil, s.AddDependency(ctx, a0)
30012-	case "gopls.add_import":
30013-		var a0 AddImportArgs
30014-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30015-			return nil, err
30016-		}
30017-		return nil, s.AddImport(ctx, a0)
30018-	case "gopls.apply_fix":
30019-		var a0 ApplyFixArgs
30020-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30021-			return nil, err
30022-		}
30023-		return nil, s.ApplyFix(ctx, a0)
30024-	case "gopls.check_upgrades":
30025-		var a0 CheckUpgradesArgs
30026-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30027-			return nil, err
30028-		}
30029-		return nil, s.CheckUpgrades(ctx, a0)
30030-	case "gopls.edit_go_directive":
30031-		var a0 EditGoDirectiveArgs
30032-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30033-			return nil, err
30034-		}
30035-		return nil, s.EditGoDirective(ctx, a0)
30036-	case "gopls.fetch_vulncheck_result":
30037-		var a0 URIArg
30038-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30039-			return nil, err
30040-		}
30041-		return s.FetchVulncheckResult(ctx, a0)
30042-	case "gopls.gc_details":
30043-		var a0 protocol.DocumentURI
30044-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30045-			return nil, err
30046-		}
30047-		return nil, s.GCDetails(ctx, a0)
30048-	case "gopls.generate":
30049-		var a0 GenerateArgs
30050-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30051-			return nil, err
30052-		}
30053-		return nil, s.Generate(ctx, a0)
30054-	case "gopls.go_get_package":
30055-		var a0 GoGetPackageArgs
30056-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30057-			return nil, err
30058-		}
30059-		return nil, s.GoGetPackage(ctx, a0)
30060-	case "gopls.list_imports":
30061-		var a0 URIArg
30062-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30063-			return nil, err
30064-		}
30065-		return s.ListImports(ctx, a0)
30066-	case "gopls.list_known_packages":
30067-		var a0 URIArg
30068-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30069-			return nil, err
30070-		}
30071-		return s.ListKnownPackages(ctx, a0)
30072-	case "gopls.mem_stats":
30073-		return s.MemStats(ctx)
30074-	case "gopls.regenerate_cgo":
30075-		var a0 URIArg
30076-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30077-			return nil, err
30078-		}
30079-		return nil, s.RegenerateCgo(ctx, a0)
30080-	case "gopls.remove_dependency":
30081-		var a0 RemoveDependencyArgs
30082-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30083-			return nil, err
30084-		}
30085-		return nil, s.RemoveDependency(ctx, a0)
30086-	case "gopls.reset_go_mod_diagnostics":
30087-		var a0 ResetGoModDiagnosticsArgs
30088-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30089-			return nil, err
30090-		}
30091-		return nil, s.ResetGoModDiagnostics(ctx, a0)
30092-	case "gopls.run_govulncheck":
30093-		var a0 VulncheckArgs
30094-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30095-			return nil, err
30096-		}
30097-		return s.RunGovulncheck(ctx, a0)
30098-	case "gopls.run_tests":
30099-		var a0 RunTestsArgs
30100-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30101-			return nil, err
30102-		}
30103-		return nil, s.RunTests(ctx, a0)
30104-	case "gopls.start_debugging":
30105-		var a0 DebuggingArgs
30106-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30107-			return nil, err
30108-		}
30109-		return s.StartDebugging(ctx, a0)
30110-	case "gopls.test":
30111-		var a0 protocol.DocumentURI
30112-		var a1 []string
30113-		var a2 []string
30114-		if err := UnmarshalArgs(params.Arguments, &a0, &a1, &a2); err != nil {
30115-			return nil, err
30116-		}
30117-		return nil, s.Test(ctx, a0, a1, a2)
30118-	case "gopls.tidy":
30119-		var a0 URIArgs
30120-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30121-			return nil, err
30122-		}
30123-		return nil, s.Tidy(ctx, a0)
30124-	case "gopls.toggle_gc_details":
30125-		var a0 URIArg
30126-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30127-			return nil, err
30128-		}
30129-		return nil, s.ToggleGCDetails(ctx, a0)
30130-	case "gopls.update_go_sum":
30131-		var a0 URIArgs
30132-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30133-			return nil, err
30134-		}
30135-		return nil, s.UpdateGoSum(ctx, a0)
30136-	case "gopls.upgrade_dependency":
30137-		var a0 DependencyArgs
30138-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30139-			return nil, err
30140-		}
30141-		return nil, s.UpgradeDependency(ctx, a0)
30142-	case "gopls.vendor":
30143-		var a0 URIArg
30144-		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
30145-			return nil, err
30146-		}
30147-		return nil, s.Vendor(ctx, a0)
30148-	}
30149-	return nil, fmt.Errorf("unsupported command %q", params.Command)
30150-}
30151-
30152-func NewAddDependencyCommand(title string, a0 DependencyArgs) (protocol.Command, error) {
30153-	args, err := MarshalArgs(a0)
30154-	if err != nil {
30155-		return protocol.Command{}, err
30156-	}
30157-	return protocol.Command{
30158-		Title:     title,
30159-		Command:   "gopls.add_dependency",
30160-		Arguments: args,
30161-	}, nil
30162-}
30163-
30164-func NewAddImportCommand(title string, a0 AddImportArgs) (protocol.Command, error) {
30165-	args, err := MarshalArgs(a0)
30166-	if err != nil {
30167-		return protocol.Command{}, err
30168-	}
30169-	return protocol.Command{
30170-		Title:     title,
30171-		Command:   "gopls.add_import",
30172-		Arguments: args,
30173-	}, nil
30174-}
30175-
30176-func NewApplyFixCommand(title string, a0 ApplyFixArgs) (protocol.Command, error) {
30177-	args, err := MarshalArgs(a0)
30178-	if err != nil {
30179-		return protocol.Command{}, err
30180-	}
30181-	return protocol.Command{
30182-		Title:     title,
30183-		Command:   "gopls.apply_fix",
30184-		Arguments: args,
30185-	}, nil
30186-}
30187-
30188-func NewCheckUpgradesCommand(title string, a0 CheckUpgradesArgs) (protocol.Command, error) {
30189-	args, err := MarshalArgs(a0)
30190-	if err != nil {
30191-		return protocol.Command{}, err
30192-	}
30193-	return protocol.Command{
30194-		Title:     title,
30195-		Command:   "gopls.check_upgrades",
30196-		Arguments: args,
30197-	}, nil
30198-}
30199-
30200-func NewEditGoDirectiveCommand(title string, a0 EditGoDirectiveArgs) (protocol.Command, error) {
30201-	args, err := MarshalArgs(a0)
30202-	if err != nil {
30203-		return protocol.Command{}, err
30204-	}
30205-	return protocol.Command{
30206-		Title:     title,
30207-		Command:   "gopls.edit_go_directive",
30208-		Arguments: args,
30209-	}, nil
30210-}
30211-
30212-func NewFetchVulncheckResultCommand(title string, a0 URIArg) (protocol.Command, error) {
30213-	args, err := MarshalArgs(a0)
30214-	if err != nil {
30215-		return protocol.Command{}, err
30216-	}
30217-	return protocol.Command{
30218-		Title:     title,
30219-		Command:   "gopls.fetch_vulncheck_result",
30220-		Arguments: args,
30221-	}, nil
30222-}
30223-
30224-func NewGCDetailsCommand(title string, a0 protocol.DocumentURI) (protocol.Command, error) {
30225-	args, err := MarshalArgs(a0)
30226-	if err != nil {
30227-		return protocol.Command{}, err
30228-	}
30229-	return protocol.Command{
30230-		Title:     title,
30231-		Command:   "gopls.gc_details",
30232-		Arguments: args,
30233-	}, nil
30234-}
30235-
30236-func NewGenerateCommand(title string, a0 GenerateArgs) (protocol.Command, error) {
30237-	args, err := MarshalArgs(a0)
30238-	if err != nil {
30239-		return protocol.Command{}, err
30240-	}
30241-	return protocol.Command{
30242-		Title:     title,
30243-		Command:   "gopls.generate",
30244-		Arguments: args,
30245-	}, nil
30246-}
30247-
30248-func NewGoGetPackageCommand(title string, a0 GoGetPackageArgs) (protocol.Command, error) {
30249-	args, err := MarshalArgs(a0)
30250-	if err != nil {
30251-		return protocol.Command{}, err
30252-	}
30253-	return protocol.Command{
30254-		Title:     title,
30255-		Command:   "gopls.go_get_package",
30256-		Arguments: args,
30257-	}, nil
30258-}
30259-
30260-func NewListImportsCommand(title string, a0 URIArg) (protocol.Command, error) {
30261-	args, err := MarshalArgs(a0)
30262-	if err != nil {
30263-		return protocol.Command{}, err
30264-	}
30265-	return protocol.Command{
30266-		Title:     title,
30267-		Command:   "gopls.list_imports",
30268-		Arguments: args,
30269-	}, nil
30270-}
30271-
30272-func NewListKnownPackagesCommand(title string, a0 URIArg) (protocol.Command, error) {
30273-	args, err := MarshalArgs(a0)
30274-	if err != nil {
30275-		return protocol.Command{}, err
30276-	}
30277-	return protocol.Command{
30278-		Title:     title,
30279-		Command:   "gopls.list_known_packages",
30280-		Arguments: args,
30281-	}, nil
30282-}
30283-
30284-func NewMemStatsCommand(title string) (protocol.Command, error) {
30285-	args, err := MarshalArgs()
30286-	if err != nil {
30287-		return protocol.Command{}, err
30288-	}
30289-	return protocol.Command{
30290-		Title:     title,
30291-		Command:   "gopls.mem_stats",
30292-		Arguments: args,
30293-	}, nil
30294-}
30295-
30296-func NewRegenerateCgoCommand(title string, a0 URIArg) (protocol.Command, error) {
30297-	args, err := MarshalArgs(a0)
30298-	if err != nil {
30299-		return protocol.Command{}, err
30300-	}
30301-	return protocol.Command{
30302-		Title:     title,
30303-		Command:   "gopls.regenerate_cgo",
30304-		Arguments: args,
30305-	}, nil
30306-}
30307-
30308-func NewRemoveDependencyCommand(title string, a0 RemoveDependencyArgs) (protocol.Command, error) {
30309-	args, err := MarshalArgs(a0)
30310-	if err != nil {
30311-		return protocol.Command{}, err
30312-	}
30313-	return protocol.Command{
30314-		Title:     title,
30315-		Command:   "gopls.remove_dependency",
30316-		Arguments: args,
30317-	}, nil
30318-}
30319-
30320-func NewResetGoModDiagnosticsCommand(title string, a0 ResetGoModDiagnosticsArgs) (protocol.Command, error) {
30321-	args, err := MarshalArgs(a0)
30322-	if err != nil {
30323-		return protocol.Command{}, err
30324-	}
30325-	return protocol.Command{
30326-		Title:     title,
30327-		Command:   "gopls.reset_go_mod_diagnostics",
30328-		Arguments: args,
30329-	}, nil
30330-}
30331-
30332-func NewRunGovulncheckCommand(title string, a0 VulncheckArgs) (protocol.Command, error) {
30333-	args, err := MarshalArgs(a0)
30334-	if err != nil {
30335-		return protocol.Command{}, err
30336-	}
30337-	return protocol.Command{
30338-		Title:     title,
30339-		Command:   "gopls.run_govulncheck",
30340-		Arguments: args,
30341-	}, nil
30342-}
30343-
30344-func NewRunTestsCommand(title string, a0 RunTestsArgs) (protocol.Command, error) {
30345-	args, err := MarshalArgs(a0)
30346-	if err != nil {
30347-		return protocol.Command{}, err
30348-	}
30349-	return protocol.Command{
30350-		Title:     title,
30351-		Command:   "gopls.run_tests",
30352-		Arguments: args,
30353-	}, nil
30354-}
30355-
30356-func NewStartDebuggingCommand(title string, a0 DebuggingArgs) (protocol.Command, error) {
30357-	args, err := MarshalArgs(a0)
30358-	if err != nil {
30359-		return protocol.Command{}, err
30360-	}
30361-	return protocol.Command{
30362-		Title:     title,
30363-		Command:   "gopls.start_debugging",
30364-		Arguments: args,
30365-	}, nil
30366-}
30367-
30368-func NewTestCommand(title string, a0 protocol.DocumentURI, a1 []string, a2 []string) (protocol.Command, error) {
30369-	args, err := MarshalArgs(a0, a1, a2)
30370-	if err != nil {
30371-		return protocol.Command{}, err
30372-	}
30373-	return protocol.Command{
30374-		Title:     title,
30375-		Command:   "gopls.test",
30376-		Arguments: args,
30377-	}, nil
30378-}
30379-
30380-func NewTidyCommand(title string, a0 URIArgs) (protocol.Command, error) {
30381-	args, err := MarshalArgs(a0)
30382-	if err != nil {
30383-		return protocol.Command{}, err
30384-	}
30385-	return protocol.Command{
30386-		Title:     title,
30387-		Command:   "gopls.tidy",
30388-		Arguments: args,
30389-	}, nil
30390-}
30391-
30392-func NewToggleGCDetailsCommand(title string, a0 URIArg) (protocol.Command, error) {
30393-	args, err := MarshalArgs(a0)
30394-	if err != nil {
30395-		return protocol.Command{}, err
30396-	}
30397-	return protocol.Command{
30398-		Title:     title,
30399-		Command:   "gopls.toggle_gc_details",
30400-		Arguments: args,
30401-	}, nil
30402-}
30403-
30404-func NewUpdateGoSumCommand(title string, a0 URIArgs) (protocol.Command, error) {
30405-	args, err := MarshalArgs(a0)
30406-	if err != nil {
30407-		return protocol.Command{}, err
30408-	}
30409-	return protocol.Command{
30410-		Title:     title,
30411-		Command:   "gopls.update_go_sum",
30412-		Arguments: args,
30413-	}, nil
30414-}
30415-
30416-func NewUpgradeDependencyCommand(title string, a0 DependencyArgs) (protocol.Command, error) {
30417-	args, err := MarshalArgs(a0)
30418-	if err != nil {
30419-		return protocol.Command{}, err
30420-	}
30421-	return protocol.Command{
30422-		Title:     title,
30423-		Command:   "gopls.upgrade_dependency",
30424-		Arguments: args,
30425-	}, nil
30426-}
30427-
30428-func NewVendorCommand(title string, a0 URIArg) (protocol.Command, error) {
30429-	args, err := MarshalArgs(a0)
30430-	if err != nil {
30431-		return protocol.Command{}, err
30432-	}
30433-	return protocol.Command{
30434-		Title:     title,
30435-		Command:   "gopls.vendor",
30436-		Arguments: args,
30437-	}, nil
30438-}
30439diff -urN a/gopls/internal/lsp/command/commandmeta/meta.go b/gopls/internal/lsp/command/commandmeta/meta.go
30440--- a/gopls/internal/lsp/command/commandmeta/meta.go	2000-01-01 00:00:00.000000000 -0000
30441+++ b/gopls/internal/lsp/command/commandmeta/meta.go	1970-01-01 00:00:00.000000000 +0000
30442@@ -1,259 +0,0 @@
30443-// Copyright 2021 The Go Authors. All rights reserved.
30444-// Use of this source code is governed by a BSD-style
30445-// license that can be found in the LICENSE file.
30446-
30447-// Package commandmeta provides metadata about LSP commands, by analyzing the
30448-// command.Interface type.
30449-package commandmeta
30450-
30451-import (
30452-	"fmt"
30453-	"go/ast"
30454-	"go/token"
30455-	"go/types"
30456-	"reflect"
30457-	"strings"
30458-	"unicode"
30459-
30460-	"golang.org/x/tools/go/ast/astutil"
30461-	"golang.org/x/tools/go/packages"
30462-	"golang.org/x/tools/gopls/internal/lsp/command"
30463-)
30464-
30465-type Command struct {
30466-	MethodName string
30467-	Name       string
30468-	// TODO(rFindley): I think Title can actually be eliminated. In all cases
30469-	// where we use it, there is probably a more appropriate contextual title.
30470-	Title  string
30471-	Doc    string
30472-	Args   []*Field
30473-	Result *Field
30474-}
30475-
30476-func (c *Command) ID() string {
30477-	return command.ID(c.Name)
30478-}
30479-
30480-type Field struct {
30481-	Name     string
30482-	Doc      string
30483-	JSONTag  string
30484-	Type     types.Type
30485-	FieldMod string
30486-	// In some circumstances, we may want to recursively load additional field
30487-	// descriptors for fields of struct types, documenting their internals.
30488-	Fields []*Field
30489-}
30490-
30491-func Load() (*packages.Package, []*Command, error) {
30492-	pkgs, err := packages.Load(
30493-		&packages.Config{
30494-			Mode:       packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedImports | packages.NeedDeps,
30495-			BuildFlags: []string{"-tags=generate"},
30496-		},
30497-		"golang.org/x/tools/gopls/internal/lsp/command",
30498-	)
30499-	if err != nil {
30500-		return nil, nil, fmt.Errorf("packages.Load: %v", err)
30501-	}
30502-	pkg := pkgs[0]
30503-	if len(pkg.Errors) > 0 {
30504-		return pkg, nil, pkg.Errors[0]
30505-	}
30506-
30507-	// For a bit of type safety, use reflection to get the interface name within
30508-	// the package scope.
30509-	it := reflect.TypeOf((*command.Interface)(nil)).Elem()
30510-	obj := pkg.Types.Scope().Lookup(it.Name()).Type().Underlying().(*types.Interface)
30511-
30512-	// Load command metadata corresponding to each interface method.
30513-	var commands []*Command
30514-	loader := fieldLoader{make(map[types.Object]*Field)}
30515-	for i := 0; i < obj.NumMethods(); i++ {
30516-		m := obj.Method(i)
30517-		c, err := loader.loadMethod(pkg, m)
30518-		if err != nil {
30519-			return nil, nil, fmt.Errorf("loading %s: %v", m.Name(), err)
30520-		}
30521-		commands = append(commands, c)
30522-	}
30523-	return pkg, commands, nil
30524-}
30525-
30526-// fieldLoader loads field information, memoizing results to prevent infinite
30527-// recursion.
30528-type fieldLoader struct {
30529-	loaded map[types.Object]*Field
30530-}
30531-
30532-var universeError = types.Universe.Lookup("error").Type()
30533-
30534-func (l *fieldLoader) loadMethod(pkg *packages.Package, m *types.Func) (*Command, error) {
30535-	node, err := findField(pkg, m.Pos())
30536-	if err != nil {
30537-		return nil, err
30538-	}
30539-	title, doc := splitDoc(node.Doc.Text())
30540-	c := &Command{
30541-		MethodName: m.Name(),
30542-		Name:       lspName(m.Name()),
30543-		Doc:        doc,
30544-		Title:      title,
30545-	}
30546-	sig := m.Type().Underlying().(*types.Signature)
30547-	rlen := sig.Results().Len()
30548-	if rlen > 2 || rlen == 0 {
30549-		return nil, fmt.Errorf("must have 1 or 2 returns, got %d", rlen)
30550-	}
30551-	finalResult := sig.Results().At(rlen - 1)
30552-	if !types.Identical(finalResult.Type(), universeError) {
30553-		return nil, fmt.Errorf("final return must be error")
30554-	}
30555-	if rlen == 2 {
30556-		obj := sig.Results().At(0)
30557-		c.Result, err = l.loadField(pkg, obj, "", "")
30558-		if err != nil {
30559-			return nil, err
30560-		}
30561-	}
30562-	for i := 0; i < sig.Params().Len(); i++ {
30563-		obj := sig.Params().At(i)
30564-		fld, err := l.loadField(pkg, obj, "", "")
30565-		if err != nil {
30566-			return nil, err
30567-		}
30568-		if i == 0 {
30569-			// Lazy check that the first argument is a context. We could relax this,
30570-			// but then the generated code gets more complicated.
30571-			if named, ok := fld.Type.(*types.Named); !ok || named.Obj().Name() != "Context" || named.Obj().Pkg().Path() != "context" {
30572-				return nil, fmt.Errorf("first method parameter must be context.Context")
30573-			}
30574-			// Skip the context argument, as it is implied.
30575-			continue
30576-		}
30577-		c.Args = append(c.Args, fld)
30578-	}
30579-	return c, nil
30580-}
30581-
30582-func (l *fieldLoader) loadField(pkg *packages.Package, obj *types.Var, doc, tag string) (*Field, error) {
30583-	if existing, ok := l.loaded[obj]; ok {
30584-		return existing, nil
30585-	}
30586-	fld := &Field{
30587-		Name:    obj.Name(),
30588-		Doc:     strings.TrimSpace(doc),
30589-		Type:    obj.Type(),
30590-		JSONTag: reflect.StructTag(tag).Get("json"),
30591-	}
30592-	under := fld.Type.Underlying()
30593-	// Quick-and-dirty handling for various underlying types.
30594-	switch p := under.(type) {
30595-	case *types.Pointer:
30596-		under = p.Elem().Underlying()
30597-	case *types.Array:
30598-		under = p.Elem().Underlying()
30599-		fld.FieldMod = fmt.Sprintf("[%d]", p.Len())
30600-	case *types.Slice:
30601-		under = p.Elem().Underlying()
30602-		fld.FieldMod = "[]"
30603-	}
30604-
30605-	if s, ok := under.(*types.Struct); ok {
30606-		for i := 0; i < s.NumFields(); i++ {
30607-			obj2 := s.Field(i)
30608-			pkg2 := pkg
30609-			if obj2.Pkg() != pkg2.Types {
30610-				pkg2, ok = pkg.Imports[obj2.Pkg().Path()]
30611-				if !ok {
30612-					return nil, fmt.Errorf("missing import for %q: %q", pkg.ID, obj2.Pkg().Path())
30613-				}
30614-			}
30615-			node, err := findField(pkg2, obj2.Pos())
30616-			if err != nil {
30617-				return nil, err
30618-			}
30619-			tag := s.Tag(i)
30620-			structField, err := l.loadField(pkg2, obj2, node.Doc.Text(), tag)
30621-			if err != nil {
30622-				return nil, err
30623-			}
30624-			fld.Fields = append(fld.Fields, structField)
30625-		}
30626-	}
30627-	return fld, nil
30628-}
30629-
30630-// splitDoc parses a command doc string to separate the title from normal
30631-// documentation.
30632-//
30633-// The doc comment should be of the form: "MethodName: Title\nDocumentation"
30634-func splitDoc(text string) (title, doc string) {
30635-	docParts := strings.SplitN(text, "\n", 2)
30636-	titleParts := strings.SplitN(docParts[0], ":", 2)
30637-	if len(titleParts) > 1 {
30638-		title = strings.TrimSpace(titleParts[1])
30639-	}
30640-	if len(docParts) > 1 {
30641-		doc = strings.TrimSpace(docParts[1])
30642-	}
30643-	return title, doc
30644-}
30645-
30646-// lspName returns the normalized command name to use in the LSP.
30647-func lspName(methodName string) string {
30648-	words := splitCamel(methodName)
30649-	for i := range words {
30650-		words[i] = strings.ToLower(words[i])
30651-	}
30652-	return strings.Join(words, "_")
30653-}
30654-
30655-// splitCamel splits s into words, according to camel-case word boundaries.
30656-// Initialisms are grouped as a single word.
30657-//
30658-// For example:
30659-//
30660-//	"RunTests" -> []string{"Run", "Tests"}
30661-//	"GCDetails" -> []string{"GC", "Details"}
30662-func splitCamel(s string) []string {
30663-	var words []string
30664-	for len(s) > 0 {
30665-		last := strings.LastIndexFunc(s, unicode.IsUpper)
30666-		if last < 0 {
30667-			last = 0
30668-		}
30669-		if last == len(s)-1 {
30670-			// Group initialisms as a single word.
30671-			last = 1 + strings.LastIndexFunc(s[:last], func(r rune) bool { return !unicode.IsUpper(r) })
30672-		}
30673-		words = append(words, s[last:])
30674-		s = s[:last]
30675-	}
30676-	for i := 0; i < len(words)/2; i++ {
30677-		j := len(words) - i - 1
30678-		words[i], words[j] = words[j], words[i]
30679-	}
30680-	return words
30681-}
30682-
30683-// findField finds the struct field or interface method positioned at pos,
30684-// within the AST.
30685-func findField(pkg *packages.Package, pos token.Pos) (*ast.Field, error) {
30686-	fset := pkg.Fset
30687-	var file *ast.File
30688-	for _, f := range pkg.Syntax {
30689-		if fset.File(f.Pos()).Name() == fset.File(pos).Name() {
30690-			file = f
30691-			break
30692-		}
30693-	}
30694-	if file == nil {
30695-		return nil, fmt.Errorf("no file for pos %v", pos)
30696-	}
30697-	path, _ := astutil.PathEnclosingInterval(file, pos, pos)
30698-	// This is fragile, but in the cases we care about, the field will be in
30699-	// path[1].
30700-	return path[1].(*ast.Field), nil
30701-}
30702diff -urN a/gopls/internal/lsp/command/gen/gen.go b/gopls/internal/lsp/command/gen/gen.go
30703--- a/gopls/internal/lsp/command/gen/gen.go	2000-01-01 00:00:00.000000000 -0000
30704+++ b/gopls/internal/lsp/command/gen/gen.go	1970-01-01 00:00:00.000000000 +0000
30705@@ -1,155 +0,0 @@
30706-// Copyright 2021 The Go Authors. All rights reserved.
30707-// Use of this source code is governed by a BSD-style
30708-// license that can be found in the LICENSE file.
30709-
30710-// Package gen is used to generate command bindings from the gopls command
30711-// interface.
30712-package gen
30713-
30714-import (
30715-	"bytes"
30716-	"fmt"
30717-	"go/types"
30718-	"text/template"
30719-
30720-	"golang.org/x/tools/internal/imports"
30721-	"golang.org/x/tools/gopls/internal/lsp/command/commandmeta"
30722-)
30723-
30724-const src = `// Copyright 2021 The Go Authors. All rights reserved.
30725-// Use of this source code is governed by a BSD-style
30726-// license that can be found in the LICENSE file.
30727-
30728-// Don't include this file during code generation, or it will break the build
30729-// if existing interface methods have been modified.
30730-//go:build !generate
30731-// +build !generate
30732-
30733-package command
30734-
30735-// Code generated by generate.go. DO NOT EDIT.
30736-
30737-import (
30738-	{{range $k, $v := .Imports -}}
30739-	"{{$k}}"
30740-	{{end}}
30741-)
30742-
30743-const (
30744-{{- range .Commands}}
30745-	{{.MethodName}} Command = "{{.Name}}"
30746-{{- end}}
30747-)
30748-
30749-var Commands = []Command {
30750-{{- range .Commands}}
30751-	{{.MethodName}},
30752-{{- end}}
30753-}
30754-
30755-func Dispatch(ctx context.Context, params *protocol.ExecuteCommandParams, s Interface) (interface{}, error) {
30756-	switch params.Command {
30757-	{{- range .Commands}}
30758-	case "{{.ID}}":
30759-		{{- if .Args -}}
30760-			{{- range $i, $v := .Args}}
30761-		var a{{$i}} {{typeString $v.Type}}
30762-			{{- end}}
30763-		if err := UnmarshalArgs(params.Arguments{{range $i, $v := .Args}}, &a{{$i}}{{end}}); err != nil {
30764-			return nil, err
30765-		}
30766-		{{end -}}
30767-		return {{if not .Result}}nil, {{end}}s.{{.MethodName}}(ctx{{range $i, $v := .Args}}, a{{$i}}{{end}})
30768-	{{- end}}
30769-	}
30770-	return nil, fmt.Errorf("unsupported command %q", params.Command)
30771-}
30772-{{- range .Commands}}
30773-
30774-func New{{.MethodName}}Command(title string, {{range $i, $v := .Args}}{{if $i}}, {{end}}a{{$i}} {{typeString $v.Type}}{{end}}) (protocol.Command, error) {
30775-	args, err := MarshalArgs({{range $i, $v := .Args}}{{if $i}}, {{end}}a{{$i}}{{end}})
30776-	if err != nil {
30777-		return protocol.Command{}, err
30778-	}
30779-	return protocol.Command{
30780-		Title: title,
30781-		Command: "{{.ID}}",
30782-		Arguments: args,
30783-	}, nil
30784-}
30785-{{end}}
30786-`
30787-
30788-type data struct {
30789-	Imports  map[string]bool
30790-	Commands []*commandmeta.Command
30791-}
30792-
30793-func Generate() ([]byte, error) {
30794-	pkg, cmds, err := commandmeta.Load()
30795-	if err != nil {
30796-		return nil, fmt.Errorf("loading command data: %v", err)
30797-	}
30798-	qf := func(p *types.Package) string {
30799-		if p == pkg.Types {
30800-			return ""
30801-		}
30802-		return p.Name()
30803-	}
30804-	tmpl, err := template.New("").Funcs(template.FuncMap{
30805-		"typeString": func(t types.Type) string {
30806-			return types.TypeString(t, qf)
30807-		},
30808-	}).Parse(src)
30809-	if err != nil {
30810-		return nil, err
30811-	}
30812-	d := data{
30813-		Commands: cmds,
30814-		Imports: map[string]bool{
30815-			"context": true,
30816-			"fmt":     true,
30817-			"golang.org/x/tools/gopls/internal/lsp/protocol": true,
30818-		},
30819-	}
30820-	const thispkg = "golang.org/x/tools/gopls/internal/lsp/command"
30821-	for _, c := range d.Commands {
30822-		for _, arg := range c.Args {
30823-			pth := pkgPath(arg.Type)
30824-			if pth != "" && pth != thispkg {
30825-				d.Imports[pth] = true
30826-			}
30827-		}
30828-		if c.Result != nil {
30829-			pth := pkgPath(c.Result.Type)
30830-			if pth != "" && pth != thispkg {
30831-				d.Imports[pth] = true
30832-			}
30833-		}
30834-	}
30835-
30836-	var buf bytes.Buffer
30837-	if err := tmpl.Execute(&buf, d); err != nil {
30838-		return nil, fmt.Errorf("executing: %v", err)
30839-	}
30840-
30841-	opts := &imports.Options{
30842-		AllErrors:  true,
30843-		FormatOnly: true,
30844-		Comments:   true,
30845-	}
30846-	content, err := imports.Process("", buf.Bytes(), opts)
30847-	if err != nil {
30848-		return nil, fmt.Errorf("goimports: %v", err)
30849-	}
30850-	return content, nil
30851-}
30852-
30853-func pkgPath(t types.Type) string {
30854-	if n, ok := t.(*types.Named); ok {
30855-		if pkg := n.Obj().Pkg(); pkg != nil {
30856-			return pkg.Path()
30857-		}
30858-	}
30859-	return ""
30860-}
30861diff -urN a/gopls/internal/lsp/command/generate.go b/gopls/internal/lsp/command/generate.go
30862--- a/gopls/internal/lsp/command/generate.go	2000-01-01 00:00:00.000000000 -0000
30863+++ b/gopls/internal/lsp/command/generate.go	1970-01-01 00:00:00.000000000 +0000
30864@@ -1,25 +0,0 @@
30865-// Copyright 2021 The Go Authors. All rights reserved.
30866-// Use of this source code is governed by a BSD-style
30867-// license that can be found in the LICENSE file.
30868-
30869-//go:build ignore
30870-// +build ignore
30871-
30872-package main
30873-
30874-import (
30875-	"log"
30876-	"os"
30877-
30878-	"golang.org/x/tools/gopls/internal/lsp/command/gen"
30879-)
30880-
30881-func main() {
30882-	content, err := gen.Generate()
30883-	if err != nil {
30884-		log.Fatal(err)
30885-	}
30886-	if err := os.WriteFile("command_gen.go", content, 0644); err != nil {
30887-		log.Fatal(err)
30888-	}
30889-}
30890diff -urN a/gopls/internal/lsp/command/interface.go b/gopls/internal/lsp/command/interface.go
30891--- a/gopls/internal/lsp/command/interface.go	2000-01-01 00:00:00.000000000 -0000
30892+++ b/gopls/internal/lsp/command/interface.go	1970-01-01 00:00:00.000000000 +0000
30893@@ -1,410 +0,0 @@
30894-// Copyright 2021 The Go Authors. All rights reserved.
30895-// Use of this source code is governed by a BSD-style
30896-// license that can be found in the LICENSE file.
30897-
30898-//go:generate go run -tags=generate generate.go
30899-
30900-// Package command defines the interface provided by gopls for the
30901-// workspace/executeCommand LSP request.
30902-//
30903-// This interface is fully specified by the Interface type, provided it
30904-// conforms to the restrictions outlined in its doc string.
30905-//
30906-// Bindings for server-side command dispatch and client-side serialization are
30907-// also provided by this package, via code generation.
30908-package command
30909-
30910-import (
30911-	"context"
30912-
30913-	"golang.org/x/tools/gopls/internal/govulncheck"
30914-	"golang.org/x/tools/gopls/internal/lsp/protocol"
30915-)
30916-
30917-// Interface defines the interface gopls exposes for the
30918-// workspace/executeCommand request.
30919-//
30920-// This interface is used to generate marshaling/unmarshaling code, dispatch,
30921-// and documentation, and so has some additional restrictions:
30922-//  1. All method arguments must be JSON serializable.
30923-//  2. Methods must return either error or (T, error), where T is a
30924-//     JSON serializable type.
30925-//  3. The first line of the doc string is special. Everything after the colon
30926-//     is considered the command 'Title'.
30927-//     TODO(rFindley): reconsider this -- Title may be unnecessary.
30928-type Interface interface {
30929-	// ApplyFix: Apply a fix
30930-	//
30931-	// Applies a fix to a region of source code.
30932-	ApplyFix(context.Context, ApplyFixArgs) error
30933-	// Test: Run test(s) (legacy)
30934-	//
30935-	// Runs `go test` for a specific set of test or benchmark functions.
30936-	Test(context.Context, protocol.DocumentURI, []string, []string) error
30937-
30938-	// TODO: deprecate Test in favor of RunTests below.
30939-
30940-	// Test: Run test(s)
30941-	//
30942-	// Runs `go test` for a specific set of test or benchmark functions.
30943-	RunTests(context.Context, RunTestsArgs) error
30944-
30945-	// Generate: Run go generate
30946-	//
30947-	// Runs `go generate` for a given directory.
30948-	Generate(context.Context, GenerateArgs) error
30949-
30950-	// RegenerateCgo: Regenerate cgo
30951-	//
30952-	// Regenerates cgo definitions.
30953-	RegenerateCgo(context.Context, URIArg) error
30954-
30955-	// Tidy: Run go mod tidy
30956-	//
30957-	// Runs `go mod tidy` for a module.
30958-	Tidy(context.Context, URIArgs) error
30959-
30960-	// Vendor: Run go mod vendor
30961-	//
30962-	// Runs `go mod vendor` for a module.
30963-	Vendor(context.Context, URIArg) error
30964-
30965-	// EditGoDirective: Run go mod edit -go=version
30966-	//
30967-	// Runs `go mod edit -go=version` for a module.
30968-	EditGoDirective(context.Context, EditGoDirectiveArgs) error
30969-
30970-	// UpdateGoSum: Update go.sum
30971-	//
30972-	// Updates the go.sum file for a module.
30973-	UpdateGoSum(context.Context, URIArgs) error
30974-
30975-	// CheckUpgrades: Check for upgrades
30976-	//
30977-	// Checks for module upgrades.
30978-	CheckUpgrades(context.Context, CheckUpgradesArgs) error
30979-
30980-	// AddDependency: Add a dependency
30981-	//
30982-	// Adds a dependency to the go.mod file for a module.
30983-	AddDependency(context.Context, DependencyArgs) error
30984-
30985-	// UpgradeDependency: Upgrade a dependency
30986-	//
30987-	// Upgrades a dependency in the go.mod file for a module.
30988-	UpgradeDependency(context.Context, DependencyArgs) error
30989-
30990-	// RemoveDependency: Remove a dependency
30991-	//
30992-	// Removes a dependency from the go.mod file of a module.
30993-	RemoveDependency(context.Context, RemoveDependencyArgs) error
30994-
30995-	// ResetGoModDiagnostics: Reset go.mod diagnostics
30996-	//
30997-	// Reset diagnostics in the go.mod file of a module.
30998-	ResetGoModDiagnostics(context.Context, ResetGoModDiagnosticsArgs) error
30999-
31000-	// GoGetPackage: go get a package
31001-	//
31002-	// Runs `go get` to fetch a package.
31003-	GoGetPackage(context.Context, GoGetPackageArgs) error
31004-
31005-	// GCDetails: Toggle gc_details
31006-	//
31007-	// Toggle the calculation of gc annotations.
31008-	GCDetails(context.Context, protocol.DocumentURI) error
31009-
31010-	// TODO: deprecate GCDetails in favor of ToggleGCDetails below.
31011-
31012-	// ToggleGCDetails: Toggle gc_details
31013-	//
31014-	// Toggle the calculation of gc annotations.
31015-	ToggleGCDetails(context.Context, URIArg) error
31016-
31017-	// ListKnownPackages: List known packages
31018-	//
31019-	// Retrieve a list of packages that are importable from the given URI.
31020-	ListKnownPackages(context.Context, URIArg) (ListKnownPackagesResult, error)
31021-
31022-	// ListImports: List imports of a file and its package
31023-	//
31024-	// Retrieve a list of imports in the given Go file, and the package it
31025-	// belongs to.
31026-	ListImports(context.Context, URIArg) (ListImportsResult, error)
31027-
31028-	// AddImport: Add an import
31029-	//
31030-	// Ask the server to add an import path to a given Go file.  The method will
31031-	// call applyEdit on the client so that clients don't have to apply the edit
31032-	// themselves.
31033-	AddImport(context.Context, AddImportArgs) error
31034-
31035-	// StartDebugging: Start the gopls debug server
31036-	//
31037-	// Start the gopls debug server if it isn't running, and return the debug
31038-	// address.
31039-	StartDebugging(context.Context, DebuggingArgs) (DebuggingResult, error)
31040-
31041-	// RunGovulncheck: Run govulncheck.
31042-	//
31043-	// Run vulnerability check (`govulncheck`).
31044-	RunGovulncheck(context.Context, VulncheckArgs) (RunVulncheckResult, error)
31045-
31046-	// FetchVulncheckResult: Get known vulncheck result
31047-	//
31048-	// Fetch the result of latest vulnerability check (`govulncheck`).
31049-	FetchVulncheckResult(context.Context, URIArg) (map[protocol.DocumentURI]*govulncheck.Result, error)
31050-
31051-	// MemStats: fetch memory statistics
31052-	//
31053-	// Call runtime.GC multiple times and return memory statistics as reported by
31054-	// runtime.MemStats.
31055-	//
31056-	// This command is used for benchmarking, and may change in the future.
31057-	MemStats(context.Context) (MemStatsResult, error)
31058-}
31059-
31060-type RunTestsArgs struct {
31061-	// The test file containing the tests to run.
31062-	URI protocol.DocumentURI
31063-
31064-	// Specific test names to run, e.g. TestFoo.
31065-	Tests []string
31066-
31067-	// Specific benchmarks to run, e.g. BenchmarkFoo.
31068-	Benchmarks []string
31069-}
31070-
31071-type GenerateArgs struct {
31072-	// URI for the directory to generate.
31073-	Dir protocol.DocumentURI
31074-
31075-	// Whether to generate recursively (go generate ./...)
31076-	Recursive bool
31077-}
31078-
31079-// TODO(rFindley): document the rest of these once the docgen is fleshed out.
31080-
31081-type ApplyFixArgs struct {
31082-	// The fix to apply.
31083-	Fix string
31084-	// The file URI for the document to fix.
31085-	URI protocol.DocumentURI
31086-	// The document range to scan for fixes.
31087-	Range protocol.Range
31088-}
31089-
31090-type URIArg struct {
31091-	// The file URI.
31092-	URI protocol.DocumentURI
31093-}
31094-
31095-type URIArgs struct {
31096-	// The file URIs.
31097-	URIs []protocol.DocumentURI
31098-}
31099-
31100-type CheckUpgradesArgs struct {
31101-	// The go.mod file URI.
31102-	URI protocol.DocumentURI
31103-	// The modules to check.
31104-	Modules []string
31105-}
31106-
31107-type DependencyArgs struct {
31108-	// The go.mod file URI.
31109-	URI protocol.DocumentURI
31110-	// Additional args to pass to the go command.
31111-	GoCmdArgs []string
31112-	// Whether to add a require directive.
31113-	AddRequire bool
31114-}
31115-
31116-type RemoveDependencyArgs struct {
31117-	// The go.mod file URI.
31118-	URI protocol.DocumentURI
31119-	// The module path to remove.
31120-	ModulePath     string
31121-	OnlyDiagnostic bool
31122-}
31123-
31124-type EditGoDirectiveArgs struct {
31125-	// Any document URI within the relevant module.
31126-	URI protocol.DocumentURI
31127-	// The version to pass to `go mod edit -go`.
31128-	Version string
31129-}
31130-
31131-type GoGetPackageArgs struct {
31132-	// Any document URI within the relevant module.
31133-	URI protocol.DocumentURI
31134-	// The package to go get.
31135-	Pkg        string
31136-	AddRequire bool
31137-}
31138-
31139-type AddImportArgs struct {
31140-	// ImportPath is the target import path that should
31141-	// be added to the URI file
31142-	ImportPath string
31143-	// URI is the file that the ImportPath should be
31144-	// added to
31145-	URI protocol.DocumentURI
31146-}
31147-
31148-type ListKnownPackagesResult struct {
31149-	// Packages is a list of packages relative
31150-	// to the URIArg passed by the command request.
31151-	// In other words, it omits paths that are already
31152-	// imported or cannot be imported due to compiler
31153-	// restrictions.
31154-	Packages []string
31155-}
31156-
31157-type ListImportsResult struct {
31158-	// Imports is a list of imports in the requested file.
31159-	Imports []FileImport
31160-
31161-	// PackageImports is a list of all imports in the requested file's package.
31162-	PackageImports []PackageImport
31163-}
31164-
31165-type FileImport struct {
31166-	// Path is the import path of the import.
31167-	Path string
31168-	// Name is the name of the import, e.g. `foo` in `import foo "strings"`.
31169-	Name string
31170-}
31171-
31172-type PackageImport struct {
31173-	// Path is the import path of the import.
31174-	Path string
31175-}
31176-
31177-type DebuggingArgs struct {
31178-	// Optional: the address (including port) for the debug server to listen on.
31179-	// If not provided, the debug server will bind to "localhost:0", and the
31180-	// full debug URL will be contained in the result.
31181-	//
31182-	// If there is more than one gopls instance along the serving path (i.e. you
31183-	// are using a daemon), each gopls instance will attempt to start debugging.
31184-	// If Addr specifies a port, only the daemon will be able to bind to that
31185-	// port, and each intermediate gopls instance will fail to start debugging.
31186-	// For this reason it is recommended not to specify a port (or equivalently,
31187-	// to specify ":0").
31188-	//
31189-	// If the server was already debugging this field has no effect, and the
31190-	// result will contain the previously configured debug URL(s).
31191-	Addr string
31192-}
31193-
31194-type DebuggingResult struct {
31195-	// The URLs to use to access the debug servers, for all gopls instances in
31196-	// the serving path. For the common case of a single gopls instance (i.e. no
31197-	// daemon), this will be exactly one address.
31198-	//
31199-	// In the case of one or more gopls instances forwarding the LSP to a daemon,
31200-	// URLs will contain debug addresses for each server in the serving path, in
31201-	// serving order. The daemon debug address will be the last entry in the
31202-	// slice. If any intermediate gopls instance fails to start debugging, no
31203-	// error will be returned but the debug URL for that server in the URLs slice
31204-	// will be empty.
31205-	URLs []string
31206-}
31207-
31208-type ResetGoModDiagnosticsArgs struct {
31209-	URIArg
31210-
31211-	// Optional: source of the diagnostics to reset.
31212-	// If not set, all resettable go.mod diagnostics will be cleared.
31213-	DiagnosticSource string
31214-}
31215-
31216-type VulncheckArgs struct {
31217-	// Any document in the directory from which govulncheck will run.
31218-	URI protocol.DocumentURI
31219-
31220-	// Package pattern. E.g. "", ".", "./...".
31221-	Pattern string
31222-
31223-	// TODO: -tests
31224-}
31225-
31226-// RunVulncheckResult holds the result of asynchronously starting the vulncheck
31227-// command.
31228-type RunVulncheckResult struct {
31229-	// Token holds the progress token for LSP workDone reporting of the vulncheck
31230-	// invocation.
31231-	Token protocol.ProgressToken
31232-}
31233-
31234-type VulncheckResult struct {
31235-	Vuln []Vuln
31236-
31237-	// TODO: Text string format output?
31238-}
31239-
31240-// CallStack models a trace of function calls starting
31241-// with a client function or method and ending with a
31242-// call to a vulnerable symbol.
31243-type CallStack []StackEntry
31244-
31245-// StackEntry models an element of a call stack.
31246-type StackEntry struct {
31247-	// See golang.org/x/exp/vulncheck.StackEntry.
31248-
31249-	// User-friendly representation of function/method names.
31250-	// e.g. package.funcName, package.(recvType).methodName, ...
31251-	Name string
31252-	URI  protocol.DocumentURI
31253-	Pos  protocol.Position // Start position. (0-based. Column is always 0)
31254-}
31255-
31256-// Vuln models an osv.Entry and representative call stacks.
31257-// TODO: deprecate
31258-type Vuln struct {
31259-	// ID is the vulnerability ID (osv.Entry.ID).
31260-	// https://ossf.github.io/osv-schema/#id-modified-fields
31261-	ID string
31262-	// Details is the description of the vulnerability (osv.Entry.Details).
31263-	// https://ossf.github.io/osv-schema/#summary-details-fields
31264-	Details string `json:",omitempty"`
31265-	// Aliases are alternative IDs of the vulnerability.
31266-	// https://ossf.github.io/osv-schema/#aliases-field
31267-	Aliases []string `json:",omitempty"`
31268-
31269-	// Symbol is the name of the detected vulnerable function or method.
31270-	// Can be empty if the vulnerability exists in required modules, but no vulnerable symbols are used.
31271-	Symbol string `json:",omitempty"`
31272-	// PkgPath is the package path of the detected Symbol.
31273-	// Can be empty if the vulnerability exists in required modules, but no vulnerable packages are used.
31274-	PkgPath string `json:",omitempty"`
31275-	// ModPath is the module path corresponding to PkgPath.
31276-	// TODO: how do we specify standard library's vulnerability?
31277-	ModPath string `json:",omitempty"`
31278-
31279-	// URL is the URL for more info about the information.
31280-	// Either the database specific URL or the one of the URLs
31281-	// included in osv.Entry.References.
31282-	URL string `json:",omitempty"`
31283-
31284-	// Current is the current module version.
31285-	CurrentVersion string `json:",omitempty"`
31286-
31287-	// Fixed is the minimum module version that contains the fix.
31288-	FixedVersion string `json:",omitempty"`
31289-
31290-	// Example call stacks.
31291-	CallStacks []CallStack `json:",omitempty"`
31292-
31293-	// Short description of each call stack in CallStacks.
31294-	CallStackSummaries []string `json:",omitempty"`
31295-
31296-	// TODO: import graph & module graph.
31297-}
31298-
31299-// MemStatsResult holds selected fields from runtime.MemStats.
31300-type MemStatsResult struct {
31301-	HeapAlloc uint64
31302-	HeapInUse uint64
31303-}
31304diff -urN a/gopls/internal/lsp/command/interface_test.go b/gopls/internal/lsp/command/interface_test.go
31305--- a/gopls/internal/lsp/command/interface_test.go	2000-01-01 00:00:00.000000000 -0000
31306+++ b/gopls/internal/lsp/command/interface_test.go	1970-01-01 00:00:00.000000000 +0000
31307@@ -1,31 +0,0 @@
31308-// Copyright 2021 The Go Authors. All rights reserved.
31309-// Use of this source code is governed by a BSD-style
31310-// license that can be found in the LICENSE file.
31311-
31312-package command_test
31313-
31314-import (
31315-	"io/ioutil"
31316-	"testing"
31317-
31318-	"github.com/google/go-cmp/cmp"
31319-	"golang.org/x/tools/gopls/internal/lsp/command/gen"
31320-	"golang.org/x/tools/internal/testenv"
31321-)
31322-
31323-func TestGenerated(t *testing.T) {
31324-	testenv.NeedsGoBuild(t) // This is a lie. We actually need the source code.
31325-
31326-	onDisk, err := ioutil.ReadFile("command_gen.go")
31327-	if err != nil {
31328-		t.Fatal(err)
31329-	}
31330-
31331-	generated, err := gen.Generate()
31332-	if err != nil {
31333-		t.Fatal(err)
31334-	}
31335-	if diff := cmp.Diff(string(generated), string(onDisk)); diff != "" {
31336-		t.Errorf("command_gen.go is stale -- regenerate (-generated +on disk)\n%s", diff)
31337-	}
31338-}
31339diff -urN a/gopls/internal/lsp/command/util.go b/gopls/internal/lsp/command/util.go
31340--- a/gopls/internal/lsp/command/util.go	2000-01-01 00:00:00.000000000 -0000
31341+++ b/gopls/internal/lsp/command/util.go	1970-01-01 00:00:00.000000000 +0000
31342@@ -1,63 +0,0 @@
31343-// Copyright 2021 The Go Authors. All rights reserved.
31344-// Use of this source code is governed by a BSD-style
31345-// license that can be found in the LICENSE file.
31346-
31347-package command
31348-
31349-import (
31350-	"encoding/json"
31351-	"fmt"
31352-)
31353-
31354-// ID returns the command name for use in the LSP.
31355-func ID(name string) string {
31356-	return "gopls." + name
31357-}
31358-
31359-type Command string
31360-
31361-func (c Command) ID() string {
31362-	return ID(string(c))
31363-}
31364-
31365-// MarshalArgs encodes the given arguments to json.RawMessages. This function
31366-// is used to construct arguments to a protocol.Command.
31367-//
31368-// Example usage:
31369-//
31370-//	jsonArgs, err := MarshalArgs(1, "hello", true, StructuredArg{42, 12.6})
31371-func MarshalArgs(args ...interface{}) ([]json.RawMessage, error) {
31372-	var out []json.RawMessage
31373-	for _, arg := range args {
31374-		argJSON, err := json.Marshal(arg)
31375-		if err != nil {
31376-			return nil, err
31377-		}
31378-		out = append(out, argJSON)
31379-	}
31380-	return out, nil
31381-}
31382-
31383-// UnmarshalArgs decodes the given json.RawMessages to the variables provided
31384-// by args. Each element of args should be a pointer.
31385-//
31386-// Example usage:
31387-//
31388-//	var (
31389-//	    num int
31390-//	    str string
31391-//	    bul bool
31392-//	    structured StructuredArg
31393-//	)
31394-//	err := UnmarshalArgs(args, &num, &str, &bul, &structured)
31395-func UnmarshalArgs(jsonArgs []json.RawMessage, args ...interface{}) error {
31396-	if len(args) != len(jsonArgs) {
31397-		return fmt.Errorf("DecodeArgs: expected %d input arguments, got %d JSON arguments", len(args), len(jsonArgs))
31398-	}
31399-	for i, arg := range args {
31400-		if err := json.Unmarshal(jsonArgs[i], arg); err != nil {
31401-			return err
31402-		}
31403-	}
31404-	return nil
31405-}
31406diff -urN a/gopls/internal/lsp/command.go b/gopls/internal/lsp/command.go
31407--- a/gopls/internal/lsp/command.go	2000-01-01 00:00:00.000000000 -0000
31408+++ b/gopls/internal/lsp/command.go	1970-01-01 00:00:00.000000000 +0000
31409@@ -1,964 +0,0 @@
31410-// Copyright 2020 The Go Authors. All rights reserved.
31411-// Use of this source code is governed by a BSD-style
31412-// license that can be found in the LICENSE file.
31413-
31414-package lsp
31415-
31416-import (
31417-	"bytes"
31418-	"context"
31419-	"encoding/json"
31420-	"errors"
31421-	"fmt"
31422-	"io"
31423-	"io/ioutil"
31424-	"os"
31425-	"os/exec"
31426-	"path/filepath"
31427-	"runtime"
31428-	"sort"
31429-	"strings"
31430-	"time"
31431-
31432-	"golang.org/x/mod/modfile"
31433-	"golang.org/x/tools/go/ast/astutil"
31434-	"golang.org/x/tools/gopls/internal/govulncheck"
31435-	"golang.org/x/tools/gopls/internal/lsp/command"
31436-	"golang.org/x/tools/gopls/internal/lsp/debug"
31437-	"golang.org/x/tools/gopls/internal/lsp/progress"
31438-	"golang.org/x/tools/gopls/internal/lsp/protocol"
31439-	"golang.org/x/tools/gopls/internal/lsp/source"
31440-	"golang.org/x/tools/gopls/internal/span"
31441-	"golang.org/x/tools/gopls/internal/vulncheck"
31442-	"golang.org/x/tools/internal/event"
31443-	"golang.org/x/tools/internal/gocommand"
31444-	"golang.org/x/tools/internal/xcontext"
31445-)
31446-
31447-func (s *Server) executeCommand(ctx context.Context, params *protocol.ExecuteCommandParams) (interface{}, error) {
31448-	var found bool
31449-	for _, name := range s.session.Options().SupportedCommands {
31450-		if name == params.Command {
31451-			found = true
31452-			break
31453-		}
31454-	}
31455-	if !found {
31456-		return nil, fmt.Errorf("%s is not a supported command", params.Command)
31457-	}
31458-
31459-	handler := &commandHandler{
31460-		s:      s,
31461-		params: params,
31462-	}
31463-	return command.Dispatch(ctx, params, handler)
31464-}
31465-
31466-type commandHandler struct {
31467-	s      *Server
31468-	params *protocol.ExecuteCommandParams
31469-}
31470-
31471-// commandConfig configures common command set-up and execution.
31472-type commandConfig struct {
31473-	async       bool                 // whether to run the command asynchronously. Async commands can only return errors.
31474-	requireSave bool                 // whether all files must be saved for the command to work
31475-	progress    string               // title to use for progress reporting. If empty, no progress will be reported.
31476-	forURI      protocol.DocumentURI // URI to resolve to a snapshot. If unset, snapshot will be nil.
31477-}
31478-
31479-// commandDeps is evaluated from a commandConfig. Note that not all fields may
31480-// be populated, depending on which configuration is set. See comments in-line
31481-// for details.
31482-type commandDeps struct {
31483-	snapshot source.Snapshot    // present if cfg.forURI was set
31484-	fh       source.FileHandle  // present if cfg.forURI was set
31485-	work     *progress.WorkDone // present cfg.progress was set
31486-}
31487-
31488-type commandFunc func(context.Context, commandDeps) error
31489-
31490-// run performs command setup for command execution, and invokes the given run
31491-// function. If cfg.async is set, run executes the given func in a separate
31492-// goroutine, and returns as soon as setup is complete and the goroutine is
31493-// scheduled.
31494-//
31495-// Invariant: if the resulting error is non-nil, the given run func will
31496-// (eventually) be executed exactly once.
31497-func (c *commandHandler) run(ctx context.Context, cfg commandConfig, run commandFunc) (err error) {
31498-	if cfg.requireSave {
31499-		var unsaved []string
31500-		for _, overlay := range c.s.session.Overlays() {
31501-			if !overlay.Saved() {
31502-				unsaved = append(unsaved, overlay.URI().Filename())
31503-			}
31504-		}
31505-		if len(unsaved) > 0 {
31506-			return fmt.Errorf("All files must be saved first (unsaved: %v).", unsaved)
31507-		}
31508-	}
31509-	var deps commandDeps
31510-	if cfg.forURI != "" {
31511-		var ok bool
31512-		var release func()
31513-		deps.snapshot, deps.fh, ok, release, err = c.s.beginFileRequest(ctx, cfg.forURI, source.UnknownKind)
31514-		defer release()
31515-		if !ok {
31516-			if err != nil {
31517-				return err
31518-			}
31519-			return fmt.Errorf("invalid file URL: %v", cfg.forURI)
31520-		}
31521-	}
31522-	ctx, cancel := context.WithCancel(xcontext.Detach(ctx))
31523-	if cfg.progress != "" {
31524-		deps.work = c.s.progress.Start(ctx, cfg.progress, "Running...", c.params.WorkDoneToken, cancel)
31525-	}
31526-	runcmd := func() error {
31527-		defer cancel()
31528-		err := run(ctx, deps)
31529-		if deps.work != nil {
31530-			switch {
31531-			case errors.Is(err, context.Canceled):
31532-				deps.work.End(ctx, "canceled")
31533-			case err != nil:
31534-				event.Error(ctx, "command error", err)
31535-				deps.work.End(ctx, "failed")
31536-			default:
31537-				deps.work.End(ctx, "completed")
31538-			}
31539-		}
31540-		return err
31541-	}
31542-	if cfg.async {
31543-		go func() {
31544-			if err := runcmd(); err != nil {
31545-				if showMessageErr := c.s.client.ShowMessage(ctx, &protocol.ShowMessageParams{
31546-					Type:    protocol.Error,
31547-					Message: err.Error(),
31548-				}); showMessageErr != nil {
31549-					event.Error(ctx, fmt.Sprintf("failed to show message: %q", err.Error()), showMessageErr)
31550-				}
31551-			}
31552-		}()
31553-		return nil
31554-	}
31555-	return runcmd()
31556-}
31557-
31558-func (c *commandHandler) ApplyFix(ctx context.Context, args command.ApplyFixArgs) error {
31559-	return c.run(ctx, commandConfig{
31560-		// Note: no progress here. Applying fixes should be quick.
31561-		forURI: args.URI,
31562-	}, func(ctx context.Context, deps commandDeps) error {
31563-		edits, err := source.ApplyFix(ctx, args.Fix, deps.snapshot, deps.fh, args.Range)
31564-		if err != nil {
31565-			return err
31566-		}
31567-		var changes []protocol.DocumentChanges
31568-		for _, edit := range edits {
31569-			edit := edit
31570-			changes = append(changes, protocol.DocumentChanges{
31571-				TextDocumentEdit: &edit,
31572-			})
31573-		}
31574-		r, err := c.s.client.ApplyEdit(ctx, &protocol.ApplyWorkspaceEditParams{
31575-			Edit: protocol.WorkspaceEdit{
31576-				DocumentChanges: changes,
31577-			},
31578-		})
31579-		if err != nil {
31580-			return err
31581-		}
31582-		if !r.Applied {
31583-			return errors.New(r.FailureReason)
31584-		}
31585-		return nil
31586-	})
31587-}
31588-
31589-func (c *commandHandler) RegenerateCgo(ctx context.Context, args command.URIArg) error {
31590-	return c.run(ctx, commandConfig{
31591-		progress: "Regenerating Cgo",
31592-	}, func(ctx context.Context, deps commandDeps) error {
31593-		mod := source.FileModification{
31594-			URI:    args.URI.SpanURI(),
31595-			Action: source.InvalidateMetadata,
31596-		}
31597-		return c.s.didModifyFiles(ctx, []source.FileModification{mod}, FromRegenerateCgo)
31598-	})
31599-}
31600-
31601-func (c *commandHandler) CheckUpgrades(ctx context.Context, args command.CheckUpgradesArgs) error {
31602-	return c.run(ctx, commandConfig{
31603-		forURI:   args.URI,
31604-		progress: "Checking for upgrades",
31605-	}, func(ctx context.Context, deps commandDeps) error {
31606-		upgrades, err := c.s.getUpgrades(ctx, deps.snapshot, args.URI.SpanURI(), args.Modules)
31607-		if err != nil {
31608-			return err
31609-		}
31610-		deps.snapshot.View().RegisterModuleUpgrades(args.URI.SpanURI(), upgrades)
31611-		// Re-diagnose the snapshot to publish the new module diagnostics.
31612-		c.s.diagnoseSnapshot(deps.snapshot, nil, false)
31613-		return nil
31614-	})
31615-}
31616-
31617-func (c *commandHandler) AddDependency(ctx context.Context, args command.DependencyArgs) error {
31618-	return c.GoGetModule(ctx, args)
31619-}
31620-
31621-func (c *commandHandler) UpgradeDependency(ctx context.Context, args command.DependencyArgs) error {
31622-	return c.GoGetModule(ctx, args)
31623-}
31624-
31625-func (c *commandHandler) ResetGoModDiagnostics(ctx context.Context, args command.ResetGoModDiagnosticsArgs) error {
31626-	return c.run(ctx, commandConfig{
31627-		forURI: args.URI,
31628-	}, func(ctx context.Context, deps commandDeps) error {
31629-		// Clear all diagnostics coming from the upgrade check source and vulncheck.
31630-		// This will clear the diagnostics in all go.mod files, but they
31631-		// will be re-calculated when the snapshot is diagnosed again.
31632-		if args.DiagnosticSource == "" || args.DiagnosticSource == string(source.UpgradeNotification) {
31633-			deps.snapshot.View().ClearModuleUpgrades(args.URI.SpanURI())
31634-			c.s.clearDiagnosticSource(modCheckUpgradesSource)
31635-		}
31636-
31637-		if args.DiagnosticSource == "" || args.DiagnosticSource == string(source.Govulncheck) {
31638-			deps.snapshot.View().SetVulnerabilities(args.URI.SpanURI(), nil)
31639-			c.s.clearDiagnosticSource(modVulncheckSource)
31640-		}
31641-
31642-		// Re-diagnose the snapshot to remove the diagnostics.
31643-		c.s.diagnoseSnapshot(deps.snapshot, nil, false)
31644-		return nil
31645-	})
31646-}
31647-
31648-func (c *commandHandler) GoGetModule(ctx context.Context, args command.DependencyArgs) error {
31649-	return c.run(ctx, commandConfig{
31650-		progress: "Running go get",
31651-		forURI:   args.URI,
31652-	}, func(ctx context.Context, deps commandDeps) error {
31653-		return c.s.runGoModUpdateCommands(ctx, deps.snapshot, args.URI.SpanURI(), func(invoke func(...string) (*bytes.Buffer, error)) error {
31654-			return runGoGetModule(invoke, args.AddRequire, args.GoCmdArgs)
31655-		})
31656-	})
31657-}
31658-
31659-// TODO(rFindley): UpdateGoSum, Tidy, and Vendor could probably all be one command.
31660-func (c *commandHandler) UpdateGoSum(ctx context.Context, args command.URIArgs) error {
31661-	return c.run(ctx, commandConfig{
31662-		progress: "Updating go.sum",
31663-	}, func(ctx context.Context, deps commandDeps) error {
31664-		for _, uri := range args.URIs {
31665-			snapshot, fh, ok, release, err := c.s.beginFileRequest(ctx, uri, source.UnknownKind)
31666-			defer release()
31667-			if !ok {
31668-				return err
31669-			}
31670-			if err := c.s.runGoModUpdateCommands(ctx, snapshot, fh.URI(), func(invoke func(...string) (*bytes.Buffer, error)) error {
31671-				_, err := invoke("list", "all")
31672-				return err
31673-			}); err != nil {
31674-				return err
31675-			}
31676-		}
31677-		return nil
31678-	})
31679-}
31680-
31681-func (c *commandHandler) Tidy(ctx context.Context, args command.URIArgs) error {
31682-	return c.run(ctx, commandConfig{
31683-		requireSave: true,
31684-		progress:    "Running go mod tidy",
31685-	}, func(ctx context.Context, deps commandDeps) error {
31686-		for _, uri := range args.URIs {
31687-			snapshot, fh, ok, release, err := c.s.beginFileRequest(ctx, uri, source.UnknownKind)
31688-			defer release()
31689-			if !ok {
31690-				return err
31691-			}
31692-			if err := c.s.runGoModUpdateCommands(ctx, snapshot, fh.URI(), func(invoke func(...string) (*bytes.Buffer, error)) error {
31693-				_, err := invoke("mod", "tidy")
31694-				return err
31695-			}); err != nil {
31696-				return err
31697-			}
31698-		}
31699-		return nil
31700-	})
31701-}
31702-
31703-func (c *commandHandler) Vendor(ctx context.Context, args command.URIArg) error {
31704-	return c.run(ctx, commandConfig{
31705-		requireSave: true,
31706-		progress:    "Running go mod vendor",
31707-		forURI:      args.URI,
31708-	}, func(ctx context.Context, deps commandDeps) error {
31709-		// Use RunGoCommandPiped here so that we don't compete with any other go
31710-		// command invocations. go mod vendor deletes modules.txt before recreating
31711-		// it, and therefore can run into file locking issues on Windows if that
31712-		// file is in use by another process, such as go list.
31713-		//
31714-		// If golang/go#44119 is resolved, go mod vendor will instead modify
31715-		// modules.txt in-place. In that case we could theoretically allow this
31716-		// command to run concurrently.
31717-		err := deps.snapshot.RunGoCommandPiped(ctx, source.Normal|source.AllowNetwork, &gocommand.Invocation{
31718-			Verb:       "mod",
31719-			Args:       []string{"vendor"},
31720-			WorkingDir: filepath.Dir(args.URI.SpanURI().Filename()),
31721-		}, &bytes.Buffer{}, &bytes.Buffer{})
31722-		return err
31723-	})
31724-}
31725-
31726-func (c *commandHandler) EditGoDirective(ctx context.Context, args command.EditGoDirectiveArgs) error {
31727-	return c.run(ctx, commandConfig{
31728-		requireSave: true, // if go.mod isn't saved it could cause a problem
31729-		forURI:      args.URI,
31730-	}, func(ctx context.Context, deps commandDeps) error {
31731-		snapshot, fh, ok, release, err := c.s.beginFileRequest(ctx, args.URI, source.UnknownKind)
31732-		defer release()
31733-		if !ok {
31734-			return err
31735-		}
31736-		if err := c.s.runGoModUpdateCommands(ctx, snapshot, fh.URI(), func(invoke func(...string) (*bytes.Buffer, error)) error {
31737-			_, err := invoke("mod", "edit", "-go", args.Version)
31738-			return err
31739-		}); err != nil {
31740-			return err
31741-		}
31742-		return nil
31743-	})
31744-}
31745-
31746-func (c *commandHandler) RemoveDependency(ctx context.Context, args command.RemoveDependencyArgs) error {
31747-	return c.run(ctx, commandConfig{
31748-		progress: "Removing dependency",
31749-		forURI:   args.URI,
31750-	}, func(ctx context.Context, deps commandDeps) error {
31751-		// If the module is tidied apart from the one unused diagnostic, we can
31752-		// run `go get module@none`, and then run `go mod tidy`. Otherwise, we
31753-		// must make textual edits.
31754-		// TODO(rstambler): In Go 1.17+, we will be able to use the go command
31755-		// without checking if the module is tidy.
31756-		if args.OnlyDiagnostic {
31757-			return c.s.runGoModUpdateCommands(ctx, deps.snapshot, args.URI.SpanURI(), func(invoke func(...string) (*bytes.Buffer, error)) error {
31758-				if err := runGoGetModule(invoke, false, []string{args.ModulePath + "@none"}); err != nil {
31759-					return err
31760-				}
31761-				_, err := invoke("mod", "tidy")
31762-				return err
31763-			})
31764-		}
31765-		pm, err := deps.snapshot.ParseMod(ctx, deps.fh)
31766-		if err != nil {
31767-			return err
31768-		}
31769-		edits, err := dropDependency(deps.snapshot, pm, args.ModulePath)
31770-		if err != nil {
31771-			return err
31772-		}
31773-		response, err := c.s.client.ApplyEdit(ctx, &protocol.ApplyWorkspaceEditParams{
31774-			Edit: protocol.WorkspaceEdit{
31775-				DocumentChanges: []protocol.DocumentChanges{
31776-					{
31777-						TextDocumentEdit: &protocol.TextDocumentEdit{
31778-							TextDocument: protocol.OptionalVersionedTextDocumentIdentifier{
31779-								Version: deps.fh.Version(),
31780-								TextDocumentIdentifier: protocol.TextDocumentIdentifier{
31781-									URI: protocol.URIFromSpanURI(deps.fh.URI()),
31782-								},
31783-							},
31784-							Edits: edits,
31785-						},
31786-					},
31787-				},
31788-			},
31789-		})
31790-		if err != nil {
31791-			return err
31792-		}
31793-		if !response.Applied {
31794-			return fmt.Errorf("edits not applied because of %s", response.FailureReason)
31795-		}
31796-		return nil
31797-	})
31798-}
31799-
31800-// dropDependency returns the edits to remove the given require from the go.mod
31801-// file.
31802-func dropDependency(snapshot source.Snapshot, pm *source.ParsedModule, modulePath string) ([]protocol.TextEdit, error) {
31803-	// We need a private copy of the parsed go.mod file, since we're going to
31804-	// modify it.
31805-	copied, err := modfile.Parse("", pm.Mapper.Content, nil)
31806-	if err != nil {
31807-		return nil, err
31808-	}
31809-	if err := copied.DropRequire(modulePath); err != nil {
31810-		return nil, err
31811-	}
31812-	copied.Cleanup()
31813-	newContent, err := copied.Format()
31814-	if err != nil {
31815-		return nil, err
31816-	}
31817-	// Calculate the edits to be made due to the change.
31818-	diff := snapshot.View().Options().ComputeEdits(string(pm.Mapper.Content), string(newContent))
31819-	return source.ToProtocolEdits(pm.Mapper, diff)
31820-}
31821-
31822-func (c *commandHandler) Test(ctx context.Context, uri protocol.DocumentURI, tests, benchmarks []string) error {
31823-	return c.RunTests(ctx, command.RunTestsArgs{
31824-		URI:        uri,
31825-		Tests:      tests,
31826-		Benchmarks: benchmarks,
31827-	})
31828-}
31829-
31830-func (c *commandHandler) RunTests(ctx context.Context, args command.RunTestsArgs) error {
31831-	return c.run(ctx, commandConfig{
31832-		async:       true,
31833-		progress:    "Running go test",
31834-		requireSave: true,
31835-		forURI:      args.URI,
31836-	}, func(ctx context.Context, deps commandDeps) error {
31837-		if err := c.runTests(ctx, deps.snapshot, deps.work, args.URI, args.Tests, args.Benchmarks); err != nil {
31838-			return fmt.Errorf("running tests failed: %w", err)
31839-		}
31840-		return nil
31841-	})
31842-}
31843-
31844-func (c *commandHandler) runTests(ctx context.Context, snapshot source.Snapshot, work *progress.WorkDone, uri protocol.DocumentURI, tests, benchmarks []string) error {
31845-	// TODO: fix the error reporting when this runs async.
31846-	metas, err := snapshot.MetadataForFile(ctx, uri.SpanURI())
31847-	if err != nil {
31848-		return err
31849-	}
31850-	metas = source.RemoveIntermediateTestVariants(metas)
31851-	if len(metas) == 0 {
31852-		return fmt.Errorf("package could not be found for file: %s", uri.SpanURI().Filename())
31853-	}
31854-	pkgPath := string(metas[0].ForTest)
31855-
31856-	// create output
31857-	buf := &bytes.Buffer{}
31858-	ew := progress.NewEventWriter(ctx, "test")
31859-	out := io.MultiWriter(ew, progress.NewWorkDoneWriter(ctx, work), buf)
31860-
31861-	// Run `go test -run Func` on each test.
31862-	var failedTests int
31863-	for _, funcName := range tests {
31864-		inv := &gocommand.Invocation{
31865-			Verb:       "test",
31866-			Args:       []string{pkgPath, "-v", "-count=1", "-run", fmt.Sprintf("^%s$", funcName)},
31867-			WorkingDir: filepath.Dir(uri.SpanURI().Filename()),
31868-		}
31869-		if err := snapshot.RunGoCommandPiped(ctx, source.Normal, inv, out, out); err != nil {
31870-			if errors.Is(err, context.Canceled) {
31871-				return err
31872-			}
31873-			failedTests++
31874-		}
31875-	}
31876-
31877-	// Run `go test -run=^$ -bench Func` on each test.
31878-	var failedBenchmarks int
31879-	for _, funcName := range benchmarks {
31880-		inv := &gocommand.Invocation{
31881-			Verb:       "test",
31882-			Args:       []string{pkgPath, "-v", "-run=^$", "-bench", fmt.Sprintf("^%s$", funcName)},
31883-			WorkingDir: filepath.Dir(uri.SpanURI().Filename()),
31884-		}
31885-		if err := snapshot.RunGoCommandPiped(ctx, source.Normal, inv, out, out); err != nil {
31886-			if errors.Is(err, context.Canceled) {
31887-				return err
31888-			}
31889-			failedBenchmarks++
31890-		}
31891-	}
31892-
31893-	var title string
31894-	if len(tests) > 0 && len(benchmarks) > 0 {
31895-		title = "tests and benchmarks"
31896-	} else if len(tests) > 0 {
31897-		title = "tests"
31898-	} else if len(benchmarks) > 0 {
31899-		title = "benchmarks"
31900-	} else {
31901-		return errors.New("No functions were provided")
31902-	}
31903-	message := fmt.Sprintf("all %s passed", title)
31904-	if failedTests > 0 && failedBenchmarks > 0 {
31905-		message = fmt.Sprintf("%d / %d tests failed and %d / %d benchmarks failed", failedTests, len(tests), failedBenchmarks, len(benchmarks))
31906-	} else if failedTests > 0 {
31907-		message = fmt.Sprintf("%d / %d tests failed", failedTests, len(tests))
31908-	} else if failedBenchmarks > 0 {
31909-		message = fmt.Sprintf("%d / %d benchmarks failed", failedBenchmarks, len(benchmarks))
31910-	}
31911-	if failedTests > 0 || failedBenchmarks > 0 {
31912-		message += "\n" + buf.String()
31913-	}
31914-
31915-	return c.s.client.ShowMessage(ctx, &protocol.ShowMessageParams{
31916-		Type:    protocol.Info,
31917-		Message: message,
31918-	})
31919-}
31920-
31921-func (c *commandHandler) Generate(ctx context.Context, args command.GenerateArgs) error {
31922-	title := "Running go generate ."
31923-	if args.Recursive {
31924-		title = "Running go generate ./..."
31925-	}
31926-	return c.run(ctx, commandConfig{
31927-		requireSave: true,
31928-		progress:    title,
31929-		forURI:      args.Dir,
31930-	}, func(ctx context.Context, deps commandDeps) error {
31931-		er := progress.NewEventWriter(ctx, "generate")
31932-
31933-		pattern := "."
31934-		if args.Recursive {
31935-			pattern = "./..."
31936-		}
31937-		inv := &gocommand.Invocation{
31938-			Verb:       "generate",
31939-			Args:       []string{"-x", pattern},
31940-			WorkingDir: args.Dir.SpanURI().Filename(),
31941-		}
31942-		stderr := io.MultiWriter(er, progress.NewWorkDoneWriter(ctx, deps.work))
31943-		if err := deps.snapshot.RunGoCommandPiped(ctx, source.Normal, inv, er, stderr); err != nil {
31944-			return err
31945-		}
31946-		return nil
31947-	})
31948-}
31949-
31950-func (c *commandHandler) GoGetPackage(ctx context.Context, args command.GoGetPackageArgs) error {
31951-	return c.run(ctx, commandConfig{
31952-		forURI:   args.URI,
31953-		progress: "Running go get",
31954-	}, func(ctx context.Context, deps commandDeps) error {
31955-		// Run on a throwaway go.mod, otherwise it'll write to the real one.
31956-		stdout, err := deps.snapshot.RunGoCommandDirect(ctx, source.WriteTemporaryModFile|source.AllowNetwork, &gocommand.Invocation{
31957-			Verb:       "list",
31958-			Args:       []string{"-f", "{{.Module.Path}}@{{.Module.Version}}", args.Pkg},
31959-			WorkingDir: filepath.Dir(args.URI.SpanURI().Filename()),
31960-		})
31961-		if err != nil {
31962-			return err
31963-		}
31964-		ver := strings.TrimSpace(stdout.String())
31965-		return c.s.runGoModUpdateCommands(ctx, deps.snapshot, args.URI.SpanURI(), func(invoke func(...string) (*bytes.Buffer, error)) error {
31966-			if args.AddRequire {
31967-				if err := addModuleRequire(invoke, []string{ver}); err != nil {
31968-					return err
31969-				}
31970-			}
31971-			_, err := invoke(append([]string{"get", "-d"}, args.Pkg)...)
31972-			return err
31973-		})
31974-	})
31975-}
31976-
31977-func (s *Server) runGoModUpdateCommands(ctx context.Context, snapshot source.Snapshot, uri span.URI, run func(invoke func(...string) (*bytes.Buffer, error)) error) error {
31978-	tmpModfile, newModBytes, newSumBytes, err := snapshot.RunGoCommands(ctx, true, filepath.Dir(uri.Filename()), run)
31979-	if err != nil {
31980-		return err
31981-	}
31982-	if !tmpModfile {
31983-		return nil
31984-	}
31985-	modURI := snapshot.GoModForFile(uri)
31986-	sumURI := span.URIFromPath(strings.TrimSuffix(modURI.Filename(), ".mod") + ".sum")
31987-	modEdits, err := applyFileEdits(ctx, snapshot, modURI, newModBytes)
31988-	if err != nil {
31989-		return err
31990-	}
31991-	sumEdits, err := applyFileEdits(ctx, snapshot, sumURI, newSumBytes)
31992-	if err != nil {
31993-		return err
31994-	}
31995-	changes := append(sumEdits, modEdits...)
31996-	if len(changes) == 0 {
31997-		return nil
31998-	}
31999-	var documentChanges []protocol.DocumentChanges
32000-	for _, change := range changes {
32001-		change := change
32002-		documentChanges = append(documentChanges, protocol.DocumentChanges{
32003-			TextDocumentEdit: &change,
32004-		})
32005-	}
32006-	response, err := s.client.ApplyEdit(ctx, &protocol.ApplyWorkspaceEditParams{
32007-		Edit: protocol.WorkspaceEdit{
32008-			DocumentChanges: documentChanges,
32009-		},
32010-	})
32011-	if err != nil {
32012-		return err
32013-	}
32014-	if !response.Applied {
32015-		return fmt.Errorf("edits not applied because of %s", response.FailureReason)
32016-	}
32017-	return nil
32018-}
32019-
32020-func applyFileEdits(ctx context.Context, snapshot source.Snapshot, uri span.URI, newContent []byte) ([]protocol.TextDocumentEdit, error) {
32021-	fh, err := snapshot.GetFile(ctx, uri)
32022-	if err != nil {
32023-		return nil, err
32024-	}
32025-	oldContent, err := fh.Read()
32026-	if err != nil && !os.IsNotExist(err) {
32027-		return nil, err
32028-	}
32029-	if bytes.Equal(oldContent, newContent) {
32030-		return nil, nil
32031-	}
32032-
32033-	// Sending a workspace edit to a closed file causes VS Code to open the
32034-	// file and leave it unsaved. We would rather apply the changes directly,
32035-	// especially to go.sum, which should be mostly invisible to the user.
32036-	if !snapshot.IsOpen(uri) {
32037-		err := ioutil.WriteFile(uri.Filename(), newContent, 0666)
32038-		return nil, err
32039-	}
32040-
32041-	m := protocol.NewMapper(fh.URI(), oldContent)
32042-	diff := snapshot.View().Options().ComputeEdits(string(oldContent), string(newContent))
32043-	edits, err := source.ToProtocolEdits(m, diff)
32044-	if err != nil {
32045-		return nil, err
32046-	}
32047-	return []protocol.TextDocumentEdit{{
32048-		TextDocument: protocol.OptionalVersionedTextDocumentIdentifier{
32049-			Version: fh.Version(),
32050-			TextDocumentIdentifier: protocol.TextDocumentIdentifier{
32051-				URI: protocol.URIFromSpanURI(uri),
32052-			},
32053-		},
32054-		Edits: edits,
32055-	}}, nil
32056-}
32057-
32058-func runGoGetModule(invoke func(...string) (*bytes.Buffer, error), addRequire bool, args []string) error {
32059-	if addRequire {
32060-		if err := addModuleRequire(invoke, args); err != nil {
32061-			return err
32062-		}
32063-	}
32064-	_, err := invoke(append([]string{"get", "-d"}, args...)...)
32065-	return err
32066-}
32067-
32068-func addModuleRequire(invoke func(...string) (*bytes.Buffer, error), args []string) error {
32069-	// Using go get to create a new dependency results in an
32070-	// `// indirect` comment we may not want. The only way to avoid it
32071-	// is to add the require as direct first. Then we can use go get to
32072-	// update go.sum and tidy up.
32073-	_, err := invoke(append([]string{"mod", "edit", "-require"}, args...)...)
32074-	return err
32075-}
32076-
32077-func (s *Server) getUpgrades(ctx context.Context, snapshot source.Snapshot, uri span.URI, modules []string) (map[string]string, error) {
32078-	stdout, err := snapshot.RunGoCommandDirect(ctx, source.Normal|source.AllowNetwork, &gocommand.Invocation{
32079-		Verb:       "list",
32080-		Args:       append([]string{"-m", "-u", "-json"}, modules...),
32081-		WorkingDir: filepath.Dir(uri.Filename()),
32082-		ModFlag:    "readonly",
32083-	})
32084-	if err != nil {
32085-		return nil, err
32086-	}
32087-
32088-	upgrades := map[string]string{}
32089-	for dec := json.NewDecoder(stdout); dec.More(); {
32090-		mod := &gocommand.ModuleJSON{}
32091-		if err := dec.Decode(mod); err != nil {
32092-			return nil, err
32093-		}
32094-		if mod.Update == nil {
32095-			continue
32096-		}
32097-		upgrades[mod.Path] = mod.Update.Version
32098-	}
32099-	return upgrades, nil
32100-}
32101-
32102-func (c *commandHandler) GCDetails(ctx context.Context, uri protocol.DocumentURI) error {
32103-	return c.ToggleGCDetails(ctx, command.URIArg{URI: uri})
32104-}
32105-
32106-func (c *commandHandler) ToggleGCDetails(ctx context.Context, args command.URIArg) error {
32107-	return c.run(ctx, commandConfig{
32108-		requireSave: true,
32109-		progress:    "Toggling GC Details",
32110-		forURI:      args.URI,
32111-	}, func(ctx context.Context, deps commandDeps) error {
32112-		metas, err := deps.snapshot.MetadataForFile(ctx, deps.fh.URI())
32113-		if err != nil {
32114-			return err
32115-		}
32116-		id := metas[0].ID // 0 => narrowest package
32117-		c.s.gcOptimizationDetailsMu.Lock()
32118-		if _, ok := c.s.gcOptimizationDetails[id]; ok {
32119-			delete(c.s.gcOptimizationDetails, id)
32120-			c.s.clearDiagnosticSource(gcDetailsSource)
32121-		} else {
32122-			c.s.gcOptimizationDetails[id] = struct{}{}
32123-		}
32124-		c.s.gcOptimizationDetailsMu.Unlock()
32125-		c.s.diagnoseSnapshot(deps.snapshot, nil, false)
32126-		return nil
32127-	})
32128-}
32129-
32130-func (c *commandHandler) ListKnownPackages(ctx context.Context, args command.URIArg) (command.ListKnownPackagesResult, error) {
32131-	var result command.ListKnownPackagesResult
32132-	err := c.run(ctx, commandConfig{
32133-		progress: "Listing packages",
32134-		forURI:   args.URI,
32135-	}, func(ctx context.Context, deps commandDeps) error {
32136-		pkgs, err := source.KnownPackagePaths(ctx, deps.snapshot, deps.fh)
32137-		for _, pkg := range pkgs {
32138-			result.Packages = append(result.Packages, string(pkg))
32139-		}
32140-		return err
32141-	})
32142-	return result, err
32143-}
32144-
32145-func (c *commandHandler) ListImports(ctx context.Context, args command.URIArg) (command.ListImportsResult, error) {
32146-	var result command.ListImportsResult
32147-	err := c.run(ctx, commandConfig{
32148-		forURI: args.URI,
32149-	}, func(ctx context.Context, deps commandDeps) error {
32150-		fh, err := deps.snapshot.GetFile(ctx, args.URI.SpanURI())
32151-		if err != nil {
32152-			return err
32153-		}
32154-		pgf, err := deps.snapshot.ParseGo(ctx, fh, source.ParseHeader)
32155-		if err != nil {
32156-			return err
32157-		}
32158-		fset := source.FileSetFor(pgf.Tok)
32159-		for _, group := range astutil.Imports(fset, pgf.File) {
32160-			for _, imp := range group {
32161-				if imp.Path == nil {
32162-					continue
32163-				}
32164-				var name string
32165-				if imp.Name != nil {
32166-					name = imp.Name.Name
32167-				}
32168-				result.Imports = append(result.Imports, command.FileImport{
32169-					Path: string(source.UnquoteImportPath(imp)),
32170-					Name: name,
32171-				})
32172-			}
32173-		}
32174-		metas, err := deps.snapshot.MetadataForFile(ctx, args.URI.SpanURI())
32175-		if err != nil {
32176-			return err // e.g. cancelled
32177-		}
32178-		if len(metas) == 0 {
32179-			return fmt.Errorf("no package containing %v", args.URI.SpanURI())
32180-		}
32181-		for pkgPath := range metas[0].DepsByPkgPath { // 0 => narrowest package
32182-			result.PackageImports = append(result.PackageImports,
32183-				command.PackageImport{Path: string(pkgPath)})
32184-		}
32185-		sort.Slice(result.PackageImports, func(i, j int) bool {
32186-			return result.PackageImports[i].Path < result.PackageImports[j].Path
32187-		})
32188-		return nil
32189-	})
32190-	return result, err
32191-}
32192-
32193-func (c *commandHandler) AddImport(ctx context.Context, args command.AddImportArgs) error {
32194-	return c.run(ctx, commandConfig{
32195-		progress: "Adding import",
32196-		forURI:   args.URI,
32197-	}, func(ctx context.Context, deps commandDeps) error {
32198-		edits, err := source.AddImport(ctx, deps.snapshot, deps.fh, args.ImportPath)
32199-		if err != nil {
32200-			return fmt.Errorf("could not add import: %v", err)
32201-		}
32202-		if _, err := c.s.client.ApplyEdit(ctx, &protocol.ApplyWorkspaceEditParams{
32203-			Edit: protocol.WorkspaceEdit{
32204-				DocumentChanges: documentChanges(deps.fh, edits),
32205-			},
32206-		}); err != nil {
32207-			return fmt.Errorf("could not apply import edits: %v", err)
32208-		}
32209-		return nil
32210-	})
32211-}
32212-
32213-func (c *commandHandler) StartDebugging(ctx context.Context, args command.DebuggingArgs) (result command.DebuggingResult, _ error) {
32214-	addr := args.Addr
32215-	if addr == "" {
32216-		addr = "localhost:0"
32217-	}
32218-	di := debug.GetInstance(ctx)
32219-	if di == nil {
32220-		return result, errors.New("internal error: server has no debugging instance")
32221-	}
32222-	listenedAddr, err := di.Serve(ctx, addr)
32223-	if err != nil {
32224-		return result, fmt.Errorf("starting debug server: %w", err)
32225-	}
32226-	result.URLs = []string{"http://" + listenedAddr}
32227-	return result, nil
32228-}
32229-
32230-// Copy of pkgLoadConfig defined in internal/lsp/cmd/vulncheck.go
32231-// TODO(hyangah): decide where to define this.
32232-type pkgLoadConfig struct {
32233-	// BuildFlags is a list of command-line flags to be passed through to
32234-	// the build system's query tool.
32235-	BuildFlags []string
32236-
32237-	// If Tests is set, the loader includes related test packages.
32238-	Tests bool
32239-}
32240-
32241-func (c *commandHandler) FetchVulncheckResult(ctx context.Context, arg command.URIArg) (map[protocol.DocumentURI]*govulncheck.Result, error) {
32242-	ret := map[protocol.DocumentURI]*govulncheck.Result{}
32243-	err := c.run(ctx, commandConfig{forURI: arg.URI}, func(ctx context.Context, deps commandDeps) error {
32244-		if deps.snapshot.View().Options().Vulncheck == source.ModeVulncheckImports {
32245-			for _, modfile := range deps.snapshot.ModFiles() {
32246-				res, err := deps.snapshot.ModVuln(ctx, modfile)
32247-				if err != nil {
32248-					return err
32249-				}
32250-				ret[protocol.URIFromSpanURI(modfile)] = res
32251-			}
32252-		}
32253-		// Overwrite if there is any govulncheck-based result.
32254-		for modfile, result := range deps.snapshot.View().Vulnerabilities() {
32255-			ret[protocol.URIFromSpanURI(modfile)] = result
32256-		}
32257-		return nil
32258-	})
32259-	return ret, err
32260-}
32261-
32262-func (c *commandHandler) RunGovulncheck(ctx context.Context, args command.VulncheckArgs) (command.RunVulncheckResult, error) {
32263-	if args.URI == "" {
32264-		return command.RunVulncheckResult{}, errors.New("VulncheckArgs is missing URI field")
32265-	}
32266-
32267-	// Return the workdone token so that clients can identify when this
32268-	// vulncheck invocation is complete.
32269-	//
32270-	// Since the run function executes asynchronously, we use a channel to
32271-	// synchronize the start of the run and return the token.
32272-	tokenChan := make(chan protocol.ProgressToken, 1)
32273-	err := c.run(ctx, commandConfig{
32274-		async:       true, // need to be async to be cancellable
32275-		progress:    "govulncheck",
32276-		requireSave: true,
32277-		forURI:      args.URI,
32278-	}, func(ctx context.Context, deps commandDeps) error {
32279-		tokenChan <- deps.work.Token()
32280-
32281-		view := deps.snapshot.View()
32282-		opts := view.Options()
32283-		// quickly test if gopls is compiled to support govulncheck
32284-		// by checking vulncheck.Main. Alternatively, we can continue and
32285-		// let the `gopls vulncheck` command fail. This is lighter-weight.
32286-		if vulncheck.Main == nil {
32287-			return errors.New("vulncheck feature is not available")
32288-		}
32289-
32290-		cmd := exec.CommandContext(ctx, os.Args[0], "vulncheck", "-config", args.Pattern)
32291-		cmd.Dir = filepath.Dir(args.URI.SpanURI().Filename())
32292-
32293-		var viewEnv []string
32294-		if e := opts.EnvSlice(); e != nil {
32295-			viewEnv = append(os.Environ(), e...)
32296-		}
32297-		cmd.Env = viewEnv
32298-
32299-		// stdin: gopls vulncheck expects JSON-encoded configuration from STDIN when -config flag is set.
32300-		var stdin bytes.Buffer
32301-		cmd.Stdin = &stdin
32302-
32303-		if err := json.NewEncoder(&stdin).Encode(pkgLoadConfig{
32304-			BuildFlags: opts.BuildFlags,
32305-			// TODO(hyangah): add `tests` flag in command.VulncheckArgs
32306-		}); err != nil {
32307-			return fmt.Errorf("failed to pass package load config: %v", err)
32308-		}
32309-
32310-		// stderr: stream gopls vulncheck's STDERR as progress reports
32311-		er := progress.NewEventWriter(ctx, "vulncheck")
32312-		stderr := io.MultiWriter(er, progress.NewWorkDoneWriter(ctx, deps.work))
32313-		cmd.Stderr = stderr
32314-		// TODO: can we stream stdout?
32315-		stdout, err := cmd.Output()
32316-		if err != nil {
32317-			return fmt.Errorf("failed to run govulncheck: %v", err)
32318-		}
32319-
32320-		var result govulncheck.Result
32321-		if err := json.Unmarshal(stdout, &result); err != nil {
32322-			// TODO: for easy debugging, log the failed stdout somewhere?
32323-			return fmt.Errorf("failed to parse govulncheck output: %v", err)
32324-		}
32325-		result.Mode = govulncheck.ModeGovulncheck
32326-		result.AsOf = time.Now()
32327-		deps.snapshot.View().SetVulnerabilities(args.URI.SpanURI(), &result)
32328-
32329-		c.s.diagnoseSnapshot(deps.snapshot, nil, false)
32330-		vulns := result.Vulns
32331-		affecting := make([]string, 0, len(vulns))
32332-		for _, v := range vulns {
32333-			if v.IsCalled() {
32334-				affecting = append(affecting, v.OSV.ID)
32335-			}
32336-		}
32337-		if len(affecting) == 0 {
32338-			return c.s.client.ShowMessage(ctx, &protocol.ShowMessageParams{
32339-				Type:    protocol.Info,
32340-				Message: "No vulnerabilities found",
32341-			})
32342-		}
32343-		sort.Strings(affecting)
32344-		return c.s.client.ShowMessage(ctx, &protocol.ShowMessageParams{
32345-			Type:    protocol.Warning,
32346-			Message: fmt.Sprintf("Found %v", strings.Join(affecting, ", ")),
32347-		})
32348-	})
32349-	if err != nil {
32350-		return command.RunVulncheckResult{}, err
32351-	}
32352-	select {
32353-	case <-ctx.Done():
32354-		return command.RunVulncheckResult{}, ctx.Err()
32355-	case token := <-tokenChan:
32356-		return command.RunVulncheckResult{Token: token}, nil
32357-	}
32358-}
32359-
32360-// MemStats implements the MemStats command. It returns an error as a
32361-// future-proof API, but the resulting error is currently always nil.
32362-func (c *commandHandler) MemStats(ctx context.Context) (command.MemStatsResult, error) {
32363-	// GC a few times for stable results.
32364-	runtime.GC()
32365-	runtime.GC()
32366-	runtime.GC()
32367-	var m runtime.MemStats
32368-	runtime.ReadMemStats(&m)
32369-	return command.MemStatsResult{
32370-		HeapAlloc: m.HeapAlloc,
32371-		HeapInUse: m.HeapInuse,
32372-	}, nil
32373-}
32374diff -urN a/gopls/internal/lsp/completion.go b/gopls/internal/lsp/completion.go
32375--- a/gopls/internal/lsp/completion.go	2000-01-01 00:00:00.000000000 -0000
32376+++ b/gopls/internal/lsp/completion.go	1970-01-01 00:00:00.000000000 +0000
32377@@ -1,140 +0,0 @@
32378-// Copyright 2018 The Go Authors. All rights reserved.
32379-// Use of this source code is governed by a BSD-style
32380-// license that can be found in the LICENSE file.
32381-
32382-package lsp
32383-
32384-import (
32385-	"context"
32386-	"fmt"
32387-	"strings"
32388-
32389-	"golang.org/x/tools/gopls/internal/lsp/protocol"
32390-	"golang.org/x/tools/gopls/internal/lsp/source"
32391-	"golang.org/x/tools/gopls/internal/lsp/source/completion"
32392-	"golang.org/x/tools/gopls/internal/lsp/template"
32393-	"golang.org/x/tools/gopls/internal/lsp/work"
32394-	"golang.org/x/tools/internal/event"
32395-	"golang.org/x/tools/internal/event/tag"
32396-)
32397-
32398-func (s *Server) completion(ctx context.Context, params *protocol.CompletionParams) (*protocol.CompletionList, error) {
32399-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.UnknownKind)
32400-	defer release()
32401-	if !ok {
32402-		return nil, err
32403-	}
32404-	var candidates []completion.CompletionItem
32405-	var surrounding *completion.Selection
32406-	switch snapshot.View().FileKind(fh) {
32407-	case source.Go:
32408-		candidates, surrounding, err = completion.Completion(ctx, snapshot, fh, params.Position, params.Context)
32409-	case source.Mod:
32410-		candidates, surrounding = nil, nil
32411-	case source.Work:
32412-		cl, err := work.Completion(ctx, snapshot, fh, params.Position)
32413-		if err != nil {
32414-			break
32415-		}
32416-		return cl, nil
32417-	case source.Tmpl:
32418-		var cl *protocol.CompletionList
32419-		cl, err = template.Completion(ctx, snapshot, fh, params.Position, params.Context)
32420-		if err != nil {
32421-			break // use common error handling, candidates==nil
32422-		}
32423-		return cl, nil
32424-	}
32425-	if err != nil {
32426-		event.Error(ctx, "no completions found", err, tag.Position.Of(params.Position))
32427-	}
32428-	if candidates == nil {
32429-		return &protocol.CompletionList{
32430-			IsIncomplete: true,
32431-			Items:        []protocol.CompletionItem{},
32432-		}, nil
32433-	}
32434-
32435-	rng, err := surrounding.Range()
32436-	if err != nil {
32437-		return nil, err
32438-	}
32439-
32440-	// When using deep completions/fuzzy matching, report results as incomplete so
32441-	// client fetches updated completions after every key stroke.
32442-	options := snapshot.View().Options()
32443-	incompleteResults := options.DeepCompletion || options.Matcher == source.Fuzzy
32444-
32445-	items := toProtocolCompletionItems(candidates, rng, options)
32446-
32447-	return &protocol.CompletionList{
32448-		IsIncomplete: incompleteResults,
32449-		Items:        items,
32450-	}, nil
32451-}
32452-
32453-func toProtocolCompletionItems(candidates []completion.CompletionItem, rng protocol.Range, options *source.Options) []protocol.CompletionItem {
32454-	var (
32455-		items                  = make([]protocol.CompletionItem, 0, len(candidates))
32456-		numDeepCompletionsSeen int
32457-	)
32458-	for i, candidate := range candidates {
32459-		// Limit the number of deep completions to not overwhelm the user in cases
32460-		// with dozens of deep completion matches.
32461-		if candidate.Depth > 0 {
32462-			if !options.DeepCompletion {
32463-				continue
32464-			}
32465-			if numDeepCompletionsSeen >= completion.MaxDeepCompletions {
32466-				continue
32467-			}
32468-			numDeepCompletionsSeen++
32469-		}
32470-		insertText := candidate.InsertText
32471-		if options.InsertTextFormat == protocol.SnippetTextFormat {
32472-			insertText = candidate.Snippet()
32473-		}
32474-
32475-		// This can happen if the client has snippets disabled but the
32476-		// candidate only supports snippet insertion.
32477-		if insertText == "" {
32478-			continue
32479-		}
32480-
32481-		doc := &protocol.Or_CompletionItem_documentation{
32482-			Value: protocol.MarkupContent{
32483-				Kind:  protocol.Markdown,
32484-				Value: source.CommentToMarkdown(candidate.Documentation, options),
32485-			},
32486-		}
32487-		if options.PreferredContentFormat != protocol.Markdown {
32488-			doc.Value = candidate.Documentation
32489-		}
32490-		item := protocol.CompletionItem{
32491-			Label:  candidate.Label,
32492-			Detail: candidate.Detail,
32493-			Kind:   candidate.Kind,
32494-			TextEdit: &protocol.TextEdit{
32495-				NewText: insertText,
32496-				Range:   rng,
32497-			},
32498-			InsertTextFormat:    &options.InsertTextFormat,
32499-			AdditionalTextEdits: candidate.AdditionalTextEdits,
32500-			// This is a hack so that the client sorts completion results in the order
32501-			// according to their score. This can be removed upon the resolution of
32502-			// https://github.com/Microsoft/language-server-protocol/issues/348.
32503-			SortText: fmt.Sprintf("%05d", i),
32504-
32505-			// Trim operators (VSCode doesn't like weird characters in
32506-			// filterText).
32507-			FilterText: strings.TrimLeft(candidate.InsertText, "&*"),
32508-
32509-			Preselect:     i == 0,
32510-			Documentation: doc,
32511-			Tags:          candidate.Tags,
32512-			Deprecated:    candidate.Deprecated,
32513-		}
32514-		items = append(items, item)
32515-	}
32516-	return items
32517-}
32518diff -urN a/gopls/internal/lsp/completion_test.go b/gopls/internal/lsp/completion_test.go
32519--- a/gopls/internal/lsp/completion_test.go	2000-01-01 00:00:00.000000000 -0000
32520+++ b/gopls/internal/lsp/completion_test.go	1970-01-01 00:00:00.000000000 +0000
32521@@ -1,176 +0,0 @@
32522-// Copyright 2019 The Go Authors. All rights reserved.
32523-// Use of this source code is governed by a BSD-style
32524-// license that can be found in the LICENSE file.
32525-
32526-package lsp
32527-
32528-import (
32529-	"fmt"
32530-	"strings"
32531-	"testing"
32532-
32533-	"golang.org/x/tools/gopls/internal/lsp/protocol"
32534-	"golang.org/x/tools/gopls/internal/lsp/source"
32535-	"golang.org/x/tools/gopls/internal/lsp/source/completion"
32536-	"golang.org/x/tools/gopls/internal/lsp/tests"
32537-	"golang.org/x/tools/gopls/internal/span"
32538-)
32539-
32540-func (r *runner) Completion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
32541-	got := r.callCompletion(t, src, func(opts *source.Options) {
32542-		opts.DeepCompletion = false
32543-		opts.Matcher = source.CaseInsensitive
32544-		opts.CompleteUnimported = false
32545-		opts.InsertTextFormat = protocol.SnippetTextFormat
32546-		opts.LiteralCompletions = strings.Contains(string(src.URI()), "literal")
32547-		opts.ExperimentalPostfixCompletions = strings.Contains(string(src.URI()), "postfix")
32548-	})
32549-	got = tests.FilterBuiltins(src, got)
32550-	want := expected(t, test, items)
32551-	if diff := tests.DiffCompletionItems(want, got); diff != "" {
32552-		t.Errorf("mismatching completion items (-want +got):\n%s", diff)
32553-	}
32554-}
32555-
32556-func (r *runner) CompletionSnippet(t *testing.T, src span.Span, expected tests.CompletionSnippet, placeholders bool, items tests.CompletionItems) {
32557-	list := r.callCompletion(t, src, func(opts *source.Options) {
32558-		opts.UsePlaceholders = placeholders
32559-		opts.DeepCompletion = true
32560-		opts.Matcher = source.Fuzzy
32561-		opts.CompleteUnimported = false
32562-	})
32563-	got := tests.FindItem(list, *items[expected.CompletionItem])
32564-	want := expected.PlainSnippet
32565-	if placeholders {
32566-		want = expected.PlaceholderSnippet
32567-	}
32568-	if diff := tests.DiffSnippets(want, got); diff != "" {
32569-		t.Errorf("%s", diff)
32570-	}
32571-}
32572-
32573-func (r *runner) UnimportedCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
32574-	got := r.callCompletion(t, src, func(opts *source.Options) {})
32575-	got = tests.FilterBuiltins(src, got)
32576-	want := expected(t, test, items)
32577-	if diff := tests.CheckCompletionOrder(want, got, false); diff != "" {
32578-		t.Errorf("%s", diff)
32579-	}
32580-}
32581-
32582-func (r *runner) DeepCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
32583-	got := r.callCompletion(t, src, func(opts *source.Options) {
32584-		opts.DeepCompletion = true
32585-		opts.Matcher = source.CaseInsensitive
32586-		opts.CompleteUnimported = false
32587-	})
32588-	got = tests.FilterBuiltins(src, got)
32589-	want := expected(t, test, items)
32590-	if diff := tests.DiffCompletionItems(want, got); diff != "" {
32591-		t.Errorf("mismatching completion items (-want +got):\n%s", diff)
32592-	}
32593-}
32594-
32595-func (r *runner) FuzzyCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
32596-	got := r.callCompletion(t, src, func(opts *source.Options) {
32597-		opts.DeepCompletion = true
32598-		opts.Matcher = source.Fuzzy
32599-		opts.CompleteUnimported = false
32600-	})
32601-	got = tests.FilterBuiltins(src, got)
32602-	want := expected(t, test, items)
32603-	if diff := tests.DiffCompletionItems(want, got); diff != "" {
32604-		t.Errorf("mismatching completion items (-want +got):\n%s", diff)
32605-	}
32606-}
32607-
32608-func (r *runner) CaseSensitiveCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
32609-	got := r.callCompletion(t, src, func(opts *source.Options) {
32610-		opts.Matcher = source.CaseSensitive
32611-		opts.CompleteUnimported = false
32612-	})
32613-	got = tests.FilterBuiltins(src, got)
32614-	want := expected(t, test, items)
32615-	if diff := tests.DiffCompletionItems(want, got); diff != "" {
32616-		t.Errorf("mismatching completion items (-want +got):\n%s", diff)
32617-	}
32618-}
32619-
32620-func (r *runner) RankCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
32621-	got := r.callCompletion(t, src, func(opts *source.Options) {
32622-		opts.DeepCompletion = true
32623-		opts.Matcher = source.Fuzzy
32624-		opts.CompleteUnimported = false
32625-		opts.LiteralCompletions = true
32626-		opts.ExperimentalPostfixCompletions = true
32627-	})
32628-	want := expected(t, test, items)
32629-	if msg := tests.CheckCompletionOrder(want, got, true); msg != "" {
32630-		t.Errorf("%s", msg)
32631-	}
32632-}
32633-
32634-func expected(t *testing.T, test tests.Completion, items tests.CompletionItems) []protocol.CompletionItem {
32635-	t.Helper()
32636-
32637-	toProtocolCompletionItem := func(item *completion.CompletionItem) protocol.CompletionItem {
32638-		pItem := protocol.CompletionItem{
32639-			Label:  item.Label,
32640-			Kind:   item.Kind,
32641-			Detail: item.Detail,
32642-			Documentation: &protocol.Or_CompletionItem_documentation{
32643-				Value: item.Documentation,
32644-			},
32645-			InsertText: item.InsertText,
32646-			TextEdit: &protocol.TextEdit{
32647-				NewText: item.Snippet(),
32648-			},
32649-			// Negate score so best score has lowest sort text like real API.
32650-			SortText: fmt.Sprint(-item.Score),
32651-		}
32652-		if pItem.InsertText == "" {
32653-			pItem.InsertText = pItem.Label
32654-		}
32655-		return pItem
32656-	}
32657-
32658-	var want []protocol.CompletionItem
32659-	for _, pos := range test.CompletionItems {
32660-		want = append(want, toProtocolCompletionItem(items[pos]))
32661-	}
32662-	return want
32663-}
32664-
32665-func (r *runner) callCompletion(t *testing.T, src span.Span, options func(*source.Options)) []protocol.CompletionItem {
32666-	t.Helper()
32667-
32668-	view, err := r.server.session.ViewOf(src.URI())
32669-	if err != nil {
32670-		t.Fatal(err)
32671-	}
32672-	original := view.Options()
32673-	modified := view.Options().Clone()
32674-	options(modified)
32675-	view, err = r.server.session.SetViewOptions(r.ctx, view, modified)
32676-	if err != nil {
32677-		t.Error(err)
32678-		return nil
32679-	}
32680-	defer r.server.session.SetViewOptions(r.ctx, view, original)
32681-
32682-	list, err := r.server.Completion(r.ctx, &protocol.CompletionParams{
32683-		TextDocumentPositionParams: protocol.TextDocumentPositionParams{
32684-			TextDocument: protocol.TextDocumentIdentifier{
32685-				URI: protocol.URIFromSpanURI(src.URI()),
32686-			},
32687-			Position: protocol.Position{
32688-				Line:      uint32(src.Start().Line() - 1),
32689-				Character: uint32(src.Start().Column() - 1),
32690-			},
32691-		},
32692-	})
32693-	if err != nil {
32694-		t.Fatal(err)
32695-	}
32696-	return list.Items
32697-}
32698diff -urN a/gopls/internal/lsp/debounce.go b/gopls/internal/lsp/debounce.go
32699--- a/gopls/internal/lsp/debounce.go	2000-01-01 00:00:00.000000000 -0000
32700+++ b/gopls/internal/lsp/debounce.go	1970-01-01 00:00:00.000000000 +0000
32701@@ -1,71 +0,0 @@
32702-// Copyright 2020 The Go Authors. All rights reserved.
32703-// Use of this source code is governed by a BSD-style
32704-// license that can be found in the LICENSE file.
32705-
32706-package lsp
32707-
32708-import (
32709-	"sync"
32710-	"time"
32711-)
32712-
32713-type debounceEvent struct {
32714-	order uint64
32715-	done  chan struct{}
32716-}
32717-
32718-type debouncer struct {
32719-	mu     sync.Mutex
32720-	events map[string]*debounceEvent
32721-}
32722-
32723-func newDebouncer() *debouncer {
32724-	return &debouncer{
32725-		events: make(map[string]*debounceEvent),
32726-	}
32727-}
32728-
32729-// debounce returns a channel that receives a boolean reporting whether,
32730-// by the time the delay channel receives a value, this call is (or will be)
32731-// the most recent call with the highest order number for its key.
32732-func (d *debouncer) debounce(key string, order uint64, delay <-chan time.Time) <-chan bool {
32733-	okc := make(chan bool, 1)
32734-
32735-	d.mu.Lock()
32736-	if prev, ok := d.events[key]; ok {
32737-		if prev.order > order {
32738-			// If we have a logical ordering of events (as is the case for snapshots),
32739-			// don't overwrite a later event with an earlier event.
32740-			d.mu.Unlock()
32741-			okc <- false
32742-			return okc
32743-		}
32744-		close(prev.done)
32745-	}
32746-	done := make(chan struct{})
32747-	next := &debounceEvent{
32748-		order: order,
32749-		done:  done,
32750-	}
32751-	d.events[key] = next
32752-	d.mu.Unlock()
32753-
32754-	go func() {
32755-		ok := false
32756-		select {
32757-		case <-delay:
32758-			d.mu.Lock()
32759-			if d.events[key] == next {
32760-				ok = true
32761-				delete(d.events, key)
32762-			} else {
32763-				// The event was superseded before we acquired d.mu.
32764-			}
32765-			d.mu.Unlock()
32766-		case <-done:
32767-		}
32768-		okc <- ok
32769-	}()
32770-
32771-	return okc
32772-}
32773diff -urN a/gopls/internal/lsp/debounce_test.go b/gopls/internal/lsp/debounce_test.go
32774--- a/gopls/internal/lsp/debounce_test.go	2000-01-01 00:00:00.000000000 -0000
32775+++ b/gopls/internal/lsp/debounce_test.go	1970-01-01 00:00:00.000000000 +0000
32776@@ -1,81 +0,0 @@
32777-// Copyright 2020 The Go Authors. All rights reserved.
32778-// Use of this source code is governed by a BSD-style
32779-// license that can be found in the LICENSE file.
32780-
32781-package lsp
32782-
32783-import (
32784-	"testing"
32785-	"time"
32786-)
32787-
32788-func TestDebouncer(t *testing.T) {
32789-	t.Parallel()
32790-
32791-	type event struct {
32792-		key       string
32793-		order     uint64
32794-		wantFired bool
32795-	}
32796-	tests := []struct {
32797-		label  string
32798-		events []*event
32799-	}{
32800-		{
32801-			label: "overridden",
32802-			events: []*event{
32803-				{key: "a", order: 1, wantFired: false},
32804-				{key: "a", order: 2, wantFired: true},
32805-			},
32806-		},
32807-		{
32808-			label: "distinct labels",
32809-			events: []*event{
32810-				{key: "a", order: 1, wantFired: true},
32811-				{key: "b", order: 2, wantFired: true},
32812-			},
32813-		},
32814-		{
32815-			label: "reverse order",
32816-			events: []*event{
32817-				{key: "a", order: 2, wantFired: true},
32818-				{key: "a", order: 1, wantFired: false},
32819-			},
32820-		},
32821-		{
32822-			label: "multiple overrides",
32823-			events: []*event{
32824-				{key: "a", order: 1, wantFired: false},
32825-				{key: "a", order: 2, wantFired: false},
32826-				{key: "a", order: 3, wantFired: false},
32827-				{key: "a", order: 4, wantFired: false},
32828-				{key: "a", order: 5, wantFired: true},
32829-			},
32830-		},
32831-	}
32832-	for _, test := range tests {
32833-		test := test
32834-		t.Run(test.label, func(t *testing.T) {
32835-			d := newDebouncer()
32836-
32837-			delays := make([]chan time.Time, len(test.events))
32838-			okcs := make([]<-chan bool, len(test.events))
32839-
32840-			// Register the events in deterministic order, synchronously.
32841-			for i, e := range test.events {
32842-				delays[i] = make(chan time.Time, 1)
32843-				okcs[i] = d.debounce(e.key, e.order, delays[i])
32844-			}
32845-
32846-			// Now see which event fired.
32847-			for i, okc := range okcs {
32848-				event := test.events[i]
32849-				delays[i] <- time.Now()
32850-				fired := <-okc
32851-				if fired != event.wantFired {
32852-					t.Errorf("[key: %q, order: %d]: fired = %t, want %t", event.key, event.order, fired, event.wantFired)
32853-				}
32854-			}
32855-		})
32856-	}
32857-}
32858diff -urN a/gopls/internal/lsp/debug/buildinfo_go1.12.go b/gopls/internal/lsp/debug/buildinfo_go1.12.go
32859--- a/gopls/internal/lsp/debug/buildinfo_go1.12.go	2000-01-01 00:00:00.000000000 -0000
32860+++ b/gopls/internal/lsp/debug/buildinfo_go1.12.go	1970-01-01 00:00:00.000000000 +0000
32861@@ -1,29 +0,0 @@
32862-// Copyright 2022 The Go Authors. All rights reserved.
32863-// Use of this source code is governed by a BSD-style
32864-// license that can be found in the LICENSE file.
32865-
32866-//go:build !go1.18
32867-// +build !go1.18
32868-
32869-package debug
32870-
32871-import (
32872-	"runtime"
32873-	"runtime/debug"
32874-)
32875-
32876-type BuildInfo struct {
32877-	debug.BuildInfo
32878-	GoVersion string // Version of Go that produced this binary
32879-}
32880-
32881-func readBuildInfo() (*BuildInfo, bool) {
32882-	rinfo, ok := debug.ReadBuildInfo()
32883-	if !ok {
32884-		return nil, false
32885-	}
32886-	return &BuildInfo{
32887-		GoVersion: runtime.Version(),
32888-		BuildInfo: *rinfo,
32889-	}, true
32890-}
32891diff -urN a/gopls/internal/lsp/debug/buildinfo_go1.18.go b/gopls/internal/lsp/debug/buildinfo_go1.18.go
32892--- a/gopls/internal/lsp/debug/buildinfo_go1.18.go	2000-01-01 00:00:00.000000000 -0000
32893+++ b/gopls/internal/lsp/debug/buildinfo_go1.18.go	1970-01-01 00:00:00.000000000 +0000
32894@@ -1,19 +0,0 @@
32895-// Copyright 2022 The Go Authors. All rights reserved.
32896-// Use of this source code is governed by a BSD-style
32897-// license that can be found in the LICENSE file.
32898-
32899-//go:build go1.18
32900-// +build go1.18
32901-
32902-package debug
32903-
32904-import (
32905-	"runtime/debug"
32906-)
32907-
32908-type BuildInfo debug.BuildInfo
32909-
32910-func readBuildInfo() (*BuildInfo, bool) {
32911-	info, ok := debug.ReadBuildInfo()
32912-	return (*BuildInfo)(info), ok
32913-}
32914diff -urN a/gopls/internal/lsp/debug/info.go b/gopls/internal/lsp/debug/info.go
32915--- a/gopls/internal/lsp/debug/info.go	2000-01-01 00:00:00.000000000 -0000
32916+++ b/gopls/internal/lsp/debug/info.go	1970-01-01 00:00:00.000000000 +0000
32917@@ -1,254 +0,0 @@
32918-// Copyright 2019 The Go Authors. All rights reserved.
32919-// Use of this source code is governed by a BSD-style
32920-// license that can be found in the LICENSE file.
32921-
32922-// Package debug exports debug information for gopls.
32923-package debug
32924-
32925-import (
32926-	"context"
32927-	"encoding/json"
32928-	"fmt"
32929-	"io"
32930-	"reflect"
32931-	"runtime"
32932-	"runtime/debug"
32933-	"sort"
32934-	"strings"
32935-
32936-	"golang.org/x/tools/gopls/internal/lsp/source"
32937-)
32938-
32939-type PrintMode int
32940-
32941-const (
32942-	PlainText = PrintMode(iota)
32943-	Markdown
32944-	HTML
32945-	JSON
32946-)
32947-
32948-// Version is a manually-updated mechanism for tracking versions.
32949-const Version = "master"
32950-
32951-// ServerVersion is the format used by gopls to report its version to the
32952-// client. This format is structured so that the client can parse it easily.
32953-type ServerVersion struct {
32954-	*BuildInfo
32955-	Version string
32956-}
32957-
32958-// VersionInfo returns the build info for the gopls process. If it was not
32959-// built in module mode, we return a GOPATH-specific message with the
32960-// hardcoded version.
32961-func VersionInfo() *ServerVersion {
32962-	if info, ok := readBuildInfo(); ok {
32963-		return getVersion(info)
32964-	}
32965-	buildInfo := &BuildInfo{}
32966-	// go1.17 or earlier, part of s.BuildInfo are embedded fields.
32967-	buildInfo.Path = "gopls, built in GOPATH mode"
32968-	buildInfo.GoVersion = runtime.Version()
32969-	return &ServerVersion{
32970-		Version:   Version,
32971-		BuildInfo: buildInfo,
32972-	}
32973-}
32974-
32975-func getVersion(info *BuildInfo) *ServerVersion {
32976-	return &ServerVersion{
32977-		Version:   Version,
32978-		BuildInfo: info,
32979-	}
32980-}
32981-
32982-// PrintServerInfo writes HTML debug info to w for the Instance.
32983-func (i *Instance) PrintServerInfo(ctx context.Context, w io.Writer) {
32984-	section(w, HTML, "Server Instance", func() {
32985-		fmt.Fprintf(w, "Start time: %v\n", i.StartTime)
32986-		fmt.Fprintf(w, "LogFile: %s\n", i.Logfile)
32987-		fmt.Fprintf(w, "Working directory: %s\n", i.Workdir)
32988-		fmt.Fprintf(w, "Address: %s\n", i.ServerAddress)
32989-		fmt.Fprintf(w, "Debug address: %s\n", i.DebugAddress())
32990-	})
32991-	PrintVersionInfo(ctx, w, true, HTML)
32992-	section(w, HTML, "Command Line", func() {
32993-		fmt.Fprintf(w, "<a href=/debug/pprof/cmdline>cmdline</a>")
32994-	})
32995-}
32996-
32997-// PrintVersionInfo writes version information to w, using the output format
32998-// specified by mode. verbose controls whether additional information is
32999-// written, including section headers.
33000-func PrintVersionInfo(_ context.Context, w io.Writer, verbose bool, mode PrintMode) error {
33001-	info := VersionInfo()
33002-	if mode == JSON {
33003-		return printVersionInfoJSON(w, info)
33004-	}
33005-
33006-	if !verbose {
33007-		printBuildInfo(w, info, false, mode)
33008-		return nil
33009-	}
33010-	section(w, mode, "Build info", func() {
33011-		printBuildInfo(w, info, true, mode)
33012-	})
33013-	return nil
33014-}
33015-
33016-func printVersionInfoJSON(w io.Writer, info *ServerVersion) error {
33017-	js, err := json.MarshalIndent(info, "", "\t")
33018-	if err != nil {
33019-		return err
33020-	}
33021-	_, err = fmt.Fprint(w, string(js))
33022-	return err
33023-}
33024-
33025-func section(w io.Writer, mode PrintMode, title string, body func()) {
33026-	switch mode {
33027-	case PlainText:
33028-		fmt.Fprintln(w, title)
33029-		fmt.Fprintln(w, strings.Repeat("-", len(title)))
33030-		body()
33031-	case Markdown:
33032-		fmt.Fprintf(w, "#### %s\n\n```\n", title)
33033-		body()
33034-		fmt.Fprintf(w, "```\n")
33035-	case HTML:
33036-		fmt.Fprintf(w, "<h3>%s</h3>\n<pre>\n", title)
33037-		body()
33038-		fmt.Fprint(w, "</pre>\n")
33039-	}
33040-}
33041-
33042-func printBuildInfo(w io.Writer, info *ServerVersion, verbose bool, mode PrintMode) {
33043-	fmt.Fprintf(w, "%v %v\n", info.Path, Version)
33044-	printModuleInfo(w, info.Main, mode)
33045-	if !verbose {
33046-		return
33047-	}
33048-	for _, dep := range info.Deps {
33049-		printModuleInfo(w, *dep, mode)
33050-	}
33051-	fmt.Fprintf(w, "go: %v\n", info.GoVersion)
33052-}
33053-
33054-func printModuleInfo(w io.Writer, m debug.Module, _ PrintMode) {
33055-	fmt.Fprintf(w, "    %s@%s", m.Path, m.Version)
33056-	if m.Sum != "" {
33057-		fmt.Fprintf(w, " %s", m.Sum)
33058-	}
33059-	if m.Replace != nil {
33060-		fmt.Fprintf(w, " => %v", m.Replace.Path)
33061-	}
33062-	fmt.Fprintf(w, "\n")
33063-}
33064-
33065-type field struct {
33066-	index []int
33067-}
33068-
33069-var fields []field
33070-
33071-// find all the options. The presumption is that the Options are nested structs
33072-// and that pointers don't need to be dereferenced
33073-func swalk(t reflect.Type, ix []int, indent string) {
33074-	switch t.Kind() {
33075-	case reflect.Struct:
33076-		for i := 0; i < t.NumField(); i++ {
33077-			fld := t.Field(i)
33078-			ixx := append(append([]int{}, ix...), i)
33079-			swalk(fld.Type, ixx, indent+". ")
33080-		}
33081-	default:
33082-		// everything is either a struct or a field (that's an assumption about Options)
33083-		fields = append(fields, field{ix})
33084-	}
33085-}
33086-
33087-type sessionOption struct {
33088-	Name    string
33089-	Type    string
33090-	Current string
33091-	Default string
33092-}
33093-
33094-func showOptions(o *source.Options) []sessionOption {
33095-	var out []sessionOption
33096-	t := reflect.TypeOf(*o)
33097-	swalk(t, []int{}, "")
33098-	v := reflect.ValueOf(*o)
33099-	do := reflect.ValueOf(*source.DefaultOptions())
33100-	for _, f := range fields {
33101-		val := v.FieldByIndex(f.index)
33102-		def := do.FieldByIndex(f.index)
33103-		tx := t.FieldByIndex(f.index)
33104-		is := strVal(val)
33105-		was := strVal(def)
33106-		out = append(out, sessionOption{
33107-			Name:    tx.Name,
33108-			Type:    tx.Type.String(),
33109-			Current: is,
33110-			Default: was,
33111-		})
33112-	}
33113-	sort.Slice(out, func(i, j int) bool {
33114-		rd := out[i].Current == out[i].Default
33115-		ld := out[j].Current == out[j].Default
33116-		if rd != ld {
33117-			return ld
33118-		}
33119-		return out[i].Name < out[j].Name
33120-	})
33121-	return out
33122-}
33123-
33124-func strVal(val reflect.Value) string {
33125-	switch val.Kind() {
33126-	case reflect.Bool:
33127-		return fmt.Sprintf("%v", val.Interface())
33128-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
33129-		return fmt.Sprintf("%v", val.Interface())
33130-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
33131-		return fmt.Sprintf("%v", val.Interface())
33132-	case reflect.Uintptr, reflect.UnsafePointer:
33133-		return fmt.Sprintf("0x%x", val.Pointer())
33134-	case reflect.Complex64, reflect.Complex128:
33135-		return fmt.Sprintf("%v", val.Complex())
33136-	case reflect.Array, reflect.Slice:
33137-		ans := []string{}
33138-		for i := 0; i < val.Len(); i++ {
33139-			ans = append(ans, strVal(val.Index(i)))
33140-		}
33141-		sort.Strings(ans)
33142-		return fmt.Sprintf("%v", ans)
33143-	case reflect.Chan, reflect.Func, reflect.Ptr:
33144-		return val.Kind().String()
33145-	case reflect.Struct:
33146-		var x source.Analyzer
33147-		if val.Type() != reflect.TypeOf(x) {
33148-			return val.Kind().String()
33149-		}
33150-		// this is sort of ugly, but usable
33151-		str := val.FieldByName("Analyzer").Elem().FieldByName("Doc").String()
33152-		ix := strings.Index(str, "\n")
33153-		if ix == -1 {
33154-			ix = len(str)
33155-		}
33156-		return str[:ix]
33157-	case reflect.String:
33158-		return fmt.Sprintf("%q", val.Interface())
33159-	case reflect.Map:
33160-		ans := []string{}
33161-		iter := val.MapRange()
33162-		for iter.Next() {
33163-			k := iter.Key()
33164-			v := iter.Value()
33165-			ans = append(ans, fmt.Sprintf("%s:%s, ", strVal(k), strVal(v)))
33166-		}
33167-		sort.Strings(ans)
33168-		return fmt.Sprintf("%v", ans)
33169-	}
33170-	return fmt.Sprintf("??%s??", val.Type())
33171-}
33172diff -urN a/gopls/internal/lsp/debug/info_test.go b/gopls/internal/lsp/debug/info_test.go
33173--- a/gopls/internal/lsp/debug/info_test.go	2000-01-01 00:00:00.000000000 -0000
33174+++ b/gopls/internal/lsp/debug/info_test.go	1970-01-01 00:00:00.000000000 +0000
33175@@ -1,47 +0,0 @@
33176-// Copyright 2022 The Go Authors. All rights reserved.
33177-// Use of this source code is governed by a BSD-style
33178-// license that can be found in the LICENSE file.
33179-
33180-// Package debug exports debug information for gopls.
33181-package debug
33182-
33183-import (
33184-	"bytes"
33185-	"context"
33186-	"encoding/json"
33187-	"runtime"
33188-	"testing"
33189-)
33190-
33191-func TestPrintVersionInfoJSON(t *testing.T) {
33192-	buf := new(bytes.Buffer)
33193-	if err := PrintVersionInfo(context.Background(), buf, true, JSON); err != nil {
33194-		t.Fatalf("PrintVersionInfo failed: %v", err)
33195-	}
33196-	res := buf.Bytes()
33197-
33198-	var got ServerVersion
33199-	if err := json.Unmarshal(res, &got); err != nil {
33200-		t.Fatalf("unexpected output: %v\n%s", err, res)
33201-	}
33202-	if g, w := got.GoVersion, runtime.Version(); g != w {
33203-		t.Errorf("go version = %v, want %v", g, w)
33204-	}
33205-	if g, w := got.Version, Version; g != w {
33206-		t.Errorf("gopls version = %v, want %v", g, w)
33207-	}
33208-	// Other fields of BuildInfo may not be available during test.
33209-}
33210-
33211-func TestPrintVersionInfoPlainText(t *testing.T) {
33212-	buf := new(bytes.Buffer)
33213-	if err := PrintVersionInfo(context.Background(), buf, true, PlainText); err != nil {
33214-		t.Fatalf("PrintVersionInfo failed: %v", err)
33215-	}
33216-	res := buf.Bytes()
33217-
33218-	// Other fields of BuildInfo may not be available during test.
33219-	if !bytes.Contains(res, []byte(Version)) || !bytes.Contains(res, []byte(runtime.Version())) {
33220-		t.Errorf("plaintext output = %q,\nwant (version: %v, go: %v)", res, Version, runtime.Version())
33221-	}
33222-}
33223diff -urN a/gopls/internal/lsp/debug/log/log.go b/gopls/internal/lsp/debug/log/log.go
33224--- a/gopls/internal/lsp/debug/log/log.go	2000-01-01 00:00:00.000000000 -0000
33225+++ b/gopls/internal/lsp/debug/log/log.go	1970-01-01 00:00:00.000000000 +0000
33226@@ -1,43 +0,0 @@
33227-// Copyright 2020 The Go Authors. All rights reserved.
33228-// Use of this source code is governed by a BSD-style
33229-// license that can be found in the LICENSE file.
33230-
33231-// Package log provides helper methods for exporting log events to the
33232-// internal/event package.
33233-package log
33234-
33235-import (
33236-	"context"
33237-	"fmt"
33238-
33239-	"golang.org/x/tools/internal/event"
33240-	"golang.org/x/tools/internal/event/label"
33241-	"golang.org/x/tools/internal/event/tag"
33242-)
33243-
33244-// Level parameterizes log severity.
33245-type Level int
33246-
33247-const (
33248-	_ Level = iota
33249-	Error
33250-	Warning
33251-	Info
33252-	Debug
33253-	Trace
33254-)
33255-
33256-// Log exports a log event labeled with level l.
33257-func (l Level) Log(ctx context.Context, msg string) {
33258-	event.Log(ctx, msg, tag.Level.Of(int(l)))
33259-}
33260-
33261-// Logf formats and exports a log event labeled with level l.
33262-func (l Level) Logf(ctx context.Context, format string, args ...interface{}) {
33263-	l.Log(ctx, fmt.Sprintf(format, args...))
33264-}
33265-
33266-// LabeledLevel extracts the labeled log l
33267-func LabeledLevel(lm label.Map) Level {
33268-	return Level(tag.Level.Get(lm))
33269-}
33270diff -urN a/gopls/internal/lsp/debug/metrics.go b/gopls/internal/lsp/debug/metrics.go
33271--- a/gopls/internal/lsp/debug/metrics.go	2000-01-01 00:00:00.000000000 -0000
33272+++ b/gopls/internal/lsp/debug/metrics.go	1970-01-01 00:00:00.000000000 +0000
33273@@ -1,58 +0,0 @@
33274-// Copyright 2019 The Go Authors. All rights reserved.
33275-// Use of this source code is governed by a BSD-style
33276-// license that can be found in the LICENSE file.
33277-
33278-package debug
33279-
33280-import (
33281-	"golang.org/x/tools/internal/event/export/metric"
33282-	"golang.org/x/tools/internal/event/label"
33283-	"golang.org/x/tools/internal/event/tag"
33284-)
33285-
33286-var (
33287-	// the distributions we use for histograms
33288-	bytesDistribution        = []int64{1 << 10, 1 << 11, 1 << 12, 1 << 14, 1 << 16, 1 << 20}
33289-	millisecondsDistribution = []float64{0.1, 0.5, 1, 2, 5, 10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000}
33290-
33291-	receivedBytes = metric.HistogramInt64{
33292-		Name:        "received_bytes",
33293-		Description: "Distribution of received bytes, by method.",
33294-		Keys:        []label.Key{tag.RPCDirection, tag.Method},
33295-		Buckets:     bytesDistribution,
33296-	}
33297-
33298-	sentBytes = metric.HistogramInt64{
33299-		Name:        "sent_bytes",
33300-		Description: "Distribution of sent bytes, by method.",
33301-		Keys:        []label.Key{tag.RPCDirection, tag.Method},
33302-		Buckets:     bytesDistribution,
33303-	}
33304-
33305-	latency = metric.HistogramFloat64{
33306-		Name:        "latency",
33307-		Description: "Distribution of latency in milliseconds, by method.",
33308-		Keys:        []label.Key{tag.RPCDirection, tag.Method},
33309-		Buckets:     millisecondsDistribution,
33310-	}
33311-
33312-	started = metric.Scalar{
33313-		Name:        "started",
33314-		Description: "Count of RPCs started by method.",
33315-		Keys:        []label.Key{tag.RPCDirection, tag.Method},
33316-	}
33317-
33318-	completed = metric.Scalar{
33319-		Name:        "completed",
33320-		Description: "Count of RPCs completed by method and status.",
33321-		Keys:        []label.Key{tag.RPCDirection, tag.Method, tag.StatusCode},
33322-	}
33323-)
33324-
33325-func registerMetrics(m *metric.Config) {
33326-	receivedBytes.Record(m, tag.ReceivedBytes)
33327-	sentBytes.Record(m, tag.SentBytes)
33328-	latency.Record(m, tag.Latency)
33329-	started.Count(m, tag.Started)
33330-	completed.Count(m, tag.Latency)
33331-}
33332diff -urN a/gopls/internal/lsp/debug/rpc.go b/gopls/internal/lsp/debug/rpc.go
33333--- a/gopls/internal/lsp/debug/rpc.go	2000-01-01 00:00:00.000000000 -0000
33334+++ b/gopls/internal/lsp/debug/rpc.go	1970-01-01 00:00:00.000000000 +0000
33335@@ -1,239 +0,0 @@
33336-// Copyright 2019 The Go Authors. All rights reserved.
33337-// Use of this source code is governed by a BSD-style
33338-// license that can be found in the LICENSE file.
33339-
33340-package debug
33341-
33342-import (
33343-	"context"
33344-	"fmt"
33345-	"html/template"
33346-	"net/http"
33347-	"sort"
33348-	"sync"
33349-	"time"
33350-
33351-	"golang.org/x/tools/internal/event"
33352-	"golang.org/x/tools/internal/event/core"
33353-	"golang.org/x/tools/internal/event/export"
33354-	"golang.org/x/tools/internal/event/label"
33355-	"golang.org/x/tools/internal/event/tag"
33356-)
33357-
33358-var RPCTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
33359-{{define "title"}}RPC Information{{end}}
33360-{{define "body"}}
33361-	<H2>Inbound</H2>
33362-	{{template "rpcSection" .Inbound}}
33363-	<H2>Outbound</H2>
33364-	{{template "rpcSection" .Outbound}}
33365-{{end}}
33366-{{define "rpcSection"}}
33367-	{{range .}}<P>
33368-		<b>{{.Method}}</b> {{.Started}} <a href="/trace/{{.Method}}">traces</a> ({{.InProgress}} in progress)
33369-		<br>
33370-		<i>Latency</i> {{with .Latency}}{{.Mean}} ({{.Min}}<{{.Max}}){{end}}
33371-		<i>By bucket</i> 0s {{range .Latency.Values}}{{if gt .Count 0}}<b>{{.Count}}</b> {{.Limit}} {{end}}{{end}}
33372-		<br>
33373-		<i>Received</i> {{.Received}} (avg. {{.ReceivedMean}})
33374-		<i>Sent</i> {{.Sent}} (avg. {{.SentMean}})
33375-		<br>
33376-		<i>Result codes</i> {{range .Codes}}{{.Key}}={{.Count}} {{end}}
33377-		</P>
33378-	{{end}}
33379-{{end}}
33380-`))
33381-
33382-type Rpcs struct { // exported for testing
33383-	mu       sync.Mutex
33384-	Inbound  []*rpcStats // stats for incoming lsp rpcs sorted by method name
33385-	Outbound []*rpcStats // stats for outgoing lsp rpcs sorted by method name
33386-}
33387-
33388-type rpcStats struct {
33389-	Method    string
33390-	Started   int64
33391-	Completed int64
33392-
33393-	Latency  rpcTimeHistogram
33394-	Received byteUnits
33395-	Sent     byteUnits
33396-	Codes    []*rpcCodeBucket
33397-}
33398-
33399-type rpcTimeHistogram struct {
33400-	Sum    timeUnits
33401-	Count  int64
33402-	Min    timeUnits
33403-	Max    timeUnits
33404-	Values []rpcTimeBucket
33405-}
33406-
33407-type rpcTimeBucket struct {
33408-	Limit timeUnits
33409-	Count int64
33410-}
33411-
33412-type rpcCodeBucket struct {
33413-	Key   string
33414-	Count int64
33415-}
33416-
33417-func (r *Rpcs) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context {
33418-	r.mu.Lock()
33419-	defer r.mu.Unlock()
33420-	switch {
33421-	case event.IsStart(ev):
33422-		if _, stats := r.getRPCSpan(ctx, ev); stats != nil {
33423-			stats.Started++
33424-		}
33425-	case event.IsEnd(ev):
33426-		span, stats := r.getRPCSpan(ctx, ev)
33427-		if stats != nil {
33428-			endRPC(ctx, ev, span, stats)
33429-		}
33430-	case event.IsMetric(ev):
33431-		sent := byteUnits(tag.SentBytes.Get(lm))
33432-		rec := byteUnits(tag.ReceivedBytes.Get(lm))
33433-		if sent != 0 || rec != 0 {
33434-			if _, stats := r.getRPCSpan(ctx, ev); stats != nil {
33435-				stats.Sent += sent
33436-				stats.Received += rec
33437-			}
33438-		}
33439-	}
33440-	return ctx
33441-}
33442-
33443-func endRPC(ctx context.Context, ev core.Event, span *export.Span, stats *rpcStats) {
33444-	// update the basic counts
33445-	stats.Completed++
33446-
33447-	// get and record the status code
33448-	if status := getStatusCode(span); status != "" {
33449-		var b *rpcCodeBucket
33450-		for c, entry := range stats.Codes {
33451-			if entry.Key == status {
33452-				b = stats.Codes[c]
33453-				break
33454-			}
33455-		}
33456-		if b == nil {
33457-			b = &rpcCodeBucket{Key: status}
33458-			stats.Codes = append(stats.Codes, b)
33459-			sort.Slice(stats.Codes, func(i int, j int) bool {
33460-				return stats.Codes[i].Key < stats.Codes[j].Key
33461-			})
33462-		}
33463-		b.Count++
33464-	}
33465-
33466-	// calculate latency if this was an rpc span
33467-	elapsedTime := span.Finish().At().Sub(span.Start().At())
33468-	latencyMillis := timeUnits(elapsedTime) / timeUnits(time.Millisecond)
33469-	if stats.Latency.Count == 0 {
33470-		stats.Latency.Min = latencyMillis
33471-		stats.Latency.Max = latencyMillis
33472-	} else {
33473-		if stats.Latency.Min > latencyMillis {
33474-			stats.Latency.Min = latencyMillis
33475-		}
33476-		if stats.Latency.Max < latencyMillis {
33477-			stats.Latency.Max = latencyMillis
33478-		}
33479-	}
33480-	stats.Latency.Count++
33481-	stats.Latency.Sum += latencyMillis
33482-	for i := range stats.Latency.Values {
33483-		if stats.Latency.Values[i].Limit > latencyMillis {
33484-			stats.Latency.Values[i].Count++
33485-			break
33486-		}
33487-	}
33488-}
33489-
33490-func (r *Rpcs) getRPCSpan(ctx context.Context, ev core.Event) (*export.Span, *rpcStats) {
33491-	// get the span
33492-	span := export.GetSpan(ctx)
33493-	if span == nil {
33494-		return nil, nil
33495-	}
33496-	// use the span start event look up the correct stats block
33497-	// we do this because it prevents us matching a sub span
33498-	return span, r.getRPCStats(span.Start())
33499-}
33500-
33501-func (r *Rpcs) getRPCStats(lm label.Map) *rpcStats {
33502-	method := tag.Method.Get(lm)
33503-	if method == "" {
33504-		return nil
33505-	}
33506-	set := &r.Inbound
33507-	if tag.RPCDirection.Get(lm) != tag.Inbound {
33508-		set = &r.Outbound
33509-	}
33510-	// get the record for this method
33511-	index := sort.Search(len(*set), func(i int) bool {
33512-		return (*set)[i].Method >= method
33513-	})
33514-
33515-	if index < len(*set) && (*set)[index].Method == method {
33516-		return (*set)[index]
33517-	}
33518-
33519-	old := *set
33520-	*set = make([]*rpcStats, len(old)+1)
33521-	copy(*set, old[:index])
33522-	copy((*set)[index+1:], old[index:])
33523-	stats := &rpcStats{Method: method}
33524-	stats.Latency.Values = make([]rpcTimeBucket, len(millisecondsDistribution))
33525-	for i, m := range millisecondsDistribution {
33526-		stats.Latency.Values[i].Limit = timeUnits(m)
33527-	}
33528-	(*set)[index] = stats
33529-	return stats
33530-}
33531-
33532-func (s *rpcStats) InProgress() int64       { return s.Started - s.Completed }
33533-func (s *rpcStats) SentMean() byteUnits     { return s.Sent / byteUnits(s.Started) }
33534-func (s *rpcStats) ReceivedMean() byteUnits { return s.Received / byteUnits(s.Started) }
33535-
33536-func (h *rpcTimeHistogram) Mean() timeUnits { return h.Sum / timeUnits(h.Count) }
33537-
33538-func getStatusCode(span *export.Span) string {
33539-	for _, ev := range span.Events() {
33540-		if status := tag.StatusCode.Get(ev); status != "" {
33541-			return status
33542-		}
33543-	}
33544-	return ""
33545-}
33546-
33547-func (r *Rpcs) getData(req *http.Request) interface{} {
33548-	return r
33549-}
33550-
33551-func units(v float64, suffixes []string) string {
33552-	s := ""
33553-	for _, s = range suffixes {
33554-		n := v / 1000
33555-		if n < 1 {
33556-			break
33557-		}
33558-		v = n
33559-	}
33560-	return fmt.Sprintf("%.2f%s", v, s)
33561-}
33562-
33563-type timeUnits float64
33564-
33565-func (v timeUnits) String() string {
33566-	v = v * 1000 * 1000
33567-	return units(float64(v), []string{"ns", "μs", "ms", "s"})
33568-}
33569-
33570-type byteUnits float64
33571-
33572-func (v byteUnits) String() string {
33573-	return units(float64(v), []string{"B", "KB", "MB", "GB", "TB"})
33574-}
33575diff -urN a/gopls/internal/lsp/debug/serve.go b/gopls/internal/lsp/debug/serve.go
33576--- a/gopls/internal/lsp/debug/serve.go	2000-01-01 00:00:00.000000000 -0000
33577+++ b/gopls/internal/lsp/debug/serve.go	1970-01-01 00:00:00.000000000 +0000
33578@@ -1,909 +0,0 @@
33579-// Copyright 2019 The Go Authors. All rights reserved.
33580-// Use of this source code is governed by a BSD-style
33581-// license that can be found in the LICENSE file.
33582-
33583-package debug
33584-
33585-import (
33586-	"archive/zip"
33587-	"bytes"
33588-	"context"
33589-	"errors"
33590-	"fmt"
33591-	"html/template"
33592-	"io"
33593-	stdlog "log"
33594-	"net"
33595-	"net/http"
33596-	"net/http/pprof"
33597-	"os"
33598-	"path"
33599-	"path/filepath"
33600-	"runtime"
33601-	rpprof "runtime/pprof"
33602-	"strconv"
33603-	"strings"
33604-	"sync"
33605-	"time"
33606-
33607-	"golang.org/x/tools/gopls/internal/lsp/cache"
33608-	"golang.org/x/tools/gopls/internal/lsp/debug/log"
33609-	"golang.org/x/tools/gopls/internal/lsp/protocol"
33610-	"golang.org/x/tools/internal/bug"
33611-	"golang.org/x/tools/internal/event"
33612-	"golang.org/x/tools/internal/event/core"
33613-	"golang.org/x/tools/internal/event/export"
33614-	"golang.org/x/tools/internal/event/export/metric"
33615-	"golang.org/x/tools/internal/event/export/ocagent"
33616-	"golang.org/x/tools/internal/event/export/prometheus"
33617-	"golang.org/x/tools/internal/event/keys"
33618-	"golang.org/x/tools/internal/event/label"
33619-	"golang.org/x/tools/internal/event/tag"
33620-)
33621-
33622-type contextKeyType int
33623-
33624-const (
33625-	instanceKey contextKeyType = iota
33626-	traceKey
33627-)
33628-
33629-// An Instance holds all debug information associated with a gopls instance.
33630-type Instance struct {
33631-	Logfile       string
33632-	StartTime     time.Time
33633-	ServerAddress string
33634-	Workdir       string
33635-	OCAgentConfig string
33636-
33637-	LogWriter io.Writer
33638-
33639-	exporter event.Exporter
33640-
33641-	ocagent    *ocagent.Exporter
33642-	prometheus *prometheus.Exporter
33643-	rpcs       *Rpcs
33644-	traces     *traces
33645-	State      *State
33646-
33647-	serveMu              sync.Mutex
33648-	debugAddress         string
33649-	listenedDebugAddress string
33650-}
33651-
33652-// State holds debugging information related to the server state.
33653-type State struct {
33654-	mu      sync.Mutex
33655-	clients []*Client
33656-	servers []*Server
33657-}
33658-
33659-func (st *State) Bugs() []bug.Bug {
33660-	return bug.List()
33661-}
33662-
33663-// Caches returns the set of Cache objects currently being served.
33664-func (st *State) Caches() []*cache.Cache {
33665-	var caches []*cache.Cache
33666-	seen := make(map[string]struct{})
33667-	for _, client := range st.Clients() {
33668-		cache := client.Session.Cache()
33669-		if _, found := seen[cache.ID()]; found {
33670-			continue
33671-		}
33672-		seen[cache.ID()] = struct{}{}
33673-		caches = append(caches, cache)
33674-	}
33675-	return caches
33676-}
33677-
33678-// Cache returns the Cache that matches the supplied id.
33679-func (st *State) Cache(id string) *cache.Cache {
33680-	for _, c := range st.Caches() {
33681-		if c.ID() == id {
33682-			return c
33683-		}
33684-	}
33685-	return nil
33686-}
33687-
33688-// Sessions returns the set of Session objects currently being served.
33689-func (st *State) Sessions() []*cache.Session {
33690-	var sessions []*cache.Session
33691-	for _, client := range st.Clients() {
33692-		sessions = append(sessions, client.Session)
33693-	}
33694-	return sessions
33695-}
33696-
33697-// Session returns the Session that matches the supplied id.
33698-func (st *State) Session(id string) *cache.Session {
33699-	for _, s := range st.Sessions() {
33700-		if s.ID() == id {
33701-			return s
33702-		}
33703-	}
33704-	return nil
33705-}
33706-
33707-// Views returns the set of View objects currently being served.
33708-func (st *State) Views() []*cache.View {
33709-	var views []*cache.View
33710-	for _, s := range st.Sessions() {
33711-		views = append(views, s.Views()...)
33712-	}
33713-	return views
33714-}
33715-
33716-// View returns the View that matches the supplied id.
33717-func (st *State) View(id string) *cache.View {
33718-	for _, v := range st.Views() {
33719-		if v.ID() == id {
33720-			return v
33721-		}
33722-	}
33723-	return nil
33724-}
33725-
33726-// Clients returns the set of Clients currently being served.
33727-func (st *State) Clients() []*Client {
33728-	st.mu.Lock()
33729-	defer st.mu.Unlock()
33730-	clients := make([]*Client, len(st.clients))
33731-	copy(clients, st.clients)
33732-	return clients
33733-}
33734-
33735-// Client returns the Client matching the supplied id.
33736-func (st *State) Client(id string) *Client {
33737-	for _, c := range st.Clients() {
33738-		if c.Session.ID() == id {
33739-			return c
33740-		}
33741-	}
33742-	return nil
33743-}
33744-
33745-// Servers returns the set of Servers the instance is currently connected to.
33746-func (st *State) Servers() []*Server {
33747-	st.mu.Lock()
33748-	defer st.mu.Unlock()
33749-	servers := make([]*Server, len(st.servers))
33750-	copy(servers, st.servers)
33751-	return servers
33752-}
33753-
33754-// A Client is an incoming connection from a remote client.
33755-type Client struct {
33756-	Session      *cache.Session
33757-	DebugAddress string
33758-	Logfile      string
33759-	GoplsPath    string
33760-	ServerID     string
33761-	Service      protocol.Server
33762-}
33763-
33764-// A Server is an outgoing connection to a remote LSP server.
33765-type Server struct {
33766-	ID           string
33767-	DebugAddress string
33768-	Logfile      string
33769-	GoplsPath    string
33770-	ClientID     string
33771-}
33772-
33773-// addClient adds a client to the set being served.
33774-func (st *State) addClient(session *cache.Session) {
33775-	st.mu.Lock()
33776-	defer st.mu.Unlock()
33777-	st.clients = append(st.clients, &Client{Session: session})
33778-}
33779-
33780-// dropClient removes a client from the set being served.
33781-func (st *State) dropClient(session *cache.Session) {
33782-	st.mu.Lock()
33783-	defer st.mu.Unlock()
33784-	for i, c := range st.clients {
33785-		if c.Session == session {
33786-			copy(st.clients[i:], st.clients[i+1:])
33787-			st.clients[len(st.clients)-1] = nil
33788-			st.clients = st.clients[:len(st.clients)-1]
33789-			return
33790-		}
33791-	}
33792-}
33793-
33794-// updateServer updates a server to the set being queried. In practice, there should
33795-// be at most one remote server.
33796-func (st *State) updateServer(server *Server) {
33797-	st.mu.Lock()
33798-	defer st.mu.Unlock()
33799-	for i, existing := range st.servers {
33800-		if existing.ID == server.ID {
33801-			// Replace, rather than mutate, to avoid a race.
33802-			newServers := make([]*Server, len(st.servers))
33803-			copy(newServers, st.servers[:i])
33804-			newServers[i] = server
33805-			copy(newServers[i+1:], st.servers[i+1:])
33806-			st.servers = newServers
33807-			return
33808-		}
33809-	}
33810-	st.servers = append(st.servers, server)
33811-}
33812-
33813-// dropServer drops a server from the set being queried.
33814-func (st *State) dropServer(id string) {
33815-	st.mu.Lock()
33816-	defer st.mu.Unlock()
33817-	for i, s := range st.servers {
33818-		if s.ID == id {
33819-			copy(st.servers[i:], st.servers[i+1:])
33820-			st.servers[len(st.servers)-1] = nil
33821-			st.servers = st.servers[:len(st.servers)-1]
33822-			return
33823-		}
33824-	}
33825-}
33826-
33827-// an http.ResponseWriter that filters writes
33828-type filterResponse struct {
33829-	w    http.ResponseWriter
33830-	edit func([]byte) []byte
33831-}
33832-
33833-func (c filterResponse) Header() http.Header {
33834-	return c.w.Header()
33835-}
33836-
33837-func (c filterResponse) Write(buf []byte) (int, error) {
33838-	ans := c.edit(buf)
33839-	return c.w.Write(ans)
33840-}
33841-
33842-func (c filterResponse) WriteHeader(n int) {
33843-	c.w.WriteHeader(n)
33844-}
33845-
33846-// replace annoying nuls by spaces
33847-func cmdline(w http.ResponseWriter, r *http.Request) {
33848-	fake := filterResponse{
33849-		w: w,
33850-		edit: func(buf []byte) []byte {
33851-			return bytes.ReplaceAll(buf, []byte{0}, []byte{' '})
33852-		},
33853-	}
33854-	pprof.Cmdline(fake, r)
33855-}
33856-
33857-func (i *Instance) getCache(r *http.Request) interface{} {
33858-	return i.State.Cache(path.Base(r.URL.Path))
33859-}
33860-
33861-func (i *Instance) getSession(r *http.Request) interface{} {
33862-	return i.State.Session(path.Base(r.URL.Path))
33863-}
33864-
33865-func (i *Instance) getClient(r *http.Request) interface{} {
33866-	return i.State.Client(path.Base(r.URL.Path))
33867-}
33868-
33869-func (i *Instance) getServer(r *http.Request) interface{} {
33870-	i.State.mu.Lock()
33871-	defer i.State.mu.Unlock()
33872-	id := path.Base(r.URL.Path)
33873-	for _, s := range i.State.servers {
33874-		if s.ID == id {
33875-			return s
33876-		}
33877-	}
33878-	return nil
33879-}
33880-
33881-func (i *Instance) getView(r *http.Request) interface{} {
33882-	return i.State.View(path.Base(r.URL.Path))
33883-}
33884-
33885-func (i *Instance) getFile(r *http.Request) interface{} {
33886-	identifier := path.Base(r.URL.Path)
33887-	sid := path.Base(path.Dir(r.URL.Path))
33888-	s := i.State.Session(sid)
33889-	if s == nil {
33890-		return nil
33891-	}
33892-	for _, o := range s.Overlays() {
33893-		// TODO(adonovan): understand and document this comparison.
33894-		if o.FileIdentity().Hash.String() == identifier {
33895-			return o
33896-		}
33897-	}
33898-	return nil
33899-}
33900-
33901-func (i *Instance) getInfo(r *http.Request) interface{} {
33902-	buf := &bytes.Buffer{}
33903-	i.PrintServerInfo(r.Context(), buf)
33904-	return template.HTML(buf.String())
33905-}
33906-
33907-func (i *Instance) AddService(s protocol.Server, session *cache.Session) {
33908-	for _, c := range i.State.clients {
33909-		if c.Session == session {
33910-			c.Service = s
33911-			return
33912-		}
33913-	}
33914-	stdlog.Printf("unable to find a Client to add the protocol.Server to")
33915-}
33916-
33917-func getMemory(_ *http.Request) interface{} {
33918-	var m runtime.MemStats
33919-	runtime.ReadMemStats(&m)
33920-	return m
33921-}
33922-
33923-func init() {
33924-	event.SetExporter(makeGlobalExporter(os.Stderr))
33925-}
33926-
33927-func GetInstance(ctx context.Context) *Instance {
33928-	if ctx == nil {
33929-		return nil
33930-	}
33931-	v := ctx.Value(instanceKey)
33932-	if v == nil {
33933-		return nil
33934-	}
33935-	return v.(*Instance)
33936-}
33937-
33938-// WithInstance creates debug instance ready for use using the supplied
33939-// configuration and stores it in the returned context.
33940-func WithInstance(ctx context.Context, workdir, agent string) context.Context {
33941-	i := &Instance{
33942-		StartTime:     time.Now(),
33943-		Workdir:       workdir,
33944-		OCAgentConfig: agent,
33945-	}
33946-	i.LogWriter = os.Stderr
33947-	ocConfig := ocagent.Discover()
33948-	//TODO: we should not need to adjust the discovered configuration
33949-	ocConfig.Address = i.OCAgentConfig
33950-	i.ocagent = ocagent.Connect(ocConfig)
33951-	i.prometheus = prometheus.New()
33952-	i.rpcs = &Rpcs{}
33953-	i.traces = &traces{}
33954-	i.State = &State{}
33955-	i.exporter = makeInstanceExporter(i)
33956-	return context.WithValue(ctx, instanceKey, i)
33957-}
33958-
33959-// SetLogFile sets the logfile for use with this instance.
33960-func (i *Instance) SetLogFile(logfile string, isDaemon bool) (func(), error) {
33961-	// TODO: probably a better solution for deferring closure to the caller would
33962-	// be for the debug instance to itself be closed, but this fixes the
33963-	// immediate bug of logs not being captured.
33964-	closeLog := func() {}
33965-	if logfile != "" {
33966-		if logfile == "auto" {
33967-			if isDaemon {
33968-				logfile = filepath.Join(os.TempDir(), fmt.Sprintf("gopls-daemon-%d.log", os.Getpid()))
33969-			} else {
33970-				logfile = filepath.Join(os.TempDir(), fmt.Sprintf("gopls-%d.log", os.Getpid()))
33971-			}
33972-		}
33973-		f, err := os.Create(logfile)
33974-		if err != nil {
33975-			return nil, fmt.Errorf("unable to create log file: %w", err)
33976-		}
33977-		closeLog = func() {
33978-			defer f.Close()
33979-		}
33980-		stdlog.SetOutput(io.MultiWriter(os.Stderr, f))
33981-		i.LogWriter = f
33982-	}
33983-	i.Logfile = logfile
33984-	return closeLog, nil
33985-}
33986-
33987-// Serve starts and runs a debug server in the background on the given addr.
33988-// It also logs the port the server starts on, to allow for :0 auto assigned
33989-// ports.
33990-func (i *Instance) Serve(ctx context.Context, addr string) (string, error) {
33991-	stdlog.SetFlags(stdlog.Lshortfile)
33992-	if addr == "" {
33993-		return "", nil
33994-	}
33995-	i.serveMu.Lock()
33996-	defer i.serveMu.Unlock()
33997-
33998-	if i.listenedDebugAddress != "" {
33999-		// Already serving. Return the bound address.
34000-		return i.listenedDebugAddress, nil
34001-	}
34002-
34003-	i.debugAddress = addr
34004-	listener, err := net.Listen("tcp", i.debugAddress)
34005-	if err != nil {
34006-		return "", err
34007-	}
34008-	i.listenedDebugAddress = listener.Addr().String()
34009-
34010-	port := listener.Addr().(*net.TCPAddr).Port
34011-	if strings.HasSuffix(i.debugAddress, ":0") {
34012-		stdlog.Printf("debug server listening at http://localhost:%d", port)
34013-	}
34014-	event.Log(ctx, "Debug serving", tag.Port.Of(port))
34015-	go func() {
34016-		mux := http.NewServeMux()
34017-		mux.HandleFunc("/", render(MainTmpl, func(*http.Request) interface{} { return i }))
34018-		mux.HandleFunc("/debug/", render(DebugTmpl, nil))
34019-		mux.HandleFunc("/debug/pprof/", pprof.Index)
34020-		mux.HandleFunc("/debug/pprof/cmdline", cmdline)
34021-		mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
34022-		mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
34023-		mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
34024-		if i.prometheus != nil {
34025-			mux.HandleFunc("/metrics/", i.prometheus.Serve)
34026-		}
34027-		if i.rpcs != nil {
34028-			mux.HandleFunc("/rpc/", render(RPCTmpl, i.rpcs.getData))
34029-		}
34030-		if i.traces != nil {
34031-			mux.HandleFunc("/trace/", render(TraceTmpl, i.traces.getData))
34032-		}
34033-		mux.HandleFunc("/cache/", render(CacheTmpl, i.getCache))
34034-		mux.HandleFunc("/session/", render(SessionTmpl, i.getSession))
34035-		mux.HandleFunc("/view/", render(ViewTmpl, i.getView))
34036-		mux.HandleFunc("/client/", render(ClientTmpl, i.getClient))
34037-		mux.HandleFunc("/server/", render(ServerTmpl, i.getServer))
34038-		mux.HandleFunc("/file/", render(FileTmpl, i.getFile))
34039-		mux.HandleFunc("/info", render(InfoTmpl, i.getInfo))
34040-		mux.HandleFunc("/memory", render(MemoryTmpl, getMemory))
34041-
34042-		// Internal debugging helpers.
34043-		mux.HandleFunc("/_dogc", func(w http.ResponseWriter, r *http.Request) {
34044-			runtime.GC()
34045-			runtime.GC()
34046-			runtime.GC()
34047-			http.Error(w, "OK", 200)
34048-		})
34049-		mux.HandleFunc("/_makeabug", func(w http.ResponseWriter, r *http.Request) {
34050-			bug.Report("bug here", nil)
34051-			http.Error(w, "made a bug", http.StatusOK)
34052-		})
34053-
34054-		if err := http.Serve(listener, mux); err != nil {
34055-			event.Error(ctx, "Debug server failed", err)
34056-			return
34057-		}
34058-		event.Log(ctx, "Debug server finished")
34059-	}()
34060-	return i.listenedDebugAddress, nil
34061-}
34062-
34063-func (i *Instance) DebugAddress() string {
34064-	i.serveMu.Lock()
34065-	defer i.serveMu.Unlock()
34066-	return i.debugAddress
34067-}
34068-
34069-func (i *Instance) ListenedDebugAddress() string {
34070-	i.serveMu.Lock()
34071-	defer i.serveMu.Unlock()
34072-	return i.listenedDebugAddress
34073-}
34074-
34075-// MonitorMemory starts recording memory statistics each second.
34076-func (i *Instance) MonitorMemory(ctx context.Context) {
34077-	tick := time.NewTicker(time.Second)
34078-	nextThresholdGiB := uint64(1)
34079-	go func() {
34080-		for {
34081-			<-tick.C
34082-			var mem runtime.MemStats
34083-			runtime.ReadMemStats(&mem)
34084-			if mem.HeapAlloc < nextThresholdGiB*1<<30 {
34085-				continue
34086-			}
34087-			if err := i.writeMemoryDebug(nextThresholdGiB, true); err != nil {
34088-				event.Error(ctx, "writing memory debug info", err)
34089-			}
34090-			if err := i.writeMemoryDebug(nextThresholdGiB, false); err != nil {
34091-				event.Error(ctx, "writing memory debug info", err)
34092-			}
34093-			event.Log(ctx, fmt.Sprintf("Wrote memory usage debug info to %v", os.TempDir()))
34094-			nextThresholdGiB++
34095-		}
34096-	}()
34097-}
34098-
34099-func (i *Instance) writeMemoryDebug(threshold uint64, withNames bool) error {
34100-	suffix := "withnames"
34101-	if !withNames {
34102-		suffix = "nonames"
34103-	}
34104-
34105-	filename := fmt.Sprintf("gopls.%d-%dGiB-%s.zip", os.Getpid(), threshold, suffix)
34106-	zipf, err := os.OpenFile(filepath.Join(os.TempDir(), filename), os.O_CREATE|os.O_RDWR, 0644)
34107-	if err != nil {
34108-		return err
34109-	}
34110-	zipw := zip.NewWriter(zipf)
34111-
34112-	f, err := zipw.Create("heap.pb.gz")
34113-	if err != nil {
34114-		return err
34115-	}
34116-	if err := rpprof.Lookup("heap").WriteTo(f, 0); err != nil {
34117-		return err
34118-	}
34119-
34120-	f, err = zipw.Create("goroutines.txt")
34121-	if err != nil {
34122-		return err
34123-	}
34124-	if err := rpprof.Lookup("goroutine").WriteTo(f, 1); err != nil {
34125-		return err
34126-	}
34127-
34128-	if err := zipw.Close(); err != nil {
34129-		return err
34130-	}
34131-	return zipf.Close()
34132-}
34133-
34134-func makeGlobalExporter(stderr io.Writer) event.Exporter {
34135-	p := export.Printer{}
34136-	var pMu sync.Mutex
34137-	return func(ctx context.Context, ev core.Event, lm label.Map) context.Context {
34138-		i := GetInstance(ctx)
34139-
34140-		if event.IsLog(ev) {
34141-			// Don't log context cancellation errors.
34142-			if err := keys.Err.Get(ev); errors.Is(err, context.Canceled) {
34143-				return ctx
34144-			}
34145-			// Make sure any log messages without an instance go to stderr.
34146-			if i == nil {
34147-				pMu.Lock()
34148-				p.WriteEvent(stderr, ev, lm)
34149-				pMu.Unlock()
34150-			}
34151-			level := log.LabeledLevel(lm)
34152-			// Exclude trace logs from LSP logs.
34153-			if level < log.Trace {
34154-				ctx = protocol.LogEvent(ctx, ev, lm, messageType(level))
34155-			}
34156-		}
34157-		if i == nil {
34158-			return ctx
34159-		}
34160-		return i.exporter(ctx, ev, lm)
34161-	}
34162-}
34163-
34164-func messageType(l log.Level) protocol.MessageType {
34165-	switch l {
34166-	case log.Error:
34167-		return protocol.Error
34168-	case log.Warning:
34169-		return protocol.Warning
34170-	case log.Debug:
34171-		return protocol.Log
34172-	}
34173-	return protocol.Info
34174-}
34175-
34176-func makeInstanceExporter(i *Instance) event.Exporter {
34177-	exporter := func(ctx context.Context, ev core.Event, lm label.Map) context.Context {
34178-		if i.ocagent != nil {
34179-			ctx = i.ocagent.ProcessEvent(ctx, ev, lm)
34180-		}
34181-		if i.prometheus != nil {
34182-			ctx = i.prometheus.ProcessEvent(ctx, ev, lm)
34183-		}
34184-		if i.rpcs != nil {
34185-			ctx = i.rpcs.ProcessEvent(ctx, ev, lm)
34186-		}
34187-		if i.traces != nil {
34188-			ctx = i.traces.ProcessEvent(ctx, ev, lm)
34189-		}
34190-		if event.IsLog(ev) {
34191-			if s := cache.KeyCreateSession.Get(ev); s != nil {
34192-				i.State.addClient(s)
34193-			}
34194-			if sid := tag.NewServer.Get(ev); sid != "" {
34195-				i.State.updateServer(&Server{
34196-					ID:           sid,
34197-					Logfile:      tag.Logfile.Get(ev),
34198-					DebugAddress: tag.DebugAddress.Get(ev),
34199-					GoplsPath:    tag.GoplsPath.Get(ev),
34200-					ClientID:     tag.ClientID.Get(ev),
34201-				})
34202-			}
34203-			if s := cache.KeyShutdownSession.Get(ev); s != nil {
34204-				i.State.dropClient(s)
34205-			}
34206-			if sid := tag.EndServer.Get(ev); sid != "" {
34207-				i.State.dropServer(sid)
34208-			}
34209-			if s := cache.KeyUpdateSession.Get(ev); s != nil {
34210-				if c := i.State.Client(s.ID()); c != nil {
34211-					c.DebugAddress = tag.DebugAddress.Get(ev)
34212-					c.Logfile = tag.Logfile.Get(ev)
34213-					c.ServerID = tag.ServerID.Get(ev)
34214-					c.GoplsPath = tag.GoplsPath.Get(ev)
34215-				}
34216-			}
34217-		}
34218-		return ctx
34219-	}
34220-	// StdTrace must be above export.Spans below (by convention, export
34221-	// middleware applies its wrapped exporter last).
34222-	exporter = StdTrace(exporter)
34223-	metrics := metric.Config{}
34224-	registerMetrics(&metrics)
34225-	exporter = metrics.Exporter(exporter)
34226-	exporter = export.Spans(exporter)
34227-	exporter = export.Labels(exporter)
34228-	return exporter
34229-}
34230-
34231-type dataFunc func(*http.Request) interface{}
34232-
34233-func render(tmpl *template.Template, fun dataFunc) func(http.ResponseWriter, *http.Request) {
34234-	return func(w http.ResponseWriter, r *http.Request) {
34235-		var data interface{}
34236-		if fun != nil {
34237-			data = fun(r)
34238-		}
34239-		if err := tmpl.Execute(w, data); err != nil {
34240-			event.Error(context.Background(), "", err)
34241-			http.Error(w, err.Error(), http.StatusInternalServerError)
34242-		}
34243-	}
34244-}
34245-
34246-func commas(s string) string {
34247-	for i := len(s); i > 3; {
34248-		i -= 3
34249-		s = s[:i] + "," + s[i:]
34250-	}
34251-	return s
34252-}
34253-
34254-func fuint64(v uint64) string {
34255-	return commas(strconv.FormatUint(v, 10))
34256-}
34257-
34258-func fuint32(v uint32) string {
34259-	return commas(strconv.FormatUint(uint64(v), 10))
34260-}
34261-
34262-func fcontent(v []byte) string {
34263-	return string(v)
34264-}
34265-
34266-var BaseTemplate = template.Must(template.New("").Parse(`
34267-<html>
34268-<head>
34269-<title>{{template "title" .}}</title>
34270-<style>
34271-.profile-name{
34272-	display:inline-block;
34273-	width:6rem;
34274-}
34275-td.value {
34276-  text-align: right;
34277-}
34278-ul.events {
34279-	list-style-type: none;
34280-}
34281-
34282-</style>
34283-{{block "head" .}}{{end}}
34284-</head>
34285-<body>
34286-<a href="/">Main</a>
34287-<a href="/info">Info</a>
34288-<a href="/memory">Memory</a>
34289-<a href="/metrics">Metrics</a>
34290-<a href="/rpc">RPC</a>
34291-<a href="/trace">Trace</a>
34292-<hr>
34293-<h1>{{template "title" .}}</h1>
34294-{{block "body" .}}
34295-Unknown page
34296-{{end}}
34297-</body>
34298-</html>
34299-
34300-{{define "cachelink"}}<a href="/cache/{{.}}">Cache {{.}}</a>{{end}}
34301-{{define "clientlink"}}<a href="/client/{{.}}">Client {{.}}</a>{{end}}
34302-{{define "serverlink"}}<a href="/server/{{.}}">Server {{.}}</a>{{end}}
34303-{{define "sessionlink"}}<a href="/session/{{.}}">Session {{.}}</a>{{end}}
34304-{{define "viewlink"}}<a href="/view/{{.}}">View {{.}}</a>{{end}}
34305-`)).Funcs(template.FuncMap{
34306-	"fuint64":  fuint64,
34307-	"fuint32":  fuint32,
34308-	"fcontent": fcontent,
34309-	"localAddress": func(s string) string {
34310-		// Try to translate loopback addresses to localhost, both for cosmetics and
34311-		// because unspecified ipv6 addresses can break links on Windows.
34312-		//
34313-		// TODO(rfindley): In the future, it would be better not to assume the
34314-		// server is running on localhost, and instead construct this address using
34315-		// the remote host.
34316-		host, port, err := net.SplitHostPort(s)
34317-		if err != nil {
34318-			return s
34319-		}
34320-		ip := net.ParseIP(host)
34321-		if ip == nil {
34322-			return s
34323-		}
34324-		if ip.IsLoopback() || ip.IsUnspecified() {
34325-			return "localhost:" + port
34326-		}
34327-		return s
34328-	},
34329-	"options": func(s *cache.Session) []sessionOption {
34330-		return showOptions(s.Options())
34331-	},
34332-})
34333-
34334-var MainTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
34335-{{define "title"}}GoPls server information{{end}}
34336-{{define "body"}}
34337-<h2>Caches</h2>
34338-<ul>{{range .State.Caches}}<li>{{template "cachelink" .ID}}</li>{{end}}</ul>
34339-<h2>Sessions</h2>
34340-<ul>{{range .State.Sessions}}<li>{{template "sessionlink" .ID}} from {{template "cachelink" .Cache.ID}}</li>{{end}}</ul>
34341-<h2>Clients</h2>
34342-<ul>{{range .State.Clients}}<li>{{template "clientlink" .Session.ID}}</li>{{end}}</ul>
34343-<h2>Servers</h2>
34344-<ul>{{range .State.Servers}}<li>{{template "serverlink" .ID}}</li>{{end}}</ul>
34345-<h2>Bug reports</h2>
34346-<dl>{{range .State.Bugs}}<dt>{{.Key}}</dt><dd>{{.Description}}</dd>{{end}}</dl>
34347-{{end}}
34348-`))
34349-
34350-var InfoTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
34351-{{define "title"}}GoPls version information{{end}}
34352-{{define "body"}}
34353-{{.}}
34354-{{end}}
34355-`))
34356-
34357-var MemoryTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
34358-{{define "title"}}GoPls memory usage{{end}}
34359-{{define "head"}}<meta http-equiv="refresh" content="5">{{end}}
34360-{{define "body"}}
34361-<h2>Stats</h2>
34362-<table>
34363-<tr><td class="label">Allocated bytes</td><td class="value">{{fuint64 .HeapAlloc}}</td></tr>
34364-<tr><td class="label">Total allocated bytes</td><td class="value">{{fuint64 .TotalAlloc}}</td></tr>
34365-<tr><td class="label">System bytes</td><td class="value">{{fuint64 .Sys}}</td></tr>
34366-<tr><td class="label">Heap system bytes</td><td class="value">{{fuint64 .HeapSys}}</td></tr>
34367-<tr><td class="label">Malloc calls</td><td class="value">{{fuint64 .Mallocs}}</td></tr>
34368-<tr><td class="label">Frees</td><td class="value">{{fuint64 .Frees}}</td></tr>
34369-<tr><td class="label">Idle heap bytes</td><td class="value">{{fuint64 .HeapIdle}}</td></tr>
34370-<tr><td class="label">In use bytes</td><td class="value">{{fuint64 .HeapInuse}}</td></tr>
34371-<tr><td class="label">Released to system bytes</td><td class="value">{{fuint64 .HeapReleased}}</td></tr>
34372-<tr><td class="label">Heap object count</td><td class="value">{{fuint64 .HeapObjects}}</td></tr>
34373-<tr><td class="label">Stack in use bytes</td><td class="value">{{fuint64 .StackInuse}}</td></tr>
34374-<tr><td class="label">Stack from system bytes</td><td class="value">{{fuint64 .StackSys}}</td></tr>
34375-<tr><td class="label">Bucket hash bytes</td><td class="value">{{fuint64 .BuckHashSys}}</td></tr>
34376-<tr><td class="label">GC metadata bytes</td><td class="value">{{fuint64 .GCSys}}</td></tr>
34377-<tr><td class="label">Off heap bytes</td><td class="value">{{fuint64 .OtherSys}}</td></tr>
34378-</table>
34379-<h2>By size</h2>
34380-<table>
34381-<tr><th>Size</th><th>Mallocs</th><th>Frees</th></tr>
34382-{{range .BySize}}<tr><td class="value">{{fuint32 .Size}}</td><td class="value">{{fuint64 .Mallocs}}</td><td class="value">{{fuint64 .Frees}}</td></tr>{{end}}
34383-</table>
34384-{{end}}
34385-`))
34386-
34387-var DebugTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
34388-{{define "title"}}GoPls Debug pages{{end}}
34389-{{define "body"}}
34390-<a href="/debug/pprof">Profiling</a>
34391-{{end}}
34392-`))
34393-
34394-var CacheTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
34395-{{define "title"}}Cache {{.ID}}{{end}}
34396-{{define "body"}}
34397-<h2>memoize.Store entries</h2>
34398-<ul>{{range $k,$v := .MemStats}}<li>{{$k}} - {{$v}}</li>{{end}}</ul>
34399-{{end}}
34400-`))
34401-
34402-var ClientTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
34403-{{define "title"}}Client {{.Session.ID}}{{end}}
34404-{{define "body"}}
34405-Using session: <b>{{template "sessionlink" .Session.ID}}</b><br>
34406-{{if .DebugAddress}}Debug this client at: <a href="http://{{localAddress .DebugAddress}}">{{localAddress .DebugAddress}}</a><br>{{end}}
34407-Logfile: {{.Logfile}}<br>
34408-Gopls Path: {{.GoplsPath}}<br>
34409-<h2>Diagnostics</h2>
34410-{{/*Service: []protocol.Server; each server has map[uri]fileReports;
34411-	each fileReport: map[diagnosticSoure]diagnosticReport
34412-	diagnosticSource is one of 5 source
34413-	diagnosticReport: snapshotID and map[hash]*source.Diagnostic
34414-	sourceDiagnostic: struct {
34415-		Range    protocol.Range
34416-		Message  string
34417-		Source   string
34418-		Code     string
34419-		CodeHref string
34420-		Severity protocol.DiagnosticSeverity
34421-		Tags     []protocol.DiagnosticTag
34422-
34423-		Related []RelatedInformation
34424-	}
34425-	RelatedInformation: struct {
34426-		URI     span.URI
34427-		Range   protocol.Range
34428-		Message string
34429-	}
34430-	*/}}
34431-<ul>{{range $k, $v := .Service.Diagnostics}}<li>{{$k}}:<ol>{{range $v}}<li>{{.}}</li>{{end}}</ol></li>{{end}}</ul>
34432-{{end}}
34433-`))
34434-
34435-var ServerTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
34436-{{define "title"}}Server {{.ID}}{{end}}
34437-{{define "body"}}
34438-{{if .DebugAddress}}Debug this server at: <a href="http://{{localAddress .DebugAddress}}">{{localAddress .DebugAddress}}</a><br>{{end}}
34439-Logfile: {{.Logfile}}<br>
34440-Gopls Path: {{.GoplsPath}}<br>
34441-{{end}}
34442-`))
34443-
34444-var SessionTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
34445-{{define "title"}}Session {{.ID}}{{end}}
34446-{{define "body"}}
34447-From: <b>{{template "cachelink" .Cache.ID}}</b><br>
34448-<h2>Views</h2>
34449-<ul>{{range .Views}}<li>{{.Name}} is {{template "viewlink" .ID}} in {{.Folder}}</li>{{end}}</ul>
34450-<h2>Overlays</h2>
34451-{{$session := .}}
34452-<ul>{{range .Overlays}}
34453-<li>
34454-<a href="/file/{{$session.ID}}/{{.FileIdentity.Hash}}">{{.FileIdentity.URI}}</a>
34455-</li>{{end}}</ul>
34456-<h2>Options</h2>
34457-{{range options .}}
34458-<p><b>{{.Name}}</b> {{.Type}}</p>
34459-<p><i>default:</i> {{.Default}}</p>
34460-{{if ne .Default .Current}}<p><i>current:</i> {{.Current}}</p>{{end}}
34461-{{end}}
34462-{{end}}
34463-`))
34464-
34465-var ViewTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
34466-{{define "title"}}View {{.ID}}{{end}}
34467-{{define "body"}}
34468-Name: <b>{{.Name}}</b><br>
34469-Folder: <b>{{.Folder}}</b><br>
34470-<h2>Environment</h2>
34471-<ul>{{range .Options.Env}}<li>{{.}}</li>{{end}}</ul>
34472-{{end}}
34473-`))
34474-
34475-var FileTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
34476-{{define "title"}}Overlay {{.FileIdentity.Hash}}{{end}}
34477-{{define "body"}}
34478-{{with .}}
34479-	URI: <b>{{.URI}}</b><br>
34480-	Identifier: <b>{{.FileIdentity.Hash}}</b><br>
34481-	Version: <b>{{.Version}}</b><br>
34482-	Kind: <b>{{.Kind}}</b><br>
34483-{{end}}
34484-<h3>Contents</h3>
34485-<pre>{{fcontent .Read}}</pre>
34486-{{end}}
34487-`))
34488diff -urN a/gopls/internal/lsp/debug/trace.go b/gopls/internal/lsp/debug/trace.go
34489--- a/gopls/internal/lsp/debug/trace.go	2000-01-01 00:00:00.000000000 -0000
34490+++ b/gopls/internal/lsp/debug/trace.go	1970-01-01 00:00:00.000000000 +0000
34491@@ -1,233 +0,0 @@
34492-// Copyright 2019 The Go Authors. All rights reserved.
34493-// Use of this source code is governed by a BSD-style
34494-// license that can be found in the LICENSE file.
34495-
34496-package debug
34497-
34498-import (
34499-	"bytes"
34500-	"context"
34501-	"fmt"
34502-	"html/template"
34503-	"net/http"
34504-	"runtime/trace"
34505-	"sort"
34506-	"strings"
34507-	"sync"
34508-	"time"
34509-
34510-	"golang.org/x/tools/internal/event"
34511-	"golang.org/x/tools/internal/event/core"
34512-	"golang.org/x/tools/internal/event/export"
34513-	"golang.org/x/tools/internal/event/label"
34514-)
34515-
34516-var TraceTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
34517-{{define "title"}}Trace Information{{end}}
34518-{{define "body"}}
34519-	{{range .Traces}}<a href="/trace/{{.Name}}">{{.Name}}</a> last: {{.Last.Duration}}, longest: {{.Longest.Duration}}<br>{{end}}
34520-	{{if .Selected}}
34521-		<H2>{{.Selected.Name}}</H2>
34522-		{{if .Selected.Last}}<H3>Last</H3><ul>{{template "details" .Selected.Last}}</ul>{{end}}
34523-		{{if .Selected.Longest}}<H3>Longest</H3><ul>{{template "details" .Selected.Longest}}</ul>{{end}}
34524-	{{end}}
34525-{{end}}
34526-{{define "details"}}
34527-	<li>{{.Offset}} {{.Name}} {{.Duration}} {{.Tags}}</li>
34528-	{{if .Events}}<ul class=events>{{range .Events}}<li>{{.Offset}} {{.Tags}}</li>{{end}}</ul>{{end}}
34529-	{{if .Children}}<ul>{{range .Children}}{{template "details" .}}{{end}}</ul>{{end}}
34530-{{end}}
34531-`))
34532-
34533-type traces struct {
34534-	mu         sync.Mutex
34535-	sets       map[string]*traceSet
34536-	unfinished map[export.SpanContext]*traceData
34537-}
34538-
34539-type TraceResults struct { // exported for testing
34540-	Traces   []*traceSet
34541-	Selected *traceSet
34542-}
34543-
34544-type traceSet struct {
34545-	Name    string
34546-	Last    *traceData
34547-	Longest *traceData
34548-}
34549-
34550-type traceData struct {
34551-	TraceID  export.TraceID
34552-	SpanID   export.SpanID
34553-	ParentID export.SpanID
34554-	Name     string
34555-	Start    time.Time
34556-	Finish   time.Time
34557-	Offset   time.Duration
34558-	Duration time.Duration
34559-	Tags     string
34560-	Events   []traceEvent
34561-	Children []*traceData
34562-}
34563-
34564-type traceEvent struct {
34565-	Time   time.Time
34566-	Offset time.Duration
34567-	Tags   string
34568-}
34569-
34570-func StdTrace(exporter event.Exporter) event.Exporter {
34571-	return func(ctx context.Context, ev core.Event, lm label.Map) context.Context {
34572-		span := export.GetSpan(ctx)
34573-		if span == nil {
34574-			return exporter(ctx, ev, lm)
34575-		}
34576-		switch {
34577-		case event.IsStart(ev):
34578-			if span.ParentID.IsValid() {
34579-				region := trace.StartRegion(ctx, span.Name)
34580-				ctx = context.WithValue(ctx, traceKey, region)
34581-			} else {
34582-				var task *trace.Task
34583-				ctx, task = trace.NewTask(ctx, span.Name)
34584-				ctx = context.WithValue(ctx, traceKey, task)
34585-			}
34586-			// Log the start event as it may contain useful labels.
34587-			msg := formatEvent(ctx, ev, lm)
34588-			trace.Log(ctx, "start", msg)
34589-		case event.IsLog(ev):
34590-			category := ""
34591-			if event.IsError(ev) {
34592-				category = "error"
34593-			}
34594-			msg := formatEvent(ctx, ev, lm)
34595-			trace.Log(ctx, category, msg)
34596-		case event.IsEnd(ev):
34597-			if v := ctx.Value(traceKey); v != nil {
34598-				v.(interface{ End() }).End()
34599-			}
34600-		}
34601-		return exporter(ctx, ev, lm)
34602-	}
34603-}
34604-
34605-func formatEvent(ctx context.Context, ev core.Event, lm label.Map) string {
34606-	buf := &bytes.Buffer{}
34607-	p := export.Printer{}
34608-	p.WriteEvent(buf, ev, lm)
34609-	return buf.String()
34610-}
34611-
34612-func (t *traces) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context {
34613-	span := export.GetSpan(ctx)
34614-	if span == nil {
34615-		return ctx
34616-	}
34617-
34618-	switch {
34619-	case event.IsStart(ev):
34620-		// Just starting: add it to the unfinished map.
34621-		// Allocate before the critical section.
34622-		td := &traceData{
34623-			TraceID:  span.ID.TraceID,
34624-			SpanID:   span.ID.SpanID,
34625-			ParentID: span.ParentID,
34626-			Name:     span.Name,
34627-			Start:    span.Start().At(),
34628-			Tags:     renderLabels(span.Start()),
34629-		}
34630-
34631-		t.mu.Lock()
34632-		defer t.mu.Unlock()
34633-		if t.sets == nil {
34634-			t.sets = make(map[string]*traceSet)
34635-			t.unfinished = make(map[export.SpanContext]*traceData)
34636-		}
34637-		t.unfinished[span.ID] = td
34638-		// and wire up parents if we have them
34639-		if !span.ParentID.IsValid() {
34640-			return ctx
34641-		}
34642-		parentID := export.SpanContext{TraceID: span.ID.TraceID, SpanID: span.ParentID}
34643-		parent, found := t.unfinished[parentID]
34644-		if !found {
34645-			// trace had an invalid parent, so it cannot itself be valid
34646-			return ctx
34647-		}
34648-		parent.Children = append(parent.Children, td)
34649-
34650-	case event.IsEnd(ev):
34651-		// Finishing: must be already in the map.
34652-		// Allocate events before the critical section.
34653-		events := span.Events()
34654-		tdEvents := make([]traceEvent, len(events))
34655-		for i, event := range events {
34656-			tdEvents[i] = traceEvent{
34657-				Time: event.At(),
34658-				Tags: renderLabels(event),
34659-			}
34660-		}
34661-
34662-		t.mu.Lock()
34663-		defer t.mu.Unlock()
34664-		td, found := t.unfinished[span.ID]
34665-		if !found {
34666-			return ctx // if this happens we are in a bad place
34667-		}
34668-		delete(t.unfinished, span.ID)
34669-
34670-		td.Finish = span.Finish().At()
34671-		td.Duration = span.Finish().At().Sub(span.Start().At())
34672-		td.Events = tdEvents
34673-
34674-		set, ok := t.sets[span.Name]
34675-		if !ok {
34676-			set = &traceSet{Name: span.Name}
34677-			t.sets[span.Name] = set
34678-		}
34679-		set.Last = td
34680-		if set.Longest == nil || set.Last.Duration > set.Longest.Duration {
34681-			set.Longest = set.Last
34682-		}
34683-		if !td.ParentID.IsValid() {
34684-			fillOffsets(td, td.Start)
34685-		}
34686-	}
34687-	return ctx
34688-}
34689-
34690-func (t *traces) getData(req *http.Request) interface{} {
34691-	if len(t.sets) == 0 {
34692-		return nil
34693-	}
34694-	data := TraceResults{}
34695-	data.Traces = make([]*traceSet, 0, len(t.sets))
34696-	for _, set := range t.sets {
34697-		data.Traces = append(data.Traces, set)
34698-	}
34699-	sort.Slice(data.Traces, func(i, j int) bool { return data.Traces[i].Name < data.Traces[j].Name })
34700-	if bits := strings.SplitN(req.URL.Path, "/trace/", 2); len(bits) > 1 {
34701-		data.Selected = t.sets[bits[1]]
34702-	}
34703-	return data
34704-}
34705-
34706-func fillOffsets(td *traceData, start time.Time) {
34707-	td.Offset = td.Start.Sub(start)
34708-	for i := range td.Events {
34709-		td.Events[i].Offset = td.Events[i].Time.Sub(start)
34710-	}
34711-	for _, child := range td.Children {
34712-		fillOffsets(child, start)
34713-	}
34714-}
34715-
34716-func renderLabels(labels label.List) string {
34717-	buf := &bytes.Buffer{}
34718-	for index := 0; labels.Valid(index); index++ {
34719-		if l := labels.Label(index); l.Valid() {
34720-			fmt.Fprintf(buf, "%v ", l)
34721-		}
34722-	}
34723-	return buf.String()
34724-}
34725diff -urN a/gopls/internal/lsp/definition.go b/gopls/internal/lsp/definition.go
34726--- a/gopls/internal/lsp/definition.go	2000-01-01 00:00:00.000000000 -0000
34727+++ b/gopls/internal/lsp/definition.go	1970-01-01 00:00:00.000000000 +0000
34728@@ -1,52 +0,0 @@
34729-// Copyright 2019 The Go Authors. All rights reserved.
34730-// Use of this source code is governed by a BSD-style
34731-// license that can be found in the LICENSE file.
34732-
34733-package lsp
34734-
34735-import (
34736-	"context"
34737-	"errors"
34738-	"fmt"
34739-
34740-	"golang.org/x/tools/gopls/internal/lsp/protocol"
34741-	"golang.org/x/tools/gopls/internal/lsp/source"
34742-	"golang.org/x/tools/gopls/internal/lsp/template"
34743-)
34744-
34745-func (s *Server) definition(ctx context.Context, params *protocol.DefinitionParams) ([]protocol.Location, error) {
34746-	// TODO(rfindley): definition requests should be multiplexed across all views.
34747-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.UnknownKind)
34748-	defer release()
34749-	if !ok {
34750-		return nil, err
34751-	}
34752-	switch kind := snapshot.View().FileKind(fh); kind {
34753-	case source.Tmpl:
34754-		return template.Definition(snapshot, fh, params.Position)
34755-	case source.Go:
34756-		// Partial support for jumping from linkname directive (position at 2nd argument).
34757-		locations, err := source.LinknameDefinition(ctx, snapshot, fh, params.Position)
34758-		if !errors.Is(err, source.ErrNoLinkname) {
34759-			return locations, err
34760-		}
34761-		return source.Definition(ctx, snapshot, fh, params.Position)
34762-	default:
34763-		return nil, fmt.Errorf("can't find definitions for file type %s", kind)
34764-	}
34765-}
34766-
34767-func (s *Server) typeDefinition(ctx context.Context, params *protocol.TypeDefinitionParams) ([]protocol.Location, error) {
34768-	// TODO(rfindley): type definition requests should be multiplexed across all views.
34769-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.Go)
34770-	defer release()
34771-	if !ok {
34772-		return nil, err
34773-	}
34774-	switch kind := snapshot.View().FileKind(fh); kind {
34775-	case source.Go:
34776-		return source.TypeDefinition(ctx, snapshot, fh, params.Position)
34777-	default:
34778-		return nil, fmt.Errorf("can't find type definitions for file type %s", kind)
34779-	}
34780-}
34781diff -urN a/gopls/internal/lsp/diagnostics.go b/gopls/internal/lsp/diagnostics.go
34782--- a/gopls/internal/lsp/diagnostics.go	2000-01-01 00:00:00.000000000 -0000
34783+++ b/gopls/internal/lsp/diagnostics.go	1970-01-01 00:00:00.000000000 +0000
34784@@ -1,764 +0,0 @@
34785-// Copyright 2018 The Go Authors. All rights reserved.
34786-// Use of this source code is governed by a BSD-style
34787-// license that can be found in the LICENSE file.
34788-
34789-package lsp
34790-
34791-import (
34792-	"context"
34793-	"crypto/sha256"
34794-	"errors"
34795-	"fmt"
34796-	"os"
34797-	"path/filepath"
34798-	"strings"
34799-	"sync"
34800-	"time"
34801-
34802-	"golang.org/x/sync/errgroup"
34803-	"golang.org/x/tools/gopls/internal/lsp/debug/log"
34804-	"golang.org/x/tools/gopls/internal/lsp/mod"
34805-	"golang.org/x/tools/gopls/internal/lsp/protocol"
34806-	"golang.org/x/tools/gopls/internal/lsp/source"
34807-	"golang.org/x/tools/gopls/internal/lsp/template"
34808-	"golang.org/x/tools/gopls/internal/lsp/work"
34809-	"golang.org/x/tools/gopls/internal/span"
34810-	"golang.org/x/tools/internal/event"
34811-	"golang.org/x/tools/internal/event/tag"
34812-	"golang.org/x/tools/internal/xcontext"
34813-)
34814-
34815-// diagnosticSource differentiates different sources of diagnostics.
34816-type diagnosticSource int
34817-
34818-const (
34819-	modSource diagnosticSource = iota
34820-	gcDetailsSource
34821-	analysisSource
34822-	typeCheckSource
34823-	orphanedSource
34824-	workSource
34825-	modCheckUpgradesSource
34826-	modVulncheckSource // source.Govulncheck + source.Vulncheck
34827-)
34828-
34829-// A diagnosticReport holds results for a single diagnostic source.
34830-type diagnosticReport struct {
34831-	snapshotID    source.GlobalSnapshotID // global snapshot ID on which the report was computed
34832-	publishedHash string                  // last published hash for this (URI, source)
34833-	diags         map[string]*source.Diagnostic
34834-}
34835-
34836-// fileReports holds a collection of diagnostic reports for a single file, as
34837-// well as the hash of the last published set of diagnostics.
34838-type fileReports struct {
34839-	// publishedSnapshotID is the last snapshot ID for which we have "published"
34840-	// diagnostics (though the publishDiagnostics notification may not have
34841-	// actually been sent, if nothing changed).
34842-	//
34843-	// Specifically, publishedSnapshotID is updated to a later snapshot ID when
34844-	// we either:
34845-	//  (1) publish diagnostics for the file for a snapshot, or
34846-	//  (2) determine that published diagnostics are valid for a new snapshot.
34847-	//
34848-	// Notably publishedSnapshotID may not match the snapshot id on individual reports in
34849-	// the reports map:
34850-	// - we may have published partial diagnostics from only a subset of
34851-	//   diagnostic sources for which new results have been computed, or
34852-	// - we may have started computing reports for an even new snapshot, but not
34853-	//   yet published.
34854-	//
34855-	// This prevents gopls from publishing stale diagnostics.
34856-	publishedSnapshotID source.GlobalSnapshotID
34857-
34858-	// publishedHash is a hash of the latest diagnostics published for the file.
34859-	publishedHash string
34860-
34861-	// If set, mustPublish marks diagnostics as needing publication, independent
34862-	// of whether their publishedHash has changed.
34863-	mustPublish bool
34864-
34865-	// The last stored diagnostics for each diagnostic source.
34866-	reports map[diagnosticSource]diagnosticReport
34867-}
34868-
34869-func (d diagnosticSource) String() string {
34870-	switch d {
34871-	case modSource:
34872-		return "FromSource"
34873-	case gcDetailsSource:
34874-		return "FromGCDetails"
34875-	case analysisSource:
34876-		return "FromAnalysis"
34877-	case typeCheckSource:
34878-		return "FromTypeChecking"
34879-	case orphanedSource:
34880-		return "FromOrphans"
34881-	case workSource:
34882-		return "FromGoWork"
34883-	case modCheckUpgradesSource:
34884-		return "FromCheckForUpgrades"
34885-	case modVulncheckSource:
34886-		return "FromModVulncheck"
34887-	default:
34888-		return fmt.Sprintf("From?%d?", d)
34889-	}
34890-}
34891-
34892-// hashDiagnostics computes a hash to identify diags.
34893-func hashDiagnostics(diags ...*source.Diagnostic) string {
34894-	source.SortDiagnostics(diags)
34895-	h := sha256.New()
34896-	for _, d := range diags {
34897-		for _, t := range d.Tags {
34898-			fmt.Fprintf(h, "%s", t)
34899-		}
34900-		for _, r := range d.Related {
34901-			fmt.Fprintf(h, "%s%s%s", r.Location.URI.SpanURI(), r.Message, r.Location.Range)
34902-		}
34903-		fmt.Fprintf(h, "%s%s%s%s", d.Message, d.Range, d.Severity, d.Source)
34904-	}
34905-	return fmt.Sprintf("%x", h.Sum(nil))
34906-}
34907-
34908-func (s *Server) diagnoseDetached(snapshot source.Snapshot) {
34909-	ctx := snapshot.BackgroundContext()
34910-	ctx = xcontext.Detach(ctx)
34911-	s.diagnose(ctx, snapshot, false)
34912-	s.publishDiagnostics(ctx, true, snapshot)
34913-}
34914-
34915-func (s *Server) diagnoseSnapshots(snapshots map[source.Snapshot][]span.URI, onDisk bool) {
34916-	var diagnosticWG sync.WaitGroup
34917-	for snapshot, uris := range snapshots {
34918-		diagnosticWG.Add(1)
34919-		go func(snapshot source.Snapshot, uris []span.URI) {
34920-			defer diagnosticWG.Done()
34921-			s.diagnoseSnapshot(snapshot, uris, onDisk)
34922-		}(snapshot, uris)
34923-	}
34924-	diagnosticWG.Wait()
34925-}
34926-
34927-func (s *Server) diagnoseSnapshot(snapshot source.Snapshot, changedURIs []span.URI, onDisk bool) {
34928-	ctx := snapshot.BackgroundContext()
34929-	ctx, done := event.Start(ctx, "Server.diagnoseSnapshot", source.SnapshotLabels(snapshot)...)
34930-	defer done()
34931-
34932-	delay := snapshot.View().Options().DiagnosticsDelay
34933-	if delay > 0 {
34934-		// 2-phase diagnostics.
34935-		//
34936-		// The first phase just parses and type-checks (but
34937-		// does not analyze) packages directly affected by
34938-		// file modifications.
34939-		//
34940-		// The second phase runs analysis on the entire snapshot,
34941-		// and is debounced by the configured delay.
34942-		s.diagnoseChangedFiles(ctx, snapshot, changedURIs, onDisk)
34943-		s.publishDiagnostics(ctx, false, snapshot)
34944-
34945-		// We debounce diagnostics separately for each view, using the snapshot
34946-		// local ID as logical ordering.
34947-		//
34948-		// TODO(rfindley): it would be cleaner to simply put the diagnostic
34949-		// debouncer on the view, and remove the "key" argument to debouncing.
34950-		if ok := <-s.diagDebouncer.debounce(snapshot.View().Name(), snapshot.SequenceID(), time.After(delay)); ok {
34951-			s.diagnose(ctx, snapshot, false)
34952-			s.publishDiagnostics(ctx, true, snapshot)
34953-		}
34954-		return
34955-	}
34956-
34957-	// Ignore possible workspace configuration warnings in the normal flow.
34958-	s.diagnose(ctx, snapshot, false)
34959-	s.publishDiagnostics(ctx, true, snapshot)
34960-}
34961-
34962-func (s *Server) diagnoseChangedFiles(ctx context.Context, snapshot source.Snapshot, uris []span.URI, onDisk bool) {
34963-	ctx, done := event.Start(ctx, "Server.diagnoseChangedFiles", source.SnapshotLabels(snapshot)...)
34964-	defer done()
34965-
34966-	// TODO(adonovan): safety: refactor so that group.Go is called
34967-	// in a second loop, so that if we should later add an early
34968-	// return to the first loop, we don't leak goroutines.
34969-	var group errgroup.Group
34970-	seen := make(map[*source.Metadata]bool)
34971-	for _, uri := range uris {
34972-		// If the change is only on-disk and the file is not open, don't
34973-		// directly request its package. It may not be a workspace package.
34974-		if onDisk && !snapshot.IsOpen(uri) {
34975-			continue
34976-		}
34977-		// If the file is not known to the snapshot (e.g., if it was deleted),
34978-		// don't diagnose it.
34979-		if snapshot.FindFile(uri) == nil {
34980-			continue
34981-		}
34982-
34983-		// Don't request type-checking for builtin.go: it's not a real package.
34984-		if snapshot.IsBuiltin(ctx, uri) {
34985-			continue
34986-		}
34987-
34988-		// Find all packages that include this file and diagnose them in parallel.
34989-		metas, err := snapshot.MetadataForFile(ctx, uri)
34990-		if err != nil {
34991-			// TODO(findleyr): we should probably do something with the error here,
34992-			// but as of now this can fail repeatedly if load fails, so can be too
34993-			// noisy to log (and we'll handle things later in the slow pass).
34994-			continue
34995-		}
34996-		for _, m := range metas {
34997-			if m.IsIntermediateTestVariant() {
34998-				continue
34999-			}
35000-			if !seen[m] {
35001-				seen[m] = true
35002-				m := m
35003-				group.Go(func() error {
35004-					s.diagnosePkg(ctx, snapshot, m, false)
35005-					return nil // error result is ignored
35006-				})
35007-			}
35008-		}
35009-	}
35010-	group.Wait() // ignore error
35011-}
35012-
35013-// diagnose is a helper function for running diagnostics with a given context.
35014-// Do not call it directly. forceAnalysis is only true for testing purposes.
35015-func (s *Server) diagnose(ctx context.Context, snapshot source.Snapshot, forceAnalysis bool) {
35016-	ctx, done := event.Start(ctx, "Server.diagnose", source.SnapshotLabels(snapshot)...)
35017-	defer done()
35018-
35019-	// Wait for a free diagnostics slot.
35020-	// TODO(adonovan): opt: shouldn't it be the analysis implementation's
35021-	// job to de-dup and limit resource consumption? In any case this
35022-	// this function spends most its time waiting for awaitLoaded, at
35023-	// least initially.
35024-	select {
35025-	case <-ctx.Done():
35026-		return
35027-	case s.diagnosticsSema <- struct{}{}:
35028-	}
35029-	defer func() {
35030-		<-s.diagnosticsSema
35031-	}()
35032-
35033-	// common code for dispatching diagnostics
35034-	store := func(dsource diagnosticSource, operation string, diagsByFile map[span.URI][]*source.Diagnostic, err error, merge bool) {
35035-		if err != nil {
35036-			event.Error(ctx, "warning: while "+operation, err, source.SnapshotLabels(snapshot)...)
35037-		}
35038-		for uri, diags := range diagsByFile {
35039-			if uri == "" {
35040-				event.Error(ctx, "missing URI while "+operation, fmt.Errorf("empty URI"), tag.Directory.Of(snapshot.View().Folder().Filename()))
35041-				continue
35042-			}
35043-			s.storeDiagnostics(snapshot, uri, dsource, diags, merge)
35044-		}
35045-	}
35046-
35047-	// Diagnose go.mod upgrades.
35048-	upgradeReports, upgradeErr := mod.UpgradeDiagnostics(ctx, snapshot)
35049-	if ctx.Err() != nil {
35050-		log.Trace.Log(ctx, "diagnose cancelled")
35051-		return
35052-	}
35053-	store(modCheckUpgradesSource, "diagnosing go.mod upgrades", upgradeReports, upgradeErr, true)
35054-
35055-	// Diagnose go.work file.
35056-	workReports, workErr := work.Diagnostics(ctx, snapshot)
35057-	if ctx.Err() != nil {
35058-		log.Trace.Log(ctx, "diagnose cancelled")
35059-		return
35060-	}
35061-	store(workSource, "diagnosing go.work file", workReports, workErr, true)
35062-
35063-	// Diagnose go.mod file.
35064-	// (This step demands type checking of all active packages:
35065-	// the bottleneck in the startup sequence for a big workspace.)
35066-	modReports, modErr := mod.Diagnostics(ctx, snapshot)
35067-	if ctx.Err() != nil {
35068-		log.Trace.Log(ctx, "diagnose cancelled")
35069-		return
35070-	}
35071-	store(modSource, "diagnosing go.mod file", modReports, modErr, true)
35072-
35073-	// Diagnose vulnerabilities.
35074-	vulnReports, vulnErr := mod.VulnerabilityDiagnostics(ctx, snapshot)
35075-	if ctx.Err() != nil {
35076-		log.Trace.Log(ctx, "diagnose cancelled")
35077-		return
35078-	}
35079-	store(modVulncheckSource, "diagnosing vulnerabilities", vulnReports, vulnErr, false)
35080-
35081-	activeMetas, activeErr := snapshot.ActiveMetadata(ctx)
35082-	if s.shouldIgnoreError(ctx, snapshot, activeErr) {
35083-		return
35084-	}
35085-	criticalErr := snapshot.GetCriticalError(ctx)
35086-	if ctx.Err() != nil { // must check ctx after GetCriticalError
35087-		return
35088-	}
35089-
35090-	// Show the error as a progress error report so that it appears in the
35091-	// status bar. If a client doesn't support progress reports, the error
35092-	// will still be shown as a ShowMessage. If there is no error, any running
35093-	// error progress reports will be closed.
35094-	s.showCriticalErrorStatus(ctx, snapshot, criticalErr)
35095-
35096-	// Diagnose template (.tmpl) files.
35097-	for _, f := range snapshot.Templates() {
35098-		diags := template.Diagnose(f)
35099-		s.storeDiagnostics(snapshot, f.URI(), typeCheckSource, diags, true)
35100-	}
35101-
35102-	// If there are no workspace packages, there is nothing to diagnose and
35103-	// there are no orphaned files.
35104-	if len(activeMetas) == 0 {
35105-		return
35106-	}
35107-
35108-	// Run go/analysis diagnosis of packages in parallel.
35109-	// TODO(adonovan): opt: it may be more efficient to
35110-	// have diagnosePkg take a set of packages.
35111-	//
35112-	// TODO(adonovan): opt: since the new analysis driver does its
35113-	// own type checking, we could strength-reduce pkg to
35114-	// PackageID and get this step started as soon as the set of
35115-	// active package IDs are known, without waiting for them to load.
35116-	var (
35117-		wg   sync.WaitGroup
35118-		seen = map[span.URI]struct{}{}
35119-	)
35120-	for _, m := range activeMetas {
35121-		for _, uri := range m.CompiledGoFiles {
35122-			seen[uri] = struct{}{}
35123-		}
35124-
35125-		wg.Add(1)
35126-		go func(m *source.Metadata) {
35127-			defer wg.Done()
35128-			s.diagnosePkg(ctx, snapshot, m, forceAnalysis)
35129-		}(m)
35130-	}
35131-	wg.Wait()
35132-
35133-	// Orphaned files.
35134-	// Confirm that every opened file belongs to a package (if any exist in
35135-	// the workspace). Otherwise, add a diagnostic to the file.
35136-	for _, o := range s.session.Overlays() {
35137-		if _, ok := seen[o.URI()]; ok {
35138-			continue
35139-		}
35140-		diagnostic := s.checkForOrphanedFile(ctx, snapshot, o)
35141-		if diagnostic == nil {
35142-			continue
35143-		}
35144-		s.storeDiagnostics(snapshot, o.URI(), orphanedSource, []*source.Diagnostic{diagnostic}, true)
35145-	}
35146-}
35147-
35148-func (s *Server) diagnosePkg(ctx context.Context, snapshot source.Snapshot, m *source.Metadata, alwaysAnalyze bool) {
35149-	ctx, done := event.Start(ctx, "Server.diagnosePkg", append(source.SnapshotLabels(snapshot), tag.Package.Of(string(m.ID)))...)
35150-	defer done()
35151-	enableDiagnostics := false
35152-	includeAnalysis := alwaysAnalyze // only run analyses for packages with open files
35153-	for _, uri := range m.CompiledGoFiles {
35154-		enableDiagnostics = enableDiagnostics || !snapshot.IgnoredFile(uri)
35155-		includeAnalysis = includeAnalysis || snapshot.IsOpen(uri)
35156-	}
35157-	// Don't show any diagnostics on ignored files.
35158-	if !enableDiagnostics {
35159-		return
35160-	}
35161-
35162-	diags, err := snapshot.PackageDiagnostics(ctx, m.ID)
35163-	if err != nil {
35164-		event.Error(ctx, "warning: diagnostics failed", err, append(source.SnapshotLabels(snapshot), tag.Package.Of(string(m.ID)))...)
35165-		return
35166-	}
35167-
35168-	// Get diagnostics from analysis framework.
35169-	// This includes type-error analyzers, which suggest fixes to compiler errors.
35170-	var analysisDiags map[span.URI][]*source.Diagnostic
35171-	if includeAnalysis {
35172-		diags, err := source.Analyze(ctx, snapshot, m.ID, false)
35173-		if err != nil {
35174-			event.Error(ctx, "warning: analyzing package", err, append(source.SnapshotLabels(snapshot), tag.Package.Of(string(m.ID)))...)
35175-			return
35176-		}
35177-		analysisDiags = diags
35178-	}
35179-
35180-	// For each file, update the server's diagnostics state.
35181-	for _, uri := range m.CompiledGoFiles {
35182-		// builtin.go exists only for documentation purposes and
35183-		// is not valid Go code. Don't report distracting errors.
35184-		if snapshot.IsBuiltin(ctx, uri) {
35185-			continue
35186-		}
35187-
35188-		pkgDiags := diags[uri]
35189-		var tdiags, adiags []*source.Diagnostic
35190-		source.CombineDiagnostics(pkgDiags, analysisDiags[uri], &tdiags, &adiags)
35191-		s.storeDiagnostics(snapshot, uri, typeCheckSource, tdiags, true)
35192-		s.storeDiagnostics(snapshot, uri, analysisSource, adiags, true)
35193-	}
35194-
35195-	// If gc optimization details are requested, add them to the
35196-	// diagnostic reports.
35197-	s.gcOptimizationDetailsMu.Lock()
35198-	_, enableGCDetails := s.gcOptimizationDetails[m.ID]
35199-	s.gcOptimizationDetailsMu.Unlock()
35200-	if enableGCDetails {
35201-		gcReports, err := source.GCOptimizationDetails(ctx, snapshot, m)
35202-		if err != nil {
35203-			event.Error(ctx, "warning: gc details", err, append(source.SnapshotLabels(snapshot), tag.Package.Of(string(m.ID)))...)
35204-		}
35205-		s.gcOptimizationDetailsMu.Lock()
35206-		_, enableGCDetails := s.gcOptimizationDetails[m.ID]
35207-
35208-		// NOTE(golang/go#44826): hold the gcOptimizationDetails lock, and re-check
35209-		// whether gc optimization details are enabled, while storing gc_details
35210-		// results. This ensures that the toggling of GC details and clearing of
35211-		// diagnostics does not race with storing the results here.
35212-		if enableGCDetails {
35213-			for uri, diags := range gcReports {
35214-				fh := snapshot.FindFile(uri)
35215-				// Don't publish gc details for unsaved buffers, since the underlying
35216-				// logic operates on the file on disk.
35217-				if fh == nil || !fh.Saved() {
35218-					continue
35219-				}
35220-				s.storeDiagnostics(snapshot, uri, gcDetailsSource, diags, true)
35221-			}
35222-		}
35223-		s.gcOptimizationDetailsMu.Unlock()
35224-	}
35225-}
35226-
35227-// mustPublishDiagnostics marks the uri as needing publication, independent of
35228-// whether the published contents have changed.
35229-//
35230-// This can be used for ensuring gopls publishes diagnostics after certain file
35231-// events.
35232-func (s *Server) mustPublishDiagnostics(uri span.URI) {
35233-	s.diagnosticsMu.Lock()
35234-	defer s.diagnosticsMu.Unlock()
35235-
35236-	if s.diagnostics[uri] == nil {
35237-		s.diagnostics[uri] = &fileReports{
35238-			publishedHash: hashDiagnostics(), // Hash for 0 diagnostics.
35239-			reports:       map[diagnosticSource]diagnosticReport{},
35240-		}
35241-	}
35242-	s.diagnostics[uri].mustPublish = true
35243-}
35244-
35245-// storeDiagnostics stores results from a single diagnostic source. If merge is
35246-// true, it merges results into any existing results for this snapshot.
35247-//
35248-// TODO(hyangah): investigate whether we can unconditionally overwrite previous report.diags
35249-// with the new diags and eliminate the need for the `merge` flag.
35250-func (s *Server) storeDiagnostics(snapshot source.Snapshot, uri span.URI, dsource diagnosticSource, diags []*source.Diagnostic, merge bool) {
35251-	// Safeguard: ensure that the file actually exists in the snapshot
35252-	// (see golang.org/issues/38602).
35253-	fh := snapshot.FindFile(uri)
35254-	if fh == nil {
35255-		return
35256-	}
35257-
35258-	s.diagnosticsMu.Lock()
35259-	defer s.diagnosticsMu.Unlock()
35260-	if s.diagnostics[uri] == nil {
35261-		s.diagnostics[uri] = &fileReports{
35262-			publishedHash: hashDiagnostics(), // Hash for 0 diagnostics.
35263-			reports:       map[diagnosticSource]diagnosticReport{},
35264-		}
35265-	}
35266-	report := s.diagnostics[uri].reports[dsource]
35267-	// Don't set obsolete diagnostics.
35268-	if report.snapshotID > snapshot.GlobalID() {
35269-		return
35270-	}
35271-	if report.diags == nil || report.snapshotID != snapshot.GlobalID() || !merge {
35272-		report.diags = map[string]*source.Diagnostic{}
35273-	}
35274-	report.snapshotID = snapshot.GlobalID()
35275-	for _, d := range diags {
35276-		report.diags[hashDiagnostics(d)] = d
35277-	}
35278-	s.diagnostics[uri].reports[dsource] = report
35279-}
35280-
35281-// clearDiagnosticSource clears all diagnostics for a given source type. It is
35282-// necessary for cases where diagnostics have been invalidated by something
35283-// other than a snapshot change, for example when gc_details is toggled.
35284-func (s *Server) clearDiagnosticSource(dsource diagnosticSource) {
35285-	s.diagnosticsMu.Lock()
35286-	defer s.diagnosticsMu.Unlock()
35287-	for _, reports := range s.diagnostics {
35288-		delete(reports.reports, dsource)
35289-	}
35290-}
35291-
35292-const WorkspaceLoadFailure = "Error loading workspace"
35293-
35294-// showCriticalErrorStatus shows the error as a progress report.
35295-// If the error is nil, it clears any existing error progress report.
35296-func (s *Server) showCriticalErrorStatus(ctx context.Context, snapshot source.Snapshot, err *source.CriticalError) {
35297-	s.criticalErrorStatusMu.Lock()
35298-	defer s.criticalErrorStatusMu.Unlock()
35299-
35300-	// Remove all newlines so that the error message can be formatted in a
35301-	// status bar.
35302-	var errMsg string
35303-	if err != nil {
35304-		event.Error(ctx, "errors loading workspace", err.MainError, source.SnapshotLabels(snapshot)...)
35305-		for _, d := range err.Diagnostics {
35306-			s.storeDiagnostics(snapshot, d.URI, modSource, []*source.Diagnostic{d}, true)
35307-		}
35308-		errMsg = strings.ReplaceAll(err.MainError.Error(), "\n", " ")
35309-	}
35310-
35311-	if s.criticalErrorStatus == nil {
35312-		if errMsg != "" {
35313-			s.criticalErrorStatus = s.progress.Start(ctx, WorkspaceLoadFailure, errMsg, nil, nil)
35314-		}
35315-		return
35316-	}
35317-
35318-	// If an error is already shown to the user, update it or mark it as
35319-	// resolved.
35320-	if errMsg == "" {
35321-		s.criticalErrorStatus.End(ctx, "Done.")
35322-		s.criticalErrorStatus = nil
35323-	} else {
35324-		s.criticalErrorStatus.Report(ctx, errMsg, 0)
35325-	}
35326-}
35327-
35328-// checkForOrphanedFile checks that the given URIs can be mapped to packages.
35329-// If they cannot and the workspace is not otherwise unloaded, it also surfaces
35330-// a warning, suggesting that the user check the file for build tags.
35331-func (s *Server) checkForOrphanedFile(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) *source.Diagnostic {
35332-	// TODO(rfindley): this function may fail to produce a diagnostic for a
35333-	// variety of reasons, some of which should probably not be ignored. For
35334-	// example, should this function be tolerant of the case where fh does not
35335-	// exist, or does not have a package name?
35336-	//
35337-	// It would be better to panic or report a bug in several of the cases below,
35338-	// so that we can move toward guaranteeing we show the user a meaningful
35339-	// error whenever it makes sense.
35340-	if snapshot.View().FileKind(fh) != source.Go {
35341-		return nil
35342-	}
35343-	// builtin files won't have a package, but they are never orphaned.
35344-	if snapshot.IsBuiltin(ctx, fh.URI()) {
35345-		return nil
35346-	}
35347-
35348-	// This call has the effect of inserting fh into snapshot.files,
35349-	// where for better or worse (actually: just worse) it influences
35350-	// the sets of open, known, and orphaned files.
35351-	snapshot.GetFile(ctx, fh.URI())
35352-
35353-	metas, _ := snapshot.MetadataForFile(ctx, fh.URI())
35354-	if len(metas) > 0 || ctx.Err() != nil {
35355-		return nil // no package, or cancelled
35356-	}
35357-	// Inv: file does not belong to a package we know about.
35358-	pgf, err := snapshot.ParseGo(ctx, fh, source.ParseHeader)
35359-	if err != nil {
35360-		return nil
35361-	}
35362-	if !pgf.File.Name.Pos().IsValid() {
35363-		return nil
35364-	}
35365-	rng, err := pgf.NodeRange(pgf.File.Name)
35366-	if err != nil {
35367-		return nil
35368-	}
35369-	// If the file no longer has a name ending in .go, this diagnostic is wrong
35370-	if filepath.Ext(fh.URI().Filename()) != ".go" {
35371-		return nil
35372-	}
35373-	// TODO(rstambler): We should be able to parse the build tags in the
35374-	// file and show a more specific error message. For now, put the diagnostic
35375-	// on the package declaration.
35376-	return &source.Diagnostic{
35377-		URI:      fh.URI(),
35378-		Range:    rng,
35379-		Severity: protocol.SeverityWarning,
35380-		Source:   source.ListError,
35381-		Message: fmt.Sprintf(`No packages found for open file %s: %v.
35382-If this file contains build tags, try adding "-tags=<build tag>" to your gopls "buildFlags" configuration (see (https://github.com/golang/tools/blob/master/gopls/doc/settings.md#buildflags-string).
35383-Otherwise, see the troubleshooting guidelines for help investigating (https://github.com/golang/tools/blob/master/gopls/doc/troubleshooting.md).
35384-`, fh.URI().Filename(), err),
35385-	}
35386-}
35387-
35388-// publishDiagnostics collects and publishes any unpublished diagnostic reports.
35389-func (s *Server) publishDiagnostics(ctx context.Context, final bool, snapshot source.Snapshot) {
35390-	ctx, done := event.Start(ctx, "Server.publishDiagnostics", source.SnapshotLabels(snapshot)...)
35391-	defer done()
35392-
35393-	s.diagnosticsMu.Lock()
35394-	defer s.diagnosticsMu.Unlock()
35395-
35396-	for uri, r := range s.diagnostics {
35397-		// Global snapshot IDs are monotonic, so we use them to enforce an ordering
35398-		// for diagnostics.
35399-		//
35400-		// If we've already delivered diagnostics for a future snapshot for this
35401-		// file, do not deliver them. See golang/go#42837 for an example of why
35402-		// this is necessary.
35403-		//
35404-		// TODO(rfindley): even using a global snapshot ID, this mechanism is
35405-		// potentially racy: elsewhere in the code (e.g. invalidateContent) we
35406-		// allow for multiple views track a given file. In this case, we should
35407-		// either only report diagnostics for snapshots from the "best" view of a
35408-		// URI, or somehow merge diagnostics from multiple views.
35409-		if r.publishedSnapshotID > snapshot.GlobalID() {
35410-			continue
35411-		}
35412-
35413-		anyReportsChanged := false
35414-		reportHashes := map[diagnosticSource]string{}
35415-		var diags []*source.Diagnostic
35416-		for dsource, report := range r.reports {
35417-			if report.snapshotID != snapshot.GlobalID() {
35418-				continue
35419-			}
35420-			var reportDiags []*source.Diagnostic
35421-			for _, d := range report.diags {
35422-				diags = append(diags, d)
35423-				reportDiags = append(reportDiags, d)
35424-			}
35425-			hash := hashDiagnostics(reportDiags...)
35426-			if hash != report.publishedHash {
35427-				anyReportsChanged = true
35428-			}
35429-			reportHashes[dsource] = hash
35430-		}
35431-
35432-		if !final && !anyReportsChanged {
35433-			// Don't invalidate existing reports on the client if we haven't got any
35434-			// new information.
35435-			continue
35436-		}
35437-
35438-		source.SortDiagnostics(diags)
35439-		hash := hashDiagnostics(diags...)
35440-		if hash == r.publishedHash && !r.mustPublish {
35441-			// Update snapshotID to be the latest snapshot for which this diagnostic
35442-			// hash is valid.
35443-			r.publishedSnapshotID = snapshot.GlobalID()
35444-			continue
35445-		}
35446-		var version int32
35447-		if fh := snapshot.FindFile(uri); fh != nil { // file may have been deleted
35448-			version = fh.Version()
35449-		}
35450-		if err := s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{
35451-			Diagnostics: toProtocolDiagnostics(diags),
35452-			URI:         protocol.URIFromSpanURI(uri),
35453-			Version:     version,
35454-		}); err == nil {
35455-			r.publishedHash = hash
35456-			r.mustPublish = false // diagnostics have been successfully published
35457-			r.publishedSnapshotID = snapshot.GlobalID()
35458-			for dsource, hash := range reportHashes {
35459-				report := r.reports[dsource]
35460-				report.publishedHash = hash
35461-				r.reports[dsource] = report
35462-			}
35463-		} else {
35464-			if ctx.Err() != nil {
35465-				// Publish may have failed due to a cancelled context.
35466-				log.Trace.Log(ctx, "publish cancelled")
35467-				return
35468-			}
35469-			event.Error(ctx, "publishReports: failed to deliver diagnostic", err, tag.URI.Of(uri))
35470-		}
35471-	}
35472-}
35473-
35474-func toProtocolDiagnostics(diagnostics []*source.Diagnostic) []protocol.Diagnostic {
35475-	reports := []protocol.Diagnostic{}
35476-	for _, diag := range diagnostics {
35477-		pdiag := protocol.Diagnostic{
35478-			// diag.Message might start with \n or \t
35479-			Message:            strings.TrimSpace(diag.Message),
35480-			Range:              diag.Range,
35481-			Severity:           diag.Severity,
35482-			Source:             string(diag.Source),
35483-			Tags:               diag.Tags,
35484-			RelatedInformation: diag.Related,
35485-		}
35486-		if diag.Code != "" {
35487-			pdiag.Code = diag.Code
35488-		}
35489-		if diag.CodeHref != "" {
35490-			pdiag.CodeDescription = &protocol.CodeDescription{Href: diag.CodeHref}
35491-		}
35492-		reports = append(reports, pdiag)
35493-	}
35494-	return reports
35495-}
35496-
35497-func (s *Server) shouldIgnoreError(ctx context.Context, snapshot source.Snapshot, err error) bool {
35498-	if err == nil { // if there is no error at all
35499-		return false
35500-	}
35501-	if errors.Is(err, context.Canceled) {
35502-		return true
35503-	}
35504-	// If the folder has no Go code in it, we shouldn't spam the user with a warning.
35505-	var hasGo bool
35506-	_ = filepath.Walk(snapshot.View().Folder().Filename(), func(path string, info os.FileInfo, err error) error {
35507-		if err != nil {
35508-			return err
35509-		}
35510-		if !strings.HasSuffix(info.Name(), ".go") {
35511-			return nil
35512-		}
35513-		hasGo = true
35514-		return errors.New("done")
35515-	})
35516-	return !hasGo
35517-}
35518-
35519-// Diagnostics formattedfor the debug server
35520-// (all the relevant fields of Server are private)
35521-// (The alternative is to export them)
35522-func (s *Server) Diagnostics() map[string][]string {
35523-	ans := make(map[string][]string)
35524-	s.diagnosticsMu.Lock()
35525-	defer s.diagnosticsMu.Unlock()
35526-	for k, v := range s.diagnostics {
35527-		fn := k.Filename()
35528-		for typ, d := range v.reports {
35529-			if len(d.diags) == 0 {
35530-				continue
35531-			}
35532-			for _, dx := range d.diags {
35533-				ans[fn] = append(ans[fn], auxStr(dx, d, typ))
35534-			}
35535-		}
35536-	}
35537-	return ans
35538-}
35539-
35540-func auxStr(v *source.Diagnostic, d diagnosticReport, typ diagnosticSource) string {
35541-	// Tags? RelatedInformation?
35542-	msg := fmt.Sprintf("(%s)%q(source:%q,code:%q,severity:%s,snapshot:%d,type:%s)",
35543-		v.Range, v.Message, v.Source, v.Code, v.Severity, d.snapshotID, typ)
35544-	for _, r := range v.Related {
35545-		msg += fmt.Sprintf(" [%s:%s,%q]", r.Location.URI.SpanURI().Filename(), r.Location.Range, r.Message)
35546-	}
35547-	return msg
35548-}
35549diff -urN a/gopls/internal/lsp/fake/client.go b/gopls/internal/lsp/fake/client.go
35550--- a/gopls/internal/lsp/fake/client.go	2000-01-01 00:00:00.000000000 -0000
35551+++ b/gopls/internal/lsp/fake/client.go	1970-01-01 00:00:00.000000000 +0000
35552@@ -1,187 +0,0 @@
35553-// Copyright 2020 The Go Authors. All rights reserved.
35554-// Use of this source code is governed by a BSD-style
35555-// license that can be found in the LICENSE file.
35556-
35557-package fake
35558-
35559-import (
35560-	"context"
35561-	"encoding/json"
35562-	"fmt"
35563-
35564-	"golang.org/x/tools/gopls/internal/lsp/glob"
35565-	"golang.org/x/tools/gopls/internal/lsp/protocol"
35566-)
35567-
35568-// ClientHooks are a set of optional hooks called during handling of
35569-// the corresponding client method (see protocol.Client for the the
35570-// LSP server-to-client RPCs) in order to make test expectations
35571-// awaitable.
35572-type ClientHooks struct {
35573-	OnLogMessage             func(context.Context, *protocol.LogMessageParams) error
35574-	OnDiagnostics            func(context.Context, *protocol.PublishDiagnosticsParams) error
35575-	OnWorkDoneProgressCreate func(context.Context, *protocol.WorkDoneProgressCreateParams) error
35576-	OnProgress               func(context.Context, *protocol.ProgressParams) error
35577-	OnShowMessage            func(context.Context, *protocol.ShowMessageParams) error
35578-	OnShowMessageRequest     func(context.Context, *protocol.ShowMessageRequestParams) error
35579-	OnRegisterCapability     func(context.Context, *protocol.RegistrationParams) error
35580-	OnUnregisterCapability   func(context.Context, *protocol.UnregistrationParams) error
35581-	OnApplyEdit              func(context.Context, *protocol.ApplyWorkspaceEditParams) error
35582-}
35583-
35584-// Client is an adapter that converts an *Editor into an LSP Client. It mostly
35585-// delegates functionality to hooks that can be configured by tests.
35586-type Client struct {
35587-	editor         *Editor
35588-	hooks          ClientHooks
35589-	skipApplyEdits bool // don't apply edits from ApplyEdit downcalls to Editor
35590-}
35591-
35592-func (c *Client) CodeLensRefresh(context.Context) error { return nil }
35593-
35594-func (c *Client) InlayHintRefresh(context.Context) error { return nil }
35595-
35596-func (c *Client) DiagnosticRefresh(context.Context) error { return nil }
35597-
35598-func (c *Client) InlineValueRefresh(context.Context) error { return nil }
35599-
35600-func (c *Client) SemanticTokensRefresh(context.Context) error { return nil }
35601-
35602-func (c *Client) LogTrace(context.Context, *protocol.LogTraceParams) error { return nil }
35603-
35604-func (c *Client) ShowMessage(ctx context.Context, params *protocol.ShowMessageParams) error {
35605-	if c.hooks.OnShowMessage != nil {
35606-		return c.hooks.OnShowMessage(ctx, params)
35607-	}
35608-	return nil
35609-}
35610-
35611-func (c *Client) ShowMessageRequest(ctx context.Context, params *protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error) {
35612-	if c.hooks.OnShowMessageRequest != nil {
35613-		if err := c.hooks.OnShowMessageRequest(ctx, params); err != nil {
35614-			return nil, err
35615-		}
35616-	}
35617-	if len(params.Actions) == 0 || len(params.Actions) > 1 {
35618-		return nil, fmt.Errorf("fake editor cannot handle multiple action items")
35619-	}
35620-	return &params.Actions[0], nil
35621-}
35622-
35623-func (c *Client) LogMessage(ctx context.Context, params *protocol.LogMessageParams) error {
35624-	if c.hooks.OnLogMessage != nil {
35625-		return c.hooks.OnLogMessage(ctx, params)
35626-	}
35627-	return nil
35628-}
35629-
35630-func (c *Client) Event(ctx context.Context, event *interface{}) error {
35631-	return nil
35632-}
35633-
35634-func (c *Client) PublishDiagnostics(ctx context.Context, params *protocol.PublishDiagnosticsParams) error {
35635-	if c.hooks.OnDiagnostics != nil {
35636-		return c.hooks.OnDiagnostics(ctx, params)
35637-	}
35638-	return nil
35639-}
35640-
35641-func (c *Client) WorkspaceFolders(context.Context) ([]protocol.WorkspaceFolder, error) {
35642-	return []protocol.WorkspaceFolder{}, nil
35643-}
35644-
35645-func (c *Client) Configuration(_ context.Context, p *protocol.ParamConfiguration) ([]interface{}, error) {
35646-	results := make([]interface{}, len(p.Items))
35647-	for i, item := range p.Items {
35648-		if item.Section == "gopls" {
35649-			c.editor.mu.Lock()
35650-			results[i] = c.editor.settingsLocked()
35651-			c.editor.mu.Unlock()
35652-		}
35653-	}
35654-	return results, nil
35655-}
35656-
35657-func (c *Client) RegisterCapability(ctx context.Context, params *protocol.RegistrationParams) error {
35658-	if c.hooks.OnRegisterCapability != nil {
35659-		if err := c.hooks.OnRegisterCapability(ctx, params); err != nil {
35660-			return err
35661-		}
35662-	}
35663-	// Update file watching patterns.
35664-	//
35665-	// TODO(rfindley): We could verify more here, like verify that the
35666-	// registration ID is distinct, and that the capability is not currently
35667-	// registered.
35668-	for _, registration := range params.Registrations {
35669-		if registration.Method == "workspace/didChangeWatchedFiles" {
35670-			// Marshal and unmarshal to interpret RegisterOptions as
35671-			// DidChangeWatchedFilesRegistrationOptions.
35672-			raw, err := json.Marshal(registration.RegisterOptions)
35673-			if err != nil {
35674-				return fmt.Errorf("marshaling registration options: %v", err)
35675-			}
35676-			var opts protocol.DidChangeWatchedFilesRegistrationOptions
35677-			if err := json.Unmarshal(raw, &opts); err != nil {
35678-				return fmt.Errorf("unmarshaling registration options: %v", err)
35679-			}
35680-			var globs []*glob.Glob
35681-			for _, watcher := range opts.Watchers {
35682-				// TODO(rfindley): honor the watch kind.
35683-				g, err := glob.Parse(watcher.GlobPattern)
35684-				if err != nil {
35685-					return fmt.Errorf("error parsing glob pattern %q: %v", watcher.GlobPattern, err)
35686-				}
35687-				globs = append(globs, g)
35688-			}
35689-			c.editor.mu.Lock()
35690-			c.editor.watchPatterns = globs
35691-			c.editor.mu.Unlock()
35692-		}
35693-	}
35694-	return nil
35695-}
35696-
35697-func (c *Client) UnregisterCapability(ctx context.Context, params *protocol.UnregistrationParams) error {
35698-	if c.hooks.OnUnregisterCapability != nil {
35699-		return c.hooks.OnUnregisterCapability(ctx, params)
35700-	}
35701-	return nil
35702-}
35703-
35704-func (c *Client) Progress(ctx context.Context, params *protocol.ProgressParams) error {
35705-	if c.hooks.OnProgress != nil {
35706-		return c.hooks.OnProgress(ctx, params)
35707-	}
35708-	return nil
35709-}
35710-
35711-func (c *Client) WorkDoneProgressCreate(ctx context.Context, params *protocol.WorkDoneProgressCreateParams) error {
35712-	if c.hooks.OnWorkDoneProgressCreate != nil {
35713-		return c.hooks.OnWorkDoneProgressCreate(ctx, params)
35714-	}
35715-	return nil
35716-}
35717-
35718-func (c *Client) ShowDocument(context.Context, *protocol.ShowDocumentParams) (*protocol.ShowDocumentResult, error) {
35719-	return nil, nil
35720-}
35721-
35722-func (c *Client) ApplyEdit(ctx context.Context, params *protocol.ApplyWorkspaceEditParams) (*protocol.ApplyWorkspaceEditResult, error) {
35723-	if len(params.Edit.Changes) != 0 {
35724-		return &protocol.ApplyWorkspaceEditResult{FailureReason: "Edit.Changes is unsupported"}, nil
35725-	}
35726-	if c.hooks.OnApplyEdit != nil {
35727-		if err := c.hooks.OnApplyEdit(ctx, params); err != nil {
35728-			return nil, err
35729-		}
35730-	}
35731-	if !c.skipApplyEdits {
35732-		for _, change := range params.Edit.DocumentChanges {
35733-			if err := c.editor.applyDocumentChange(ctx, change); err != nil {
35734-				return nil, err
35735-			}
35736-		}
35737-	}
35738-	return &protocol.ApplyWorkspaceEditResult{Applied: true}, nil
35739-}
35740diff -urN a/gopls/internal/lsp/fake/doc.go b/gopls/internal/lsp/fake/doc.go
35741--- a/gopls/internal/lsp/fake/doc.go	2000-01-01 00:00:00.000000000 -0000
35742+++ b/gopls/internal/lsp/fake/doc.go	1970-01-01 00:00:00.000000000 +0000
35743@@ -1,19 +0,0 @@
35744-// Copyright 2020 The Go Authors. All rights reserved.
35745-// Use of this source code is governed by a BSD-style
35746-// license that can be found in the LICENSE file.
35747-
35748-// Package fake provides fake implementations of a text editor, LSP client
35749-// plugin, and Sandbox environment for use in tests.
35750-//
35751-// The Editor type provides a high level API for text editor operations
35752-// (open/modify/save/close a buffer, jump to definition, etc.), and the Client
35753-// type exposes an LSP client for the editor that can be connected to a
35754-// language server. By default, the Editor and Client should be compliant with
35755-// the LSP spec: their intended use is to verify server compliance with the
35756-// spec in a variety of environment. Possible future enhancements of these
35757-// types may allow them to misbehave in configurable ways, but that is not
35758-// their primary use.
35759-//
35760-// The Sandbox type provides a facility for executing tests with a temporary
35761-// directory, module proxy, and GOPATH.
35762-package fake
35763diff -urN a/gopls/internal/lsp/fake/edit.go b/gopls/internal/lsp/fake/edit.go
35764--- a/gopls/internal/lsp/fake/edit.go	2000-01-01 00:00:00.000000000 -0000
35765+++ b/gopls/internal/lsp/fake/edit.go	1970-01-01 00:00:00.000000000 +0000
35766@@ -1,51 +0,0 @@
35767-// Copyright 2020 The Go Authors. All rights reserved.
35768-// Use of this source code is governed by a BSD-style
35769-// license that can be found in the LICENSE file.
35770-
35771-package fake
35772-
35773-import (
35774-	"golang.org/x/tools/gopls/internal/lsp/protocol"
35775-	"golang.org/x/tools/gopls/internal/lsp/source"
35776-	"golang.org/x/tools/internal/diff"
35777-)
35778-
35779-// NewEdit creates an edit replacing all content between the 0-based
35780-// (startLine, startColumn) and (endLine, endColumn) with text.
35781-//
35782-// Columns measure UTF-16 codes.
35783-func NewEdit(startLine, startColumn, endLine, endColumn uint32, text string) protocol.TextEdit {
35784-	return protocol.TextEdit{
35785-		Range: protocol.Range{
35786-			Start: protocol.Position{Line: startLine, Character: startColumn},
35787-			End:   protocol.Position{Line: endLine, Character: endColumn},
35788-		},
35789-		NewText: text,
35790-	}
35791-}
35792-
35793-func EditToChangeEvent(e protocol.TextEdit) protocol.TextDocumentContentChangeEvent {
35794-	var rng protocol.Range = e.Range
35795-	return protocol.TextDocumentContentChangeEvent{
35796-		Range: &rng,
35797-		Text:  e.NewText,
35798-	}
35799-}
35800-
35801-// applyEdits applies the edits to a file with the specified lines,
35802-// and returns a new slice containing the lines of the patched file.
35803-// It is a wrapper around diff.Apply; see that function for preconditions.
35804-func applyEdits(mapper *protocol.Mapper, edits []protocol.TextEdit, windowsLineEndings bool) ([]byte, error) {
35805-	diffEdits, err := source.FromProtocolEdits(mapper, edits)
35806-	if err != nil {
35807-		return nil, err
35808-	}
35809-	patched, err := diff.ApplyBytes(mapper.Content, diffEdits)
35810-	if err != nil {
35811-		return nil, err
35812-	}
35813-	if windowsLineEndings {
35814-		patched = toWindowsLineEndings(patched)
35815-	}
35816-	return patched, nil
35817-}
35818diff -urN a/gopls/internal/lsp/fake/editor.go b/gopls/internal/lsp/fake/editor.go
35819--- a/gopls/internal/lsp/fake/editor.go	2000-01-01 00:00:00.000000000 -0000
35820+++ b/gopls/internal/lsp/fake/editor.go	1970-01-01 00:00:00.000000000 +0000
35821@@ -1,1464 +0,0 @@
35822-// Copyright 2020 The Go Authors. All rights reserved.
35823-// Use of this source code is governed by a BSD-style
35824-// license that can be found in the LICENSE file.
35825-
35826-package fake
35827-
35828-import (
35829-	"bytes"
35830-	"context"
35831-	"errors"
35832-	"fmt"
35833-	"os"
35834-	"path"
35835-	"path/filepath"
35836-	"regexp"
35837-	"strings"
35838-	"sync"
35839-
35840-	"golang.org/x/tools/gopls/internal/lsp/command"
35841-	"golang.org/x/tools/gopls/internal/lsp/glob"
35842-	"golang.org/x/tools/gopls/internal/lsp/protocol"
35843-	"golang.org/x/tools/gopls/internal/lsp/source"
35844-	"golang.org/x/tools/gopls/internal/span"
35845-	"golang.org/x/tools/internal/jsonrpc2"
35846-	"golang.org/x/tools/internal/jsonrpc2/servertest"
35847-	"golang.org/x/tools/internal/xcontext"
35848-)
35849-
35850-// Editor is a fake editor client.  It keeps track of client state and can be
35851-// used for writing LSP tests.
35852-type Editor struct {
35853-
35854-	// Server, client, and sandbox are concurrency safe and written only
35855-	// at construction time, so do not require synchronization.
35856-	Server     protocol.Server
35857-	cancelConn func()
35858-	serverConn jsonrpc2.Conn
35859-	client     *Client
35860-	sandbox    *Sandbox
35861-	defaultEnv map[string]string
35862-
35863-	// TODO(adonovan): buffers should be keyed by protocol.DocumentURI.
35864-	mu                 sync.Mutex
35865-	config             EditorConfig                // editor configuration
35866-	buffers            map[string]buffer           // open buffers (relative path -> buffer content)
35867-	serverCapabilities protocol.ServerCapabilities // capabilities / options
35868-	watchPatterns      []*glob.Glob                // glob patterns to watch
35869-
35870-	// Call metrics for the purpose of expectations. This is done in an ad-hoc
35871-	// manner for now. Perhaps in the future we should do something more
35872-	// systematic. Guarded with a separate mutex as calls may need to be accessed
35873-	// asynchronously via callbacks into the Editor.
35874-	callsMu sync.Mutex
35875-	calls   CallCounts
35876-}
35877-
35878-// CallCounts tracks the number of protocol notifications of different types.
35879-type CallCounts struct {
35880-	DidOpen, DidChange, DidSave, DidChangeWatchedFiles, DidClose uint64
35881-}
35882-
35883-// buffer holds information about an open buffer in the editor.
35884-type buffer struct {
35885-	version int              // monotonic version; incremented on edits
35886-	path    string           // relative path in the workspace
35887-	mapper  *protocol.Mapper // buffer content
35888-	dirty   bool             // if true, content is unsaved (TODO(rfindley): rename this field)
35889-}
35890-
35891-func (b buffer) text() string {
35892-	return string(b.mapper.Content)
35893-}
35894-
35895-// EditorConfig configures the editor's LSP session. This is similar to
35896-// source.UserOptions, but we use a separate type here so that we expose only
35897-// that configuration which we support.
35898-//
35899-// The zero value for EditorConfig should correspond to its defaults.
35900-type EditorConfig struct {
35901-	// Env holds environment variables to apply on top of the default editor
35902-	// environment. When applying these variables, the special string
35903-	// $SANDBOX_WORKDIR is replaced by the absolute path to the sandbox working
35904-	// directory.
35905-	Env map[string]string
35906-
35907-	// WorkspaceFolders is the workspace folders to configure on the LSP server,
35908-	// relative to the sandbox workdir.
35909-	//
35910-	// As a special case, if WorkspaceFolders is nil the editor defaults to
35911-	// configuring a single workspace folder corresponding to the workdir root.
35912-	// To explicitly send no workspace folders, use an empty (non-nil) slice.
35913-	WorkspaceFolders []string
35914-
35915-	// Whether to edit files with windows line endings.
35916-	WindowsLineEndings bool
35917-
35918-	// Map of language ID -> regexp to match, used to set the file type of new
35919-	// buffers. Applied as an overlay on top of the following defaults:
35920-	//  "go" -> ".*\.go"
35921-	//  "go.mod" -> "go\.mod"
35922-	//  "go.sum" -> "go\.sum"
35923-	//  "gotmpl" -> ".*tmpl"
35924-	FileAssociations map[string]string
35925-
35926-	// Settings holds user-provided configuration for the LSP server.
35927-	Settings map[string]interface{}
35928-}
35929-
35930-// NewEditor creates a new Editor.
35931-func NewEditor(sandbox *Sandbox, config EditorConfig) *Editor {
35932-	return &Editor{
35933-		buffers:    make(map[string]buffer),
35934-		sandbox:    sandbox,
35935-		defaultEnv: sandbox.GoEnv(),
35936-		config:     config,
35937-	}
35938-}
35939-
35940-// Connect configures the editor to communicate with an LSP server on conn. It
35941-// is not concurrency safe, and should be called at most once, before using the
35942-// editor.
35943-//
35944-// It returns the editor, so that it may be called as follows:
35945-//
35946-//	editor, err := NewEditor(s).Connect(ctx, conn, hooks)
35947-func (e *Editor) Connect(ctx context.Context, connector servertest.Connector, hooks ClientHooks, skipApplyEdits bool) (*Editor, error) {
35948-	bgCtx, cancelConn := context.WithCancel(xcontext.Detach(ctx))
35949-	conn := connector.Connect(bgCtx)
35950-	e.cancelConn = cancelConn
35951-
35952-	e.serverConn = conn
35953-	e.Server = protocol.ServerDispatcher(conn)
35954-	e.client = &Client{editor: e, hooks: hooks, skipApplyEdits: skipApplyEdits}
35955-	conn.Go(bgCtx,
35956-		protocol.Handlers(
35957-			protocol.ClientHandler(e.client,
35958-				jsonrpc2.MethodNotFound)))
35959-
35960-	if err := e.initialize(ctx); err != nil {
35961-		return nil, err
35962-	}
35963-	e.sandbox.Workdir.AddWatcher(e.onFileChanges)
35964-	return e, nil
35965-}
35966-
35967-func (e *Editor) Stats() CallCounts {
35968-	e.callsMu.Lock()
35969-	defer e.callsMu.Unlock()
35970-	return e.calls
35971-}
35972-
35973-// Shutdown issues the 'shutdown' LSP notification.
35974-func (e *Editor) Shutdown(ctx context.Context) error {
35975-	if e.Server != nil {
35976-		if err := e.Server.Shutdown(ctx); err != nil {
35977-			return fmt.Errorf("Shutdown: %w", err)
35978-		}
35979-	}
35980-	return nil
35981-}
35982-
35983-// Exit issues the 'exit' LSP notification.
35984-func (e *Editor) Exit(ctx context.Context) error {
35985-	if e.Server != nil {
35986-		// Not all LSP clients issue the exit RPC, but we do so here to ensure that
35987-		// we gracefully handle it on multi-session servers.
35988-		if err := e.Server.Exit(ctx); err != nil {
35989-			return fmt.Errorf("Exit: %w", err)
35990-		}
35991-	}
35992-	return nil
35993-}
35994-
35995-// Close issues the shutdown and exit sequence an editor should.
35996-func (e *Editor) Close(ctx context.Context) error {
35997-	if err := e.Shutdown(ctx); err != nil {
35998-		return err
35999-	}
36000-	if err := e.Exit(ctx); err != nil {
36001-		return err
36002-	}
36003-	defer func() {
36004-		e.cancelConn()
36005-	}()
36006-
36007-	// called close on the editor should result in the connection closing
36008-	select {
36009-	case <-e.serverConn.Done():
36010-		// connection closed itself
36011-		return nil
36012-	case <-ctx.Done():
36013-		return fmt.Errorf("connection not closed: %w", ctx.Err())
36014-	}
36015-}
36016-
36017-// Client returns the LSP client for this editor.
36018-func (e *Editor) Client() *Client {
36019-	return e.client
36020-}
36021-
36022-// settingsLocked builds the settings map for use in LSP settings RPCs.
36023-//
36024-// e.mu must be held while calling this function.
36025-func (e *Editor) settingsLocked() map[string]interface{} {
36026-	env := make(map[string]string)
36027-	for k, v := range e.defaultEnv {
36028-		env[k] = v
36029-	}
36030-	for k, v := range e.config.Env {
36031-		env[k] = v
36032-	}
36033-	for k, v := range env {
36034-		v = strings.ReplaceAll(v, "$SANDBOX_WORKDIR", e.sandbox.Workdir.RootURI().SpanURI().Filename())
36035-		env[k] = v
36036-	}
36037-
36038-	settings := map[string]interface{}{
36039-		"env": env,
36040-
36041-		// Use verbose progress reporting so that regtests can assert on
36042-		// asynchronous operations being completed (such as diagnosing a snapshot).
36043-		"verboseWorkDoneProgress": true,
36044-
36045-		// Set a generous completion budget, so that tests don't flake because
36046-		// completions are too slow.
36047-		"completionBudget": "10s",
36048-
36049-		// Shorten the diagnostic delay to speed up test execution (else we'd add
36050-		// the default delay to each assertion about diagnostics)
36051-		"diagnosticsDelay": "10ms",
36052-	}
36053-
36054-	for k, v := range e.config.Settings {
36055-		if k == "env" {
36056-			panic("must not provide env via the EditorConfig.Settings field: use the EditorConfig.Env field instead")
36057-		}
36058-		settings[k] = v
36059-	}
36060-
36061-	return settings
36062-}
36063-
36064-func (e *Editor) initialize(ctx context.Context) error {
36065-	params := &protocol.ParamInitialize{}
36066-	params.ClientInfo = &protocol.Msg_XInitializeParams_clientInfo{}
36067-	params.ClientInfo.Name = "fakeclient"
36068-	params.ClientInfo.Version = "v1.0.0"
36069-	e.mu.Lock()
36070-	params.WorkspaceFolders = e.makeWorkspaceFoldersLocked()
36071-	params.InitializationOptions = e.settingsLocked()
36072-	e.mu.Unlock()
36073-	params.Capabilities.Workspace.Configuration = true
36074-	params.Capabilities.Window.WorkDoneProgress = true
36075-
36076-	// TODO: set client capabilities
36077-	params.Capabilities.TextDocument.Completion.CompletionItem.TagSupport.ValueSet = []protocol.CompletionItemTag{protocol.ComplDeprecated}
36078-
36079-	params.Capabilities.TextDocument.Completion.CompletionItem.SnippetSupport = true
36080-	params.Capabilities.TextDocument.SemanticTokens.Requests.Full.Value = true
36081-	// copied from lsp/semantic.go to avoid import cycle in tests
36082-	params.Capabilities.TextDocument.SemanticTokens.TokenTypes = []string{
36083-		"namespace", "type", "class", "enum", "interface",
36084-		"struct", "typeParameter", "parameter", "variable", "property", "enumMember",
36085-		"event", "function", "method", "macro", "keyword", "modifier", "comment",
36086-		"string", "number", "regexp", "operator",
36087-	}
36088-	params.Capabilities.TextDocument.SemanticTokens.TokenModifiers = []string{
36089-		"declaration", "definition", "readonly", "static",
36090-		"deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary",
36091-	}
36092-
36093-	// This is a bit of a hack, since the fake editor doesn't actually support
36094-	// watching changed files that match a specific glob pattern. However, the
36095-	// editor does send didChangeWatchedFiles notifications, so set this to
36096-	// true.
36097-	params.Capabilities.Workspace.DidChangeWatchedFiles.DynamicRegistration = true
36098-	params.Capabilities.Workspace.WorkspaceEdit = &protocol.WorkspaceEditClientCapabilities{
36099-		ResourceOperations: []protocol.ResourceOperationKind{
36100-			"rename",
36101-		},
36102-	}
36103-
36104-	trace := protocol.TraceValues("messages")
36105-	params.Trace = &trace
36106-	// TODO: support workspace folders.
36107-	if e.Server != nil {
36108-		resp, err := e.Server.Initialize(ctx, params)
36109-		if err != nil {
36110-			return fmt.Errorf("initialize: %w", err)
36111-		}
36112-		e.mu.Lock()
36113-		e.serverCapabilities = resp.Capabilities
36114-		e.mu.Unlock()
36115-
36116-		if err := e.Server.Initialized(ctx, &protocol.InitializedParams{}); err != nil {
36117-			return fmt.Errorf("initialized: %w", err)
36118-		}
36119-	}
36120-	// TODO: await initial configuration here, or expect gopls to manage that?
36121-	return nil
36122-}
36123-
36124-// makeWorkspaceFoldersLocked creates a slice of workspace folders to use for
36125-// this editing session, based on the editor configuration.
36126-//
36127-// e.mu must be held while calling this function.
36128-func (e *Editor) makeWorkspaceFoldersLocked() (folders []protocol.WorkspaceFolder) {
36129-	paths := e.config.WorkspaceFolders
36130-	if len(paths) == 0 {
36131-		paths = append(paths, string(e.sandbox.Workdir.RelativeTo))
36132-	}
36133-
36134-	for _, path := range paths {
36135-		uri := string(e.sandbox.Workdir.URI(path))
36136-		folders = append(folders, protocol.WorkspaceFolder{
36137-			URI:  uri,
36138-			Name: filepath.Base(uri),
36139-		})
36140-	}
36141-
36142-	return folders
36143-}
36144-
36145-// onFileChanges is registered to be called by the Workdir on any writes that
36146-// go through the Workdir API. It is called synchronously by the Workdir.
36147-func (e *Editor) onFileChanges(ctx context.Context, evts []protocol.FileEvent) {
36148-	if e.Server == nil {
36149-		return
36150-	}
36151-
36152-	// e may be locked when onFileChanges is called, but it is important that we
36153-	// synchronously increment this counter so that we can subsequently assert on
36154-	// the number of expected DidChangeWatchedFiles calls.
36155-	e.callsMu.Lock()
36156-	e.calls.DidChangeWatchedFiles++
36157-	e.callsMu.Unlock()
36158-
36159-	// Since e may be locked, we must run this mutation asynchronously.
36160-	go func() {
36161-		e.mu.Lock()
36162-		defer e.mu.Unlock()
36163-		for _, evt := range evts {
36164-			// Always send an on-disk change, even for events that seem useless
36165-			// because they're shadowed by an open buffer.
36166-			path := e.sandbox.Workdir.URIToPath(evt.URI)
36167-			if buf, ok := e.buffers[path]; ok {
36168-				// Following VS Code, don't honor deletions or changes to dirty buffers.
36169-				if buf.dirty || evt.Type == protocol.Deleted {
36170-					continue
36171-				}
36172-
36173-				content, err := e.sandbox.Workdir.ReadFile(path)
36174-				if err != nil {
36175-					continue // A race with some other operation.
36176-				}
36177-				// No need to update if the buffer content hasn't changed.
36178-				if string(content) == buf.text() {
36179-					continue
36180-				}
36181-				// During shutdown, this call will fail. Ignore the error.
36182-				_ = e.setBufferContentLocked(ctx, path, false, content, nil)
36183-			}
36184-		}
36185-		var matchedEvts []protocol.FileEvent
36186-		for _, evt := range evts {
36187-			filename := filepath.ToSlash(evt.URI.SpanURI().Filename())
36188-			for _, g := range e.watchPatterns {
36189-				if g.Match(filename) {
36190-					matchedEvts = append(matchedEvts, evt)
36191-					break
36192-				}
36193-			}
36194-		}
36195-
36196-		// TODO(rfindley): don't send notifications while locked.
36197-		e.Server.DidChangeWatchedFiles(ctx, &protocol.DidChangeWatchedFilesParams{
36198-			Changes: matchedEvts,
36199-		})
36200-	}()
36201-}
36202-
36203-// OpenFile creates a buffer for the given workdir-relative file.
36204-//
36205-// If the file is already open, it is a no-op.
36206-func (e *Editor) OpenFile(ctx context.Context, path string) error {
36207-	if e.HasBuffer(path) {
36208-		return nil
36209-	}
36210-	content, err := e.sandbox.Workdir.ReadFile(path)
36211-	if err != nil {
36212-		return err
36213-	}
36214-	if e.Config().WindowsLineEndings {
36215-		content = toWindowsLineEndings(content)
36216-	}
36217-	return e.createBuffer(ctx, path, false, content)
36218-}
36219-
36220-// toWindowsLineEndings checks whether content has windows line endings.
36221-//
36222-// If so, it returns content unmodified. If not, it returns a new byte slice modified to use CRLF line endings.
36223-func toWindowsLineEndings(content []byte) []byte {
36224-	abnormal := false
36225-	for i, b := range content {
36226-		if b == '\n' && (i == 0 || content[i-1] != '\r') {
36227-			abnormal = true
36228-			break
36229-		}
36230-	}
36231-	if !abnormal {
36232-		return content
36233-	}
36234-	var buf bytes.Buffer
36235-	for i, b := range content {
36236-		if b == '\n' && (i == 0 || content[i-1] != '\r') {
36237-			buf.WriteByte('\r')
36238-		}
36239-		buf.WriteByte(b)
36240-	}
36241-	return buf.Bytes()
36242-}
36243-
36244-// CreateBuffer creates a new unsaved buffer corresponding to the workdir path,
36245-// containing the given textual content.
36246-func (e *Editor) CreateBuffer(ctx context.Context, path, content string) error {
36247-	return e.createBuffer(ctx, path, true, []byte(content))
36248-}
36249-
36250-func (e *Editor) createBuffer(ctx context.Context, path string, dirty bool, content []byte) error {
36251-	e.mu.Lock()
36252-
36253-	if _, ok := e.buffers[path]; ok {
36254-		e.mu.Unlock()
36255-		return fmt.Errorf("buffer %q already exists", path)
36256-	}
36257-
36258-	uri := e.sandbox.Workdir.URI(path).SpanURI()
36259-	buf := buffer{
36260-		version: 1,
36261-		path:    path,
36262-		mapper:  protocol.NewMapper(uri, content),
36263-		dirty:   dirty,
36264-	}
36265-	e.buffers[path] = buf
36266-
36267-	item := e.textDocumentItem(buf)
36268-	e.mu.Unlock()
36269-
36270-	return e.sendDidOpen(ctx, item)
36271-}
36272-
36273-// textDocumentItem builds a protocol.TextDocumentItem for the given buffer.
36274-//
36275-// Precondition: e.mu must be held.
36276-func (e *Editor) textDocumentItem(buf buffer) protocol.TextDocumentItem {
36277-	return protocol.TextDocumentItem{
36278-		URI:        e.sandbox.Workdir.URI(buf.path),
36279-		LanguageID: languageID(buf.path, e.config.FileAssociations),
36280-		Version:    int32(buf.version),
36281-		Text:       buf.text(),
36282-	}
36283-}
36284-
36285-func (e *Editor) sendDidOpen(ctx context.Context, item protocol.TextDocumentItem) error {
36286-	if e.Server != nil {
36287-		if err := e.Server.DidOpen(ctx, &protocol.DidOpenTextDocumentParams{
36288-			TextDocument: item,
36289-		}); err != nil {
36290-			return fmt.Errorf("DidOpen: %w", err)
36291-		}
36292-		e.callsMu.Lock()
36293-		e.calls.DidOpen++
36294-		e.callsMu.Unlock()
36295-	}
36296-	return nil
36297-}
36298-
36299-var defaultFileAssociations = map[string]*regexp.Regexp{
36300-	"go":      regexp.MustCompile(`^.*\.go$`), // '$' is important: don't match .gotmpl!
36301-	"go.mod":  regexp.MustCompile(`^go\.mod$`),
36302-	"go.sum":  regexp.MustCompile(`^go(\.work)?\.sum$`),
36303-	"go.work": regexp.MustCompile(`^go\.work$`),
36304-	"gotmpl":  regexp.MustCompile(`^.*tmpl$`),
36305-}
36306-
36307-// languageID returns the language identifier for the path p given the user
36308-// configured fileAssociations.
36309-func languageID(p string, fileAssociations map[string]string) string {
36310-	base := path.Base(p)
36311-	for lang, re := range fileAssociations {
36312-		re := regexp.MustCompile(re)
36313-		if re.MatchString(base) {
36314-			return lang
36315-		}
36316-	}
36317-	for lang, re := range defaultFileAssociations {
36318-		if re.MatchString(base) {
36319-			return lang
36320-		}
36321-	}
36322-	return ""
36323-}
36324-
36325-// CloseBuffer removes the current buffer (regardless of whether it is saved).
36326-func (e *Editor) CloseBuffer(ctx context.Context, path string) error {
36327-	e.mu.Lock()
36328-	_, ok := e.buffers[path]
36329-	if !ok {
36330-		e.mu.Unlock()
36331-		return ErrUnknownBuffer
36332-	}
36333-	delete(e.buffers, path)
36334-	e.mu.Unlock()
36335-
36336-	return e.sendDidClose(ctx, e.TextDocumentIdentifier(path))
36337-}
36338-
36339-func (e *Editor) sendDidClose(ctx context.Context, doc protocol.TextDocumentIdentifier) error {
36340-	if e.Server != nil {
36341-		if err := e.Server.DidClose(ctx, &protocol.DidCloseTextDocumentParams{
36342-			TextDocument: doc,
36343-		}); err != nil {
36344-			return fmt.Errorf("DidClose: %w", err)
36345-		}
36346-		e.callsMu.Lock()
36347-		e.calls.DidClose++
36348-		e.callsMu.Unlock()
36349-	}
36350-	return nil
36351-}
36352-
36353-func (e *Editor) TextDocumentIdentifier(path string) protocol.TextDocumentIdentifier {
36354-	return protocol.TextDocumentIdentifier{
36355-		URI: e.sandbox.Workdir.URI(path),
36356-	}
36357-}
36358-
36359-// SaveBuffer writes the content of the buffer specified by the given path to
36360-// the filesystem.
36361-func (e *Editor) SaveBuffer(ctx context.Context, path string) error {
36362-	if err := e.OrganizeImports(ctx, path); err != nil {
36363-		return fmt.Errorf("organizing imports before save: %w", err)
36364-	}
36365-	if err := e.FormatBuffer(ctx, path); err != nil {
36366-		return fmt.Errorf("formatting before save: %w", err)
36367-	}
36368-	return e.SaveBufferWithoutActions(ctx, path)
36369-}
36370-
36371-func (e *Editor) SaveBufferWithoutActions(ctx context.Context, path string) error {
36372-	e.mu.Lock()
36373-	defer e.mu.Unlock()
36374-	buf, ok := e.buffers[path]
36375-	if !ok {
36376-		return fmt.Errorf(fmt.Sprintf("unknown buffer: %q", path))
36377-	}
36378-	content := buf.text()
36379-	includeText := false
36380-	syncOptions, ok := e.serverCapabilities.TextDocumentSync.(protocol.TextDocumentSyncOptions)
36381-	if ok {
36382-		includeText = syncOptions.Save.IncludeText
36383-	}
36384-
36385-	docID := e.TextDocumentIdentifier(buf.path)
36386-	if e.Server != nil {
36387-		if err := e.Server.WillSave(ctx, &protocol.WillSaveTextDocumentParams{
36388-			TextDocument: docID,
36389-			Reason:       protocol.Manual,
36390-		}); err != nil {
36391-			return fmt.Errorf("WillSave: %w", err)
36392-		}
36393-	}
36394-	if err := e.sandbox.Workdir.WriteFile(ctx, path, content); err != nil {
36395-		return fmt.Errorf("writing %q: %w", path, err)
36396-	}
36397-
36398-	buf.dirty = false
36399-	e.buffers[path] = buf
36400-
36401-	if e.Server != nil {
36402-		params := &protocol.DidSaveTextDocumentParams{
36403-			TextDocument: docID,
36404-		}
36405-		if includeText {
36406-			params.Text = &content
36407-		}
36408-		if err := e.Server.DidSave(ctx, params); err != nil {
36409-			return fmt.Errorf("DidSave: %w", err)
36410-		}
36411-		e.callsMu.Lock()
36412-		e.calls.DidSave++
36413-		e.callsMu.Unlock()
36414-	}
36415-	return nil
36416-}
36417-
36418-// ErrNoMatch is returned if a regexp search fails.
36419-var (
36420-	ErrNoMatch       = errors.New("no match")
36421-	ErrUnknownBuffer = errors.New("unknown buffer")
36422-)
36423-
36424-// regexpLocation returns the location of the first occurrence of either re
36425-// or its singular subgroup. It returns ErrNoMatch if the regexp doesn't match.
36426-func regexpLocation(mapper *protocol.Mapper, re string) (protocol.Location, error) {
36427-	var start, end int
36428-	rec, err := regexp.Compile(re)
36429-	if err != nil {
36430-		return protocol.Location{}, err
36431-	}
36432-	indexes := rec.FindSubmatchIndex(mapper.Content)
36433-	if indexes == nil {
36434-		return protocol.Location{}, ErrNoMatch
36435-	}
36436-	switch len(indexes) {
36437-	case 2:
36438-		// no subgroups: return the range of the regexp expression
36439-		start, end = indexes[0], indexes[1]
36440-	case 4:
36441-		// one subgroup: return its range
36442-		start, end = indexes[2], indexes[3]
36443-	default:
36444-		return protocol.Location{}, fmt.Errorf("invalid search regexp %q: expect either 0 or 1 subgroups, got %d", re, len(indexes)/2-1)
36445-	}
36446-	return mapper.OffsetLocation(start, end)
36447-}
36448-
36449-// RegexpSearch returns the Location of the first match for re in the buffer
36450-// bufName. For convenience, RegexpSearch supports the following two modes:
36451-//  1. If re has no subgroups, return the position of the match for re itself.
36452-//  2. If re has one subgroup, return the position of the first subgroup.
36453-//
36454-// It returns an error re is invalid, has more than one subgroup, or doesn't
36455-// match the buffer.
36456-func (e *Editor) RegexpSearch(bufName, re string) (protocol.Location, error) {
36457-	e.mu.Lock()
36458-	buf, ok := e.buffers[bufName]
36459-	e.mu.Unlock()
36460-	if !ok {
36461-		return protocol.Location{}, ErrUnknownBuffer
36462-	}
36463-	return regexpLocation(buf.mapper, re)
36464-}
36465-
36466-// RegexpReplace edits the buffer corresponding to path by replacing the first
36467-// instance of re, or its first subgroup, with the replace text. See
36468-// RegexpSearch for more explanation of these two modes.
36469-// It returns an error if re is invalid, has more than one subgroup, or doesn't
36470-// match the buffer.
36471-func (e *Editor) RegexpReplace(ctx context.Context, path, re, replace string) error {
36472-	e.mu.Lock()
36473-	defer e.mu.Unlock()
36474-	buf, ok := e.buffers[path]
36475-	if !ok {
36476-		return ErrUnknownBuffer
36477-	}
36478-	loc, err := regexpLocation(buf.mapper, re)
36479-	if err != nil {
36480-		return err
36481-	}
36482-	edits := []protocol.TextEdit{{
36483-		Range:   loc.Range,
36484-		NewText: replace,
36485-	}}
36486-	patched, err := applyEdits(buf.mapper, edits, e.config.WindowsLineEndings)
36487-	if err != nil {
36488-		return fmt.Errorf("editing %q: %v", path, err)
36489-	}
36490-	return e.setBufferContentLocked(ctx, path, true, patched, edits)
36491-}
36492-
36493-// EditBuffer applies the given test edits to the buffer identified by path.
36494-func (e *Editor) EditBuffer(ctx context.Context, path string, edits []protocol.TextEdit) error {
36495-	e.mu.Lock()
36496-	defer e.mu.Unlock()
36497-	return e.editBufferLocked(ctx, path, edits)
36498-}
36499-
36500-func (e *Editor) SetBufferContent(ctx context.Context, path, content string) error {
36501-	e.mu.Lock()
36502-	defer e.mu.Unlock()
36503-	return e.setBufferContentLocked(ctx, path, true, []byte(content), nil)
36504-}
36505-
36506-// HasBuffer reports whether the file name is open in the editor.
36507-func (e *Editor) HasBuffer(name string) bool {
36508-	e.mu.Lock()
36509-	defer e.mu.Unlock()
36510-	_, ok := e.buffers[name]
36511-	return ok
36512-}
36513-
36514-// BufferText returns the content of the buffer with the given name, or "" if
36515-// the file at that path is not open. The second return value reports whether
36516-// the file is open.
36517-func (e *Editor) BufferText(name string) (string, bool) {
36518-	e.mu.Lock()
36519-	defer e.mu.Unlock()
36520-	buf, ok := e.buffers[name]
36521-	if !ok {
36522-		return "", false
36523-	}
36524-	return buf.text(), true
36525-}
36526-
36527-// Mapper returns the protocol.Mapper for the given buffer name, if it is open.
36528-func (e *Editor) Mapper(name string) (*protocol.Mapper, error) {
36529-	e.mu.Lock()
36530-	defer e.mu.Unlock()
36531-	buf, ok := e.buffers[name]
36532-	if !ok {
36533-		return nil, fmt.Errorf("no mapper for %q", name)
36534-	}
36535-	return buf.mapper, nil
36536-}
36537-
36538-// BufferVersion returns the current version of the buffer corresponding to
36539-// name (or 0 if it is not being edited).
36540-func (e *Editor) BufferVersion(name string) int {
36541-	e.mu.Lock()
36542-	defer e.mu.Unlock()
36543-	return e.buffers[name].version
36544-}
36545-
36546-func (e *Editor) editBufferLocked(ctx context.Context, path string, edits []protocol.TextEdit) error {
36547-	buf, ok := e.buffers[path]
36548-	if !ok {
36549-		return fmt.Errorf("unknown buffer %q", path)
36550-	}
36551-	content, err := applyEdits(buf.mapper, edits, e.config.WindowsLineEndings)
36552-	if err != nil {
36553-		return fmt.Errorf("editing %q: %v; edits:\n%v", path, err, edits)
36554-	}
36555-	return e.setBufferContentLocked(ctx, path, true, content, edits)
36556-}
36557-
36558-func (e *Editor) setBufferContentLocked(ctx context.Context, path string, dirty bool, content []byte, fromEdits []protocol.TextEdit) error {
36559-	buf, ok := e.buffers[path]
36560-	if !ok {
36561-		return fmt.Errorf("unknown buffer %q", path)
36562-	}
36563-	buf.mapper = protocol.NewMapper(buf.mapper.URI, content)
36564-	buf.version++
36565-	buf.dirty = dirty
36566-	e.buffers[path] = buf
36567-	// A simple heuristic: if there is only one edit, send it incrementally.
36568-	// Otherwise, send the entire content.
36569-	var evts []protocol.TextDocumentContentChangeEvent
36570-	if len(fromEdits) == 1 {
36571-		evts = append(evts, EditToChangeEvent(fromEdits[0]))
36572-	} else {
36573-		evts = append(evts, protocol.TextDocumentContentChangeEvent{
36574-			Text: buf.text(),
36575-		})
36576-	}
36577-	params := &protocol.DidChangeTextDocumentParams{
36578-		TextDocument: protocol.VersionedTextDocumentIdentifier{
36579-			Version:                int32(buf.version),
36580-			TextDocumentIdentifier: e.TextDocumentIdentifier(buf.path),
36581-		},
36582-		ContentChanges: evts,
36583-	}
36584-	if e.Server != nil {
36585-		if err := e.Server.DidChange(ctx, params); err != nil {
36586-			return fmt.Errorf("DidChange: %w", err)
36587-		}
36588-		e.callsMu.Lock()
36589-		e.calls.DidChange++
36590-		e.callsMu.Unlock()
36591-	}
36592-	return nil
36593-}
36594-
36595-// GoToDefinition jumps to the definition of the symbol at the given position
36596-// in an open buffer. It returns the location of the resulting jump.
36597-//
36598-// TODO(rfindley): rename to "Definition", to be consistent with LSP
36599-// terminology.
36600-func (e *Editor) GoToDefinition(ctx context.Context, loc protocol.Location) (protocol.Location, error) {
36601-	if err := e.checkBufferLocation(loc); err != nil {
36602-		return protocol.Location{}, err
36603-	}
36604-	params := &protocol.DefinitionParams{}
36605-	params.TextDocument.URI = loc.URI
36606-	params.Position = loc.Range.Start
36607-
36608-	resp, err := e.Server.Definition(ctx, params)
36609-	if err != nil {
36610-		return protocol.Location{}, fmt.Errorf("definition: %w", err)
36611-	}
36612-	return e.extractFirstLocation(ctx, resp)
36613-}
36614-
36615-// GoToTypeDefinition jumps to the type definition of the symbol at the given location
36616-// in an open buffer.
36617-func (e *Editor) GoToTypeDefinition(ctx context.Context, loc protocol.Location) (protocol.Location, error) {
36618-	if err := e.checkBufferLocation(loc); err != nil {
36619-		return protocol.Location{}, err
36620-	}
36621-	params := &protocol.TypeDefinitionParams{}
36622-	params.TextDocument.URI = loc.URI
36623-	params.Position = loc.Range.Start
36624-
36625-	resp, err := e.Server.TypeDefinition(ctx, params)
36626-	if err != nil {
36627-		return protocol.Location{}, fmt.Errorf("type definition: %w", err)
36628-	}
36629-	return e.extractFirstLocation(ctx, resp)
36630-}
36631-
36632-// extractFirstLocation returns the first location.
36633-// It opens the file if needed.
36634-func (e *Editor) extractFirstLocation(ctx context.Context, locs []protocol.Location) (protocol.Location, error) {
36635-	if len(locs) == 0 {
36636-		return protocol.Location{}, nil
36637-	}
36638-
36639-	newPath := e.sandbox.Workdir.URIToPath(locs[0].URI)
36640-	if !e.HasBuffer(newPath) {
36641-		if err := e.OpenFile(ctx, newPath); err != nil {
36642-			return protocol.Location{}, fmt.Errorf("OpenFile: %w", err)
36643-		}
36644-	}
36645-	return locs[0], nil
36646-}
36647-
36648-// Symbol performs a workspace symbol search using query
36649-func (e *Editor) Symbol(ctx context.Context, query string) ([]protocol.SymbolInformation, error) {
36650-	params := &protocol.WorkspaceSymbolParams{Query: query}
36651-	return e.Server.Symbol(ctx, params)
36652-}
36653-
36654-// OrganizeImports requests and performs the source.organizeImports codeAction.
36655-func (e *Editor) OrganizeImports(ctx context.Context, path string) error {
36656-	loc := protocol.Location{URI: e.sandbox.Workdir.URI(path)} // zero Range => whole file
36657-	_, err := e.applyCodeActions(ctx, loc, nil, protocol.SourceOrganizeImports)
36658-	return err
36659-}
36660-
36661-// RefactorRewrite requests and performs the source.refactorRewrite codeAction.
36662-func (e *Editor) RefactorRewrite(ctx context.Context, loc protocol.Location) error {
36663-	applied, err := e.applyCodeActions(ctx, loc, nil, protocol.RefactorRewrite)
36664-	if err != nil {
36665-		return err
36666-	}
36667-	if applied == 0 {
36668-		return fmt.Errorf("no refactorings were applied")
36669-	}
36670-	return nil
36671-}
36672-
36673-// ApplyQuickFixes requests and performs the quickfix codeAction.
36674-func (e *Editor) ApplyQuickFixes(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic) error {
36675-	applied, err := e.applyCodeActions(ctx, loc, diagnostics, protocol.SourceFixAll, protocol.QuickFix)
36676-	if applied == 0 {
36677-		return fmt.Errorf("no quick fixes were applied")
36678-	}
36679-	return err
36680-}
36681-
36682-// ApplyCodeAction applies the given code action.
36683-func (e *Editor) ApplyCodeAction(ctx context.Context, action protocol.CodeAction) error {
36684-	if action.Edit != nil {
36685-		for _, change := range action.Edit.DocumentChanges {
36686-			if change.TextDocumentEdit != nil {
36687-				path := e.sandbox.Workdir.URIToPath(change.TextDocumentEdit.TextDocument.URI)
36688-				if int32(e.buffers[path].version) != change.TextDocumentEdit.TextDocument.Version {
36689-					// Skip edits for old versions.
36690-					continue
36691-				}
36692-				if err := e.EditBuffer(ctx, path, change.TextDocumentEdit.Edits); err != nil {
36693-					return fmt.Errorf("editing buffer %q: %w", path, err)
36694-				}
36695-			}
36696-		}
36697-	}
36698-	// Execute any commands. The specification says that commands are
36699-	// executed after edits are applied.
36700-	if action.Command != nil {
36701-		if _, err := e.ExecuteCommand(ctx, &protocol.ExecuteCommandParams{
36702-			Command:   action.Command.Command,
36703-			Arguments: action.Command.Arguments,
36704-		}); err != nil {
36705-			return err
36706-		}
36707-	}
36708-	// Some commands may edit files on disk.
36709-	return e.sandbox.Workdir.CheckForFileChanges(ctx)
36710-}
36711-
36712-// GetQuickFixes returns the available quick fix code actions.
36713-func (e *Editor) GetQuickFixes(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic) ([]protocol.CodeAction, error) {
36714-	return e.getCodeActions(ctx, loc, diagnostics, protocol.QuickFix, protocol.SourceFixAll)
36715-}
36716-
36717-func (e *Editor) applyCodeActions(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic, only ...protocol.CodeActionKind) (int, error) {
36718-	actions, err := e.getCodeActions(ctx, loc, diagnostics, only...)
36719-	if err != nil {
36720-		return 0, err
36721-	}
36722-	applied := 0
36723-	for _, action := range actions {
36724-		if action.Title == "" {
36725-			return 0, fmt.Errorf("empty title for code action")
36726-		}
36727-		var match bool
36728-		for _, o := range only {
36729-			if action.Kind == o {
36730-				match = true
36731-				break
36732-			}
36733-		}
36734-		if !match {
36735-			continue
36736-		}
36737-		applied++
36738-		if err := e.ApplyCodeAction(ctx, action); err != nil {
36739-			return 0, err
36740-		}
36741-	}
36742-	return applied, nil
36743-}
36744-
36745-func (e *Editor) getCodeActions(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic, only ...protocol.CodeActionKind) ([]protocol.CodeAction, error) {
36746-	if e.Server == nil {
36747-		return nil, nil
36748-	}
36749-	params := &protocol.CodeActionParams{}
36750-	params.TextDocument.URI = loc.URI
36751-	params.Context.Only = only
36752-	params.Range = loc.Range // may be zero => whole file
36753-	if diagnostics != nil {
36754-		params.Context.Diagnostics = diagnostics
36755-	}
36756-	return e.Server.CodeAction(ctx, params)
36757-}
36758-
36759-func (e *Editor) ExecuteCommand(ctx context.Context, params *protocol.ExecuteCommandParams) (interface{}, error) {
36760-	if e.Server == nil {
36761-		return nil, nil
36762-	}
36763-	var match bool
36764-	if e.serverCapabilities.ExecuteCommandProvider != nil {
36765-		// Ensure that this command was actually listed as a supported command.
36766-		for _, command := range e.serverCapabilities.ExecuteCommandProvider.Commands {
36767-			if command == params.Command {
36768-				match = true
36769-				break
36770-			}
36771-		}
36772-	}
36773-	if !match {
36774-		return nil, fmt.Errorf("unsupported command %q", params.Command)
36775-	}
36776-	result, err := e.Server.ExecuteCommand(ctx, params)
36777-	if err != nil {
36778-		return nil, err
36779-	}
36780-	// Some commands use the go command, which writes directly to disk.
36781-	// For convenience, check for those changes.
36782-	if err := e.sandbox.Workdir.CheckForFileChanges(ctx); err != nil {
36783-		return nil, fmt.Errorf("checking for file changes: %v", err)
36784-	}
36785-	return result, nil
36786-}
36787-
36788-// FormatBuffer gofmts a Go file.
36789-func (e *Editor) FormatBuffer(ctx context.Context, path string) error {
36790-	if e.Server == nil {
36791-		return nil
36792-	}
36793-	e.mu.Lock()
36794-	version := e.buffers[path].version
36795-	e.mu.Unlock()
36796-	params := &protocol.DocumentFormattingParams{}
36797-	params.TextDocument.URI = e.sandbox.Workdir.URI(path)
36798-	edits, err := e.Server.Formatting(ctx, params)
36799-	if err != nil {
36800-		return fmt.Errorf("textDocument/formatting: %w", err)
36801-	}
36802-	e.mu.Lock()
36803-	defer e.mu.Unlock()
36804-	if versionAfter := e.buffers[path].version; versionAfter != version {
36805-		return fmt.Errorf("before receipt of formatting edits, buffer version changed from %d to %d", version, versionAfter)
36806-	}
36807-	if len(edits) == 0 {
36808-		return nil
36809-	}
36810-	return e.editBufferLocked(ctx, path, edits)
36811-}
36812-
36813-func (e *Editor) checkBufferLocation(loc protocol.Location) error {
36814-	e.mu.Lock()
36815-	defer e.mu.Unlock()
36816-	path := e.sandbox.Workdir.URIToPath(loc.URI)
36817-	buf, ok := e.buffers[path]
36818-	if !ok {
36819-		return fmt.Errorf("buffer %q is not open", path)
36820-	}
36821-
36822-	_, _, err := buf.mapper.RangeOffsets(loc.Range)
36823-	return err
36824-}
36825-
36826-// RunGenerate runs `go generate` non-recursively in the workdir-relative dir
36827-// path. It does not report any resulting file changes as a watched file
36828-// change, so must be followed by a call to Workdir.CheckForFileChanges once
36829-// the generate command has completed.
36830-// TODO(rFindley): this shouldn't be necessary anymore. Delete it.
36831-func (e *Editor) RunGenerate(ctx context.Context, dir string) error {
36832-	if e.Server == nil {
36833-		return nil
36834-	}
36835-	absDir := e.sandbox.Workdir.AbsPath(dir)
36836-	cmd, err := command.NewGenerateCommand("", command.GenerateArgs{
36837-		Dir:       protocol.URIFromSpanURI(span.URIFromPath(absDir)),
36838-		Recursive: false,
36839-	})
36840-	if err != nil {
36841-		return err
36842-	}
36843-	params := &protocol.ExecuteCommandParams{
36844-		Command:   cmd.Command,
36845-		Arguments: cmd.Arguments,
36846-	}
36847-	if _, err := e.ExecuteCommand(ctx, params); err != nil {
36848-		return fmt.Errorf("running generate: %v", err)
36849-	}
36850-	// Unfortunately we can't simply poll the workdir for file changes here,
36851-	// because server-side command may not have completed. In regtests, we can
36852-	// Await this state change, but here we must delegate that responsibility to
36853-	// the caller.
36854-	return nil
36855-}
36856-
36857-// CodeLens executes a codelens request on the server.
36858-func (e *Editor) CodeLens(ctx context.Context, path string) ([]protocol.CodeLens, error) {
36859-	if e.Server == nil {
36860-		return nil, nil
36861-	}
36862-	e.mu.Lock()
36863-	_, ok := e.buffers[path]
36864-	e.mu.Unlock()
36865-	if !ok {
36866-		return nil, fmt.Errorf("buffer %q is not open", path)
36867-	}
36868-	params := &protocol.CodeLensParams{
36869-		TextDocument: e.TextDocumentIdentifier(path),
36870-	}
36871-	lens, err := e.Server.CodeLens(ctx, params)
36872-	if err != nil {
36873-		return nil, err
36874-	}
36875-	return lens, nil
36876-}
36877-
36878-// Completion executes a completion request on the server.
36879-func (e *Editor) Completion(ctx context.Context, loc protocol.Location) (*protocol.CompletionList, error) {
36880-	if e.Server == nil {
36881-		return nil, nil
36882-	}
36883-	path := e.sandbox.Workdir.URIToPath(loc.URI)
36884-	e.mu.Lock()
36885-	_, ok := e.buffers[path]
36886-	e.mu.Unlock()
36887-	if !ok {
36888-		return nil, fmt.Errorf("buffer %q is not open", path)
36889-	}
36890-	params := &protocol.CompletionParams{
36891-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
36892-	}
36893-	completions, err := e.Server.Completion(ctx, params)
36894-	if err != nil {
36895-		return nil, err
36896-	}
36897-	return completions, nil
36898-}
36899-
36900-// AcceptCompletion accepts a completion for the given item at the given
36901-// position.
36902-func (e *Editor) AcceptCompletion(ctx context.Context, loc protocol.Location, item protocol.CompletionItem) error {
36903-	if e.Server == nil {
36904-		return nil
36905-	}
36906-	e.mu.Lock()
36907-	defer e.mu.Unlock()
36908-	path := e.sandbox.Workdir.URIToPath(loc.URI)
36909-	_, ok := e.buffers[path]
36910-	if !ok {
36911-		return fmt.Errorf("buffer %q is not open", path)
36912-	}
36913-	return e.editBufferLocked(ctx, path, append([]protocol.TextEdit{
36914-		*item.TextEdit,
36915-	}, item.AdditionalTextEdits...))
36916-}
36917-
36918-// Symbols executes a workspace/symbols request on the server.
36919-func (e *Editor) Symbols(ctx context.Context, sym string) ([]protocol.SymbolInformation, error) {
36920-	if e.Server == nil {
36921-		return nil, nil
36922-	}
36923-	params := &protocol.WorkspaceSymbolParams{Query: sym}
36924-	ans, err := e.Server.Symbol(ctx, params)
36925-	return ans, err
36926-}
36927-
36928-// CodeLens executes a codelens request on the server.
36929-func (e *Editor) InlayHint(ctx context.Context, path string) ([]protocol.InlayHint, error) {
36930-	if e.Server == nil {
36931-		return nil, nil
36932-	}
36933-	e.mu.Lock()
36934-	_, ok := e.buffers[path]
36935-	e.mu.Unlock()
36936-	if !ok {
36937-		return nil, fmt.Errorf("buffer %q is not open", path)
36938-	}
36939-	params := &protocol.InlayHintParams{
36940-		TextDocument: e.TextDocumentIdentifier(path),
36941-	}
36942-	hints, err := e.Server.InlayHint(ctx, params)
36943-	if err != nil {
36944-		return nil, err
36945-	}
36946-	return hints, nil
36947-}
36948-
36949-// References returns references to the object at loc, as returned by
36950-// the connected LSP server. If no server is connected, it returns (nil, nil).
36951-func (e *Editor) References(ctx context.Context, loc protocol.Location) ([]protocol.Location, error) {
36952-	if e.Server == nil {
36953-		return nil, nil
36954-	}
36955-	path := e.sandbox.Workdir.URIToPath(loc.URI)
36956-	e.mu.Lock()
36957-	_, ok := e.buffers[path]
36958-	e.mu.Unlock()
36959-	if !ok {
36960-		return nil, fmt.Errorf("buffer %q is not open", path)
36961-	}
36962-	params := &protocol.ReferenceParams{
36963-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
36964-		Context: protocol.ReferenceContext{
36965-			IncludeDeclaration: true,
36966-		},
36967-	}
36968-	locations, err := e.Server.References(ctx, params)
36969-	if err != nil {
36970-		return nil, err
36971-	}
36972-	return locations, nil
36973-}
36974-
36975-// Rename performs a rename of the object at loc to newName, using the
36976-// connected LSP server. If no server is connected, it returns nil.
36977-func (e *Editor) Rename(ctx context.Context, loc protocol.Location, newName string) error {
36978-	if e.Server == nil {
36979-		return nil
36980-	}
36981-	path := e.sandbox.Workdir.URIToPath(loc.URI)
36982-
36983-	// Verify that PrepareRename succeeds.
36984-	prepareParams := &protocol.PrepareRenameParams{}
36985-	prepareParams.TextDocument = e.TextDocumentIdentifier(path)
36986-	prepareParams.Position = loc.Range.Start
36987-	if _, err := e.Server.PrepareRename(ctx, prepareParams); err != nil {
36988-		return fmt.Errorf("preparing rename: %v", err)
36989-	}
36990-
36991-	params := &protocol.RenameParams{
36992-		TextDocument: e.TextDocumentIdentifier(path),
36993-		Position:     loc.Range.Start,
36994-		NewName:      newName,
36995-	}
36996-	wsEdits, err := e.Server.Rename(ctx, params)
36997-	if err != nil {
36998-		return err
36999-	}
37000-	for _, change := range wsEdits.DocumentChanges {
37001-		if err := e.applyDocumentChange(ctx, change); err != nil {
37002-			return err
37003-		}
37004-	}
37005-	return nil
37006-}
37007-
37008-// Implementations returns implementations for the object at loc, as
37009-// returned by the connected LSP server. If no server is connected, it returns
37010-// (nil, nil).
37011-func (e *Editor) Implementations(ctx context.Context, loc protocol.Location) ([]protocol.Location, error) {
37012-	if e.Server == nil {
37013-		return nil, nil
37014-	}
37015-	path := e.sandbox.Workdir.URIToPath(loc.URI)
37016-	e.mu.Lock()
37017-	_, ok := e.buffers[path]
37018-	e.mu.Unlock()
37019-	if !ok {
37020-		return nil, fmt.Errorf("buffer %q is not open", path)
37021-	}
37022-	params := &protocol.ImplementationParams{
37023-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
37024-	}
37025-	return e.Server.Implementation(ctx, params)
37026-}
37027-
37028-func (e *Editor) SignatureHelp(ctx context.Context, loc protocol.Location) (*protocol.SignatureHelp, error) {
37029-	if e.Server == nil {
37030-		return nil, nil
37031-	}
37032-	path := e.sandbox.Workdir.URIToPath(loc.URI)
37033-	e.mu.Lock()
37034-	_, ok := e.buffers[path]
37035-	e.mu.Unlock()
37036-	if !ok {
37037-		return nil, fmt.Errorf("buffer %q is not open", path)
37038-	}
37039-	params := &protocol.SignatureHelpParams{
37040-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
37041-	}
37042-	return e.Server.SignatureHelp(ctx, params)
37043-}
37044-
37045-func (e *Editor) RenameFile(ctx context.Context, oldPath, newPath string) error {
37046-	closed, opened, err := e.renameBuffers(ctx, oldPath, newPath)
37047-	if err != nil {
37048-		return err
37049-	}
37050-
37051-	for _, c := range closed {
37052-		if err := e.sendDidClose(ctx, c); err != nil {
37053-			return err
37054-		}
37055-	}
37056-	for _, o := range opened {
37057-		if err := e.sendDidOpen(ctx, o); err != nil {
37058-			return err
37059-		}
37060-	}
37061-
37062-	// Finally, perform the renaming on disk.
37063-	if err := e.sandbox.Workdir.RenameFile(ctx, oldPath, newPath); err != nil {
37064-		return fmt.Errorf("renaming sandbox file: %w", err)
37065-	}
37066-	return nil
37067-}
37068-
37069-// renameBuffers renames in-memory buffers affected by the renaming of
37070-// oldPath->newPath, returning the resulting text documents that must be closed
37071-// and opened over the LSP.
37072-func (e *Editor) renameBuffers(ctx context.Context, oldPath, newPath string) (closed []protocol.TextDocumentIdentifier, opened []protocol.TextDocumentItem, _ error) {
37073-	e.mu.Lock()
37074-	defer e.mu.Unlock()
37075-
37076-	// In case either oldPath or newPath is absolute, convert to absolute paths
37077-	// before checking for containment.
37078-	oldAbs := e.sandbox.Workdir.AbsPath(oldPath)
37079-	newAbs := e.sandbox.Workdir.AbsPath(newPath)
37080-
37081-	// Collect buffers that are affected by the given file or directory renaming.
37082-	buffersToRename := make(map[string]string) // old path -> new path
37083-
37084-	for path := range e.buffers {
37085-		abs := e.sandbox.Workdir.AbsPath(path)
37086-		if oldAbs == abs || source.InDir(oldAbs, abs) {
37087-			rel, err := filepath.Rel(oldAbs, abs)
37088-			if err != nil {
37089-				return nil, nil, fmt.Errorf("filepath.Rel(%q, %q): %v", oldAbs, abs, err)
37090-			}
37091-			nabs := filepath.Join(newAbs, rel)
37092-			newPath := e.sandbox.Workdir.RelPath(nabs)
37093-			buffersToRename[path] = newPath
37094-		}
37095-	}
37096-
37097-	// Update buffers, and build protocol changes.
37098-	for old, new := range buffersToRename {
37099-		buf := e.buffers[old]
37100-		delete(e.buffers, old)
37101-		buf.version = 1
37102-		buf.path = new
37103-		e.buffers[new] = buf
37104-
37105-		closed = append(closed, e.TextDocumentIdentifier(old))
37106-		opened = append(opened, e.textDocumentItem(buf))
37107-	}
37108-
37109-	return closed, opened, nil
37110-}
37111-
37112-func (e *Editor) applyDocumentChange(ctx context.Context, change protocol.DocumentChanges) error {
37113-	if change.RenameFile != nil {
37114-		oldPath := e.sandbox.Workdir.URIToPath(change.RenameFile.OldURI)
37115-		newPath := e.sandbox.Workdir.URIToPath(change.RenameFile.NewURI)
37116-
37117-		return e.RenameFile(ctx, oldPath, newPath)
37118-	}
37119-	if change.TextDocumentEdit != nil {
37120-		return e.applyTextDocumentEdit(ctx, *change.TextDocumentEdit)
37121-	}
37122-	panic("Internal error: one of RenameFile or TextDocumentEdit must be set")
37123-}
37124-
37125-func (e *Editor) applyTextDocumentEdit(ctx context.Context, change protocol.TextDocumentEdit) error {
37126-	path := e.sandbox.Workdir.URIToPath(change.TextDocument.URI)
37127-	if ver := int32(e.BufferVersion(path)); ver != change.TextDocument.Version {
37128-		return fmt.Errorf("buffer versions for %q do not match: have %d, editing %d", path, ver, change.TextDocument.Version)
37129-	}
37130-	if !e.HasBuffer(path) {
37131-		err := e.OpenFile(ctx, path)
37132-		if os.IsNotExist(err) {
37133-			// TODO: it's unclear if this is correct. Here we create the buffer (with
37134-			// version 1), then apply edits. Perhaps we should apply the edits before
37135-			// sending the didOpen notification.
37136-			e.CreateBuffer(ctx, path, "")
37137-			err = nil
37138-		}
37139-		if err != nil {
37140-			return err
37141-		}
37142-	}
37143-	return e.EditBuffer(ctx, path, change.Edits)
37144-}
37145-
37146-// Config returns the current editor configuration.
37147-func (e *Editor) Config() EditorConfig {
37148-	e.mu.Lock()
37149-	defer e.mu.Unlock()
37150-	return e.config
37151-}
37152-
37153-// ChangeConfiguration sets the new editor configuration, and if applicable
37154-// sends a didChangeConfiguration notification.
37155-//
37156-// An error is returned if the change notification failed to send.
37157-func (e *Editor) ChangeConfiguration(ctx context.Context, newConfig EditorConfig) error {
37158-	e.mu.Lock()
37159-	e.config = newConfig
37160-	e.mu.Unlock() // don't hold e.mu during server calls
37161-	if e.Server != nil {
37162-		var params protocol.DidChangeConfigurationParams // empty: gopls ignores the Settings field
37163-		if err := e.Server.DidChangeConfiguration(ctx, &params); err != nil {
37164-			return err
37165-		}
37166-	}
37167-	return nil
37168-}
37169-
37170-// ChangeWorkspaceFolders sets the new workspace folders, and sends a
37171-// didChangeWorkspaceFolders notification to the server.
37172-//
37173-// The given folders must all be unique.
37174-func (e *Editor) ChangeWorkspaceFolders(ctx context.Context, folders []string) error {
37175-	// capture existing folders so that we can compute the change.
37176-	e.mu.Lock()
37177-	oldFolders := e.makeWorkspaceFoldersLocked()
37178-	e.config.WorkspaceFolders = folders
37179-	newFolders := e.makeWorkspaceFoldersLocked()
37180-	e.mu.Unlock()
37181-
37182-	if e.Server == nil {
37183-		return nil
37184-	}
37185-
37186-	var params protocol.DidChangeWorkspaceFoldersParams
37187-
37188-	// Keep track of old workspace folders that must be removed.
37189-	toRemove := make(map[protocol.URI]protocol.WorkspaceFolder)
37190-	for _, folder := range oldFolders {
37191-		toRemove[folder.URI] = folder
37192-	}
37193-
37194-	// Sanity check: if we see a folder twice the algorithm below doesn't work,
37195-	// so track seen folders to ensure that we panic in that case.
37196-	seen := make(map[protocol.URI]protocol.WorkspaceFolder)
37197-	for _, folder := range newFolders {
37198-		if _, ok := seen[folder.URI]; ok {
37199-			panic(fmt.Sprintf("folder %s seen twice", folder.URI))
37200-		}
37201-
37202-		// If this folder already exists, we don't want to remove it.
37203-		// Otherwise, we need to add it.
37204-		if _, ok := toRemove[folder.URI]; ok {
37205-			delete(toRemove, folder.URI)
37206-		} else {
37207-			params.Event.Added = append(params.Event.Added, folder)
37208-		}
37209-	}
37210-
37211-	for _, v := range toRemove {
37212-		params.Event.Removed = append(params.Event.Removed, v)
37213-	}
37214-
37215-	return e.Server.DidChangeWorkspaceFolders(ctx, &params)
37216-}
37217-
37218-// CodeAction executes a codeAction request on the server.
37219-// If loc.Range is zero, the whole file is implied.
37220-func (e *Editor) CodeAction(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic) ([]protocol.CodeAction, error) {
37221-	if e.Server == nil {
37222-		return nil, nil
37223-	}
37224-	path := e.sandbox.Workdir.URIToPath(loc.URI)
37225-	e.mu.Lock()
37226-	_, ok := e.buffers[path]
37227-	e.mu.Unlock()
37228-	if !ok {
37229-		return nil, fmt.Errorf("buffer %q is not open", path)
37230-	}
37231-	params := &protocol.CodeActionParams{
37232-		TextDocument: e.TextDocumentIdentifier(path),
37233-		Context: protocol.CodeActionContext{
37234-			Diagnostics: diagnostics,
37235-		},
37236-		Range: loc.Range, // may be zero
37237-	}
37238-	lens, err := e.Server.CodeAction(ctx, params)
37239-	if err != nil {
37240-		return nil, err
37241-	}
37242-	return lens, nil
37243-}
37244-
37245-// Hover triggers a hover at the given position in an open buffer.
37246-func (e *Editor) Hover(ctx context.Context, loc protocol.Location) (*protocol.MarkupContent, protocol.Location, error) {
37247-	if err := e.checkBufferLocation(loc); err != nil {
37248-		return nil, protocol.Location{}, err
37249-	}
37250-	params := &protocol.HoverParams{}
37251-	params.TextDocument.URI = loc.URI
37252-	params.Position = loc.Range.Start
37253-
37254-	resp, err := e.Server.Hover(ctx, params)
37255-	if err != nil {
37256-		return nil, protocol.Location{}, fmt.Errorf("hover: %w", err)
37257-	}
37258-	if resp == nil {
37259-		return nil, protocol.Location{}, nil
37260-	}
37261-	return &resp.Contents, protocol.Location{URI: loc.URI, Range: resp.Range}, nil
37262-}
37263-
37264-func (e *Editor) DocumentLink(ctx context.Context, path string) ([]protocol.DocumentLink, error) {
37265-	if e.Server == nil {
37266-		return nil, nil
37267-	}
37268-	params := &protocol.DocumentLinkParams{}
37269-	params.TextDocument.URI = e.sandbox.Workdir.URI(path)
37270-	return e.Server.DocumentLink(ctx, params)
37271-}
37272-
37273-func (e *Editor) DocumentHighlight(ctx context.Context, loc protocol.Location) ([]protocol.DocumentHighlight, error) {
37274-	if e.Server == nil {
37275-		return nil, nil
37276-	}
37277-	if err := e.checkBufferLocation(loc); err != nil {
37278-		return nil, err
37279-	}
37280-	params := &protocol.DocumentHighlightParams{}
37281-	params.TextDocument.URI = loc.URI
37282-	params.Position = loc.Range.Start
37283-
37284-	return e.Server.DocumentHighlight(ctx, params)
37285-}
37286diff -urN a/gopls/internal/lsp/fake/editor_test.go b/gopls/internal/lsp/fake/editor_test.go
37287--- a/gopls/internal/lsp/fake/editor_test.go	2000-01-01 00:00:00.000000000 -0000
37288+++ b/gopls/internal/lsp/fake/editor_test.go	1970-01-01 00:00:00.000000000 +0000
37289@@ -1,61 +0,0 @@
37290-// Copyright 2020 The Go Authors. All rights reserved.
37291-// Use of this source code is governed by a BSD-style
37292-// license that can be found in the LICENSE file.
37293-
37294-package fake
37295-
37296-import (
37297-	"context"
37298-	"testing"
37299-
37300-	"golang.org/x/tools/gopls/internal/lsp/protocol"
37301-)
37302-
37303-const exampleProgram = `
37304--- go.mod --
37305-go 1.12
37306--- main.go --
37307-package main
37308-
37309-import "fmt"
37310-
37311-func main() {
37312-	fmt.Println("Hello World.")
37313-}
37314-`
37315-
37316-func TestClientEditing(t *testing.T) {
37317-	ws, err := NewSandbox(&SandboxConfig{Files: UnpackTxt(exampleProgram)})
37318-	if err != nil {
37319-		t.Fatal(err)
37320-	}
37321-	defer ws.Close()
37322-	ctx := context.Background()
37323-	editor := NewEditor(ws, EditorConfig{})
37324-	if err := editor.OpenFile(ctx, "main.go"); err != nil {
37325-		t.Fatal(err)
37326-	}
37327-	if err := editor.EditBuffer(ctx, "main.go", []protocol.TextEdit{
37328-		{
37329-			Range: protocol.Range{
37330-				Start: protocol.Position{Line: 5, Character: 14},
37331-				End:   protocol.Position{Line: 5, Character: 26},
37332-			},
37333-			NewText: "Hola, mundo.",
37334-		},
37335-	}); err != nil {
37336-		t.Fatal(err)
37337-	}
37338-	got := editor.buffers["main.go"].text()
37339-	want := `package main
37340-
37341-import "fmt"
37342-
37343-func main() {
37344-	fmt.Println("Hola, mundo.")
37345-}
37346-`
37347-	if got != want {
37348-		t.Errorf("got text %q, want %q", got, want)
37349-	}
37350-}
37351diff -urN a/gopls/internal/lsp/fake/edit_test.go b/gopls/internal/lsp/fake/edit_test.go
37352--- a/gopls/internal/lsp/fake/edit_test.go	2000-01-01 00:00:00.000000000 -0000
37353+++ b/gopls/internal/lsp/fake/edit_test.go	1970-01-01 00:00:00.000000000 +0000
37354@@ -1,96 +0,0 @@
37355-// Copyright 2020 The Go Authors. All rights reserved.
37356-// Use of this source code is governed by a BSD-style
37357-// license that can be found in the LICENSE file.
37358-
37359-package fake
37360-
37361-import (
37362-	"testing"
37363-
37364-	"golang.org/x/tools/gopls/internal/lsp/protocol"
37365-)
37366-
37367-func TestApplyEdits(t *testing.T) {
37368-	tests := []struct {
37369-		label   string
37370-		content string
37371-		edits   []protocol.TextEdit
37372-		want    string
37373-		wantErr bool
37374-	}{
37375-		{
37376-			label: "empty content",
37377-		},
37378-		{
37379-			label:   "empty edit",
37380-			content: "hello",
37381-			edits:   []protocol.TextEdit{},
37382-			want:    "hello",
37383-		},
37384-		{
37385-			label:   "unicode edit",
37386-			content: "hello, 日本語",
37387-			edits: []protocol.TextEdit{
37388-				NewEdit(0, 7, 0, 10, "world"),
37389-			},
37390-			want: "hello, world",
37391-		},
37392-		{
37393-			label:   "range edit",
37394-			content: "ABC\nDEF\nGHI\nJKL",
37395-			edits: []protocol.TextEdit{
37396-				NewEdit(1, 1, 2, 3, "12\n345"),
37397-			},
37398-			want: "ABC\nD12\n345\nJKL",
37399-		},
37400-		{
37401-			label:   "regression test for issue #57627",
37402-			content: "go 1.18\nuse moda/a",
37403-			edits: []protocol.TextEdit{
37404-				NewEdit(1, 0, 1, 0, "\n"),
37405-				NewEdit(2, 0, 2, 0, "\n"),
37406-			},
37407-			want: "go 1.18\n\nuse moda/a\n",
37408-		},
37409-		{
37410-			label:   "end before start",
37411-			content: "ABC\nDEF\nGHI\nJKL",
37412-			edits: []protocol.TextEdit{
37413-				NewEdit(2, 3, 1, 1, "12\n345"),
37414-			},
37415-			wantErr: true,
37416-		},
37417-		{
37418-			label:   "out of bounds line",
37419-			content: "ABC\nDEF\nGHI\nJKL",
37420-			edits: []protocol.TextEdit{
37421-				NewEdit(1, 1, 4, 3, "12\n345"),
37422-			},
37423-			wantErr: true,
37424-		},
37425-		{
37426-			label:   "out of bounds column",
37427-			content: "ABC\nDEF\nGHI\nJKL",
37428-			edits: []protocol.TextEdit{
37429-				NewEdit(1, 4, 2, 3, "12\n345"),
37430-			},
37431-			wantErr: true,
37432-		},
37433-	}
37434-
37435-	for _, test := range tests {
37436-		test := test
37437-		t.Run(test.label, func(t *testing.T) {
37438-			got, err := applyEdits(protocol.NewMapper("", []byte(test.content)), test.edits, false)
37439-			if (err != nil) != test.wantErr {
37440-				t.Errorf("got err %v, want error: %t", err, test.wantErr)
37441-			}
37442-			if err != nil {
37443-				return
37444-			}
37445-			if got := string(got); got != test.want {
37446-				t.Errorf("got %q, want %q", got, test.want)
37447-			}
37448-		})
37449-	}
37450-}
37451diff -urN a/gopls/internal/lsp/fake/proxy.go b/gopls/internal/lsp/fake/proxy.go
37452--- a/gopls/internal/lsp/fake/proxy.go	2000-01-01 00:00:00.000000000 -0000
37453+++ b/gopls/internal/lsp/fake/proxy.go	1970-01-01 00:00:00.000000000 +0000
37454@@ -1,35 +0,0 @@
37455-// Copyright 2020 The Go Authors. All rights reserved.
37456-// Use of this source code is governed by a BSD-style
37457-// license that can be found in the LICENSE file.
37458-
37459-package fake
37460-
37461-import (
37462-	"fmt"
37463-
37464-	"golang.org/x/tools/internal/proxydir"
37465-)
37466-
37467-// WriteProxy creates a new proxy file tree using the txtar-encoded content,
37468-// and returns its URL.
37469-func WriteProxy(tmpdir string, files map[string][]byte) (string, error) {
37470-	type moduleVersion struct {
37471-		modulePath, version string
37472-	}
37473-	// Transform into the format expected by the proxydir package.
37474-	filesByModule := make(map[moduleVersion]map[string][]byte)
37475-	for name, data := range files {
37476-		modulePath, version, suffix := splitModuleVersionPath(name)
37477-		mv := moduleVersion{modulePath, version}
37478-		if _, ok := filesByModule[mv]; !ok {
37479-			filesByModule[mv] = make(map[string][]byte)
37480-		}
37481-		filesByModule[mv][suffix] = data
37482-	}
37483-	for mv, files := range filesByModule {
37484-		if err := proxydir.WriteModuleVersion(tmpdir, mv.modulePath, mv.version, files); err != nil {
37485-			return "", fmt.Errorf("error writing %s@%s: %v", mv.modulePath, mv.version, err)
37486-		}
37487-	}
37488-	return proxydir.ToURL(tmpdir), nil
37489-}
37490diff -urN a/gopls/internal/lsp/fake/sandbox.go b/gopls/internal/lsp/fake/sandbox.go
37491--- a/gopls/internal/lsp/fake/sandbox.go	2000-01-01 00:00:00.000000000 -0000
37492+++ b/gopls/internal/lsp/fake/sandbox.go	1970-01-01 00:00:00.000000000 +0000
37493@@ -1,299 +0,0 @@
37494-// Copyright 2020 The Go Authors. All rights reserved.
37495-// Use of this source code is governed by a BSD-style
37496-// license that can be found in the LICENSE file.
37497-
37498-package fake
37499-
37500-import (
37501-	"context"
37502-	"errors"
37503-	"fmt"
37504-	"io/ioutil"
37505-	"os"
37506-	"path/filepath"
37507-	"strings"
37508-
37509-	"golang.org/x/tools/internal/gocommand"
37510-	"golang.org/x/tools/internal/robustio"
37511-	"golang.org/x/tools/internal/testenv"
37512-	"golang.org/x/tools/txtar"
37513-)
37514-
37515-// Sandbox holds a collection of temporary resources to use for working with Go
37516-// code in tests.
37517-type Sandbox struct {
37518-	gopath          string
37519-	rootdir         string
37520-	goproxy         string
37521-	Workdir         *Workdir
37522-	goCommandRunner gocommand.Runner
37523-}
37524-
37525-// SandboxConfig controls the behavior of a test sandbox. The zero value
37526-// defines a reasonable default.
37527-type SandboxConfig struct {
37528-	// RootDir sets the base directory to use when creating temporary
37529-	// directories. If not specified, defaults to a new temporary directory.
37530-	RootDir string
37531-	// Files holds a txtar-encoded archive of files to populate the initial state
37532-	// of the working directory.
37533-	//
37534-	// For convenience, the special substring "$SANDBOX_WORKDIR" is replaced with
37535-	// the sandbox's resolved working directory before writing files.
37536-	Files map[string][]byte
37537-	// InGoPath specifies that the working directory should be within the
37538-	// temporary GOPATH.
37539-	InGoPath bool
37540-	// Workdir configures the working directory of the Sandbox. It behaves as
37541-	// follows:
37542-	//  - if set to an absolute path, use that path as the working directory.
37543-	//  - if set to a relative path, create and use that path relative to the
37544-	//    sandbox.
37545-	//  - if unset, default to a the 'work' subdirectory of the sandbox.
37546-	//
37547-	// This option is incompatible with InGoPath or Files.
37548-	Workdir string
37549-	// ProxyFiles holds a txtar-encoded archive of files to populate a file-based
37550-	// Go proxy.
37551-	ProxyFiles map[string][]byte
37552-	// GOPROXY is the explicit GOPROXY value that should be used for the sandbox.
37553-	//
37554-	// This option is incompatible with ProxyFiles.
37555-	GOPROXY string
37556-}
37557-
37558-// NewSandbox creates a collection of named temporary resources, with a
37559-// working directory populated by the txtar-encoded content in srctxt, and a
37560-// file-based module proxy populated with the txtar-encoded content in
37561-// proxytxt.
37562-//
37563-// If rootDir is non-empty, it will be used as the root of temporary
37564-// directories created for the sandbox. Otherwise, a new temporary directory
37565-// will be used as root.
37566-//
37567-// TODO(rfindley): the sandbox abstraction doesn't seem to carry its weight.
37568-// Sandboxes should be composed out of their building-blocks, rather than via a
37569-// monolithic configuration.
37570-func NewSandbox(config *SandboxConfig) (_ *Sandbox, err error) {
37571-	if config == nil {
37572-		config = new(SandboxConfig)
37573-	}
37574-	if err := validateConfig(*config); err != nil {
37575-		return nil, fmt.Errorf("invalid SandboxConfig: %v", err)
37576-	}
37577-
37578-	sb := &Sandbox{}
37579-	defer func() {
37580-		// Clean up if we fail at any point in this constructor.
37581-		if err != nil {
37582-			sb.Close()
37583-		}
37584-	}()
37585-
37586-	rootDir := config.RootDir
37587-	if rootDir == "" {
37588-		rootDir, err = ioutil.TempDir(config.RootDir, "gopls-sandbox-")
37589-		if err != nil {
37590-			return nil, fmt.Errorf("creating temporary workdir: %v", err)
37591-		}
37592-	}
37593-	sb.rootdir = rootDir
37594-	sb.gopath = filepath.Join(sb.rootdir, "gopath")
37595-	if err := os.Mkdir(sb.gopath, 0755); err != nil {
37596-		return nil, err
37597-	}
37598-	if config.GOPROXY != "" {
37599-		sb.goproxy = config.GOPROXY
37600-	} else {
37601-		proxydir := filepath.Join(sb.rootdir, "proxy")
37602-		if err := os.Mkdir(proxydir, 0755); err != nil {
37603-			return nil, err
37604-		}
37605-		sb.goproxy, err = WriteProxy(proxydir, config.ProxyFiles)
37606-		if err != nil {
37607-			return nil, err
37608-		}
37609-	}
37610-	// Short-circuit writing the workdir if we're given an absolute path, since
37611-	// this is used for running in an existing directory.
37612-	// TODO(findleyr): refactor this to be less of a workaround.
37613-	if filepath.IsAbs(config.Workdir) {
37614-		sb.Workdir, err = NewWorkdir(config.Workdir, nil)
37615-		if err != nil {
37616-			return nil, err
37617-		}
37618-		return sb, nil
37619-	}
37620-	var workdir string
37621-	if config.Workdir == "" {
37622-		if config.InGoPath {
37623-			// Set the working directory as $GOPATH/src.
37624-			workdir = filepath.Join(sb.gopath, "src")
37625-		} else if workdir == "" {
37626-			workdir = filepath.Join(sb.rootdir, "work")
37627-		}
37628-	} else {
37629-		// relative path
37630-		workdir = filepath.Join(sb.rootdir, config.Workdir)
37631-	}
37632-	if err := os.MkdirAll(workdir, 0755); err != nil {
37633-		return nil, err
37634-	}
37635-	sb.Workdir, err = NewWorkdir(workdir, config.Files)
37636-	if err != nil {
37637-		return nil, err
37638-	}
37639-	return sb, nil
37640-}
37641-
37642-// Tempdir creates a new temp directory with the given txtar-encoded files. It
37643-// is the responsibility of the caller to call os.RemoveAll on the returned
37644-// file path when it is no longer needed.
37645-func Tempdir(files map[string][]byte) (string, error) {
37646-	dir, err := ioutil.TempDir("", "gopls-tempdir-")
37647-	if err != nil {
37648-		return "", err
37649-	}
37650-	for name, data := range files {
37651-		if err := writeFileData(name, data, RelativeTo(dir)); err != nil {
37652-			return "", fmt.Errorf("writing to tempdir: %w", err)
37653-		}
37654-	}
37655-	return dir, nil
37656-}
37657-
37658-func UnpackTxt(txt string) map[string][]byte {
37659-	dataMap := make(map[string][]byte)
37660-	archive := txtar.Parse([]byte(txt))
37661-	for _, f := range archive.Files {
37662-		if _, ok := dataMap[f.Name]; ok {
37663-			panic(fmt.Sprintf("found file %q twice", f.Name))
37664-		}
37665-		dataMap[f.Name] = f.Data
37666-	}
37667-	return dataMap
37668-}
37669-
37670-func validateConfig(config SandboxConfig) error {
37671-	if filepath.IsAbs(config.Workdir) && (len(config.Files) > 0 || config.InGoPath) {
37672-		return errors.New("absolute Workdir cannot be set in conjunction with Files or InGoPath")
37673-	}
37674-	if config.Workdir != "" && config.InGoPath {
37675-		return errors.New("Workdir cannot be set in conjunction with InGoPath")
37676-	}
37677-	if config.GOPROXY != "" && config.ProxyFiles != nil {
37678-		return errors.New("GOPROXY cannot be set in conjunction with ProxyFiles")
37679-	}
37680-	return nil
37681-}
37682-
37683-// splitModuleVersionPath extracts module information from files stored in the
37684-// directory structure modulePath@version/suffix.
37685-// For example:
37686-//
37687-//	splitModuleVersionPath("[email protected]/package") = ("mod.com", "v1.2.3", "package")
37688-func splitModuleVersionPath(path string) (modulePath, version, suffix string) {
37689-	parts := strings.Split(path, "/")
37690-	var modulePathParts []string
37691-	for i, p := range parts {
37692-		if strings.Contains(p, "@") {
37693-			mv := strings.SplitN(p, "@", 2)
37694-			modulePathParts = append(modulePathParts, mv[0])
37695-			return strings.Join(modulePathParts, "/"), mv[1], strings.Join(parts[i+1:], "/")
37696-		}
37697-		modulePathParts = append(modulePathParts, p)
37698-	}
37699-	// Default behavior: this is just a module path.
37700-	return path, "", ""
37701-}
37702-
37703-func (sb *Sandbox) RootDir() string {
37704-	return sb.rootdir
37705-}
37706-
37707-// GOPATH returns the value of the Sandbox GOPATH.
37708-func (sb *Sandbox) GOPATH() string {
37709-	return sb.gopath
37710-}
37711-
37712-// GoEnv returns the default environment variables that can be used for
37713-// invoking Go commands in the sandbox.
37714-func (sb *Sandbox) GoEnv() map[string]string {
37715-	vars := map[string]string{
37716-		"GOPATH":           sb.GOPATH(),
37717-		"GOPROXY":          sb.goproxy,
37718-		"GO111MODULE":      "",
37719-		"GOSUMDB":          "off",
37720-		"GOPACKAGESDRIVER": "off",
37721-	}
37722-	if testenv.Go1Point() >= 5 {
37723-		vars["GOMODCACHE"] = ""
37724-	}
37725-	return vars
37726-}
37727-
37728-// goCommandInvocation returns a new gocommand.Invocation initialized with the
37729-// sandbox environment variables and working directory.
37730-func (sb *Sandbox) goCommandInvocation() gocommand.Invocation {
37731-	var vars []string
37732-	for k, v := range sb.GoEnv() {
37733-		vars = append(vars, fmt.Sprintf("%s=%s", k, v))
37734-	}
37735-	inv := gocommand.Invocation{
37736-		Env: vars,
37737-	}
37738-	// sb.Workdir may be nil if we exited the constructor with errors (we call
37739-	// Close to clean up any partial state from the constructor, which calls
37740-	// RunGoCommand).
37741-	if sb.Workdir != nil {
37742-		inv.WorkingDir = string(sb.Workdir.RelativeTo)
37743-	}
37744-	return inv
37745-}
37746-
37747-// RunGoCommand executes a go command in the sandbox. If checkForFileChanges is
37748-// true, the sandbox scans the working directory and emits file change events
37749-// for any file changes it finds.
37750-func (sb *Sandbox) RunGoCommand(ctx context.Context, dir, verb string, args []string, checkForFileChanges bool) error {
37751-	inv := sb.goCommandInvocation()
37752-	inv.Verb = verb
37753-	inv.Args = args
37754-	if dir != "" {
37755-		inv.WorkingDir = sb.Workdir.AbsPath(dir)
37756-	}
37757-	stdout, stderr, _, err := sb.goCommandRunner.RunRaw(ctx, inv)
37758-	if err != nil {
37759-		return fmt.Errorf("go command failed (stdout: %s) (stderr: %s): %v", stdout.String(), stderr.String(), err)
37760-	}
37761-	// Since running a go command may result in changes to workspace files,
37762-	// check if we need to send any any "watched" file events.
37763-	//
37764-	// TODO(rFindley): this side-effect can impact the usability of the sandbox
37765-	//                 for benchmarks. Consider refactoring.
37766-	if sb.Workdir != nil && checkForFileChanges {
37767-		if err := sb.Workdir.CheckForFileChanges(ctx); err != nil {
37768-			return fmt.Errorf("checking for file changes: %w", err)
37769-		}
37770-	}
37771-	return nil
37772-}
37773-
37774-// GoVersion checks the version of the go command.
37775-// It returns the X in Go 1.X.
37776-func (sb *Sandbox) GoVersion(ctx context.Context) (int, error) {
37777-	inv := sb.goCommandInvocation()
37778-	return gocommand.GoVersion(ctx, inv, &sb.goCommandRunner)
37779-}
37780-
37781-// Close removes all state associated with the sandbox.
37782-func (sb *Sandbox) Close() error {
37783-	var goCleanErr error
37784-	if sb.gopath != "" {
37785-		goCleanErr = sb.RunGoCommand(context.Background(), "", "clean", []string{"-modcache"}, false)
37786-	}
37787-	err := robustio.RemoveAll(sb.rootdir)
37788-	if err != nil || goCleanErr != nil {
37789-		return fmt.Errorf("error(s) cleaning sandbox: cleaning modcache: %v; removing files: %v", goCleanErr, err)
37790-	}
37791-	return nil
37792-}
37793diff -urN a/gopls/internal/lsp/fake/workdir.go b/gopls/internal/lsp/fake/workdir.go
37794--- a/gopls/internal/lsp/fake/workdir.go	2000-01-01 00:00:00.000000000 -0000
37795+++ b/gopls/internal/lsp/fake/workdir.go	1970-01-01 00:00:00.000000000 +0000
37796@@ -1,438 +0,0 @@
37797-// Copyright 2020 The Go Authors. All rights reserved.
37798-// Use of this source code is governed by a BSD-style
37799-// license that can be found in the LICENSE file.
37800-
37801-package fake
37802-
37803-import (
37804-	"bytes"
37805-	"context"
37806-	"crypto/sha256"
37807-	"fmt"
37808-	"io/fs"
37809-	"io/ioutil"
37810-	"os"
37811-	"path/filepath"
37812-	"runtime"
37813-	"sort"
37814-	"strings"
37815-	"sync"
37816-	"time"
37817-
37818-	"golang.org/x/tools/gopls/internal/lsp/protocol"
37819-	"golang.org/x/tools/gopls/internal/span"
37820-	"golang.org/x/tools/internal/robustio"
37821-)
37822-
37823-// RelativeTo is a helper for operations relative to a given directory.
37824-type RelativeTo string
37825-
37826-// AbsPath returns an absolute filesystem path for the workdir-relative path.
37827-func (r RelativeTo) AbsPath(path string) string {
37828-	fp := filepath.FromSlash(path)
37829-	if filepath.IsAbs(fp) {
37830-		return fp
37831-	}
37832-	return filepath.Join(string(r), filepath.FromSlash(path))
37833-}
37834-
37835-// RelPath returns a '/'-encoded path relative to the working directory (or an
37836-// absolute path if the file is outside of workdir)
37837-func (r RelativeTo) RelPath(fp string) string {
37838-	root := string(r)
37839-	if rel, err := filepath.Rel(root, fp); err == nil && !strings.HasPrefix(rel, "..") {
37840-		return filepath.ToSlash(rel)
37841-	}
37842-	return filepath.ToSlash(fp)
37843-}
37844-
37845-// writeFileData writes content to the relative path, replacing the special
37846-// token $SANDBOX_WORKDIR with the relative root given by rel. It does not
37847-// trigger any file events.
37848-func writeFileData(path string, content []byte, rel RelativeTo) error {
37849-	content = bytes.ReplaceAll(content, []byte("$SANDBOX_WORKDIR"), []byte(rel))
37850-	fp := rel.AbsPath(path)
37851-	if err := os.MkdirAll(filepath.Dir(fp), 0755); err != nil {
37852-		return fmt.Errorf("creating nested directory: %w", err)
37853-	}
37854-	backoff := 1 * time.Millisecond
37855-	for {
37856-		err := ioutil.WriteFile(fp, []byte(content), 0644)
37857-		if err != nil {
37858-			// This lock file violation is not handled by the robustio package, as it
37859-			// indicates a real race condition that could be avoided.
37860-			if isWindowsErrLockViolation(err) {
37861-				time.Sleep(backoff)
37862-				backoff *= 2
37863-				continue
37864-			}
37865-			return fmt.Errorf("writing %q: %w", path, err)
37866-		}
37867-		return nil
37868-	}
37869-}
37870-
37871-// isWindowsErrLockViolation reports whether err is ERROR_LOCK_VIOLATION
37872-// on Windows.
37873-var isWindowsErrLockViolation = func(err error) bool { return false }
37874-
37875-// Workdir is a temporary working directory for tests. It exposes file
37876-// operations in terms of relative paths, and fakes file watching by triggering
37877-// events on file operations.
37878-type Workdir struct {
37879-	RelativeTo
37880-
37881-	watcherMu sync.Mutex
37882-	watchers  []func(context.Context, []protocol.FileEvent)
37883-
37884-	fileMu sync.Mutex
37885-	// File identities we know about, for the purpose of detecting changes.
37886-	//
37887-	// Since files is only used for detecting _changes_, we are tolerant of
37888-	// fileIDs that may have hash and mtime coming from different states of the
37889-	// file: if either are out of sync, then the next poll should detect a
37890-	// discrepancy. It is OK if we detect too many changes, but not OK if we miss
37891-	// changes.
37892-	//
37893-	// For that matter, this mechanism for detecting changes can still be flaky
37894-	// on platforms where mtime is very coarse (such as older versions of WSL).
37895-	// It would be much better to use a proper fs event library, but we can't
37896-	// currently import those into x/tools.
37897-	//
37898-	// TODO(golang/go#52284): replace this polling mechanism with a
37899-	// cross-platform library for filesystem notifications.
37900-	files map[string]fileID
37901-}
37902-
37903-// NewWorkdir writes the txtar-encoded file data in txt to dir, and returns a
37904-// Workir for operating on these files using
37905-func NewWorkdir(dir string, files map[string][]byte) (*Workdir, error) {
37906-	w := &Workdir{RelativeTo: RelativeTo(dir)}
37907-	for name, data := range files {
37908-		if err := writeFileData(name, data, w.RelativeTo); err != nil {
37909-			return nil, fmt.Errorf("writing to workdir: %w", err)
37910-		}
37911-	}
37912-	_, err := w.pollFiles() // poll files to populate the files map.
37913-	return w, err
37914-}
37915-
37916-// fileID identifies a file version on disk.
37917-type fileID struct {
37918-	mtime time.Time
37919-	hash  string // empty if mtime is old enough to be reliabe; otherwise a file digest
37920-}
37921-
37922-func hashFile(data []byte) string {
37923-	return fmt.Sprintf("%x", sha256.Sum256(data))
37924-}
37925-
37926-// RootURI returns the root URI for this working directory of this scratch
37927-// environment.
37928-func (w *Workdir) RootURI() protocol.DocumentURI {
37929-	return toURI(string(w.RelativeTo))
37930-}
37931-
37932-// AddWatcher registers the given func to be called on any file change.
37933-func (w *Workdir) AddWatcher(watcher func(context.Context, []protocol.FileEvent)) {
37934-	w.watcherMu.Lock()
37935-	w.watchers = append(w.watchers, watcher)
37936-	w.watcherMu.Unlock()
37937-}
37938-
37939-// URI returns the URI to a the workdir-relative path.
37940-func (w *Workdir) URI(path string) protocol.DocumentURI {
37941-	return toURI(w.AbsPath(path))
37942-}
37943-
37944-// URIToPath converts a uri to a workdir-relative path (or an absolute path,
37945-// if the uri is outside of the workdir).
37946-func (w *Workdir) URIToPath(uri protocol.DocumentURI) string {
37947-	fp := uri.SpanURI().Filename()
37948-	return w.RelPath(fp)
37949-}
37950-
37951-func toURI(fp string) protocol.DocumentURI {
37952-	return protocol.DocumentURI(span.URIFromPath(fp))
37953-}
37954-
37955-// ReadFile reads a text file specified by a workdir-relative path.
37956-func (w *Workdir) ReadFile(path string) ([]byte, error) {
37957-	backoff := 1 * time.Millisecond
37958-	for {
37959-		b, err := ioutil.ReadFile(w.AbsPath(path))
37960-		if err != nil {
37961-			if runtime.GOOS == "plan9" && strings.HasSuffix(err.Error(), " exclusive use file already open") {
37962-				// Plan 9 enforces exclusive access to locked files.
37963-				// Give the owner time to unlock it and retry.
37964-				time.Sleep(backoff)
37965-				backoff *= 2
37966-				continue
37967-			}
37968-			return nil, err
37969-		}
37970-		return b, nil
37971-	}
37972-}
37973-
37974-// RegexpSearch searches the file corresponding to path for the first position
37975-// matching re.
37976-func (w *Workdir) RegexpSearch(path string, re string) (protocol.Location, error) {
37977-	content, err := w.ReadFile(path)
37978-	if err != nil {
37979-		return protocol.Location{}, err
37980-	}
37981-	mapper := protocol.NewMapper(w.URI(path).SpanURI(), content)
37982-	return regexpLocation(mapper, re)
37983-}
37984-
37985-// RemoveFile removes a workdir-relative file path and notifies watchers of the
37986-// change.
37987-func (w *Workdir) RemoveFile(ctx context.Context, path string) error {
37988-	fp := w.AbsPath(path)
37989-	if err := robustio.RemoveAll(fp); err != nil {
37990-		return fmt.Errorf("removing %q: %w", path, err)
37991-	}
37992-
37993-	return w.CheckForFileChanges(ctx)
37994-}
37995-
37996-// WriteFiles writes the text file content to workdir-relative paths and
37997-// notifies watchers of the changes.
37998-func (w *Workdir) WriteFiles(ctx context.Context, files map[string]string) error {
37999-	for path, content := range files {
38000-		fp := w.AbsPath(path)
38001-		_, err := os.Stat(fp)
38002-		if err != nil && !os.IsNotExist(err) {
38003-			return fmt.Errorf("checking if %q exists: %w", path, err)
38004-		}
38005-		if err := writeFileData(path, []byte(content), w.RelativeTo); err != nil {
38006-			return err
38007-		}
38008-	}
38009-	return w.CheckForFileChanges(ctx)
38010-}
38011-
38012-// WriteFile writes text file content to a workdir-relative path and notifies
38013-// watchers of the change.
38014-func (w *Workdir) WriteFile(ctx context.Context, path, content string) error {
38015-	return w.WriteFiles(ctx, map[string]string{path: content})
38016-}
38017-
38018-func (w *Workdir) fileEvent(path string, changeType protocol.FileChangeType) protocol.FileEvent {
38019-	return protocol.FileEvent{
38020-		URI:  w.URI(path),
38021-		Type: changeType,
38022-	}
38023-}
38024-
38025-// RenameFile performs an on disk-renaming of the workdir-relative oldPath to
38026-// workdir-relative newPath, and notifies watchers of the changes.
38027-//
38028-// oldPath must either be a regular file or in the same directory as newPath.
38029-func (w *Workdir) RenameFile(ctx context.Context, oldPath, newPath string) error {
38030-	oldAbs := w.AbsPath(oldPath)
38031-	newAbs := w.AbsPath(newPath)
38032-
38033-	// For os.Rename, “OS-specific restrictions may apply when oldpath and newpath
38034-	// are in different directories.” If that applies here, we may fall back to
38035-	// ReadFile, WriteFile, and RemoveFile to perform the rename non-atomically.
38036-	//
38037-	// However, the fallback path only works for regular files: renaming a
38038-	// directory would be much more complex and isn't needed for our tests.
38039-	fallbackOk := false
38040-	if filepath.Dir(oldAbs) != filepath.Dir(newAbs) {
38041-		fi, err := os.Stat(oldAbs)
38042-		if err == nil && !fi.Mode().IsRegular() {
38043-			return &os.PathError{
38044-				Op:   "RenameFile",
38045-				Path: oldPath,
38046-				Err:  fmt.Errorf("%w: file is not regular and not in the same directory as %s", os.ErrInvalid, newPath),
38047-			}
38048-		}
38049-		fallbackOk = true
38050-	}
38051-
38052-	var renameErr error
38053-	const debugFallback = false
38054-	if fallbackOk && debugFallback {
38055-		renameErr = fmt.Errorf("%w: debugging fallback path", os.ErrInvalid)
38056-	} else {
38057-		renameErr = robustio.Rename(oldAbs, newAbs)
38058-	}
38059-	if renameErr != nil {
38060-		if !fallbackOk {
38061-			return renameErr // The OS-specific Rename restrictions do not apply.
38062-		}
38063-
38064-		content, err := w.ReadFile(oldPath)
38065-		if err != nil {
38066-			// If we can't even read the file, the error from Rename may be accurate.
38067-			return renameErr
38068-		}
38069-		fi, err := os.Stat(newAbs)
38070-		if err == nil {
38071-			if fi.IsDir() {
38072-				// “If newpath already exists and is not a directory, Rename replaces it.”
38073-				// But if it is a directory, maybe not?
38074-				return renameErr
38075-			}
38076-			// On most platforms, Rename replaces the named file with a new file,
38077-			// rather than overwriting the existing file it in place. Mimic that
38078-			// behavior here.
38079-			if err := robustio.RemoveAll(newAbs); err != nil {
38080-				// Maybe we don't have permission to replace newPath?
38081-				return renameErr
38082-			}
38083-		} else if !os.IsNotExist(err) {
38084-			// If the destination path already exists or there is some problem with it,
38085-			// the error from Rename may be accurate.
38086-			return renameErr
38087-		}
38088-		if writeErr := writeFileData(newPath, []byte(content), w.RelativeTo); writeErr != nil {
38089-			// At this point we have tried to actually write the file.
38090-			// If it still doesn't exist, assume that the error from Rename was accurate:
38091-			// for example, maybe we don't have permission to create the new path.
38092-			// Otherwise, return the error from the write, which may indicate some
38093-			// other problem (such as a full disk).
38094-			if _, statErr := os.Stat(newAbs); !os.IsNotExist(statErr) {
38095-				return writeErr
38096-			}
38097-			return renameErr
38098-		}
38099-		if err := robustio.RemoveAll(oldAbs); err != nil {
38100-			// If we failed to remove the old file, that may explain the Rename error too.
38101-			// Make a best effort to back out the write to the new path.
38102-			robustio.RemoveAll(newAbs)
38103-			return renameErr
38104-		}
38105-	}
38106-
38107-	return w.CheckForFileChanges(ctx)
38108-}
38109-
38110-// ListFiles returns a new sorted list of the relative paths of files in dir,
38111-// recursively.
38112-func (w *Workdir) ListFiles(dir string) ([]string, error) {
38113-	absDir := w.AbsPath(dir)
38114-	var paths []string
38115-	if err := filepath.Walk(absDir, func(fp string, info os.FileInfo, err error) error {
38116-		if err != nil {
38117-			return err
38118-		}
38119-		if info.Mode()&(fs.ModeDir|fs.ModeSymlink) == 0 {
38120-			paths = append(paths, w.RelPath(fp))
38121-		}
38122-		return nil
38123-	}); err != nil {
38124-		return nil, err
38125-	}
38126-	sort.Strings(paths)
38127-	return paths, nil
38128-}
38129-
38130-// CheckForFileChanges walks the working directory and checks for any files
38131-// that have changed since the last poll.
38132-func (w *Workdir) CheckForFileChanges(ctx context.Context) error {
38133-	evts, err := w.pollFiles()
38134-	if err != nil {
38135-		return err
38136-	}
38137-	if len(evts) == 0 {
38138-		return nil
38139-	}
38140-	w.watcherMu.Lock()
38141-	watchers := make([]func(context.Context, []protocol.FileEvent), len(w.watchers))
38142-	copy(watchers, w.watchers)
38143-	w.watcherMu.Unlock()
38144-	for _, w := range watchers {
38145-		w(ctx, evts)
38146-	}
38147-	return nil
38148-}
38149-
38150-// pollFiles updates w.files and calculates FileEvents corresponding to file
38151-// state changes since the last poll. It does not call sendEvents.
38152-func (w *Workdir) pollFiles() ([]protocol.FileEvent, error) {
38153-	w.fileMu.Lock()
38154-	defer w.fileMu.Unlock()
38155-
38156-	newFiles := make(map[string]fileID)
38157-	var evts []protocol.FileEvent
38158-	if err := filepath.Walk(string(w.RelativeTo), func(fp string, info os.FileInfo, err error) error {
38159-		if err != nil {
38160-			return err
38161-		}
38162-		// Skip directories and symbolic links (which may be links to directories).
38163-		//
38164-		// The latter matters for repos like Kubernetes, which use symlinks.
38165-		if info.Mode()&(fs.ModeDir|fs.ModeSymlink) != 0 {
38166-			return nil
38167-		}
38168-
38169-		// Opt: avoid reading the file if mtime is sufficently old to be reliable.
38170-		//
38171-		// If mtime is recent, it may not sufficiently identify the file contents:
38172-		// a subsequent write could result in the same mtime. For these cases, we
38173-		// must read the file contents.
38174-		id := fileID{mtime: info.ModTime()}
38175-		if time.Since(info.ModTime()) < 2*time.Second {
38176-			data, err := ioutil.ReadFile(fp)
38177-			if err != nil {
38178-				return err
38179-			}
38180-			id.hash = hashFile(data)
38181-		}
38182-		path := w.RelPath(fp)
38183-		newFiles[path] = id
38184-
38185-		if w.files != nil {
38186-			oldID, ok := w.files[path]
38187-			delete(w.files, path)
38188-			switch {
38189-			case !ok:
38190-				evts = append(evts, protocol.FileEvent{
38191-					URI:  w.URI(path),
38192-					Type: protocol.Created,
38193-				})
38194-			case oldID != id:
38195-				changed := true
38196-
38197-				// Check whether oldID and id do not match because oldID was polled at
38198-				// a recent enough to time such as to require hashing.
38199-				//
38200-				// In this case, read the content to check whether the file actually
38201-				// changed.
38202-				if oldID.mtime.Equal(id.mtime) && oldID.hash != "" && id.hash == "" {
38203-					data, err := ioutil.ReadFile(fp)
38204-					if err != nil {
38205-						return err
38206-					}
38207-					if hashFile(data) == oldID.hash {
38208-						changed = false
38209-					}
38210-				}
38211-				if changed {
38212-					evts = append(evts, protocol.FileEvent{
38213-						URI:  w.URI(path),
38214-						Type: protocol.Changed,
38215-					})
38216-				}
38217-			}
38218-		}
38219-
38220-		return nil
38221-	}); err != nil {
38222-		return nil, err
38223-	}
38224-
38225-	// Any remaining files must have been deleted.
38226-	for path := range w.files {
38227-		evts = append(evts, protocol.FileEvent{
38228-			URI:  w.URI(path),
38229-			Type: protocol.Deleted,
38230-		})
38231-	}
38232-	w.files = newFiles
38233-	return evts, nil
38234-}
38235diff -urN a/gopls/internal/lsp/fake/workdir_test.go b/gopls/internal/lsp/fake/workdir_test.go
38236--- a/gopls/internal/lsp/fake/workdir_test.go	2000-01-01 00:00:00.000000000 -0000
38237+++ b/gopls/internal/lsp/fake/workdir_test.go	1970-01-01 00:00:00.000000000 +0000
38238@@ -1,220 +0,0 @@
38239-// Copyright 2020 The Go Authors. All rights reserved.
38240-// Use of this source code is governed by a BSD-style
38241-// license that can be found in the LICENSE file.
38242-
38243-package fake
38244-
38245-import (
38246-	"context"
38247-	"io/ioutil"
38248-	"os"
38249-	"sync"
38250-	"testing"
38251-
38252-	"github.com/google/go-cmp/cmp"
38253-	"golang.org/x/tools/gopls/internal/lsp/protocol"
38254-)
38255-
38256-const sharedData = `
38257--- go.mod --
38258-go 1.12
38259--- nested/README.md --
38260-Hello World!
38261-`
38262-
38263-// newWorkdir sets up a temporary Workdir with the given txtar-encoded content.
38264-// It also configures an eventBuffer to receive file event notifications. These
38265-// notifications are sent synchronously for each operation, such that once a
38266-// workdir file operation has returned the caller can expect that any relevant
38267-// file notifications are present in the buffer.
38268-//
38269-// It is the caller's responsibility to call the returned cleanup function.
38270-func newWorkdir(t *testing.T, txt string) (*Workdir, *eventBuffer, func()) {
38271-	t.Helper()
38272-
38273-	tmpdir, err := ioutil.TempDir("", "goplstest-workdir-")
38274-	if err != nil {
38275-		t.Fatal(err)
38276-	}
38277-	wd, err := NewWorkdir(tmpdir, UnpackTxt(txt))
38278-	if err != nil {
38279-		t.Fatal(err)
38280-	}
38281-	cleanup := func() {
38282-		if err := os.RemoveAll(tmpdir); err != nil {
38283-			t.Error(err)
38284-		}
38285-	}
38286-
38287-	buf := new(eventBuffer)
38288-	wd.AddWatcher(buf.onEvents)
38289-	return wd, buf, cleanup
38290-}
38291-
38292-// eventBuffer collects events from a file watcher.
38293-type eventBuffer struct {
38294-	mu     sync.Mutex
38295-	events []protocol.FileEvent
38296-}
38297-
38298-// onEvents collects adds events to the buffer; to be used with Workdir.AddWatcher.
38299-func (c *eventBuffer) onEvents(_ context.Context, events []protocol.FileEvent) {
38300-	c.mu.Lock()
38301-	defer c.mu.Unlock()
38302-
38303-	c.events = append(c.events, events...)
38304-}
38305-
38306-// take empties the buffer, returning its previous contents.
38307-func (c *eventBuffer) take() []protocol.FileEvent {
38308-	c.mu.Lock()
38309-	defer c.mu.Unlock()
38310-
38311-	evts := c.events
38312-	c.events = nil
38313-	return evts
38314-}
38315-
38316-func TestWorkdir_ReadFile(t *testing.T) {
38317-	wd, _, cleanup := newWorkdir(t, sharedData)
38318-	defer cleanup()
38319-
38320-	got, err := wd.ReadFile("nested/README.md")
38321-	if err != nil {
38322-		t.Fatal(err)
38323-	}
38324-	want := "Hello World!\n"
38325-	if got := string(got); got != want {
38326-		t.Errorf("reading workdir file, got %q, want %q", got, want)
38327-	}
38328-}
38329-
38330-func TestWorkdir_WriteFile(t *testing.T) {
38331-	wd, events, cleanup := newWorkdir(t, sharedData)
38332-	defer cleanup()
38333-	ctx := context.Background()
38334-
38335-	tests := []struct {
38336-		path     string
38337-		wantType protocol.FileChangeType
38338-	}{
38339-		{"data.txt", protocol.Created},
38340-		{"nested/README.md", protocol.Changed},
38341-	}
38342-
38343-	for _, test := range tests {
38344-		if err := wd.WriteFile(ctx, test.path, "42"); err != nil {
38345-			t.Fatal(err)
38346-		}
38347-		es := events.take()
38348-		if got := len(es); got != 1 {
38349-			t.Fatalf("len(events) = %d, want 1", got)
38350-		}
38351-		path := wd.URIToPath(es[0].URI)
38352-		if path != test.path {
38353-			t.Errorf("event path = %q, want %q", path, test.path)
38354-		}
38355-		if es[0].Type != test.wantType {
38356-			t.Errorf("event type = %v, want %v", es[0].Type, test.wantType)
38357-		}
38358-		got, err := wd.ReadFile(test.path)
38359-		if err != nil {
38360-			t.Fatal(err)
38361-		}
38362-		want := "42"
38363-		if got := string(got); got != want {
38364-			t.Errorf("ws.ReadFile(%q) = %q, want %q", test.path, got, want)
38365-		}
38366-	}
38367-}
38368-
38369-// Test for file notifications following file operations.
38370-func TestWorkdir_FileWatching(t *testing.T) {
38371-	wd, events, cleanup := newWorkdir(t, "")
38372-	defer cleanup()
38373-	ctx := context.Background()
38374-
38375-	must := func(err error) {
38376-		if err != nil {
38377-			t.Fatal(err)
38378-		}
38379-	}
38380-
38381-	type changeMap map[string]protocol.FileChangeType
38382-	checkEvent := func(wantChanges changeMap) {
38383-		gotChanges := make(changeMap)
38384-		for _, e := range events.take() {
38385-			gotChanges[wd.URIToPath(e.URI)] = e.Type
38386-		}
38387-		if diff := cmp.Diff(wantChanges, gotChanges); diff != "" {
38388-			t.Errorf("mismatching file events (-want +got):\n%s", diff)
38389-		}
38390-	}
38391-
38392-	must(wd.WriteFile(ctx, "foo.go", "package foo"))
38393-	checkEvent(changeMap{"foo.go": protocol.Created})
38394-
38395-	must(wd.RenameFile(ctx, "foo.go", "bar.go"))
38396-	checkEvent(changeMap{"foo.go": protocol.Deleted, "bar.go": protocol.Created})
38397-
38398-	must(wd.RemoveFile(ctx, "bar.go"))
38399-	checkEvent(changeMap{"bar.go": protocol.Deleted})
38400-}
38401-
38402-func TestWorkdir_CheckForFileChanges(t *testing.T) {
38403-	t.Skip("broken on darwin-amd64-10_12")
38404-	wd, events, cleanup := newWorkdir(t, sharedData)
38405-	defer cleanup()
38406-	ctx := context.Background()
38407-
38408-	checkChange := func(wantPath string, wantType protocol.FileChangeType) {
38409-		if err := wd.CheckForFileChanges(ctx); err != nil {
38410-			t.Fatal(err)
38411-		}
38412-		ev := events.take()
38413-		if len(ev) == 0 {
38414-			t.Fatal("no file events received")
38415-		}
38416-		gotEvt := ev[0]
38417-		gotPath := wd.URIToPath(gotEvt.URI)
38418-		// Only check relative path and Type
38419-		if gotPath != wantPath || gotEvt.Type != wantType {
38420-			t.Errorf("file events: got %v, want {Path: %s, Type: %v}", gotEvt, wantPath, wantType)
38421-		}
38422-	}
38423-	// Sleep some positive amount of time to ensure a distinct mtime.
38424-	if err := writeFileData("go.mod", []byte("module foo.test\n"), wd.RelativeTo); err != nil {
38425-		t.Fatal(err)
38426-	}
38427-	checkChange("go.mod", protocol.Changed)
38428-	if err := writeFileData("newFile", []byte("something"), wd.RelativeTo); err != nil {
38429-		t.Fatal(err)
38430-	}
38431-	checkChange("newFile", protocol.Created)
38432-	fp := wd.AbsPath("newFile")
38433-	if err := os.Remove(fp); err != nil {
38434-		t.Fatal(err)
38435-	}
38436-	checkChange("newFile", protocol.Deleted)
38437-}
38438-
38439-func TestSplitModuleVersionPath(t *testing.T) {
38440-	tests := []struct {
38441-		path                                string
38442-		wantModule, wantVersion, wantSuffix string
38443-	}{
38444-		{"[email protected]/bar", "foo.com", "v1.2.3", "bar"},
38445-		{"foo.com/module@v1.2.3/bar", "foo.com/module", "v1.2.3", "bar"},
38446-		{"[email protected]", "foo.com", "v1.2.3", ""},
38447-		{"[email protected]", "std", "v1.14.0", ""},
38448-		{"another/module/path", "another/module/path", "", ""},
38449-	}
38450-
38451-	for _, test := range tests {
38452-		module, version, suffix := splitModuleVersionPath(test.path)
38453-		if module != test.wantModule || version != test.wantVersion || suffix != test.wantSuffix {
38454-			t.Errorf("splitModuleVersionPath(%q) =\n\t(%q, %q, %q)\nwant\n\t(%q, %q, %q)",
38455-				test.path, module, version, suffix, test.wantModule, test.wantVersion, test.wantSuffix)
38456-		}
38457-	}
38458-}
38459diff -urN a/gopls/internal/lsp/fake/workdir_windows.go b/gopls/internal/lsp/fake/workdir_windows.go
38460--- a/gopls/internal/lsp/fake/workdir_windows.go	2000-01-01 00:00:00.000000000 -0000
38461+++ b/gopls/internal/lsp/fake/workdir_windows.go	1970-01-01 00:00:00.000000000 +0000
38462@@ -1,21 +0,0 @@
38463-// Copyright 2021 The Go Authors. All rights reserved.
38464-// Use of this source code is governed by a BSD-style
38465-// license that can be found in the LICENSE file.
38466-
38467-package fake
38468-
38469-import (
38470-	"errors"
38471-	"syscall"
38472-)
38473-
38474-func init() {
38475-	// constants copied from GOROOT/src/internal/syscall/windows/syscall_windows.go
38476-	const (
38477-		ERROR_LOCK_VIOLATION syscall.Errno = 33
38478-	)
38479-
38480-	isWindowsErrLockViolation = func(err error) bool {
38481-		return errors.Is(err, ERROR_LOCK_VIOLATION)
38482-	}
38483-}
38484diff -urN a/gopls/internal/lsp/filecache/filecache.go b/gopls/internal/lsp/filecache/filecache.go
38485--- a/gopls/internal/lsp/filecache/filecache.go	2000-01-01 00:00:00.000000000 -0000
38486+++ b/gopls/internal/lsp/filecache/filecache.go	1970-01-01 00:00:00.000000000 +0000
38487@@ -1,369 +0,0 @@
38488-// Copyright 2022 The Go Authors. All rights reserved.
38489-// Use of this source code is governed by a BSD-style
38490-// license that can be found in the LICENSE file.
38491-
38492-// The filecache package provides a file-based shared durable blob cache.
38493-//
38494-// The cache is a machine-global mapping from (kind string, key
38495-// [32]byte) to []byte, where kind is an identifier describing the
38496-// namespace or purpose (e.g. "analysis"), and key is a SHA-256 digest
38497-// of the recipe of the value. (It need not be the digest of the value
38498-// itself, so you can query the cache without knowing what value the
38499-// recipe would produce.)
38500-//
38501-// The space budget of the cache can be controlled by [SetBudget].
38502-// Cache entries may be evicted at any time or in any order.
38503-// Note that "du -sh $GOPLSCACHE" may report a disk usage
38504-// figure that is rather larger (e.g. 50%) than the budget because
38505-// it rounds up partial disk blocks.
38506-//
38507-// The Get and Set operations are concurrency-safe.
38508-package filecache
38509-
38510-import (
38511-	"bytes"
38512-	"crypto/sha256"
38513-	"encoding/binary"
38514-	"errors"
38515-	"fmt"
38516-	"io"
38517-	"log"
38518-	"os"
38519-	"path/filepath"
38520-	"sort"
38521-	"sync"
38522-	"sync/atomic"
38523-	"time"
38524-
38525-	"golang.org/x/tools/internal/lockedfile"
38526-)
38527-
38528-// Get retrieves from the cache and returns a newly allocated
38529-// copy of the value most recently supplied to Set(kind, key),
38530-// possibly by another process.
38531-// Get returns ErrNotFound if the value was not found.
38532-func Get(kind string, key [32]byte) ([]byte, error) {
38533-	name := filename(kind, key)
38534-	data, err := lockedfile.Read(name)
38535-	if err != nil {
38536-		if errors.Is(err, os.ErrNotExist) {
38537-			return nil, ErrNotFound
38538-		}
38539-		return nil, err
38540-	}
38541-
38542-	// Verify that the Write was complete
38543-	// by checking the recorded length.
38544-	if len(data) < 8 {
38545-		return nil, ErrNotFound // cache entry is incomplete
38546-	}
38547-	if length := binary.LittleEndian.Uint64(data); int(length) != len(data)-8 {
38548-		return nil, ErrNotFound // cache entry is incomplete (or too long!)
38549-	}
38550-	data = data[8:]
38551-
38552-	// Update file time for use by LRU eviction.
38553-	// (This turns every read into a write operation.
38554-	// If this is a performance problem, we should
38555-	// touch the files aynchronously.)
38556-	//
38557-	// (Traditionally the access time would be updated
38558-	// automatically, but for efficiency most POSIX systems have
38559-	// for many years set the noatime mount option to avoid every
38560-	// open or read operation entailing a metadata write.)
38561-	now := time.Now()
38562-	if err := os.Chtimes(name, now, now); err != nil {
38563-		return nil, fmt.Errorf("failed to update access time: %w", err)
38564-	}
38565-
38566-	return data, nil
38567-}
38568-
38569-// ErrNotFound is the distinguished error
38570-// returned by Get when the key is not found.
38571-var ErrNotFound = fmt.Errorf("not found")
38572-
38573-// Set updates the value in the cache.
38574-func Set(kind string, key [32]byte, value []byte) error {
38575-	name := filename(kind, key)
38576-	if err := os.MkdirAll(filepath.Dir(name), 0700); err != nil {
38577-		return err
38578-	}
38579-
38580-	// In the unlikely event of a short write (e.g. ENOSPC)
38581-	// followed by process termination (e.g. a power cut), we
38582-	// don't want a reader to see a short file, so we record
38583-	// the expected length first and verify it in Get.
38584-	var length [8]byte
38585-	binary.LittleEndian.PutUint64(length[:], uint64(len(value)))
38586-	header := bytes.NewReader(length[:])
38587-	payload := bytes.NewReader(value)
38588-
38589-	// Windows doesn't support atomic rename--we tried MoveFile,
38590-	// MoveFileEx, ReplaceFileEx, and SetFileInformationByHandle
38591-	// of RenameFileInfo, all to no avail--so instead we use
38592-	// advisory file locking, which is only about 2x slower even
38593-	// on POSIX platforms with atomic rename.
38594-	return lockedfile.Write(name, io.MultiReader(header, payload), 0600)
38595-}
38596-
38597-var budget int64 = 1e9 // 1GB
38598-
38599-// SetBudget sets a soft limit on disk usage of the cache (in bytes)
38600-// and returns the previous value. Supplying a negative value queries
38601-// the current value without changing it.
38602-//
38603-// If two gopls processes have different budgets, the one with the
38604-// lower budget will collect garbage more actively, but both will
38605-// observe the effect.
38606-func SetBudget(new int64) (old int64) {
38607-	if new < 0 {
38608-		return atomic.LoadInt64(&budget)
38609-	}
38610-	return atomic.SwapInt64(&budget, new)
38611-}
38612-
38613-// --- implementation ----
38614-
38615-// filename returns the cache entry of the specified kind and key.
38616-//
38617-// A typical cache entry is a file name such as:
38618-//
38619-//	$HOME/Library/Caches / gopls / VVVVVVVV / kind / KK / KKKK...KKKK
38620-//
38621-// The portions separated by spaces are as follows:
38622-// - The user's preferred cache directory; the default value varies by OS.
38623-// - The constant "gopls".
38624-// - The "version", 32 bits of the digest of the gopls executable.
38625-// - The kind or purpose of this cache subtree (e.g. "analysis").
38626-// - The first 8 bits of the key, to avoid huge directories.
38627-// - The full 256 bits of the key.
38628-//
38629-// Once a file is written its contents are never modified, though it
38630-// may be atomically replaced or removed.
38631-//
38632-// New versions of gopls are free to reorganize the contents of the
38633-// version directory as needs evolve.  But all versions of gopls must
38634-// in perpetuity treat the "gopls" directory in a common fashion.
38635-//
38636-// In particular, each gopls process attempts to garbage collect
38637-// the entire gopls directory so that newer binaries can clean up
38638-// after older ones: in the development cycle especially, new
38639-// new versions may be created frequently.
38640-func filename(kind string, key [32]byte) string {
38641-	hex := fmt.Sprintf("%x", key)
38642-	return filepath.Join(getCacheDir(), kind, hex[:2], hex)
38643-}
38644-
38645-// getCacheDir returns the persistent cache directory of all processes
38646-// running this version of the gopls executable.
38647-//
38648-// It must incorporate the hash of the executable so that we needn't
38649-// worry about incompatible changes to the file format or changes to
38650-// the algorithm that produced the index.
38651-func getCacheDir() string {
38652-	cacheDirOnce.Do(func() {
38653-		// Use user's preferred cache directory.
38654-		userDir := os.Getenv("GOPLSCACHE")
38655-		if userDir == "" {
38656-			var err error
38657-			userDir, err = os.UserCacheDir()
38658-			if err != nil {
38659-				userDir = os.TempDir()
38660-			}
38661-		}
38662-		goplsDir := filepath.Join(userDir, "gopls")
38663-
38664-		// UserCacheDir may return a nonexistent directory
38665-		// (in which case we must create it, which may fail),
38666-		// or it may return a non-writable directory, in
38667-		// which case we should ideally respect the user's express
38668-		// wishes (e.g. XDG_CACHE_HOME) and not write somewhere else.
38669-		// Sadly UserCacheDir doesn't currently let us distinguish
38670-		// such intent from accidental misconfiguraton such as HOME=/
38671-		// in a CI builder. So, we check whether the gopls subdirectory
38672-		// can be created (or already exists) and not fall back to /tmp.
38673-		// See also https://github.com/golang/go/issues/57638.
38674-		if os.MkdirAll(goplsDir, 0700) != nil {
38675-			goplsDir = filepath.Join(os.TempDir(), "gopls")
38676-		}
38677-
38678-		// Start the garbage collector.
38679-		go gc(goplsDir)
38680-
38681-		// Compute the hash of this executable (~20ms) and create a subdirectory.
38682-		hash, err := hashExecutable()
38683-		if err != nil {
38684-			log.Fatalf("can't hash gopls executable: %v", err)
38685-		}
38686-		// Use only 32 bits of the digest to avoid unwieldy filenames.
38687-		// It's not an adversarial situation.
38688-		cacheDir = filepath.Join(goplsDir, fmt.Sprintf("%x", hash[:4]))
38689-		if err := os.MkdirAll(cacheDir, 0700); err != nil {
38690-			log.Fatalf("can't create cache: %v", err)
38691-		}
38692-	})
38693-	return cacheDir
38694-}
38695-
38696-var (
38697-	cacheDirOnce sync.Once
38698-	cacheDir     string // only accessed by getCacheDir
38699-)
38700-
38701-func hashExecutable() (hash [32]byte, err error) {
38702-	exe, err := os.Executable()
38703-	if err != nil {
38704-		return hash, err
38705-	}
38706-	f, err := os.Open(exe)
38707-	if err != nil {
38708-		return hash, err
38709-	}
38710-	defer f.Close()
38711-	h := sha256.New()
38712-	if _, err := io.Copy(h, f); err != nil {
38713-		return hash, fmt.Errorf("can't read executable: %w", err)
38714-	}
38715-	h.Sum(hash[:0])
38716-	return hash, nil
38717-}
38718-
38719-// gc runs forever, periodically deleting files from the gopls
38720-// directory until the space budget is no longer exceeded, and also
38721-// deleting files older than the maximum age, regardless of budget.
38722-//
38723-// One gopls process may delete garbage created by a different gopls
38724-// process, possibly running a different version of gopls, possibly
38725-// running concurrently.
38726-func gc(goplsDir string) {
38727-	const period = 1 * time.Minute // period between collections
38728-	// Sleep statDelay*batchSize between stats to smooth out I/O.
38729-	//
38730-	// The constants below were chosen using the following heuristics:
38731-	//  - 1GB of filecache is on the order of ~100-200k files, in which case
38732-	//    100μs delay per file introduces 10-20s of additional walk time, less
38733-	//    than the 1m gc period.
38734-	//  - Processing batches of stats at once is much more efficient than
38735-	//    sleeping after every stat (due to OS optimizations).
38736-	const statDelay = 100 * time.Microsecond // average delay between stats, to smooth out I/O
38737-	const batchSize = 1000                   // # of stats to process before sleeping
38738-	const maxAge = 5 * 24 * time.Hour        // max time since last access before file is deleted
38739-
38740-	// The macOS filesystem is strikingly slow, at least on some machines.
38741-	// /usr/bin/find achieves only about 25,000 stats per second
38742-	// at full speed (no pause between items), meaning a large
38743-	// cache may take several minutes to scan.
38744-	// We must ensure that short-lived processes (crucially,
38745-	// tests) are able to make progress sweeping garbage.
38746-	//
38747-	// (gopls' caches should never actually get this big in
38748-	// practice: the example mentioned above resulted from a bug
38749-	// that caused filecache to fail to delete any files.)
38750-
38751-	const debug = false
38752-
38753-	// Names of all directories found in first pass; nil thereafter.
38754-	dirs := make(map[string]bool)
38755-
38756-	for {
38757-		// Enumerate all files in the cache.
38758-		type item struct {
38759-			path string
38760-			stat os.FileInfo
38761-		}
38762-		var files []item
38763-		start := time.Now()
38764-		var total int64 // bytes
38765-		_ = filepath.Walk(goplsDir, func(path string, stat os.FileInfo, err error) error {
38766-			if err != nil {
38767-				return nil // ignore errors
38768-			}
38769-			if stat.IsDir() {
38770-				// Collect (potentially empty) directories.
38771-				if dirs != nil {
38772-					dirs[path] = true
38773-				}
38774-			} else {
38775-				// Unconditionally delete files we haven't used in ages.
38776-				// (We do this here, not in the second loop, so that we
38777-				// perform age-based collection even in short-lived processes.)
38778-				age := time.Since(stat.ModTime())
38779-				if age > maxAge {
38780-					if debug {
38781-						log.Printf("age: deleting stale file %s (%dB, age %v)",
38782-							path, stat.Size(), age)
38783-					}
38784-					os.Remove(path) // ignore error
38785-				} else {
38786-					files = append(files, item{path, stat})
38787-					total += stat.Size()
38788-					if debug && len(files)%1000 == 0 {
38789-						log.Printf("filecache: checked %d files in %v", len(files), time.Since(start))
38790-					}
38791-					if len(files)%batchSize == 0 {
38792-						time.Sleep(batchSize * statDelay)
38793-					}
38794-				}
38795-			}
38796-			return nil
38797-		})
38798-
38799-		// Sort oldest files first.
38800-		sort.Slice(files, func(i, j int) bool {
38801-			return files[i].stat.ModTime().Before(files[j].stat.ModTime())
38802-		})
38803-
38804-		// Delete oldest files until we're under budget.
38805-		budget := atomic.LoadInt64(&budget)
38806-		for _, file := range files {
38807-			if total < budget {
38808-				break
38809-			}
38810-			if debug {
38811-				age := time.Since(file.stat.ModTime())
38812-				log.Printf("budget: deleting stale file %s (%dB, age %v)",
38813-					file.path, file.stat.Size(), age)
38814-			}
38815-			os.Remove(file.path) // ignore error
38816-			total -= file.stat.Size()
38817-		}
38818-
38819-		time.Sleep(period)
38820-
38821-		// Once only, delete all directories.
38822-		// This will succeed only for the empty ones,
38823-		// and ensures that stale directories (whose
38824-		// files have been deleted) are removed eventually.
38825-		// They don't take up much space but they do slow
38826-		// down the traversal.
38827-		//
38828-		// We do this after the sleep to minimize the
38829-		// race against Set, which may create a directory
38830-		// that is momentarily empty.
38831-		//
38832-		// (Test processes don't live that long, so
38833-		// this may not be reached on the CI builders.)
38834-		if dirs != nil {
38835-			dirnames := make([]string, 0, len(dirs))
38836-			for dir := range dirs {
38837-				dirnames = append(dirnames, dir)
38838-			}
38839-			dirs = nil
38840-
38841-			// Descending length order => children before parents.
38842-			sort.Slice(dirnames, func(i, j int) bool {
38843-				return len(dirnames[i]) > len(dirnames[j])
38844-			})
38845-			var deleted int
38846-			for _, dir := range dirnames {
38847-				if os.Remove(dir) == nil { // ignore error
38848-					deleted++
38849-				}
38850-			}
38851-			if debug {
38852-				log.Printf("deleted %d empty directories", deleted)
38853-			}
38854-		}
38855-	}
38856-}
38857diff -urN a/gopls/internal/lsp/filecache/filecache_test.go b/gopls/internal/lsp/filecache/filecache_test.go
38858--- a/gopls/internal/lsp/filecache/filecache_test.go	2000-01-01 00:00:00.000000000 -0000
38859+++ b/gopls/internal/lsp/filecache/filecache_test.go	1970-01-01 00:00:00.000000000 +0000
38860@@ -1,215 +0,0 @@
38861-// Copyright 2022 The Go Authors. All rights reserved.
38862-// Use of this source code is governed by a BSD-style
38863-// license that can be found in the LICENSE file.
38864-
38865-package filecache_test
38866-
38867-// This file defines tests of the API of the filecache package.
38868-//
38869-// Some properties (e.g. garbage collection) cannot be exercised
38870-// through the API, so this test does not attempt to do so.
38871-
38872-import (
38873-	"bytes"
38874-	cryptorand "crypto/rand"
38875-	"fmt"
38876-	"log"
38877-	mathrand "math/rand"
38878-	"os"
38879-	"os/exec"
38880-	"strconv"
38881-	"testing"
38882-
38883-	"golang.org/x/sync/errgroup"
38884-	"golang.org/x/tools/gopls/internal/lsp/filecache"
38885-)
38886-
38887-func TestBasics(t *testing.T) {
38888-	const kind = "TestBasics"
38889-	key := uniqueKey() // never used before
38890-	value := []byte("hello")
38891-
38892-	// Get of a never-seen key returns not found.
38893-	if _, err := filecache.Get(kind, key); err != filecache.ErrNotFound {
38894-		t.Errorf("Get of random key returned err=%q, want not found", err)
38895-	}
38896-
38897-	// Set of a never-seen key and a small value succeeds.
38898-	if err := filecache.Set(kind, key, value); err != nil {
38899-		t.Errorf("Set failed: %v", err)
38900-	}
38901-
38902-	// Get of the key returns a copy of the value.
38903-	if got, err := filecache.Get(kind, key); err != nil {
38904-		t.Errorf("Get after Set failed: %v", err)
38905-	} else if string(got) != string(value) {
38906-		t.Errorf("Get after Set returned different value: got %q, want %q", got, value)
38907-	}
38908-
38909-	// The kind is effectively part of the key.
38910-	if _, err := filecache.Get("different-kind", key); err != filecache.ErrNotFound {
38911-		t.Errorf("Get with wrong kind returned err=%q, want not found", err)
38912-	}
38913-}
38914-
38915-// TestConcurrency exercises concurrent access to the same entry.
38916-func TestConcurrency(t *testing.T) {
38917-	const kind = "TestConcurrency"
38918-	key := uniqueKey()
38919-	const N = 100 // concurrency level
38920-
38921-	// Construct N distinct values, each larger
38922-	// than a typical 4KB OS file buffer page.
38923-	var values [N][8192]byte
38924-	for i := range values {
38925-		if _, err := mathrand.Read(values[i][:]); err != nil {
38926-			t.Fatalf("rand: %v", err)
38927-		}
38928-	}
38929-
38930-	// get calls Get and verifies that the cache entry
38931-	// matches one of the values passed to Set.
38932-	get := func(mustBeFound bool) error {
38933-		got, err := filecache.Get(kind, key)
38934-		if err != nil {
38935-			if err == filecache.ErrNotFound && !mustBeFound {
38936-				return nil // not found
38937-			}
38938-			return err
38939-		}
38940-		for _, want := range values {
38941-			if bytes.Equal(want[:], got) {
38942-				return nil // a match
38943-			}
38944-		}
38945-		return fmt.Errorf("Get returned a value that was never Set")
38946-	}
38947-
38948-	// Perform N concurrent calls to Set and Get.
38949-	// All sets must succeed.
38950-	// All gets must return nothing, or one of the Set values;
38951-	// there is no third possibility.
38952-	var group errgroup.Group
38953-	for i := range values {
38954-		i := i
38955-		group.Go(func() error { return filecache.Set(kind, key, values[i][:]) })
38956-		group.Go(func() error { return get(false) })
38957-	}
38958-	if err := group.Wait(); err != nil {
38959-		t.Fatal(err)
38960-	}
38961-
38962-	// A final Get must report one of the values that was Set.
38963-	if err := get(true); err != nil {
38964-		t.Fatalf("final Get failed: %v", err)
38965-	}
38966-}
38967-
38968-const (
38969-	testIPCKind   = "TestIPC"
38970-	testIPCValueA = "hello"
38971-	testIPCValueB = "world"
38972-)
38973-
38974-// TestIPC exercises interprocess communication through the cache.
38975-// It calls Set(A) in the parent, { Get(A); Set(B) } in the child
38976-// process, then Get(B) in the parent.
38977-func TestIPC(t *testing.T) {
38978-	keyA := uniqueKey()
38979-	keyB := uniqueKey()
38980-	value := []byte(testIPCValueA)
38981-
38982-	// Set keyA.
38983-	if err := filecache.Set(testIPCKind, keyA, value); err != nil {
38984-		t.Fatalf("Set: %v", err)
38985-	}
38986-
38987-	// Call ipcChild in a child process,
38988-	// passing it the keys in the environment
38989-	// (quoted, to avoid NUL termination of C strings).
38990-	// It will Get(A) then Set(B).
38991-	cmd := exec.Command(os.Args[0], os.Args[1:]...)
38992-	cmd.Env = append(os.Environ(),
38993-		"ENTRYPOINT=ipcChild",
38994-		fmt.Sprintf("KEYA=%q", keyA),
38995-		fmt.Sprintf("KEYB=%q", keyB))
38996-	cmd.Stdout = os.Stderr
38997-	cmd.Stderr = os.Stderr
38998-	if err := cmd.Run(); err != nil {
38999-		t.Fatal(err)
39000-	}
39001-
39002-	// Verify keyB.
39003-	got, err := filecache.Get(testIPCKind, keyB)
39004-	if err != nil {
39005-		t.Fatal(err)
39006-	}
39007-	if string(got) != "world" {
39008-		t.Fatalf("Get(keyB) = %q, want %q", got, "world")
39009-	}
39010-}
39011-
39012-// We define our own main function so that portions of
39013-// some tests can run in a separate (child) process.
39014-func TestMain(m *testing.M) {
39015-	switch os.Getenv("ENTRYPOINT") {
39016-	case "ipcChild":
39017-		ipcChild()
39018-	default:
39019-		os.Exit(m.Run())
39020-	}
39021-}
39022-
39023-// ipcChild is the portion of TestIPC that runs in a child process.
39024-func ipcChild() {
39025-	getenv := func(name string) (key [32]byte) {
39026-		s, _ := strconv.Unquote(os.Getenv(name))
39027-		copy(key[:], []byte(s))
39028-		return
39029-	}
39030-
39031-	// Verify key A.
39032-	got, err := filecache.Get(testIPCKind, getenv("KEYA"))
39033-	if err != nil || string(got) != testIPCValueA {
39034-		log.Fatalf("child: Get(key) = %q, %v; want %q", got, err, testIPCValueA)
39035-	}
39036-
39037-	// Set key B.
39038-	if err := filecache.Set(testIPCKind, getenv("KEYB"), []byte(testIPCValueB)); err != nil {
39039-		log.Fatalf("child: Set(keyB) failed: %v", err)
39040-	}
39041-}
39042-
39043-// uniqueKey returns a key that has never been used before.
39044-func uniqueKey() (key [32]byte) {
39045-	if _, err := cryptorand.Read(key[:]); err != nil {
39046-		log.Fatalf("rand: %v", err)
39047-	}
39048-	return
39049-}
39050-
39051-func BenchmarkUncontendedGet(b *testing.B) {
39052-	const kind = "BenchmarkUncontendedGet"
39053-	key := uniqueKey()
39054-
39055-	var value [8192]byte
39056-	if _, err := mathrand.Read(value[:]); err != nil {
39057-		b.Fatalf("rand: %v", err)
39058-	}
39059-	if err := filecache.Set(kind, key, value[:]); err != nil {
39060-		b.Fatal(err)
39061-	}
39062-	b.ResetTimer()
39063-
39064-	var group errgroup.Group
39065-	group.SetLimit(50)
39066-	for i := 0; i < b.N; i++ {
39067-		group.Go(func() error {
39068-			_, err := filecache.Get(kind, key)
39069-			return err
39070-		})
39071-	}
39072-	if err := group.Wait(); err != nil {
39073-		b.Fatal(err)
39074-	}
39075-}
39076diff -urN a/gopls/internal/lsp/folding_range.go b/gopls/internal/lsp/folding_range.go
39077--- a/gopls/internal/lsp/folding_range.go	2000-01-01 00:00:00.000000000 -0000
39078+++ b/gopls/internal/lsp/folding_range.go	1970-01-01 00:00:00.000000000 +0000
39079@@ -1,41 +0,0 @@
39080-// Copyright 2019 The Go Authors. All rights reserved.
39081-// Use of this source code is governed by a BSD-style
39082-// license that can be found in the LICENSE file.
39083-
39084-package lsp
39085-
39086-import (
39087-	"context"
39088-
39089-	"golang.org/x/tools/gopls/internal/lsp/protocol"
39090-	"golang.org/x/tools/gopls/internal/lsp/source"
39091-)
39092-
39093-func (s *Server) foldingRange(ctx context.Context, params *protocol.FoldingRangeParams) ([]protocol.FoldingRange, error) {
39094-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.Go)
39095-	defer release()
39096-	if !ok {
39097-		return nil, err
39098-	}
39099-
39100-	ranges, err := source.FoldingRange(ctx, snapshot, fh, snapshot.View().Options().LineFoldingOnly)
39101-	if err != nil {
39102-		return nil, err
39103-	}
39104-	return toProtocolFoldingRanges(ranges)
39105-}
39106-
39107-func toProtocolFoldingRanges(ranges []*source.FoldingRangeInfo) ([]protocol.FoldingRange, error) {
39108-	result := make([]protocol.FoldingRange, 0, len(ranges))
39109-	for _, info := range ranges {
39110-		rng := info.MappedRange.Range()
39111-		result = append(result, protocol.FoldingRange{
39112-			StartLine:      rng.Start.Line,
39113-			StartCharacter: rng.Start.Character,
39114-			EndLine:        rng.End.Line,
39115-			EndCharacter:   rng.End.Character,
39116-			Kind:           string(info.Kind),
39117-		})
39118-	}
39119-	return result, nil
39120-}
39121diff -urN a/gopls/internal/lsp/format.go b/gopls/internal/lsp/format.go
39122--- a/gopls/internal/lsp/format.go	2000-01-01 00:00:00.000000000 -0000
39123+++ b/gopls/internal/lsp/format.go	1970-01-01 00:00:00.000000000 +0000
39124@@ -1,31 +0,0 @@
39125-// Copyright 2018 The Go Authors. All rights reserved.
39126-// Use of this source code is governed by a BSD-style
39127-// license that can be found in the LICENSE file.
39128-
39129-package lsp
39130-
39131-import (
39132-	"context"
39133-
39134-	"golang.org/x/tools/gopls/internal/lsp/mod"
39135-	"golang.org/x/tools/gopls/internal/lsp/protocol"
39136-	"golang.org/x/tools/gopls/internal/lsp/source"
39137-	"golang.org/x/tools/gopls/internal/lsp/work"
39138-)
39139-
39140-func (s *Server) formatting(ctx context.Context, params *protocol.DocumentFormattingParams) ([]protocol.TextEdit, error) {
39141-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.UnknownKind)
39142-	defer release()
39143-	if !ok {
39144-		return nil, err
39145-	}
39146-	switch snapshot.View().FileKind(fh) {
39147-	case source.Mod:
39148-		return mod.Format(ctx, snapshot, fh)
39149-	case source.Go:
39150-		return source.Format(ctx, snapshot, fh)
39151-	case source.Work:
39152-		return work.Format(ctx, snapshot, fh)
39153-	}
39154-	return nil, nil
39155-}
39156diff -urN a/gopls/internal/lsp/general.go b/gopls/internal/lsp/general.go
39157--- a/gopls/internal/lsp/general.go	2000-01-01 00:00:00.000000000 -0000
39158+++ b/gopls/internal/lsp/general.go	1970-01-01 00:00:00.000000000 +0000
39159@@ -1,619 +0,0 @@
39160-// Copyright 2019 The Go Authors. All rights reserved.
39161-// Use of this source code is governed by a BSD-style
39162-// license that can be found in the LICENSE file.
39163-
39164-package lsp
39165-
39166-import (
39167-	"context"
39168-	"encoding/json"
39169-	"fmt"
39170-	"log"
39171-	"os"
39172-	"path"
39173-	"path/filepath"
39174-	"sort"
39175-	"strings"
39176-	"sync"
39177-
39178-	"golang.org/x/tools/gopls/internal/lsp/debug"
39179-	"golang.org/x/tools/gopls/internal/lsp/protocol"
39180-	"golang.org/x/tools/gopls/internal/lsp/source"
39181-	"golang.org/x/tools/gopls/internal/span"
39182-	"golang.org/x/tools/internal/bug"
39183-	"golang.org/x/tools/internal/event"
39184-	"golang.org/x/tools/internal/jsonrpc2"
39185-)
39186-
39187-func (s *Server) initialize(ctx context.Context, params *protocol.ParamInitialize) (*protocol.InitializeResult, error) {
39188-	s.stateMu.Lock()
39189-	if s.state >= serverInitializing {
39190-		defer s.stateMu.Unlock()
39191-		return nil, fmt.Errorf("%w: initialize called while server in %v state", jsonrpc2.ErrInvalidRequest, s.state)
39192-	}
39193-	s.state = serverInitializing
39194-	s.stateMu.Unlock()
39195-
39196-	// For uniqueness, use the gopls PID rather than params.ProcessID (the client
39197-	// pid). Some clients might start multiple gopls servers, though they
39198-	// probably shouldn't.
39199-	pid := os.Getpid()
39200-	s.tempDir = filepath.Join(os.TempDir(), fmt.Sprintf("gopls-%d.%s", pid, s.session.ID()))
39201-	err := os.Mkdir(s.tempDir, 0700)
39202-	if err != nil {
39203-		// MkdirTemp could fail due to permissions issues. This is a problem with
39204-		// the user's environment, but should not block gopls otherwise behaving.
39205-		// All usage of s.tempDir should be predicated on having a non-empty
39206-		// s.tempDir.
39207-		event.Error(ctx, "creating temp dir", err)
39208-		s.tempDir = ""
39209-	}
39210-	s.progress.SetSupportsWorkDoneProgress(params.Capabilities.Window.WorkDoneProgress)
39211-
39212-	options := s.session.Options()
39213-	defer func() { s.session.SetOptions(options) }()
39214-
39215-	if err := s.handleOptionResults(ctx, source.SetOptions(options, params.InitializationOptions)); err != nil {
39216-		return nil, err
39217-	}
39218-	options.ForClientCapabilities(params.Capabilities)
39219-
39220-	if options.ShowBugReports {
39221-		// Report the next bug that occurs on the server.
39222-		bugCh := bug.Notify()
39223-		go func() {
39224-			b := <-bugCh
39225-			msg := &protocol.ShowMessageParams{
39226-				Type:    protocol.Error,
39227-				Message: fmt.Sprintf("A bug occurred on the server: %s\nLocation:%s", b.Description, b.Key),
39228-			}
39229-			if err := s.eventuallyShowMessage(context.Background(), msg); err != nil {
39230-				log.Printf("error showing bug: %v", err)
39231-			}
39232-		}()
39233-	}
39234-
39235-	folders := params.WorkspaceFolders
39236-	if len(folders) == 0 {
39237-		if params.RootURI != "" {
39238-			folders = []protocol.WorkspaceFolder{{
39239-				URI:  string(params.RootURI),
39240-				Name: path.Base(params.RootURI.SpanURI().Filename()),
39241-			}}
39242-		}
39243-	}
39244-	for _, folder := range folders {
39245-		uri := span.URIFromURI(folder.URI)
39246-		if !uri.IsFile() {
39247-			continue
39248-		}
39249-		s.pendingFolders = append(s.pendingFolders, folder)
39250-	}
39251-	// gopls only supports URIs with a file:// scheme, so if we have no
39252-	// workspace folders with a supported scheme, fail to initialize.
39253-	if len(folders) > 0 && len(s.pendingFolders) == 0 {
39254-		return nil, fmt.Errorf("unsupported URI schemes: %v (gopls only supports file URIs)", folders)
39255-	}
39256-
39257-	var codeActionProvider interface{} = true
39258-	if ca := params.Capabilities.TextDocument.CodeAction; len(ca.CodeActionLiteralSupport.CodeActionKind.ValueSet) > 0 {
39259-		// If the client has specified CodeActionLiteralSupport,
39260-		// send the code actions we support.
39261-		//
39262-		// Using CodeActionOptions is only valid if codeActionLiteralSupport is set.
39263-		codeActionProvider = &protocol.CodeActionOptions{
39264-			CodeActionKinds: s.getSupportedCodeActions(),
39265-		}
39266-	}
39267-	var renameOpts interface{} = true
39268-	if r := params.Capabilities.TextDocument.Rename; r != nil && r.PrepareSupport {
39269-		renameOpts = protocol.RenameOptions{
39270-			PrepareProvider: r.PrepareSupport,
39271-		}
39272-	}
39273-
39274-	versionInfo := debug.VersionInfo()
39275-
39276-	// golang/go#45732: Warn users who've installed sergi/go-diff@v1.2.0, since
39277-	// it will corrupt the formatting of their files.
39278-	for _, dep := range versionInfo.Deps {
39279-		if dep.Path == "github.com/sergi/go-diff" && dep.Version == "v1.2.0" {
39280-			if err := s.eventuallyShowMessage(ctx, &protocol.ShowMessageParams{
39281-				Message: `It looks like you have a bad gopls installation.
39282-Please reinstall gopls by running 'GO111MODULE=on go install golang.org/x/tools/gopls@latest'.
39283-See https://github.com/golang/go/issues/45732 for more information.`,
39284-				Type: protocol.Error,
39285-			}); err != nil {
39286-				return nil, err
39287-			}
39288-		}
39289-	}
39290-
39291-	goplsVersion, err := json.Marshal(versionInfo)
39292-	if err != nil {
39293-		return nil, err
39294-	}
39295-
39296-	return &protocol.InitializeResult{
39297-		Capabilities: protocol.ServerCapabilities{
39298-			CallHierarchyProvider: &protocol.Or_ServerCapabilities_callHierarchyProvider{Value: true},
39299-			CodeActionProvider:    codeActionProvider,
39300-			CodeLensProvider:      &protocol.CodeLensOptions{}, // must be non-nil to enable the code lens capability
39301-			CompletionProvider: &protocol.CompletionOptions{
39302-				TriggerCharacters: []string{"."},
39303-			},
39304-			DefinitionProvider:         &protocol.Or_ServerCapabilities_definitionProvider{Value: true},
39305-			TypeDefinitionProvider:     &protocol.Or_ServerCapabilities_typeDefinitionProvider{Value: true},
39306-			ImplementationProvider:     &protocol.Or_ServerCapabilities_implementationProvider{Value: true},
39307-			DocumentFormattingProvider: &protocol.Or_ServerCapabilities_documentFormattingProvider{Value: true},
39308-			DocumentSymbolProvider:     &protocol.Or_ServerCapabilities_documentSymbolProvider{Value: true},
39309-			WorkspaceSymbolProvider:    &protocol.Or_ServerCapabilities_workspaceSymbolProvider{Value: true},
39310-			ExecuteCommandProvider: &protocol.ExecuteCommandOptions{
39311-				Commands: options.SupportedCommands,
39312-			},
39313-			FoldingRangeProvider:      &protocol.Or_ServerCapabilities_foldingRangeProvider{Value: true},
39314-			HoverProvider:             &protocol.Or_ServerCapabilities_hoverProvider{Value: true},
39315-			DocumentHighlightProvider: &protocol.Or_ServerCapabilities_documentHighlightProvider{Value: true},
39316-			DocumentLinkProvider:      &protocol.DocumentLinkOptions{},
39317-			InlayHintProvider:         protocol.InlayHintOptions{},
39318-			ReferencesProvider:        &protocol.Or_ServerCapabilities_referencesProvider{Value: true},
39319-			RenameProvider:            renameOpts,
39320-			SelectionRangeProvider:    &protocol.Or_ServerCapabilities_selectionRangeProvider{Value: true},
39321-			SemanticTokensProvider: protocol.SemanticTokensOptions{
39322-				Range: &protocol.Or_SemanticTokensOptions_range{Value: true},
39323-				Full:  &protocol.Or_SemanticTokensOptions_full{Value: true},
39324-				Legend: protocol.SemanticTokensLegend{
39325-					TokenTypes:     s.session.Options().SemanticTypes,
39326-					TokenModifiers: s.session.Options().SemanticMods,
39327-				},
39328-			},
39329-			SignatureHelpProvider: &protocol.SignatureHelpOptions{
39330-				TriggerCharacters: []string{"(", ","},
39331-			},
39332-			TextDocumentSync: &protocol.TextDocumentSyncOptions{
39333-				Change:    protocol.Incremental,
39334-				OpenClose: true,
39335-				Save: &protocol.SaveOptions{
39336-					IncludeText: false,
39337-				},
39338-			},
39339-			Workspace: &protocol.Workspace6Gn{
39340-				WorkspaceFolders: &protocol.WorkspaceFolders5Gn{
39341-					Supported:           true,
39342-					ChangeNotifications: "workspace/didChangeWorkspaceFolders",
39343-				},
39344-			},
39345-		},
39346-		ServerInfo: &protocol.PServerInfoMsg_initialize{
39347-			Name:    "gopls",
39348-			Version: string(goplsVersion),
39349-		},
39350-	}, nil
39351-}
39352-
39353-func (s *Server) initialized(ctx context.Context, params *protocol.InitializedParams) error {
39354-	s.stateMu.Lock()
39355-	if s.state >= serverInitialized {
39356-		defer s.stateMu.Unlock()
39357-		return fmt.Errorf("%w: initialized called while server in %v state", jsonrpc2.ErrInvalidRequest, s.state)
39358-	}
39359-	s.state = serverInitialized
39360-	s.stateMu.Unlock()
39361-
39362-	for _, not := range s.notifications {
39363-		s.client.ShowMessage(ctx, not)
39364-	}
39365-	s.notifications = nil
39366-
39367-	options := s.session.Options()
39368-	defer func() { s.session.SetOptions(options) }()
39369-
39370-	if err := s.addFolders(ctx, s.pendingFolders); err != nil {
39371-		return err
39372-	}
39373-	s.pendingFolders = nil
39374-	s.checkViewGoVersions()
39375-
39376-	var registrations []protocol.Registration
39377-	if options.ConfigurationSupported && options.DynamicConfigurationSupported {
39378-		registrations = append(registrations, protocol.Registration{
39379-			ID:     "workspace/didChangeConfiguration",
39380-			Method: "workspace/didChangeConfiguration",
39381-		})
39382-	}
39383-	if len(registrations) > 0 {
39384-		if err := s.client.RegisterCapability(ctx, &protocol.RegistrationParams{
39385-			Registrations: registrations,
39386-		}); err != nil {
39387-			return err
39388-		}
39389-	}
39390-	return nil
39391-}
39392-
39393-// GoVersionTable maps Go versions to the gopls version in which support will
39394-// be deprecated, and the final gopls version supporting them without warnings.
39395-// Keep this in sync with gopls/README.md
39396-//
39397-// Must be sorted in ascending order of Go version.
39398-//
39399-// Mutable for testing.
39400-var GoVersionTable = []GoVersionSupport{
39401-	{12, "", "v0.7.5"},
39402-	{15, "v0.11.0", "v0.9.5"},
39403-}
39404-
39405-// GoVersionSupport holds information about end-of-life Go version support.
39406-type GoVersionSupport struct {
39407-	GoVersion           int
39408-	DeprecatedVersion   string // if unset, the version is already deprecated
39409-	InstallGoplsVersion string
39410-}
39411-
39412-// OldestSupportedGoVersion is the last X in Go 1.X that this version of gopls
39413-// supports.
39414-func OldestSupportedGoVersion() int {
39415-	return GoVersionTable[len(GoVersionTable)-1].GoVersion + 1
39416-}
39417-
39418-// versionMessage returns the warning/error message to display if the user is
39419-// on the given Go version, if any. The goVersion variable is the X in Go 1.X.
39420-//
39421-// If goVersion is invalid (< 0), it returns "", 0.
39422-func versionMessage(goVersion int) (string, protocol.MessageType) {
39423-	if goVersion < 0 {
39424-		return "", 0
39425-	}
39426-
39427-	for _, v := range GoVersionTable {
39428-		if goVersion <= v.GoVersion {
39429-			var msgBuilder strings.Builder
39430-
39431-			mType := protocol.Error
39432-			fmt.Fprintf(&msgBuilder, "Found Go version 1.%d", goVersion)
39433-			if v.DeprecatedVersion != "" {
39434-				// not deprecated yet, just a warning
39435-				fmt.Fprintf(&msgBuilder, ", which will be unsupported by gopls %s. ", v.DeprecatedVersion)
39436-				mType = protocol.Warning
39437-			} else {
39438-				fmt.Fprint(&msgBuilder, ", which is not supported by this version of gopls. ")
39439-			}
39440-			fmt.Fprintf(&msgBuilder, "Please upgrade to Go 1.%d or later and reinstall gopls. ", OldestSupportedGoVersion())
39441-			fmt.Fprintf(&msgBuilder, "If you can't upgrade and want this message to go away, please install gopls %s. ", v.InstallGoplsVersion)
39442-			fmt.Fprint(&msgBuilder, "See https://go.dev/s/gopls-support-policy for more details.")
39443-
39444-			return msgBuilder.String(), mType
39445-		}
39446-	}
39447-	return "", 0
39448-}
39449-
39450-// checkViewGoVersions checks whether any Go version used by a view is too old,
39451-// raising a showMessage notification if so.
39452-//
39453-// It should be called after views change.
39454-func (s *Server) checkViewGoVersions() {
39455-	oldestVersion := -1
39456-	for _, view := range s.session.Views() {
39457-		viewVersion := view.GoVersion()
39458-		if oldestVersion == -1 || viewVersion < oldestVersion {
39459-			oldestVersion = viewVersion
39460-		}
39461-	}
39462-
39463-	if msg, mType := versionMessage(oldestVersion); msg != "" {
39464-		s.eventuallyShowMessage(context.Background(), &protocol.ShowMessageParams{
39465-			Type:    mType,
39466-			Message: msg,
39467-		})
39468-	}
39469-}
39470-
39471-func (s *Server) addFolders(ctx context.Context, folders []protocol.WorkspaceFolder) error {
39472-	originalViews := len(s.session.Views())
39473-	viewErrors := make(map[span.URI]error)
39474-
39475-	var ndiagnose sync.WaitGroup // number of unfinished diagnose calls
39476-	if s.session.Options().VerboseWorkDoneProgress {
39477-		work := s.progress.Start(ctx, DiagnosticWorkTitle(FromInitialWorkspaceLoad), "Calculating diagnostics for initial workspace load...", nil, nil)
39478-		defer func() {
39479-			go func() {
39480-				ndiagnose.Wait()
39481-				work.End(ctx, "Done.")
39482-			}()
39483-		}()
39484-	}
39485-	// Only one view gets to have a workspace.
39486-	var nsnapshots sync.WaitGroup // number of unfinished snapshot initializations
39487-	for _, folder := range folders {
39488-		uri := span.URIFromURI(folder.URI)
39489-		// Ignore non-file URIs.
39490-		if !uri.IsFile() {
39491-			continue
39492-		}
39493-		work := s.progress.Start(ctx, "Setting up workspace", "Loading packages...", nil, nil)
39494-		snapshot, release, err := s.addView(ctx, folder.Name, uri)
39495-		if err != nil {
39496-			if err == source.ErrViewExists {
39497-				continue
39498-			}
39499-			viewErrors[uri] = err
39500-			work.End(ctx, fmt.Sprintf("Error loading packages: %s", err))
39501-			continue
39502-		}
39503-		// Inv: release() must be called once.
39504-
39505-		// Initialize snapshot asynchronously.
39506-		initialized := make(chan struct{})
39507-		nsnapshots.Add(1)
39508-		go func() {
39509-			snapshot.AwaitInitialized(ctx)
39510-			work.End(ctx, "Finished loading packages.")
39511-			nsnapshots.Done()
39512-			close(initialized) // signal
39513-		}()
39514-
39515-		// Diagnose the newly created view asynchronously.
39516-		ndiagnose.Add(1)
39517-		go func() {
39518-			s.diagnoseDetached(snapshot)
39519-			<-initialized
39520-			release()
39521-			ndiagnose.Done()
39522-		}()
39523-	}
39524-
39525-	// Wait for snapshots to be initialized so that all files are known.
39526-	// (We don't need to wait for diagnosis to finish.)
39527-	nsnapshots.Wait()
39528-
39529-	// Register for file watching notifications, if they are supported.
39530-	if err := s.updateWatchedDirectories(ctx); err != nil {
39531-		event.Error(ctx, "failed to register for file watching notifications", err)
39532-	}
39533-
39534-	if len(viewErrors) > 0 {
39535-		errMsg := fmt.Sprintf("Error loading workspace folders (expected %v, got %v)\n", len(folders), len(s.session.Views())-originalViews)
39536-		for uri, err := range viewErrors {
39537-			errMsg += fmt.Sprintf("failed to load view for %s: %v\n", uri, err)
39538-		}
39539-		return s.client.ShowMessage(ctx, &protocol.ShowMessageParams{
39540-			Type:    protocol.Error,
39541-			Message: errMsg,
39542-		})
39543-	}
39544-	return nil
39545-}
39546-
39547-// updateWatchedDirectories compares the current set of directories to watch
39548-// with the previously registered set of directories. If the set of directories
39549-// has changed, we unregister and re-register for file watching notifications.
39550-// updatedSnapshots is the set of snapshots that have been updated.
39551-func (s *Server) updateWatchedDirectories(ctx context.Context) error {
39552-	patterns := s.session.FileWatchingGlobPatterns(ctx)
39553-
39554-	s.watchedGlobPatternsMu.Lock()
39555-	defer s.watchedGlobPatternsMu.Unlock()
39556-
39557-	// Nothing to do if the set of workspace directories is unchanged.
39558-	if equalURISet(s.watchedGlobPatterns, patterns) {
39559-		return nil
39560-	}
39561-
39562-	// If the set of directories to watch has changed, register the updates and
39563-	// unregister the previously watched directories. This ordering avoids a
39564-	// period where no files are being watched. Still, if a user makes on-disk
39565-	// changes before these updates are complete, we may miss them for the new
39566-	// directories.
39567-	prevID := s.watchRegistrationCount - 1
39568-	if err := s.registerWatchedDirectoriesLocked(ctx, patterns); err != nil {
39569-		return err
39570-	}
39571-	if prevID >= 0 {
39572-		return s.client.UnregisterCapability(ctx, &protocol.UnregistrationParams{
39573-			Unregisterations: []protocol.Unregistration{{
39574-				ID:     watchedFilesCapabilityID(prevID),
39575-				Method: "workspace/didChangeWatchedFiles",
39576-			}},
39577-		})
39578-	}
39579-	return nil
39580-}
39581-
39582-func watchedFilesCapabilityID(id int) string {
39583-	return fmt.Sprintf("workspace/didChangeWatchedFiles-%d", id)
39584-}
39585-
39586-func equalURISet(m1, m2 map[string]struct{}) bool {
39587-	if len(m1) != len(m2) {
39588-		return false
39589-	}
39590-	for k := range m1 {
39591-		_, ok := m2[k]
39592-		if !ok {
39593-			return false
39594-		}
39595-	}
39596-	return true
39597-}
39598-
39599-// registerWatchedDirectoriesLocked sends the workspace/didChangeWatchedFiles
39600-// registrations to the client and updates s.watchedDirectories.
39601-func (s *Server) registerWatchedDirectoriesLocked(ctx context.Context, patterns map[string]struct{}) error {
39602-	if !s.session.Options().DynamicWatchedFilesSupported {
39603-		return nil
39604-	}
39605-	for k := range s.watchedGlobPatterns {
39606-		delete(s.watchedGlobPatterns, k)
39607-	}
39608-	var watchers []protocol.FileSystemWatcher
39609-	val := protocol.WatchChange | protocol.WatchDelete | protocol.WatchCreate
39610-	for pattern := range patterns {
39611-		watchers = append(watchers, protocol.FileSystemWatcher{
39612-			GlobPattern: pattern,
39613-			Kind:        &val,
39614-		})
39615-	}
39616-
39617-	if err := s.client.RegisterCapability(ctx, &protocol.RegistrationParams{
39618-		Registrations: []protocol.Registration{{
39619-			ID:     watchedFilesCapabilityID(s.watchRegistrationCount),
39620-			Method: "workspace/didChangeWatchedFiles",
39621-			RegisterOptions: protocol.DidChangeWatchedFilesRegistrationOptions{
39622-				Watchers: watchers,
39623-			},
39624-		}},
39625-	}); err != nil {
39626-		return err
39627-	}
39628-	s.watchRegistrationCount++
39629-
39630-	for k, v := range patterns {
39631-		s.watchedGlobPatterns[k] = v
39632-	}
39633-	return nil
39634-}
39635-
39636-func (s *Server) fetchConfig(ctx context.Context, name string, folder span.URI, o *source.Options) error {
39637-	if !s.session.Options().ConfigurationSupported {
39638-		return nil
39639-	}
39640-	configs, err := s.client.Configuration(ctx, &protocol.ParamConfiguration{
39641-		Items: []protocol.ConfigurationItem{{
39642-			ScopeURI: string(folder),
39643-			Section:  "gopls",
39644-		}},
39645-	},
39646-	)
39647-	if err != nil {
39648-		return fmt.Errorf("failed to get workspace configuration from client (%s): %v", folder, err)
39649-	}
39650-	for _, config := range configs {
39651-		if err := s.handleOptionResults(ctx, source.SetOptions(o, config)); err != nil {
39652-			return err
39653-		}
39654-	}
39655-	return nil
39656-}
39657-
39658-func (s *Server) eventuallyShowMessage(ctx context.Context, msg *protocol.ShowMessageParams) error {
39659-	s.stateMu.Lock()
39660-	defer s.stateMu.Unlock()
39661-	if s.state == serverInitialized {
39662-		return s.client.ShowMessage(ctx, msg)
39663-	}
39664-	s.notifications = append(s.notifications, msg)
39665-	return nil
39666-}
39667-
39668-func (s *Server) handleOptionResults(ctx context.Context, results source.OptionResults) error {
39669-	var warnings, errors []string
39670-	for _, result := range results {
39671-		switch result.Error.(type) {
39672-		case nil:
39673-			// nothing to do
39674-		case *source.SoftError:
39675-			warnings = append(warnings, result.Error.Error())
39676-		default:
39677-			errors = append(errors, result.Error.Error())
39678-		}
39679-	}
39680-
39681-	// Sort messages, but put errors first.
39682-	//
39683-	// Having stable content for the message allows clients to de-duplicate. This
39684-	// matters because we may send duplicate warnings for clients that support
39685-	// dynamic configuration: one for the initial settings, and then more for the
39686-	// individual view settings.
39687-	var msgs []string
39688-	msgType := protocol.Warning
39689-	if len(errors) > 0 {
39690-		msgType = protocol.Error
39691-		sort.Strings(errors)
39692-		msgs = append(msgs, errors...)
39693-	}
39694-	if len(warnings) > 0 {
39695-		sort.Strings(warnings)
39696-		msgs = append(msgs, warnings...)
39697-	}
39698-
39699-	if len(msgs) > 0 {
39700-		// Settings
39701-		combined := "Invalid settings: " + strings.Join(msgs, "; ")
39702-		params := &protocol.ShowMessageParams{
39703-			Type:    msgType,
39704-			Message: combined,
39705-		}
39706-		return s.eventuallyShowMessage(ctx, params)
39707-	}
39708-
39709-	return nil
39710-}
39711-
39712-// beginFileRequest checks preconditions for a file-oriented request and routes
39713-// it to a snapshot.
39714-// We don't want to return errors for benign conditions like wrong file type,
39715-// so callers should do if !ok { return err } rather than if err != nil.
39716-// The returned cleanup function is non-nil even in case of false/error result.
39717-func (s *Server) beginFileRequest(ctx context.Context, pURI protocol.DocumentURI, expectKind source.FileKind) (source.Snapshot, source.FileHandle, bool, func(), error) {
39718-	uri := pURI.SpanURI()
39719-	if !uri.IsFile() {
39720-		// Not a file URI. Stop processing the request, but don't return an error.
39721-		return nil, nil, false, func() {}, nil
39722-	}
39723-	view, err := s.session.ViewOf(uri)
39724-	if err != nil {
39725-		return nil, nil, false, func() {}, err
39726-	}
39727-	snapshot, release, err := view.Snapshot()
39728-	if err != nil {
39729-		return nil, nil, false, func() {}, err
39730-	}
39731-	fh, err := snapshot.GetFile(ctx, uri)
39732-	if err != nil {
39733-		release()
39734-		return nil, nil, false, func() {}, err
39735-	}
39736-	if expectKind != source.UnknownKind && view.FileKind(fh) != expectKind {
39737-		// Wrong kind of file. Nothing to do.
39738-		release()
39739-		return nil, nil, false, func() {}, nil
39740-	}
39741-	return snapshot, fh, true, release, nil
39742-}
39743-
39744-// shutdown implements the 'shutdown' LSP handler. It releases resources
39745-// associated with the server and waits for all ongoing work to complete.
39746-func (s *Server) shutdown(ctx context.Context) error {
39747-	s.stateMu.Lock()
39748-	defer s.stateMu.Unlock()
39749-	if s.state < serverInitialized {
39750-		event.Log(ctx, "server shutdown without initialization")
39751-	}
39752-	if s.state != serverShutDown {
39753-		// drop all the active views
39754-		s.session.Shutdown(ctx)
39755-		s.state = serverShutDown
39756-		if s.tempDir != "" {
39757-			if err := os.RemoveAll(s.tempDir); err != nil {
39758-				event.Error(ctx, "removing temp dir", err)
39759-			}
39760-		}
39761-	}
39762-	return nil
39763-}
39764-
39765-func (s *Server) exit(ctx context.Context) error {
39766-	s.stateMu.Lock()
39767-	defer s.stateMu.Unlock()
39768-
39769-	s.client.Close()
39770-
39771-	if s.state != serverShutDown {
39772-		// TODO: We should be able to do better than this.
39773-		os.Exit(1)
39774-	}
39775-	// we don't terminate the process on a normal exit, we just allow it to
39776-	// close naturally if needed after the connection is closed.
39777-	return nil
39778-}
39779diff -urN a/gopls/internal/lsp/general_test.go b/gopls/internal/lsp/general_test.go
39780--- a/gopls/internal/lsp/general_test.go	2000-01-01 00:00:00.000000000 -0000
39781+++ b/gopls/internal/lsp/general_test.go	1970-01-01 00:00:00.000000000 +0000
39782@@ -1,44 +0,0 @@
39783-// Copyright 2022 The Go Authors. All rights reserved.
39784-// Use of this source code is governed by a BSD-style
39785-// license that can be found in the LICENSE file.
39786-
39787-package lsp
39788-
39789-import (
39790-	"strings"
39791-	"testing"
39792-
39793-	"golang.org/x/tools/gopls/internal/lsp/protocol"
39794-)
39795-
39796-func TestVersionMessage(t *testing.T) {
39797-	tests := []struct {
39798-		goVersion    int
39799-		wantContains []string // string fragments that we expect to see
39800-		wantType     protocol.MessageType
39801-	}{
39802-		{-1, nil, 0},
39803-		{12, []string{"1.12", "not supported", "upgrade to Go 1.16", "install gopls v0.7.5"}, protocol.Error},
39804-		{13, []string{"1.13", "will be unsupported by gopls v0.11.0", "upgrade to Go 1.16", "install gopls v0.9.5"}, protocol.Warning},
39805-		{15, []string{"1.15", "will be unsupported by gopls v0.11.0", "upgrade to Go 1.16", "install gopls v0.9.5"}, protocol.Warning},
39806-		{16, nil, 0},
39807-	}
39808-
39809-	for _, test := range tests {
39810-		gotMsg, gotType := versionMessage(test.goVersion)
39811-
39812-		if len(test.wantContains) == 0 && gotMsg != "" {
39813-			t.Errorf("versionMessage(%d) = %q, want \"\"", test.goVersion, gotMsg)
39814-		}
39815-
39816-		for _, want := range test.wantContains {
39817-			if !strings.Contains(gotMsg, want) {
39818-				t.Errorf("versionMessage(%d) = %q, want containing %q", test.goVersion, gotMsg, want)
39819-			}
39820-		}
39821-
39822-		if gotType != test.wantType {
39823-			t.Errorf("versionMessage(%d) = returned message type %d, want %d", test.goVersion, gotType, test.wantType)
39824-		}
39825-	}
39826-}
39827diff -urN a/gopls/internal/lsp/glob/glob.go b/gopls/internal/lsp/glob/glob.go
39828--- a/gopls/internal/lsp/glob/glob.go	2000-01-01 00:00:00.000000000 -0000
39829+++ b/gopls/internal/lsp/glob/glob.go	1970-01-01 00:00:00.000000000 +0000
39830@@ -1,349 +0,0 @@
39831-// Copyright 2023 The Go Authors. All rights reserved.
39832-// Use of this source code is governed by a BSD-style
39833-// license that can be found in the LICENSE file.
39834-
39835-// Package glob implements an LSP-compliant glob pattern matcher for testing.
39836-package glob
39837-
39838-import (
39839-	"errors"
39840-	"fmt"
39841-	"strings"
39842-	"unicode/utf8"
39843-)
39844-
39845-// A Glob is an LSP-compliant glob pattern, as defined by the spec:
39846-// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#documentFilter
39847-//
39848-// NOTE: this implementation is currently only intended for testing. In order
39849-// to make it production ready, we'd need to:
39850-//   - verify it against the VS Code implementation
39851-//   - add more tests
39852-//   - microbenchmark, likely avoiding the element interface
39853-//   - resolve the question of what is meant by "character". If it's a UTF-16
39854-//     code (as we suspect) it'll be a bit more work.
39855-//
39856-// Quoting from the spec:
39857-// Glob patterns can have the following syntax:
39858-//   - `*` to match one or more characters in a path segment
39859-//   - `?` to match on one character in a path segment
39860-//   - `**` to match any number of path segments, including none
39861-//   - `{}` to group sub patterns into an OR expression. (e.g. `**/*.{ts,js}`
39862-//     matches all TypeScript and JavaScript files)
39863-//   - `[]` to declare a range of characters to match in a path segment
39864-//     (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
39865-//   - `[!...]` to negate a range of characters to match in a path segment
39866-//     (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but
39867-//     not `example.0`)
39868-//
39869-// Expanding on this:
39870-//   - '/' matches one or more literal slashes.
39871-//   - any other character matches itself literally.
39872-type Glob struct {
39873-	elems []element // pattern elements
39874-}
39875-
39876-// Parse builds a Glob for the given pattern, returning an error if the pattern
39877-// is invalid.
39878-func Parse(pattern string) (*Glob, error) {
39879-	g, _, err := parse(pattern, false)
39880-	return g, err
39881-}
39882-
39883-func parse(pattern string, nested bool) (*Glob, string, error) {
39884-	g := new(Glob)
39885-	for len(pattern) > 0 {
39886-		switch pattern[0] {
39887-		case '/':
39888-			pattern = pattern[1:]
39889-			g.elems = append(g.elems, slash{})
39890-
39891-		case '*':
39892-			if len(pattern) > 1 && pattern[1] == '*' {
39893-				if (len(g.elems) > 0 && g.elems[len(g.elems)-1] != slash{}) || (len(pattern) > 2 && pattern[2] != '/') {
39894-					return nil, "", errors.New("** may only be adjacent to '/'")
39895-				}
39896-				pattern = pattern[2:]
39897-				g.elems = append(g.elems, starStar{})
39898-				break
39899-			}
39900-			pattern = pattern[1:]
39901-			g.elems = append(g.elems, star{})
39902-
39903-		case '?':
39904-			pattern = pattern[1:]
39905-			g.elems = append(g.elems, anyChar{})
39906-
39907-		case '{':
39908-			var gs group
39909-			for pattern[0] != '}' {
39910-				pattern = pattern[1:]
39911-				g, pat, err := parse(pattern, true)
39912-				if err != nil {
39913-					return nil, "", err
39914-				}
39915-				if len(pat) == 0 {
39916-					return nil, "", errors.New("unmatched '{'")
39917-				}
39918-				pattern = pat
39919-				gs = append(gs, g)
39920-			}
39921-			pattern = pattern[1:]
39922-			g.elems = append(g.elems, gs)
39923-
39924-		case '}', ',':
39925-			if nested {
39926-				return g, pattern, nil
39927-			}
39928-			pattern = g.parseLiteral(pattern, false)
39929-
39930-		case '[':
39931-			pattern = pattern[1:]
39932-			if len(pattern) == 0 {
39933-				return nil, "", errBadRange
39934-			}
39935-			negate := false
39936-			if pattern[0] == '!' {
39937-				pattern = pattern[1:]
39938-				negate = true
39939-			}
39940-			low, sz, err := readRangeRune(pattern)
39941-			if err != nil {
39942-				return nil, "", err
39943-			}
39944-			pattern = pattern[sz:]
39945-			if len(pattern) == 0 || pattern[0] != '-' {
39946-				return nil, "", errBadRange
39947-			}
39948-			pattern = pattern[1:]
39949-			high, sz, err := readRangeRune(pattern)
39950-			if err != nil {
39951-				return nil, "", err
39952-			}
39953-			pattern = pattern[sz:]
39954-			if len(pattern) == 0 || pattern[0] != ']' {
39955-				return nil, "", errBadRange
39956-			}
39957-			pattern = pattern[1:]
39958-			g.elems = append(g.elems, charRange{negate, low, high})
39959-
39960-		default:
39961-			pattern = g.parseLiteral(pattern, nested)
39962-		}
39963-	}
39964-	return g, "", nil
39965-}
39966-
39967-// helper for decoding a rune in range elements, e.g. [a-z]
39968-func readRangeRune(input string) (rune, int, error) {
39969-	r, sz := utf8.DecodeRuneInString(input)
39970-	var err error
39971-	if r == utf8.RuneError {
39972-		// See the documentation for DecodeRuneInString.
39973-		switch sz {
39974-		case 0:
39975-			err = errBadRange
39976-		case 1:
39977-			err = errInvalidUTF8
39978-		}
39979-	}
39980-	return r, sz, err
39981-}
39982-
39983-var (
39984-	errBadRange    = errors.New("'[' patterns must be of the form [x-y]")
39985-	errInvalidUTF8 = errors.New("invalid UTF-8 encoding")
39986-)
39987-
39988-func (g *Glob) parseLiteral(pattern string, nested bool) string {
39989-	var specialChars string
39990-	if nested {
39991-		specialChars = "*?{[/},"
39992-	} else {
39993-		specialChars = "*?{[/"
39994-	}
39995-	end := strings.IndexAny(pattern, specialChars)
39996-	if end == -1 {
39997-		end = len(pattern)
39998-	}
39999-	g.elems = append(g.elems, literal(pattern[:end]))
40000-	return pattern[end:]
40001-}
40002-
40003-func (g *Glob) String() string {
40004-	var b strings.Builder
40005-	for _, e := range g.elems {
40006-		fmt.Fprint(&b, e)
40007-	}
40008-	return b.String()
40009-}
40010-
40011-// element holds a glob pattern element, as defined below.
40012-type element fmt.Stringer
40013-
40014-// element types.
40015-type (
40016-	slash     struct{} // One or more '/' separators
40017-	literal   string   // string literal, not containing /, *, ?, {}, or []
40018-	star      struct{} // *
40019-	anyChar   struct{} // ?
40020-	starStar  struct{} // **
40021-	group     []*Glob  // {foo, bar, ...} grouping
40022-	charRange struct { // [a-z] character range
40023-		negate    bool
40024-		low, high rune
40025-	}
40026-)
40027-
40028-func (s slash) String() string    { return "/" }
40029-func (l literal) String() string  { return string(l) }
40030-func (s star) String() string     { return "*" }
40031-func (a anyChar) String() string  { return "?" }
40032-func (s starStar) String() string { return "**" }
40033-func (g group) String() string {
40034-	var parts []string
40035-	for _, g := range g {
40036-		parts = append(parts, g.String())
40037-	}
40038-	return "{" + strings.Join(parts, ",") + "}"
40039-}
40040-func (r charRange) String() string {
40041-	return "[" + string(r.low) + "-" + string(r.high) + "]"
40042-}
40043-
40044-// Match reports whether the input string matches the glob pattern.
40045-func (g *Glob) Match(input string) bool {
40046-	return match(g.elems, input)
40047-}
40048-
40049-func match(elems []element, input string) (ok bool) {
40050-	var elem interface{}
40051-	for len(elems) > 0 {
40052-		elem, elems = elems[0], elems[1:]
40053-		switch elem := elem.(type) {
40054-		case slash:
40055-			if len(input) == 0 || input[0] != '/' {
40056-				return false
40057-			}
40058-			for input[0] == '/' {
40059-				input = input[1:]
40060-			}
40061-
40062-		case starStar:
40063-			// Special cases:
40064-			//  - **/a matches "a"
40065-			//  - **/ matches everything
40066-			//
40067-			// Note that if ** is followed by anything, it must be '/' (this is
40068-			// enforced by Parse).
40069-			if len(elems) > 0 {
40070-				elems = elems[1:]
40071-			}
40072-
40073-			// A trailing ** matches anything.
40074-			if len(elems) == 0 {
40075-				return true
40076-			}
40077-
40078-			// Backtracking: advance pattern segments until the remaining pattern
40079-			// elements match.
40080-			for len(input) != 0 {
40081-				if match(elems, input) {
40082-					return true
40083-				}
40084-				_, input = split(input)
40085-			}
40086-			return false
40087-
40088-		case literal:
40089-			if !strings.HasPrefix(input, string(elem)) {
40090-				return false
40091-			}
40092-			input = input[len(elem):]
40093-
40094-		case star:
40095-			var segInput string
40096-			segInput, input = split(input)
40097-
40098-			elemEnd := len(elems)
40099-			for i, e := range elems {
40100-				if e == (slash{}) {
40101-					elemEnd = i
40102-					break
40103-				}
40104-			}
40105-			segElems := elems[:elemEnd]
40106-			elems = elems[elemEnd:]
40107-
40108-			// A trailing * matches the entire segment.
40109-			if len(segElems) == 0 {
40110-				break
40111-			}
40112-
40113-			// Backtracking: advance characters until remaining subpattern elements
40114-			// match.
40115-			matched := false
40116-			for i := range segInput {
40117-				if match(segElems, segInput[i:]) {
40118-					matched = true
40119-					break
40120-				}
40121-			}
40122-			if !matched {
40123-				return false
40124-			}
40125-
40126-		case anyChar:
40127-			if len(input) == 0 || input[0] == '/' {
40128-				return false
40129-			}
40130-			input = input[1:]
40131-
40132-		case group:
40133-			// Append remaining pattern elements to each group member looking for a
40134-			// match.
40135-			var branch []element
40136-			for _, m := range elem {
40137-				branch = branch[:0]
40138-				branch = append(branch, m.elems...)
40139-				branch = append(branch, elems...)
40140-				if match(branch, input) {
40141-					return true
40142-				}
40143-			}
40144-			return false
40145-
40146-		case charRange:
40147-			if len(input) == 0 || input[0] == '/' {
40148-				return false
40149-			}
40150-			c, sz := utf8.DecodeRuneInString(input)
40151-			if c < elem.low || c > elem.high {
40152-				return false
40153-			}
40154-			input = input[sz:]
40155-
40156-		default:
40157-			panic(fmt.Sprintf("segment type %T not implemented", elem))
40158-		}
40159-	}
40160-
40161-	return len(input) == 0
40162-}
40163-
40164-// split returns the portion before and after the first slash
40165-// (or sequence of consecutive slashes). If there is no slash
40166-// it returns (input, nil).
40167-func split(input string) (first, rest string) {
40168-	i := strings.IndexByte(input, '/')
40169-	if i < 0 {
40170-		return input, ""
40171-	}
40172-	first = input[:i]
40173-	for j := i; j < len(input); j++ {
40174-		if input[j] != '/' {
40175-			return first, input[j:]
40176-		}
40177-	}
40178-	return first, ""
40179-}
40180diff -urN a/gopls/internal/lsp/glob/glob_test.go b/gopls/internal/lsp/glob/glob_test.go
40181--- a/gopls/internal/lsp/glob/glob_test.go	2000-01-01 00:00:00.000000000 -0000
40182+++ b/gopls/internal/lsp/glob/glob_test.go	1970-01-01 00:00:00.000000000 +0000
40183@@ -1,118 +0,0 @@
40184-// Copyright 2023 The Go Authors. All rights reserved.
40185-// Use of this source code is governed by a BSD-style
40186-// license that can be found in the LICENSE file.
40187-
40188-package glob_test
40189-
40190-import (
40191-	"testing"
40192-
40193-	"golang.org/x/tools/gopls/internal/lsp/glob"
40194-)
40195-
40196-func TestParseErrors(t *testing.T) {
40197-	tests := []string{
40198-		"***",
40199-		"ab{c",
40200-		"[]",
40201-		"[a-]",
40202-		"ab{c{d}",
40203-	}
40204-
40205-	for _, test := range tests {
40206-		_, err := glob.Parse(test)
40207-		if err == nil {
40208-			t.Errorf("Parse(%q) succeeded unexpectedly", test)
40209-		}
40210-	}
40211-}
40212-
40213-func TestMatch(t *testing.T) {
40214-	tests := []struct {
40215-		pattern, input string
40216-		want           bool
40217-	}{
40218-		// Basic cases.
40219-		{"", "", true},
40220-		{"", "a", false},
40221-		{"", "/", false},
40222-		{"abc", "abc", true},
40223-
40224-		// ** behavior
40225-		{"**", "abc", true},
40226-		{"**/abc", "abc", true},
40227-		{"**", "abc/def", true},
40228-		{"{a/**/c,a/**/d}", "a/b/c", true},
40229-		{"{a/**/c,a/**/d}", "a/b/c/d", true},
40230-		{"{a/**/c,a/**/e}", "a/b/c/d", false},
40231-		{"{a/**/c,a/**/e,a/**/d}", "a/b/c/d", true},
40232-		{"{/a/**/c,a/**/e,a/**/d}", "a/b/c/d", true},
40233-		{"{/a/**/c,a/**/e,a/**/d}", "/a/b/c/d", false},
40234-		{"{/a/**/c,a/**/e,a/**/d}", "/a/b/c", true},
40235-		{"{/a/**/e,a/**/e,a/**/d}", "/a/b/c", false},
40236-
40237-		// * and ? behavior
40238-		{"/*", "/a", true},
40239-		{"*", "foo", true},
40240-		{"*o", "foo", true},
40241-		{"*o", "foox", false},
40242-		{"f*o", "foo", true},
40243-		{"f*o", "fo", true},
40244-		{"fo?", "foo", true},
40245-		{"fo?", "fox", true},
40246-		{"fo?", "fooo", false},
40247-		{"fo?", "fo", false},
40248-		{"?", "a", true},
40249-		{"?", "ab", false},
40250-		{"?", "", false},
40251-		{"*?", "", false},
40252-		{"?b", "ab", true},
40253-		{"?c", "ab", false},
40254-
40255-		// {} behavior
40256-		{"ab{c,d}e", "abce", true},
40257-		{"ab{c,d}e", "abde", true},
40258-		{"ab{c,d}e", "abxe", false},
40259-		{"ab{c,d}e", "abe", false},
40260-		{"{a,b}c", "ac", true},
40261-		{"{a,b}c", "bc", true},
40262-		{"{a,b}c", "ab", false},
40263-		{"a{b,c}", "ab", true},
40264-		{"a{b,c}", "ac", true},
40265-		{"a{b,c}", "bc", false},
40266-		{"ab{c{1,2},d}e", "abc1e", true},
40267-		{"ab{c{1,2},d}e", "abde", true},
40268-		{"ab{c{1,2},d}e", "abc1f", false},
40269-		{"ab{c{1,2},d}e", "abce", false},
40270-		{"ab{c[}-~]}d", "abc}d", true},
40271-		{"ab{c[}-~]}d", "abc~d", true},
40272-		{"ab{c[}-~],y}d", "abcxd", false},
40273-		{"ab{c[}-~],y}d", "abyd", true},
40274-		{"ab{c[}-~],y}d", "abd", false},
40275-		{"{a/b/c,d/e/f}", "a/b/c", true},
40276-		{"/ab{/c,d}e", "/ab/ce", true},
40277-		{"/ab{/c,d}e", "/ab/cf", false},
40278-
40279-		// [-] behavior
40280-		{"[a-c]", "a", true},
40281-		{"[a-c]", "b", true},
40282-		{"[a-c]", "c", true},
40283-		{"[a-c]", "d", false},
40284-		{"[a-c]", " ", false},
40285-
40286-		// Realistic examples.
40287-		{"**/*.{ts,js}", "path/to/foo.ts", true},
40288-		{"**/*.{ts,js}", "path/to/foo.js", true},
40289-		{"**/*.{ts,js}", "path/to/foo.go", false},
40290-	}
40291-
40292-	for _, test := range tests {
40293-		g, err := glob.Parse(test.pattern)
40294-		if err != nil {
40295-			t.Fatalf("New(%q) failed unexpectedly: %v", test.pattern, err)
40296-		}
40297-		if got := g.Match(test.input); got != test.want {
40298-			t.Errorf("New(%q).Match(%q) = %t, want %t", test.pattern, test.input, got, test.want)
40299-		}
40300-	}
40301-}
40302diff -urN a/gopls/internal/lsp/helper/helper.go b/gopls/internal/lsp/helper/helper.go
40303--- a/gopls/internal/lsp/helper/helper.go	2000-01-01 00:00:00.000000000 -0000
40304+++ b/gopls/internal/lsp/helper/helper.go	1970-01-01 00:00:00.000000000 +0000
40305@@ -1,264 +0,0 @@
40306-// Copyright 2020 The Go Authors. All rights reserved.
40307-// Use of this source code is governed by a BSD-style
40308-// license that can be found in the LICENSE file.
40309-
40310-// The helper command generates the declaration of the concrete
40311-// 'server' type that implements the abstract Server interface defined
40312-// in protocol/tsserver.go (which is itself generated from the LSP
40313-// protocol).
40314-//
40315-// To run, invoke "go generate" in the parent (lsp) directory.
40316-//
40317-// TODO(adonovan): merge this into the main LSP generator.
40318-package main
40319-
40320-import (
40321-	"bytes"
40322-	"flag"
40323-	"fmt"
40324-	"go/ast"
40325-	"go/format"
40326-	"go/parser"
40327-	"go/token"
40328-	"log"
40329-	"os"
40330-	"sort"
40331-	"strings"
40332-	"text/template"
40333-)
40334-
40335-var (
40336-	typ = flag.String("t", "Server", "generate code for this type")
40337-	def = flag.String("d", "", "the file the type is defined in") // this relies on punning
40338-	use = flag.String("u", "", "look for uses in this package")
40339-	out = flag.String("o", "", "where to write the generated file")
40340-)
40341-
40342-func main() {
40343-	log.SetFlags(log.Lshortfile)
40344-	flag.Parse()
40345-	if *typ == "" || *def == "" || *use == "" || *out == "" {
40346-		flag.PrintDefaults()
40347-		os.Exit(1)
40348-	}
40349-	// read the type definition and see what methods we're looking for
40350-	doTypes()
40351-
40352-	// parse the package and see which methods are defined
40353-	doUses()
40354-
40355-	output()
40356-}
40357-
40358-// replace "\\\n" with nothing before using
40359-var tmpl = `// Copyright 2021 The Go Authors. All rights reserved.
40360-// Use of this source code is governed by a BSD-style
40361-// license that can be found in the LICENSE file.
40362-
40363-package lsp
40364-
40365-// code generated by helper. DO NOT EDIT.
40366-
40367-import (
40368-	"context"
40369-
40370-	"golang.org/x/tools/gopls/internal/lsp/protocol"
40371-)
40372-
40373-{{range $key, $v := .Stuff}}
40374-func (s *{{$.Type}}) {{$v.Name}}({{.Param}}) {{.Result}} {
40375-	{{if ne .Found ""}} return s.{{.Internal}}({{.Invoke}})\
40376-	{{else}}return {{if lt 1 (len .Results)}}nil, {{end}}notImplemented("{{.Name}}"){{end}}
40377-}
40378-{{end}}
40379-`
40380-
40381-func output() {
40382-	// put in empty param names as needed
40383-	for _, t := range types {
40384-		if t.paramnames == nil {
40385-			t.paramnames = make([]string, len(t.paramtypes))
40386-		}
40387-		for i, p := range t.paramtypes {
40388-			cm := ""
40389-			if i > 0 {
40390-				cm = ", "
40391-			}
40392-			t.Param += fmt.Sprintf("%s%s %s", cm, t.paramnames[i], p)
40393-			this := t.paramnames[i]
40394-			if this == "_" {
40395-				this = "nil"
40396-			}
40397-			t.Invoke += fmt.Sprintf("%s%s", cm, this)
40398-		}
40399-		if len(t.Results) > 1 {
40400-			t.Result = "("
40401-		}
40402-		for i, r := range t.Results {
40403-			cm := ""
40404-			if i > 0 {
40405-				cm = ", "
40406-			}
40407-			t.Result += fmt.Sprintf("%s%s", cm, r)
40408-		}
40409-		if len(t.Results) > 1 {
40410-			t.Result += ")"
40411-		}
40412-	}
40413-
40414-	fd, err := os.Create(*out)
40415-	if err != nil {
40416-		log.Fatal(err)
40417-	}
40418-	t, err := template.New("foo").Parse(tmpl)
40419-	if err != nil {
40420-		log.Fatal(err)
40421-	}
40422-	type par struct {
40423-		Type  string
40424-		Stuff []*Function
40425-	}
40426-	p := par{*typ, types}
40427-	if false { // debugging the template
40428-		t.Execute(os.Stderr, &p)
40429-	}
40430-	buf := bytes.NewBuffer(nil)
40431-	err = t.Execute(buf, &p)
40432-	if err != nil {
40433-		log.Fatal(err)
40434-	}
40435-	ans, err := format.Source(bytes.Replace(buf.Bytes(), []byte("\\\n"), []byte{}, -1))
40436-	if err != nil {
40437-		log.Fatal(err)
40438-	}
40439-	fd.Write(ans)
40440-}
40441-
40442-func doUses() {
40443-	fset := token.NewFileSet()
40444-	pkgs, err := parser.ParseDir(fset, *use, nil, 0)
40445-	if err != nil {
40446-		log.Fatalf("%q:%v", *use, err)
40447-	}
40448-	pkg := pkgs["lsp"] // CHECK
40449-	files := pkg.Files
40450-	for fname, f := range files {
40451-		for _, d := range f.Decls {
40452-			fd, ok := d.(*ast.FuncDecl)
40453-			if !ok {
40454-				continue
40455-			}
40456-			nm := fd.Name.String()
40457-			if ast.IsExported(nm) {
40458-				// we're looking for things like didChange
40459-				continue
40460-			}
40461-			if fx, ok := byname[nm]; ok {
40462-				if fx.Found != "" {
40463-					log.Fatalf("found %s in %s and %s", fx.Internal, fx.Found, fname)
40464-				}
40465-				fx.Found = fname
40466-				// and the Paramnames
40467-				ft := fd.Type
40468-				for _, f := range ft.Params.List {
40469-					nm := ""
40470-					if len(f.Names) > 0 {
40471-						nm = f.Names[0].String()
40472-						if nm == "_" {
40473-							nm = "_gen"
40474-						}
40475-					}
40476-					fx.paramnames = append(fx.paramnames, nm)
40477-				}
40478-			}
40479-		}
40480-	}
40481-	if false {
40482-		for i, f := range types {
40483-			log.Printf("%d %s %s", i, f.Internal, f.Found)
40484-		}
40485-	}
40486-}
40487-
40488-type Function struct {
40489-	Name       string
40490-	Internal   string // first letter lower case
40491-	paramtypes []string
40492-	paramnames []string
40493-	Results    []string
40494-	Param      string
40495-	Result     string // do it in code, easier than in a template
40496-	Invoke     string
40497-	Found      string // file it was found in
40498-}
40499-
40500-var types []*Function
40501-var byname = map[string]*Function{} // internal names
40502-
40503-func doTypes() {
40504-	fset := token.NewFileSet()
40505-	f, err := parser.ParseFile(fset, *def, nil, 0)
40506-	if err != nil {
40507-		log.Fatal(err)
40508-	}
40509-	fd, err := os.Create("/tmp/ast")
40510-	if err != nil {
40511-		log.Fatal(err)
40512-	}
40513-	ast.Fprint(fd, fset, f, ast.NotNilFilter)
40514-	ast.Inspect(f, inter)
40515-	sort.Slice(types, func(i, j int) bool { return types[i].Name < types[j].Name })
40516-	if false {
40517-		for i, f := range types {
40518-			log.Printf("%d %s(%v) %v", i, f.Name, f.paramtypes, f.Results)
40519-		}
40520-	}
40521-}
40522-
40523-func inter(n ast.Node) bool {
40524-	x, ok := n.(*ast.TypeSpec)
40525-	if !ok || x.Name.Name != *typ {
40526-		return true
40527-	}
40528-	m := x.Type.(*ast.InterfaceType).Methods.List
40529-	for _, fld := range m {
40530-		fn := fld.Type.(*ast.FuncType)
40531-		p := fn.Params.List
40532-		r := fn.Results.List
40533-		fx := &Function{
40534-			Name: fld.Names[0].String(),
40535-		}
40536-		fx.Internal = strings.ToLower(fx.Name[:1]) + fx.Name[1:]
40537-		for _, f := range p {
40538-			fx.paramtypes = append(fx.paramtypes, whatis(f.Type))
40539-		}
40540-		for _, f := range r {
40541-			fx.Results = append(fx.Results, whatis(f.Type))
40542-		}
40543-		types = append(types, fx)
40544-		byname[fx.Internal] = fx
40545-	}
40546-	return false
40547-}
40548-
40549-func whatis(x ast.Expr) string {
40550-	switch n := x.(type) {
40551-	case *ast.SelectorExpr:
40552-		return whatis(n.X) + "." + n.Sel.String()
40553-	case *ast.StarExpr:
40554-		return "*" + whatis(n.X)
40555-	case *ast.Ident:
40556-		if ast.IsExported(n.Name) {
40557-			// these are from package protocol
40558-			return "protocol." + n.Name
40559-		}
40560-		return n.Name
40561-	case *ast.ArrayType:
40562-		return "[]" + whatis(n.Elt)
40563-	case *ast.InterfaceType:
40564-		return "interface{}"
40565-	default:
40566-		log.Fatalf("Fatal %T", x)
40567-		return fmt.Sprintf("%T", x)
40568-	}
40569-}
40570diff -urN a/gopls/internal/lsp/helper/README.md b/gopls/internal/lsp/helper/README.md
40571--- a/gopls/internal/lsp/helper/README.md	2000-01-01 00:00:00.000000000 -0000
40572+++ b/gopls/internal/lsp/helper/README.md	1970-01-01 00:00:00.000000000 +0000
40573@@ -1,35 +0,0 @@
40574-# Generate server_gen.go
40575-
40576-`helper` generates the file `../server_gen.go` (in package
40577-`internal/lsp`) which contains stub declarations of server methods.
40578-
40579-To invoke it, run `go generate` in the `gopls/internal/lsp` directory.
40580-
40581-It is derived from `gopls/internal/lsp/protocol/tsserver.go`, which
40582-itself is generated from the protocol downloaded from VSCode, so be
40583-sure to run `go generate` in the protocol first. Or run `go generate
40584-./...` twice in the gopls directory.
40585-
40586-It decides what stubs are needed and their signatures
40587-by looking at the `Server` interface (`-t` flag). These all look somewhat like
40588-`Resolve(context.Context, *CompletionItem) (*CompletionItem, error)`.
40589-
40590-It then parses the `lsp` directory (`-u` flag) to see if there is a corresponding
40591-implementation function (which in this case would be named `resolve`). If so
40592-it discovers the parameter names needed, and generates (in `server_gen.go`) code
40593-like
40594-
40595-``` go
40596-func (s *Server) resolve(ctx context.Context, params *protocol.CompletionItem) (*protocol.CompletionItem, error) {
40597-    return s.resolve(ctx, params)
40598-}
40599-```
40600-
40601-If `resolve` is not defined (and it is not), then the body of the generated function is
40602-
40603-```go
40604-    return nil, notImplemented("resolve")
40605-```
40606-
40607-So to add a capability currently not implemented, just define it somewhere in `lsp`.
40608-In this case, just define `func (s *Server) resolve(...)` and re-generate `server_gen.go`.
40609diff -urN a/gopls/internal/lsp/highlight.go b/gopls/internal/lsp/highlight.go
40610--- a/gopls/internal/lsp/highlight.go	2000-01-01 00:00:00.000000000 -0000
40611+++ b/gopls/internal/lsp/highlight.go	1970-01-01 00:00:00.000000000 +0000
40612@@ -1,45 +0,0 @@
40613-// Copyright 2019 The Go Authors. All rights reserved.
40614-// Use of this source code is governed by a BSD-style
40615-// license that can be found in the LICENSE file.
40616-
40617-package lsp
40618-
40619-import (
40620-	"context"
40621-
40622-	"golang.org/x/tools/internal/event"
40623-	"golang.org/x/tools/internal/event/tag"
40624-	"golang.org/x/tools/gopls/internal/lsp/protocol"
40625-	"golang.org/x/tools/gopls/internal/lsp/source"
40626-	"golang.org/x/tools/gopls/internal/lsp/template"
40627-)
40628-
40629-func (s *Server) documentHighlight(ctx context.Context, params *protocol.DocumentHighlightParams) ([]protocol.DocumentHighlight, error) {
40630-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.Go)
40631-	defer release()
40632-	if !ok {
40633-		return nil, err
40634-	}
40635-
40636-	if snapshot.View().FileKind(fh) == source.Tmpl {
40637-		return template.Highlight(ctx, snapshot, fh, params.Position)
40638-	}
40639-
40640-	rngs, err := source.Highlight(ctx, snapshot, fh, params.Position)
40641-	if err != nil {
40642-		event.Error(ctx, "no highlight", err, tag.URI.Of(params.TextDocument.URI))
40643-	}
40644-	return toProtocolHighlight(rngs), nil
40645-}
40646-
40647-func toProtocolHighlight(rngs []protocol.Range) []protocol.DocumentHighlight {
40648-	result := make([]protocol.DocumentHighlight, 0, len(rngs))
40649-	kind := protocol.Text
40650-	for _, rng := range rngs {
40651-		result = append(result, protocol.DocumentHighlight{
40652-			Kind:  kind,
40653-			Range: rng,
40654-		})
40655-	}
40656-	return result
40657-}
40658diff -urN a/gopls/internal/lsp/hover.go b/gopls/internal/lsp/hover.go
40659--- a/gopls/internal/lsp/hover.go	2000-01-01 00:00:00.000000000 -0000
40660+++ b/gopls/internal/lsp/hover.go	1970-01-01 00:00:00.000000000 +0000
40661@@ -1,34 +0,0 @@
40662-// Copyright 2019 The Go Authors. All rights reserved.
40663-// Use of this source code is governed by a BSD-style
40664-// license that can be found in the LICENSE file.
40665-
40666-package lsp
40667-
40668-import (
40669-	"context"
40670-
40671-	"golang.org/x/tools/gopls/internal/lsp/mod"
40672-	"golang.org/x/tools/gopls/internal/lsp/protocol"
40673-	"golang.org/x/tools/gopls/internal/lsp/source"
40674-	"golang.org/x/tools/gopls/internal/lsp/template"
40675-	"golang.org/x/tools/gopls/internal/lsp/work"
40676-)
40677-
40678-func (s *Server) hover(ctx context.Context, params *protocol.HoverParams) (*protocol.Hover, error) {
40679-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.UnknownKind)
40680-	defer release()
40681-	if !ok {
40682-		return nil, err
40683-	}
40684-	switch snapshot.View().FileKind(fh) {
40685-	case source.Mod:
40686-		return mod.Hover(ctx, snapshot, fh, params.Position)
40687-	case source.Go:
40688-		return source.Hover(ctx, snapshot, fh, params.Position)
40689-	case source.Tmpl:
40690-		return template.Hover(ctx, snapshot, fh, params.Position)
40691-	case source.Work:
40692-		return work.Hover(ctx, snapshot, fh, params.Position)
40693-	}
40694-	return nil, nil
40695-}
40696diff -urN a/gopls/internal/lsp/implementation.go b/gopls/internal/lsp/implementation.go
40697--- a/gopls/internal/lsp/implementation.go	2000-01-01 00:00:00.000000000 -0000
40698+++ b/gopls/internal/lsp/implementation.go	1970-01-01 00:00:00.000000000 +0000
40699@@ -1,21 +0,0 @@
40700-// Copyright 2019 The Go Authors. All rights reserved.
40701-// Use of this source code is governed by a BSD-style
40702-// license that can be found in the LICENSE file.
40703-
40704-package lsp
40705-
40706-import (
40707-	"context"
40708-
40709-	"golang.org/x/tools/gopls/internal/lsp/protocol"
40710-	"golang.org/x/tools/gopls/internal/lsp/source"
40711-)
40712-
40713-func (s *Server) implementation(ctx context.Context, params *protocol.ImplementationParams) ([]protocol.Location, error) {
40714-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.Go)
40715-	defer release()
40716-	if !ok {
40717-		return nil, err
40718-	}
40719-	return source.Implementation(ctx, snapshot, fh, params.Position)
40720-}
40721diff -urN a/gopls/internal/lsp/inlay_hint.go b/gopls/internal/lsp/inlay_hint.go
40722--- a/gopls/internal/lsp/inlay_hint.go	2000-01-01 00:00:00.000000000 -0000
40723+++ b/gopls/internal/lsp/inlay_hint.go	1970-01-01 00:00:00.000000000 +0000
40724@@ -1,21 +0,0 @@
40725-// Copyright 2022 The Go Authors. All rights reserved.
40726-// Use of this source code is governed by a BSD-style
40727-// license that can be found in the LICENSE file.
40728-
40729-package lsp
40730-
40731-import (
40732-	"context"
40733-
40734-	"golang.org/x/tools/gopls/internal/lsp/protocol"
40735-	"golang.org/x/tools/gopls/internal/lsp/source"
40736-)
40737-
40738-func (s *Server) inlayHint(ctx context.Context, params *protocol.InlayHintParams) ([]protocol.InlayHint, error) {
40739-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.Go)
40740-	defer release()
40741-	if !ok {
40742-		return nil, err
40743-	}
40744-	return source.InlayHint(ctx, snapshot, fh, params.Range)
40745-}
40746diff -urN a/gopls/internal/lsp/link.go b/gopls/internal/lsp/link.go
40747--- a/gopls/internal/lsp/link.go	2000-01-01 00:00:00.000000000 -0000
40748+++ b/gopls/internal/lsp/link.go	1970-01-01 00:00:00.000000000 +0000
40749@@ -1,278 +0,0 @@
40750-// Copyright 2018 The Go Authors. All rights reserved.
40751-// Use of this source code is governed by a BSD-style
40752-// license that can be found in the LICENSE file.
40753-
40754-package lsp
40755-
40756-import (
40757-	"bytes"
40758-	"context"
40759-	"fmt"
40760-	"go/ast"
40761-	"go/token"
40762-	"net/url"
40763-	"regexp"
40764-	"strings"
40765-	"sync"
40766-
40767-	"golang.org/x/mod/modfile"
40768-	"golang.org/x/tools/gopls/internal/lsp/protocol"
40769-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
40770-	"golang.org/x/tools/gopls/internal/lsp/source"
40771-	"golang.org/x/tools/internal/event"
40772-	"golang.org/x/tools/internal/event/tag"
40773-)
40774-
40775-func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLinkParams) (links []protocol.DocumentLink, err error) {
40776-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.UnknownKind)
40777-	defer release()
40778-	if !ok {
40779-		return nil, err
40780-	}
40781-	switch snapshot.View().FileKind(fh) {
40782-	case source.Mod:
40783-		links, err = modLinks(ctx, snapshot, fh)
40784-	case source.Go:
40785-		links, err = goLinks(ctx, snapshot, fh)
40786-	}
40787-	// Don't return errors for document links.
40788-	if err != nil {
40789-		event.Error(ctx, "failed to compute document links", err, tag.URI.Of(fh.URI()))
40790-		return nil, nil
40791-	}
40792-	return links, nil
40793-}
40794-
40795-func modLinks(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) ([]protocol.DocumentLink, error) {
40796-	pm, err := snapshot.ParseMod(ctx, fh)
40797-	if err != nil {
40798-		return nil, err
40799-	}
40800-
40801-	var links []protocol.DocumentLink
40802-	for _, req := range pm.File.Require {
40803-		if req.Syntax == nil {
40804-			continue
40805-		}
40806-		// See golang/go#36998: don't link to modules matching GOPRIVATE.
40807-		if snapshot.View().IsGoPrivatePath(req.Mod.Path) {
40808-			continue
40809-		}
40810-		dep := []byte(req.Mod.Path)
40811-		start, end := req.Syntax.Start.Byte, req.Syntax.End.Byte
40812-		i := bytes.Index(pm.Mapper.Content[start:end], dep)
40813-		if i == -1 {
40814-			continue
40815-		}
40816-		// Shift the start position to the location of the
40817-		// dependency within the require statement.
40818-		target := source.BuildLink(snapshot.View().Options().LinkTarget, "mod/"+req.Mod.String(), "")
40819-		l, err := toProtocolLink(pm.Mapper, target, start+i, start+i+len(dep))
40820-		if err != nil {
40821-			return nil, err
40822-		}
40823-		links = append(links, l)
40824-	}
40825-	// TODO(ridersofrohan): handle links for replace and exclude directives.
40826-	if syntax := pm.File.Syntax; syntax == nil {
40827-		return links, nil
40828-	}
40829-
40830-	// Get all the links that are contained in the comments of the file.
40831-	urlRegexp := snapshot.View().Options().URLRegexp
40832-	for _, expr := range pm.File.Syntax.Stmt {
40833-		comments := expr.Comment()
40834-		if comments == nil {
40835-			continue
40836-		}
40837-		for _, section := range [][]modfile.Comment{comments.Before, comments.Suffix, comments.After} {
40838-			for _, comment := range section {
40839-				l, err := findLinksInString(urlRegexp, comment.Token, comment.Start.Byte, pm.Mapper)
40840-				if err != nil {
40841-					return nil, err
40842-				}
40843-				links = append(links, l...)
40844-			}
40845-		}
40846-	}
40847-	return links, nil
40848-}
40849-
40850-// goLinks returns the set of hyperlink annotations for the specified Go file.
40851-func goLinks(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) ([]protocol.DocumentLink, error) {
40852-	view := snapshot.View()
40853-
40854-	pgf, err := snapshot.ParseGo(ctx, fh, source.ParseFull)
40855-	if err != nil {
40856-		return nil, err
40857-	}
40858-
40859-	var links []protocol.DocumentLink
40860-
40861-	// Create links for import specs.
40862-	if view.Options().ImportShortcut.ShowLinks() {
40863-
40864-		// If links are to pkg.go.dev, append module version suffixes.
40865-		// This requires the import map from the package metadata. Ignore errors.
40866-		var depsByImpPath map[source.ImportPath]source.PackageID
40867-		if strings.ToLower(view.Options().LinkTarget) == "pkg.go.dev" {
40868-			if metas, _ := snapshot.MetadataForFile(ctx, fh.URI()); len(metas) > 0 {
40869-				depsByImpPath = metas[0].DepsByImpPath // 0 => narrowest package
40870-			}
40871-		}
40872-
40873-		for _, imp := range pgf.File.Imports {
40874-			importPath := source.UnquoteImportPath(imp)
40875-			if importPath == "" {
40876-				continue // bad import
40877-			}
40878-			// See golang/go#36998: don't link to modules matching GOPRIVATE.
40879-			if view.IsGoPrivatePath(string(importPath)) {
40880-				continue
40881-			}
40882-
40883-			urlPath := string(importPath)
40884-
40885-			// For pkg.go.dev, append module version suffix to package import path.
40886-			if m := snapshot.Metadata(depsByImpPath[importPath]); m != nil && m.Module != nil && m.Module.Path != "" && m.Module.Version != "" {
40887-				urlPath = strings.Replace(urlPath, m.Module.Path, m.Module.Path+"@"+m.Module.Version, 1)
40888-			}
40889-
40890-			start, end, err := safetoken.Offsets(pgf.Tok, imp.Path.Pos(), imp.Path.End())
40891-			if err != nil {
40892-				return nil, err
40893-			}
40894-			targetURL := source.BuildLink(view.Options().LinkTarget, urlPath, "")
40895-			// Account for the quotation marks in the positions.
40896-			l, err := toProtocolLink(pgf.Mapper, targetURL, start+len(`"`), end-len(`"`))
40897-			if err != nil {
40898-				return nil, err
40899-			}
40900-			links = append(links, l)
40901-		}
40902-	}
40903-
40904-	urlRegexp := snapshot.View().Options().URLRegexp
40905-
40906-	// Gather links found in string literals.
40907-	var str []*ast.BasicLit
40908-	ast.Inspect(pgf.File, func(node ast.Node) bool {
40909-		switch n := node.(type) {
40910-		case *ast.ImportSpec:
40911-			return false // don't process import strings again
40912-		case *ast.BasicLit:
40913-			if n.Kind == token.STRING {
40914-				str = append(str, n)
40915-			}
40916-		}
40917-		return true
40918-	})
40919-	for _, s := range str {
40920-		strOffset, err := safetoken.Offset(pgf.Tok, s.Pos())
40921-		if err != nil {
40922-			return nil, err
40923-		}
40924-		l, err := findLinksInString(urlRegexp, s.Value, strOffset, pgf.Mapper)
40925-		if err != nil {
40926-			return nil, err
40927-		}
40928-		links = append(links, l...)
40929-	}
40930-
40931-	// Gather links found in comments.
40932-	for _, commentGroup := range pgf.File.Comments {
40933-		for _, comment := range commentGroup.List {
40934-			commentOffset, err := safetoken.Offset(pgf.Tok, comment.Pos())
40935-			if err != nil {
40936-				return nil, err
40937-			}
40938-			l, err := findLinksInString(urlRegexp, comment.Text, commentOffset, pgf.Mapper)
40939-			if err != nil {
40940-				return nil, err
40941-			}
40942-			links = append(links, l...)
40943-		}
40944-	}
40945-
40946-	return links, nil
40947-}
40948-
40949-// acceptedSchemes controls the schemes that URLs must have to be shown to the
40950-// user. Other schemes can't be opened by LSP clients, so linkifying them is
40951-// distracting. See golang/go#43990.
40952-var acceptedSchemes = map[string]bool{
40953-	"http":  true,
40954-	"https": true,
40955-}
40956-
40957-// urlRegexp is the user-supplied regular expression to match URL.
40958-// srcOffset is the start offset of 'src' within m's file.
40959-func findLinksInString(urlRegexp *regexp.Regexp, src string, srcOffset int, m *protocol.Mapper) ([]protocol.DocumentLink, error) {
40960-	var links []protocol.DocumentLink
40961-	for _, index := range urlRegexp.FindAllIndex([]byte(src), -1) {
40962-		start, end := index[0], index[1]
40963-		link := src[start:end]
40964-		linkURL, err := url.Parse(link)
40965-		// Fallback: Linkify IP addresses as suggested in golang/go#18824.
40966-		if err != nil {
40967-			linkURL, err = url.Parse("//" + link)
40968-			// Not all potential links will be valid, so don't return this error.
40969-			if err != nil {
40970-				continue
40971-			}
40972-		}
40973-		// If the URL has no scheme, use https.
40974-		if linkURL.Scheme == "" {
40975-			linkURL.Scheme = "https"
40976-		}
40977-		if !acceptedSchemes[linkURL.Scheme] {
40978-			continue
40979-		}
40980-
40981-		l, err := toProtocolLink(m, linkURL.String(), srcOffset+start, srcOffset+end)
40982-		if err != nil {
40983-			return nil, err
40984-		}
40985-		links = append(links, l)
40986-	}
40987-	// Handle golang/go#1234-style links.
40988-	r := getIssueRegexp()
40989-	for _, index := range r.FindAllIndex([]byte(src), -1) {
40990-		start, end := index[0], index[1]
40991-		matches := r.FindStringSubmatch(src)
40992-		if len(matches) < 4 {
40993-			continue
40994-		}
40995-		org, repo, number := matches[1], matches[2], matches[3]
40996-		targetURL := fmt.Sprintf("https://github.com/%s/%s/issues/%s", org, repo, number)
40997-		l, err := toProtocolLink(m, targetURL, srcOffset+start, srcOffset+end)
40998-		if err != nil {
40999-			return nil, err
41000-		}
41001-		links = append(links, l)
41002-	}
41003-	return links, nil
41004-}
41005-
41006-func getIssueRegexp() *regexp.Regexp {
41007-	once.Do(func() {
41008-		issueRegexp = regexp.MustCompile(`(\w+)/([\w-]+)#([0-9]+)`)
41009-	})
41010-	return issueRegexp
41011-}
41012-
41013-var (
41014-	once        sync.Once
41015-	issueRegexp *regexp.Regexp
41016-)
41017-
41018-func toProtocolLink(m *protocol.Mapper, targetURL string, start, end int) (protocol.DocumentLink, error) {
41019-	rng, err := m.OffsetRange(start, end)
41020-	if err != nil {
41021-		return protocol.DocumentLink{}, err
41022-	}
41023-	return protocol.DocumentLink{
41024-		Range:  rng,
41025-		Target: targetURL,
41026-	}, nil
41027-}
41028diff -urN a/gopls/internal/lsp/lsprpc/autostart_default.go b/gopls/internal/lsp/lsprpc/autostart_default.go
41029--- a/gopls/internal/lsp/lsprpc/autostart_default.go	2000-01-01 00:00:00.000000000 -0000
41030+++ b/gopls/internal/lsp/lsprpc/autostart_default.go	1970-01-01 00:00:00.000000000 +0000
41031@@ -1,39 +0,0 @@
41032-// Copyright 2020 The Go Authors. All rights reserved.
41033-// Use of this source code is governed by a BSD-style
41034-// license that can be found in the LICENSE file.
41035-
41036-package lsprpc
41037-
41038-import (
41039-	"fmt"
41040-
41041-	exec "golang.org/x/sys/execabs"
41042-)
41043-
41044-var (
41045-	daemonize             = func(*exec.Cmd) {}
41046-	autoNetworkAddress    = autoNetworkAddressDefault
41047-	verifyRemoteOwnership = verifyRemoteOwnershipDefault
41048-)
41049-
41050-func runRemote(cmd *exec.Cmd) error {
41051-	daemonize(cmd)
41052-	if err := cmd.Start(); err != nil {
41053-		return fmt.Errorf("starting remote gopls: %w", err)
41054-	}
41055-	return nil
41056-}
41057-
41058-// autoNetworkAddressDefault returns the default network and address for the
41059-// automatically-started gopls remote. See autostart_posix.go for more
41060-// information.
41061-func autoNetworkAddressDefault(goplsPath, id string) (network string, address string) {
41062-	if id != "" {
41063-		panic("identified remotes are not supported on windows")
41064-	}
41065-	return "tcp", "localhost:37374"
41066-}
41067-
41068-func verifyRemoteOwnershipDefault(network, address string) (bool, error) {
41069-	return true, nil
41070-}
41071diff -urN a/gopls/internal/lsp/lsprpc/autostart_posix.go b/gopls/internal/lsp/lsprpc/autostart_posix.go
41072--- a/gopls/internal/lsp/lsprpc/autostart_posix.go	2000-01-01 00:00:00.000000000 -0000
41073+++ b/gopls/internal/lsp/lsprpc/autostart_posix.go	1970-01-01 00:00:00.000000000 +0000
41074@@ -1,97 +0,0 @@
41075-// Copyright 2020 The Go Authors. All rights reserved.
41076-// Use of this source code is governed by a BSD-style
41077-// license that can be found in the LICENSE file.
41078-
41079-//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
41080-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
41081-
41082-package lsprpc
41083-
41084-import (
41085-	"crypto/sha256"
41086-	"errors"
41087-	"fmt"
41088-	"log"
41089-	"os"
41090-	"os/user"
41091-	"path/filepath"
41092-	"strconv"
41093-	"syscall"
41094-
41095-	exec "golang.org/x/sys/execabs"
41096-)
41097-
41098-func init() {
41099-	daemonize = daemonizePosix
41100-	autoNetworkAddress = autoNetworkAddressPosix
41101-	verifyRemoteOwnership = verifyRemoteOwnershipPosix
41102-}
41103-
41104-func daemonizePosix(cmd *exec.Cmd) {
41105-	cmd.SysProcAttr = &syscall.SysProcAttr{
41106-		Setsid: true,
41107-	}
41108-}
41109-
41110-// autoNetworkAddressPosix resolves an id on the 'auto' pseduo-network to a
41111-// real network and address. On unix, this uses unix domain sockets.
41112-func autoNetworkAddressPosix(goplsPath, id string) (network string, address string) {
41113-	// Especially when doing local development or testing, it's important that
41114-	// the remote gopls instance we connect to is running the same binary as our
41115-	// forwarder. So we encode a short hash of the binary path into the daemon
41116-	// socket name. If possible, we also include the buildid in this hash, to
41117-	// account for long-running processes where the binary has been subsequently
41118-	// rebuilt.
41119-	h := sha256.New()
41120-	cmd := exec.Command("go", "tool", "buildid", goplsPath)
41121-	cmd.Stdout = h
41122-	var pathHash []byte
41123-	if err := cmd.Run(); err == nil {
41124-		pathHash = h.Sum(nil)
41125-	} else {
41126-		log.Printf("error getting current buildid: %v", err)
41127-		sum := sha256.Sum256([]byte(goplsPath))
41128-		pathHash = sum[:]
41129-	}
41130-	shortHash := fmt.Sprintf("%x", pathHash)[:6]
41131-	user := os.Getenv("USER")
41132-	if user == "" {
41133-		user = "shared"
41134-	}
41135-	basename := filepath.Base(goplsPath)
41136-	idComponent := ""
41137-	if id != "" {
41138-		idComponent = "-" + id
41139-	}
41140-	runtimeDir := os.TempDir()
41141-	if xdg := os.Getenv("XDG_RUNTIME_DIR"); xdg != "" {
41142-		runtimeDir = xdg
41143-	}
41144-	return "unix", filepath.Join(runtimeDir, fmt.Sprintf("%s-%s-daemon.%s%s", basename, shortHash, user, idComponent))
41145-}
41146-
41147-func verifyRemoteOwnershipPosix(network, address string) (bool, error) {
41148-	if network != "unix" {
41149-		return true, nil
41150-	}
41151-	fi, err := os.Stat(address)
41152-	if err != nil {
41153-		if os.IsNotExist(err) {
41154-			return true, nil
41155-		}
41156-		return false, fmt.Errorf("checking socket owner: %w", err)
41157-	}
41158-	stat, ok := fi.Sys().(*syscall.Stat_t)
41159-	if !ok {
41160-		return false, errors.New("fi.Sys() is not a Stat_t")
41161-	}
41162-	user, err := user.Current()
41163-	if err != nil {
41164-		return false, fmt.Errorf("checking current user: %w", err)
41165-	}
41166-	uid, err := strconv.ParseUint(user.Uid, 10, 32)
41167-	if err != nil {
41168-		return false, fmt.Errorf("parsing current UID: %w", err)
41169-	}
41170-	return stat.Uid == uint32(uid), nil
41171-}
41172diff -urN a/gopls/internal/lsp/lsprpc/binder.go b/gopls/internal/lsp/lsprpc/binder.go
41173--- a/gopls/internal/lsp/lsprpc/binder.go	2000-01-01 00:00:00.000000000 -0000
41174+++ b/gopls/internal/lsp/lsprpc/binder.go	1970-01-01 00:00:00.000000000 +0000
41175@@ -1,148 +0,0 @@
41176-// Copyright 2021 The Go Authors. All rights reserved.
41177-// Use of this source code is governed by a BSD-style
41178-// license that can be found in the LICENSE file.
41179-
41180-package lsprpc
41181-
41182-import (
41183-	"context"
41184-	"encoding/json"
41185-	"fmt"
41186-
41187-	"golang.org/x/tools/gopls/internal/lsp/protocol"
41188-	"golang.org/x/tools/internal/event"
41189-	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
41190-	"golang.org/x/tools/internal/xcontext"
41191-)
41192-
41193-// The BinderFunc type adapts a bind function to implement the jsonrpc2.Binder
41194-// interface.
41195-type BinderFunc func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions
41196-
41197-func (f BinderFunc) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
41198-	return f(ctx, conn)
41199-}
41200-
41201-// Middleware defines a transformation of jsonrpc2 Binders, that may be
41202-// composed to build jsonrpc2 servers.
41203-type Middleware func(jsonrpc2_v2.Binder) jsonrpc2_v2.Binder
41204-
41205-// A ServerFunc is used to construct an LSP server for a given client.
41206-type ServerFunc func(context.Context, protocol.ClientCloser) protocol.Server
41207-
41208-// ServerBinder binds incoming connections to a new server.
41209-type ServerBinder struct {
41210-	newServer ServerFunc
41211-}
41212-
41213-func NewServerBinder(newServer ServerFunc) *ServerBinder {
41214-	return &ServerBinder{newServer: newServer}
41215-}
41216-
41217-func (b *ServerBinder) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
41218-	client := protocol.ClientDispatcherV2(conn)
41219-	server := b.newServer(ctx, client)
41220-	serverHandler := protocol.ServerHandlerV2(server)
41221-	// Wrap the server handler to inject the client into each request context, so
41222-	// that log events are reflected back to the client.
41223-	wrapped := jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
41224-		ctx = protocol.WithClient(ctx, client)
41225-		return serverHandler.Handle(ctx, req)
41226-	})
41227-	preempter := &canceler{
41228-		conn: conn,
41229-	}
41230-	return jsonrpc2_v2.ConnectionOptions{
41231-		Handler:   wrapped,
41232-		Preempter: preempter,
41233-	}
41234-}
41235-
41236-type canceler struct {
41237-	conn *jsonrpc2_v2.Connection
41238-}
41239-
41240-func (c *canceler) Preempt(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
41241-	if req.Method != "$/cancelRequest" {
41242-		return nil, jsonrpc2_v2.ErrNotHandled
41243-	}
41244-	var params protocol.CancelParams
41245-	if err := json.Unmarshal(req.Params, &params); err != nil {
41246-		return nil, fmt.Errorf("%w: %v", jsonrpc2_v2.ErrParse, err)
41247-	}
41248-	var id jsonrpc2_v2.ID
41249-	switch raw := params.ID.(type) {
41250-	case float64:
41251-		id = jsonrpc2_v2.Int64ID(int64(raw))
41252-	case string:
41253-		id = jsonrpc2_v2.StringID(raw)
41254-	default:
41255-		return nil, fmt.Errorf("%w: invalid ID type %T", jsonrpc2_v2.ErrParse, params.ID)
41256-	}
41257-	c.conn.Cancel(id)
41258-	return nil, nil
41259-}
41260-
41261-type ForwardBinder struct {
41262-	dialer jsonrpc2_v2.Dialer
41263-	onBind func(*jsonrpc2_v2.Connection)
41264-}
41265-
41266-func NewForwardBinder(dialer jsonrpc2_v2.Dialer) *ForwardBinder {
41267-	return &ForwardBinder{
41268-		dialer: dialer,
41269-	}
41270-}
41271-
41272-func (b *ForwardBinder) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) (opts jsonrpc2_v2.ConnectionOptions) {
41273-	client := protocol.ClientDispatcherV2(conn)
41274-	clientBinder := NewClientBinder(func(context.Context, protocol.Server) protocol.Client { return client })
41275-
41276-	serverConn, err := jsonrpc2_v2.Dial(context.Background(), b.dialer, clientBinder)
41277-	if err != nil {
41278-		return jsonrpc2_v2.ConnectionOptions{
41279-			Handler: jsonrpc2_v2.HandlerFunc(func(context.Context, *jsonrpc2_v2.Request) (interface{}, error) {
41280-				return nil, fmt.Errorf("%w: %v", jsonrpc2_v2.ErrInternal, err)
41281-			}),
41282-		}
41283-	}
41284-
41285-	if b.onBind != nil {
41286-		b.onBind(serverConn)
41287-	}
41288-	server := protocol.ServerDispatcherV2(serverConn)
41289-	preempter := &canceler{
41290-		conn: conn,
41291-	}
41292-	detached := xcontext.Detach(ctx)
41293-	go func() {
41294-		conn.Wait()
41295-		if err := serverConn.Close(); err != nil {
41296-			event.Log(detached, fmt.Sprintf("closing remote connection: %v", err))
41297-		}
41298-	}()
41299-	return jsonrpc2_v2.ConnectionOptions{
41300-		Handler:   protocol.ServerHandlerV2(server),
41301-		Preempter: preempter,
41302-	}
41303-}
41304-
41305-// A ClientFunc is used to construct an LSP client for a given server.
41306-type ClientFunc func(context.Context, protocol.Server) protocol.Client
41307-
41308-// ClientBinder binds an LSP client to an incoming connection.
41309-type ClientBinder struct {
41310-	newClient ClientFunc
41311-}
41312-
41313-func NewClientBinder(newClient ClientFunc) *ClientBinder {
41314-	return &ClientBinder{newClient}
41315-}
41316-
41317-func (b *ClientBinder) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
41318-	server := protocol.ServerDispatcherV2(conn)
41319-	client := b.newClient(ctx, server)
41320-	return jsonrpc2_v2.ConnectionOptions{
41321-		Handler: protocol.ClientHandlerV2(client),
41322-	}
41323-}
41324diff -urN a/gopls/internal/lsp/lsprpc/binder_test.go b/gopls/internal/lsp/lsprpc/binder_test.go
41325--- a/gopls/internal/lsp/lsprpc/binder_test.go	2000-01-01 00:00:00.000000000 -0000
41326+++ b/gopls/internal/lsp/lsprpc/binder_test.go	1970-01-01 00:00:00.000000000 +0000
41327@@ -1,147 +0,0 @@
41328-// Copyright 2021 The Go Authors. All rights reserved.
41329-// Use of this source code is governed by a BSD-style
41330-// license that can be found in the LICENSE file.
41331-
41332-package lsprpc_test
41333-
41334-import (
41335-	"context"
41336-	"regexp"
41337-	"strings"
41338-	"testing"
41339-	"time"
41340-
41341-	"golang.org/x/tools/gopls/internal/lsp/protocol"
41342-	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
41343-
41344-	. "golang.org/x/tools/gopls/internal/lsp/lsprpc"
41345-)
41346-
41347-type TestEnv struct {
41348-	Conns   []*jsonrpc2_v2.Connection
41349-	Servers []*jsonrpc2_v2.Server
41350-}
41351-
41352-func (e *TestEnv) Shutdown(t *testing.T) {
41353-	for _, s := range e.Servers {
41354-		s.Shutdown()
41355-	}
41356-	for _, c := range e.Conns {
41357-		if err := c.Close(); err != nil {
41358-			t.Error(err)
41359-		}
41360-	}
41361-	for _, s := range e.Servers {
41362-		if err := s.Wait(); err != nil {
41363-			t.Error(err)
41364-		}
41365-	}
41366-}
41367-
41368-func (e *TestEnv) serve(ctx context.Context, t *testing.T, server jsonrpc2_v2.Binder) (jsonrpc2_v2.Listener, *jsonrpc2_v2.Server) {
41369-	l, err := jsonrpc2_v2.NetPipeListener(ctx)
41370-	if err != nil {
41371-		t.Fatal(err)
41372-	}
41373-	s := jsonrpc2_v2.NewServer(ctx, l, server)
41374-	e.Servers = append(e.Servers, s)
41375-	return l, s
41376-}
41377-
41378-func (e *TestEnv) dial(ctx context.Context, t *testing.T, dialer jsonrpc2_v2.Dialer, client jsonrpc2_v2.Binder, forwarded bool) *jsonrpc2_v2.Connection {
41379-	if forwarded {
41380-		l, _ := e.serve(ctx, t, NewForwardBinder(dialer))
41381-		dialer = l.Dialer()
41382-	}
41383-	conn, err := jsonrpc2_v2.Dial(ctx, dialer, client)
41384-	if err != nil {
41385-		t.Fatal(err)
41386-	}
41387-	e.Conns = append(e.Conns, conn)
41388-	return conn
41389-}
41390-
41391-func staticClientBinder(client protocol.Client) jsonrpc2_v2.Binder {
41392-	f := func(context.Context, protocol.Server) protocol.Client { return client }
41393-	return NewClientBinder(f)
41394-}
41395-
41396-func staticServerBinder(server protocol.Server) jsonrpc2_v2.Binder {
41397-	f := func(ctx context.Context, client protocol.ClientCloser) protocol.Server {
41398-		return server
41399-	}
41400-	return NewServerBinder(f)
41401-}
41402-
41403-func TestClientLoggingV2(t *testing.T) {
41404-	ctx := context.Background()
41405-
41406-	for name, forwarded := range map[string]bool{
41407-		"forwarded":  true,
41408-		"standalone": false,
41409-	} {
41410-		t.Run(name, func(t *testing.T) {
41411-			client := FakeClient{Logs: make(chan string, 10)}
41412-			env := new(TestEnv)
41413-			defer env.Shutdown(t)
41414-			l, _ := env.serve(ctx, t, staticServerBinder(PingServer{}))
41415-			conn := env.dial(ctx, t, l.Dialer(), staticClientBinder(client), forwarded)
41416-
41417-			if err := protocol.ServerDispatcherV2(conn).DidOpen(ctx, &protocol.DidOpenTextDocumentParams{}); err != nil {
41418-				t.Errorf("DidOpen: %v", err)
41419-			}
41420-			select {
41421-			case got := <-client.Logs:
41422-				want := "ping"
41423-				matched, err := regexp.MatchString(want, got)
41424-				if err != nil {
41425-					t.Fatal(err)
41426-				}
41427-				if !matched {
41428-					t.Errorf("got log %q, want a log containing %q", got, want)
41429-				}
41430-			case <-time.After(1 * time.Second):
41431-				t.Error("timeout waiting for client log")
41432-			}
41433-		})
41434-	}
41435-}
41436-
41437-func TestRequestCancellationV2(t *testing.T) {
41438-	ctx := context.Background()
41439-
41440-	for name, forwarded := range map[string]bool{
41441-		"forwarded":  true,
41442-		"standalone": false,
41443-	} {
41444-		t.Run(name, func(t *testing.T) {
41445-			server := WaitableServer{
41446-				Started:   make(chan struct{}),
41447-				Completed: make(chan error),
41448-			}
41449-			env := new(TestEnv)
41450-			defer env.Shutdown(t)
41451-			l, _ := env.serve(ctx, t, staticServerBinder(server))
41452-			client := FakeClient{Logs: make(chan string, 10)}
41453-			conn := env.dial(ctx, t, l.Dialer(), staticClientBinder(client), forwarded)
41454-
41455-			sd := protocol.ServerDispatcherV2(conn)
41456-			ctx, cancel := context.WithCancel(ctx)
41457-
41458-			result := make(chan error)
41459-			go func() {
41460-				_, err := sd.Hover(ctx, &protocol.HoverParams{})
41461-				result <- err
41462-			}()
41463-			// Wait for the Hover request to start.
41464-			<-server.Started
41465-			cancel()
41466-			if err := <-result; err == nil {
41467-				t.Error("nil error for cancelled Hover(), want non-nil")
41468-			}
41469-			if err := <-server.Completed; err == nil || !strings.Contains(err.Error(), "cancelled hover") {
41470-				t.Errorf("Hover(): unexpected server-side error %v", err)
41471-			}
41472-		})
41473-	}
41474-}
41475diff -urN a/gopls/internal/lsp/lsprpc/commandinterceptor.go b/gopls/internal/lsp/lsprpc/commandinterceptor.go
41476--- a/gopls/internal/lsp/lsprpc/commandinterceptor.go	2000-01-01 00:00:00.000000000 -0000
41477+++ b/gopls/internal/lsp/lsprpc/commandinterceptor.go	1970-01-01 00:00:00.000000000 +0000
41478@@ -1,44 +0,0 @@
41479-// Copyright 2021 The Go Authors. All rights reserved.
41480-// Use of this source code is governed by a BSD-style
41481-// license that can be found in the LICENSE file.
41482-
41483-package lsprpc
41484-
41485-import (
41486-	"context"
41487-	"encoding/json"
41488-
41489-	"golang.org/x/tools/gopls/internal/lsp/protocol"
41490-	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
41491-)
41492-
41493-// HandlerMiddleware is a middleware that only modifies the jsonrpc2 handler.
41494-type HandlerMiddleware func(jsonrpc2_v2.Handler) jsonrpc2_v2.Handler
41495-
41496-// BindHandler transforms a HandlerMiddleware into a Middleware.
41497-func BindHandler(hmw HandlerMiddleware) Middleware {
41498-	return Middleware(func(binder jsonrpc2_v2.Binder) jsonrpc2_v2.Binder {
41499-		return BinderFunc(func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
41500-			opts := binder.Bind(ctx, conn)
41501-			opts.Handler = hmw(opts.Handler)
41502-			return opts
41503-		})
41504-	})
41505-}
41506-
41507-func CommandInterceptor(command string, run func(*protocol.ExecuteCommandParams) (interface{}, error)) Middleware {
41508-	return BindHandler(func(delegate jsonrpc2_v2.Handler) jsonrpc2_v2.Handler {
41509-		return jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
41510-			if req.Method == "workspace/executeCommand" {
41511-				var params protocol.ExecuteCommandParams
41512-				if err := json.Unmarshal(req.Params, &params); err == nil {
41513-					if params.Command == command {
41514-						return run(&params)
41515-					}
41516-				}
41517-			}
41518-
41519-			return delegate.Handle(ctx, req)
41520-		})
41521-	})
41522-}
41523diff -urN a/gopls/internal/lsp/lsprpc/commandinterceptor_test.go b/gopls/internal/lsp/lsprpc/commandinterceptor_test.go
41524--- a/gopls/internal/lsp/lsprpc/commandinterceptor_test.go	2000-01-01 00:00:00.000000000 -0000
41525+++ b/gopls/internal/lsp/lsprpc/commandinterceptor_test.go	1970-01-01 00:00:00.000000000 +0000
41526@@ -1,42 +0,0 @@
41527-// Copyright 2021 The Go Authors. All rights reserved.
41528-// Use of this source code is governed by a BSD-style
41529-// license that can be found in the LICENSE file.
41530-
41531-package lsprpc_test
41532-
41533-import (
41534-	"context"
41535-	"testing"
41536-
41537-	"golang.org/x/tools/gopls/internal/lsp/protocol"
41538-
41539-	. "golang.org/x/tools/gopls/internal/lsp/lsprpc"
41540-)
41541-
41542-func TestCommandInterceptor(t *testing.T) {
41543-	const command = "foo"
41544-	caught := false
41545-	intercept := func(_ *protocol.ExecuteCommandParams) (interface{}, error) {
41546-		caught = true
41547-		return map[string]interface{}{}, nil
41548-	}
41549-
41550-	ctx := context.Background()
41551-	env := new(TestEnv)
41552-	defer env.Shutdown(t)
41553-	mw := CommandInterceptor(command, intercept)
41554-	l, _ := env.serve(ctx, t, mw(noopBinder))
41555-	conn := env.dial(ctx, t, l.Dialer(), noopBinder, false)
41556-
41557-	params := &protocol.ExecuteCommandParams{
41558-		Command: command,
41559-	}
41560-	var res interface{}
41561-	err := conn.Call(ctx, "workspace/executeCommand", params).Await(ctx, &res)
41562-	if err != nil {
41563-		t.Fatal(err)
41564-	}
41565-	if !caught {
41566-		t.Errorf("workspace/executeCommand was not intercepted")
41567-	}
41568-}
41569diff -urN a/gopls/internal/lsp/lsprpc/dialer.go b/gopls/internal/lsp/lsprpc/dialer.go
41570--- a/gopls/internal/lsp/lsprpc/dialer.go	2000-01-01 00:00:00.000000000 -0000
41571+++ b/gopls/internal/lsp/lsprpc/dialer.go	1970-01-01 00:00:00.000000000 +0000
41572@@ -1,114 +0,0 @@
41573-// Copyright 2021 The Go Authors. All rights reserved.
41574-// Use of this source code is governed by a BSD-style
41575-// license that can be found in the LICENSE file.
41576-
41577-package lsprpc
41578-
41579-import (
41580-	"context"
41581-	"fmt"
41582-	"io"
41583-	"net"
41584-	"os"
41585-	"time"
41586-
41587-	exec "golang.org/x/sys/execabs"
41588-	"golang.org/x/tools/internal/event"
41589-)
41590-
41591-// AutoNetwork is the pseudo network type used to signal that gopls should use
41592-// automatic discovery to resolve a remote address.
41593-const AutoNetwork = "auto"
41594-
41595-// An AutoDialer is a jsonrpc2 dialer that understands the 'auto' network.
41596-type AutoDialer struct {
41597-	network, addr string // the 'real' network and address
41598-	isAuto        bool   // whether the server is on the 'auto' network
41599-
41600-	executable string
41601-	argFunc    func(network, addr string) []string
41602-}
41603-
41604-func NewAutoDialer(rawAddr string, argFunc func(network, addr string) []string) (*AutoDialer, error) {
41605-	d := AutoDialer{
41606-		argFunc: argFunc,
41607-	}
41608-	d.network, d.addr = ParseAddr(rawAddr)
41609-	if d.network == AutoNetwork {
41610-		d.isAuto = true
41611-		bin, err := os.Executable()
41612-		if err != nil {
41613-			return nil, fmt.Errorf("getting executable: %w", err)
41614-		}
41615-		d.executable = bin
41616-		d.network, d.addr = autoNetworkAddress(bin, d.addr)
41617-	}
41618-	return &d, nil
41619-}
41620-
41621-// Dial implements the jsonrpc2.Dialer interface.
41622-func (d *AutoDialer) Dial(ctx context.Context) (io.ReadWriteCloser, error) {
41623-	conn, err := d.dialNet(ctx)
41624-	return conn, err
41625-}
41626-
41627-// TODO(rFindley): remove this once we no longer need to integrate with v1 of
41628-// the jsonrpc2 package.
41629-func (d *AutoDialer) dialNet(ctx context.Context) (net.Conn, error) {
41630-	// Attempt to verify that we own the remote. This is imperfect, but if we can
41631-	// determine that the remote is owned by a different user, we should fail.
41632-	ok, err := verifyRemoteOwnership(d.network, d.addr)
41633-	if err != nil {
41634-		// If the ownership check itself failed, we fail open but log an error to
41635-		// the user.
41636-		event.Error(ctx, "unable to check daemon socket owner, failing open", err)
41637-	} else if !ok {
41638-		// We successfully checked that the socket is not owned by us, we fail
41639-		// closed.
41640-		return nil, fmt.Errorf("socket %q is owned by a different user", d.addr)
41641-	}
41642-	const dialTimeout = 1 * time.Second
41643-	// Try dialing our remote once, in case it is already running.
41644-	netConn, err := net.DialTimeout(d.network, d.addr, dialTimeout)
41645-	if err == nil {
41646-		return netConn, nil
41647-	}
41648-	if d.isAuto && d.argFunc != nil {
41649-		if d.network == "unix" {
41650-			// Sometimes the socketfile isn't properly cleaned up when the server
41651-			// shuts down. Since we have already tried and failed to dial this
41652-			// address, it should *usually* be safe to remove the socket before
41653-			// binding to the address.
41654-			// TODO(rfindley): there is probably a race here if multiple server
41655-			// instances are simultaneously starting up.
41656-			if _, err := os.Stat(d.addr); err == nil {
41657-				if err := os.Remove(d.addr); err != nil {
41658-					return nil, fmt.Errorf("removing remote socket file: %w", err)
41659-				}
41660-			}
41661-		}
41662-		args := d.argFunc(d.network, d.addr)
41663-		cmd := exec.Command(d.executable, args...)
41664-		if err := runRemote(cmd); err != nil {
41665-			return nil, err
41666-		}
41667-	}
41668-
41669-	const retries = 5
41670-	// It can take some time for the newly started server to bind to our address,
41671-	// so we retry for a bit.
41672-	for retry := 0; retry < retries; retry++ {
41673-		startDial := time.Now()
41674-		netConn, err = net.DialTimeout(d.network, d.addr, dialTimeout)
41675-		if err == nil {
41676-			return netConn, nil
41677-		}
41678-		event.Log(ctx, fmt.Sprintf("failed attempt #%d to connect to remote: %v\n", retry+2, err))
41679-		// In case our failure was a fast-failure, ensure we wait at least
41680-		// f.dialTimeout before trying again.
41681-		if retry != retries-1 {
41682-			time.Sleep(dialTimeout - time.Since(startDial))
41683-		}
41684-	}
41685-	return nil, fmt.Errorf("dialing remote: %w", err)
41686-}
41687diff -urN a/gopls/internal/lsp/lsprpc/goenv.go b/gopls/internal/lsp/lsprpc/goenv.go
41688--- a/gopls/internal/lsp/lsprpc/goenv.go	2000-01-01 00:00:00.000000000 -0000
41689+++ b/gopls/internal/lsp/lsprpc/goenv.go	1970-01-01 00:00:00.000000000 +0000
41690@@ -1,96 +0,0 @@
41691-// Copyright 2021 The Go Authors. All rights reserved.
41692-// Use of this source code is governed by a BSD-style
41693-// license that can be found in the LICENSE file.
41694-
41695-package lsprpc
41696-
41697-import (
41698-	"context"
41699-	"encoding/json"
41700-	"fmt"
41701-	"os"
41702-
41703-	"golang.org/x/tools/internal/event"
41704-	"golang.org/x/tools/internal/gocommand"
41705-	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
41706-	"golang.org/x/tools/gopls/internal/lsp/protocol"
41707-)
41708-
41709-func GoEnvMiddleware() (Middleware, error) {
41710-	return BindHandler(func(delegate jsonrpc2_v2.Handler) jsonrpc2_v2.Handler {
41711-		return jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
41712-			if req.Method == "initialize" {
41713-				if err := addGoEnvToInitializeRequestV2(ctx, req); err != nil {
41714-					event.Error(ctx, "adding go env to initialize", err)
41715-				}
41716-			}
41717-			return delegate.Handle(ctx, req)
41718-		})
41719-	}), nil
41720-}
41721-
41722-func addGoEnvToInitializeRequestV2(ctx context.Context, req *jsonrpc2_v2.Request) error {
41723-	var params protocol.ParamInitialize
41724-	if err := json.Unmarshal(req.Params, &params); err != nil {
41725-		return err
41726-	}
41727-	var opts map[string]interface{}
41728-	switch v := params.InitializationOptions.(type) {
41729-	case nil:
41730-		opts = make(map[string]interface{})
41731-	case map[string]interface{}:
41732-		opts = v
41733-	default:
41734-		return fmt.Errorf("unexpected type for InitializationOptions: %T", v)
41735-	}
41736-	envOpt, ok := opts["env"]
41737-	if !ok {
41738-		envOpt = make(map[string]interface{})
41739-	}
41740-	env, ok := envOpt.(map[string]interface{})
41741-	if !ok {
41742-		return fmt.Errorf("env option is %T, expected a map", envOpt)
41743-	}
41744-	goenv, err := getGoEnv(ctx, env)
41745-	if err != nil {
41746-		return err
41747-	}
41748-	// We don't want to propagate GOWORK unless explicitly set since that could mess with
41749-	// path inference during cmd/go invocations, see golang/go#51825.
41750-	_, goworkSet := os.LookupEnv("GOWORK")
41751-	for govar, value := range goenv {
41752-		if govar == "GOWORK" && !goworkSet {
41753-			continue
41754-		}
41755-		env[govar] = value
41756-	}
41757-	opts["env"] = env
41758-	params.InitializationOptions = opts
41759-	raw, err := json.Marshal(params)
41760-	if err != nil {
41761-		return fmt.Errorf("marshaling updated options: %v", err)
41762-	}
41763-	req.Params = json.RawMessage(raw)
41764-	return nil
41765-}
41766-
41767-func getGoEnv(ctx context.Context, env map[string]interface{}) (map[string]string, error) {
41768-	var runEnv []string
41769-	for k, v := range env {
41770-		runEnv = append(runEnv, fmt.Sprintf("%s=%s", k, v))
41771-	}
41772-	runner := gocommand.Runner{}
41773-	output, err := runner.Run(ctx, gocommand.Invocation{
41774-		Verb: "env",
41775-		Args: []string{"-json"},
41776-		Env:  runEnv,
41777-	})
41778-	if err != nil {
41779-		return nil, err
41780-	}
41781-	envmap := make(map[string]string)
41782-	if err := json.Unmarshal(output.Bytes(), &envmap); err != nil {
41783-		return nil, err
41784-	}
41785-	return envmap, nil
41786-}
41787diff -urN a/gopls/internal/lsp/lsprpc/goenv_test.go b/gopls/internal/lsp/lsprpc/goenv_test.go
41788--- a/gopls/internal/lsp/lsprpc/goenv_test.go	2000-01-01 00:00:00.000000000 -0000
41789+++ b/gopls/internal/lsp/lsprpc/goenv_test.go	1970-01-01 00:00:00.000000000 +0000
41790@@ -1,65 +0,0 @@
41791-// Copyright 2021 The Go Authors. All rights reserved.
41792-// Use of this source code is governed by a BSD-style
41793-// license that can be found in the LICENSE file.
41794-
41795-package lsprpc_test
41796-
41797-import (
41798-	"context"
41799-	"testing"
41800-
41801-	"golang.org/x/tools/gopls/internal/lsp/protocol"
41802-
41803-	. "golang.org/x/tools/gopls/internal/lsp/lsprpc"
41804-)
41805-
41806-type initServer struct {
41807-	protocol.Server
41808-
41809-	params *protocol.ParamInitialize
41810-}
41811-
41812-func (s *initServer) Initialize(ctx context.Context, params *protocol.ParamInitialize) (*protocol.InitializeResult, error) {
41813-	s.params = params
41814-	return &protocol.InitializeResult{}, nil
41815-}
41816-
41817-func TestGoEnvMiddleware(t *testing.T) {
41818-	ctx := context.Background()
41819-
41820-	server := &initServer{}
41821-	env := new(TestEnv)
41822-	defer env.Shutdown(t)
41823-	l, _ := env.serve(ctx, t, staticServerBinder(server))
41824-	mw, err := GoEnvMiddleware()
41825-	if err != nil {
41826-		t.Fatal(err)
41827-	}
41828-	binder := mw(NewForwardBinder(l.Dialer()))
41829-	l, _ = env.serve(ctx, t, binder)
41830-	conn := env.dial(ctx, t, l.Dialer(), noopBinder, true)
41831-	dispatch := protocol.ServerDispatcherV2(conn)
41832-	initParams := &protocol.ParamInitialize{}
41833-	initParams.InitializationOptions = map[string]interface{}{
41834-		"env": map[string]interface{}{
41835-			"GONOPROXY": "example.com",
41836-		},
41837-	}
41838-	if _, err := dispatch.Initialize(ctx, initParams); err != nil {
41839-		t.Fatal(err)
41840-	}
41841-
41842-	if server.params == nil {
41843-		t.Fatalf("initialize params are unset")
41844-	}
41845-	envOpts := server.params.InitializationOptions.(map[string]interface{})["env"].(map[string]interface{})
41846-
41847-	// Check for an arbitrary Go variable. It should be set.
41848-	if _, ok := envOpts["GOPRIVATE"]; !ok {
41849-		t.Errorf("Go environment variable GOPRIVATE unset in initialization options")
41850-	}
41851-	// Check that the variable present in our user config was not overwritten.
41852-	if got, want := envOpts["GONOPROXY"], "example.com"; got != want {
41853-		t.Errorf("GONOPROXY=%q, want %q", got, want)
41854-	}
41855-}
41856diff -urN a/gopls/internal/lsp/lsprpc/lsprpc.go b/gopls/internal/lsp/lsprpc/lsprpc.go
41857--- a/gopls/internal/lsp/lsprpc/lsprpc.go	2000-01-01 00:00:00.000000000 -0000
41858+++ b/gopls/internal/lsp/lsprpc/lsprpc.go	1970-01-01 00:00:00.000000000 +0000
41859@@ -1,543 +0,0 @@
41860-// Copyright 2020 The Go Authors. All rights reserved.
41861-// Use of this source code is governed by a BSD-style
41862-// license that can be found in the LICENSE file.
41863-
41864-// Package lsprpc implements a jsonrpc2.StreamServer that may be used to
41865-// serve the LSP on a jsonrpc2 channel.
41866-package lsprpc
41867-
41868-import (
41869-	"context"
41870-	"encoding/json"
41871-	"fmt"
41872-	"log"
41873-	"net"
41874-	"os"
41875-	"strconv"
41876-	"strings"
41877-	"sync"
41878-	"sync/atomic"
41879-	"time"
41880-
41881-	"golang.org/x/tools/gopls/internal/lsp"
41882-	"golang.org/x/tools/gopls/internal/lsp/cache"
41883-	"golang.org/x/tools/gopls/internal/lsp/command"
41884-	"golang.org/x/tools/gopls/internal/lsp/debug"
41885-	"golang.org/x/tools/gopls/internal/lsp/protocol"
41886-	"golang.org/x/tools/gopls/internal/lsp/source"
41887-	"golang.org/x/tools/internal/event"
41888-	"golang.org/x/tools/internal/event/tag"
41889-	"golang.org/x/tools/internal/jsonrpc2"
41890-)
41891-
41892-// Unique identifiers for client/server.
41893-var serverIndex int64
41894-
41895-// The StreamServer type is a jsonrpc2.StreamServer that handles incoming
41896-// streams as a new LSP session, using a shared cache.
41897-type StreamServer struct {
41898-	cache *cache.Cache
41899-	// daemon controls whether or not to log new connections.
41900-	daemon bool
41901-
41902-	// optionsOverrides is passed to newly created sessions.
41903-	optionsOverrides func(*source.Options)
41904-
41905-	// serverForTest may be set to a test fake for testing.
41906-	serverForTest protocol.Server
41907-}
41908-
41909-// NewStreamServer creates a StreamServer using the shared cache. If
41910-// withTelemetry is true, each session is instrumented with telemetry that
41911-// records RPC statistics.
41912-func NewStreamServer(cache *cache.Cache, daemon bool, optionsFunc func(*source.Options)) *StreamServer {
41913-	return &StreamServer{cache: cache, daemon: daemon, optionsOverrides: optionsFunc}
41914-}
41915-
41916-func (s *StreamServer) Binder() *ServerBinder {
41917-	newServer := func(ctx context.Context, client protocol.ClientCloser) protocol.Server {
41918-		session := cache.NewSession(ctx, s.cache, s.optionsOverrides)
41919-		server := s.serverForTest
41920-		if server == nil {
41921-			server = lsp.NewServer(session, client)
41922-			if instance := debug.GetInstance(ctx); instance != nil {
41923-				instance.AddService(server, session)
41924-			}
41925-		}
41926-		return server
41927-	}
41928-	return NewServerBinder(newServer)
41929-}
41930-
41931-// ServeStream implements the jsonrpc2.StreamServer interface, by handling
41932-// incoming streams using a new lsp server.
41933-func (s *StreamServer) ServeStream(ctx context.Context, conn jsonrpc2.Conn) error {
41934-	client := protocol.ClientDispatcher(conn)
41935-	session := cache.NewSession(ctx, s.cache, s.optionsOverrides)
41936-	server := s.serverForTest
41937-	if server == nil {
41938-		server = lsp.NewServer(session, client)
41939-		if instance := debug.GetInstance(ctx); instance != nil {
41940-			instance.AddService(server, session)
41941-		}
41942-	}
41943-	// Clients may or may not send a shutdown message. Make sure the server is
41944-	// shut down.
41945-	// TODO(rFindley): this shutdown should perhaps be on a disconnected context.
41946-	defer func() {
41947-		if err := server.Shutdown(ctx); err != nil {
41948-			event.Error(ctx, "error shutting down", err)
41949-		}
41950-	}()
41951-	executable, err := os.Executable()
41952-	if err != nil {
41953-		log.Printf("error getting gopls path: %v", err)
41954-		executable = ""
41955-	}
41956-	ctx = protocol.WithClient(ctx, client)
41957-	conn.Go(ctx,
41958-		protocol.Handlers(
41959-			handshaker(session, executable, s.daemon,
41960-				protocol.ServerHandler(server,
41961-					jsonrpc2.MethodNotFound))))
41962-	if s.daemon {
41963-		log.Printf("Session %s: connected", session.ID())
41964-		defer log.Printf("Session %s: exited", session.ID())
41965-	}
41966-	<-conn.Done()
41967-	return conn.Err()
41968-}
41969-
41970-// A Forwarder is a jsonrpc2.StreamServer that handles an LSP stream by
41971-// forwarding it to a remote. This is used when the gopls process started by
41972-// the editor is in the `-remote` mode, which means it finds and connects to a
41973-// separate gopls daemon. In these cases, we still want the forwarder gopls to
41974-// be instrumented with telemetry, and want to be able to in some cases hijack
41975-// the jsonrpc2 connection with the daemon.
41976-type Forwarder struct {
41977-	dialer *AutoDialer
41978-
41979-	mu sync.Mutex
41980-	// Hold on to the server connection so that we can redo the handshake if any
41981-	// information changes.
41982-	serverConn jsonrpc2.Conn
41983-	serverID   string
41984-}
41985-
41986-// NewForwarder creates a new Forwarder, ready to forward connections to the
41987-// remote server specified by rawAddr. If provided and rawAddr indicates an
41988-// 'automatic' address (starting with 'auto;'), argFunc may be used to start a
41989-// remote server for the auto-discovered address.
41990-func NewForwarder(rawAddr string, argFunc func(network, address string) []string) (*Forwarder, error) {
41991-	dialer, err := NewAutoDialer(rawAddr, argFunc)
41992-	if err != nil {
41993-		return nil, err
41994-	}
41995-	fwd := &Forwarder{
41996-		dialer: dialer,
41997-	}
41998-	return fwd, nil
41999-}
42000-
42001-// QueryServerState queries the server state of the current server.
42002-func QueryServerState(ctx context.Context, addr string) (*ServerState, error) {
42003-	serverConn, err := dialRemote(ctx, addr)
42004-	if err != nil {
42005-		return nil, err
42006-	}
42007-	var state ServerState
42008-	if err := protocol.Call(ctx, serverConn, sessionsMethod, nil, &state); err != nil {
42009-		return nil, fmt.Errorf("querying server state: %w", err)
42010-	}
42011-	return &state, nil
42012-}
42013-
42014-// dialRemote is used for making calls into the gopls daemon. addr should be a
42015-// URL, possibly on the synthetic 'auto' network (e.g. tcp://..., unix://...,
42016-// or auto://...).
42017-func dialRemote(ctx context.Context, addr string) (jsonrpc2.Conn, error) {
42018-	network, address := ParseAddr(addr)
42019-	if network == AutoNetwork {
42020-		gp, err := os.Executable()
42021-		if err != nil {
42022-			return nil, fmt.Errorf("getting gopls path: %w", err)
42023-		}
42024-		network, address = autoNetworkAddress(gp, address)
42025-	}
42026-	netConn, err := net.DialTimeout(network, address, 5*time.Second)
42027-	if err != nil {
42028-		return nil, fmt.Errorf("dialing remote: %w", err)
42029-	}
42030-	serverConn := jsonrpc2.NewConn(jsonrpc2.NewHeaderStream(netConn))
42031-	serverConn.Go(ctx, jsonrpc2.MethodNotFound)
42032-	return serverConn, nil
42033-}
42034-
42035-func ExecuteCommand(ctx context.Context, addr string, id string, request, result interface{}) error {
42036-	serverConn, err := dialRemote(ctx, addr)
42037-	if err != nil {
42038-		return err
42039-	}
42040-	args, err := command.MarshalArgs(request)
42041-	if err != nil {
42042-		return err
42043-	}
42044-	params := protocol.ExecuteCommandParams{
42045-		Command:   id,
42046-		Arguments: args,
42047-	}
42048-	return protocol.Call(ctx, serverConn, "workspace/executeCommand", params, result)
42049-}
42050-
42051-// ServeStream dials the forwarder remote and binds the remote to serve the LSP
42052-// on the incoming stream.
42053-func (f *Forwarder) ServeStream(ctx context.Context, clientConn jsonrpc2.Conn) error {
42054-	client := protocol.ClientDispatcher(clientConn)
42055-
42056-	netConn, err := f.dialer.dialNet(ctx)
42057-	if err != nil {
42058-		return fmt.Errorf("forwarder: connecting to remote: %w", err)
42059-	}
42060-	serverConn := jsonrpc2.NewConn(jsonrpc2.NewHeaderStream(netConn))
42061-	server := protocol.ServerDispatcher(serverConn)
42062-
42063-	// Forward between connections.
42064-	serverConn.Go(ctx,
42065-		protocol.Handlers(
42066-			protocol.ClientHandler(client,
42067-				jsonrpc2.MethodNotFound)))
42068-
42069-	// Don't run the clientConn yet, so that we can complete the handshake before
42070-	// processing any client messages.
42071-
42072-	// Do a handshake with the server instance to exchange debug information.
42073-	index := atomic.AddInt64(&serverIndex, 1)
42074-	f.mu.Lock()
42075-	f.serverConn = serverConn
42076-	f.serverID = strconv.FormatInt(index, 10)
42077-	f.mu.Unlock()
42078-	f.handshake(ctx)
42079-	clientConn.Go(ctx,
42080-		protocol.Handlers(
42081-			f.handler(
42082-				protocol.ServerHandler(server,
42083-					jsonrpc2.MethodNotFound))))
42084-
42085-	select {
42086-	case <-serverConn.Done():
42087-		clientConn.Close()
42088-	case <-clientConn.Done():
42089-		serverConn.Close()
42090-	}
42091-
42092-	err = nil
42093-	if serverConn.Err() != nil {
42094-		err = fmt.Errorf("remote disconnected: %v", serverConn.Err())
42095-	} else if clientConn.Err() != nil {
42096-		err = fmt.Errorf("client disconnected: %v", clientConn.Err())
42097-	}
42098-	event.Log(ctx, fmt.Sprintf("forwarder: exited with error: %v", err))
42099-	return err
42100-}
42101-
42102-// TODO(rfindley): remove this handshaking in favor of middleware.
42103-func (f *Forwarder) handshake(ctx context.Context) {
42104-	// This call to os.Executable is redundant, and will be eliminated by the
42105-	// transition to the V2 API.
42106-	goplsPath, err := os.Executable()
42107-	if err != nil {
42108-		event.Error(ctx, "getting executable for handshake", err)
42109-		goplsPath = ""
42110-	}
42111-	var (
42112-		hreq = handshakeRequest{
42113-			ServerID:  f.serverID,
42114-			GoplsPath: goplsPath,
42115-		}
42116-		hresp handshakeResponse
42117-	)
42118-	if di := debug.GetInstance(ctx); di != nil {
42119-		hreq.Logfile = di.Logfile
42120-		hreq.DebugAddr = di.ListenedDebugAddress()
42121-	}
42122-	if err := protocol.Call(ctx, f.serverConn, handshakeMethod, hreq, &hresp); err != nil {
42123-		// TODO(rfindley): at some point in the future we should return an error
42124-		// here.  Handshakes have become functional in nature.
42125-		event.Error(ctx, "forwarder: gopls handshake failed", err)
42126-	}
42127-	if hresp.GoplsPath != goplsPath {
42128-		event.Error(ctx, "", fmt.Errorf("forwarder: gopls path mismatch: forwarder is %q, remote is %q", goplsPath, hresp.GoplsPath))
42129-	}
42130-	event.Log(ctx, "New server",
42131-		tag.NewServer.Of(f.serverID),
42132-		tag.Logfile.Of(hresp.Logfile),
42133-		tag.DebugAddress.Of(hresp.DebugAddr),
42134-		tag.GoplsPath.Of(hresp.GoplsPath),
42135-		tag.ClientID.Of(hresp.SessionID),
42136-	)
42137-}
42138-
42139-func ConnectToRemote(ctx context.Context, addr string) (net.Conn, error) {
42140-	dialer, err := NewAutoDialer(addr, nil)
42141-	if err != nil {
42142-		return nil, err
42143-	}
42144-	return dialer.dialNet(ctx)
42145-}
42146-
42147-// handler intercepts messages to the daemon to enrich them with local
42148-// information.
42149-func (f *Forwarder) handler(handler jsonrpc2.Handler) jsonrpc2.Handler {
42150-	return func(ctx context.Context, reply jsonrpc2.Replier, r jsonrpc2.Request) error {
42151-		// Intercept certain messages to add special handling.
42152-		switch r.Method() {
42153-		case "initialize":
42154-			if newr, err := addGoEnvToInitializeRequest(ctx, r); err == nil {
42155-				r = newr
42156-			} else {
42157-				log.Printf("unable to add local env to initialize request: %v", err)
42158-			}
42159-		case "workspace/executeCommand":
42160-			var params protocol.ExecuteCommandParams
42161-			if err := json.Unmarshal(r.Params(), &params); err == nil {
42162-				if params.Command == command.StartDebugging.ID() {
42163-					var args command.DebuggingArgs
42164-					if err := command.UnmarshalArgs(params.Arguments, &args); err == nil {
42165-						reply = f.replyWithDebugAddress(ctx, reply, args)
42166-					} else {
42167-						event.Error(ctx, "unmarshaling debugging args", err)
42168-					}
42169-				}
42170-			} else {
42171-				event.Error(ctx, "intercepting executeCommand request", err)
42172-			}
42173-		}
42174-		// The gopls workspace environment defaults to the process environment in
42175-		// which gopls daemon was started. To avoid discrepancies in Go environment
42176-		// between the editor and daemon, inject any unset variables in `go env`
42177-		// into the options sent by initialize.
42178-		//
42179-		// See also golang.org/issue/37830.
42180-		return handler(ctx, reply, r)
42181-	}
42182-}
42183-
42184-// addGoEnvToInitializeRequest builds a new initialize request in which we set
42185-// any environment variables output by `go env` and not already present in the
42186-// request.
42187-//
42188-// It returns an error if r is not an initialize request, or is otherwise
42189-// malformed.
42190-func addGoEnvToInitializeRequest(ctx context.Context, r jsonrpc2.Request) (jsonrpc2.Request, error) {
42191-	var params protocol.ParamInitialize
42192-	if err := json.Unmarshal(r.Params(), &params); err != nil {
42193-		return nil, err
42194-	}
42195-	var opts map[string]interface{}
42196-	switch v := params.InitializationOptions.(type) {
42197-	case nil:
42198-		opts = make(map[string]interface{})
42199-	case map[string]interface{}:
42200-		opts = v
42201-	default:
42202-		return nil, fmt.Errorf("unexpected type for InitializationOptions: %T", v)
42203-	}
42204-	envOpt, ok := opts["env"]
42205-	if !ok {
42206-		envOpt = make(map[string]interface{})
42207-	}
42208-	env, ok := envOpt.(map[string]interface{})
42209-	if !ok {
42210-		return nil, fmt.Errorf(`env option is %T, expected a map`, envOpt)
42211-	}
42212-	goenv, err := getGoEnv(ctx, env)
42213-	if err != nil {
42214-		return nil, err
42215-	}
42216-	// We don't want to propagate GOWORK unless explicitly set since that could mess with
42217-	// path inference during cmd/go invocations, see golang/go#51825.
42218-	_, goworkSet := os.LookupEnv("GOWORK")
42219-	for govar, value := range goenv {
42220-		if govar == "GOWORK" && !goworkSet {
42221-			continue
42222-		}
42223-		env[govar] = value
42224-	}
42225-	opts["env"] = env
42226-	params.InitializationOptions = opts
42227-	call, ok := r.(*jsonrpc2.Call)
42228-	if !ok {
42229-		return nil, fmt.Errorf("%T is not a *jsonrpc2.Call", r)
42230-	}
42231-	return jsonrpc2.NewCall(call.ID(), "initialize", params)
42232-}
42233-
42234-func (f *Forwarder) replyWithDebugAddress(outerCtx context.Context, r jsonrpc2.Replier, args command.DebuggingArgs) jsonrpc2.Replier {
42235-	di := debug.GetInstance(outerCtx)
42236-	if di == nil {
42237-		event.Log(outerCtx, "no debug instance to start")
42238-		return r
42239-	}
42240-	return func(ctx context.Context, result interface{}, outerErr error) error {
42241-		if outerErr != nil {
42242-			return r(ctx, result, outerErr)
42243-		}
42244-		// Enrich the result with our own debugging information. Since we're an
42245-		// intermediary, the jsonrpc2 package has deserialized the result into
42246-		// maps, by default. Re-do the unmarshalling.
42247-		raw, err := json.Marshal(result)
42248-		if err != nil {
42249-			event.Error(outerCtx, "marshaling intermediate command result", err)
42250-			return r(ctx, result, err)
42251-		}
42252-		var modified command.DebuggingResult
42253-		if err := json.Unmarshal(raw, &modified); err != nil {
42254-			event.Error(outerCtx, "unmarshaling intermediate command result", err)
42255-			return r(ctx, result, err)
42256-		}
42257-		addr := args.Addr
42258-		if addr == "" {
42259-			addr = "localhost:0"
42260-		}
42261-		addr, err = di.Serve(outerCtx, addr)
42262-		if err != nil {
42263-			event.Error(outerCtx, "starting debug server", err)
42264-			return r(ctx, result, outerErr)
42265-		}
42266-		urls := []string{"http://" + addr}
42267-		modified.URLs = append(urls, modified.URLs...)
42268-		go f.handshake(ctx)
42269-		return r(ctx, modified, nil)
42270-	}
42271-}
42272-
42273-// A handshakeRequest identifies a client to the LSP server.
42274-type handshakeRequest struct {
42275-	// ServerID is the ID of the server on the client. This should usually be 0.
42276-	ServerID string `json:"serverID"`
42277-	// Logfile is the location of the clients log file.
42278-	Logfile string `json:"logfile"`
42279-	// DebugAddr is the client debug address.
42280-	DebugAddr string `json:"debugAddr"`
42281-	// GoplsPath is the path to the Gopls binary running the current client
42282-	// process.
42283-	GoplsPath string `json:"goplsPath"`
42284-}
42285-
42286-// A handshakeResponse is returned by the LSP server to tell the LSP client
42287-// information about its session.
42288-type handshakeResponse struct {
42289-	// SessionID is the server session associated with the client.
42290-	SessionID string `json:"sessionID"`
42291-	// Logfile is the location of the server logs.
42292-	Logfile string `json:"logfile"`
42293-	// DebugAddr is the server debug address.
42294-	DebugAddr string `json:"debugAddr"`
42295-	// GoplsPath is the path to the Gopls binary running the current server
42296-	// process.
42297-	GoplsPath string `json:"goplsPath"`
42298-}
42299-
42300-// ClientSession identifies a current client LSP session on the server. Note
42301-// that it looks similar to handshakeResposne, but in fact 'Logfile' and
42302-// 'DebugAddr' now refer to the client.
42303-type ClientSession struct {
42304-	SessionID string `json:"sessionID"`
42305-	Logfile   string `json:"logfile"`
42306-	DebugAddr string `json:"debugAddr"`
42307-}
42308-
42309-// ServerState holds information about the gopls daemon process, including its
42310-// debug information and debug information of all of its current connected
42311-// clients.
42312-type ServerState struct {
42313-	Logfile         string          `json:"logfile"`
42314-	DebugAddr       string          `json:"debugAddr"`
42315-	GoplsPath       string          `json:"goplsPath"`
42316-	CurrentClientID string          `json:"currentClientID"`
42317-	Clients         []ClientSession `json:"clients"`
42318-}
42319-
42320-const (
42321-	handshakeMethod = "gopls/handshake"
42322-	sessionsMethod  = "gopls/sessions"
42323-)
42324-
42325-func handshaker(session *cache.Session, goplsPath string, logHandshakes bool, handler jsonrpc2.Handler) jsonrpc2.Handler {
42326-	return func(ctx context.Context, reply jsonrpc2.Replier, r jsonrpc2.Request) error {
42327-		switch r.Method() {
42328-		case handshakeMethod:
42329-			// We log.Printf in this handler, rather than event.Log when we want logs
42330-			// to go to the daemon log rather than being reflected back to the
42331-			// client.
42332-			var req handshakeRequest
42333-			if err := json.Unmarshal(r.Params(), &req); err != nil {
42334-				if logHandshakes {
42335-					log.Printf("Error processing handshake for session %s: %v", session.ID(), err)
42336-				}
42337-				sendError(ctx, reply, err)
42338-				return nil
42339-			}
42340-			if logHandshakes {
42341-				log.Printf("Session %s: got handshake. Logfile: %q, Debug addr: %q", session.ID(), req.Logfile, req.DebugAddr)
42342-			}
42343-			event.Log(ctx, "Handshake session update",
42344-				cache.KeyUpdateSession.Of(session),
42345-				tag.DebugAddress.Of(req.DebugAddr),
42346-				tag.Logfile.Of(req.Logfile),
42347-				tag.ServerID.Of(req.ServerID),
42348-				tag.GoplsPath.Of(req.GoplsPath),
42349-			)
42350-			resp := handshakeResponse{
42351-				SessionID: session.ID(),
42352-				GoplsPath: goplsPath,
42353-			}
42354-			if di := debug.GetInstance(ctx); di != nil {
42355-				resp.Logfile = di.Logfile
42356-				resp.DebugAddr = di.ListenedDebugAddress()
42357-			}
42358-			return reply(ctx, resp, nil)
42359-
42360-		case sessionsMethod:
42361-			resp := ServerState{
42362-				GoplsPath:       goplsPath,
42363-				CurrentClientID: session.ID(),
42364-			}
42365-			if di := debug.GetInstance(ctx); di != nil {
42366-				resp.Logfile = di.Logfile
42367-				resp.DebugAddr = di.ListenedDebugAddress()
42368-				for _, c := range di.State.Clients() {
42369-					resp.Clients = append(resp.Clients, ClientSession{
42370-						SessionID: c.Session.ID(),
42371-						Logfile:   c.Logfile,
42372-						DebugAddr: c.DebugAddress,
42373-					})
42374-				}
42375-			}
42376-			return reply(ctx, resp, nil)
42377-		}
42378-		return handler(ctx, reply, r)
42379-	}
42380-}
42381-
42382-func sendError(ctx context.Context, reply jsonrpc2.Replier, err error) {
42383-	err = fmt.Errorf("%v: %w", err, jsonrpc2.ErrParse)
42384-	if err := reply(ctx, nil, err); err != nil {
42385-		event.Error(ctx, "", err)
42386-	}
42387-}
42388-
42389-// ParseAddr parses the address of a gopls remote.
42390-// TODO(rFindley): further document this syntax, and allow URI-style remote
42391-// addresses such as "auto://...".
42392-func ParseAddr(listen string) (network string, address string) {
42393-	// Allow passing just -remote=auto, as a shorthand for using automatic remote
42394-	// resolution.
42395-	if listen == AutoNetwork {
42396-		return AutoNetwork, ""
42397-	}
42398-	if parts := strings.SplitN(listen, ";", 2); len(parts) == 2 {
42399-		return parts[0], parts[1]
42400-	}
42401-	return "tcp", listen
42402-}
42403diff -urN a/gopls/internal/lsp/lsprpc/lsprpc_test.go b/gopls/internal/lsp/lsprpc/lsprpc_test.go
42404--- a/gopls/internal/lsp/lsprpc/lsprpc_test.go	2000-01-01 00:00:00.000000000 -0000
42405+++ b/gopls/internal/lsp/lsprpc/lsprpc_test.go	1970-01-01 00:00:00.000000000 +0000
42406@@ -1,345 +0,0 @@
42407-// Copyright 2020 The Go Authors. All rights reserved.
42408-// Use of this source code is governed by a BSD-style
42409-// license that can be found in the LICENSE file.
42410-
42411-package lsprpc
42412-
42413-import (
42414-	"context"
42415-	"errors"
42416-	"regexp"
42417-	"strings"
42418-	"testing"
42419-	"time"
42420-
42421-	"golang.org/x/tools/gopls/internal/lsp/cache"
42422-	"golang.org/x/tools/gopls/internal/lsp/debug"
42423-	"golang.org/x/tools/gopls/internal/lsp/fake"
42424-	"golang.org/x/tools/gopls/internal/lsp/protocol"
42425-	"golang.org/x/tools/internal/event"
42426-	"golang.org/x/tools/internal/jsonrpc2"
42427-	"golang.org/x/tools/internal/jsonrpc2/servertest"
42428-)
42429-
42430-type FakeClient struct {
42431-	protocol.Client
42432-
42433-	Logs chan string
42434-}
42435-
42436-func (c FakeClient) LogMessage(ctx context.Context, params *protocol.LogMessageParams) error {
42437-	c.Logs <- params.Message
42438-	return nil
42439-}
42440-
42441-// fakeServer is intended to be embedded in the test fakes below, to trivially
42442-// implement Shutdown.
42443-type fakeServer struct {
42444-	protocol.Server
42445-}
42446-
42447-func (fakeServer) Shutdown(ctx context.Context) error {
42448-	return nil
42449-}
42450-
42451-type PingServer struct{ fakeServer }
42452-
42453-func (s PingServer) DidOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error {
42454-	event.Log(ctx, "ping")
42455-	return nil
42456-}
42457-
42458-func TestClientLogging(t *testing.T) {
42459-	ctx, cancel := context.WithCancel(context.Background())
42460-	defer cancel()
42461-
42462-	server := PingServer{}
42463-	client := FakeClient{Logs: make(chan string, 10)}
42464-
42465-	ctx = debug.WithInstance(ctx, "", "")
42466-	ss := NewStreamServer(cache.New(nil), false, nil)
42467-	ss.serverForTest = server
42468-	ts := servertest.NewPipeServer(ss, nil)
42469-	defer checkClose(t, ts.Close)
42470-	cc := ts.Connect(ctx)
42471-	cc.Go(ctx, protocol.ClientHandler(client, jsonrpc2.MethodNotFound))
42472-
42473-	if err := protocol.ServerDispatcher(cc).DidOpen(ctx, &protocol.DidOpenTextDocumentParams{}); err != nil {
42474-		t.Errorf("DidOpen: %v", err)
42475-	}
42476-
42477-	select {
42478-	case got := <-client.Logs:
42479-		want := "ping"
42480-		matched, err := regexp.MatchString(want, got)
42481-		if err != nil {
42482-			t.Fatal(err)
42483-		}
42484-		if !matched {
42485-			t.Errorf("got log %q, want a log containing %q", got, want)
42486-		}
42487-	case <-time.After(1 * time.Second):
42488-		t.Error("timeout waiting for client log")
42489-	}
42490-}
42491-
42492-// WaitableServer instruments LSP request so that we can control their timing.
42493-// The requests chosen are arbitrary: we simply needed one that blocks, and
42494-// another that doesn't.
42495-type WaitableServer struct {
42496-	fakeServer
42497-
42498-	Started   chan struct{}
42499-	Completed chan error
42500-}
42501-
42502-func (s WaitableServer) Hover(ctx context.Context, _ *protocol.HoverParams) (_ *protocol.Hover, err error) {
42503-	s.Started <- struct{}{}
42504-	defer func() {
42505-		s.Completed <- err
42506-	}()
42507-	select {
42508-	case <-ctx.Done():
42509-		return nil, errors.New("cancelled hover")
42510-	case <-time.After(10 * time.Second):
42511-	}
42512-	return &protocol.Hover{}, nil
42513-}
42514-
42515-func (s WaitableServer) ResolveCompletionItem(_ context.Context, item *protocol.CompletionItem) (*protocol.CompletionItem, error) {
42516-	return item, nil
42517-}
42518-
42519-func checkClose(t *testing.T, closer func() error) {
42520-	t.Helper()
42521-	if err := closer(); err != nil {
42522-		t.Errorf("closing: %v", err)
42523-	}
42524-}
42525-
42526-func setupForwarding(ctx context.Context, t *testing.T, s protocol.Server) (direct, forwarded servertest.Connector, cleanup func()) {
42527-	t.Helper()
42528-	serveCtx := debug.WithInstance(ctx, "", "")
42529-	ss := NewStreamServer(cache.New(nil), false, nil)
42530-	ss.serverForTest = s
42531-	tsDirect := servertest.NewTCPServer(serveCtx, ss, nil)
42532-
42533-	forwarder, err := NewForwarder("tcp;"+tsDirect.Addr, nil)
42534-	if err != nil {
42535-		t.Fatal(err)
42536-	}
42537-	tsForwarded := servertest.NewPipeServer(forwarder, nil)
42538-	return tsDirect, tsForwarded, func() {
42539-		checkClose(t, tsDirect.Close)
42540-		checkClose(t, tsForwarded.Close)
42541-	}
42542-}
42543-
42544-func TestRequestCancellation(t *testing.T) {
42545-	ctx := context.Background()
42546-	server := WaitableServer{
42547-		Started:   make(chan struct{}),
42548-		Completed: make(chan error),
42549-	}
42550-	tsDirect, tsForwarded, cleanup := setupForwarding(ctx, t, server)
42551-	defer cleanup()
42552-	tests := []struct {
42553-		serverType string
42554-		ts         servertest.Connector
42555-	}{
42556-		{"direct", tsDirect},
42557-		{"forwarder", tsForwarded},
42558-	}
42559-
42560-	for _, test := range tests {
42561-		t.Run(test.serverType, func(t *testing.T) {
42562-			cc := test.ts.Connect(ctx)
42563-			sd := protocol.ServerDispatcher(cc)
42564-			cc.Go(ctx,
42565-				protocol.Handlers(
42566-					jsonrpc2.MethodNotFound))
42567-
42568-			ctx := context.Background()
42569-			ctx, cancel := context.WithCancel(ctx)
42570-
42571-			result := make(chan error)
42572-			go func() {
42573-				_, err := sd.Hover(ctx, &protocol.HoverParams{})
42574-				result <- err
42575-			}()
42576-			// Wait for the Hover request to start.
42577-			<-server.Started
42578-			cancel()
42579-			if err := <-result; err == nil {
42580-				t.Error("nil error for cancelled Hover(), want non-nil")
42581-			}
42582-			if err := <-server.Completed; err == nil || !strings.Contains(err.Error(), "cancelled hover") {
42583-				t.Errorf("Hover(): unexpected server-side error %v", err)
42584-			}
42585-		})
42586-	}
42587-}
42588-
42589-const exampleProgram = `
42590--- go.mod --
42591-module mod
42592-
42593-go 1.12
42594--- main.go --
42595-package main
42596-
42597-import "fmt"
42598-
42599-func main() {
42600-	fmt.Println("Hello World.")
42601-}`
42602-
42603-func TestDebugInfoLifecycle(t *testing.T) {
42604-	sb, err := fake.NewSandbox(&fake.SandboxConfig{Files: fake.UnpackTxt(exampleProgram)})
42605-	if err != nil {
42606-		t.Fatal(err)
42607-	}
42608-	defer func() {
42609-		if err := sb.Close(); err != nil {
42610-			// TODO(golang/go#38490): we can't currently make this an error because
42611-			// it fails on Windows: the workspace directory is still locked by a
42612-			// separate Go process.
42613-			// Once we have a reliable way to wait for proper shutdown, make this an
42614-			// error.
42615-			t.Logf("closing workspace failed: %v", err)
42616-		}
42617-	}()
42618-
42619-	baseCtx, cancel := context.WithCancel(context.Background())
42620-	defer cancel()
42621-	clientCtx := debug.WithInstance(baseCtx, "", "")
42622-	serverCtx := debug.WithInstance(baseCtx, "", "")
42623-
42624-	cache := cache.New(nil)
42625-	ss := NewStreamServer(cache, false, nil)
42626-	tsBackend := servertest.NewTCPServer(serverCtx, ss, nil)
42627-
42628-	forwarder, err := NewForwarder("tcp;"+tsBackend.Addr, nil)
42629-	if err != nil {
42630-		t.Fatal(err)
42631-	}
42632-	tsForwarder := servertest.NewPipeServer(forwarder, nil)
42633-
42634-	const skipApplyEdits = false
42635-	ed1, err := fake.NewEditor(sb, fake.EditorConfig{}).Connect(clientCtx, tsForwarder, fake.ClientHooks{}, skipApplyEdits)
42636-	if err != nil {
42637-		t.Fatal(err)
42638-	}
42639-	defer ed1.Close(clientCtx)
42640-	ed2, err := fake.NewEditor(sb, fake.EditorConfig{}).Connect(baseCtx, tsBackend, fake.ClientHooks{}, skipApplyEdits)
42641-	if err != nil {
42642-		t.Fatal(err)
42643-	}
42644-	defer ed2.Close(baseCtx)
42645-
42646-	serverDebug := debug.GetInstance(serverCtx)
42647-	if got, want := len(serverDebug.State.Clients()), 2; got != want {
42648-		t.Errorf("len(server:Clients) = %d, want %d", got, want)
42649-	}
42650-	if got, want := len(serverDebug.State.Sessions()), 2; got != want {
42651-		t.Errorf("len(server:Sessions) = %d, want %d", got, want)
42652-	}
42653-	clientDebug := debug.GetInstance(clientCtx)
42654-	if got, want := len(clientDebug.State.Servers()), 1; got != want {
42655-		t.Errorf("len(client:Servers) = %d, want %d", got, want)
42656-	}
42657-	// Close one of the connections to verify that the client and session were
42658-	// dropped.
42659-	if err := ed1.Close(clientCtx); err != nil {
42660-		t.Fatal(err)
42661-	}
42662-	/*TODO: at this point we have verified the editor is closed
42663-	However there is no way currently to wait for all associated go routines to
42664-	go away, and we need to wait for those to trigger the client drop
42665-	for now we just give it a little bit of time, but we need to fix this
42666-	in a principled way
42667-	*/
42668-	start := time.Now()
42669-	delay := time.Millisecond
42670-	const maxWait = time.Second
42671-	for len(serverDebug.State.Clients()) > 1 {
42672-		if time.Since(start) > maxWait {
42673-			break
42674-		}
42675-		time.Sleep(delay)
42676-		delay *= 2
42677-	}
42678-	if got, want := len(serverDebug.State.Clients()), 1; got != want {
42679-		t.Errorf("len(server:Clients) = %d, want %d", got, want)
42680-	}
42681-	if got, want := len(serverDebug.State.Sessions()), 1; got != want {
42682-		t.Errorf("len(server:Sessions()) = %d, want %d", got, want)
42683-	}
42684-}
42685-
42686-type initServer struct {
42687-	fakeServer
42688-
42689-	params *protocol.ParamInitialize
42690-}
42691-
42692-func (s *initServer) Initialize(ctx context.Context, params *protocol.ParamInitialize) (*protocol.InitializeResult, error) {
42693-	s.params = params
42694-	return &protocol.InitializeResult{}, nil
42695-}
42696-
42697-func TestEnvForwarding(t *testing.T) {
42698-	ctx := context.Background()
42699-
42700-	server := &initServer{}
42701-	_, tsForwarded, cleanup := setupForwarding(ctx, t, server)
42702-	defer cleanup()
42703-
42704-	conn := tsForwarded.Connect(ctx)
42705-	conn.Go(ctx, jsonrpc2.MethodNotFound)
42706-	dispatch := protocol.ServerDispatcher(conn)
42707-	initParams := &protocol.ParamInitialize{}
42708-	initParams.InitializationOptions = map[string]interface{}{
42709-		"env": map[string]interface{}{
42710-			"GONOPROXY": "example.com",
42711-		},
42712-	}
42713-	_, err := dispatch.Initialize(ctx, initParams)
42714-	if err != nil {
42715-		t.Fatal(err)
42716-	}
42717-	if server.params == nil {
42718-		t.Fatalf("initialize params are unset")
42719-	}
42720-	env := server.params.InitializationOptions.(map[string]interface{})["env"].(map[string]interface{})
42721-
42722-	// Check for an arbitrary Go variable. It should be set.
42723-	if _, ok := env["GOPRIVATE"]; !ok {
42724-		t.Errorf("Go environment variable GOPRIVATE unset in initialization options")
42725-	}
42726-	// Check that the variable present in our user config was not overwritten.
42727-	if v := env["GONOPROXY"]; v != "example.com" {
42728-		t.Errorf("GONOPROXY environment variable was overwritten")
42729-	}
42730-}
42731-
42732-func TestListenParsing(t *testing.T) {
42733-	tests := []struct {
42734-		input, wantNetwork, wantAddr string
42735-	}{
42736-		{"127.0.0.1:0", "tcp", "127.0.0.1:0"},
42737-		{"unix;/tmp/sock", "unix", "/tmp/sock"},
42738-		{"auto", "auto", ""},
42739-		{"auto;foo", "auto", "foo"},
42740-	}
42741-
42742-	for _, test := range tests {
42743-		gotNetwork, gotAddr := ParseAddr(test.input)
42744-		if gotNetwork != test.wantNetwork {
42745-			t.Errorf("network = %q, want %q", gotNetwork, test.wantNetwork)
42746-		}
42747-		if gotAddr != test.wantAddr {
42748-			t.Errorf("addr = %q, want %q", gotAddr, test.wantAddr)
42749-		}
42750-	}
42751-}
42752diff -urN a/gopls/internal/lsp/lsprpc/middleware.go b/gopls/internal/lsp/lsprpc/middleware.go
42753--- a/gopls/internal/lsp/lsprpc/middleware.go	2000-01-01 00:00:00.000000000 -0000
42754+++ b/gopls/internal/lsp/lsprpc/middleware.go	1970-01-01 00:00:00.000000000 +0000
42755@@ -1,142 +0,0 @@
42756-// Copyright 2021 The Go Authors. All rights reserved.
42757-// Use of this source code is governed by a BSD-style
42758-// license that can be found in the LICENSE file.
42759-
42760-package lsprpc
42761-
42762-import (
42763-	"context"
42764-	"encoding/json"
42765-	"fmt"
42766-	"sync"
42767-
42768-	"golang.org/x/tools/internal/event"
42769-	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
42770-)
42771-
42772-// Metadata holds arbitrary data transferred between jsonrpc2 peers.
42773-type Metadata map[string]interface{}
42774-
42775-// PeerInfo holds information about a peering between jsonrpc2 servers.
42776-type PeerInfo struct {
42777-	// RemoteID is the identity of the current server on its peer.
42778-	RemoteID int64
42779-
42780-	// LocalID is the identity of the peer on the server.
42781-	LocalID int64
42782-
42783-	// IsClient reports whether the peer is a client. If false, the peer is a
42784-	// server.
42785-	IsClient bool
42786-
42787-	// Metadata holds arbitrary information provided by the peer.
42788-	Metadata Metadata
42789-}
42790-
42791-// Handshaker handles both server and client handshaking over jsonrpc2. To
42792-// instrument server-side handshaking, use Handshaker.Middleware. To instrument
42793-// client-side handshaking, call Handshaker.ClientHandshake for any new
42794-// client-side connections.
42795-type Handshaker struct {
42796-	// Metadata will be shared with peers via handshaking.
42797-	Metadata Metadata
42798-
42799-	mu     sync.Mutex
42800-	prevID int64
42801-	peers  map[int64]PeerInfo
42802-}
42803-
42804-// Peers returns the peer info this handshaker knows about by way of either the
42805-// server-side handshake middleware, or client-side handshakes.
42806-func (h *Handshaker) Peers() []PeerInfo {
42807-	h.mu.Lock()
42808-	defer h.mu.Unlock()
42809-
42810-	var c []PeerInfo
42811-	for _, v := range h.peers {
42812-		c = append(c, v)
42813-	}
42814-	return c
42815-}
42816-
42817-// Middleware is a jsonrpc2 middleware function to augment connection binding
42818-// to handle the handshake method, and record disconnections.
42819-func (h *Handshaker) Middleware(inner jsonrpc2_v2.Binder) jsonrpc2_v2.Binder {
42820-	return BinderFunc(func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
42821-		opts := inner.Bind(ctx, conn)
42822-
42823-		localID := h.nextID()
42824-		info := &PeerInfo{
42825-			RemoteID: localID,
42826-			Metadata: h.Metadata,
42827-		}
42828-
42829-		// Wrap the delegated handler to accept the handshake.
42830-		delegate := opts.Handler
42831-		opts.Handler = jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
42832-			if req.Method == handshakeMethod {
42833-				var peerInfo PeerInfo
42834-				if err := json.Unmarshal(req.Params, &peerInfo); err != nil {
42835-					return nil, fmt.Errorf("%w: unmarshaling client info: %v", jsonrpc2_v2.ErrInvalidParams, err)
42836-				}
42837-				peerInfo.LocalID = localID
42838-				peerInfo.IsClient = true
42839-				h.recordPeer(peerInfo)
42840-				return info, nil
42841-			}
42842-			return delegate.Handle(ctx, req)
42843-		})
42844-
42845-		// Record the dropped client.
42846-		go h.cleanupAtDisconnect(conn, localID)
42847-
42848-		return opts
42849-	})
42850-}
42851-
42852-// ClientHandshake performs a client-side handshake with the server at the
42853-// other end of conn, recording the server's peer info and watching for conn's
42854-// disconnection.
42855-func (h *Handshaker) ClientHandshake(ctx context.Context, conn *jsonrpc2_v2.Connection) {
42856-	localID := h.nextID()
42857-	info := &PeerInfo{
42858-		RemoteID: localID,
42859-		Metadata: h.Metadata,
42860-	}
42861-
42862-	call := conn.Call(ctx, handshakeMethod, info)
42863-	var serverInfo PeerInfo
42864-	if err := call.Await(ctx, &serverInfo); err != nil {
42865-		event.Error(ctx, "performing handshake", err)
42866-		return
42867-	}
42868-	serverInfo.LocalID = localID
42869-	h.recordPeer(serverInfo)
42870-
42871-	go h.cleanupAtDisconnect(conn, localID)
42872-}
42873-
42874-func (h *Handshaker) nextID() int64 {
42875-	h.mu.Lock()
42876-	defer h.mu.Unlock()
42877-
42878-	h.prevID++
42879-	return h.prevID
42880-}
42881-
42882-func (h *Handshaker) cleanupAtDisconnect(conn *jsonrpc2_v2.Connection, peerID int64) {
42883-	conn.Wait()
42884-
42885-	h.mu.Lock()
42886-	defer h.mu.Unlock()
42887-	delete(h.peers, peerID)
42888-}
42889-
42890-func (h *Handshaker) recordPeer(info PeerInfo) {
42891-	h.mu.Lock()
42892-	defer h.mu.Unlock()
42893-	if h.peers == nil {
42894-		h.peers = make(map[int64]PeerInfo)
42895-	}
42896-	h.peers[info.LocalID] = info
42897-}
42898diff -urN a/gopls/internal/lsp/lsprpc/middleware_test.go b/gopls/internal/lsp/lsprpc/middleware_test.go
42899--- a/gopls/internal/lsp/lsprpc/middleware_test.go	2000-01-01 00:00:00.000000000 -0000
42900+++ b/gopls/internal/lsp/lsprpc/middleware_test.go	1970-01-01 00:00:00.000000000 +0000
42901@@ -1,93 +0,0 @@
42902-// Copyright 2021 The Go Authors. All rights reserved.
42903-// Use of this source code is governed by a BSD-style
42904-// license that can be found in the LICENSE file.
42905-
42906-package lsprpc_test
42907-
42908-import (
42909-	"context"
42910-	"errors"
42911-	"fmt"
42912-	"testing"
42913-	"time"
42914-
42915-	. "golang.org/x/tools/gopls/internal/lsp/lsprpc"
42916-	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
42917-)
42918-
42919-var noopBinder = BinderFunc(func(context.Context, *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
42920-	return jsonrpc2_v2.ConnectionOptions{}
42921-})
42922-
42923-func TestHandshakeMiddleware(t *testing.T) {
42924-	sh := &Handshaker{
42925-		Metadata: Metadata{
42926-			"answer": 42,
42927-		},
42928-	}
42929-	ctx := context.Background()
42930-	env := new(TestEnv)
42931-	defer env.Shutdown(t)
42932-	l, _ := env.serve(ctx, t, sh.Middleware(noopBinder))
42933-	conn := env.dial(ctx, t, l.Dialer(), noopBinder, false)
42934-	ch := &Handshaker{
42935-		Metadata: Metadata{
42936-			"question": 6 * 9,
42937-		},
42938-	}
42939-
42940-	check := func(connected bool) error {
42941-		clients := sh.Peers()
42942-		servers := ch.Peers()
42943-		want := 0
42944-		if connected {
42945-			want = 1
42946-		}
42947-		if got := len(clients); got != want {
42948-			return fmt.Errorf("got %d clients on the server, want %d", got, want)
42949-		}
42950-		if got := len(servers); got != want {
42951-			return fmt.Errorf("got %d servers on the client, want %d", got, want)
42952-		}
42953-		if !connected {
42954-			return nil
42955-		}
42956-		client := clients[0]
42957-		server := servers[0]
42958-		if _, ok := client.Metadata["question"]; !ok {
42959-			return errors.New("no client metadata")
42960-		}
42961-		if _, ok := server.Metadata["answer"]; !ok {
42962-			return errors.New("no server metadata")
42963-		}
42964-		if client.LocalID != server.RemoteID {
42965-			return fmt.Errorf("client.LocalID == %d, server.PeerID == %d", client.LocalID, server.RemoteID)
42966-		}
42967-		if client.RemoteID != server.LocalID {
42968-			return fmt.Errorf("client.PeerID == %d, server.LocalID == %d", client.RemoteID, server.LocalID)
42969-		}
42970-		return nil
42971-	}
42972-
42973-	if err := check(false); err != nil {
42974-		t.Fatalf("before handshake: %v", err)
42975-	}
42976-	ch.ClientHandshake(ctx, conn)
42977-	if err := check(true); err != nil {
42978-		t.Fatalf("after handshake: %v", err)
42979-	}
42980-	conn.Close()
42981-	// Wait for up to ~2s for connections to get cleaned up.
42982-	delay := 25 * time.Millisecond
42983-	for retries := 3; retries >= 0; retries-- {
42984-		time.Sleep(delay)
42985-		err := check(false)
42986-		if err == nil {
42987-			return
42988-		}
42989-		if retries == 0 {
42990-			t.Fatalf("after closing connection: %v", err)
42991-		}
42992-		delay *= 4
42993-	}
42994-}
42995diff -urN a/gopls/internal/lsp/lsp_test.go b/gopls/internal/lsp/lsp_test.go
42996--- a/gopls/internal/lsp/lsp_test.go	2000-01-01 00:00:00.000000000 -0000
42997+++ b/gopls/internal/lsp/lsp_test.go	1970-01-01 00:00:00.000000000 +0000
42998@@ -1,1360 +0,0 @@
42999-// Copyright 2018 The Go Authors. All rights reserved.
43000-// Use of this source code is governed by a BSD-style
43001-// license that can be found in the LICENSE file.
43002-
43003-package lsp
43004-
43005-import (
43006-	"bytes"
43007-	"context"
43008-	"fmt"
43009-	"os"
43010-	"os/exec"
43011-	"path/filepath"
43012-	"sort"
43013-	"strings"
43014-	"testing"
43015-
43016-	"github.com/google/go-cmp/cmp"
43017-	"github.com/google/go-cmp/cmp/cmpopts"
43018-	"golang.org/x/tools/gopls/internal/lsp/cache"
43019-	"golang.org/x/tools/gopls/internal/lsp/command"
43020-	"golang.org/x/tools/gopls/internal/lsp/protocol"
43021-	"golang.org/x/tools/gopls/internal/lsp/source"
43022-	"golang.org/x/tools/gopls/internal/lsp/tests"
43023-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
43024-	"golang.org/x/tools/gopls/internal/span"
43025-	"golang.org/x/tools/internal/bug"
43026-	"golang.org/x/tools/internal/diff"
43027-	"golang.org/x/tools/internal/event"
43028-	"golang.org/x/tools/internal/testenv"
43029-)
43030-
43031-func TestMain(m *testing.M) {
43032-	bug.PanicOnBugs = true
43033-	testenv.ExitIfSmallMachine()
43034-
43035-	// Set the global exporter to nil so that we don't log to stderr. This avoids
43036-	// a lot of misleading noise in test output.
43037-	//
43038-	// TODO(rfindley): investigate whether we can/should capture logs scoped to
43039-	// individual tests by passing in a context with a local exporter.
43040-	event.SetExporter(nil)
43041-
43042-	os.Exit(m.Run())
43043-}
43044-
43045-// TestLSP runs the marker tests in files beneath testdata/ using
43046-// implementations of each of the marker operations (e.g. @codelens) that
43047-// make LSP RPCs (e.g. textDocument/codeLens) to a gopls server.
43048-func TestLSP(t *testing.T) {
43049-	tests.RunTests(t, "testdata", true, testLSP)
43050-}
43051-
43052-func testLSP(t *testing.T, datum *tests.Data) {
43053-	ctx := tests.Context(t)
43054-
43055-	session := cache.NewSession(ctx, cache.New(nil), nil)
43056-	options := source.DefaultOptions().Clone()
43057-	tests.DefaultOptions(options)
43058-	session.SetOptions(options)
43059-	options.SetEnvSlice(datum.Config.Env)
43060-	view, snapshot, release, err := session.NewView(ctx, datum.Config.Dir, span.URIFromPath(datum.Config.Dir), options)
43061-	if err != nil {
43062-		t.Fatal(err)
43063-	}
43064-
43065-	defer session.RemoveView(view)
43066-
43067-	// Enable type error analyses for tests.
43068-	// TODO(golang/go#38212): Delete this once they are enabled by default.
43069-	tests.EnableAllAnalyzers(options)
43070-	session.SetViewOptions(ctx, view, options)
43071-
43072-	// Enable all inlay hints for tests.
43073-	tests.EnableAllInlayHints(options)
43074-
43075-	// Only run the -modfile specific tests in module mode with Go 1.14 or above.
43076-	datum.ModfileFlagAvailable = len(snapshot.ModFiles()) > 0 && testenv.Go1Point() >= 14
43077-	release()
43078-
43079-	// Open all files for performance reasons. This is done because gopls only
43080-	// keeps active packages in memory for open files.
43081-	//
43082-	// In practice clients will only send document-oriented requests for open
43083-	// files.
43084-	var modifications []source.FileModification
43085-	for _, module := range datum.Exported.Modules {
43086-		for name := range module.Files {
43087-			filename := datum.Exported.File(module.Name, name)
43088-			if filepath.Ext(filename) != ".go" {
43089-				continue
43090-			}
43091-			content, err := datum.Exported.FileContents(filename)
43092-			if err != nil {
43093-				t.Fatal(err)
43094-			}
43095-			modifications = append(modifications, source.FileModification{
43096-				URI:        span.URIFromPath(filename),
43097-				Action:     source.Open,
43098-				Version:    -1,
43099-				Text:       content,
43100-				LanguageID: "go",
43101-			})
43102-		}
43103-	}
43104-	for filename, content := range datum.Config.Overlay {
43105-		if filepath.Ext(filename) != ".go" {
43106-			continue
43107-		}
43108-		modifications = append(modifications, source.FileModification{
43109-			URI:        span.URIFromPath(filename),
43110-			Action:     source.Open,
43111-			Version:    -1,
43112-			Text:       content,
43113-			LanguageID: "go",
43114-		})
43115-	}
43116-	if err := session.ModifyFiles(ctx, modifications); err != nil {
43117-		t.Fatal(err)
43118-	}
43119-	r := &runner{
43120-		data:        datum,
43121-		ctx:         ctx,
43122-		normalizers: tests.CollectNormalizers(datum.Exported),
43123-		editRecv:    make(chan map[span.URI][]byte, 1),
43124-	}
43125-
43126-	r.server = NewServer(session, testClient{runner: r})
43127-	tests.Run(t, r, datum)
43128-}
43129-
43130-// runner implements tests.Tests by making LSP RPCs to a gopls server.
43131-type runner struct {
43132-	server      *Server
43133-	data        *tests.Data
43134-	diagnostics map[span.URI][]*source.Diagnostic
43135-	ctx         context.Context
43136-	normalizers []tests.Normalizer
43137-	editRecv    chan map[span.URI][]byte
43138-}
43139-
43140-// testClient stubs any client functions that may be called by LSP functions.
43141-type testClient struct {
43142-	protocol.Client
43143-	runner *runner
43144-}
43145-
43146-func (c testClient) Close() error {
43147-	return nil
43148-}
43149-
43150-// Trivially implement PublishDiagnostics so that we can call
43151-// server.publishReports below to de-dup sent diagnostics.
43152-func (c testClient) PublishDiagnostics(context.Context, *protocol.PublishDiagnosticsParams) error {
43153-	return nil
43154-}
43155-
43156-func (c testClient) ShowMessage(context.Context, *protocol.ShowMessageParams) error {
43157-	return nil
43158-}
43159-
43160-func (c testClient) ApplyEdit(ctx context.Context, params *protocol.ApplyWorkspaceEditParams) (*protocol.ApplyWorkspaceEditResult, error) {
43161-	res, err := applyTextDocumentEdits(c.runner, params.Edit.DocumentChanges)
43162-	if err != nil {
43163-		return nil, err
43164-	}
43165-	c.runner.editRecv <- res
43166-	return &protocol.ApplyWorkspaceEditResult{Applied: true}, nil
43167-}
43168-
43169-func (r *runner) CallHierarchy(t *testing.T, spn span.Span, expectedCalls *tests.CallHierarchyResult) {
43170-	mapper, err := r.data.Mapper(spn.URI())
43171-	if err != nil {
43172-		t.Fatal(err)
43173-	}
43174-	loc, err := mapper.SpanLocation(spn)
43175-	if err != nil {
43176-		t.Fatalf("failed for %v: %v", spn, err)
43177-	}
43178-
43179-	params := &protocol.CallHierarchyPrepareParams{
43180-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
43181-	}
43182-
43183-	items, err := r.server.PrepareCallHierarchy(r.ctx, params)
43184-	if err != nil {
43185-		t.Fatal(err)
43186-	}
43187-	if len(items) == 0 {
43188-		t.Fatalf("expected call hierarchy item to be returned for identifier at %v\n", loc.Range)
43189-	}
43190-
43191-	callLocation := protocol.Location{
43192-		URI:   items[0].URI,
43193-		Range: items[0].Range,
43194-	}
43195-	if callLocation != loc {
43196-		t.Fatalf("expected server.PrepareCallHierarchy to return identifier at %v but got %v\n", loc, callLocation)
43197-	}
43198-
43199-	incomingCalls, err := r.server.IncomingCalls(r.ctx, &protocol.CallHierarchyIncomingCallsParams{Item: items[0]})
43200-	if err != nil {
43201-		t.Error(err)
43202-	}
43203-	var incomingCallItems []protocol.CallHierarchyItem
43204-	for _, item := range incomingCalls {
43205-		incomingCallItems = append(incomingCallItems, item.From)
43206-	}
43207-	msg := tests.DiffCallHierarchyItems(incomingCallItems, expectedCalls.IncomingCalls)
43208-	if msg != "" {
43209-		t.Error(fmt.Sprintf("incoming calls: %s", msg))
43210-	}
43211-
43212-	outgoingCalls, err := r.server.OutgoingCalls(r.ctx, &protocol.CallHierarchyOutgoingCallsParams{Item: items[0]})
43213-	if err != nil {
43214-		t.Error(err)
43215-	}
43216-	var outgoingCallItems []protocol.CallHierarchyItem
43217-	for _, item := range outgoingCalls {
43218-		outgoingCallItems = append(outgoingCallItems, item.To)
43219-	}
43220-	msg = tests.DiffCallHierarchyItems(outgoingCallItems, expectedCalls.OutgoingCalls)
43221-	if msg != "" {
43222-		t.Error(fmt.Sprintf("outgoing calls: %s", msg))
43223-	}
43224-}
43225-
43226-func (r *runner) CodeLens(t *testing.T, uri span.URI, want []protocol.CodeLens) {
43227-	if !strings.HasSuffix(uri.Filename(), "go.mod") {
43228-		return
43229-	}
43230-	got, err := r.server.codeLens(r.ctx, &protocol.CodeLensParams{
43231-		TextDocument: protocol.TextDocumentIdentifier{
43232-			URI: protocol.DocumentURI(uri),
43233-		},
43234-	})
43235-	if err != nil {
43236-		t.Fatal(err)
43237-	}
43238-	if diff := tests.DiffCodeLens(uri, want, got); diff != "" {
43239-		t.Errorf("%s: %s", uri, diff)
43240-	}
43241-}
43242-
43243-func (r *runner) Diagnostics(t *testing.T, uri span.URI, want []*source.Diagnostic) {
43244-	// Get the diagnostics for this view if we have not done it before.
43245-	v := r.server.session.View(r.data.Config.Dir)
43246-	r.collectDiagnostics(v)
43247-	tests.CompareDiagnostics(t, uri, want, r.diagnostics[uri])
43248-}
43249-
43250-func (r *runner) FoldingRanges(t *testing.T, spn span.Span) {
43251-	uri := spn.URI()
43252-	view, err := r.server.session.ViewOf(uri)
43253-	if err != nil {
43254-		t.Fatal(err)
43255-	}
43256-	original := view.Options()
43257-	modified := original
43258-	defer r.server.session.SetViewOptions(r.ctx, view, original)
43259-
43260-	for _, test := range []struct {
43261-		lineFoldingOnly bool
43262-		prefix          string
43263-	}{
43264-		{false, "foldingRange"},
43265-		{true, "foldingRange-lineFolding"},
43266-	} {
43267-		modified.LineFoldingOnly = test.lineFoldingOnly
43268-		view, err = r.server.session.SetViewOptions(r.ctx, view, modified)
43269-		if err != nil {
43270-			t.Error(err)
43271-			continue
43272-		}
43273-		ranges, err := r.server.FoldingRange(r.ctx, &protocol.FoldingRangeParams{
43274-			TextDocument: protocol.TextDocumentIdentifier{
43275-				URI: protocol.URIFromSpanURI(uri),
43276-			},
43277-		})
43278-		if err != nil {
43279-			t.Error(err)
43280-			continue
43281-		}
43282-		r.foldingRanges(t, test.prefix, uri, ranges)
43283-	}
43284-}
43285-
43286-func (r *runner) foldingRanges(t *testing.T, prefix string, uri span.URI, ranges []protocol.FoldingRange) {
43287-	m, err := r.data.Mapper(uri)
43288-	if err != nil {
43289-		t.Fatal(err)
43290-	}
43291-	// Fold all ranges.
43292-	nonOverlapping := nonOverlappingRanges(ranges)
43293-	for i, rngs := range nonOverlapping {
43294-		got, err := foldRanges(m, string(m.Content), rngs)
43295-		if err != nil {
43296-			t.Error(err)
43297-			continue
43298-		}
43299-		tag := fmt.Sprintf("%s-%d", prefix, i)
43300-		want := string(r.data.Golden(t, tag, uri.Filename(), func() ([]byte, error) {
43301-			return []byte(got), nil
43302-		}))
43303-
43304-		if want != got {
43305-			t.Errorf("%s: foldingRanges failed for %s, expected:\n%v\ngot:\n%v", tag, uri.Filename(), want, got)
43306-		}
43307-	}
43308-
43309-	// Filter by kind.
43310-	kinds := []protocol.FoldingRangeKind{protocol.Imports, protocol.Comment}
43311-	for _, kind := range kinds {
43312-		var kindOnly []protocol.FoldingRange
43313-		for _, fRng := range ranges {
43314-			if fRng.Kind == string(kind) {
43315-				kindOnly = append(kindOnly, fRng)
43316-			}
43317-		}
43318-
43319-		nonOverlapping := nonOverlappingRanges(kindOnly)
43320-		for i, rngs := range nonOverlapping {
43321-			got, err := foldRanges(m, string(m.Content), rngs)
43322-			if err != nil {
43323-				t.Error(err)
43324-				continue
43325-			}
43326-			tag := fmt.Sprintf("%s-%s-%d", prefix, kind, i)
43327-			want := string(r.data.Golden(t, tag, uri.Filename(), func() ([]byte, error) {
43328-				return []byte(got), nil
43329-			}))
43330-
43331-			if want != got {
43332-				t.Errorf("%s: foldingRanges failed for %s, expected:\n%v\ngot:\n%v", tag, uri.Filename(), want, got)
43333-			}
43334-		}
43335-
43336-	}
43337-}
43338-
43339-func nonOverlappingRanges(ranges []protocol.FoldingRange) (res [][]protocol.FoldingRange) {
43340-	for _, fRng := range ranges {
43341-		setNum := len(res)
43342-		for i := 0; i < len(res); i++ {
43343-			canInsert := true
43344-			for _, rng := range res[i] {
43345-				if conflict(rng, fRng) {
43346-					canInsert = false
43347-					break
43348-				}
43349-			}
43350-			if canInsert {
43351-				setNum = i
43352-				break
43353-			}
43354-		}
43355-		if setNum == len(res) {
43356-			res = append(res, []protocol.FoldingRange{})
43357-		}
43358-		res[setNum] = append(res[setNum], fRng)
43359-	}
43360-	return res
43361-}
43362-
43363-func conflict(a, b protocol.FoldingRange) bool {
43364-	// a start position is <= b start positions
43365-	return (a.StartLine < b.StartLine || (a.StartLine == b.StartLine && a.StartCharacter <= b.StartCharacter)) &&
43366-		(a.EndLine > b.StartLine || (a.EndLine == b.StartLine && a.EndCharacter > b.StartCharacter))
43367-}
43368-
43369-func foldRanges(m *protocol.Mapper, contents string, ranges []protocol.FoldingRange) (string, error) {
43370-	foldedText := "<>"
43371-	res := contents
43372-	// Apply the edits from the end of the file forward
43373-	// to preserve the offsets
43374-	// TODO(adonovan): factor to use diff.ApplyEdits, which validates the input.
43375-	for i := len(ranges) - 1; i >= 0; i-- {
43376-		r := ranges[i]
43377-		start, err := m.PositionPoint(protocol.Position{Line: r.StartLine, Character: r.StartCharacter})
43378-		if err != nil {
43379-			return "", err
43380-		}
43381-		end, err := m.PositionPoint(protocol.Position{Line: r.EndLine, Character: r.EndCharacter})
43382-		if err != nil {
43383-			return "", err
43384-		}
43385-		res = res[:start.Offset()] + foldedText + res[end.Offset():]
43386-	}
43387-	return res, nil
43388-}
43389-
43390-func (r *runner) Format(t *testing.T, spn span.Span) {
43391-	uri := spn.URI()
43392-	filename := uri.Filename()
43393-	gofmted := r.data.Golden(t, "gofmt", filename, func() ([]byte, error) {
43394-		cmd := exec.Command("gofmt", filename)
43395-		out, _ := cmd.Output() // ignore error, sometimes we have intentionally ungofmt-able files
43396-		return out, nil
43397-	})
43398-
43399-	edits, err := r.server.Formatting(r.ctx, &protocol.DocumentFormattingParams{
43400-		TextDocument: protocol.TextDocumentIdentifier{
43401-			URI: protocol.URIFromSpanURI(uri),
43402-		},
43403-	})
43404-	if err != nil {
43405-		if len(gofmted) > 0 {
43406-			t.Error(err)
43407-		}
43408-		return
43409-	}
43410-	m, err := r.data.Mapper(uri)
43411-	if err != nil {
43412-		t.Fatal(err)
43413-	}
43414-	got, _, err := source.ApplyProtocolEdits(m, edits)
43415-	if err != nil {
43416-		t.Error(err)
43417-	}
43418-	if diff := compare.Bytes(gofmted, got); diff != "" {
43419-		t.Errorf("format failed for %s (-want +got):\n%s", filename, diff)
43420-	}
43421-}
43422-
43423-func (r *runner) SemanticTokens(t *testing.T, spn span.Span) {
43424-	uri := spn.URI()
43425-	filename := uri.Filename()
43426-	// this is called solely for coverage in semantic.go
43427-	_, err := r.server.semanticTokensFull(r.ctx, &protocol.SemanticTokensParams{
43428-		TextDocument: protocol.TextDocumentIdentifier{
43429-			URI: protocol.URIFromSpanURI(uri),
43430-		},
43431-	})
43432-	if err != nil {
43433-		t.Errorf("%v for %s", err, filename)
43434-	}
43435-	_, err = r.server.semanticTokensRange(r.ctx, &protocol.SemanticTokensRangeParams{
43436-		TextDocument: protocol.TextDocumentIdentifier{
43437-			URI: protocol.URIFromSpanURI(uri),
43438-		},
43439-		// any legal range. Just to exercise the call.
43440-		Range: protocol.Range{
43441-			Start: protocol.Position{
43442-				Line:      0,
43443-				Character: 0,
43444-			},
43445-			End: protocol.Position{
43446-				Line:      2,
43447-				Character: 0,
43448-			},
43449-		},
43450-	})
43451-	if err != nil {
43452-		t.Errorf("%v for Range %s", err, filename)
43453-	}
43454-}
43455-
43456-func (r *runner) Import(t *testing.T, spn span.Span) {
43457-	// Invokes textDocument/codeAction and applies all the "goimports" edits.
43458-
43459-	uri := spn.URI()
43460-	filename := uri.Filename()
43461-	actions, err := r.server.CodeAction(r.ctx, &protocol.CodeActionParams{
43462-		TextDocument: protocol.TextDocumentIdentifier{
43463-			URI: protocol.URIFromSpanURI(uri),
43464-		},
43465-	})
43466-	if err != nil {
43467-		t.Fatal(err)
43468-	}
43469-	m, err := r.data.Mapper(uri)
43470-	if err != nil {
43471-		t.Fatal(err)
43472-	}
43473-	got := m.Content
43474-	if len(actions) > 0 {
43475-		res, err := applyTextDocumentEdits(r, actions[0].Edit.DocumentChanges)
43476-		if err != nil {
43477-			t.Fatal(err)
43478-		}
43479-		got = res[uri]
43480-	}
43481-	want := r.data.Golden(t, "goimports", filename, func() ([]byte, error) {
43482-		return got, nil
43483-	})
43484-	if diff := compare.Bytes(want, got); diff != "" {
43485-		t.Errorf("import failed for %s:\n%s", filename, diff)
43486-	}
43487-}
43488-
43489-func (r *runner) SuggestedFix(t *testing.T, spn span.Span, actionKinds []tests.SuggestedFix, expectedActions int) {
43490-	uri := spn.URI()
43491-	view, err := r.server.session.ViewOf(uri)
43492-	if err != nil {
43493-		t.Fatal(err)
43494-	}
43495-
43496-	m, err := r.data.Mapper(uri)
43497-	if err != nil {
43498-		t.Fatal(err)
43499-	}
43500-	rng, err := m.SpanRange(spn)
43501-	if err != nil {
43502-		t.Fatal(err)
43503-	}
43504-	// Get the diagnostics for this view if we have not done it before.
43505-	r.collectDiagnostics(view)
43506-	var diagnostics []protocol.Diagnostic
43507-	for _, d := range r.diagnostics[uri] {
43508-		// Compare the start positions rather than the entire range because
43509-		// some diagnostics have a range with the same start and end position (8:1-8:1).
43510-		// The current marker functionality prevents us from having a range of 0 length.
43511-		if protocol.ComparePosition(d.Range.Start, rng.Start) == 0 {
43512-			diagnostics = append(diagnostics, toProtocolDiagnostics([]*source.Diagnostic{d})...)
43513-			break
43514-		}
43515-	}
43516-	var codeActionKinds []protocol.CodeActionKind
43517-	for _, k := range actionKinds {
43518-		codeActionKinds = append(codeActionKinds, protocol.CodeActionKind(k.ActionKind))
43519-	}
43520-	allActions, err := r.server.CodeAction(r.ctx, &protocol.CodeActionParams{
43521-		TextDocument: protocol.TextDocumentIdentifier{
43522-			URI: protocol.URIFromSpanURI(uri),
43523-		},
43524-		Range: rng,
43525-		Context: protocol.CodeActionContext{
43526-			Only:        codeActionKinds,
43527-			Diagnostics: diagnostics,
43528-		},
43529-	})
43530-	if err != nil {
43531-		t.Fatalf("CodeAction %s failed: %v", spn, err)
43532-	}
43533-	var actions []protocol.CodeAction
43534-	for _, action := range allActions {
43535-		for _, fix := range actionKinds {
43536-			if strings.Contains(action.Title, fix.Title) {
43537-				actions = append(actions, action)
43538-				break
43539-			}
43540-		}
43541-
43542-	}
43543-	if len(actions) != expectedActions {
43544-		var summaries []string
43545-		for _, a := range actions {
43546-			summaries = append(summaries, fmt.Sprintf("%q (%s)", a.Title, a.Kind))
43547-		}
43548-		t.Fatalf("CodeAction(...): got %d code actions (%v), want %d", len(actions), summaries, expectedActions)
43549-	}
43550-	action := actions[0]
43551-	var match bool
43552-	for _, k := range codeActionKinds {
43553-		if action.Kind == k {
43554-			match = true
43555-			break
43556-		}
43557-	}
43558-	if !match {
43559-		t.Fatalf("unexpected kind for code action %s, got %v, want one of %v", action.Title, action.Kind, codeActionKinds)
43560-	}
43561-	var res map[span.URI][]byte
43562-	if cmd := action.Command; cmd != nil {
43563-		_, err := r.server.ExecuteCommand(r.ctx, &protocol.ExecuteCommandParams{
43564-			Command:   action.Command.Command,
43565-			Arguments: action.Command.Arguments,
43566-		})
43567-		if err != nil {
43568-			t.Fatalf("error converting command %q to edits: %v", action.Command.Command, err)
43569-		}
43570-		res = <-r.editRecv
43571-	} else {
43572-		res, err = applyTextDocumentEdits(r, action.Edit.DocumentChanges)
43573-		if err != nil {
43574-			t.Fatal(err)
43575-		}
43576-	}
43577-	for u, got := range res {
43578-		want := r.data.Golden(t, "suggestedfix_"+tests.SpanName(spn), u.Filename(), func() ([]byte, error) {
43579-			return got, nil
43580-		})
43581-		if diff := compare.Bytes(want, got); diff != "" {
43582-			t.Errorf("suggested fixes failed for %s:\n%s", u.Filename(), diff)
43583-		}
43584-	}
43585-}
43586-
43587-func (r *runner) FunctionExtraction(t *testing.T, start span.Span, end span.Span) {
43588-	uri := start.URI()
43589-	m, err := r.data.Mapper(uri)
43590-	if err != nil {
43591-		t.Fatal(err)
43592-	}
43593-	spn := span.New(start.URI(), start.Start(), end.End())
43594-	rng, err := m.SpanRange(spn)
43595-	if err != nil {
43596-		t.Fatal(err)
43597-	}
43598-	actionsRaw, err := r.server.CodeAction(r.ctx, &protocol.CodeActionParams{
43599-		TextDocument: protocol.TextDocumentIdentifier{
43600-			URI: protocol.URIFromSpanURI(uri),
43601-		},
43602-		Range: rng,
43603-		Context: protocol.CodeActionContext{
43604-			Only: []protocol.CodeActionKind{"refactor.extract"},
43605-		},
43606-	})
43607-	if err != nil {
43608-		t.Fatal(err)
43609-	}
43610-	var actions []protocol.CodeAction
43611-	for _, action := range actionsRaw {
43612-		if action.Command.Title == "Extract function" {
43613-			actions = append(actions, action)
43614-		}
43615-	}
43616-	// Hack: We assume that we only get one code action per range.
43617-	// TODO(rstambler): Support multiple code actions per test.
43618-	if len(actions) == 0 || len(actions) > 1 {
43619-		t.Fatalf("unexpected number of code actions, want 1, got %v", len(actions))
43620-	}
43621-	_, err = r.server.ExecuteCommand(r.ctx, &protocol.ExecuteCommandParams{
43622-		Command:   actions[0].Command.Command,
43623-		Arguments: actions[0].Command.Arguments,
43624-	})
43625-	if err != nil {
43626-		t.Fatal(err)
43627-	}
43628-	res := <-r.editRecv
43629-	for u, got := range res {
43630-		want := r.data.Golden(t, "functionextraction_"+tests.SpanName(spn), u.Filename(), func() ([]byte, error) {
43631-			return got, nil
43632-		})
43633-		if diff := compare.Bytes(want, got); diff != "" {
43634-			t.Errorf("function extraction failed for %s:\n%s", u.Filename(), diff)
43635-		}
43636-	}
43637-}
43638-
43639-func (r *runner) MethodExtraction(t *testing.T, start span.Span, end span.Span) {
43640-	uri := start.URI()
43641-	m, err := r.data.Mapper(uri)
43642-	if err != nil {
43643-		t.Fatal(err)
43644-	}
43645-	spn := span.New(start.URI(), start.Start(), end.End())
43646-	rng, err := m.SpanRange(spn)
43647-	if err != nil {
43648-		t.Fatal(err)
43649-	}
43650-	actionsRaw, err := r.server.CodeAction(r.ctx, &protocol.CodeActionParams{
43651-		TextDocument: protocol.TextDocumentIdentifier{
43652-			URI: protocol.URIFromSpanURI(uri),
43653-		},
43654-		Range: rng,
43655-		Context: protocol.CodeActionContext{
43656-			Only: []protocol.CodeActionKind{"refactor.extract"},
43657-		},
43658-	})
43659-	if err != nil {
43660-		t.Fatal(err)
43661-	}
43662-	var actions []protocol.CodeAction
43663-	for _, action := range actionsRaw {
43664-		if action.Command.Title == "Extract method" {
43665-			actions = append(actions, action)
43666-		}
43667-	}
43668-	// Hack: We assume that we only get one matching code action per range.
43669-	// TODO(rstambler): Support multiple code actions per test.
43670-	if len(actions) == 0 || len(actions) > 1 {
43671-		t.Fatalf("unexpected number of code actions, want 1, got %v", len(actions))
43672-	}
43673-	_, err = r.server.ExecuteCommand(r.ctx, &protocol.ExecuteCommandParams{
43674-		Command:   actions[0].Command.Command,
43675-		Arguments: actions[0].Command.Arguments,
43676-	})
43677-	if err != nil {
43678-		t.Fatal(err)
43679-	}
43680-	res := <-r.editRecv
43681-	for u, got := range res {
43682-		want := r.data.Golden(t, "methodextraction_"+tests.SpanName(spn), u.Filename(), func() ([]byte, error) {
43683-			return got, nil
43684-		})
43685-		if diff := compare.Bytes(want, got); diff != "" {
43686-			t.Errorf("method extraction failed for %s:\n%s", u.Filename(), diff)
43687-		}
43688-	}
43689-}
43690-
43691-// TODO(rfindley): This handler needs more work. The output is still a bit hard
43692-// to read (range diffs do not format nicely), and it is too entangled with hover.
43693-func (r *runner) Definition(t *testing.T, _ span.Span, d tests.Definition) {
43694-	sm, err := r.data.Mapper(d.Src.URI())
43695-	if err != nil {
43696-		t.Fatal(err)
43697-	}
43698-	loc, err := sm.SpanLocation(d.Src)
43699-	if err != nil {
43700-		t.Fatalf("failed for %v: %v", d.Src, err)
43701-	}
43702-	tdpp := protocol.LocationTextDocumentPositionParams(loc)
43703-	var got []protocol.Location
43704-	var hover *protocol.Hover
43705-	if d.IsType {
43706-		params := &protocol.TypeDefinitionParams{
43707-			TextDocumentPositionParams: tdpp,
43708-		}
43709-		got, err = r.server.TypeDefinition(r.ctx, params)
43710-	} else {
43711-		params := &protocol.DefinitionParams{
43712-			TextDocumentPositionParams: tdpp,
43713-		}
43714-		got, err = r.server.Definition(r.ctx, params)
43715-		if err != nil {
43716-			t.Fatalf("failed for %v: %+v", d.Src, err)
43717-		}
43718-		v := &protocol.HoverParams{
43719-			TextDocumentPositionParams: tdpp,
43720-		}
43721-		hover, err = r.server.Hover(r.ctx, v)
43722-	}
43723-	if err != nil {
43724-		t.Fatalf("failed for %v: %v", d.Src, err)
43725-	}
43726-	dm, err := r.data.Mapper(d.Def.URI())
43727-	if err != nil {
43728-		t.Fatal(err)
43729-	}
43730-	def, err := dm.SpanLocation(d.Def)
43731-	if err != nil {
43732-		t.Fatal(err)
43733-	}
43734-	if !d.OnlyHover {
43735-		want := []protocol.Location{def}
43736-		if diff := cmp.Diff(want, got); diff != "" {
43737-			t.Fatalf("Definition(%s) mismatch (-want +got):\n%s", d.Src, diff)
43738-		}
43739-	}
43740-	didSomething := false
43741-	if hover != nil {
43742-		didSomething = true
43743-		tag := fmt.Sprintf("%s-hoverdef", d.Name)
43744-		want := string(r.data.Golden(t, tag, d.Src.URI().Filename(), func() ([]byte, error) {
43745-			return []byte(hover.Contents.Value), nil
43746-		}))
43747-		got := hover.Contents.Value
43748-		if diff := tests.DiffMarkdown(want, got); diff != "" {
43749-			t.Errorf("%s: markdown mismatch:\n%s", d.Src, diff)
43750-		}
43751-	}
43752-	if !d.OnlyHover {
43753-		didSomething = true
43754-		locURI := got[0].URI.SpanURI()
43755-		lm, err := r.data.Mapper(locURI)
43756-		if err != nil {
43757-			t.Fatal(err)
43758-		}
43759-		if def, err := lm.LocationSpan(got[0]); err != nil {
43760-			t.Fatalf("failed for %v: %v", got[0], err)
43761-		} else if def != d.Def {
43762-			t.Errorf("for %v got %v want %v", d.Src, def, d.Def)
43763-		}
43764-	}
43765-	if !didSomething {
43766-		t.Errorf("no tests ran for %s", d.Src.URI())
43767-	}
43768-}
43769-
43770-func (r *runner) Implementation(t *testing.T, spn span.Span, wantSpans []span.Span) {
43771-	sm, err := r.data.Mapper(spn.URI())
43772-	if err != nil {
43773-		t.Fatal(err)
43774-	}
43775-	loc, err := sm.SpanLocation(spn)
43776-	if err != nil {
43777-		t.Fatal(err)
43778-	}
43779-	gotImpls, err := r.server.Implementation(r.ctx, &protocol.ImplementationParams{
43780-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
43781-	})
43782-	if err != nil {
43783-		t.Fatalf("Server.Implementation(%s): %v", spn, err)
43784-	}
43785-	gotLocs, err := tests.LocationsToSpans(r.data, gotImpls)
43786-	if err != nil {
43787-		t.Fatal(err)
43788-	}
43789-	sanitize := func(s string) string {
43790-		return strings.ReplaceAll(s, r.data.Config.Dir, "gopls/internal/lsp/testdata")
43791-	}
43792-	want := sanitize(tests.SortAndFormatSpans(wantSpans))
43793-	got := sanitize(tests.SortAndFormatSpans(gotLocs))
43794-	if got != want {
43795-		t.Errorf("implementations(%s):\n%s", sanitize(fmt.Sprint(spn)), diff.Unified("want", "got", want, got))
43796-	}
43797-}
43798-
43799-func (r *runner) Highlight(t *testing.T, src span.Span, spans []span.Span) {
43800-	m, err := r.data.Mapper(src.URI())
43801-	if err != nil {
43802-		t.Fatal(err)
43803-	}
43804-	loc, err := m.SpanLocation(src)
43805-	if err != nil {
43806-		t.Fatal(err)
43807-	}
43808-	params := &protocol.DocumentHighlightParams{
43809-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
43810-	}
43811-	highlights, err := r.server.DocumentHighlight(r.ctx, params)
43812-	if err != nil {
43813-		t.Fatalf("DocumentHighlight(%v) failed: %v", params, err)
43814-	}
43815-	var got []protocol.Range
43816-	for _, h := range highlights {
43817-		got = append(got, h.Range)
43818-	}
43819-
43820-	var want []protocol.Range
43821-	for _, s := range spans {
43822-		rng, err := m.SpanRange(s)
43823-		if err != nil {
43824-			t.Fatalf("Mapper.SpanRange(%v) failed: %v", s, err)
43825-		}
43826-		want = append(want, rng)
43827-	}
43828-
43829-	sortRanges := func(s []protocol.Range) {
43830-		sort.Slice(s, func(i, j int) bool {
43831-			return protocol.CompareRange(s[i], s[j]) < 0
43832-		})
43833-	}
43834-
43835-	sortRanges(got)
43836-	sortRanges(want)
43837-
43838-	if diff := cmp.Diff(want, got); diff != "" {
43839-		t.Errorf("DocumentHighlight(%v) mismatch (-want +got):\n%s", src, diff)
43840-	}
43841-}
43842-
43843-func (r *runner) References(t *testing.T, src span.Span, itemList []span.Span) {
43844-	// This test is substantially the same as (*runner).References in source/source_test.go.
43845-	// TODO(adonovan): Factor (and remove fluff). Where should the common code live?
43846-
43847-	sm, err := r.data.Mapper(src.URI())
43848-	if err != nil {
43849-		t.Fatal(err)
43850-	}
43851-	loc, err := sm.SpanLocation(src)
43852-	if err != nil {
43853-		t.Fatalf("failed for %v: %v", src, err)
43854-	}
43855-	for _, includeDeclaration := range []bool{true, false} {
43856-		t.Run(fmt.Sprintf("refs-declaration-%v", includeDeclaration), func(t *testing.T) {
43857-			want := make(map[protocol.Location]bool)
43858-			for i, pos := range itemList {
43859-				// We don't want the first result if we aren't including the declaration.
43860-				// TODO(adonovan): don't assume a single declaration:
43861-				// there may be >1 if corresponding methods are considered.
43862-				if i == 0 && !includeDeclaration {
43863-					continue
43864-				}
43865-				m, err := r.data.Mapper(pos.URI())
43866-				if err != nil {
43867-					t.Fatal(err)
43868-				}
43869-				loc, err := m.SpanLocation(pos)
43870-				if err != nil {
43871-					t.Fatalf("failed for %v: %v", src, err)
43872-				}
43873-				want[loc] = true
43874-			}
43875-			params := &protocol.ReferenceParams{
43876-				TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
43877-				Context: protocol.ReferenceContext{
43878-					IncludeDeclaration: includeDeclaration,
43879-				},
43880-			}
43881-			got, err := r.server.References(r.ctx, params)
43882-			if err != nil {
43883-				t.Fatalf("failed for %v: %v", src, err)
43884-			}
43885-
43886-			sanitize := func(s string) string {
43887-				// In practice, CONFIGDIR means "gopls/internal/lsp/testdata".
43888-				return strings.ReplaceAll(s, r.data.Config.Dir, "CONFIGDIR")
43889-			}
43890-			formatLocation := func(loc protocol.Location) string {
43891-				return fmt.Sprintf("%s:%d.%d-%d.%d",
43892-					sanitize(string(loc.URI)),
43893-					loc.Range.Start.Line+1,
43894-					loc.Range.Start.Character+1,
43895-					loc.Range.End.Line+1,
43896-					loc.Range.End.Character+1)
43897-			}
43898-			toSlice := func(set map[protocol.Location]bool) []protocol.Location {
43899-				// TODO(adonovan): use generic maps.Keys(), someday.
43900-				list := make([]protocol.Location, 0, len(set))
43901-				for key := range set {
43902-					list = append(list, key)
43903-				}
43904-				return list
43905-			}
43906-			toString := func(locs []protocol.Location) string {
43907-				// TODO(adonovan): use generic JoinValues(locs, formatLocation).
43908-				strs := make([]string, len(locs))
43909-				for i, loc := range locs {
43910-					strs[i] = formatLocation(loc)
43911-				}
43912-				sort.Strings(strs)
43913-				return strings.Join(strs, "\n")
43914-			}
43915-			gotStr := toString(got)
43916-			wantStr := toString(toSlice(want))
43917-			if gotStr != wantStr {
43918-				t.Errorf("incorrect references (got %d, want %d) at %s:\n%s",
43919-					len(got), len(want),
43920-					formatLocation(loc),
43921-					diff.Unified("want", "got", wantStr, gotStr))
43922-			}
43923-		})
43924-	}
43925-}
43926-
43927-func (r *runner) InlayHints(t *testing.T, spn span.Span) {
43928-	uri := spn.URI()
43929-	filename := uri.Filename()
43930-
43931-	hints, err := r.server.InlayHint(r.ctx, &protocol.InlayHintParams{
43932-		TextDocument: protocol.TextDocumentIdentifier{
43933-			URI: protocol.URIFromSpanURI(uri),
43934-		},
43935-		// TODO: add Range
43936-	})
43937-	if err != nil {
43938-		t.Fatal(err)
43939-	}
43940-
43941-	// Map inlay hints to text edits.
43942-	edits := make([]protocol.TextEdit, len(hints))
43943-	for i, hint := range hints {
43944-		var paddingLeft, paddingRight string
43945-		if hint.PaddingLeft {
43946-			paddingLeft = " "
43947-		}
43948-		if hint.PaddingRight {
43949-			paddingRight = " "
43950-		}
43951-		edits[i] = protocol.TextEdit{
43952-			Range:   protocol.Range{Start: hint.Position, End: hint.Position},
43953-			NewText: fmt.Sprintf("<%s%s%s>", paddingLeft, hint.Label[0].Value, paddingRight),
43954-		}
43955-	}
43956-
43957-	m, err := r.data.Mapper(uri)
43958-	if err != nil {
43959-		t.Fatal(err)
43960-	}
43961-	got, _, err := source.ApplyProtocolEdits(m, edits)
43962-	if err != nil {
43963-		t.Error(err)
43964-	}
43965-
43966-	withinlayHints := r.data.Golden(t, "inlayHint", filename, func() ([]byte, error) {
43967-		return got, nil
43968-	})
43969-
43970-	if !bytes.Equal(withinlayHints, got) {
43971-		t.Errorf("inlay hints failed for %s, expected:\n%s\ngot:\n%s", filename, withinlayHints, got)
43972-	}
43973-}
43974-
43975-func (r *runner) Rename(t *testing.T, spn span.Span, newText string) {
43976-	tag := fmt.Sprintf("%s-rename", newText)
43977-
43978-	uri := spn.URI()
43979-	filename := uri.Filename()
43980-	sm, err := r.data.Mapper(uri)
43981-	if err != nil {
43982-		t.Fatal(err)
43983-	}
43984-	loc, err := sm.SpanLocation(spn)
43985-	if err != nil {
43986-		t.Fatalf("failed for %v: %v", spn, err)
43987-	}
43988-
43989-	wedit, err := r.server.Rename(r.ctx, &protocol.RenameParams{
43990-		TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI},
43991-		Position:     loc.Range.Start,
43992-		NewName:      newText,
43993-	})
43994-	if err != nil {
43995-		renamed := string(r.data.Golden(t, tag, filename, func() ([]byte, error) {
43996-			return []byte(err.Error()), nil
43997-		}))
43998-		if err.Error() != renamed {
43999-			t.Errorf("%s: rename failed for %s, expected:\n%v\ngot:\n%v\n", spn, newText, renamed, err)
44000-		}
44001-		return
44002-	}
44003-	res, err := applyTextDocumentEdits(r, wedit.DocumentChanges)
44004-	if err != nil {
44005-		t.Fatal(err)
44006-	}
44007-	var orderedURIs []string
44008-	for uri := range res {
44009-		orderedURIs = append(orderedURIs, string(uri))
44010-	}
44011-	sort.Strings(orderedURIs)
44012-
44013-	// Print the name and content of each modified file,
44014-	// concatenated, and compare against the golden.
44015-	var buf bytes.Buffer
44016-	for i := 0; i < len(res); i++ {
44017-		if i != 0 {
44018-			buf.WriteByte('\n')
44019-		}
44020-		uri := span.URIFromURI(orderedURIs[i])
44021-		if len(res) > 1 {
44022-			buf.WriteString(filepath.Base(uri.Filename()))
44023-			buf.WriteString(":\n")
44024-		}
44025-		buf.Write(res[uri])
44026-	}
44027-	got := buf.Bytes()
44028-	want := r.data.Golden(t, tag, filename, func() ([]byte, error) {
44029-		return got, nil
44030-	})
44031-	if diff := compare.Bytes(want, got); diff != "" {
44032-		t.Errorf("rename failed for %s:\n%s", newText, diff)
44033-	}
44034-}
44035-
44036-func (r *runner) PrepareRename(t *testing.T, src span.Span, want *source.PrepareItem) {
44037-	m, err := r.data.Mapper(src.URI())
44038-	if err != nil {
44039-		t.Fatal(err)
44040-	}
44041-	loc, err := m.SpanLocation(src)
44042-	if err != nil {
44043-		t.Fatalf("failed for %v: %v", src, err)
44044-	}
44045-	params := &protocol.PrepareRenameParams{
44046-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
44047-	}
44048-	got, err := r.server.PrepareRename(context.Background(), params)
44049-	if err != nil {
44050-		t.Errorf("prepare rename failed for %v: got error: %v", src, err)
44051-		return
44052-	}
44053-
44054-	// TODO(rfindley): can we consolidate on a single representation for
44055-	// PrepareRename results, and use cmp.Diff here?
44056-
44057-	// PrepareRename may fail with no error if there was no object found at the
44058-	// position.
44059-	if got == nil {
44060-		if want.Text != "" { // expected an ident.
44061-			t.Errorf("prepare rename failed for %v: got nil", src)
44062-		}
44063-		return
44064-	}
44065-	if got.Range.Start == got.Range.End {
44066-		// Special case for 0-length ranges. Marks can't specify a 0-length range,
44067-		// so just compare the start.
44068-		if got.Range.Start != want.Range.Start {
44069-			t.Errorf("prepare rename failed: incorrect point, got %v want %v", got.Range.Start, want.Range.Start)
44070-		}
44071-	} else {
44072-		if got.Range != want.Range {
44073-			t.Errorf("prepare rename failed: incorrect range got %v want %v", got.Range, want.Range)
44074-		}
44075-	}
44076-	if got.Placeholder != want.Text {
44077-		t.Errorf("prepare rename failed: incorrect text got %v want %v", got.Placeholder, want.Text)
44078-	}
44079-}
44080-
44081-func applyTextDocumentEdits(r *runner, edits []protocol.DocumentChanges) (map[span.URI][]byte, error) {
44082-	res := make(map[span.URI][]byte)
44083-	for _, docEdits := range edits {
44084-		if docEdits.TextDocumentEdit != nil {
44085-			uri := docEdits.TextDocumentEdit.TextDocument.URI.SpanURI()
44086-			var m *protocol.Mapper
44087-			// If we have already edited this file, we use the edited version (rather than the
44088-			// file in its original state) so that we preserve our initial changes.
44089-			if content, ok := res[uri]; ok {
44090-				m = protocol.NewMapper(uri, content)
44091-			} else {
44092-				var err error
44093-				if m, err = r.data.Mapper(uri); err != nil {
44094-					return nil, err
44095-				}
44096-			}
44097-			patched, _, err := source.ApplyProtocolEdits(m, docEdits.TextDocumentEdit.Edits)
44098-			if err != nil {
44099-				return nil, err
44100-			}
44101-			res[uri] = patched
44102-		}
44103-	}
44104-	return res, nil
44105-}
44106-
44107-func (r *runner) Symbols(t *testing.T, uri span.URI, expectedSymbols []protocol.DocumentSymbol) {
44108-	params := &protocol.DocumentSymbolParams{
44109-		TextDocument: protocol.TextDocumentIdentifier{
44110-			URI: protocol.URIFromSpanURI(uri),
44111-		},
44112-	}
44113-	got, err := r.server.DocumentSymbol(r.ctx, params)
44114-	if err != nil {
44115-		t.Fatal(err)
44116-	}
44117-
44118-	symbols := make([]protocol.DocumentSymbol, len(got))
44119-	for i, s := range got {
44120-		s, ok := s.(protocol.DocumentSymbol)
44121-		if !ok {
44122-			t.Fatalf("%v: wanted []DocumentSymbols but got %v", uri, got)
44123-		}
44124-		symbols[i] = s
44125-	}
44126-
44127-	// Sort by position to make it easier to find errors.
44128-	sortSymbols := func(s []protocol.DocumentSymbol) {
44129-		sort.Slice(s, func(i, j int) bool {
44130-			return protocol.CompareRange(s[i].SelectionRange, s[j].SelectionRange) < 0
44131-		})
44132-	}
44133-	sortSymbols(expectedSymbols)
44134-	sortSymbols(symbols)
44135-
44136-	// Ignore 'Range' here as it is difficult (impossible?) to express
44137-	// multi-line ranges in the packagestest framework.
44138-	ignoreRange := cmpopts.IgnoreFields(protocol.DocumentSymbol{}, "Range")
44139-	if diff := cmp.Diff(expectedSymbols, symbols, ignoreRange); diff != "" {
44140-		t.Errorf("mismatching symbols (-want +got)\n%s", diff)
44141-	}
44142-}
44143-
44144-func (r *runner) WorkspaceSymbols(t *testing.T, uri span.URI, query string, typ tests.WorkspaceSymbolsTestType) {
44145-	matcher := tests.WorkspaceSymbolsTestTypeToMatcher(typ)
44146-
44147-	original := r.server.session.Options()
44148-	modified := original
44149-	modified.SymbolMatcher = matcher
44150-	r.server.session.SetOptions(modified)
44151-	defer r.server.session.SetOptions(original)
44152-
44153-	params := &protocol.WorkspaceSymbolParams{
44154-		Query: query,
44155-	}
44156-	gotSymbols, err := r.server.Symbol(r.ctx, params)
44157-	if err != nil {
44158-		t.Fatal(err)
44159-	}
44160-	got, err := tests.WorkspaceSymbolsString(r.ctx, r.data, uri, gotSymbols)
44161-	if err != nil {
44162-		t.Fatal(err)
44163-	}
44164-	got = filepath.ToSlash(tests.Normalize(got, r.normalizers))
44165-	want := string(r.data.Golden(t, fmt.Sprintf("workspace_symbol-%s-%s", strings.ToLower(string(matcher)), query), uri.Filename(), func() ([]byte, error) {
44166-		return []byte(got), nil
44167-	}))
44168-	if diff := compare.Text(want, got); diff != "" {
44169-		t.Error(diff)
44170-	}
44171-}
44172-
44173-func (r *runner) SignatureHelp(t *testing.T, spn span.Span, want *protocol.SignatureHelp) {
44174-	m, err := r.data.Mapper(spn.URI())
44175-	if err != nil {
44176-		t.Fatal(err)
44177-	}
44178-	loc, err := m.SpanLocation(spn)
44179-	if err != nil {
44180-		t.Fatalf("failed for %v: %v", loc, err)
44181-	}
44182-	params := &protocol.SignatureHelpParams{
44183-		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
44184-	}
44185-	got, err := r.server.SignatureHelp(r.ctx, params)
44186-	if err != nil {
44187-		// Only fail if we got an error we did not expect.
44188-		if want != nil {
44189-			t.Fatal(err)
44190-		}
44191-		return
44192-	}
44193-	if want == nil {
44194-		if got != nil {
44195-			t.Errorf("expected no signature, got %v", got)
44196-		}
44197-		return
44198-	}
44199-	if got == nil {
44200-		t.Fatalf("expected %v, got nil", want)
44201-	}
44202-	if diff := tests.DiffSignatures(spn, want, got); diff != "" {
44203-		t.Error(diff)
44204-	}
44205-}
44206-
44207-func (r *runner) Link(t *testing.T, uri span.URI, wantLinks []tests.Link) {
44208-	m, err := r.data.Mapper(uri)
44209-	if err != nil {
44210-		t.Fatal(err)
44211-	}
44212-	got, err := r.server.DocumentLink(r.ctx, &protocol.DocumentLinkParams{
44213-		TextDocument: protocol.TextDocumentIdentifier{
44214-			URI: protocol.URIFromSpanURI(uri),
44215-		},
44216-	})
44217-	if err != nil {
44218-		t.Fatal(err)
44219-	}
44220-	if diff := tests.DiffLinks(m, wantLinks, got); diff != "" {
44221-		t.Error(diff)
44222-	}
44223-}
44224-
44225-func (r *runner) AddImport(t *testing.T, uri span.URI, expectedImport string) {
44226-	cmd, err := command.NewListKnownPackagesCommand("List Known Packages", command.URIArg{
44227-		URI: protocol.URIFromSpanURI(uri),
44228-	})
44229-	if err != nil {
44230-		t.Fatal(err)
44231-	}
44232-	resp, err := r.server.executeCommand(r.ctx, &protocol.ExecuteCommandParams{
44233-		Command:   cmd.Command,
44234-		Arguments: cmd.Arguments,
44235-	})
44236-	if err != nil {
44237-		t.Fatal(err)
44238-	}
44239-	res := resp.(command.ListKnownPackagesResult)
44240-	var hasPkg bool
44241-	for _, p := range res.Packages {
44242-		if p == expectedImport {
44243-			hasPkg = true
44244-			break
44245-		}
44246-	}
44247-	if !hasPkg {
44248-		t.Fatalf("%s: got %v packages\nwant contains %q", command.ListKnownPackages, res.Packages, expectedImport)
44249-	}
44250-	cmd, err = command.NewAddImportCommand("Add Imports", command.AddImportArgs{
44251-		URI:        protocol.URIFromSpanURI(uri),
44252-		ImportPath: expectedImport,
44253-	})
44254-	if err != nil {
44255-		t.Fatal(err)
44256-	}
44257-	_, err = r.server.executeCommand(r.ctx, &protocol.ExecuteCommandParams{
44258-		Command:   cmd.Command,
44259-		Arguments: cmd.Arguments,
44260-	})
44261-	if err != nil {
44262-		t.Fatal(err)
44263-	}
44264-	got := (<-r.editRecv)[uri]
44265-	want := r.data.Golden(t, "addimport", uri.Filename(), func() ([]byte, error) {
44266-		return []byte(got), nil
44267-	})
44268-	if want == nil {
44269-		t.Fatalf("golden file %q not found", uri.Filename())
44270-	}
44271-	if diff := compare.Bytes(want, got); diff != "" {
44272-		t.Errorf("%s mismatch\n%s", command.AddImport, diff)
44273-	}
44274-}
44275-
44276-func (r *runner) SelectionRanges(t *testing.T, spn span.Span) {
44277-	uri := spn.URI()
44278-	sm, err := r.data.Mapper(uri)
44279-	if err != nil {
44280-		t.Fatal(err)
44281-	}
44282-	loc, err := sm.SpanLocation(spn)
44283-	if err != nil {
44284-		t.Error(err)
44285-	}
44286-
44287-	ranges, err := r.server.selectionRange(r.ctx, &protocol.SelectionRangeParams{
44288-		TextDocument: protocol.TextDocumentIdentifier{
44289-			URI: protocol.URIFromSpanURI(uri),
44290-		},
44291-		Positions: []protocol.Position{loc.Range.Start},
44292-	})
44293-	if err != nil {
44294-		t.Fatal(err)
44295-	}
44296-
44297-	sb := &strings.Builder{}
44298-	for i, path := range ranges {
44299-		fmt.Fprintf(sb, "Ranges %d: ", i)
44300-		rng := path
44301-		for {
44302-			s, e, err := sm.RangeOffsets(rng.Range)
44303-			if err != nil {
44304-				t.Error(err)
44305-			}
44306-
44307-			var snippet string
44308-			if e-s < 30 {
44309-				snippet = string(sm.Content[s:e])
44310-			} else {
44311-				snippet = string(sm.Content[s:s+15]) + "..." + string(sm.Content[e-15:e])
44312-			}
44313-
44314-			fmt.Fprintf(sb, "\n\t%v %q", rng.Range, strings.ReplaceAll(snippet, "\n", "\\n"))
44315-
44316-			if rng.Parent == nil {
44317-				break
44318-			}
44319-			rng = *rng.Parent
44320-		}
44321-		sb.WriteRune('\n')
44322-	}
44323-	got := sb.String()
44324-
44325-	testName := "selectionrange_" + tests.SpanName(spn)
44326-	want := r.data.Golden(t, testName, uri.Filename(), func() ([]byte, error) {
44327-		return []byte(got), nil
44328-	})
44329-	if want == nil {
44330-		t.Fatalf("golden file %q not found", uri.Filename())
44331-	}
44332-	if diff := compare.Text(got, string(want)); diff != "" {
44333-		t.Errorf("%s mismatch\n%s", testName, diff)
44334-	}
44335-}
44336-
44337-func (r *runner) collectDiagnostics(view *cache.View) {
44338-	if r.diagnostics != nil {
44339-		return
44340-	}
44341-	r.diagnostics = make(map[span.URI][]*source.Diagnostic)
44342-
44343-	snapshot, release, err := view.Snapshot()
44344-	if err != nil {
44345-		panic(err)
44346-	}
44347-	defer release()
44348-
44349-	// Always run diagnostics with analysis.
44350-	r.server.diagnose(r.ctx, snapshot, true)
44351-	for uri, reports := range r.server.diagnostics {
44352-		for _, report := range reports.reports {
44353-			for _, d := range report.diags {
44354-				r.diagnostics[uri] = append(r.diagnostics[uri], d)
44355-			}
44356-		}
44357-	}
44358-}
44359diff -urN a/gopls/internal/lsp/mod/code_lens.go b/gopls/internal/lsp/mod/code_lens.go
44360--- a/gopls/internal/lsp/mod/code_lens.go	2000-01-01 00:00:00.000000000 -0000
44361+++ b/gopls/internal/lsp/mod/code_lens.go	1970-01-01 00:00:00.000000000 +0000
44362@@ -1,191 +0,0 @@
44363-// Copyright 2020 The Go Authors. All rights reserved.
44364-// Use of this source code is governed by a BSD-style
44365-// license that can be found in the LICENSE file.
44366-
44367-package mod
44368-
44369-import (
44370-	"context"
44371-	"fmt"
44372-	"os"
44373-	"path/filepath"
44374-
44375-	"golang.org/x/mod/modfile"
44376-	"golang.org/x/tools/gopls/internal/lsp/command"
44377-	"golang.org/x/tools/gopls/internal/lsp/protocol"
44378-	"golang.org/x/tools/gopls/internal/lsp/source"
44379-)
44380-
44381-// LensFuncs returns the supported lensFuncs for go.mod files.
44382-func LensFuncs() map[command.Command]source.LensFunc {
44383-	return map[command.Command]source.LensFunc{
44384-		command.UpgradeDependency: upgradeLenses,
44385-		command.Tidy:              tidyLens,
44386-		command.Vendor:            vendorLens,
44387-		command.RunGovulncheck:    vulncheckLenses,
44388-	}
44389-}
44390-
44391-func upgradeLenses(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) ([]protocol.CodeLens, error) {
44392-	pm, err := snapshot.ParseMod(ctx, fh)
44393-	if err != nil || pm.File == nil {
44394-		return nil, err
44395-	}
44396-	uri := protocol.URIFromSpanURI(fh.URI())
44397-	reset, err := command.NewResetGoModDiagnosticsCommand("Reset go.mod diagnostics", command.ResetGoModDiagnosticsArgs{URIArg: command.URIArg{URI: uri}})
44398-	if err != nil {
44399-		return nil, err
44400-	}
44401-	// Put the `Reset go.mod diagnostics` codelens on the module statement.
44402-	modrng, err := moduleStmtRange(fh, pm)
44403-	if err != nil {
44404-		return nil, err
44405-	}
44406-	lenses := []protocol.CodeLens{{Range: modrng, Command: &reset}}
44407-	if len(pm.File.Require) == 0 {
44408-		// Nothing to upgrade.
44409-		return lenses, nil
44410-	}
44411-	var requires []string
44412-	for _, req := range pm.File.Require {
44413-		requires = append(requires, req.Mod.Path)
44414-	}
44415-	checkUpgrade, err := command.NewCheckUpgradesCommand("Check for upgrades", command.CheckUpgradesArgs{
44416-		URI:     uri,
44417-		Modules: requires,
44418-	})
44419-	if err != nil {
44420-		return nil, err
44421-	}
44422-	upgradeTransitive, err := command.NewUpgradeDependencyCommand("Upgrade transitive dependencies", command.DependencyArgs{
44423-		URI:        uri,
44424-		AddRequire: false,
44425-		GoCmdArgs:  []string{"-d", "-u", "-t", "./..."},
44426-	})
44427-	if err != nil {
44428-		return nil, err
44429-	}
44430-	upgradeDirect, err := command.NewUpgradeDependencyCommand("Upgrade direct dependencies", command.DependencyArgs{
44431-		URI:        uri,
44432-		AddRequire: false,
44433-		GoCmdArgs:  append([]string{"-d"}, requires...),
44434-	})
44435-	if err != nil {
44436-		return nil, err
44437-	}
44438-
44439-	// Put the upgrade code lenses above the first require block or statement.
44440-	rng, err := firstRequireRange(fh, pm)
44441-	if err != nil {
44442-		return nil, err
44443-	}
44444-
44445-	return append(lenses, []protocol.CodeLens{
44446-		{Range: rng, Command: &checkUpgrade},
44447-		{Range: rng, Command: &upgradeTransitive},
44448-		{Range: rng, Command: &upgradeDirect},
44449-	}...), nil
44450-}
44451-
44452-func tidyLens(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) ([]protocol.CodeLens, error) {
44453-	pm, err := snapshot.ParseMod(ctx, fh)
44454-	if err != nil || pm.File == nil {
44455-		return nil, err
44456-	}
44457-	uri := protocol.URIFromSpanURI(fh.URI())
44458-	cmd, err := command.NewTidyCommand("Run go mod tidy", command.URIArgs{URIs: []protocol.DocumentURI{uri}})
44459-	if err != nil {
44460-		return nil, err
44461-	}
44462-	rng, err := moduleStmtRange(fh, pm)
44463-	if err != nil {
44464-		return nil, err
44465-	}
44466-	return []protocol.CodeLens{{
44467-		Range:   rng,
44468-		Command: &cmd,
44469-	}}, nil
44470-}
44471-
44472-func vendorLens(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) ([]protocol.CodeLens, error) {
44473-	pm, err := snapshot.ParseMod(ctx, fh)
44474-	if err != nil || pm.File == nil {
44475-		return nil, err
44476-	}
44477-	if len(pm.File.Require) == 0 {
44478-		// Nothing to vendor.
44479-		return nil, nil
44480-	}
44481-	rng, err := moduleStmtRange(fh, pm)
44482-	if err != nil {
44483-		return nil, err
44484-	}
44485-	title := "Create vendor directory"
44486-	uri := protocol.URIFromSpanURI(fh.URI())
44487-	cmd, err := command.NewVendorCommand(title, command.URIArg{URI: uri})
44488-	if err != nil {
44489-		return nil, err
44490-	}
44491-	// Change the message depending on whether or not the module already has a
44492-	// vendor directory.
44493-	vendorDir := filepath.Join(filepath.Dir(fh.URI().Filename()), "vendor")
44494-	if info, _ := os.Stat(vendorDir); info != nil && info.IsDir() {
44495-		title = "Sync vendor directory"
44496-	}
44497-	return []protocol.CodeLens{{Range: rng, Command: &cmd}}, nil
44498-}
44499-
44500-func moduleStmtRange(fh source.FileHandle, pm *source.ParsedModule) (protocol.Range, error) {
44501-	if pm.File == nil || pm.File.Module == nil || pm.File.Module.Syntax == nil {
44502-		return protocol.Range{}, fmt.Errorf("no module statement in %s", fh.URI())
44503-	}
44504-	syntax := pm.File.Module.Syntax
44505-	return pm.Mapper.OffsetRange(syntax.Start.Byte, syntax.End.Byte)
44506-}
44507-
44508-// firstRequireRange returns the range for the first "require" in the given
44509-// go.mod file. This is either a require block or an individual require line.
44510-func firstRequireRange(fh source.FileHandle, pm *source.ParsedModule) (protocol.Range, error) {
44511-	if len(pm.File.Require) == 0 {
44512-		return protocol.Range{}, fmt.Errorf("no requires in the file %s", fh.URI())
44513-	}
44514-	var start, end modfile.Position
44515-	for _, stmt := range pm.File.Syntax.Stmt {
44516-		if b, ok := stmt.(*modfile.LineBlock); ok && len(b.Token) == 1 && b.Token[0] == "require" {
44517-			start, end = b.Span()
44518-			break
44519-		}
44520-	}
44521-
44522-	firstRequire := pm.File.Require[0].Syntax
44523-	if start.Byte == 0 || firstRequire.Start.Byte < start.Byte {
44524-		start, end = firstRequire.Start, firstRequire.End
44525-	}
44526-	return pm.Mapper.OffsetRange(start.Byte, end.Byte)
44527-}
44528-
44529-func vulncheckLenses(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) ([]protocol.CodeLens, error) {
44530-	pm, err := snapshot.ParseMod(ctx, fh)
44531-	if err != nil || pm.File == nil {
44532-		return nil, err
44533-	}
44534-	// Place the codelenses near the module statement.
44535-	// A module may not have the require block,
44536-	// but vulnerabilities can exist in standard libraries.
44537-	uri := protocol.URIFromSpanURI(fh.URI())
44538-	rng, err := moduleStmtRange(fh, pm)
44539-	if err != nil {
44540-		return nil, err
44541-	}
44542-
44543-	vulncheck, err := command.NewRunGovulncheckCommand("Run govulncheck", command.VulncheckArgs{
44544-		URI:     uri,
44545-		Pattern: "./...",
44546-	})
44547-	if err != nil {
44548-		return nil, err
44549-	}
44550-	return []protocol.CodeLens{
44551-		{Range: rng, Command: &vulncheck},
44552-	}, nil
44553-}
44554diff -urN a/gopls/internal/lsp/mod/diagnostics.go b/gopls/internal/lsp/mod/diagnostics.go
44555--- a/gopls/internal/lsp/mod/diagnostics.go	2000-01-01 00:00:00.000000000 -0000
44556+++ b/gopls/internal/lsp/mod/diagnostics.go	1970-01-01 00:00:00.000000000 +0000
44557@@ -1,561 +0,0 @@
44558-// Copyright 2019 The Go Authors. All rights reserved.
44559-// Use of this source code is governed by a BSD-style
44560-// license that can be found in the LICENSE file.
44561-
44562-// Package mod provides core features related to go.mod file
44563-// handling for use by Go editors and tools.
44564-package mod
44565-
44566-import (
44567-	"context"
44568-	"fmt"
44569-	"sort"
44570-	"strings"
44571-
44572-	"golang.org/x/mod/modfile"
44573-	"golang.org/x/mod/semver"
44574-	"golang.org/x/tools/gopls/internal/govulncheck"
44575-	"golang.org/x/tools/gopls/internal/lsp/command"
44576-	"golang.org/x/tools/gopls/internal/lsp/protocol"
44577-	"golang.org/x/tools/gopls/internal/lsp/source"
44578-	"golang.org/x/tools/gopls/internal/span"
44579-	"golang.org/x/tools/internal/event"
44580-	"golang.org/x/vuln/osv"
44581-)
44582-
44583-// Diagnostics returns diagnostics for the modules in the workspace.
44584-//
44585-// It waits for completion of type-checking of all active packages.
44586-func Diagnostics(ctx context.Context, snapshot source.Snapshot) (map[span.URI][]*source.Diagnostic, error) {
44587-	ctx, done := event.Start(ctx, "mod.Diagnostics", source.SnapshotLabels(snapshot)...)
44588-	defer done()
44589-
44590-	return collectDiagnostics(ctx, snapshot, ModDiagnostics)
44591-}
44592-
44593-// UpgradeDiagnostics returns upgrade diagnostics for the modules in the
44594-// workspace with known upgrades.
44595-func UpgradeDiagnostics(ctx context.Context, snapshot source.Snapshot) (map[span.URI][]*source.Diagnostic, error) {
44596-	ctx, done := event.Start(ctx, "mod.UpgradeDiagnostics", source.SnapshotLabels(snapshot)...)
44597-	defer done()
44598-
44599-	return collectDiagnostics(ctx, snapshot, ModUpgradeDiagnostics)
44600-}
44601-
44602-// VulnerabilityDiagnostics returns vulnerability diagnostics for the active modules in the
44603-// workspace with known vulnerabilities.
44604-func VulnerabilityDiagnostics(ctx context.Context, snapshot source.Snapshot) (map[span.URI][]*source.Diagnostic, error) {
44605-	ctx, done := event.Start(ctx, "mod.VulnerabilityDiagnostics", source.SnapshotLabels(snapshot)...)
44606-	defer done()
44607-
44608-	return collectDiagnostics(ctx, snapshot, ModVulnerabilityDiagnostics)
44609-}
44610-
44611-func collectDiagnostics(ctx context.Context, snapshot source.Snapshot, diagFn func(context.Context, source.Snapshot, source.FileHandle) ([]*source.Diagnostic, error)) (map[span.URI][]*source.Diagnostic, error) {
44612-	reports := make(map[span.URI][]*source.Diagnostic)
44613-	for _, uri := range snapshot.ModFiles() {
44614-		fh, err := snapshot.GetFile(ctx, uri)
44615-		if err != nil {
44616-			return nil, err
44617-		}
44618-		reports[fh.URI()] = []*source.Diagnostic{}
44619-		diagnostics, err := diagFn(ctx, snapshot, fh)
44620-		if err != nil {
44621-			return nil, err
44622-		}
44623-		for _, d := range diagnostics {
44624-			fh, err := snapshot.GetFile(ctx, d.URI)
44625-			if err != nil {
44626-				return nil, err
44627-			}
44628-			reports[fh.URI()] = append(reports[fh.URI()], d)
44629-		}
44630-	}
44631-	return reports, nil
44632-}
44633-
44634-// ModDiagnostics waits for completion of type-checking of all active
44635-// packages, then returns diagnostics from diagnosing the packages in
44636-// the workspace and from tidying the go.mod file.
44637-func ModDiagnostics(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) (diagnostics []*source.Diagnostic, err error) {
44638-	pm, err := snapshot.ParseMod(ctx, fh)
44639-	if err != nil {
44640-		if pm == nil || len(pm.ParseErrors) == 0 {
44641-			return nil, err
44642-		}
44643-		return pm.ParseErrors, nil
44644-	}
44645-
44646-	// Packages in the workspace can contribute diagnostics to go.mod files.
44647-	// TODO(rfindley): Try to avoid type checking all packages in the workspace here,
44648-	// for every go.mod file. If gc_details is enabled, it looks like this could lead to extra
44649-	// go command invocations (as gc details is not memoized).
44650-	active, err := snapshot.ActiveMetadata(ctx)
44651-	if err != nil && !source.IsNonFatalGoModError(err) {
44652-		event.Error(ctx, fmt.Sprintf("workspace packages: diagnosing %s", pm.URI), err)
44653-	}
44654-	if err == nil {
44655-		// Note: the call to PackageDiagnostics below may be the first operation
44656-		// after the initial metadata load, and therefore result in type-checking
44657-		// or loading many packages.
44658-		ids := make([]source.PackageID, len(active))
44659-		for i, meta := range active {
44660-			ids[i] = meta.ID
44661-		}
44662-		diags, err := snapshot.PackageDiagnostics(ctx, ids...)
44663-		if err != nil {
44664-			return nil, err
44665-		}
44666-		diagnostics = append(diagnostics, diags[fh.URI()]...)
44667-	}
44668-
44669-	tidied, err := snapshot.ModTidy(ctx, pm)
44670-	if err != nil && !source.IsNonFatalGoModError(err) {
44671-		event.Error(ctx, fmt.Sprintf("tidy: diagnosing %s", pm.URI), err)
44672-	}
44673-	if err == nil {
44674-		for _, d := range tidied.Diagnostics {
44675-			if d.URI != fh.URI() {
44676-				continue
44677-			}
44678-			diagnostics = append(diagnostics, d)
44679-		}
44680-	}
44681-	return diagnostics, nil
44682-}
44683-
44684-// ModUpgradeDiagnostics adds upgrade quick fixes for individual modules if the upgrades
44685-// are recorded in the view.
44686-func ModUpgradeDiagnostics(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) (upgradeDiagnostics []*source.Diagnostic, err error) {
44687-	pm, err := snapshot.ParseMod(ctx, fh)
44688-	if err != nil {
44689-		// Don't return an error if there are parse error diagnostics to be shown, but also do not
44690-		// continue since we won't be able to show the upgrade diagnostics.
44691-		if pm != nil && len(pm.ParseErrors) != 0 {
44692-			return nil, nil
44693-		}
44694-		return nil, err
44695-	}
44696-
44697-	upgrades := snapshot.View().ModuleUpgrades(fh.URI())
44698-	for _, req := range pm.File.Require {
44699-		ver, ok := upgrades[req.Mod.Path]
44700-		if !ok || req.Mod.Version == ver {
44701-			continue
44702-		}
44703-		rng, err := pm.Mapper.OffsetRange(req.Syntax.Start.Byte, req.Syntax.End.Byte)
44704-		if err != nil {
44705-			return nil, err
44706-		}
44707-		// Upgrade to the exact version we offer the user, not the most recent.
44708-		title := fmt.Sprintf("%s%v", upgradeCodeActionPrefix, ver)
44709-		cmd, err := command.NewUpgradeDependencyCommand(title, command.DependencyArgs{
44710-			URI:        protocol.URIFromSpanURI(fh.URI()),
44711-			AddRequire: false,
44712-			GoCmdArgs:  []string{req.Mod.Path + "@" + ver},
44713-		})
44714-		if err != nil {
44715-			return nil, err
44716-		}
44717-		upgradeDiagnostics = append(upgradeDiagnostics, &source.Diagnostic{
44718-			URI:            fh.URI(),
44719-			Range:          rng,
44720-			Severity:       protocol.SeverityInformation,
44721-			Source:         source.UpgradeNotification,
44722-			Message:        fmt.Sprintf("%v can be upgraded", req.Mod.Path),
44723-			SuggestedFixes: []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)},
44724-		})
44725-	}
44726-
44727-	return upgradeDiagnostics, nil
44728-}
44729-
44730-const upgradeCodeActionPrefix = "Upgrade to "
44731-
44732-// ModVulnerabilityDiagnostics adds diagnostics for vulnerabilities in individual modules
44733-// if the vulnerability is recorded in the view.
44734-func ModVulnerabilityDiagnostics(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) (vulnDiagnostics []*source.Diagnostic, err error) {
44735-	pm, err := snapshot.ParseMod(ctx, fh)
44736-	if err != nil {
44737-		// Don't return an error if there are parse error diagnostics to be shown, but also do not
44738-		// continue since we won't be able to show the vulnerability diagnostics.
44739-		if pm != nil && len(pm.ParseErrors) != 0 {
44740-			return nil, nil
44741-		}
44742-		return nil, err
44743-	}
44744-
44745-	diagSource := source.Govulncheck
44746-	vs := snapshot.View().Vulnerabilities(fh.URI())[fh.URI()]
44747-	if vs == nil && snapshot.View().Options().Vulncheck == source.ModeVulncheckImports {
44748-		vs, err = snapshot.ModVuln(ctx, fh.URI())
44749-		if err != nil {
44750-			return nil, err
44751-		}
44752-		diagSource = source.Vulncheck
44753-	}
44754-	if vs == nil || len(vs.Vulns) == 0 {
44755-		return nil, nil
44756-	}
44757-
44758-	suggestRunOrResetGovulncheck, err := suggestGovulncheckAction(diagSource == source.Govulncheck, fh.URI())
44759-	if err != nil {
44760-		// must not happen
44761-		return nil, err // TODO: bug report
44762-	}
44763-	type modVuln struct {
44764-		mod  *govulncheck.Module
44765-		vuln *govulncheck.Vuln
44766-	}
44767-	vulnsByModule := make(map[string][]modVuln)
44768-	for _, vuln := range vs.Vulns {
44769-		for _, mod := range vuln.Modules {
44770-			vulnsByModule[mod.Path] = append(vulnsByModule[mod.Path], modVuln{mod, vuln})
44771-		}
44772-	}
44773-
44774-	for _, req := range pm.File.Require {
44775-		vulns := vulnsByModule[req.Mod.Path]
44776-		if len(vulns) == 0 {
44777-			continue
44778-		}
44779-		// note: req.Syntax is the line corresponding to 'require', which means
44780-		// req.Syntax.Start can point to the beginning of the "require" keyword
44781-		// for a single line require (e.g. "require golang.org/x/mod v0.0.0").
44782-		start := req.Syntax.Start.Byte
44783-		if len(req.Syntax.Token) == 3 {
44784-			start += len("require ")
44785-		}
44786-		rng, err := pm.Mapper.OffsetRange(start, req.Syntax.End.Byte)
44787-		if err != nil {
44788-			return nil, err
44789-		}
44790-		// Map affecting vulns to 'warning' level diagnostics,
44791-		// others to 'info' level diagnostics.
44792-		// Fixes will include only the upgrades for warning level diagnostics.
44793-		var warningFixes, infoFixes []source.SuggestedFix
44794-		var warning, info []string
44795-		var relatedInfo []protocol.DiagnosticRelatedInformation
44796-		for _, mv := range vulns {
44797-			mod, vuln := mv.mod, mv.vuln
44798-			// It is possible that the source code was changed since the last
44799-			// govulncheck run and information in the `vulns` info is stale.
44800-			// For example, imagine that a user is in the middle of updating
44801-			// problematic modules detected by the govulncheck run by applying
44802-			// quick fixes. Stale diagnostics can be confusing and prevent the
44803-			// user from quickly locating the next module to fix.
44804-			// Ideally we should rerun the analysis with the updated module
44805-			// dependencies or any other code changes, but we are not yet
44806-			// in the position of automatically triggering the analysis
44807-			// (govulncheck can take a while). We also don't know exactly what
44808-			// part of source code was changed since `vulns` was computed.
44809-			// As a heuristic, we assume that a user upgrades the affecting
44810-			// module to the version with the fix or the latest one, and if the
44811-			// version in the require statement is equal to or higher than the
44812-			// fixed version, skip generating a diagnostic about the vulnerability.
44813-			// Eventually, the user has to rerun govulncheck.
44814-			if mod.FixedVersion != "" && semver.IsValid(req.Mod.Version) && semver.Compare(mod.FixedVersion, req.Mod.Version) <= 0 {
44815-				continue
44816-			}
44817-			if !vuln.IsCalled() {
44818-				info = append(info, vuln.OSV.ID)
44819-			} else {
44820-				warning = append(warning, vuln.OSV.ID)
44821-				relatedInfo = append(relatedInfo, listRelatedInfo(ctx, snapshot, vuln)...)
44822-			}
44823-			// Upgrade to the exact version we offer the user, not the most recent.
44824-			if fixedVersion := mod.FixedVersion; semver.IsValid(fixedVersion) && semver.Compare(req.Mod.Version, fixedVersion) < 0 {
44825-				cmd, err := getUpgradeCodeAction(fh, req, fixedVersion)
44826-				if err != nil {
44827-					return nil, err // TODO: bug report
44828-				}
44829-				sf := source.SuggestedFixFromCommand(cmd, protocol.QuickFix)
44830-				if !vuln.IsCalled() {
44831-					infoFixes = append(infoFixes, sf)
44832-				} else {
44833-					warningFixes = append(warningFixes, sf)
44834-				}
44835-			}
44836-		}
44837-
44838-		if len(warning) == 0 && len(info) == 0 {
44839-			continue
44840-		}
44841-		// Add an upgrade for module@latest.
44842-		// TODO(suzmue): verify if latest is the same as fixedVersion.
44843-		latest, err := getUpgradeCodeAction(fh, req, "latest")
44844-		if err != nil {
44845-			return nil, err // TODO: bug report
44846-		}
44847-		sf := source.SuggestedFixFromCommand(latest, protocol.QuickFix)
44848-		if len(warningFixes) > 0 {
44849-			warningFixes = append(warningFixes, sf)
44850-		}
44851-		if len(infoFixes) > 0 {
44852-			infoFixes = append(infoFixes, sf)
44853-		}
44854-
44855-		sort.Strings(warning)
44856-		sort.Strings(info)
44857-
44858-		if len(warning) > 0 {
44859-			warningFixes = append(warningFixes, suggestRunOrResetGovulncheck)
44860-			vulnDiagnostics = append(vulnDiagnostics, &source.Diagnostic{
44861-				URI:            fh.URI(),
44862-				Range:          rng,
44863-				Severity:       protocol.SeverityWarning,
44864-				Source:         diagSource,
44865-				Message:        getVulnMessage(req.Mod.Path, warning, true, diagSource == source.Govulncheck),
44866-				SuggestedFixes: warningFixes,
44867-				Related:        relatedInfo,
44868-			})
44869-		}
44870-		if len(info) > 0 {
44871-			infoFixes = append(infoFixes, suggestRunOrResetGovulncheck)
44872-			vulnDiagnostics = append(vulnDiagnostics, &source.Diagnostic{
44873-				URI:            fh.URI(),
44874-				Range:          rng,
44875-				Severity:       protocol.SeverityInformation,
44876-				Source:         diagSource,
44877-				Message:        getVulnMessage(req.Mod.Path, info, false, diagSource == source.Govulncheck),
44878-				SuggestedFixes: infoFixes,
44879-				Related:        relatedInfo,
44880-			})
44881-		}
44882-	}
44883-
44884-	// TODO(hyangah): place this diagnostic on the `go` directive or `toolchain` directive
44885-	// after https://go.dev/issue/57001.
44886-	const diagnoseStdLib = false
44887-	if diagnoseStdLib {
44888-		// Add standard library vulnerabilities.
44889-		stdlibVulns := vulnsByModule["stdlib"]
44890-		if len(stdlibVulns) == 0 {
44891-			return vulnDiagnostics, nil
44892-		}
44893-
44894-		// Put the standard library diagnostic on the module declaration.
44895-		rng, err := pm.Mapper.OffsetRange(pm.File.Module.Syntax.Start.Byte, pm.File.Module.Syntax.End.Byte)
44896-		if err != nil {
44897-			return vulnDiagnostics, nil // TODO: bug report
44898-		}
44899-
44900-		stdlib := stdlibVulns[0].mod.FoundVersion
44901-		var warning, info []string
44902-		var relatedInfo []protocol.DiagnosticRelatedInformation
44903-		for _, mv := range stdlibVulns {
44904-			vuln := mv.vuln
44905-			stdlib = mv.mod.FoundVersion
44906-			if !vuln.IsCalled() {
44907-				info = append(info, vuln.OSV.ID)
44908-			} else {
44909-				warning = append(warning, vuln.OSV.ID)
44910-				relatedInfo = append(relatedInfo, listRelatedInfo(ctx, snapshot, vuln)...)
44911-			}
44912-		}
44913-		if len(warning) > 0 {
44914-			fixes := []source.SuggestedFix{suggestRunOrResetGovulncheck}
44915-			vulnDiagnostics = append(vulnDiagnostics, &source.Diagnostic{
44916-				URI:            fh.URI(),
44917-				Range:          rng,
44918-				Severity:       protocol.SeverityWarning,
44919-				Source:         diagSource,
44920-				Message:        getVulnMessage(stdlib, warning, true, diagSource == source.Govulncheck),
44921-				SuggestedFixes: fixes,
44922-				Related:        relatedInfo,
44923-			})
44924-		}
44925-		if len(info) > 0 {
44926-			fixes := []source.SuggestedFix{suggestRunOrResetGovulncheck}
44927-			vulnDiagnostics = append(vulnDiagnostics, &source.Diagnostic{
44928-				URI:            fh.URI(),
44929-				Range:          rng,
44930-				Severity:       protocol.SeverityInformation,
44931-				Source:         diagSource,
44932-				Message:        getVulnMessage(stdlib, info, false, diagSource == source.Govulncheck),
44933-				SuggestedFixes: fixes,
44934-				Related:        relatedInfo,
44935-			})
44936-		}
44937-	}
44938-
44939-	return vulnDiagnostics, nil
44940-}
44941-
44942-// suggestGovulncheckAction returns a code action that suggests either run govulncheck
44943-// for more accurate investigation (if the present vulncheck diagnostics are based on
44944-// analysis less accurate than govulncheck) or reset the existing govulncheck result
44945-// (if the present vulncheck diagnostics are already based on govulncheck run).
44946-func suggestGovulncheckAction(fromGovulncheck bool, uri span.URI) (source.SuggestedFix, error) {
44947-	if fromGovulncheck {
44948-		resetVulncheck, err := command.NewResetGoModDiagnosticsCommand("Reset govulncheck result", command.ResetGoModDiagnosticsArgs{
44949-			URIArg:           command.URIArg{URI: protocol.DocumentURI(uri)},
44950-			DiagnosticSource: string(source.Govulncheck),
44951-		})
44952-		if err != nil {
44953-			return source.SuggestedFix{}, err
44954-		}
44955-		return source.SuggestedFixFromCommand(resetVulncheck, protocol.QuickFix), nil
44956-	}
44957-	vulncheck, err := command.NewRunGovulncheckCommand("Run govulncheck to verify", command.VulncheckArgs{
44958-		URI:     protocol.DocumentURI(uri),
44959-		Pattern: "./...",
44960-	})
44961-	if err != nil {
44962-		return source.SuggestedFix{}, err
44963-	}
44964-	return source.SuggestedFixFromCommand(vulncheck, protocol.QuickFix), nil
44965-}
44966-
44967-func getVulnMessage(mod string, vulns []string, used, fromGovulncheck bool) string {
44968-	var b strings.Builder
44969-	if used {
44970-		switch len(vulns) {
44971-		case 1:
44972-			fmt.Fprintf(&b, "%v has a vulnerability used in the code: %v.", mod, vulns[0])
44973-		default:
44974-			fmt.Fprintf(&b, "%v has vulnerabilities used in the code: %v.", mod, strings.Join(vulns, ", "))
44975-		}
44976-	} else {
44977-		if fromGovulncheck {
44978-			switch len(vulns) {
44979-			case 1:
44980-				fmt.Fprintf(&b, "%v has a vulnerability %v that is not used in the code.", mod, vulns[0])
44981-			default:
44982-				fmt.Fprintf(&b, "%v has known vulnerabilities %v that are not used in the code.", mod, strings.Join(vulns, ", "))
44983-			}
44984-		} else {
44985-			switch len(vulns) {
44986-			case 1:
44987-				fmt.Fprintf(&b, "%v has a vulnerability %v.", mod, vulns[0])
44988-			default:
44989-				fmt.Fprintf(&b, "%v has known vulnerabilities %v.", mod, strings.Join(vulns, ", "))
44990-			}
44991-		}
44992-	}
44993-	return b.String()
44994-}
44995-
44996-func listRelatedInfo(ctx context.Context, snapshot source.Snapshot, vuln *govulncheck.Vuln) []protocol.DiagnosticRelatedInformation {
44997-	var ri []protocol.DiagnosticRelatedInformation
44998-	for _, m := range vuln.Modules {
44999-		for _, p := range m.Packages {
45000-			for _, c := range p.CallStacks {
45001-				if len(c.Frames) == 0 {
45002-					continue
45003-				}
45004-				entry := c.Frames[0]
45005-				pos := entry.Position
45006-				if pos.Filename == "" {
45007-					continue // token.Position Filename is an optional field.
45008-				}
45009-				uri := span.URIFromPath(pos.Filename)
45010-				startPos := protocol.Position{
45011-					Line: uint32(pos.Line) - 1,
45012-					// We need to read the file contents to precisesly map
45013-					// token.Position (pos) to the UTF16-based column offset
45014-					// protocol.Position requires. That can be expensive.
45015-					// We need this related info to just help users to open
45016-					// the entry points of the callstack and once the file is
45017-					// open, we will compute the precise location based on the
45018-					// open file contents. So, use the beginning of the line
45019-					// as the position here instead of precise UTF16-based
45020-					// position computation.
45021-					Character: 0,
45022-				}
45023-				ri = append(ri, protocol.DiagnosticRelatedInformation{
45024-					Location: protocol.Location{
45025-						URI: protocol.URIFromSpanURI(uri),
45026-						Range: protocol.Range{
45027-							Start: startPos,
45028-							End:   startPos,
45029-						},
45030-					},
45031-					Message: fmt.Sprintf("[%v] %v -> %v.%v", vuln.OSV.ID, entry.Name(), p.Path, c.Symbol),
45032-				})
45033-			}
45034-		}
45035-	}
45036-	return ri
45037-}
45038-
45039-func formatMessage(v *govulncheck.Vuln) string {
45040-	details := []byte(v.OSV.Details)
45041-	// Remove any new lines that are not preceded or followed by a new line.
45042-	for i, r := range details {
45043-		if r == '\n' && i > 0 && details[i-1] != '\n' && i+1 < len(details) && details[i+1] != '\n' {
45044-			details[i] = ' '
45045-		}
45046-	}
45047-	return strings.TrimSpace(strings.Replace(string(details), "\n\n", "\n\n  ", -1))
45048-}
45049-
45050-// href returns the url for the vulnerability information.
45051-// Eventually we should retrieve the url embedded in the osv.Entry.
45052-// While vuln.go.dev is under development, this always returns
45053-// the page in pkg.go.dev.
45054-func href(vuln *osv.Entry) string {
45055-	return fmt.Sprintf("https://pkg.go.dev/vuln/%s", vuln.ID)
45056-}
45057-
45058-func getUpgradeCodeAction(fh source.FileHandle, req *modfile.Require, version string) (protocol.Command, error) {
45059-	cmd, err := command.NewUpgradeDependencyCommand(upgradeTitle(version), command.DependencyArgs{
45060-		URI:        protocol.URIFromSpanURI(fh.URI()),
45061-		AddRequire: false,
45062-		GoCmdArgs:  []string{req.Mod.Path + "@" + version},
45063-	})
45064-	if err != nil {
45065-		return protocol.Command{}, err
45066-	}
45067-	return cmd, nil
45068-}
45069-
45070-func upgradeTitle(fixedVersion string) string {
45071-	title := fmt.Sprintf("%s%v", upgradeCodeActionPrefix, fixedVersion)
45072-	return title
45073-}
45074-
45075-// SelectUpgradeCodeActions takes a list of code actions for a required module
45076-// and returns a more selective list of upgrade code actions,
45077-// where the code actions have been deduped. Code actions unrelated to upgrade
45078-// are deduplicated by the name.
45079-func SelectUpgradeCodeActions(actions []protocol.CodeAction) []protocol.CodeAction {
45080-	if len(actions) <= 1 {
45081-		return actions // return early if no sorting necessary
45082-	}
45083-	var versionedUpgrade, latestUpgrade, resetAction protocol.CodeAction
45084-	var chosenVersionedUpgrade string
45085-	var selected []protocol.CodeAction
45086-
45087-	seen := make(map[string]bool)
45088-
45089-	for _, action := range actions {
45090-		if strings.HasPrefix(action.Title, upgradeCodeActionPrefix) {
45091-			if v := getUpgradeVersion(action); v == "latest" && latestUpgrade.Title == "" {
45092-				latestUpgrade = action
45093-			} else if versionedUpgrade.Title == "" || semver.Compare(v, chosenVersionedUpgrade) > 0 {
45094-				chosenVersionedUpgrade = v
45095-				versionedUpgrade = action
45096-			}
45097-		} else if strings.HasPrefix(action.Title, "Reset govulncheck") {
45098-			resetAction = action
45099-		} else if !seen[action.Command.Title] {
45100-			seen[action.Command.Title] = true
45101-			selected = append(selected, action)
45102-		}
45103-	}
45104-	if versionedUpgrade.Title != "" {
45105-		selected = append(selected, versionedUpgrade)
45106-	}
45107-	if latestUpgrade.Title != "" {
45108-		selected = append(selected, latestUpgrade)
45109-	}
45110-	if resetAction.Title != "" {
45111-		selected = append(selected, resetAction)
45112-	}
45113-	return selected
45114-}
45115-
45116-func getUpgradeVersion(p protocol.CodeAction) string {
45117-	return strings.TrimPrefix(p.Title, upgradeCodeActionPrefix)
45118-}
45119diff -urN a/gopls/internal/lsp/mod/format.go b/gopls/internal/lsp/mod/format.go
45120--- a/gopls/internal/lsp/mod/format.go	2000-01-01 00:00:00.000000000 -0000
45121+++ b/gopls/internal/lsp/mod/format.go	1970-01-01 00:00:00.000000000 +0000
45122@@ -1,30 +0,0 @@
45123-// Copyright 2020 The Go Authors. All rights reserved.
45124-// Use of this source code is governed by a BSD-style
45125-// license that can be found in the LICENSE file.
45126-
45127-package mod
45128-
45129-import (
45130-	"context"
45131-
45132-	"golang.org/x/tools/gopls/internal/lsp/protocol"
45133-	"golang.org/x/tools/gopls/internal/lsp/source"
45134-	"golang.org/x/tools/internal/event"
45135-)
45136-
45137-func Format(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) ([]protocol.TextEdit, error) {
45138-	ctx, done := event.Start(ctx, "mod.Format")
45139-	defer done()
45140-
45141-	pm, err := snapshot.ParseMod(ctx, fh)
45142-	if err != nil {
45143-		return nil, err
45144-	}
45145-	formatted, err := pm.File.Format()
45146-	if err != nil {
45147-		return nil, err
45148-	}
45149-	// Calculate the edits to be made due to the change.
45150-	diffs := snapshot.View().Options().ComputeEdits(string(pm.Mapper.Content), string(formatted))
45151-	return source.ToProtocolEdits(pm.Mapper, diffs)
45152-}
45153diff -urN a/gopls/internal/lsp/mod/hover.go b/gopls/internal/lsp/mod/hover.go
45154--- a/gopls/internal/lsp/mod/hover.go	2000-01-01 00:00:00.000000000 -0000
45155+++ b/gopls/internal/lsp/mod/hover.go	1970-01-01 00:00:00.000000000 +0000
45156@@ -1,358 +0,0 @@
45157-// Copyright 2020 The Go Authors. All rights reserved.
45158-// Use of this source code is governed by a BSD-style
45159-// license that can be found in the LICENSE file.
45160-
45161-package mod
45162-
45163-import (
45164-	"bytes"
45165-	"context"
45166-	"fmt"
45167-	"sort"
45168-	"strings"
45169-
45170-	"golang.org/x/mod/modfile"
45171-	"golang.org/x/mod/semver"
45172-	"golang.org/x/tools/gopls/internal/govulncheck"
45173-	"golang.org/x/tools/gopls/internal/lsp/protocol"
45174-	"golang.org/x/tools/gopls/internal/lsp/source"
45175-	"golang.org/x/tools/internal/event"
45176-)
45177-
45178-func Hover(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle, position protocol.Position) (*protocol.Hover, error) {
45179-	var found bool
45180-	for _, uri := range snapshot.ModFiles() {
45181-		if fh.URI() == uri {
45182-			found = true
45183-			break
45184-		}
45185-	}
45186-
45187-	// We only provide hover information for the view's go.mod files.
45188-	if !found {
45189-		return nil, nil
45190-	}
45191-
45192-	ctx, done := event.Start(ctx, "mod.Hover")
45193-	defer done()
45194-
45195-	// Get the position of the cursor.
45196-	pm, err := snapshot.ParseMod(ctx, fh)
45197-	if err != nil {
45198-		return nil, fmt.Errorf("getting modfile handle: %w", err)
45199-	}
45200-	offset, err := pm.Mapper.PositionOffset(position)
45201-	if err != nil {
45202-		return nil, fmt.Errorf("computing cursor position: %w", err)
45203-	}
45204-
45205-	// If the cursor position is on a module statement
45206-	if hover, ok := hoverOnModuleStatement(ctx, pm, offset, snapshot, fh); ok {
45207-		return hover, nil
45208-	}
45209-	return hoverOnRequireStatement(ctx, pm, offset, snapshot, fh)
45210-}
45211-
45212-func hoverOnRequireStatement(ctx context.Context, pm *source.ParsedModule, offset int, snapshot source.Snapshot, fh source.FileHandle) (*protocol.Hover, error) {
45213-	// Confirm that the cursor is at the position of a require statement.
45214-	var req *modfile.Require
45215-	var startOffset, endOffset int
45216-	for _, r := range pm.File.Require {
45217-		dep := []byte(r.Mod.Path)
45218-		s, e := r.Syntax.Start.Byte, r.Syntax.End.Byte
45219-		i := bytes.Index(pm.Mapper.Content[s:e], dep)
45220-		if i == -1 {
45221-			continue
45222-		}
45223-		// Shift the start position to the location of the
45224-		// dependency within the require statement.
45225-		startOffset, endOffset = s+i, e
45226-		if startOffset <= offset && offset <= endOffset {
45227-			req = r
45228-			break
45229-		}
45230-	}
45231-	// TODO(hyangah): find position for info about vulnerabilities in Go
45232-
45233-	// The cursor position is not on a require statement.
45234-	if req == nil {
45235-		return nil, nil
45236-	}
45237-
45238-	// Get the vulnerability info.
45239-	fromGovulncheck := true
45240-	vs := snapshot.View().Vulnerabilities(fh.URI())[fh.URI()]
45241-	if vs == nil && snapshot.View().Options().Vulncheck == source.ModeVulncheckImports {
45242-		var err error
45243-		vs, err = snapshot.ModVuln(ctx, fh.URI())
45244-		if err != nil {
45245-			return nil, err
45246-		}
45247-		fromGovulncheck = false
45248-	}
45249-	affecting, nonaffecting := lookupVulns(vs, req.Mod.Path, req.Mod.Version)
45250-
45251-	// Get the `go mod why` results for the given file.
45252-	why, err := snapshot.ModWhy(ctx, fh)
45253-	if err != nil {
45254-		return nil, err
45255-	}
45256-	explanation, ok := why[req.Mod.Path]
45257-	if !ok {
45258-		return nil, nil
45259-	}
45260-
45261-	// Get the range to highlight for the hover.
45262-	// TODO(hyangah): adjust the hover range to include the version number
45263-	// to match the diagnostics' range.
45264-	rng, err := pm.Mapper.OffsetRange(startOffset, endOffset)
45265-	if err != nil {
45266-		return nil, err
45267-	}
45268-	options := snapshot.View().Options()
45269-	isPrivate := snapshot.View().IsGoPrivatePath(req.Mod.Path)
45270-	header := formatHeader(req.Mod.Path, options)
45271-	explanation = formatExplanation(explanation, req, options, isPrivate)
45272-	vulns := formatVulnerabilities(req.Mod.Path, affecting, nonaffecting, options, fromGovulncheck)
45273-
45274-	return &protocol.Hover{
45275-		Contents: protocol.MarkupContent{
45276-			Kind:  options.PreferredContentFormat,
45277-			Value: header + vulns + explanation,
45278-		},
45279-		Range: rng,
45280-	}, nil
45281-}
45282-
45283-func hoverOnModuleStatement(ctx context.Context, pm *source.ParsedModule, offset int, snapshot source.Snapshot, fh source.FileHandle) (*protocol.Hover, bool) {
45284-	module := pm.File.Module
45285-	if module == nil {
45286-		return nil, false // no module stmt
45287-	}
45288-	if offset < module.Syntax.Start.Byte || offset > module.Syntax.End.Byte {
45289-		return nil, false // cursor not in module stmt
45290-	}
45291-
45292-	rng, err := pm.Mapper.OffsetRange(module.Syntax.Start.Byte, module.Syntax.End.Byte)
45293-	if err != nil {
45294-		return nil, false
45295-	}
45296-	fromGovulncheck := true
45297-	vs := snapshot.View().Vulnerabilities(fh.URI())[fh.URI()]
45298-
45299-	if vs == nil && snapshot.View().Options().Vulncheck == source.ModeVulncheckImports {
45300-		vs, err = snapshot.ModVuln(ctx, fh.URI())
45301-		if err != nil {
45302-			return nil, false
45303-		}
45304-		fromGovulncheck = false
45305-	}
45306-	modpath := "stdlib"
45307-	goVersion := snapshot.View().GoVersionString()
45308-	affecting, nonaffecting := lookupVulns(vs, modpath, goVersion)
45309-	options := snapshot.View().Options()
45310-	vulns := formatVulnerabilities(modpath, affecting, nonaffecting, options, fromGovulncheck)
45311-
45312-	return &protocol.Hover{
45313-		Contents: protocol.MarkupContent{
45314-			Kind:  options.PreferredContentFormat,
45315-			Value: vulns,
45316-		},
45317-		Range: rng,
45318-	}, true
45319-}
45320-
45321-func formatHeader(modpath string, options *source.Options) string {
45322-	var b strings.Builder
45323-	// Write the heading as an H3.
45324-	b.WriteString("#### " + modpath)
45325-	if options.PreferredContentFormat == protocol.Markdown {
45326-		b.WriteString("\n\n")
45327-	} else {
45328-		b.WriteRune('\n')
45329-	}
45330-	return b.String()
45331-}
45332-
45333-func lookupVulns(vulns *govulncheck.Result, modpath, version string) (affecting, nonaffecting []*govulncheck.Vuln) {
45334-	if vulns == nil {
45335-		return nil, nil
45336-	}
45337-	for _, vuln := range vulns.Vulns {
45338-		for _, mod := range vuln.Modules {
45339-			if mod.Path != modpath {
45340-				continue
45341-			}
45342-			// It is possible that the source code was changed since the last
45343-			// govulncheck run and information in the `vulns` info is stale.
45344-			// For example, imagine that a user is in the middle of updating
45345-			// problematic modules detected by the govulncheck run by applying
45346-			// quick fixes. Stale diagnostics can be confusing and prevent the
45347-			// user from quickly locating the next module to fix.
45348-			// Ideally we should rerun the analysis with the updated module
45349-			// dependencies or any other code changes, but we are not yet
45350-			// in the position of automatically triggering the analysis
45351-			// (govulncheck can take a while). We also don't know exactly what
45352-			// part of source code was changed since `vulns` was computed.
45353-			// As a heuristic, we assume that a user upgrades the affecting
45354-			// module to the version with the fix or the latest one, and if the
45355-			// version in the require statement is equal to or higher than the
45356-			// fixed version, skip the vulnerability information in the hover.
45357-			// Eventually, the user has to rerun govulncheck.
45358-			if mod.FixedVersion != "" && semver.IsValid(version) && semver.Compare(mod.FixedVersion, version) <= 0 {
45359-				continue
45360-			}
45361-			if vuln.IsCalled() {
45362-				affecting = append(affecting, vuln)
45363-			} else {
45364-				nonaffecting = append(nonaffecting, vuln)
45365-			}
45366-		}
45367-	}
45368-	sort.Slice(nonaffecting, func(i, j int) bool { return nonaffecting[i].OSV.ID < nonaffecting[j].OSV.ID })
45369-	sort.Slice(affecting, func(i, j int) bool { return affecting[i].OSV.ID < affecting[j].OSV.ID })
45370-	return affecting, nonaffecting
45371-}
45372-
45373-func formatVulnerabilities(modPath string, affecting, nonaffecting []*govulncheck.Vuln, options *source.Options, fromGovulncheck bool) string {
45374-	if len(affecting) == 0 && len(nonaffecting) == 0 {
45375-		return ""
45376-	}
45377-
45378-	// TODO(hyangah): can we use go templates to generate hover messages?
45379-	// Then, we can use a different template for markdown case.
45380-	useMarkdown := options.PreferredContentFormat == protocol.Markdown
45381-
45382-	var b strings.Builder
45383-
45384-	if len(affecting) > 0 {
45385-		// TODO(hyangah): make the message more eyecatching (icon/codicon/color)
45386-		if len(affecting) == 1 {
45387-			b.WriteString(fmt.Sprintf("\n**WARNING:** Found %d reachable vulnerability.\n", len(affecting)))
45388-		} else {
45389-			b.WriteString(fmt.Sprintf("\n**WARNING:** Found %d reachable vulnerabilities.\n", len(affecting)))
45390-		}
45391-	}
45392-	for _, v := range affecting {
45393-		fix := fixedVersionInfo(v, modPath)
45394-		pkgs := vulnerablePkgsInfo(v, modPath, useMarkdown)
45395-
45396-		if useMarkdown {
45397-			fmt.Fprintf(&b, "- [**%v**](%v) %v%v%v\n", v.OSV.ID, href(v.OSV), formatMessage(v), pkgs, fix)
45398-		} else {
45399-			fmt.Fprintf(&b, "  - [%v] %v (%v) %v%v\n", v.OSV.ID, formatMessage(v), href(v.OSV), pkgs, fix)
45400-		}
45401-	}
45402-	if len(nonaffecting) > 0 {
45403-		if fromGovulncheck {
45404-			fmt.Fprintf(&b, "\n**Note:** The project imports packages with known vulnerabilities, but does not call the vulnerable code.\n")
45405-		} else {
45406-			fmt.Fprintf(&b, "\n**Note:** The project imports packages with known vulnerabilities. Use `govulncheck` to check if the project uses vulnerable symbols.\n")
45407-		}
45408-	}
45409-	for _, v := range nonaffecting {
45410-		fix := fixedVersionInfo(v, modPath)
45411-		pkgs := vulnerablePkgsInfo(v, modPath, useMarkdown)
45412-		if useMarkdown {
45413-			fmt.Fprintf(&b, "- [%v](%v) %v%v%v\n", v.OSV.ID, href(v.OSV), formatMessage(v), pkgs, fix)
45414-		} else {
45415-			fmt.Fprintf(&b, "  - [%v] %v (%v) %v%v\n", v.OSV.ID, formatMessage(v), href(v.OSV), pkgs, fix)
45416-		}
45417-	}
45418-	b.WriteString("\n")
45419-	return b.String()
45420-}
45421-
45422-func vulnerablePkgsInfo(v *govulncheck.Vuln, modPath string, useMarkdown bool) string {
45423-	var b bytes.Buffer
45424-	for _, m := range v.Modules {
45425-		if m.Path != modPath {
45426-			continue
45427-		}
45428-		if c := len(m.Packages); c == 1 {
45429-			b.WriteString("\n  Vulnerable package is:")
45430-		} else if c > 1 {
45431-			b.WriteString("\n  Vulnerable packages are:")
45432-		}
45433-		for _, pkg := range m.Packages {
45434-			if useMarkdown {
45435-				b.WriteString("\n  * `")
45436-			} else {
45437-				b.WriteString("\n    ")
45438-			}
45439-			b.WriteString(pkg.Path)
45440-			if useMarkdown {
45441-				b.WriteString("`")
45442-			}
45443-		}
45444-	}
45445-	if b.Len() == 0 {
45446-		return ""
45447-	}
45448-	return b.String()
45449-}
45450-func fixedVersionInfo(v *govulncheck.Vuln, modPath string) string {
45451-	fix := "\n\n  **No fix is available.**"
45452-	for _, m := range v.Modules {
45453-		if m.Path != modPath {
45454-			continue
45455-		}
45456-		if m.FixedVersion != "" {
45457-			fix = "\n\n  Fixed in " + m.FixedVersion + "."
45458-		}
45459-		break
45460-	}
45461-	return fix
45462-}
45463-
45464-func formatExplanation(text string, req *modfile.Require, options *source.Options, isPrivate bool) string {
45465-	text = strings.TrimSuffix(text, "\n")
45466-	splt := strings.Split(text, "\n")
45467-	length := len(splt)
45468-
45469-	var b strings.Builder
45470-
45471-	// If the explanation is 2 lines, then it is of the form:
45472-	// # golang.org/x/text/encoding
45473-	// (main module does not need package golang.org/x/text/encoding)
45474-	if length == 2 {
45475-		b.WriteString(splt[1])
45476-		return b.String()
45477-	}
45478-
45479-	imp := splt[length-1] // import path
45480-	reference := imp
45481-	// See golang/go#36998: don't link to modules matching GOPRIVATE.
45482-	if !isPrivate && options.PreferredContentFormat == protocol.Markdown {
45483-		target := imp
45484-		if strings.ToLower(options.LinkTarget) == "pkg.go.dev" {
45485-			target = strings.Replace(target, req.Mod.Path, req.Mod.String(), 1)
45486-		}
45487-		reference = fmt.Sprintf("[%s](%s)", imp, source.BuildLink(options.LinkTarget, target, ""))
45488-	}
45489-	b.WriteString("This module is necessary because " + reference + " is imported in")
45490-
45491-	// If the explanation is 3 lines, then it is of the form:
45492-	// # golang.org/x/tools
45493-	// modtest
45494-	// golang.org/x/tools/go/packages
45495-	if length == 3 {
45496-		msg := fmt.Sprintf(" `%s`.", splt[1])
45497-		b.WriteString(msg)
45498-		return b.String()
45499-	}
45500-
45501-	// If the explanation is more than 3 lines, then it is of the form:
45502-	// # golang.org/x/text/language
45503-	// rsc.io/quote
45504-	// rsc.io/sampler
45505-	// golang.org/x/text/language
45506-	b.WriteString(":\n```text")
45507-	dash := ""
45508-	for _, imp := range splt[1 : length-1] {
45509-		dash += "-"
45510-		b.WriteString("\n" + dash + " " + imp)
45511-	}
45512-	b.WriteString("\n```")
45513-	return b.String()
45514-}
45515diff -urN a/gopls/internal/lsp/mod/mod_test.go b/gopls/internal/lsp/mod/mod_test.go
45516--- a/gopls/internal/lsp/mod/mod_test.go	2000-01-01 00:00:00.000000000 -0000
45517+++ b/gopls/internal/lsp/mod/mod_test.go	1970-01-01 00:00:00.000000000 +0000
45518@@ -1,57 +0,0 @@
45519-// Copyright 2019 The Go Authors. All rights reserved.
45520-// Use of this source code is governed by a BSD-style
45521-// license that can be found in the LICENSE file.
45522-
45523-package mod
45524-
45525-import (
45526-	"io/ioutil"
45527-	"os"
45528-	"path/filepath"
45529-	"testing"
45530-
45531-	"golang.org/x/tools/gopls/internal/lsp/cache"
45532-	"golang.org/x/tools/gopls/internal/lsp/source"
45533-	"golang.org/x/tools/gopls/internal/lsp/tests"
45534-	"golang.org/x/tools/gopls/internal/span"
45535-	"golang.org/x/tools/internal/testenv"
45536-)
45537-
45538-func TestMain(m *testing.M) {
45539-	testenv.ExitIfSmallMachine()
45540-	os.Exit(m.Run())
45541-}
45542-
45543-func TestModfileRemainsUnchanged(t *testing.T) {
45544-	ctx := tests.Context(t)
45545-	session := cache.NewSession(ctx, cache.New(nil), nil)
45546-	options := source.DefaultOptions().Clone()
45547-	tests.DefaultOptions(options)
45548-	options.TempModfile = true
45549-	options.Env = map[string]string{"GOPACKAGESDRIVER": "off", "GOROOT": ""}
45550-
45551-	// Make sure to copy the test directory to a temporary directory so we do not
45552-	// modify the test code or add go.sum files when we run the tests.
45553-	folder, err := tests.CopyFolderToTempDir(filepath.Join("testdata", "unchanged"))
45554-	if err != nil {
45555-		t.Fatal(err)
45556-	}
45557-	defer os.RemoveAll(folder)
45558-
45559-	before, err := ioutil.ReadFile(filepath.Join(folder, "go.mod"))
45560-	if err != nil {
45561-		t.Fatal(err)
45562-	}
45563-	_, _, release, err := session.NewView(ctx, "diagnostics_test", span.URIFromPath(folder), options)
45564-	if err != nil {
45565-		t.Fatal(err)
45566-	}
45567-	release()
45568-	after, err := ioutil.ReadFile(filepath.Join(folder, "go.mod"))
45569-	if err != nil {
45570-		t.Fatal(err)
45571-	}
45572-	if string(before) != string(after) {
45573-		t.Errorf("the real go.mod file was changed even when tempModfile=true")
45574-	}
45575-}
45576diff -urN a/gopls/internal/lsp/mod/testdata/unchanged/go.mod b/gopls/internal/lsp/mod/testdata/unchanged/go.mod
45577--- a/gopls/internal/lsp/mod/testdata/unchanged/go.mod	2000-01-01 00:00:00.000000000 -0000
45578+++ b/gopls/internal/lsp/mod/testdata/unchanged/go.mod	1970-01-01 00:00:00.000000000 +0000
45579@@ -1 +0,0 @@
45580-module unchanged
45581diff -urN a/gopls/internal/lsp/mod/testdata/unchanged/main.go b/gopls/internal/lsp/mod/testdata/unchanged/main.go
45582--- a/gopls/internal/lsp/mod/testdata/unchanged/main.go	2000-01-01 00:00:00.000000000 -0000
45583+++ b/gopls/internal/lsp/mod/testdata/unchanged/main.go	1970-01-01 00:00:00.000000000 +0000
45584@@ -1,6 +0,0 @@
45585-// Package unchanged does something
45586-package unchanged
45587-
45588-func Yo() {
45589-	println("yo")
45590-}
45591diff -urN a/gopls/internal/lsp/progress/progress.go b/gopls/internal/lsp/progress/progress.go
45592--- a/gopls/internal/lsp/progress/progress.go	2000-01-01 00:00:00.000000000 -0000
45593+++ b/gopls/internal/lsp/progress/progress.go	1970-01-01 00:00:00.000000000 +0000
45594@@ -1,271 +0,0 @@
45595-// Copyright 2020 The Go Authors. All rights reserved.
45596-// Use of this source code is governed by a BSD-style
45597-// license that can be found in the LICENSE file.
45598-
45599-package progress
45600-
45601-import (
45602-	"context"
45603-	"fmt"
45604-	"math/rand"
45605-	"strconv"
45606-	"strings"
45607-	"sync"
45608-
45609-	"golang.org/x/tools/gopls/internal/lsp/protocol"
45610-	"golang.org/x/tools/internal/event"
45611-	"golang.org/x/tools/internal/event/tag"
45612-	"golang.org/x/tools/internal/xcontext"
45613-)
45614-
45615-type Tracker struct {
45616-	client                   protocol.Client
45617-	supportsWorkDoneProgress bool
45618-
45619-	mu         sync.Mutex
45620-	inProgress map[protocol.ProgressToken]*WorkDone
45621-}
45622-
45623-func NewTracker(client protocol.Client) *Tracker {
45624-	return &Tracker{
45625-		client:     client,
45626-		inProgress: make(map[protocol.ProgressToken]*WorkDone),
45627-	}
45628-}
45629-
45630-func (tracker *Tracker) SetSupportsWorkDoneProgress(b bool) {
45631-	tracker.supportsWorkDoneProgress = b
45632-}
45633-
45634-// Start notifies the client of work being done on the server. It uses either
45635-// ShowMessage RPCs or $/progress messages, depending on the capabilities of
45636-// the client.  The returned WorkDone handle may be used to report incremental
45637-// progress, and to report work completion. In particular, it is an error to
45638-// call start and not call end(...) on the returned WorkDone handle.
45639-//
45640-// If token is empty, a token will be randomly generated.
45641-//
45642-// The progress item is considered cancellable if the given cancel func is
45643-// non-nil. In this case, cancel is called when the work done
45644-//
45645-// Example:
45646-//
45647-//	func Generate(ctx) (err error) {
45648-//	  ctx, cancel := context.WithCancel(ctx)
45649-//	  defer cancel()
45650-//	  work := s.progress.start(ctx, "generate", "running go generate", cancel)
45651-//	  defer func() {
45652-//	    if err != nil {
45653-//	      work.end(ctx, fmt.Sprintf("generate failed: %v", err))
45654-//	    } else {
45655-//	      work.end(ctx, "done")
45656-//	    }
45657-//	  }()
45658-//	  // Do the work...
45659-//	}
45660-func (t *Tracker) Start(ctx context.Context, title, message string, token protocol.ProgressToken, cancel func()) *WorkDone {
45661-	ctx = xcontext.Detach(ctx) // progress messages should not be cancelled
45662-	wd := &WorkDone{
45663-		client: t.client,
45664-		token:  token,
45665-		cancel: cancel,
45666-	}
45667-	if !t.supportsWorkDoneProgress {
45668-		// Previous iterations of this fallback attempted to retain cancellation
45669-		// support by using ShowMessageCommand with a 'Cancel' button, but this is
45670-		// not ideal as the 'Cancel' dialog stays open even after the command
45671-		// completes.
45672-		//
45673-		// Just show a simple message. Clients can implement workDone progress
45674-		// reporting to get cancellation support.
45675-		if err := wd.client.ShowMessage(ctx, &protocol.ShowMessageParams{
45676-			Type:    protocol.Log,
45677-			Message: message,
45678-		}); err != nil {
45679-			event.Error(ctx, "showing start message for "+title, err)
45680-		}
45681-		return wd
45682-	}
45683-	if wd.token == nil {
45684-		token = strconv.FormatInt(rand.Int63(), 10)
45685-		err := wd.client.WorkDoneProgressCreate(ctx, &protocol.WorkDoneProgressCreateParams{
45686-			Token: token,
45687-		})
45688-		if err != nil {
45689-			wd.err = err
45690-			event.Error(ctx, "starting work for "+title, err)
45691-			return wd
45692-		}
45693-		wd.token = token
45694-	}
45695-	// At this point we have a token that the client knows about. Store the token
45696-	// before starting work.
45697-	t.mu.Lock()
45698-	t.inProgress[wd.token] = wd
45699-	t.mu.Unlock()
45700-	wd.cleanup = func() {
45701-		t.mu.Lock()
45702-		delete(t.inProgress, token)
45703-		t.mu.Unlock()
45704-	}
45705-	err := wd.client.Progress(ctx, &protocol.ProgressParams{
45706-		Token: wd.token,
45707-		Value: &protocol.WorkDoneProgressBegin{
45708-			Kind:        "begin",
45709-			Cancellable: wd.cancel != nil,
45710-			Message:     message,
45711-			Title:       title,
45712-		},
45713-	})
45714-	if err != nil {
45715-		event.Error(ctx, "progress begin", err)
45716-	}
45717-	return wd
45718-}
45719-
45720-func (t *Tracker) Cancel(token protocol.ProgressToken) error {
45721-	t.mu.Lock()
45722-	defer t.mu.Unlock()
45723-	wd, ok := t.inProgress[token]
45724-	if !ok {
45725-		return fmt.Errorf("token %q not found in progress", token)
45726-	}
45727-	if wd.cancel == nil {
45728-		return fmt.Errorf("work %q is not cancellable", token)
45729-	}
45730-	wd.doCancel()
45731-	return nil
45732-}
45733-
45734-// WorkDone represents a unit of work that is reported to the client via the
45735-// progress API.
45736-type WorkDone struct {
45737-	client protocol.Client
45738-	// If token is nil, this workDone object uses the ShowMessage API, rather
45739-	// than $/progress.
45740-	token protocol.ProgressToken
45741-	// err is set if progress reporting is broken for some reason (for example,
45742-	// if there was an initial error creating a token).
45743-	err error
45744-
45745-	cancelMu  sync.Mutex
45746-	cancelled bool
45747-	cancel    func()
45748-
45749-	cleanup func()
45750-}
45751-
45752-func (wd *WorkDone) Token() protocol.ProgressToken {
45753-	return wd.token
45754-}
45755-
45756-func (wd *WorkDone) doCancel() {
45757-	wd.cancelMu.Lock()
45758-	defer wd.cancelMu.Unlock()
45759-	if !wd.cancelled {
45760-		wd.cancel()
45761-	}
45762-}
45763-
45764-// Report reports an update on WorkDone report back to the client.
45765-func (wd *WorkDone) Report(ctx context.Context, message string, percentage float64) {
45766-	ctx = xcontext.Detach(ctx) // progress messages should not be cancelled
45767-	if wd == nil {
45768-		return
45769-	}
45770-	wd.cancelMu.Lock()
45771-	cancelled := wd.cancelled
45772-	wd.cancelMu.Unlock()
45773-	if cancelled {
45774-		return
45775-	}
45776-	if wd.err != nil || wd.token == nil {
45777-		// Not using the workDone API, so we do nothing. It would be far too spammy
45778-		// to send incremental messages.
45779-		return
45780-	}
45781-	message = strings.TrimSuffix(message, "\n")
45782-	err := wd.client.Progress(ctx, &protocol.ProgressParams{
45783-		Token: wd.token,
45784-		Value: &protocol.WorkDoneProgressReport{
45785-			Kind: "report",
45786-			// Note that in the LSP spec, the value of Cancellable may be changed to
45787-			// control whether the cancel button in the UI is enabled. Since we don't
45788-			// yet use this feature, the value is kept constant here.
45789-			Cancellable: wd.cancel != nil,
45790-			Message:     message,
45791-			Percentage:  uint32(percentage),
45792-		},
45793-	})
45794-	if err != nil {
45795-		event.Error(ctx, "reporting progress", err)
45796-	}
45797-}
45798-
45799-// End reports a workdone completion back to the client.
45800-func (wd *WorkDone) End(ctx context.Context, message string) {
45801-	ctx = xcontext.Detach(ctx) // progress messages should not be cancelled
45802-	if wd == nil {
45803-		return
45804-	}
45805-	var err error
45806-	switch {
45807-	case wd.err != nil:
45808-		// There is a prior error.
45809-	case wd.token == nil:
45810-		// We're falling back to message-based reporting.
45811-		err = wd.client.ShowMessage(ctx, &protocol.ShowMessageParams{
45812-			Type:    protocol.Info,
45813-			Message: message,
45814-		})
45815-	default:
45816-		err = wd.client.Progress(ctx, &protocol.ProgressParams{
45817-			Token: wd.token,
45818-			Value: &protocol.WorkDoneProgressEnd{
45819-				Kind:    "end",
45820-				Message: message,
45821-			},
45822-		})
45823-	}
45824-	if err != nil {
45825-		event.Error(ctx, "ending work", err)
45826-	}
45827-	if wd.cleanup != nil {
45828-		wd.cleanup()
45829-	}
45830-}
45831-
45832-// EventWriter writes every incoming []byte to
45833-// event.Print with the operation=generate tag
45834-// to distinguish its logs from others.
45835-type EventWriter struct {
45836-	ctx       context.Context
45837-	operation string
45838-}
45839-
45840-func NewEventWriter(ctx context.Context, operation string) *EventWriter {
45841-	return &EventWriter{ctx: ctx, operation: operation}
45842-}
45843-
45844-func (ew *EventWriter) Write(p []byte) (n int, err error) {
45845-	event.Log(ew.ctx, string(p), tag.Operation.Of(ew.operation))
45846-	return len(p), nil
45847-}
45848-
45849-// WorkDoneWriter wraps a workDone handle to provide a Writer interface,
45850-// so that workDone reporting can more easily be hooked into commands.
45851-type WorkDoneWriter struct {
45852-	// In order to implement the io.Writer interface, we must close over ctx.
45853-	ctx context.Context
45854-	wd  *WorkDone
45855-}
45856-
45857-func NewWorkDoneWriter(ctx context.Context, wd *WorkDone) *WorkDoneWriter {
45858-	return &WorkDoneWriter{ctx: ctx, wd: wd}
45859-}
45860-
45861-func (wdw *WorkDoneWriter) Write(p []byte) (n int, err error) {
45862-	wdw.wd.Report(wdw.ctx, string(p), 0)
45863-	// Don't fail just because of a failure to report progress.
45864-	return len(p), nil
45865-}
45866diff -urN a/gopls/internal/lsp/progress/progress_test.go b/gopls/internal/lsp/progress/progress_test.go
45867--- a/gopls/internal/lsp/progress/progress_test.go	2000-01-01 00:00:00.000000000 -0000
45868+++ b/gopls/internal/lsp/progress/progress_test.go	1970-01-01 00:00:00.000000000 +0000
45869@@ -1,161 +0,0 @@
45870-// Copyright 2020 The Go Authors. All rights reserved.
45871-// Use of this source code is governed by a BSD-style
45872-// license that can be found in the LICENSE file.
45873-
45874-package progress
45875-
45876-import (
45877-	"context"
45878-	"fmt"
45879-	"sync"
45880-	"testing"
45881-
45882-	"golang.org/x/tools/gopls/internal/lsp/protocol"
45883-)
45884-
45885-type fakeClient struct {
45886-	protocol.Client
45887-
45888-	token protocol.ProgressToken
45889-
45890-	mu                                        sync.Mutex
45891-	created, begun, reported, messages, ended int
45892-}
45893-
45894-func (c *fakeClient) checkToken(token protocol.ProgressToken) {
45895-	if token == nil {
45896-		panic("nil token in progress message")
45897-	}
45898-	if c.token != nil && c.token != token {
45899-		panic(fmt.Errorf("invalid token in progress message: got %v, want %v", token, c.token))
45900-	}
45901-}
45902-
45903-func (c *fakeClient) WorkDoneProgressCreate(ctx context.Context, params *protocol.WorkDoneProgressCreateParams) error {
45904-	c.mu.Lock()
45905-	defer c.mu.Unlock()
45906-	c.checkToken(params.Token)
45907-	c.created++
45908-	return nil
45909-}
45910-
45911-func (c *fakeClient) Progress(ctx context.Context, params *protocol.ProgressParams) error {
45912-	c.mu.Lock()
45913-	defer c.mu.Unlock()
45914-	c.checkToken(params.Token)
45915-	switch params.Value.(type) {
45916-	case *protocol.WorkDoneProgressBegin:
45917-		c.begun++
45918-	case *protocol.WorkDoneProgressReport:
45919-		c.reported++
45920-	case *protocol.WorkDoneProgressEnd:
45921-		c.ended++
45922-	default:
45923-		panic(fmt.Errorf("unknown progress value %T", params.Value))
45924-	}
45925-	return nil
45926-}
45927-
45928-func (c *fakeClient) ShowMessage(context.Context, *protocol.ShowMessageParams) error {
45929-	c.mu.Lock()
45930-	defer c.mu.Unlock()
45931-	c.messages++
45932-	return nil
45933-}
45934-
45935-func setup(token protocol.ProgressToken) (context.Context, *Tracker, *fakeClient) {
45936-	c := &fakeClient{}
45937-	tracker := NewTracker(c)
45938-	tracker.SetSupportsWorkDoneProgress(true)
45939-	return context.Background(), tracker, c
45940-}
45941-
45942-func TestProgressTracker_Reporting(t *testing.T) {
45943-	for _, test := range []struct {
45944-		name                                            string
45945-		supported                                       bool
45946-		token                                           protocol.ProgressToken
45947-		wantReported, wantCreated, wantBegun, wantEnded int
45948-		wantMessages                                    int
45949-	}{
45950-		{
45951-			name:         "unsupported",
45952-			wantMessages: 2,
45953-		},
45954-		{
45955-			name:         "random token",
45956-			supported:    true,
45957-			wantCreated:  1,
45958-			wantBegun:    1,
45959-			wantReported: 1,
45960-			wantEnded:    1,
45961-		},
45962-		{
45963-			name:         "string token",
45964-			supported:    true,
45965-			token:        "token",
45966-			wantBegun:    1,
45967-			wantReported: 1,
45968-			wantEnded:    1,
45969-		},
45970-		{
45971-			name:         "numeric token",
45972-			supported:    true,
45973-			token:        1,
45974-			wantReported: 1,
45975-			wantBegun:    1,
45976-			wantEnded:    1,
45977-		},
45978-	} {
45979-		test := test
45980-		t.Run(test.name, func(t *testing.T) {
45981-			ctx, tracker, client := setup(test.token)
45982-			ctx, cancel := context.WithCancel(ctx)
45983-			defer cancel()
45984-			tracker.supportsWorkDoneProgress = test.supported
45985-			work := tracker.Start(ctx, "work", "message", test.token, nil)
45986-			client.mu.Lock()
45987-			gotCreated, gotBegun := client.created, client.begun
45988-			client.mu.Unlock()
45989-			if gotCreated != test.wantCreated {
45990-				t.Errorf("got %d created tokens, want %d", gotCreated, test.wantCreated)
45991-			}
45992-			if gotBegun != test.wantBegun {
45993-				t.Errorf("got %d work begun, want %d", gotBegun, test.wantBegun)
45994-			}
45995-			// Ignore errors: this is just testing the reporting behavior.
45996-			work.Report(ctx, "report", 50)
45997-			client.mu.Lock()
45998-			gotReported := client.reported
45999-			client.mu.Unlock()
46000-			if gotReported != test.wantReported {
46001-				t.Errorf("got %d progress reports, want %d", gotReported, test.wantCreated)
46002-			}
46003-			work.End(ctx, "done")
46004-			client.mu.Lock()
46005-			gotEnded, gotMessages := client.ended, client.messages
46006-			client.mu.Unlock()
46007-			if gotEnded != test.wantEnded {
46008-				t.Errorf("got %d ended reports, want %d", gotEnded, test.wantEnded)
46009-			}
46010-			if gotMessages != test.wantMessages {
46011-				t.Errorf("got %d messages, want %d", gotMessages, test.wantMessages)
46012-			}
46013-		})
46014-	}
46015-}
46016-
46017-func TestProgressTracker_Cancellation(t *testing.T) {
46018-	for _, token := range []protocol.ProgressToken{nil, 1, "a"} {
46019-		ctx, tracker, _ := setup(token)
46020-		var canceled bool
46021-		cancel := func() { canceled = true }
46022-		work := tracker.Start(ctx, "work", "message", token, cancel)
46023-		if err := tracker.Cancel(work.Token()); err != nil {
46024-			t.Fatal(err)
46025-		}
46026-		if !canceled {
46027-			t.Errorf("tracker.cancel(...): cancel not called")
46028-		}
46029-	}
46030-}
46031diff -urN a/gopls/internal/lsp/protocol/codeactionkind.go b/gopls/internal/lsp/protocol/codeactionkind.go
46032--- a/gopls/internal/lsp/protocol/codeactionkind.go	2000-01-01 00:00:00.000000000 -0000
46033+++ b/gopls/internal/lsp/protocol/codeactionkind.go	1970-01-01 00:00:00.000000000 +0000
46034@@ -1,11 +0,0 @@
46035-// Copyright 2020 The Go Authors. All rights reserved.
46036-// Use of this source code is governed by a BSD-style
46037-// license that can be found in the LICENSE file.
46038-
46039-package protocol
46040-
46041-// Custom code actions that aren't explicitly stated in LSP
46042-const (
46043-	GoTest CodeActionKind = "goTest"
46044-	// TODO: Add GoGenerate, RegenerateCgo etc.
46045-)
46046diff -urN a/gopls/internal/lsp/protocol/context.go b/gopls/internal/lsp/protocol/context.go
46047--- a/gopls/internal/lsp/protocol/context.go	2000-01-01 00:00:00.000000000 -0000
46048+++ b/gopls/internal/lsp/protocol/context.go	1970-01-01 00:00:00.000000000 +0000
46049@@ -1,43 +0,0 @@
46050-// Copyright 2019 The Go Authors. All rights reserved.
46051-// Use of this source code is governed by a BSD-style
46052-// license that can be found in the LICENSE file.
46053-
46054-package protocol
46055-
46056-import (
46057-	"bytes"
46058-	"context"
46059-
46060-	"golang.org/x/tools/internal/event"
46061-	"golang.org/x/tools/internal/event/core"
46062-	"golang.org/x/tools/internal/event/export"
46063-	"golang.org/x/tools/internal/event/label"
46064-	"golang.org/x/tools/internal/xcontext"
46065-)
46066-
46067-type contextKey int
46068-
46069-const (
46070-	clientKey = contextKey(iota)
46071-)
46072-
46073-func WithClient(ctx context.Context, client Client) context.Context {
46074-	return context.WithValue(ctx, clientKey, client)
46075-}
46076-
46077-func LogEvent(ctx context.Context, ev core.Event, lm label.Map, mt MessageType) context.Context {
46078-	client, ok := ctx.Value(clientKey).(Client)
46079-	if !ok {
46080-		return ctx
46081-	}
46082-	buf := &bytes.Buffer{}
46083-	p := export.Printer{}
46084-	p.WriteEvent(buf, ev, lm)
46085-	msg := &LogMessageParams{Type: mt, Message: buf.String()}
46086-	// Handle messages generated via event.Error, which won't have a level Label.
46087-	if event.IsError(ev) {
46088-		msg.Type = Error
46089-	}
46090-	go client.LogMessage(xcontext.Detach(ctx), msg)
46091-	return ctx
46092-}
46093diff -urN a/gopls/internal/lsp/protocol/doc.go b/gopls/internal/lsp/protocol/doc.go
46094--- a/gopls/internal/lsp/protocol/doc.go	2000-01-01 00:00:00.000000000 -0000
46095+++ b/gopls/internal/lsp/protocol/doc.go	1970-01-01 00:00:00.000000000 +0000
46096@@ -1,18 +0,0 @@
46097-// Copyright 2018 The Go Authors. All rights reserved.
46098-// Use of this source code is governed by a BSD-style
46099-// license that can be found in the LICENSE file.
46100-
46101-//go:generate go run ./generate
46102-
46103-// Package protocol contains the structs that map directly to the
46104-// request and response messages of the Language Server Protocol.
46105-//
46106-// It is a literal transcription, with unmodified comments, and only the changes
46107-// required to make it go code.
46108-// Names are uppercased to export them.
46109-// All fields have JSON tags added to correct the names.
46110-// Fields marked with a ? are also marked as "omitempty"
46111-// Fields that are "|| null" are made pointers
46112-// Fields that are string or number are left as string
46113-// Fields that are type "number" are made float64
46114-package protocol
46115diff -urN a/gopls/internal/lsp/protocol/enums.go b/gopls/internal/lsp/protocol/enums.go
46116--- a/gopls/internal/lsp/protocol/enums.go	2000-01-01 00:00:00.000000000 -0000
46117+++ b/gopls/internal/lsp/protocol/enums.go	1970-01-01 00:00:00.000000000 +0000
46118@@ -1,231 +0,0 @@
46119-// Copyright 2018 The Go Authors. All rights reserved.
46120-// Use of this source code is governed by a BSD-style
46121-// license that can be found in the LICENSE file.
46122-
46123-package protocol
46124-
46125-import (
46126-	"fmt"
46127-)
46128-
46129-var (
46130-	namesTextDocumentSyncKind   [int(Incremental) + 1]string
46131-	namesMessageType            [int(Log) + 1]string
46132-	namesFileChangeType         [int(Deleted) + 1]string
46133-	namesWatchKind              [int(WatchDelete) + 1]string
46134-	namesCompletionTriggerKind  [int(TriggerForIncompleteCompletions) + 1]string
46135-	namesDiagnosticSeverity     [int(SeverityHint) + 1]string
46136-	namesDiagnosticTag          [int(Unnecessary) + 1]string
46137-	namesCompletionItemKind     [int(TypeParameterCompletion) + 1]string
46138-	namesInsertTextFormat       [int(SnippetTextFormat) + 1]string
46139-	namesDocumentHighlightKind  [int(Write) + 1]string
46140-	namesSymbolKind             [int(TypeParameter) + 1]string
46141-	namesTextDocumentSaveReason [int(FocusOut) + 1]string
46142-)
46143-
46144-func init() {
46145-	namesTextDocumentSyncKind[int(None)] = "None"
46146-	namesTextDocumentSyncKind[int(Full)] = "Full"
46147-	namesTextDocumentSyncKind[int(Incremental)] = "Incremental"
46148-
46149-	namesMessageType[int(Error)] = "Error"
46150-	namesMessageType[int(Warning)] = "Warning"
46151-	namesMessageType[int(Info)] = "Info"
46152-	namesMessageType[int(Log)] = "Log"
46153-
46154-	namesFileChangeType[int(Created)] = "Created"
46155-	namesFileChangeType[int(Changed)] = "Changed"
46156-	namesFileChangeType[int(Deleted)] = "Deleted"
46157-
46158-	namesWatchKind[int(WatchCreate)] = "WatchCreate"
46159-	namesWatchKind[int(WatchChange)] = "WatchChange"
46160-	namesWatchKind[int(WatchDelete)] = "WatchDelete"
46161-
46162-	namesCompletionTriggerKind[int(Invoked)] = "Invoked"
46163-	namesCompletionTriggerKind[int(TriggerCharacter)] = "TriggerCharacter"
46164-	namesCompletionTriggerKind[int(TriggerForIncompleteCompletions)] = "TriggerForIncompleteCompletions"
46165-
46166-	namesDiagnosticSeverity[int(SeverityError)] = "Error"
46167-	namesDiagnosticSeverity[int(SeverityWarning)] = "Warning"
46168-	namesDiagnosticSeverity[int(SeverityInformation)] = "Information"
46169-	namesDiagnosticSeverity[int(SeverityHint)] = "Hint"
46170-
46171-	namesDiagnosticTag[int(Unnecessary)] = "Unnecessary"
46172-
46173-	namesCompletionItemKind[int(TextCompletion)] = "text"
46174-	namesCompletionItemKind[int(MethodCompletion)] = "method"
46175-	namesCompletionItemKind[int(FunctionCompletion)] = "func"
46176-	namesCompletionItemKind[int(ConstructorCompletion)] = "constructor"
46177-	namesCompletionItemKind[int(FieldCompletion)] = "field"
46178-	namesCompletionItemKind[int(VariableCompletion)] = "var"
46179-	namesCompletionItemKind[int(ClassCompletion)] = "type"
46180-	namesCompletionItemKind[int(InterfaceCompletion)] = "interface"
46181-	namesCompletionItemKind[int(ModuleCompletion)] = "package"
46182-	namesCompletionItemKind[int(PropertyCompletion)] = "property"
46183-	namesCompletionItemKind[int(UnitCompletion)] = "unit"
46184-	namesCompletionItemKind[int(ValueCompletion)] = "value"
46185-	namesCompletionItemKind[int(EnumCompletion)] = "enum"
46186-	namesCompletionItemKind[int(KeywordCompletion)] = "keyword"
46187-	namesCompletionItemKind[int(SnippetCompletion)] = "snippet"
46188-	namesCompletionItemKind[int(ColorCompletion)] = "color"
46189-	namesCompletionItemKind[int(FileCompletion)] = "file"
46190-	namesCompletionItemKind[int(ReferenceCompletion)] = "reference"
46191-	namesCompletionItemKind[int(FolderCompletion)] = "folder"
46192-	namesCompletionItemKind[int(EnumMemberCompletion)] = "enumMember"
46193-	namesCompletionItemKind[int(ConstantCompletion)] = "const"
46194-	namesCompletionItemKind[int(StructCompletion)] = "struct"
46195-	namesCompletionItemKind[int(EventCompletion)] = "event"
46196-	namesCompletionItemKind[int(OperatorCompletion)] = "operator"
46197-	namesCompletionItemKind[int(TypeParameterCompletion)] = "typeParam"
46198-
46199-	namesInsertTextFormat[int(PlainTextTextFormat)] = "PlainText"
46200-	namesInsertTextFormat[int(SnippetTextFormat)] = "Snippet"
46201-
46202-	namesDocumentHighlightKind[int(Text)] = "Text"
46203-	namesDocumentHighlightKind[int(Read)] = "Read"
46204-	namesDocumentHighlightKind[int(Write)] = "Write"
46205-
46206-	namesSymbolKind[int(File)] = "File"
46207-	namesSymbolKind[int(Module)] = "Module"
46208-	namesSymbolKind[int(Namespace)] = "Namespace"
46209-	namesSymbolKind[int(Package)] = "Package"
46210-	namesSymbolKind[int(Class)] = "Class"
46211-	namesSymbolKind[int(Method)] = "Method"
46212-	namesSymbolKind[int(Property)] = "Property"
46213-	namesSymbolKind[int(Field)] = "Field"
46214-	namesSymbolKind[int(Constructor)] = "Constructor"
46215-	namesSymbolKind[int(Enum)] = "Enum"
46216-	namesSymbolKind[int(Interface)] = "Interface"
46217-	namesSymbolKind[int(Function)] = "Function"
46218-	namesSymbolKind[int(Variable)] = "Variable"
46219-	namesSymbolKind[int(Constant)] = "Constant"
46220-	namesSymbolKind[int(String)] = "String"
46221-	namesSymbolKind[int(Number)] = "Number"
46222-	namesSymbolKind[int(Boolean)] = "Boolean"
46223-	namesSymbolKind[int(Array)] = "Array"
46224-	namesSymbolKind[int(Object)] = "Object"
46225-	namesSymbolKind[int(Key)] = "Key"
46226-	namesSymbolKind[int(Null)] = "Null"
46227-	namesSymbolKind[int(EnumMember)] = "EnumMember"
46228-	namesSymbolKind[int(Struct)] = "Struct"
46229-	namesSymbolKind[int(Event)] = "Event"
46230-	namesSymbolKind[int(Operator)] = "Operator"
46231-	namesSymbolKind[int(TypeParameter)] = "TypeParameter"
46232-
46233-	namesTextDocumentSaveReason[int(Manual)] = "Manual"
46234-	namesTextDocumentSaveReason[int(AfterDelay)] = "AfterDelay"
46235-	namesTextDocumentSaveReason[int(FocusOut)] = "FocusOut"
46236-}
46237-
46238-func formatEnum(f fmt.State, c rune, i int, names []string, unknown string) {
46239-	s := ""
46240-	if i >= 0 && i < len(names) {
46241-		s = names[i]
46242-	}
46243-	if s != "" {
46244-		fmt.Fprint(f, s)
46245-	} else {
46246-		fmt.Fprintf(f, "%s(%d)", unknown, i)
46247-	}
46248-}
46249-
46250-func parseEnum(s string, names []string) int {
46251-	for i, name := range names {
46252-		if s == name {
46253-			return i
46254-		}
46255-	}
46256-	return 0
46257-}
46258-
46259-func (e TextDocumentSyncKind) Format(f fmt.State, c rune) {
46260-	formatEnum(f, c, int(e), namesTextDocumentSyncKind[:], "TextDocumentSyncKind")
46261-}
46262-
46263-func ParseTextDocumentSyncKind(s string) TextDocumentSyncKind {
46264-	return TextDocumentSyncKind(parseEnum(s, namesTextDocumentSyncKind[:]))
46265-}
46266-
46267-func (e MessageType) Format(f fmt.State, c rune) {
46268-	formatEnum(f, c, int(e), namesMessageType[:], "MessageType")
46269-}
46270-
46271-func ParseMessageType(s string) MessageType {
46272-	return MessageType(parseEnum(s, namesMessageType[:]))
46273-}
46274-
46275-func (e FileChangeType) Format(f fmt.State, c rune) {
46276-	formatEnum(f, c, int(e), namesFileChangeType[:], "FileChangeType")
46277-}
46278-
46279-func ParseFileChangeType(s string) FileChangeType {
46280-	return FileChangeType(parseEnum(s, namesFileChangeType[:]))
46281-}
46282-
46283-func ParseWatchKind(s string) WatchKind {
46284-	return WatchKind(parseEnum(s, namesWatchKind[:]))
46285-}
46286-
46287-func (e CompletionTriggerKind) Format(f fmt.State, c rune) {
46288-	formatEnum(f, c, int(e), namesCompletionTriggerKind[:], "CompletionTriggerKind")
46289-}
46290-
46291-func ParseCompletionTriggerKind(s string) CompletionTriggerKind {
46292-	return CompletionTriggerKind(parseEnum(s, namesCompletionTriggerKind[:]))
46293-}
46294-
46295-func (e DiagnosticSeverity) Format(f fmt.State, c rune) {
46296-	formatEnum(f, c, int(e), namesDiagnosticSeverity[:], "DiagnosticSeverity")
46297-}
46298-
46299-func ParseDiagnosticSeverity(s string) DiagnosticSeverity {
46300-	return DiagnosticSeverity(parseEnum(s, namesDiagnosticSeverity[:]))
46301-}
46302-
46303-func (e DiagnosticTag) Format(f fmt.State, c rune) {
46304-	formatEnum(f, c, int(e), namesDiagnosticTag[:], "DiagnosticTag")
46305-}
46306-
46307-func ParseDiagnosticTag(s string) DiagnosticTag {
46308-	return DiagnosticTag(parseEnum(s, namesDiagnosticTag[:]))
46309-}
46310-
46311-func (e CompletionItemKind) Format(f fmt.State, c rune) {
46312-	formatEnum(f, c, int(e), namesCompletionItemKind[:], "CompletionItemKind")
46313-}
46314-
46315-func ParseCompletionItemKind(s string) CompletionItemKind {
46316-	return CompletionItemKind(parseEnum(s, namesCompletionItemKind[:]))
46317-}
46318-
46319-func (e InsertTextFormat) Format(f fmt.State, c rune) {
46320-	formatEnum(f, c, int(e), namesInsertTextFormat[:], "InsertTextFormat")
46321-}
46322-
46323-func ParseInsertTextFormat(s string) InsertTextFormat {
46324-	return InsertTextFormat(parseEnum(s, namesInsertTextFormat[:]))
46325-}
46326-
46327-func (e DocumentHighlightKind) Format(f fmt.State, c rune) {
46328-	formatEnum(f, c, int(e), namesDocumentHighlightKind[:], "DocumentHighlightKind")
46329-}
46330-
46331-func ParseDocumentHighlightKind(s string) DocumentHighlightKind {
46332-	return DocumentHighlightKind(parseEnum(s, namesDocumentHighlightKind[:]))
46333-}
46334-
46335-func (e SymbolKind) Format(f fmt.State, c rune) {
46336-	formatEnum(f, c, int(e), namesSymbolKind[:], "SymbolKind")
46337-}
46338-
46339-func ParseSymbolKind(s string) SymbolKind {
46340-	return SymbolKind(parseEnum(s, namesSymbolKind[:]))
46341-}
46342-
46343-func (e TextDocumentSaveReason) Format(f fmt.State, c rune) {
46344-	formatEnum(f, c, int(e), namesTextDocumentSaveReason[:], "TextDocumentSaveReason")
46345-}
46346-
46347-func ParseTextDocumentSaveReason(s string) TextDocumentSaveReason {
46348-	return TextDocumentSaveReason(parseEnum(s, namesTextDocumentSaveReason[:]))
46349-}
46350diff -urN a/gopls/internal/lsp/protocol/generate/generate.go b/gopls/internal/lsp/protocol/generate/generate.go
46351--- a/gopls/internal/lsp/protocol/generate/generate.go	2000-01-01 00:00:00.000000000 -0000
46352+++ b/gopls/internal/lsp/protocol/generate/generate.go	1970-01-01 00:00:00.000000000 +0000
46353@@ -1,121 +0,0 @@
46354-// Copyright 2022 The Go Authors. All rights reserved.
46355-// Use of this source code is governed by a BSD-style
46356-// license that can be found in the LICENSE file.
46357-
46358-//go:build go1.19
46359-// +build go1.19
46360-
46361-package main
46362-
46363-import (
46364-	"bytes"
46365-	"fmt"
46366-	"log"
46367-	"strings"
46368-)
46369-
46370-// a newType is a type that needs a name and a definition
46371-// These are the various types that the json specification doesn't name
46372-type newType struct {
46373-	name       string
46374-	properties Properties // for struct/literal types
46375-	items      []*Type    // for other types ("and", "tuple")
46376-	line       int
46377-	kind       string // Or, And, Tuple, Lit, Map
46378-	typ        *Type
46379-}
46380-
46381-func generateDoc(out *bytes.Buffer, doc string) {
46382-	if doc == "" {
46383-		return
46384-	}
46385-
46386-	if !strings.Contains(doc, "\n") {
46387-		fmt.Fprintf(out, "// %s\n", doc)
46388-		return
46389-	}
46390-	var list bool
46391-	for _, line := range strings.Split(doc, "\n") {
46392-		// Lists in metaModel.json start with a dash.
46393-		// To make a go doc list they have to be preceded
46394-		// by a blank line, and indented.
46395-		// (see type TextDccumentFilter in protocol.go)
46396-		if len(line) > 0 && line[0] == '-' {
46397-			if !list {
46398-				list = true
46399-				fmt.Fprintf(out, "//\n")
46400-			}
46401-			fmt.Fprintf(out, "//  %s\n", line)
46402-		} else {
46403-			if len(line) == 0 {
46404-				list = false
46405-			}
46406-			fmt.Fprintf(out, "// %s\n", line)
46407-		}
46408-	}
46409-}
46410-
46411-// decide if a property is optional, and if it needs a *
46412-// return ",omitempty" if it is optional, and "*" if it needs a pointer
46413-func propStar(name string, t NameType, gotype string) (string, string) {
46414-	var opt, star string
46415-	if t.Optional {
46416-		star = "*"
46417-		opt = ",omitempty"
46418-	}
46419-	if strings.HasPrefix(gotype, "[]") || strings.HasPrefix(gotype, "map[") {
46420-		star = "" // passed by reference, so no need for *
46421-	} else {
46422-		switch gotype {
46423-		case "bool", "uint32", "int32", "string", "interface{}":
46424-			star = "" // gopls compatibility if t.Optional
46425-		}
46426-	}
46427-	ostar, oopt := star, opt
46428-	if newStar, ok := goplsStar[prop{name, t.Name}]; ok {
46429-		switch newStar {
46430-		case nothing:
46431-			star, opt = "", ""
46432-		case wantStar:
46433-			star, opt = "*", ""
46434-		case wantOpt:
46435-			star, opt = "", ",omitempty"
46436-		case wantOptStar:
46437-			star, opt = "*", ",omitempty"
46438-		}
46439-		if star == ostar && opt == oopt { // no change
46440-			log.Printf("goplsStar[ {%q, %q} ](%d) useless %s/%s %s/%s", name, t.Name, t.Line, ostar, star, oopt, opt)
46441-		}
46442-		usedGoplsStar[prop{name, t.Name}] = true
46443-	}
46444-
46445-	return opt, star
46446-}
46447-
46448-func goName(s string) string {
46449-	// Go naming conventions
46450-	if strings.HasSuffix(s, "Id") {
46451-		s = s[:len(s)-len("Id")] + "ID"
46452-	} else if strings.HasSuffix(s, "Uri") {
46453-		s = s[:len(s)-3] + "URI"
46454-	} else if s == "uri" {
46455-		s = "URI"
46456-	} else if s == "id" {
46457-		s = "ID"
46458-	}
46459-
46460-	// renames for temporary GOPLS compatibility
46461-	if news := goplsType[s]; news != "" {
46462-		usedGoplsType[s] = true
46463-		s = news
46464-	}
46465-	// Names beginning _ are not exported
46466-	if strings.HasPrefix(s, "_") {
46467-		s = strings.Replace(s, "_", "X", 1)
46468-	}
46469-	if s != "string" { // base types are unchanged (textDocuemnt/diagnostic)
46470-		// Title is deprecated, but a) s is only one word, b) replacement is too heavy-weight
46471-		s = strings.Title(s)
46472-	}
46473-	return s
46474-}
46475diff -urN a/gopls/internal/lsp/protocol/generate/main.go b/gopls/internal/lsp/protocol/generate/main.go
46476--- a/gopls/internal/lsp/protocol/generate/main.go	2000-01-01 00:00:00.000000000 -0000
46477+++ b/gopls/internal/lsp/protocol/generate/main.go	1970-01-01 00:00:00.000000000 +0000
46478@@ -1,387 +0,0 @@
46479-// Copyright 2022 The Go Authors. All rights reserved.
46480-// Use of this source code is governed by a BSD-style
46481-// license that can be found in the LICENSE file.
46482-
46483-//go:build go1.19
46484-// +build go1.19
46485-
46486-// The generate command generates Go declarations from VSCode's
46487-// description of the Language Server Protocol.
46488-//
46489-// To run it, type 'go generate' in the parent (protocol) directory.
46490-package main
46491-
46492-import (
46493-	"bytes"
46494-	"encoding/json"
46495-	"flag"
46496-	"fmt"
46497-	"go/format"
46498-	"log"
46499-	"os"
46500-	"os/exec"
46501-	"path/filepath"
46502-	"strings"
46503-)
46504-
46505-const vscodeRepo = "https://github.com/microsoft/vscode-languageserver-node"
46506-
46507-// lspGitRef names a branch or tag in vscodeRepo.
46508-// It implicitly determines the protocol version of the LSP used by gopls.
46509-// For example, tag release/protocol/3.17.3 of the repo defines protocol version 3.17.0.
46510-// (Point releases are reflected in the git tag version even when they are cosmetic
46511-// and don't change the protocol.)
46512-var lspGitRef = "release/protocol/3.17.3-next.6"
46513-
46514-var (
46515-	repodir   = flag.String("d", "", "directory containing clone of "+vscodeRepo)
46516-	outputdir = flag.String("o", ".", "output directory")
46517-	// PJW: not for real code
46518-	cmpdir = flag.String("c", "", "directory of earlier code")
46519-	doboth = flag.String("b", "", "generate and compare")
46520-)
46521-
46522-func main() {
46523-	log.SetFlags(log.Lshortfile) // log file name and line number, not time
46524-	flag.Parse()
46525-
46526-	processinline()
46527-}
46528-
46529-func processinline() {
46530-	// A local repository may be specified during debugging.
46531-	// The default behavior is to download the canonical version.
46532-	if *repodir == "" {
46533-		tmpdir, err := os.MkdirTemp("", "")
46534-		if err != nil {
46535-			log.Fatal(err)
46536-		}
46537-		defer os.RemoveAll(tmpdir) // ignore error
46538-
46539-		// Clone the repository.
46540-		cmd := exec.Command("git", "clone", "--quiet", "--depth=1", "-c", "advice.detachedHead=false", vscodeRepo, "--branch="+lspGitRef, "--single-branch", tmpdir)
46541-		cmd.Stdout = os.Stderr
46542-		cmd.Stderr = os.Stderr
46543-		if err := cmd.Run(); err != nil {
46544-			log.Fatal(err)
46545-		}
46546-
46547-		*repodir = tmpdir
46548-	} else {
46549-		lspGitRef = fmt.Sprintf("(not git, local dir %s)", *repodir)
46550-	}
46551-
46552-	model := parse(filepath.Join(*repodir, "protocol/metaModel.json"))
46553-
46554-	findTypeNames(model)
46555-	generateOutput(model)
46556-
46557-	fileHdr = fileHeader(model)
46558-
46559-	// write the files
46560-	writeclient()
46561-	writeserver()
46562-	writeprotocol()
46563-	writejsons()
46564-
46565-	checkTables()
46566-}
46567-
46568-// common file header for output files
46569-var fileHdr string
46570-
46571-func writeclient() {
46572-	out := new(bytes.Buffer)
46573-	fmt.Fprintln(out, fileHdr)
46574-	out.WriteString(
46575-		`import (
46576-	"context"
46577-	"encoding/json"
46578-
46579-	"golang.org/x/tools/internal/jsonrpc2"
46580-)
46581-`)
46582-	out.WriteString("type Client interface {\n")
46583-	for _, k := range cdecls.keys() {
46584-		out.WriteString(cdecls[k])
46585-	}
46586-	out.WriteString("}\n\n")
46587-	out.WriteString("func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier, r jsonrpc2.Request) (bool, error) {\n")
46588-	out.WriteString("\tswitch r.Method() {\n")
46589-	for _, k := range ccases.keys() {
46590-		out.WriteString(ccases[k])
46591-	}
46592-	out.WriteString(("\tdefault:\n\t\treturn false, nil\n\t}\n}\n\n"))
46593-	for _, k := range cfuncs.keys() {
46594-		out.WriteString(cfuncs[k])
46595-	}
46596-
46597-	x, err := format.Source(out.Bytes())
46598-	if err != nil {
46599-		os.WriteFile("/tmp/a.go", out.Bytes(), 0644)
46600-		log.Fatalf("tsclient.go: %v", err)
46601-	}
46602-
46603-	if err := os.WriteFile(filepath.Join(*outputdir, "tsclient.go"), x, 0644); err != nil {
46604-		log.Fatalf("%v writing tsclient.go", err)
46605-	}
46606-}
46607-
46608-func writeserver() {
46609-	out := new(bytes.Buffer)
46610-	fmt.Fprintln(out, fileHdr)
46611-	out.WriteString(
46612-		`import (
46613-	"context"
46614-	"encoding/json"
46615-
46616-	"golang.org/x/tools/internal/jsonrpc2"
46617-)
46618-`)
46619-	out.WriteString("type Server interface {\n")
46620-	for _, k := range sdecls.keys() {
46621-		out.WriteString(sdecls[k])
46622-	}
46623-	out.WriteString(`	NonstandardRequest(ctx context.Context, method string, params interface{}) (interface{}, error)
46624-}
46625-
46626-func serverDispatch(ctx context.Context, server Server, reply jsonrpc2.Replier, r jsonrpc2.Request) (bool, error) {
46627-	switch r.Method() {
46628-`)
46629-	for _, k := range scases.keys() {
46630-		out.WriteString(scases[k])
46631-	}
46632-	out.WriteString(("\tdefault:\n\t\treturn false, nil\n\t}\n}\n\n"))
46633-	for _, k := range sfuncs.keys() {
46634-		out.WriteString(sfuncs[k])
46635-	}
46636-	out.WriteString(`func (s *serverDispatcher) NonstandardRequest(ctx context.Context, method string, params interface{}) (interface{}, error) {
46637-	var result interface{}
46638-	if err := s.sender.Call(ctx, method, params, &result); err != nil {
46639-		return nil, err
46640-	}
46641-	return result, nil
46642-}
46643-`)
46644-
46645-	x, err := format.Source(out.Bytes())
46646-	if err != nil {
46647-		os.WriteFile("/tmp/a.go", out.Bytes(), 0644)
46648-		log.Fatalf("tsserver.go: %v", err)
46649-	}
46650-
46651-	if err := os.WriteFile(filepath.Join(*outputdir, "tsserver.go"), x, 0644); err != nil {
46652-		log.Fatalf("%v writing tsserver.go", err)
46653-	}
46654-}
46655-
46656-func writeprotocol() {
46657-	out := new(bytes.Buffer)
46658-	fmt.Fprintln(out, fileHdr)
46659-	out.WriteString("import \"encoding/json\"\n\n")
46660-
46661-	// The followiing are unneeded, but make the new code a superset of the old
46662-	hack := func(newer, existing string) {
46663-		if _, ok := types[existing]; !ok {
46664-			log.Fatalf("types[%q] not found", existing)
46665-		}
46666-		types[newer] = strings.Replace(types[existing], existing, newer, 1)
46667-	}
46668-	hack("ConfigurationParams", "ParamConfiguration")
46669-	hack("InitializeParams", "ParamInitialize")
46670-	hack("PreviousResultId", "PreviousResultID")
46671-	hack("WorkspaceFoldersServerCapabilities", "WorkspaceFolders5Gn")
46672-	hack("_InitializeParams", "XInitializeParams")
46673-	// and some aliases to make the new code contain the old
46674-	types["PrepareRename2Gn"] = "type PrepareRename2Gn = Msg_PrepareRename2Gn // (alias) line 13927\n"
46675-	types["PrepareRenameResult"] = "type PrepareRenameResult = Msg_PrepareRename2Gn // (alias) line 13927\n"
46676-	for _, k := range types.keys() {
46677-		if k == "WatchKind" {
46678-			types[k] = "type WatchKind = uint32 // line 13505" // strict gopls compatibility needs the '='
46679-		}
46680-		out.WriteString(types[k])
46681-	}
46682-
46683-	out.WriteString("\nconst (\n")
46684-	for _, k := range consts.keys() {
46685-		out.WriteString(consts[k])
46686-	}
46687-	out.WriteString(")\n\n")
46688-	x, err := format.Source(out.Bytes())
46689-	if err != nil {
46690-		os.WriteFile("/tmp/a.go", out.Bytes(), 0644)
46691-		log.Fatalf("tsprotocol.go: %v", err)
46692-	}
46693-	if err := os.WriteFile(filepath.Join(*outputdir, "tsprotocol.go"), x, 0644); err != nil {
46694-		log.Fatalf("%v writing tsprotocol.go", err)
46695-	}
46696-}
46697-
46698-func writejsons() {
46699-	out := new(bytes.Buffer)
46700-	fmt.Fprintln(out, fileHdr)
46701-	out.WriteString("import \"encoding/json\"\n\n")
46702-	out.WriteString("import \"fmt\"\n")
46703-
46704-	out.WriteString(`
46705-// UnmarshalError indicates that a JSON value did not conform to
46706-// one of the expected cases of an LSP union type.
46707-type UnmarshalError struct {
46708-	msg string
46709-}
46710-
46711-func (e UnmarshalError) Error() string {
46712-	return e.msg
46713-}
46714-`)
46715-
46716-	for _, k := range jsons.keys() {
46717-		out.WriteString(jsons[k])
46718-	}
46719-	x, err := format.Source(out.Bytes())
46720-	if err != nil {
46721-		os.WriteFile("/tmp/a.go", out.Bytes(), 0644)
46722-		log.Fatalf("tsjson.go: %v", err)
46723-	}
46724-	if err := os.WriteFile(filepath.Join(*outputdir, "tsjson.go"), x, 0644); err != nil {
46725-		log.Fatalf("%v writing tsjson.go", err)
46726-	}
46727-}
46728-
46729-// create the common file header for the output files
46730-func fileHeader(model Model) string {
46731-	fname := filepath.Join(*repodir, ".git", "HEAD")
46732-	buf, err := os.ReadFile(fname)
46733-	if err != nil {
46734-		log.Fatal(err)
46735-	}
46736-	buf = bytes.TrimSpace(buf)
46737-	var githash string
46738-	if len(buf) == 40 {
46739-		githash = string(buf[:40])
46740-	} else if bytes.HasPrefix(buf, []byte("ref: ")) {
46741-		fname = filepath.Join(*repodir, ".git", string(buf[5:]))
46742-		buf, err = os.ReadFile(fname)
46743-		if err != nil {
46744-			log.Fatal(err)
46745-		}
46746-		githash = string(buf[:40])
46747-	} else {
46748-		log.Fatalf("githash cannot be recovered from %s", fname)
46749-	}
46750-
46751-	format := `// Copyright 2023 The Go Authors. All rights reserved.
46752-// Use of this source code is governed by a BSD-style
46753-// license that can be found in the LICENSE file.
46754-
46755-// Code generated for LSP. DO NOT EDIT.
46756-
46757-package protocol
46758-
46759-// Code generated from %[1]s at ref %[2]s (hash %[3]s).
46760-// %[4]s/blob/%[2]s/%[1]s
46761-// LSP metaData.version = %[5]s.
46762-
46763-`
46764-	return fmt.Sprintf(format,
46765-		"protocol/metaModel.json", // 1
46766-		lspGitRef,                 // 2
46767-		githash,                   // 3
46768-		vscodeRepo,                // 4
46769-		model.Version.Version)     // 5
46770-}
46771-
46772-func parse(fname string) Model {
46773-	buf, err := os.ReadFile(fname)
46774-	if err != nil {
46775-		log.Fatal(err)
46776-	}
46777-	buf = addLineNumbers(buf)
46778-	var model Model
46779-	if err := json.Unmarshal(buf, &model); err != nil {
46780-		log.Fatal(err)
46781-	}
46782-	return model
46783-}
46784-
46785-// Type.Value has to be treated specially for literals and maps
46786-func (t *Type) UnmarshalJSON(data []byte) error {
46787-	// First unmarshal only the unambiguous fields.
46788-	var x struct {
46789-		Kind    string  `json:"kind"`
46790-		Items   []*Type `json:"items"`
46791-		Element *Type   `json:"element"`
46792-		Name    string  `json:"name"`
46793-		Key     *Type   `json:"key"`
46794-		Value   any     `json:"value"`
46795-		Line    int     `json:"line"`
46796-	}
46797-	if err := json.Unmarshal(data, &x); err != nil {
46798-		return err
46799-	}
46800-	*t = Type{
46801-		Kind:    x.Kind,
46802-		Items:   x.Items,
46803-		Element: x.Element,
46804-		Name:    x.Name,
46805-		Value:   x.Value,
46806-		Line:    x.Line,
46807-	}
46808-
46809-	// Then unmarshal the 'value' field based on the kind.
46810-	// This depends on Unmarshal ignoring fields it doesn't know about.
46811-	switch x.Kind {
46812-	case "map":
46813-		var x struct {
46814-			Key   *Type `json:"key"`
46815-			Value *Type `json:"value"`
46816-		}
46817-		if err := json.Unmarshal(data, &x); err != nil {
46818-			return fmt.Errorf("Type.kind=map: %v", err)
46819-		}
46820-		t.Key = x.Key
46821-		t.Value = x.Value
46822-
46823-	case "literal":
46824-		var z struct {
46825-			Value ParseLiteral `json:"value"`
46826-		}
46827-
46828-		if err := json.Unmarshal(data, &z); err != nil {
46829-			return fmt.Errorf("Type.kind=literal: %v", err)
46830-		}
46831-		t.Value = z.Value
46832-
46833-	case "base", "reference", "array", "and", "or", "tuple",
46834-		"stringLiteral":
46835-		// no-op. never seen integerLiteral or booleanLiteral.
46836-
46837-	default:
46838-		return fmt.Errorf("cannot decode Type.kind %q: %s", x.Kind, data)
46839-	}
46840-	return nil
46841-}
46842-
46843-// which table entries were not used
46844-func checkTables() {
46845-	for k := range disambiguate {
46846-		if !usedDisambiguate[k] {
46847-			log.Printf("disambiguate[%v] unused", k)
46848-		}
46849-	}
46850-	for k := range renameProp {
46851-		if !usedRenameProp[k] {
46852-			log.Printf("renameProp {%q, %q} unused", k[0], k[1])
46853-		}
46854-	}
46855-	for k := range goplsStar {
46856-		if !usedGoplsStar[k] {
46857-			log.Printf("goplsStar {%q, %q} unused", k[0], k[1])
46858-		}
46859-	}
46860-	for k := range goplsType {
46861-		if !usedGoplsType[k] {
46862-			log.Printf("unused goplsType[%q]->%s", k, goplsType[k])
46863-		}
46864-	}
46865-}
46866diff -urN a/gopls/internal/lsp/protocol/generate/main_test.go b/gopls/internal/lsp/protocol/generate/main_test.go
46867--- a/gopls/internal/lsp/protocol/generate/main_test.go	2000-01-01 00:00:00.000000000 -0000
46868+++ b/gopls/internal/lsp/protocol/generate/main_test.go	1970-01-01 00:00:00.000000000 +0000
46869@@ -1,118 +0,0 @@
46870-// Copyright 2022 The Go Authors. All rights reserved.
46871-// Use of this source code is governed by a BSD-style
46872-// license that can be found in the LICENSE file.
46873-
46874-//go:build go1.19
46875-// +build go1.19
46876-
46877-package main
46878-
46879-import (
46880-	"encoding/json"
46881-	"fmt"
46882-	"log"
46883-	"os"
46884-	"testing"
46885-)
46886-
46887-// These tests require the result of
46888-//"git clone https://github.com/microsoft/vscode-languageserver-node" in the HOME directory
46889-
46890-// this is not a test, but a way to get code coverage,
46891-// (in vscode, just run the test with  "go.coverOnSingleTest": true)
46892-func TestAll(t *testing.T) {
46893-	t.Skip("needs vscode-languageserver-node repository")
46894-	log.SetFlags(log.Lshortfile)
46895-	main()
46896-}
46897-
46898-// check that the parsed file includes all the information
46899-// from the json file. This test will fail if the spec
46900-// introduces new fields. (one can test this test by
46901-// commenting out the version field in Model.)
46902-func TestParseContents(t *testing.T) {
46903-	t.Skip("needs vscode-languageserver-node repository")
46904-	log.SetFlags(log.Lshortfile)
46905-
46906-	// compute our parse of the specification
46907-	dir := os.Getenv("HOME") + "/vscode-languageserver-node"
46908-	fname := dir + "/protocol/metaModel.json"
46909-	v := parse(fname)
46910-	out, err := json.Marshal(v)
46911-	if err != nil {
46912-		t.Fatal(err)
46913-	}
46914-	var our interface{}
46915-	if err := json.Unmarshal(out, &our); err != nil {
46916-		t.Fatal(err)
46917-	}
46918-
46919-	// process the json file
46920-	buf, err := os.ReadFile(fname)
46921-	if err != nil {
46922-		t.Fatalf("could not read metaModel.json: %v", err)
46923-	}
46924-	var raw interface{}
46925-	if err := json.Unmarshal(buf, &raw); err != nil {
46926-		t.Fatal(err)
46927-	}
46928-
46929-	// convert to strings showing the fields
46930-	them := flatten(raw)
46931-	us := flatten(our)
46932-
46933-	// everything in them should be in us
46934-	lesser := make(sortedMap[bool])
46935-	for _, s := range them {
46936-		lesser[s] = true
46937-	}
46938-	greater := make(sortedMap[bool]) // set of fields we have
46939-	for _, s := range us {
46940-		greater[s] = true
46941-	}
46942-	for _, k := range lesser.keys() { // set if fields they have
46943-		if !greater[k] {
46944-			t.Errorf("missing %s", k)
46945-		}
46946-	}
46947-}
46948-
46949-// flatten(nil) = "nil"
46950-// flatten(v string) = fmt.Sprintf("%q", v)
46951-// flatten(v float64)= fmt.Sprintf("%g", v)
46952-// flatten(v bool) = fmt.Sprintf("%v", v)
46953-// flatten(v []any) = []string{"[0]"flatten(v[0]), "[1]"flatten(v[1]), ...}
46954-// flatten(v map[string]any) = {"key1": flatten(v["key1"]), "key2": flatten(v["key2"]), ...}
46955-func flatten(x any) []string {
46956-	switch v := x.(type) {
46957-	case nil:
46958-		return []string{"nil"}
46959-	case string:
46960-		return []string{fmt.Sprintf("%q", v)}
46961-	case float64:
46962-		return []string{fmt.Sprintf("%g", v)}
46963-	case bool:
46964-		return []string{fmt.Sprintf("%v", v)}
46965-	case []any:
46966-		var ans []string
46967-		for i, x := range v {
46968-			idx := fmt.Sprintf("[%.3d]", i)
46969-			for _, s := range flatten(x) {
46970-				ans = append(ans, idx+s)
46971-			}
46972-		}
46973-		return ans
46974-	case map[string]any:
46975-		var ans []string
46976-		for k, x := range v {
46977-			idx := fmt.Sprintf("%q:", k)
46978-			for _, s := range flatten(x) {
46979-				ans = append(ans, idx+s)
46980-			}
46981-		}
46982-		return ans
46983-	default:
46984-		log.Fatalf("unexpected type %T", x)
46985-		return nil
46986-	}
46987-}
46988diff -urN a/gopls/internal/lsp/protocol/generate/output.go b/gopls/internal/lsp/protocol/generate/output.go
46989--- a/gopls/internal/lsp/protocol/generate/output.go	2000-01-01 00:00:00.000000000 -0000
46990+++ b/gopls/internal/lsp/protocol/generate/output.go	1970-01-01 00:00:00.000000000 +0000
46991@@ -1,420 +0,0 @@
46992-// Copyright 2022 The Go Authors. All rights reserved.
46993-// Use of this source code is governed by a BSD-style
46994-// license that can be found in the LICENSE file.
46995-
46996-//go:build go1.19
46997-// +build go1.19
46998-
46999-package main
47000-
47001-import (
47002-	"bytes"
47003-	"fmt"
47004-	"log"
47005-	"sort"
47006-	"strings"
47007-)
47008-
47009-var (
47010-	// tsclient.go has 3 sections
47011-	cdecls = make(sortedMap[string])
47012-	ccases = make(sortedMap[string])
47013-	cfuncs = make(sortedMap[string])
47014-	// tsserver.go has 3 sections
47015-	sdecls = make(sortedMap[string])
47016-	scases = make(sortedMap[string])
47017-	sfuncs = make(sortedMap[string])
47018-	// tsprotocol.go has 2 sections
47019-	types  = make(sortedMap[string])
47020-	consts = make(sortedMap[string])
47021-	// tsjson has 1 section
47022-	jsons = make(sortedMap[string])
47023-)
47024-
47025-func generateOutput(model Model) {
47026-	for _, r := range model.Requests {
47027-		genDecl(r.Method, r.Params, r.Result, r.Direction)
47028-		genCase(r.Method, r.Params, r.Result, r.Direction)
47029-		genFunc(r.Method, r.Params, r.Result, r.Direction, false)
47030-	}
47031-	for _, n := range model.Notifications {
47032-		if n.Method == "$/cancelRequest" {
47033-			continue // handled internally by jsonrpc2
47034-		}
47035-		genDecl(n.Method, n.Params, nil, n.Direction)
47036-		genCase(n.Method, n.Params, nil, n.Direction)
47037-		genFunc(n.Method, n.Params, nil, n.Direction, true)
47038-	}
47039-	genStructs(model)
47040-	genAliases(model)
47041-	genGenTypes() // generate the unnamed types
47042-	genConsts(model)
47043-	genMarshal()
47044-}
47045-
47046-func genDecl(method string, param, result *Type, dir string) {
47047-	fname := methodNames[method]
47048-	p := ""
47049-	if notNil(param) {
47050-		p = ", *" + goplsName(param)
47051-	}
47052-	ret := "error"
47053-	if notNil(result) {
47054-		tp := goplsName(result)
47055-		if !hasNilValue(tp) {
47056-			tp = "*" + tp
47057-		}
47058-		ret = fmt.Sprintf("(%s, error)", tp)
47059-	}
47060-	// special gopls compatibility case (PJW: still needed?)
47061-	switch method {
47062-	case "workspace/configuration":
47063-		// was And_Param_workspace_configuration, but the type substitution doesn't work,
47064-		// as ParamConfiguration is embedded in And_Param_workspace_configuration
47065-		p = ", *ParamConfiguration"
47066-		ret = "([]LSPAny, error)"
47067-	}
47068-	msg := fmt.Sprintf("\t%s(context.Context%s) %s // %s\n", fname, p, ret, method)
47069-	switch dir {
47070-	case "clientToServer":
47071-		sdecls[method] = msg
47072-	case "serverToClient":
47073-		cdecls[method] = msg
47074-	case "both":
47075-		sdecls[method] = msg
47076-		cdecls[method] = msg
47077-	default:
47078-		log.Fatalf("impossible direction %q", dir)
47079-	}
47080-}
47081-
47082-func genCase(method string, param, result *Type, dir string) {
47083-	out := new(bytes.Buffer)
47084-	fmt.Fprintf(out, "\tcase %q:\n", method)
47085-	var p string
47086-	fname := methodNames[method]
47087-	if notNil(param) {
47088-		nm := goplsName(param)
47089-		if method == "workspace/configuration" { // gopls compatibility
47090-			// was And_Param_workspace_configuration, which contains ParamConfiguration
47091-			// so renaming the type leads to circular definitions
47092-			nm = "ParamConfiguration" // gopls compatibility
47093-		}
47094-		fmt.Fprintf(out, "\t\tvar params %s\n", nm)
47095-		fmt.Fprintf(out, "\t\tif err := json.Unmarshal(r.Params(), &params); err != nil {\n")
47096-		fmt.Fprintf(out, "\t\t\treturn true, sendParseError(ctx, reply, err)\n\t\t}\n")
47097-		p = ", &params"
47098-	}
47099-	if notNil(result) {
47100-		fmt.Fprintf(out, "\t\tresp, err := %%s.%s(ctx%s)\n", fname, p)
47101-		out.WriteString("\t\tif err != nil {\n")
47102-		out.WriteString("\t\t\treturn true, reply(ctx, nil, err)\n")
47103-		out.WriteString("\t\t}\n")
47104-		out.WriteString("\t\treturn true, reply(ctx, resp, nil)\n")
47105-	} else {
47106-		fmt.Fprintf(out, "\t\terr := %%s.%s(ctx%s)\n", fname, p)
47107-		out.WriteString("\t\treturn true, reply(ctx, nil, err)\n")
47108-	}
47109-	msg := out.String()
47110-	switch dir {
47111-	case "clientToServer":
47112-		scases[method] = fmt.Sprintf(msg, "server")
47113-	case "serverToClient":
47114-		ccases[method] = fmt.Sprintf(msg, "client")
47115-	case "both":
47116-		scases[method] = fmt.Sprintf(msg, "server")
47117-		ccases[method] = fmt.Sprintf(msg, "client")
47118-	default:
47119-		log.Fatalf("impossible direction %q", dir)
47120-	}
47121-}
47122-
47123-func genFunc(method string, param, result *Type, dir string, isnotify bool) {
47124-	out := new(bytes.Buffer)
47125-	var p, r string
47126-	var goResult string
47127-	if notNil(param) {
47128-		p = ", params *" + goplsName(param)
47129-	}
47130-	if notNil(result) {
47131-		goResult = goplsName(result)
47132-		if !hasNilValue(goResult) {
47133-			goResult = "*" + goResult
47134-		}
47135-		r = fmt.Sprintf("(%s, error)", goResult)
47136-	} else {
47137-		r = "error"
47138-	}
47139-	// special gopls compatibility case
47140-	switch method {
47141-	case "workspace/configuration":
47142-		// was And_Param_workspace_configuration, but the type substitution doesn't work,
47143-		// as ParamConfiguration is embedded in And_Param_workspace_configuration
47144-		p = ", params *ParamConfiguration"
47145-		r = "([]LSPAny, error)"
47146-		goResult = "[]LSPAny"
47147-	}
47148-	fname := methodNames[method]
47149-	fmt.Fprintf(out, "func (s *%%sDispatcher) %s(ctx context.Context%s) %s {\n",
47150-		fname, p, r)
47151-
47152-	if !notNil(result) {
47153-		if isnotify {
47154-			if notNil(param) {
47155-				fmt.Fprintf(out, "\treturn s.sender.Notify(ctx, %q, params)\n", method)
47156-			} else {
47157-				fmt.Fprintf(out, "\treturn s.sender.Notify(ctx, %q, nil)\n", method)
47158-			}
47159-		} else {
47160-			if notNil(param) {
47161-				fmt.Fprintf(out, "\treturn s.sender.Call(ctx, %q, params, nil)\n", method)
47162-			} else {
47163-				fmt.Fprintf(out, "\treturn s.sender.Call(ctx, %q, nil, nil)\n", method)
47164-			}
47165-		}
47166-	} else {
47167-		fmt.Fprintf(out, "\tvar result %s\n", goResult)
47168-		if isnotify {
47169-			if notNil(param) {
47170-				fmt.Fprintf(out, "\ts.sender.Notify(ctx, %q, params)\n", method)
47171-			} else {
47172-				fmt.Fprintf(out, "\t\tif err := s.sender.Notify(ctx, %q, nil); err != nil {\n", method)
47173-			}
47174-		} else {
47175-			if notNil(param) {
47176-				fmt.Fprintf(out, "\t\tif err := s.sender.Call(ctx, %q, params, &result); err != nil {\n", method)
47177-			} else {
47178-				fmt.Fprintf(out, "\t\tif err := s.sender.Call(ctx, %q, nil, &result); err != nil {\n", method)
47179-			}
47180-		}
47181-		fmt.Fprintf(out, "\t\treturn nil, err\n\t}\n\treturn result, nil\n")
47182-	}
47183-	out.WriteString("}\n")
47184-	msg := out.String()
47185-	switch dir {
47186-	case "clientToServer":
47187-		sfuncs[method] = fmt.Sprintf(msg, "server")
47188-	case "serverToClient":
47189-		cfuncs[method] = fmt.Sprintf(msg, "client")
47190-	case "both":
47191-		sfuncs[method] = fmt.Sprintf(msg, "server")
47192-		cfuncs[method] = fmt.Sprintf(msg, "client")
47193-	default:
47194-		log.Fatalf("impossible direction %q", dir)
47195-	}
47196-}
47197-
47198-func genStructs(model Model) {
47199-	structures := make(map[string]*Structure) // for expanding Extends
47200-	for _, s := range model.Structures {
47201-		structures[s.Name] = s
47202-	}
47203-	for _, s := range model.Structures {
47204-		out := new(bytes.Buffer)
47205-		generateDoc(out, s.Documentation)
47206-		nm := goName(s.Name)
47207-		if nm == "string" { // an unacceptable strut name
47208-			// a weird case, and needed only so the generated code contains the old gopls code
47209-			nm = "DocumentDiagnosticParams"
47210-		}
47211-		fmt.Fprintf(out, "type %s struct { // line %d\n", nm, s.Line)
47212-		// for gpls compatibilitye, embed most extensions, but expand the rest some day
47213-		props := append([]NameType{}, s.Properties...)
47214-		if s.Name == "SymbolInformation" { // but expand this one
47215-			for _, ex := range s.Extends {
47216-				fmt.Fprintf(out, "\t// extends %s\n", ex.Name)
47217-				props = append(props, structures[ex.Name].Properties...)
47218-			}
47219-			genProps(out, props, nm)
47220-		} else {
47221-			genProps(out, props, nm)
47222-			for _, ex := range s.Extends {
47223-				fmt.Fprintf(out, "\t%s\n", goName(ex.Name))
47224-			}
47225-		}
47226-		for _, ex := range s.Mixins {
47227-			fmt.Fprintf(out, "\t%s\n", goName(ex.Name))
47228-		}
47229-		out.WriteString("}\n")
47230-		types[nm] = out.String()
47231-	}
47232-	// base types
47233-	types["DocumentURI"] = "type DocumentURI string\n"
47234-	types["URI"] = "type URI = string\n"
47235-
47236-	types["LSPAny"] = "type LSPAny = interface{}\n"
47237-	// A special case, the only previously existing Or type
47238-	types["DocumentDiagnosticReport"] = "type DocumentDiagnosticReport = Or_DocumentDiagnosticReport // (alias) line 13909\n"
47239-
47240-}
47241-
47242-func genProps(out *bytes.Buffer, props []NameType, name string) {
47243-	for _, p := range props {
47244-		tp := goplsName(p.Type)
47245-		if newNm, ok := renameProp[prop{name, p.Name}]; ok {
47246-			usedRenameProp[prop{name, p.Name}] = true
47247-			if tp == newNm {
47248-				log.Printf("renameProp useless {%q, %q} for %s", name, p.Name, tp)
47249-			}
47250-			tp = newNm
47251-		}
47252-		// it's a pointer if it is optional, or for gopls compatibility
47253-		opt, star := propStar(name, p, tp)
47254-		json := fmt.Sprintf(" `json:\"%s%s\"`", p.Name, opt)
47255-		generateDoc(out, p.Documentation)
47256-		fmt.Fprintf(out, "\t%s %s%s %s\n", goName(p.Name), star, tp, json)
47257-	}
47258-}
47259-
47260-func genAliases(model Model) {
47261-	for _, ta := range model.TypeAliases {
47262-		out := new(bytes.Buffer)
47263-		generateDoc(out, ta.Documentation)
47264-		nm := goName(ta.Name)
47265-		if nm != ta.Name {
47266-			continue // renamed the type, e.g., "DocumentDiagnosticReport", an or-type to "string"
47267-		}
47268-		tp := goplsName(ta.Type)
47269-		fmt.Fprintf(out, "type %s = %s // (alias) line %d\n", nm, tp, ta.Line)
47270-		types[nm] = out.String()
47271-	}
47272-}
47273-
47274-func genGenTypes() {
47275-	for _, nt := range genTypes {
47276-		out := new(bytes.Buffer)
47277-		nm := goplsName(nt.typ)
47278-		switch nt.kind {
47279-		case "literal":
47280-			fmt.Fprintf(out, "// created for Literal (%s)\n", nt.name)
47281-			fmt.Fprintf(out, "type %s struct { // line %d\n", nm, nt.line+1)
47282-			genProps(out, nt.properties, nt.name) // systematic name, not gopls name; is this a good choice?
47283-		case "or":
47284-			if !strings.HasPrefix(nm, "Or") {
47285-				// It was replaced by a narrower type defined elsewhere
47286-				continue
47287-			}
47288-			names := []string{}
47289-			for _, t := range nt.items {
47290-				if notNil(t) {
47291-					names = append(names, goplsName(t))
47292-				}
47293-			}
47294-			sort.Strings(names)
47295-			fmt.Fprintf(out, "// created for Or %v\n", names)
47296-			fmt.Fprintf(out, "type %s struct { // line %d\n", nm, nt.line+1)
47297-			fmt.Fprintf(out, "\tValue interface{} `json:\"value\"`\n")
47298-		case "and":
47299-			fmt.Fprintf(out, "// created for And\n")
47300-			fmt.Fprintf(out, "type %s struct { // line %d\n", nm, nt.line+1)
47301-			for _, x := range nt.items {
47302-				nm := goplsName(x)
47303-				fmt.Fprintf(out, "\t%s\n", nm)
47304-			}
47305-		case "tuple": // there's only this one
47306-			nt.name = "UIntCommaUInt"
47307-			fmt.Fprintf(out, "//created for Tuple\ntype %s struct { // line %d\n", nm, nt.line+1)
47308-			fmt.Fprintf(out, "\tFld0 uint32 `json:\"fld0\"`\n")
47309-			fmt.Fprintf(out, "\tFld1 uint32 `json:\"fld1\"`\n")
47310-		default:
47311-			log.Fatalf("%s not handled", nt.kind)
47312-		}
47313-		out.WriteString("}\n")
47314-		types[nm] = out.String()
47315-	}
47316-}
47317-func genConsts(model Model) {
47318-	for _, e := range model.Enumerations {
47319-		out := new(bytes.Buffer)
47320-		generateDoc(out, e.Documentation)
47321-		tp := goplsName(e.Type)
47322-		nm := goName(e.Name)
47323-		fmt.Fprintf(out, "type %s %s // line %d\n", nm, tp, e.Line)
47324-		types[nm] = out.String()
47325-		vals := new(bytes.Buffer)
47326-		generateDoc(vals, e.Documentation)
47327-		for _, v := range e.Values {
47328-			generateDoc(vals, v.Documentation)
47329-			nm := goName(v.Name)
47330-			more, ok := disambiguate[e.Name]
47331-			if ok {
47332-				usedDisambiguate[e.Name] = true
47333-				nm = more.prefix + nm + more.suffix
47334-				nm = goName(nm) // stringType
47335-			}
47336-			var val string
47337-			switch v := v.Value.(type) {
47338-			case string:
47339-				val = fmt.Sprintf("%q", v)
47340-			case float64:
47341-				val = fmt.Sprintf("%d", int(v))
47342-			default:
47343-				log.Fatalf("impossible type %T", v)
47344-			}
47345-			fmt.Fprintf(vals, "\t%s %s = %s // line %d\n", nm, e.Name, val, v.Line)
47346-		}
47347-		consts[nm] = vals.String()
47348-	}
47349-}
47350-func genMarshal() {
47351-	for _, nt := range genTypes {
47352-		nm := goplsName(nt.typ)
47353-		if !strings.HasPrefix(nm, "Or") {
47354-			continue
47355-		}
47356-		names := []string{}
47357-		for _, t := range nt.items {
47358-			if notNil(t) {
47359-				names = append(names, goplsName(t))
47360-			}
47361-		}
47362-		sort.Strings(names)
47363-		var buf bytes.Buffer
47364-		fmt.Fprintf(&buf, "// from line %d\n", nt.line)
47365-		fmt.Fprintf(&buf, "func (t %s) MarshalJSON() ([]byte, error) {\n", nm)
47366-		buf.WriteString("\tswitch x := t.Value.(type){\n")
47367-		for _, nmx := range names {
47368-			fmt.Fprintf(&buf, "\tcase %s:\n", nmx)
47369-			fmt.Fprintf(&buf, "\t\treturn json.Marshal(x)\n")
47370-		}
47371-		buf.WriteString("\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n")
47372-		fmt.Fprintf(&buf, "\treturn nil, fmt.Errorf(\"type %%T not one of %v\", t)\n", names)
47373-		buf.WriteString("}\n\n")
47374-
47375-		fmt.Fprintf(&buf, "func (t *%s) UnmarshalJSON(x []byte) error {\n", nm)
47376-		buf.WriteString("\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\t\treturn nil\n\t}\n")
47377-		for i, nmx := range names {
47378-			fmt.Fprintf(&buf, "\tvar h%d %s\n", i, nmx)
47379-			fmt.Fprintf(&buf, "\tif err := json.Unmarshal(x, &h%d); err == nil {\n\t\tt.Value = h%d\n\t\t\treturn nil\n\t\t}\n", i, i)
47380-		}
47381-		fmt.Fprintf(&buf, "return &UnmarshalError{\"unmarshal failed to match one of %v\"}", names)
47382-		buf.WriteString("}\n\n")
47383-		jsons[nm] = buf.String()
47384-	}
47385-}
47386-
47387-func goplsName(t *Type) string {
47388-	nm := typeNames[t]
47389-	// translate systematic name to gopls name
47390-	if newNm, ok := goplsType[nm]; ok {
47391-		usedGoplsType[nm] = true
47392-		nm = newNm
47393-	}
47394-	return nm
47395-}
47396-
47397-func notNil(t *Type) bool { // shutdwon is the special case that needs this
47398-	return t != nil && (t.Kind != "base" || t.Name != "null")
47399-}
47400-
47401-func hasNilValue(t string) bool {
47402-	// this may be unreliable, and need a supplementary table
47403-	if strings.HasPrefix(t, "[]") || strings.HasPrefix(t, "*") {
47404-		return true
47405-	}
47406-	if t == "interface{}" || t == "any" {
47407-		return true
47408-	}
47409-	// that's all the cases that occur currently
47410-	return false
47411-}
47412diff -urN a/gopls/internal/lsp/protocol/generate/README.md b/gopls/internal/lsp/protocol/generate/README.md
47413--- a/gopls/internal/lsp/protocol/generate/README.md	2000-01-01 00:00:00.000000000 -0000
47414+++ b/gopls/internal/lsp/protocol/generate/README.md	1970-01-01 00:00:00.000000000 +0000
47415@@ -1,136 +0,0 @@
47416-# LSP Support for gopls
47417-
47418-## The protocol
47419-
47420-The LSP protocol exchanges json-encoded messages between the client and the server.
47421-(gopls is the server.) The messages are either Requests, which require Responses, or
47422-Notifications, which generate no response. Each Request or Notification has a method name
47423-such as "textDocument/hover" that indicates its meaning and determines which function in the server will handle it.
47424-The protocol is described in a
47425-[web page](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/),
47426-in words, and in a json file (metaModel.json) available either linked towards the bottom of the
47427-web page, or in the vscode-languageserver-node repository. This code uses the latter so the
47428-exact version can be tied to a githash. By default, the command will download the `github.com/microsoft/vscode-languageserver-node` repository to a temporary directory.
47429-
47430-The specification has five sections
47431-1. Requests, which describe the Request and Response types for request methods (e.g., *textDocument/didChange*),
47432-2. Notifications, which describe the Request types for notification methods,
47433-3. Structures, which describe named struct-like types,
47434-4. TypeAliases, which describe type aliases,
47435-5. Enumerations, which describe named constants.
47436-
47437-Requests and Notifications are tagged with a Method (e.g., `"textDocument/hover"`).
47438-The specification does not specify the names of the functions that handle the messages. These
47439-names are specified by the `methodNames` map. Enumerations generate Go `const`s, but
47440-in Typescript they are scoped to namespaces, while in Go they are scoped to a package, so the Go names
47441-may need to be modified to avoid name collisions. (See the `disambiguate` map, and its use.)
47442-
47443-Finally, the specified types are Typescript types, which are quite different from Go types.
47444-
47445-### Optionality
47446-The specification can mark fields in structs as Optional. The client distinguishes between missing
47447-fields and `null` fields in some cases. The Go translation for an optional type
47448-should be making sure the field's value
47449-can be `nil`, and adding the json tag `,omitempty`. The former condition would be satisfied by
47450-adding `*` to the field's type if the type is not a reference type.
47451-
47452-### Types
47453-The specification uses a number of different types, only a few of which correspond directly to Go types.
47454-The specification's types are "base", "reference", "map", "literal", "stringLiteral", "tuple", "and", "or".
47455-The "base" types correspond directly to Go types, although some Go types needs to be chosen for `URI` and `DocumentUri`. (The "base" types`RegExp`, `BooleanLiteral`, `NumericLiteral` never occur.)
47456-
47457-"reference" types are the struct-like types in the Structures section of the specification. The given
47458-names are suitable for Go to use, except the code needs to change names like `_Initialze` to `XInitialize` so
47459-they are exported for json marshaling and unmarshaling.
47460-
47461-"map" types are just like Go. (The key type in all of them is `DocumentUri`.)
47462-
47463-"stringLiteral" types are types whose type name and value are a single string. The chosen Go equivalent
47464-is to make the type `string` and the value a constant. (The alternative would be to generate a new
47465-named type, which seemed redundant.)
47466-
47467-"literal" types are like Go anonymous structs, so they have to be given a name. (All instances
47468-of the remaining types have to be given names. One approach is to construct the name from the components
47469-of the type, but this leads to misleading punning, and is unstable if components are added. The other approach
47470-is to construct the name from the context of the definition, that is, from the types it is defined within.
47471-For instance `Lit__InitializeParams_clientInfo` is the "literal" type at the
47472-`clientInfo` field in the `_InitializeParams`
47473-struct. Although this choice is sensitive to the ordering of the components, the code uses this approach,
47474-presuming that reordering components is an unlikely protocol change.)
47475-
47476-"tuple" types are generated as Go structs. (There is only one, with two `uint32` fields.)
47477-
47478-"and" types are Go structs with embedded type names. (There is only one, `And_Param_workspace_configuration`.)
47479-
47480-"or" types are the most complicated. There are a lot of them and there is no simple Go equivalent.
47481-They are defined as structs with a single `Value interface{}` field and custom json marshaling
47482-and unmarshaling code. Users can assign anything to `Value` but the type will be checked, and
47483-correctly marshaled, by the custom marshaling code. The unmarshaling code checks types, so `Value`
47484-will have one of the permitted types. (`nil` is always allowed.) There are about 40 "or" types that
47485-have a single non-null component, and these are converted to the component type.
47486-
47487-## Processing
47488-The code parses the json specification file, and scans all the types. It assigns names, as described
47489-above, to the types that are unnamed in the specification, and constructs Go equivalents as required.
47490-(Most of this code is in typenames.go.)
47491-
47492-There are four output files. tsclient.go and tsserver.go contain the definition and implementation
47493-of the `protocol.Client` and `protocol.Server` types and the code that dispatches on the Method
47494-of the Request or Notification. tsjson.go contains the custom marshaling and unmarshaling code.
47495-And tsprotocol.go contains the type and const definitions.
47496-
47497-### Accommodating gopls
47498-As the code generates output, mostly in generateoutput.go and main.go,
47499-it makes adjustments so that no changes are required to the existing Go code.
47500-(Organizing the computation this way makes the code's structure simpler, but results in
47501-a lot of unused types.)
47502-There are three major classes of these adjustments, and leftover special cases.
47503-
47504-The first major
47505-adjustment is to change generated type names to the ones gopls expects. Some of these don't change the
47506-semantics of the type, just the name.
47507-But for historical reasons a lot of them replace "or" types by a single
47508-component of the type. (Until fairly recently Go only saw or used only one of components.)
47509-The `goplsType` map in tables.go controls this process.
47510-
47511-The second major adjustment is to the types of fields of structs, which is done using the
47512-`renameProp` map in tables.go.
47513-
47514-The third major adjustment handles optionality, controlling `*` and `,omitempty` placement when
47515-the default rules don't match what gopls is expecting. (The map is `goplsStar`, also in tables.go)
47516-(If the intermediate components in expressions of the form `A.B.C.S` were optional, the code would need
47517-a lot of useless checking for nils. Typescript has a language construct to avoid most checks.)
47518-
47519-Then there are some additional special cases. There are a few places with adjustments to avoid
47520-recursive types. For instance `LSPArray` is `[]LSPAny`, but `LSPAny` is an "or" type including `LSPArray`.
47521-The solution is to make `LSPAny` an `interface{}`. Another instance is `_InitializeParams.trace`
47522-whose type is an "or" of 3 stringLiterals, which just becomes a `string`.
47523-
47524-### Checking
47525-`TestAll(t *testing.T)` checks that there are no unexpected fields in the json specification.
47526-
47527-While the code is executing, it checks that all the entries in the maps in tables.go are used.
47528-It also checks that the entries in `renameProp` and `goplsStar` are not redundant.
47529-
47530-As a one-time check on the first release of this code, diff-ing the existing and generated tsclient.go
47531-and tsserver.go code results in only whitespace and comment diffs. The existing and generated
47532-tsprotocol.go differ in whitespace and comments, and in a substantial number of new type definitions
47533-that the older, more heuristic, code did not generate. (And the unused type `_InitializeParams` differs
47534-slightly between the new and the old, and is not worth fixing.)
47535-
47536-### Some history
47537-The original stub code was written by hand, but with the protocol under active development, that
47538-couldn't last. The web page existed before the json specification, but it lagged the implementation
47539-and was hard to process by machine. So the earlier version of the generating code was written in Typescript, and
47540-used the Typescript compiler's API to parse the protocol code in the repository.
47541-It then used a set of heuristics
47542-to pick out the elements of the protocol, and another set of overlapping heuristics to create the Go code.
47543-The output was functional, but idiosyncratic, and the code was fragile and barely maintainable.
47544-
47545-### The future
47546-Most of the adjustments using the maps in tables.go could be removed by making changes, mostly to names,
47547-in the gopls code. Using more "or" types in gopls requires more elaborate, but stereotyped, changes.
47548-But even without all the adjustments, making this its own module would face problems; a number of
47549-dependencies would have to be factored out. And, it is fragile. The custom unmarshaling code knows what
47550-types it expects. A design that return an 'any' on unexpected types would match the json
47551-'ignore unexpected values' philosophy better, but the the Go code would need extra checking.
47552diff -urN a/gopls/internal/lsp/protocol/generate/tables.go b/gopls/internal/lsp/protocol/generate/tables.go
47553--- a/gopls/internal/lsp/protocol/generate/tables.go	2000-01-01 00:00:00.000000000 -0000
47554+++ b/gopls/internal/lsp/protocol/generate/tables.go	1970-01-01 00:00:00.000000000 +0000
47555@@ -1,327 +0,0 @@
47556-// Copyright 2022 The Go Authors. All rights reserved.
47557-// Use of this source code is governed by a BSD-style
47558-// license that can be found in the LICENSE file.
47559-
47560-//go:build go1.19
47561-// +build go1.19
47562-
47563-package main
47564-
47565-// prop combines the name of a property with the name of the structure it is in.
47566-type prop [2]string
47567-
47568-const (
47569-	nothing = iota
47570-	wantStar
47571-	wantOpt
47572-	wantOptStar
47573-)
47574-
47575-// goplsStar records the optionality of each field in the protocol.
47576-// The comments are vague hints as to why removing the line is not trivial.
47577-// A.B.C.D means that one of B or C would change to a pointer
47578-// so a test or initialization would be needed
47579-var goplsStar = map[prop]int{
47580-	{"ClientCapabilities", "textDocument"}: wantOpt, // A.B.C.D at fake/editor.go:255
47581-	{"ClientCapabilities", "window"}:       wantOpt, // regtest failures
47582-	{"ClientCapabilities", "workspace"}:    wantOpt, // regtest failures
47583-	{"CodeAction", "kind"}:                 wantOpt, // A.B.C.D
47584-
47585-	{"CodeActionClientCapabilities", "codeActionLiteralSupport"}: wantOpt, // regtest failures
47586-
47587-	{"CompletionClientCapabilities", "completionItem"}: wantOpt, // A.B.C.D
47588-	{"CompletionClientCapabilities", "insertTextMode"}: wantOpt, // A.B.C.D
47589-	{"CompletionItem", "kind"}:                         wantOpt, // need temporary variables
47590-	{"CompletionParams", "context"}:                    wantOpt, // needs nil checks
47591-
47592-	{"Diagnostic", "severity"}:            wantOpt,     // nil checks or more careful thought
47593-	{"DidSaveTextDocumentParams", "text"}: wantOptStar, // capabilities_test.go:112 logic
47594-	{"DocumentHighlight", "kind"}:         wantOpt,     // need temporary variables
47595-	{"Hover", "range"}:                    wantOpt,     // complex expressions
47596-	{"InlayHint", "kind"}:                 wantOpt,     // temporary variables
47597-
47598-	{"Lit_CompletionClientCapabilities_completionItem", "tagSupport"}:     nothing, // A.B.C.
47599-	{"Lit_SemanticTokensClientCapabilities_requests", "full"}:             nothing, // A.B.C.D
47600-	{"Lit_SemanticTokensClientCapabilities_requests", "range"}:            nothing, // A.B.C.D
47601-	{"Lit_SemanticTokensClientCapabilities_requests_full_Item1", "delta"}: nothing, // A.B.C.D
47602-	{"Lit_SemanticTokensOptions_full_Item1", "delta"}:                     nothing, // A.B.C.
47603-
47604-	{"Lit_TextDocumentContentChangeEvent_Item0", "range"}: wantStar, // == nil test
47605-
47606-	{"TextDocumentClientCapabilities", "codeAction"}:          wantOpt, // A.B.C.D
47607-	{"TextDocumentClientCapabilities", "completion"}:          wantOpt, // A.B.C.D
47608-	{"TextDocumentClientCapabilities", "documentSymbol"}:      wantOpt, // A.B.C.D
47609-	{"TextDocumentClientCapabilities", "publishDiagnostics"}:  wantOpt, //A.B.C.D
47610-	{"TextDocumentClientCapabilities", "semanticTokens"}:      wantOpt, // A.B.C.D
47611-	{"TextDocumentSyncOptions", "change"}:                     wantOpt, // &constant
47612-	{"WorkDoneProgressParams", "workDoneToken"}:               wantOpt, // regtest
47613-	{"WorkspaceClientCapabilities", "didChangeConfiguration"}: wantOpt, // A.B.C.D
47614-	{"WorkspaceClientCapabilities", "didChangeWatchedFiles"}:  wantOpt, // A.B.C.D
47615-}
47616-
47617-// keep track of which entries in goplsStar are used
47618-var usedGoplsStar = make(map[prop]bool)
47619-
47620-// For gopls compatibility, use a different, typically more restrictive, type for some fields.
47621-var renameProp = map[prop]string{
47622-	{"CancelParams", "id"}:         "interface{}",
47623-	{"Command", "arguments"}:       "[]json.RawMessage",
47624-	{"CompletionItem", "textEdit"}: "TextEdit",
47625-	{"Diagnostic", "code"}:         "interface{}",
47626-
47627-	{"DocumentDiagnosticReportPartialResult", "relatedDocuments"}: "map[DocumentURI]interface{}",
47628-
47629-	{"ExecuteCommandParams", "arguments"}: "[]json.RawMessage",
47630-	{"FoldingRange", "kind"}:              "string",
47631-	{"Hover", "contents"}:                 "MarkupContent",
47632-	{"InlayHint", "label"}:                "[]InlayHintLabelPart",
47633-
47634-	{"RelatedFullDocumentDiagnosticReport", "relatedDocuments"}:      "map[DocumentURI]interface{}",
47635-	{"RelatedUnchangedDocumentDiagnosticReport", "relatedDocuments"}: "map[DocumentURI]interface{}",
47636-
47637-	// PJW: this one is tricky.
47638-	{"ServerCapabilities", "codeActionProvider"}: "interface{}",
47639-
47640-	{"ServerCapabilities", "inlayHintProvider"}: "interface{}",
47641-	// slightly tricky
47642-	{"ServerCapabilities", "renameProvider"}: "interface{}",
47643-	// slightly tricky
47644-	{"ServerCapabilities", "semanticTokensProvider"}: "interface{}",
47645-	// slightly tricky
47646-	{"ServerCapabilities", "textDocumentSync"}: "interface{}",
47647-	{"TextDocumentEdit", "edits"}:              "[]TextEdit",
47648-	{"TextDocumentSyncOptions", "save"}:        "SaveOptions",
47649-	{"WorkspaceEdit", "documentChanges"}:       "[]DocumentChanges",
47650-}
47651-
47652-// which entries of renameProp were used
47653-var usedRenameProp = make(map[prop]bool)
47654-
47655-type adjust struct {
47656-	prefix, suffix string
47657-}
47658-
47659-// disambiguate specifies prefixes or suffixes to add to all values of
47660-// some enum types to avoid name conflicts
47661-var disambiguate = map[string]adjust{
47662-	"CodeActionTriggerKind":        {"CodeAction", ""},
47663-	"CompletionItemKind":           {"", "Completion"},
47664-	"CompletionItemTag":            {"Compl", ""},
47665-	"DiagnosticSeverity":           {"Severity", ""},
47666-	"DocumentDiagnosticReportKind": {"Diagnostic", ""},
47667-	"FileOperationPatternKind":     {"", "Pattern"},
47668-	"InsertTextFormat":             {"", "TextFormat"},
47669-	"SemanticTokenModifiers":       {"Mod", ""},
47670-	"SemanticTokenTypes":           {"", "Type"},
47671-	"SignatureHelpTriggerKind":     {"Sig", ""},
47672-	"SymbolTag":                    {"", "Symbol"},
47673-	"WatchKind":                    {"Watch", ""},
47674-}
47675-
47676-// which entries of disambiguate got used
47677-var usedDisambiguate = make(map[string]bool)
47678-
47679-// for gopls compatibility, replace generated type names with existing ones
47680-var goplsType = map[string]string{
47681-	"And_RegOpt_textDocument_colorPresentation": "WorkDoneProgressOptionsAndTextDocumentRegistrationOptions",
47682-	"ConfigurationParams":                       "ParamConfiguration",
47683-	"DocumentDiagnosticParams":                  "string",
47684-	"DocumentDiagnosticReport":                  "string",
47685-	"DocumentUri":                               "DocumentURI",
47686-	"InitializeParams":                          "ParamInitialize",
47687-	"LSPAny":                                    "interface{}",
47688-
47689-	"Lit_CodeActionClientCapabilities_codeActionLiteralSupport":                "PCodeActionLiteralSupportPCodeAction",
47690-	"Lit_CodeActionClientCapabilities_codeActionLiteralSupport_codeActionKind": "FCodeActionKindPCodeActionLiteralSupport",
47691-
47692-	"Lit_CodeActionClientCapabilities_resolveSupport":     "PResolveSupportPCodeAction",
47693-	"Lit_CodeAction_disabled":                             "PDisabledMsg_textDocument_codeAction",
47694-	"Lit_CompletionClientCapabilities_completionItem":     "PCompletionItemPCompletion",
47695-	"Lit_CompletionClientCapabilities_completionItemKind": "PCompletionItemKindPCompletion",
47696-
47697-	"Lit_CompletionClientCapabilities_completionItem_insertTextModeSupport": "FInsertTextModeSupportPCompletionItem",
47698-
47699-	"Lit_CompletionClientCapabilities_completionItem_resolveSupport": "FResolveSupportPCompletionItem",
47700-	"Lit_CompletionClientCapabilities_completionItem_tagSupport":     "FTagSupportPCompletionItem",
47701-
47702-	"Lit_CompletionClientCapabilities_completionList":     "PCompletionListPCompletion",
47703-	"Lit_CompletionList_itemDefaults":                     "PItemDefaultsMsg_textDocument_completion",
47704-	"Lit_CompletionList_itemDefaults_editRange_Item1":     "FEditRangePItemDefaults",
47705-	"Lit_CompletionOptions_completionItem":                "PCompletionItemPCompletionProvider",
47706-	"Lit_DocumentSymbolClientCapabilities_symbolKind":     "PSymbolKindPDocumentSymbol",
47707-	"Lit_DocumentSymbolClientCapabilities_tagSupport":     "PTagSupportPDocumentSymbol",
47708-	"Lit_FoldingRangeClientCapabilities_foldingRange":     "PFoldingRangePFoldingRange",
47709-	"Lit_FoldingRangeClientCapabilities_foldingRangeKind": "PFoldingRangeKindPFoldingRange",
47710-	"Lit_GeneralClientCapabilities_staleRequestSupport":   "PStaleRequestSupportPGeneral",
47711-	"Lit_InitializeResult_serverInfo":                     "PServerInfoMsg_initialize",
47712-	"Lit_InlayHintClientCapabilities_resolveSupport":      "PResolveSupportPInlayHint",
47713-	"Lit_MarkedString_Item1":                              "Msg_MarkedString",
47714-	"Lit_NotebookDocumentChangeEvent_cells":               "PCellsPChange",
47715-	"Lit_NotebookDocumentChangeEvent_cells_structure":     "FStructurePCells",
47716-	"Lit_NotebookDocumentFilter_Item0":                    "Msg_NotebookDocumentFilter",
47717-
47718-	"Lit_NotebookDocumentSyncOptions_notebookSelector_Elem_Item0": "PNotebookSelectorPNotebookDocumentSync",
47719-
47720-	"Lit_PrepareRenameResult_Item1": "Msg_PrepareRename2Gn",
47721-
47722-	"Lit_PublishDiagnosticsClientCapabilities_tagSupport":       "PTagSupportPPublishDiagnostics",
47723-	"Lit_SemanticTokensClientCapabilities_requests":             "PRequestsPSemanticTokens",
47724-	"Lit_SemanticTokensClientCapabilities_requests_full_Item1":  "FFullPRequests",
47725-	"Lit_SemanticTokensClientCapabilities_requests_range_Item1": "FRangePRequests",
47726-
47727-	"Lit_SemanticTokensOptions_full_Item1":  "PFullESemanticTokensOptions",
47728-	"Lit_SemanticTokensOptions_range_Item1": "PRangeESemanticTokensOptions",
47729-	"Lit_ServerCapabilities_workspace":      "Workspace6Gn",
47730-
47731-	"Lit_ShowMessageRequestClientCapabilities_messageActionItem": "PMessageActionItemPShowMessage",
47732-	"Lit_SignatureHelpClientCapabilities_signatureInformation":   "PSignatureInformationPSignatureHelp",
47733-
47734-	"Lit_SignatureHelpClientCapabilities_signatureInformation_parameterInformation": "FParameterInformationPSignatureInformation",
47735-
47736-	"Lit_TextDocumentContentChangeEvent_Item0":                    "Msg_TextDocumentContentChangeEvent",
47737-	"Lit_TextDocumentFilter_Item0":                                "Msg_TextDocumentFilter",
47738-	"Lit_TextDocumentFilter_Item1":                                "Msg_TextDocumentFilter",
47739-	"Lit_WorkspaceEditClientCapabilities_changeAnnotationSupport": "PChangeAnnotationSupportPWorkspaceEdit",
47740-	"Lit_WorkspaceSymbolClientCapabilities_resolveSupport":        "PResolveSupportPSymbol",
47741-	"Lit_WorkspaceSymbolClientCapabilities_symbolKind":            "PSymbolKindPSymbol",
47742-	"Lit_WorkspaceSymbolClientCapabilities_tagSupport":            "PTagSupportPSymbol",
47743-	"Lit_WorkspaceSymbol_location_Item1":                          "PLocationMsg_workspace_symbol",
47744-	"Lit__InitializeParams_clientInfo":                            "Msg_XInitializeParams_clientInfo",
47745-	"Or_CompletionList_itemDefaults_editRange":                    "OrFEditRangePItemDefaults",
47746-	"Or_Declaration": "[]Location",
47747-	"Or_DidChangeConfigurationRegistrationOptions_section": "OrPSection_workspace_didChangeConfiguration",
47748-	"Or_GlobPattern":                "string",
47749-	"Or_InlayHintLabelPart_tooltip": "OrPTooltipPLabel",
47750-	"Or_InlayHint_tooltip":          "OrPTooltip_textDocument_inlayHint",
47751-	"Or_LSPAny":                     "interface{}",
47752-	"Or_NotebookDocumentFilter":     "Msg_NotebookDocumentFilter",
47753-	"Or_NotebookDocumentSyncOptions_notebookSelector_Elem": "PNotebookSelectorPNotebookDocumentSync",
47754-
47755-	"Or_NotebookDocumentSyncOptions_notebookSelector_Elem_Item0_notebook": "OrFNotebookPNotebookSelector",
47756-
47757-	"Or_ParameterInformation_documentation":                     "string",
47758-	"Or_ParameterInformation_label":                             "string",
47759-	"Or_PrepareRenameResult":                                    "Msg_PrepareRename2Gn",
47760-	"Or_ProgressToken":                                          "interface{}",
47761-	"Or_Result_textDocument_completion":                         "CompletionList",
47762-	"Or_Result_textDocument_declaration":                        "Or_textDocument_declaration",
47763-	"Or_Result_textDocument_definition":                         "[]Location",
47764-	"Or_Result_textDocument_documentSymbol":                     "[]interface{}",
47765-	"Or_Result_textDocument_implementation":                     "[]Location",
47766-	"Or_Result_textDocument_semanticTokens_full_delta":          "interface{}",
47767-	"Or_Result_textDocument_typeDefinition":                     "[]Location",
47768-	"Or_Result_workspace_symbol":                                "[]SymbolInformation",
47769-	"Or_TextDocumentContentChangeEvent":                         "Msg_TextDocumentContentChangeEvent",
47770-	"Or_TextDocumentFilter":                                     "Msg_TextDocumentFilter",
47771-	"Or_WorkspaceFoldersServerCapabilities_changeNotifications": "string",
47772-	"Or_WorkspaceSymbol_location":                               "OrPLocation_workspace_symbol",
47773-	"PrepareRenameResult":                                       "PrepareRename2Gn",
47774-	"Tuple_ParameterInformation_label_Item1":                    "UIntCommaUInt",
47775-	"WorkspaceFoldersServerCapabilities":                        "WorkspaceFolders5Gn",
47776-	"[]LSPAny":                                                  "[]interface{}",
47777-	"[]Or_NotebookDocumentSyncOptions_notebookSelector_Elem":    "[]PNotebookSelectorPNotebookDocumentSync",
47778-	"[]Or_Result_textDocument_codeAction_Item0_Elem":            "[]CodeAction",
47779-	"[]PreviousResultId":                                        "[]PreviousResultID",
47780-	"[]uinteger":                                                "[]uint32",
47781-	"boolean":                                                   "bool",
47782-	"decimal":                                                   "float64",
47783-	"integer":                                                   "int32",
47784-	"map[DocumentUri][]TextEdit":                                "map[DocumentURI][]TextEdit",
47785-	"uinteger":                                                  "uint32",
47786-}
47787-
47788-var usedGoplsType = make(map[string]bool)
47789-
47790-// methodNames is a map from the method to the name of the function that handles it
47791-var methodNames = map[string]string{
47792-	"$/cancelRequest":                        "CancelRequest",
47793-	"$/logTrace":                             "LogTrace",
47794-	"$/progress":                             "Progress",
47795-	"$/setTrace":                             "SetTrace",
47796-	"callHierarchy/incomingCalls":            "IncomingCalls",
47797-	"callHierarchy/outgoingCalls":            "OutgoingCalls",
47798-	"client/registerCapability":              "RegisterCapability",
47799-	"client/unregisterCapability":            "UnregisterCapability",
47800-	"codeAction/resolve":                     "ResolveCodeAction",
47801-	"codeLens/resolve":                       "ResolveCodeLens",
47802-	"completionItem/resolve":                 "ResolveCompletionItem",
47803-	"documentLink/resolve":                   "ResolveDocumentLink",
47804-	"exit":                                   "Exit",
47805-	"initialize":                             "Initialize",
47806-	"initialized":                            "Initialized",
47807-	"inlayHint/resolve":                      "Resolve",
47808-	"notebookDocument/didChange":             "DidChangeNotebookDocument",
47809-	"notebookDocument/didClose":              "DidCloseNotebookDocument",
47810-	"notebookDocument/didOpen":               "DidOpenNotebookDocument",
47811-	"notebookDocument/didSave":               "DidSaveNotebookDocument",
47812-	"shutdown":                               "Shutdown",
47813-	"telemetry/event":                        "Event",
47814-	"textDocument/codeAction":                "CodeAction",
47815-	"textDocument/codeLens":                  "CodeLens",
47816-	"textDocument/colorPresentation":         "ColorPresentation",
47817-	"textDocument/completion":                "Completion",
47818-	"textDocument/declaration":               "Declaration",
47819-	"textDocument/definition":                "Definition",
47820-	"textDocument/diagnostic":                "Diagnostic",
47821-	"textDocument/didChange":                 "DidChange",
47822-	"textDocument/didClose":                  "DidClose",
47823-	"textDocument/didOpen":                   "DidOpen",
47824-	"textDocument/didSave":                   "DidSave",
47825-	"textDocument/documentColor":             "DocumentColor",
47826-	"textDocument/documentHighlight":         "DocumentHighlight",
47827-	"textDocument/documentLink":              "DocumentLink",
47828-	"textDocument/documentSymbol":            "DocumentSymbol",
47829-	"textDocument/foldingRange":              "FoldingRange",
47830-	"textDocument/formatting":                "Formatting",
47831-	"textDocument/hover":                     "Hover",
47832-	"textDocument/implementation":            "Implementation",
47833-	"textDocument/inlayHint":                 "InlayHint",
47834-	"textDocument/inlineValue":               "InlineValue",
47835-	"textDocument/linkedEditingRange":        "LinkedEditingRange",
47836-	"textDocument/moniker":                   "Moniker",
47837-	"textDocument/onTypeFormatting":          "OnTypeFormatting",
47838-	"textDocument/prepareCallHierarchy":      "PrepareCallHierarchy",
47839-	"textDocument/prepareRename":             "PrepareRename",
47840-	"textDocument/prepareTypeHierarchy":      "PrepareTypeHierarchy",
47841-	"textDocument/publishDiagnostics":        "PublishDiagnostics",
47842-	"textDocument/rangeFormatting":           "RangeFormatting",
47843-	"textDocument/references":                "References",
47844-	"textDocument/rename":                    "Rename",
47845-	"textDocument/selectionRange":            "SelectionRange",
47846-	"textDocument/semanticTokens/full":       "SemanticTokensFull",
47847-	"textDocument/semanticTokens/full/delta": "SemanticTokensFullDelta",
47848-	"textDocument/semanticTokens/range":      "SemanticTokensRange",
47849-	"textDocument/signatureHelp":             "SignatureHelp",
47850-	"textDocument/typeDefinition":            "TypeDefinition",
47851-	"textDocument/willSave":                  "WillSave",
47852-	"textDocument/willSaveWaitUntil":         "WillSaveWaitUntil",
47853-	"typeHierarchy/subtypes":                 "Subtypes",
47854-	"typeHierarchy/supertypes":               "Supertypes",
47855-	"window/logMessage":                      "LogMessage",
47856-	"window/showDocument":                    "ShowDocument",
47857-	"window/showMessage":                     "ShowMessage",
47858-	"window/showMessageRequest":              "ShowMessageRequest",
47859-	"window/workDoneProgress/cancel":         "WorkDoneProgressCancel",
47860-	"window/workDoneProgress/create":         "WorkDoneProgressCreate",
47861-	"workspace/applyEdit":                    "ApplyEdit",
47862-	"workspace/codeLens/refresh":             "CodeLensRefresh",
47863-	"workspace/configuration":                "Configuration",
47864-	"workspace/diagnostic":                   "DiagnosticWorkspace",
47865-	"workspace/diagnostic/refresh":           "DiagnosticRefresh",
47866-	"workspace/didChangeConfiguration":       "DidChangeConfiguration",
47867-	"workspace/didChangeWatchedFiles":        "DidChangeWatchedFiles",
47868-	"workspace/didChangeWorkspaceFolders":    "DidChangeWorkspaceFolders",
47869-	"workspace/didCreateFiles":               "DidCreateFiles",
47870-	"workspace/didDeleteFiles":               "DidDeleteFiles",
47871-	"workspace/didRenameFiles":               "DidRenameFiles",
47872-	"workspace/executeCommand":               "ExecuteCommand",
47873-	"workspace/inlayHint/refresh":            "InlayHintRefresh",
47874-	"workspace/inlineValue/refresh":          "InlineValueRefresh",
47875-	"workspace/semanticTokens/refresh":       "SemanticTokensRefresh",
47876-	"workspace/symbol":                       "Symbol",
47877-	"workspace/willCreateFiles":              "WillCreateFiles",
47878-	"workspace/willDeleteFiles":              "WillDeleteFiles",
47879-	"workspace/willRenameFiles":              "WillRenameFiles",
47880-	"workspace/workspaceFolders":             "WorkspaceFolders",
47881-	"workspaceSymbol/resolve":                "ResolveWorkspaceSymbol",
47882-}
47883diff -urN a/gopls/internal/lsp/protocol/generate/typenames.go b/gopls/internal/lsp/protocol/generate/typenames.go
47884--- a/gopls/internal/lsp/protocol/generate/typenames.go	2000-01-01 00:00:00.000000000 -0000
47885+++ b/gopls/internal/lsp/protocol/generate/typenames.go	1970-01-01 00:00:00.000000000 +0000
47886@@ -1,184 +0,0 @@
47887-// Copyright 2022 The Go Authors. All rights reserved.
47888-// Use of this source code is governed by a BSD-style
47889-// license that can be found in the LICENSE file.
47890-
47891-//go:build go1.19
47892-// +build go1.19
47893-
47894-package main
47895-
47896-import (
47897-	"fmt"
47898-	"log"
47899-	"strings"
47900-)
47901-
47902-var typeNames = make(map[*Type]string)
47903-var genTypes []*newType
47904-
47905-func findTypeNames(model Model) {
47906-	for _, s := range model.Structures {
47907-		for _, e := range s.Extends {
47908-			nameType(e, nil) // all references
47909-		}
47910-		for _, m := range s.Mixins {
47911-			nameType(m, nil) // all references
47912-		}
47913-		for _, p := range s.Properties {
47914-			nameType(p.Type, []string{s.Name, p.Name})
47915-		}
47916-	}
47917-	for _, t := range model.Enumerations {
47918-		nameType(t.Type, []string{t.Name})
47919-	}
47920-	for _, t := range model.TypeAliases {
47921-		nameType(t.Type, []string{t.Name})
47922-	}
47923-	for _, r := range model.Requests {
47924-		nameType(r.Params, []string{"Param", r.Method})
47925-		nameType(r.Result, []string{"Result", r.Method})
47926-		nameType(r.RegistrationOptions, []string{"RegOpt", r.Method})
47927-	}
47928-	for _, n := range model.Notifications {
47929-		nameType(n.Params, []string{"Param", n.Method})
47930-		nameType(n.RegistrationOptions, []string{"RegOpt", n.Method})
47931-	}
47932-}
47933-
47934-// nameType populates typeNames[t] with the computed name of the type.
47935-// path is the list of enclosing constructs in the JSON model.
47936-func nameType(t *Type, path []string) string {
47937-	if t == nil || typeNames[t] != "" {
47938-		return ""
47939-	}
47940-	switch t.Kind {
47941-	case "base":
47942-		typeNames[t] = t.Name
47943-		return t.Name
47944-	case "reference":
47945-		typeNames[t] = t.Name
47946-		return t.Name
47947-	case "array":
47948-		nm := "[]" + nameType(t.Element, append(path, "Elem"))
47949-		typeNames[t] = nm
47950-		return nm
47951-	case "map":
47952-		key := nameType(t.Key, nil) // never a generated type
47953-		value := nameType(t.Value.(*Type), append(path, "Value"))
47954-		nm := "map[" + key + "]" + value
47955-		typeNames[t] = nm
47956-		return nm
47957-	// generated types
47958-	case "and":
47959-		nm := nameFromPath("And", path)
47960-		typeNames[t] = nm
47961-		for _, it := range t.Items {
47962-			nameType(it, append(path, "Item"))
47963-		}
47964-		genTypes = append(genTypes, &newType{
47965-			name:  nm,
47966-			typ:   t,
47967-			kind:  "and",
47968-			items: t.Items,
47969-			line:  t.Line,
47970-		})
47971-		return nm
47972-	case "literal":
47973-		nm := nameFromPath("Lit", path)
47974-		typeNames[t] = nm
47975-		for _, p := range t.Value.(ParseLiteral).Properties {
47976-			nameType(p.Type, append(path, p.Name))
47977-		}
47978-		genTypes = append(genTypes, &newType{
47979-			name:       nm,
47980-			typ:        t,
47981-			kind:       "literal",
47982-			properties: t.Value.(ParseLiteral).Properties,
47983-			line:       t.Line,
47984-		})
47985-		return nm
47986-	case "tuple":
47987-		nm := nameFromPath("Tuple", path)
47988-		typeNames[t] = nm
47989-		for _, it := range t.Items {
47990-			nameType(it, append(path, "Item"))
47991-		}
47992-		genTypes = append(genTypes, &newType{
47993-			name:  nm,
47994-			typ:   t,
47995-			kind:  "tuple",
47996-			items: t.Items,
47997-			line:  t.Line,
47998-		})
47999-		return nm
48000-	case "or":
48001-		nm := nameFromPath("Or", path)
48002-		typeNames[t] = nm
48003-		for i, it := range t.Items {
48004-			// these names depend on the ordering within the "or" type
48005-			nameType(it, append(path, fmt.Sprintf("Item%d", i)))
48006-		}
48007-		// this code handles an "or" of stringLiterals (_InitializeParams.trace)
48008-		names := make(map[string]int)
48009-		msg := ""
48010-		for _, it := range t.Items {
48011-			if line, ok := names[typeNames[it]]; ok {
48012-				// duplicate component names are bad
48013-				msg += fmt.Sprintf("lines %d %d dup, %s for %s\n", line, it.Line, typeNames[it], nm)
48014-			}
48015-			names[typeNames[it]] = t.Line
48016-		}
48017-		// this code handles an "or" of stringLiterals (_InitializeParams.trace)
48018-		if len(names) == 1 {
48019-			var solekey string
48020-			for k := range names {
48021-				solekey = k // the sole name
48022-			}
48023-			if solekey == "string" { // _InitializeParams.trace
48024-				typeNames[t] = "string"
48025-				return "string"
48026-			}
48027-			// otherwise unexpected
48028-			log.Printf("unexpected: single-case 'or' type has non-string key %s: %s", nm, solekey)
48029-			log.Fatal(msg)
48030-		} else if len(names) == 2 {
48031-			// if one of the names is null, just use the other, rather than generating an "or".
48032-			// This removes about 40 types from the generated code. An entry in goplsStar
48033-			// could be added to handle the null case, if necessary.
48034-			newNm := ""
48035-			sawNull := false
48036-			for k := range names {
48037-				if k == "null" {
48038-					sawNull = true
48039-				} else {
48040-					newNm = k
48041-				}
48042-			}
48043-			if sawNull {
48044-				typeNames[t] = newNm
48045-				return newNm
48046-			}
48047-		}
48048-		genTypes = append(genTypes, &newType{
48049-			name:  nm,
48050-			typ:   t,
48051-			kind:  "or",
48052-			items: t.Items,
48053-			line:  t.Line,
48054-		})
48055-		return nm
48056-	case "stringLiteral": // a single type, like 'kind' or 'rename'
48057-		typeNames[t] = "string"
48058-		return "string"
48059-	default:
48060-		log.Fatalf("nameType: %T unexpected, line:%d path:%v", t, t.Line, path)
48061-		panic("unreachable in nameType")
48062-	}
48063-}
48064-
48065-func nameFromPath(prefix string, path []string) string {
48066-	nm := prefix + "_" + strings.Join(path, "_")
48067-	// methods have slashes
48068-	nm = strings.ReplaceAll(nm, "/", "_")
48069-	return nm
48070-}
48071diff -urN a/gopls/internal/lsp/protocol/generate/types.go b/gopls/internal/lsp/protocol/generate/types.go
48072--- a/gopls/internal/lsp/protocol/generate/types.go	2000-01-01 00:00:00.000000000 -0000
48073+++ b/gopls/internal/lsp/protocol/generate/types.go	1970-01-01 00:00:00.000000000 +0000
48074@@ -1,170 +0,0 @@
48075-// Copyright 2022 The Go Authors. All rights reserved.
48076-// Use of this source code is governed by a BSD-style
48077-// license that can be found in the LICENSE file.
48078-
48079-//go:build go1.19
48080-// +build go1.19
48081-
48082-package main
48083-
48084-import (
48085-	"fmt"
48086-	"sort"
48087-)
48088-
48089-// Model contains the parsed version of the spec
48090-type Model struct {
48091-	Version       Metadata        `json:"metaData"`
48092-	Requests      []*Request      `json:"requests"`
48093-	Notifications []*Notification `json:"notifications"`
48094-	Structures    []*Structure    `json:"structures"`
48095-	Enumerations  []*Enumeration  `json:"enumerations"`
48096-	TypeAliases   []*TypeAlias    `json:"typeAliases"`
48097-	Line          int             `json:"line"`
48098-}
48099-
48100-// Metadata is information about the version of the spec
48101-type Metadata struct {
48102-	Version string `json:"version"`
48103-	Line    int    `json:"line"`
48104-}
48105-
48106-// A Request is the parsed version of an LSP request
48107-type Request struct {
48108-	Documentation       string `json:"documentation"`
48109-	ErrorData           *Type  `json:"errorData"`
48110-	Direction           string `json:"messageDirection"`
48111-	Method              string `json:"method"`
48112-	Params              *Type  `json:"params"`
48113-	PartialResult       *Type  `json:"partialResult"`
48114-	Proposed            bool   `json:"proposed"`
48115-	RegistrationMethod  string `json:"registrationMethod"`
48116-	RegistrationOptions *Type  `json:"registrationOptions"`
48117-	Result              *Type  `json:"result"`
48118-	Since               string `json:"since"`
48119-	Line                int    `json:"line"`
48120-}
48121-
48122-// A Notificatin is the parsed version of an LSP notification
48123-type Notification struct {
48124-	Documentation       string `json:"documentation"`
48125-	Direction           string `json:"messageDirection"`
48126-	Method              string `json:"method"`
48127-	Params              *Type  `json:"params"`
48128-	Proposed            bool   `json:"proposed"`
48129-	RegistrationMethod  string `json:"registrationMethod"`
48130-	RegistrationOptions *Type  `json:"registrationOptions"`
48131-	Since               string `json:"since"`
48132-	Line                int    `json:"line"`
48133-}
48134-
48135-// A Structure is the parsed version of an LSP structure from the spec
48136-type Structure struct {
48137-	Documentation string     `json:"documentation"`
48138-	Extends       []*Type    `json:"extends"`
48139-	Mixins        []*Type    `json:"mixins"`
48140-	Name          string     `json:"name"`
48141-	Properties    []NameType `json:"properties"`
48142-	Proposed      bool       `json:"proposed"`
48143-	Since         string     `json:"since"`
48144-	Line          int        `json:"line"`
48145-}
48146-
48147-// An enumeration is the parsed version of an LSP enumeration from the spec
48148-type Enumeration struct {
48149-	Documentation        string      `json:"documentation"`
48150-	Name                 string      `json:"name"`
48151-	Proposed             bool        `json:"proposed"`
48152-	Since                string      `json:"since"`
48153-	SupportsCustomValues bool        `json:"supportsCustomValues"`
48154-	Type                 *Type       `json:"type"`
48155-	Values               []NameValue `json:"values"`
48156-	Line                 int         `json:"line"`
48157-}
48158-
48159-// A TypeAlias is the parsed version of an LSP type alias from the spec
48160-type TypeAlias struct {
48161-	Documentation string `json:"documentation"`
48162-	Deprecated    string `json:"deprecated"`
48163-	Name          string `json:"name"`
48164-	Proposed      bool   `json:"proposed"`
48165-	Since         string `json:"since"`
48166-	Type          *Type  `json:"type"`
48167-	Line          int    `json:"line"`
48168-}
48169-
48170-// A NameValue describes an enumeration constant
48171-type NameValue struct {
48172-	Documentation string `json:"documentation"`
48173-	Name          string `json:"name"`
48174-	Proposed      bool   `json:"proposed"`
48175-	Since         string `json:"since"`
48176-	Value         any    `json:"value"` // number or string
48177-	Line          int    `json:"line"`
48178-}
48179-
48180-// A Type is the parsed version of an LSP type from the spec,
48181-// or a Type the code constructs
48182-type Type struct {
48183-	Kind    string  `json:"kind"`    // -- which kind goes with which field --
48184-	Items   []*Type `json:"items"`   // "and", "or", "tuple"
48185-	Element *Type   `json:"element"` // "array"
48186-	Name    string  `json:"name"`    // "base", "reference"
48187-	Key     *Type   `json:"key"`     // "map"
48188-	Value   any     `json:"value"`   // "map", "stringLiteral", "literal"
48189-	Line    int     `json:"line"`    // JSON source line
48190-}
48191-
48192-// ParsedLiteral is Type.Value when Type.Kind is "literal"
48193-type ParseLiteral struct {
48194-	Properties `json:"properties"`
48195-}
48196-
48197-// A NameType represents the name and type of a structure element
48198-type NameType struct {
48199-	Name          string `json:"name"`
48200-	Type          *Type  `json:"type"`
48201-	Optional      bool   `json:"optional"`
48202-	Documentation string `json:"documentation"`
48203-	Deprecated    string `json:"deprecated"`
48204-	Since         string `json:"since"`
48205-	Proposed      bool   `json:"proposed"`
48206-	Line          int    `json:"line"`
48207-}
48208-
48209-// Properties are the collection of structure fields
48210-type Properties []NameType
48211-
48212-// addLineNumbers adds a "line" field to each object in the JSON.
48213-func addLineNumbers(buf []byte) []byte {
48214-	var ans []byte
48215-	// In the specification .json file, the delimiter '{' is
48216-	// always followed by a newline. There are other {s embedded in strings.
48217-	// json.Token does not return \n, or :, or , so using it would
48218-	// require parsing the json to reconstruct the missing information.
48219-	for linecnt, i := 1, 0; i < len(buf); i++ {
48220-		ans = append(ans, buf[i])
48221-		switch buf[i] {
48222-		case '{':
48223-			if buf[i+1] == '\n' {
48224-				ans = append(ans, fmt.Sprintf(`"line": %d, `, linecnt)...)
48225-				// warning: this would fail if the spec file had
48226-				// `"value": {\n}`, but it does not, as comma is a separator.
48227-			}
48228-		case '\n':
48229-			linecnt++
48230-		}
48231-	}
48232-	return ans
48233-}
48234-
48235-type sortedMap[T any] map[string]T
48236-
48237-func (s sortedMap[T]) keys() []string {
48238-	var keys []string
48239-	for k := range s {
48240-		keys = append(keys, k)
48241-	}
48242-	sort.Strings(keys)
48243-	return keys
48244-}
48245diff -urN a/gopls/internal/lsp/protocol/log.go b/gopls/internal/lsp/protocol/log.go
48246--- a/gopls/internal/lsp/protocol/log.go	2000-01-01 00:00:00.000000000 -0000
48247+++ b/gopls/internal/lsp/protocol/log.go	1970-01-01 00:00:00.000000000 +0000
48248@@ -1,136 +0,0 @@
48249-// Copyright 2019 The Go Authors. All rights reserved.
48250-// Use of this source code is governed by a BSD-style
48251-// license that can be found in the LICENSE file.
48252-
48253-package protocol
48254-
48255-import (
48256-	"context"
48257-	"fmt"
48258-	"io"
48259-	"strings"
48260-	"sync"
48261-	"time"
48262-
48263-	"golang.org/x/tools/internal/jsonrpc2"
48264-)
48265-
48266-type loggingStream struct {
48267-	stream jsonrpc2.Stream
48268-	logMu  sync.Mutex
48269-	log    io.Writer
48270-}
48271-
48272-// LoggingStream returns a stream that does LSP protocol logging too
48273-func LoggingStream(str jsonrpc2.Stream, w io.Writer) jsonrpc2.Stream {
48274-	return &loggingStream{stream: str, log: w}
48275-}
48276-
48277-func (s *loggingStream) Read(ctx context.Context) (jsonrpc2.Message, int64, error) {
48278-	msg, count, err := s.stream.Read(ctx)
48279-	if err == nil {
48280-		s.logCommon(msg, true)
48281-	}
48282-	return msg, count, err
48283-}
48284-
48285-func (s *loggingStream) Write(ctx context.Context, msg jsonrpc2.Message) (int64, error) {
48286-	s.logCommon(msg, false)
48287-	count, err := s.stream.Write(ctx, msg)
48288-	return count, err
48289-}
48290-
48291-func (s *loggingStream) Close() error {
48292-	return s.stream.Close()
48293-}
48294-
48295-type req struct {
48296-	method string
48297-	start  time.Time
48298-}
48299-
48300-type mapped struct {
48301-	mu          sync.Mutex
48302-	clientCalls map[string]req
48303-	serverCalls map[string]req
48304-}
48305-
48306-var maps = &mapped{
48307-	sync.Mutex{},
48308-	make(map[string]req),
48309-	make(map[string]req),
48310-}
48311-
48312-// these 4 methods are each used exactly once, but it seemed
48313-// better to have the encapsulation rather than ad hoc mutex
48314-// code in 4 places
48315-func (m *mapped) client(id string) req {
48316-	m.mu.Lock()
48317-	defer m.mu.Unlock()
48318-	v := m.clientCalls[id]
48319-	delete(m.clientCalls, id)
48320-	return v
48321-}
48322-
48323-func (m *mapped) server(id string) req {
48324-	m.mu.Lock()
48325-	defer m.mu.Unlock()
48326-	v := m.serverCalls[id]
48327-	delete(m.serverCalls, id)
48328-	return v
48329-}
48330-
48331-func (m *mapped) setClient(id string, r req) {
48332-	m.mu.Lock()
48333-	defer m.mu.Unlock()
48334-	m.clientCalls[id] = r
48335-}
48336-
48337-func (m *mapped) setServer(id string, r req) {
48338-	m.mu.Lock()
48339-	defer m.mu.Unlock()
48340-	m.serverCalls[id] = r
48341-}
48342-
48343-const eor = "\r\n\r\n\r\n"
48344-
48345-func (s *loggingStream) logCommon(msg jsonrpc2.Message, isRead bool) {
48346-	s.logMu.Lock()
48347-	defer s.logMu.Unlock()
48348-	direction, pastTense := "Received", "Received"
48349-	get, set := maps.client, maps.setServer
48350-	if isRead {
48351-		direction, pastTense = "Sending", "Sent"
48352-		get, set = maps.server, maps.setClient
48353-	}
48354-	if msg == nil || s.log == nil {
48355-		return
48356-	}
48357-	tm := time.Now()
48358-	tmfmt := tm.Format("15:04:05.000 PM")
48359-
48360-	buf := strings.Builder{}
48361-	fmt.Fprintf(&buf, "[Trace - %s] ", tmfmt) // common beginning
48362-	switch msg := msg.(type) {
48363-	case *jsonrpc2.Call:
48364-		id := fmt.Sprint(msg.ID())
48365-		fmt.Fprintf(&buf, "%s request '%s - (%s)'.\n", direction, msg.Method(), id)
48366-		fmt.Fprintf(&buf, "Params: %s%s", msg.Params(), eor)
48367-		set(id, req{method: msg.Method(), start: tm})
48368-	case *jsonrpc2.Notification:
48369-		fmt.Fprintf(&buf, "%s notification '%s'.\n", direction, msg.Method())
48370-		fmt.Fprintf(&buf, "Params: %s%s", msg.Params(), eor)
48371-	case *jsonrpc2.Response:
48372-		id := fmt.Sprint(msg.ID())
48373-		if err := msg.Err(); err != nil {
48374-			fmt.Fprintf(s.log, "[Error - %s] %s #%s %s%s", pastTense, tmfmt, id, err, eor)
48375-			return
48376-		}
48377-		cc := get(id)
48378-		elapsed := tm.Sub(cc.start)
48379-		fmt.Fprintf(&buf, "%s response '%s - (%s)' in %dms.\n",
48380-			direction, cc.method, id, elapsed/time.Millisecond)
48381-		fmt.Fprintf(&buf, "Result: %s%s", msg.Result(), eor)
48382-	}
48383-	s.log.Write([]byte(buf.String()))
48384-}
48385diff -urN a/gopls/internal/lsp/protocol/mapper.go b/gopls/internal/lsp/protocol/mapper.go
48386--- a/gopls/internal/lsp/protocol/mapper.go	2000-01-01 00:00:00.000000000 -0000
48387+++ b/gopls/internal/lsp/protocol/mapper.go	1970-01-01 00:00:00.000000000 +0000
48388@@ -1,529 +0,0 @@
48389-// Copyright 2023 The Go Authors. All rights reserved.
48390-// Use of this source code is governed by a BSD-style
48391-// license that can be found in the LICENSE file.
48392-
48393-package protocol
48394-
48395-// This file defines Mapper, which wraps a file content buffer
48396-// ([]byte) and provides efficient conversion between every kind of
48397-// position representation.
48398-//
48399-// gopls uses four main representations of position:
48400-//
48401-// 1. byte offsets, e.g. (start, end int), starting from zero.
48402-//
48403-// 2. go/token notation. Use these types when interacting directly
48404-//    with the go/* syntax packages:
48405-//
48406-// 	token.Pos
48407-// 	token.FileSet
48408-// 	token.File
48409-//
48410-//    Because File.Offset and File.Pos panic on invalid inputs,
48411-//    we do not call them directly and instead use the safetoken package
48412-//    for these conversions. This is enforced by a static check.
48413-//
48414-//    Beware also that the methods of token.File have two bugs for which
48415-//    safetoken contains workarounds:
48416-//    - #57490, whereby the parser may create ast.Nodes during error
48417-//      recovery whose computed positions are out of bounds (EOF+1).
48418-//    - #41029, whereby the wrong line number is returned for the EOF position.
48419-//
48420-// 3. the span package.
48421-//
48422-//    span.Point = (line, col8, offset).
48423-//    span.Span = (uri URI, start, end span.Point)
48424-//
48425-//          Line and column are 1-based.
48426-//          Columns are measured in bytes (UTF-8 codes).
48427-//          All fields are optional.
48428-//
48429-//    These types are useful as intermediate conversions of validated
48430-//    ranges (though MappedRange is superior as it is self contained
48431-//    and universally convertible).  Since their fields are optional
48432-//    they are also useful for parsing user-provided positions (e.g. in
48433-//    the CLI) before we have access to file contents.
48434-//
48435-// 4. protocol, the LSP RPC message format.
48436-//
48437-//    protocol.Position = (Line, Character uint32)
48438-//    protocol.Range = (start, end Position)
48439-//    protocol.Location = (URI, protocol.Range)
48440-//
48441-//          Line and Character are 0-based.
48442-//          Characters (columns) are measured in UTF-16 codes.
48443-//
48444-//    protocol.Mapper holds the (URI, Content) of a file, enabling
48445-//    efficient mapping between byte offsets, span ranges, and
48446-//    protocol ranges.
48447-//
48448-//    protocol.MappedRange holds a protocol.Mapper and valid (start,
48449-//    end int) byte offsets, enabling infallible, efficient conversion
48450-//    to any other format.
48451-
48452-import (
48453-	"bytes"
48454-	"fmt"
48455-	"go/ast"
48456-	"go/token"
48457-	"path/filepath"
48458-	"sort"
48459-	"strings"
48460-	"sync"
48461-	"unicode/utf8"
48462-
48463-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
48464-	"golang.org/x/tools/gopls/internal/span"
48465-	"golang.org/x/tools/internal/bug"
48466-)
48467-
48468-// A Mapper wraps the content of a file and provides mapping
48469-// between byte offsets and notations of position such as:
48470-//
48471-//   - (line, col8) pairs, where col8 is a 1-based UTF-8 column number
48472-//     (bytes), as used by the go/token and span packages.
48473-//
48474-//   - (line, col16) pairs, where col16 is a 1-based UTF-16 column
48475-//     number, as used by the LSP protocol.
48476-//
48477-// All conversion methods are named "FromTo", where From and To are the two types.
48478-// For example, the PointPosition method converts from a Point to a Position.
48479-//
48480-// Mapper does not intrinsically depend on go/token-based
48481-// representations.  Use safetoken to map between token.Pos <=> byte
48482-// offsets, or the convenience methods such as PosPosition,
48483-// NodePosition, or NodeRange.
48484-//
48485-// See overview comments at top of this file.
48486-type Mapper struct {
48487-	URI     span.URI
48488-	Content []byte
48489-
48490-	// Line-number information is requested only for a tiny
48491-	// fraction of Mappers, so we compute it lazily.
48492-	// Call initLines() before accessing fields below.
48493-	linesOnce sync.Once
48494-	lineStart []int // byte offset of start of ith line (0-based); last=EOF iff \n-terminated
48495-	nonASCII  bool
48496-
48497-	// TODO(adonovan): adding an extra lineStart entry for EOF
48498-	// might simplify every method that accesses it. Try it out.
48499-}
48500-
48501-// NewMapper creates a new mapper for the given URI and content.
48502-func NewMapper(uri span.URI, content []byte) *Mapper {
48503-	return &Mapper{URI: uri, Content: content}
48504-}
48505-
48506-// initLines populates the lineStart table.
48507-func (m *Mapper) initLines() {
48508-	m.linesOnce.Do(func() {
48509-		nlines := bytes.Count(m.Content, []byte("\n"))
48510-		m.lineStart = make([]int, 1, nlines+1) // initially []int{0}
48511-		for offset, b := range m.Content {
48512-			if b == '\n' {
48513-				m.lineStart = append(m.lineStart, offset+1)
48514-			}
48515-			if b >= utf8.RuneSelf {
48516-				m.nonASCII = true
48517-			}
48518-		}
48519-	})
48520-}
48521-
48522-// -- conversions from span (UTF-8) domain --
48523-
48524-// SpanLocation converts a (UTF-8) span to a protocol (UTF-16) range.
48525-// Precondition: the URIs of SpanLocation and Mapper match.
48526-func (m *Mapper) SpanLocation(s span.Span) (Location, error) {
48527-	rng, err := m.SpanRange(s)
48528-	if err != nil {
48529-		return Location{}, err
48530-	}
48531-	return m.RangeLocation(rng), nil
48532-}
48533-
48534-// SpanRange converts a (UTF-8) span to a protocol (UTF-16) range.
48535-// Precondition: the URIs of Span and Mapper match.
48536-func (m *Mapper) SpanRange(s span.Span) (Range, error) {
48537-	// Assert that we aren't using the wrong mapper.
48538-	// We check only the base name, and case insensitively,
48539-	// because we can't assume clean paths, no symbolic links,
48540-	// case-sensitive directories. The authoritative answer
48541-	// requires querying the file system, and we don't want
48542-	// to do that.
48543-	if !strings.EqualFold(filepath.Base(string(m.URI)), filepath.Base(string(s.URI()))) {
48544-		return Range{}, bug.Errorf("mapper is for file %q instead of %q", m.URI, s.URI())
48545-	}
48546-	start, err := m.PointPosition(s.Start())
48547-	if err != nil {
48548-		return Range{}, fmt.Errorf("start: %w", err)
48549-	}
48550-	end, err := m.PointPosition(s.End())
48551-	if err != nil {
48552-		return Range{}, fmt.Errorf("end: %w", err)
48553-	}
48554-	return Range{Start: start, End: end}, nil
48555-}
48556-
48557-// PointPosition converts a valid span (UTF-8) point to a protocol (UTF-16) position.
48558-func (m *Mapper) PointPosition(p span.Point) (Position, error) {
48559-	if p.HasPosition() {
48560-		line, col8 := p.Line()-1, p.Column()-1 // both 0-based
48561-		m.initLines()
48562-		if line >= len(m.lineStart) {
48563-			return Position{}, fmt.Errorf("line number %d out of range (max %d)", line, len(m.lineStart))
48564-		}
48565-		offset := m.lineStart[line]
48566-		end := offset + col8
48567-
48568-		// Validate column.
48569-		if end > len(m.Content) {
48570-			return Position{}, fmt.Errorf("column is beyond end of file")
48571-		} else if line+1 < len(m.lineStart) && end >= m.lineStart[line+1] {
48572-			return Position{}, fmt.Errorf("column is beyond end of line")
48573-		}
48574-
48575-		char := UTF16Len(m.Content[offset:end])
48576-		return Position{Line: uint32(line), Character: uint32(char)}, nil
48577-	}
48578-	if p.HasOffset() {
48579-		return m.OffsetPosition(p.Offset())
48580-	}
48581-	return Position{}, fmt.Errorf("point has neither offset nor line/column")
48582-}
48583-
48584-// -- conversions from byte offsets --
48585-
48586-// OffsetLocation converts a byte-offset interval to a protocol (UTF-16) location.
48587-func (m *Mapper) OffsetLocation(start, end int) (Location, error) {
48588-	rng, err := m.OffsetRange(start, end)
48589-	if err != nil {
48590-		return Location{}, err
48591-	}
48592-	return m.RangeLocation(rng), nil
48593-}
48594-
48595-// OffsetRange converts a byte-offset interval to a protocol (UTF-16) range.
48596-func (m *Mapper) OffsetRange(start, end int) (Range, error) {
48597-	if start > end {
48598-		return Range{}, fmt.Errorf("start offset (%d) > end (%d)", start, end)
48599-	}
48600-	startPosition, err := m.OffsetPosition(start)
48601-	if err != nil {
48602-		return Range{}, fmt.Errorf("start: %v", err)
48603-	}
48604-	endPosition, err := m.OffsetPosition(end)
48605-	if err != nil {
48606-		return Range{}, fmt.Errorf("end: %v", err)
48607-	}
48608-	return Range{Start: startPosition, End: endPosition}, nil
48609-}
48610-
48611-// OffsetSpan converts a byte-offset interval to a (UTF-8) span.
48612-// The resulting span contains line, column, and offset information.
48613-func (m *Mapper) OffsetSpan(start, end int) (span.Span, error) {
48614-	if start > end {
48615-		return span.Span{}, fmt.Errorf("start offset (%d) > end (%d)", start, end)
48616-	}
48617-	startPoint, err := m.OffsetPoint(start)
48618-	if err != nil {
48619-		return span.Span{}, fmt.Errorf("start: %v", err)
48620-	}
48621-	endPoint, err := m.OffsetPoint(end)
48622-	if err != nil {
48623-		return span.Span{}, fmt.Errorf("end: %v", err)
48624-	}
48625-	return span.New(m.URI, startPoint, endPoint), nil
48626-}
48627-
48628-// OffsetPosition converts a byte offset to a protocol (UTF-16) position.
48629-func (m *Mapper) OffsetPosition(offset int) (Position, error) {
48630-	if !(0 <= offset && offset <= len(m.Content)) {
48631-		return Position{}, fmt.Errorf("invalid offset %d (want 0-%d)", offset, len(m.Content))
48632-	}
48633-	// No error may be returned after this point,
48634-	// even if the offset does not fall at a rune boundary.
48635-	// (See panic in MappedRange.Range reachable.)
48636-
48637-	line, col16 := m.lineCol16(offset)
48638-	return Position{Line: uint32(line), Character: uint32(col16)}, nil
48639-}
48640-
48641-// lineCol16 converts a valid byte offset to line and UTF-16 column numbers, both 0-based.
48642-func (m *Mapper) lineCol16(offset int) (int, int) {
48643-	line, start, cr := m.line(offset)
48644-	var col16 int
48645-	if m.nonASCII {
48646-		col16 = UTF16Len(m.Content[start:offset])
48647-	} else {
48648-		col16 = offset - start
48649-	}
48650-	if cr {
48651-		col16-- // retreat from \r at line end
48652-	}
48653-	return line, col16
48654-}
48655-
48656-// lineCol8 converts a valid byte offset to line and UTF-8 column numbers, both 0-based.
48657-func (m *Mapper) lineCol8(offset int) (int, int) {
48658-	line, start, cr := m.line(offset)
48659-	col8 := offset - start
48660-	if cr {
48661-		col8-- // retreat from \r at line end
48662-	}
48663-	return line, col8
48664-}
48665-
48666-// line returns:
48667-// - the 0-based index of the line that encloses the (valid) byte offset;
48668-// - the start offset of that line; and
48669-// - whether the offset denotes a carriage return (\r) at line end.
48670-func (m *Mapper) line(offset int) (int, int, bool) {
48671-	m.initLines()
48672-	// In effect, binary search returns a 1-based result.
48673-	line := sort.Search(len(m.lineStart), func(i int) bool {
48674-		return offset < m.lineStart[i]
48675-	})
48676-
48677-	// Adjustment for line-endings: \r|\n is the same as |\r\n.
48678-	var eol int
48679-	if line == len(m.lineStart) {
48680-		eol = len(m.Content) // EOF
48681-	} else {
48682-		eol = m.lineStart[line] - 1
48683-	}
48684-	cr := offset == eol && offset > 0 && m.Content[offset-1] == '\r'
48685-
48686-	line-- // 0-based
48687-
48688-	return line, m.lineStart[line], cr
48689-}
48690-
48691-// OffsetPoint converts a byte offset to a span (UTF-8) point.
48692-// The resulting point contains line, column, and offset information.
48693-func (m *Mapper) OffsetPoint(offset int) (span.Point, error) {
48694-	if !(0 <= offset && offset <= len(m.Content)) {
48695-		return span.Point{}, fmt.Errorf("invalid offset %d (want 0-%d)", offset, len(m.Content))
48696-	}
48697-	line, col8 := m.lineCol8(offset)
48698-	return span.NewPoint(line+1, col8+1, offset), nil
48699-}
48700-
48701-// OffsetMappedRange returns a MappedRange for the given byte offsets.
48702-// A MappedRange can be converted to any other form.
48703-func (m *Mapper) OffsetMappedRange(start, end int) (MappedRange, error) {
48704-	if !(0 <= start && start <= end && end <= len(m.Content)) {
48705-		return MappedRange{}, fmt.Errorf("invalid offsets (%d, %d) (file %s has size %d)", start, end, m.URI, len(m.Content))
48706-	}
48707-	return MappedRange{m, start, end}, nil
48708-}
48709-
48710-// -- conversions from protocol (UTF-16) domain --
48711-
48712-// LocationSpan converts a protocol (UTF-16) Location to a (UTF-8) span.
48713-// Precondition: the URIs of Location and Mapper match.
48714-func (m *Mapper) LocationSpan(l Location) (span.Span, error) {
48715-	// TODO(adonovan): check that l.URI matches m.URI.
48716-	return m.RangeSpan(l.Range)
48717-}
48718-
48719-// RangeSpan converts a protocol (UTF-16) range to a (UTF-8) span.
48720-// The resulting span has valid Positions and Offsets.
48721-func (m *Mapper) RangeSpan(r Range) (span.Span, error) {
48722-	start, end, err := m.RangeOffsets(r)
48723-	if err != nil {
48724-		return span.Span{}, err
48725-	}
48726-	return m.OffsetSpan(start, end)
48727-}
48728-
48729-// RangeOffsets converts a protocol (UTF-16) range to start/end byte offsets.
48730-func (m *Mapper) RangeOffsets(r Range) (int, int, error) {
48731-	start, err := m.PositionOffset(r.Start)
48732-	if err != nil {
48733-		return 0, 0, err
48734-	}
48735-	end, err := m.PositionOffset(r.End)
48736-	if err != nil {
48737-		return 0, 0, err
48738-	}
48739-	return start, end, nil
48740-}
48741-
48742-// PositionOffset converts a protocol (UTF-16) position to a byte offset.
48743-func (m *Mapper) PositionOffset(p Position) (int, error) {
48744-	m.initLines()
48745-
48746-	// Validate line number.
48747-	if p.Line > uint32(len(m.lineStart)) {
48748-		return 0, fmt.Errorf("line number %d out of range 0-%d", p.Line, len(m.lineStart))
48749-	} else if p.Line == uint32(len(m.lineStart)) {
48750-		if p.Character == 0 {
48751-			return len(m.Content), nil // EOF
48752-		}
48753-		return 0, fmt.Errorf("column is beyond end of file")
48754-	}
48755-
48756-	offset := m.lineStart[p.Line]
48757-	content := m.Content[offset:] // rest of file from start of enclosing line
48758-
48759-	// Advance bytes up to the required number of UTF-16 codes.
48760-	col8 := 0
48761-	for col16 := 0; col16 < int(p.Character); col16++ {
48762-		r, sz := utf8.DecodeRune(content)
48763-		if sz == 0 {
48764-			return 0, fmt.Errorf("column is beyond end of file")
48765-		}
48766-		if r == '\n' {
48767-			return 0, fmt.Errorf("column is beyond end of line")
48768-		}
48769-		if sz == 1 && r == utf8.RuneError {
48770-			return 0, fmt.Errorf("buffer contains invalid UTF-8 text")
48771-		}
48772-		content = content[sz:]
48773-
48774-		if r >= 0x10000 {
48775-			col16++ // rune was encoded by a pair of surrogate UTF-16 codes
48776-
48777-			if col16 == int(p.Character) {
48778-				break // requested position is in the middle of a rune
48779-			}
48780-		}
48781-		col8 += sz
48782-	}
48783-	return offset + col8, nil
48784-}
48785-
48786-// PositionPoint converts a protocol (UTF-16) position to a span (UTF-8) point.
48787-// The resulting point has a valid Position and Offset.
48788-func (m *Mapper) PositionPoint(p Position) (span.Point, error) {
48789-	offset, err := m.PositionOffset(p)
48790-	if err != nil {
48791-		return span.Point{}, err
48792-	}
48793-	line, col8 := m.lineCol8(offset)
48794-
48795-	return span.NewPoint(line+1, col8+1, offset), nil
48796-}
48797-
48798-// -- go/token domain convenience methods --
48799-
48800-// PosPosition converts a token pos to a protocol (UTF-16) position.
48801-func (m *Mapper) PosPosition(tf *token.File, pos token.Pos) (Position, error) {
48802-	offset, err := safetoken.Offset(tf, pos)
48803-	if err != nil {
48804-		return Position{}, err
48805-	}
48806-	return m.OffsetPosition(offset)
48807-}
48808-
48809-// PosLocation converts a token range to a protocol (UTF-16) location.
48810-func (m *Mapper) PosLocation(tf *token.File, start, end token.Pos) (Location, error) {
48811-	startOffset, endOffset, err := safetoken.Offsets(tf, start, end)
48812-	if err != nil {
48813-		return Location{}, err
48814-	}
48815-	rng, err := m.OffsetRange(startOffset, endOffset)
48816-	if err != nil {
48817-		return Location{}, err
48818-	}
48819-	return m.RangeLocation(rng), nil
48820-}
48821-
48822-// PosRange converts a token range to a protocol (UTF-16) range.
48823-func (m *Mapper) PosRange(tf *token.File, start, end token.Pos) (Range, error) {
48824-	startOffset, endOffset, err := safetoken.Offsets(tf, start, end)
48825-	if err != nil {
48826-		return Range{}, err
48827-	}
48828-	return m.OffsetRange(startOffset, endOffset)
48829-}
48830-
48831-// NodeRange converts a syntax node range to a protocol (UTF-16) range.
48832-func (m *Mapper) NodeRange(tf *token.File, node ast.Node) (Range, error) {
48833-	return m.PosRange(tf, node.Pos(), node.End())
48834-}
48835-
48836-// RangeLocation pairs a protocol Range with its URI, in a Location.
48837-func (m *Mapper) RangeLocation(rng Range) Location {
48838-	return Location{URI: URIFromSpanURI(m.URI), Range: rng}
48839-}
48840-
48841-// PosMappedRange returns a MappedRange for the given token.Pos range.
48842-func (m *Mapper) PosMappedRange(tf *token.File, start, end token.Pos) (MappedRange, error) {
48843-	startOffset, endOffset, err := safetoken.Offsets(tf, start, end)
48844-	if err != nil {
48845-		return MappedRange{}, nil
48846-	}
48847-	return m.OffsetMappedRange(startOffset, endOffset)
48848-}
48849-
48850-// NodeMappedRange returns a MappedRange for the given node range.
48851-func (m *Mapper) NodeMappedRange(tf *token.File, node ast.Node) (MappedRange, error) {
48852-	return m.PosMappedRange(tf, node.Pos(), node.End())
48853-}
48854-
48855-// -- MappedRange --
48856-
48857-// A MappedRange represents a valid byte-offset range of a file.
48858-// Through its Mapper it can be converted into other forms such
48859-// as protocol.Range or span.Span.
48860-//
48861-// Construct one by calling Mapper.OffsetMappedRange with start/end offsets.
48862-// From the go/token domain, call safetoken.Offsets first,
48863-// or use a helper such as ParsedGoFile.MappedPosRange.
48864-//
48865-// Two MappedRanges produced the same Mapper are equal if and only if they
48866-// denote the same range.  Two MappedRanges produced by different Mappers
48867-// are unequal even when they represent the same range of the same file.
48868-type MappedRange struct {
48869-	Mapper     *Mapper
48870-	start, end int // valid byte offsets:  0 <= start <= end <= len(Mapper.Content)
48871-}
48872-
48873-// Offsets returns the (start, end) byte offsets of this range.
48874-func (mr MappedRange) Offsets() (start, end int) { return mr.start, mr.end }
48875-
48876-// -- convenience functions --
48877-
48878-// URI returns the URI of the range's file.
48879-func (mr MappedRange) URI() span.URI {
48880-	return mr.Mapper.URI
48881-}
48882-
48883-// Range returns the range in protocol (UTF-16) form.
48884-func (mr MappedRange) Range() Range {
48885-	rng, err := mr.Mapper.OffsetRange(mr.start, mr.end)
48886-	if err != nil {
48887-		panic(err) // can't happen
48888-	}
48889-	return rng
48890-}
48891-
48892-// Location returns the range in protocol location (UTF-16) form.
48893-func (mr MappedRange) Location() Location {
48894-	return mr.Mapper.RangeLocation(mr.Range())
48895-}
48896-
48897-// Span returns the range in span (UTF-8) form.
48898-func (mr MappedRange) Span() span.Span {
48899-	spn, err := mr.Mapper.OffsetSpan(mr.start, mr.end)
48900-	if err != nil {
48901-		panic(err) // can't happen
48902-	}
48903-	return spn
48904-}
48905-
48906-// String formats the range in span (UTF-8) notation.
48907-func (mr MappedRange) String() string {
48908-	return fmt.Sprint(mr.Span())
48909-}
48910-
48911-// LocationTextDocumentPositionParams converts its argument to its result.
48912-func LocationTextDocumentPositionParams(loc Location) TextDocumentPositionParams {
48913-	return TextDocumentPositionParams{
48914-		TextDocument: TextDocumentIdentifier{URI: loc.URI},
48915-		Position:     loc.Range.Start,
48916-	}
48917-}
48918diff -urN a/gopls/internal/lsp/protocol/mapper_test.go b/gopls/internal/lsp/protocol/mapper_test.go
48919--- a/gopls/internal/lsp/protocol/mapper_test.go	2000-01-01 00:00:00.000000000 -0000
48920+++ b/gopls/internal/lsp/protocol/mapper_test.go	1970-01-01 00:00:00.000000000 +0000
48921@@ -1,441 +0,0 @@
48922-// Copyright 2023 The Go Authors. All rights reserved.
48923-// Use of this source code is governed by a BSD-style
48924-// license that can be found in the LICENSE file.
48925-
48926-package protocol_test
48927-
48928-import (
48929-	"fmt"
48930-	"strings"
48931-	"testing"
48932-
48933-	"golang.org/x/tools/gopls/internal/lsp/protocol"
48934-	"golang.org/x/tools/gopls/internal/span"
48935-)
48936-
48937-// This file tests Mapper's logic for converting between
48938-// span.Point and UTF-16 columns. (The strange form attests to an
48939-// earlier abstraction.)
48940-
48941-// �� is U+10400 = [F0 90 90 80] in UTF-8, [D801 DC00] in UTF-16.
48942-var funnyString = []byte("��23\n��45")
48943-
48944-var toUTF16Tests = []struct {
48945-	scenario    string
48946-	input       []byte
48947-	line        int    // 1-indexed count
48948-	col         int    // 1-indexed byte position in line
48949-	offset      int    // 0-indexed byte offset into input
48950-	resUTF16col int    // 1-indexed UTF-16 col number
48951-	pre         string // everything before the cursor on the line
48952-	post        string // everything from the cursor onwards
48953-	err         string // expected error string in call to ToUTF16Column
48954-	issue       *bool
48955-}{
48956-	{
48957-		scenario: "cursor missing content",
48958-		input:    nil,
48959-		offset:   -1,
48960-		err:      "point has neither offset nor line/column",
48961-	},
48962-	{
48963-		scenario: "cursor missing position",
48964-		input:    funnyString,
48965-		line:     -1,
48966-		col:      -1,
48967-		offset:   -1,
48968-		err:      "point has neither offset nor line/column",
48969-	},
48970-	{
48971-		scenario:    "zero length input; cursor at first col, first line",
48972-		input:       []byte(""),
48973-		line:        1,
48974-		col:         1,
48975-		offset:      0,
48976-		resUTF16col: 1,
48977-	},
48978-	{
48979-		scenario:    "cursor before funny character; first line",
48980-		input:       funnyString,
48981-		line:        1,
48982-		col:         1,
48983-		offset:      0,
48984-		resUTF16col: 1,
48985-		pre:         "",
48986-		post:        "��23",
48987-	},
48988-	{
48989-		scenario:    "cursor after funny character; first line",
48990-		input:       funnyString,
48991-		line:        1,
48992-		col:         5, // 4 + 1 (1-indexed)
48993-		offset:      4, // (unused since we have line+col)
48994-		resUTF16col: 3, // 2 + 1 (1-indexed)
48995-		pre:         "��",
48996-		post:        "23",
48997-	},
48998-	{
48999-		scenario:    "cursor after last character on first line",
49000-		input:       funnyString,
49001-		line:        1,
49002-		col:         7, // 4 + 1 + 1 + 1 (1-indexed)
49003-		offset:      6, // 4 + 1 + 1 (unused since we have line+col)
49004-		resUTF16col: 5, // 2 + 1 + 1 + 1 (1-indexed)
49005-		pre:         "��23",
49006-		post:        "",
49007-	},
49008-	{
49009-		scenario:    "cursor before funny character; second line",
49010-		input:       funnyString,
49011-		line:        2,
49012-		col:         1,
49013-		offset:      7, // length of first line (unused since we have line+col)
49014-		resUTF16col: 1,
49015-		pre:         "",
49016-		post:        "��45",
49017-	},
49018-	{
49019-		scenario:    "cursor after funny character; second line",
49020-		input:       funnyString,
49021-		line:        1,
49022-		col:         5,  // 4 + 1 (1-indexed)
49023-		offset:      11, // 7 (length of first line) + 4 (unused since we have line+col)
49024-		resUTF16col: 3,  // 2 + 1 (1-indexed)
49025-		pre:         "��",
49026-		post:        "45",
49027-	},
49028-	{
49029-		scenario:    "cursor after last character on second line",
49030-		input:       funnyString,
49031-		line:        2,
49032-		col:         7,  // 4 + 1 + 1 + 1 (1-indexed)
49033-		offset:      13, // 7 (length of first line) + 4 + 1 + 1 (unused since we have line+col)
49034-		resUTF16col: 5,  // 2 + 1 + 1 + 1 (1-indexed)
49035-		pre:         "��45",
49036-		post:        "",
49037-	},
49038-	{
49039-		scenario: "cursor beyond end of file",
49040-		input:    funnyString,
49041-		line:     2,
49042-		col:      8,  // 4 + 1 + 1 + 1 + 1 (1-indexed)
49043-		offset:   14, // 4 + 1 + 1 + 1 (unused since we have line+col)
49044-		err:      "column is beyond end of file",
49045-	},
49046-}
49047-
49048-var fromUTF16Tests = []struct {
49049-	scenario  string
49050-	input     []byte
49051-	line      int    // 1-indexed line number (isn't actually used)
49052-	utf16col  int    // 1-indexed UTF-16 col number
49053-	resCol    int    // 1-indexed byte position in line
49054-	resOffset int    // 0-indexed byte offset into input
49055-	pre       string // everything before the cursor on the line
49056-	post      string // everything from the cursor onwards
49057-	err       string // expected error string in call to ToUTF16Column
49058-}{
49059-	{
49060-		scenario:  "zero length input; cursor at first col, first line",
49061-		input:     []byte(""),
49062-		line:      1,
49063-		utf16col:  1,
49064-		resCol:    1,
49065-		resOffset: 0,
49066-		pre:       "",
49067-		post:      "",
49068-	},
49069-	{
49070-		scenario:  "cursor before funny character",
49071-		input:     funnyString,
49072-		line:      1,
49073-		utf16col:  1,
49074-		resCol:    1,
49075-		resOffset: 0,
49076-		pre:       "",
49077-		post:      "��23",
49078-	},
49079-	{
49080-		scenario:  "cursor after funny character",
49081-		input:     funnyString,
49082-		line:      1,
49083-		utf16col:  3,
49084-		resCol:    5,
49085-		resOffset: 4,
49086-		pre:       "��",
49087-		post:      "23",
49088-	},
49089-	{
49090-		scenario:  "cursor after last character on line",
49091-		input:     funnyString,
49092-		line:      1,
49093-		utf16col:  5,
49094-		resCol:    7,
49095-		resOffset: 6,
49096-		pre:       "��23",
49097-		post:      "",
49098-	},
49099-	{
49100-		scenario:  "cursor beyond last character on line",
49101-		input:     funnyString,
49102-		line:      1,
49103-		utf16col:  6,
49104-		resCol:    7,
49105-		resOffset: 6,
49106-		pre:       "��23",
49107-		post:      "",
49108-		err:       "column is beyond end of line",
49109-	},
49110-	{
49111-		scenario:  "cursor before funny character; second line",
49112-		input:     funnyString,
49113-		line:      2,
49114-		utf16col:  1,
49115-		resCol:    1,
49116-		resOffset: 7,
49117-		pre:       "",
49118-		post:      "��45",
49119-	},
49120-	{
49121-		scenario:  "cursor after funny character; second line",
49122-		input:     funnyString,
49123-		line:      2,
49124-		utf16col:  3,  // 2 + 1 (1-indexed)
49125-		resCol:    5,  // 4 + 1 (1-indexed)
49126-		resOffset: 11, // 7 (length of first line) + 4
49127-		pre:       "��",
49128-		post:      "45",
49129-	},
49130-	{
49131-		scenario:  "cursor after last character on second line",
49132-		input:     funnyString,
49133-		line:      2,
49134-		utf16col:  5,  // 2 + 1 + 1 + 1 (1-indexed)
49135-		resCol:    7,  // 4 + 1 + 1 + 1 (1-indexed)
49136-		resOffset: 13, // 7 (length of first line) + 4 + 1 + 1
49137-		pre:       "��45",
49138-		post:      "",
49139-	},
49140-	{
49141-		scenario:  "cursor beyond end of file",
49142-		input:     funnyString,
49143-		line:      2,
49144-		utf16col:  6,  // 2 + 1 + 1 + 1 + 1(1-indexed)
49145-		resCol:    8,  // 4 + 1 + 1 + 1 + 1 (1-indexed)
49146-		resOffset: 14, // 7 (length of first line) + 4 + 1 + 1 + 1
49147-		err:       "column is beyond end of file",
49148-	},
49149-}
49150-
49151-func TestToUTF16(t *testing.T) {
49152-	for _, e := range toUTF16Tests {
49153-		t.Run(e.scenario, func(t *testing.T) {
49154-			if e.issue != nil && !*e.issue {
49155-				t.Skip("expected to fail")
49156-			}
49157-			p := span.NewPoint(e.line, e.col, e.offset)
49158-			m := protocol.NewMapper("", e.input)
49159-			pos, err := m.PointPosition(p)
49160-			if err != nil {
49161-				if err.Error() != e.err {
49162-					t.Fatalf("expected error %v; got %v", e.err, err)
49163-				}
49164-				return
49165-			}
49166-			if e.err != "" {
49167-				t.Fatalf("unexpected success; wanted %v", e.err)
49168-			}
49169-			got := int(pos.Character) + 1
49170-			if got != e.resUTF16col {
49171-				t.Fatalf("expected result %v; got %v", e.resUTF16col, got)
49172-			}
49173-			pre, post := getPrePost(e.input, p.Offset())
49174-			if string(pre) != e.pre {
49175-				t.Fatalf("expected #%d pre %q; got %q", p.Offset(), e.pre, pre)
49176-			}
49177-			if string(post) != e.post {
49178-				t.Fatalf("expected #%d, post %q; got %q", p.Offset(), e.post, post)
49179-			}
49180-		})
49181-	}
49182-}
49183-
49184-func TestFromUTF16(t *testing.T) {
49185-	for _, e := range fromUTF16Tests {
49186-		t.Run(e.scenario, func(t *testing.T) {
49187-			m := protocol.NewMapper("", []byte(e.input))
49188-			p, err := m.PositionPoint(protocol.Position{
49189-				Line:      uint32(e.line - 1),
49190-				Character: uint32(e.utf16col - 1),
49191-			})
49192-			if err != nil {
49193-				if err.Error() != e.err {
49194-					t.Fatalf("expected error %v; got %v", e.err, err)
49195-				}
49196-				return
49197-			}
49198-			if e.err != "" {
49199-				t.Fatalf("unexpected success; wanted %v", e.err)
49200-			}
49201-			if p.Column() != e.resCol {
49202-				t.Fatalf("expected resulting col %v; got %v", e.resCol, p.Column())
49203-			}
49204-			if p.Offset() != e.resOffset {
49205-				t.Fatalf("expected resulting offset %v; got %v", e.resOffset, p.Offset())
49206-			}
49207-			pre, post := getPrePost(e.input, p.Offset())
49208-			if string(pre) != e.pre {
49209-				t.Fatalf("expected #%d pre %q; got %q", p.Offset(), e.pre, pre)
49210-			}
49211-			if string(post) != e.post {
49212-				t.Fatalf("expected #%d post %q; got %q", p.Offset(), e.post, post)
49213-			}
49214-		})
49215-	}
49216-}
49217-
49218-func getPrePost(content []byte, offset int) (string, string) {
49219-	pre, post := string(content)[:offset], string(content)[offset:]
49220-	if i := strings.LastIndex(pre, "\n"); i >= 0 {
49221-		pre = pre[i+1:]
49222-	}
49223-	if i := strings.IndexRune(post, '\n'); i >= 0 {
49224-		post = post[:i]
49225-	}
49226-	return pre, post
49227-}
49228-
49229-// -- these are the historical lsppos tests --
49230-
49231-type testCase struct {
49232-	content            string      // input text
49233-	substrOrOffset     interface{} // explicit integer offset, or a substring
49234-	wantLine, wantChar int         // expected LSP position information
49235-}
49236-
49237-// offset returns the test case byte offset
49238-func (c testCase) offset() int {
49239-	switch x := c.substrOrOffset.(type) {
49240-	case int:
49241-		return x
49242-	case string:
49243-		i := strings.Index(c.content, x)
49244-		if i < 0 {
49245-			panic(fmt.Sprintf("%q does not contain substring %q", c.content, x))
49246-		}
49247-		return i
49248-	}
49249-	panic("substrOrIndex must be an integer or string")
49250-}
49251-
49252-var tests = []testCase{
49253-	{"a��b", "a", 0, 0},
49254-	{"a��b", "��", 0, 1},
49255-	{"a��b", "b", 0, 3},
49256-	{"a��b\n", "\n", 0, 4},
49257-	{"a��b\r\n", "\n", 0, 4}, // \r|\n is not a valid position, so we move back to the end of the first line.
49258-	{"a��b\r\nx", "x", 1, 0},
49259-	{"a��b\r\nx\ny", "y", 2, 0},
49260-
49261-	// Testing EOL and EOF positions
49262-	{"", 0, 0, 0}, // 0th position of an empty buffer is (0, 0)
49263-	{"abc", "c", 0, 2},
49264-	{"abc", 3, 0, 3},
49265-	{"abc\n", "\n", 0, 3},
49266-	{"abc\n", 4, 1, 0}, // position after a newline is on the next line
49267-}
49268-
49269-func TestLineChar(t *testing.T) {
49270-	for _, test := range tests {
49271-		m := protocol.NewMapper("", []byte(test.content))
49272-		offset := test.offset()
49273-		posn, _ := m.OffsetPosition(offset)
49274-		gotLine, gotChar := int(posn.Line), int(posn.Character)
49275-		if gotLine != test.wantLine || gotChar != test.wantChar {
49276-			t.Errorf("LineChar(%d) = (%d,%d), want (%d,%d)", offset, gotLine, gotChar, test.wantLine, test.wantChar)
49277-		}
49278-	}
49279-}
49280-
49281-func TestInvalidOffset(t *testing.T) {
49282-	content := []byte("a��b\r\nx\ny")
49283-	m := protocol.NewMapper("", content)
49284-	for _, offset := range []int{-1, 100} {
49285-		posn, err := m.OffsetPosition(offset)
49286-		if err == nil {
49287-			t.Errorf("OffsetPosition(%d) = %s, want error", offset, posn)
49288-		}
49289-	}
49290-}
49291-
49292-func TestPosition(t *testing.T) {
49293-	for _, test := range tests {
49294-		m := protocol.NewMapper("", []byte(test.content))
49295-		offset := test.offset()
49296-		got, err := m.OffsetPosition(offset)
49297-		if err != nil {
49298-			t.Errorf("OffsetPosition(%d) failed: %v", offset, err)
49299-			continue
49300-		}
49301-		want := protocol.Position{Line: uint32(test.wantLine), Character: uint32(test.wantChar)}
49302-		if got != want {
49303-			t.Errorf("Position(%d) = %v, want %v", offset, got, want)
49304-		}
49305-	}
49306-}
49307-
49308-func TestRange(t *testing.T) {
49309-	for _, test := range tests {
49310-		m := protocol.NewMapper("", []byte(test.content))
49311-		offset := test.offset()
49312-		got, err := m.OffsetRange(0, offset)
49313-		if err != nil {
49314-			t.Fatal(err)
49315-		}
49316-		want := protocol.Range{
49317-			End: protocol.Position{Line: uint32(test.wantLine), Character: uint32(test.wantChar)},
49318-		}
49319-		if got != want {
49320-			t.Errorf("Range(%d) = %v, want %v", offset, got, want)
49321-		}
49322-	}
49323-}
49324-
49325-func TestBytesOffset(t *testing.T) {
49326-	tests := []struct {
49327-		text string
49328-		pos  protocol.Position
49329-		want int
49330-	}{
49331-		// U+10400 encodes as [F0 90 90 80] in UTF-8 and [D801 DC00] in UTF-16.
49332-		{text: `a��b`, pos: protocol.Position{Line: 0, Character: 0}, want: 0},
49333-		{text: `a��b`, pos: protocol.Position{Line: 0, Character: 1}, want: 1},
49334-		{text: `a��b`, pos: protocol.Position{Line: 0, Character: 2}, want: 1},
49335-		{text: `a��b`, pos: protocol.Position{Line: 0, Character: 3}, want: 5},
49336-		{text: `a��b`, pos: protocol.Position{Line: 0, Character: 4}, want: 6},
49337-		{text: `a��b`, pos: protocol.Position{Line: 0, Character: 5}, want: -1},
49338-		{text: "aaa\nbbb\n", pos: protocol.Position{Line: 0, Character: 3}, want: 3},
49339-		{text: "aaa\nbbb\n", pos: protocol.Position{Line: 0, Character: 4}, want: -1},
49340-		{text: "aaa\nbbb\n", pos: protocol.Position{Line: 1, Character: 0}, want: 4},
49341-		{text: "aaa\nbbb\n", pos: protocol.Position{Line: 1, Character: 3}, want: 7},
49342-		{text: "aaa\nbbb\n", pos: protocol.Position{Line: 1, Character: 4}, want: -1},
49343-		{text: "aaa\nbbb\n", pos: protocol.Position{Line: 2, Character: 0}, want: 8},
49344-		{text: "aaa\nbbb\n", pos: protocol.Position{Line: 2, Character: 1}, want: -1},
49345-		{text: "aaa\nbbb\n\n", pos: protocol.Position{Line: 2, Character: 0}, want: 8},
49346-	}
49347-
49348-	for i, test := range tests {
49349-		fname := fmt.Sprintf("test %d", i)
49350-		uri := span.URIFromPath(fname)
49351-		mapper := protocol.NewMapper(uri, []byte(test.text))
49352-		got, err := mapper.PositionPoint(test.pos)
49353-		if err != nil && test.want != -1 {
49354-			t.Errorf("%d: unexpected error: %v", i, err)
49355-		}
49356-		if err == nil && got.Offset() != test.want {
49357-			t.Errorf("want %d for %q(Line:%d,Character:%d), but got %d", test.want, test.text, int(test.pos.Line), int(test.pos.Character), got.Offset())
49358-		}
49359-	}
49360-}
49361-
49362-// -- end --
49363diff -urN a/gopls/internal/lsp/protocol/protocol.go b/gopls/internal/lsp/protocol/protocol.go
49364--- a/gopls/internal/lsp/protocol/protocol.go	2000-01-01 00:00:00.000000000 -0000
49365+++ b/gopls/internal/lsp/protocol/protocol.go	1970-01-01 00:00:00.000000000 +0000
49366@@ -1,284 +0,0 @@
49367-// Copyright 2018 The Go Authors. All rights reserved.
49368-// Use of this source code is governed by a BSD-style
49369-// license that can be found in the LICENSE file.
49370-
49371-package protocol
49372-
49373-import (
49374-	"context"
49375-	"encoding/json"
49376-	"fmt"
49377-	"io"
49378-
49379-	"golang.org/x/tools/internal/event"
49380-	"golang.org/x/tools/internal/jsonrpc2"
49381-	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
49382-	"golang.org/x/tools/internal/xcontext"
49383-)
49384-
49385-var (
49386-	// RequestCancelledError should be used when a request is cancelled early.
49387-	RequestCancelledError   = jsonrpc2.NewError(-32800, "JSON RPC cancelled")
49388-	RequestCancelledErrorV2 = jsonrpc2_v2.NewError(-32800, "JSON RPC cancelled")
49389-)
49390-
49391-type ClientCloser interface {
49392-	Client
49393-	io.Closer
49394-}
49395-
49396-type connSender interface {
49397-	io.Closer
49398-
49399-	Notify(ctx context.Context, method string, params interface{}) error
49400-	Call(ctx context.Context, method string, params, result interface{}) error
49401-}
49402-
49403-type clientDispatcher struct {
49404-	sender connSender
49405-}
49406-
49407-func (c *clientDispatcher) Close() error {
49408-	return c.sender.Close()
49409-}
49410-
49411-// ClientDispatcher returns a Client that dispatches LSP requests across the
49412-// given jsonrpc2 connection.
49413-func ClientDispatcher(conn jsonrpc2.Conn) ClientCloser {
49414-	return &clientDispatcher{sender: clientConn{conn}}
49415-}
49416-
49417-type clientConn struct {
49418-	conn jsonrpc2.Conn
49419-}
49420-
49421-func (c clientConn) Close() error {
49422-	return c.conn.Close()
49423-}
49424-
49425-func (c clientConn) Notify(ctx context.Context, method string, params interface{}) error {
49426-	return c.conn.Notify(ctx, method, params)
49427-}
49428-
49429-func (c clientConn) Call(ctx context.Context, method string, params interface{}, result interface{}) error {
49430-	id, err := c.conn.Call(ctx, method, params, result)
49431-	if ctx.Err() != nil {
49432-		cancelCall(ctx, c, id)
49433-	}
49434-	return err
49435-}
49436-
49437-func ClientDispatcherV2(conn *jsonrpc2_v2.Connection) ClientCloser {
49438-	return &clientDispatcher{clientConnV2{conn}}
49439-}
49440-
49441-type clientConnV2 struct {
49442-	conn *jsonrpc2_v2.Connection
49443-}
49444-
49445-func (c clientConnV2) Close() error {
49446-	return c.conn.Close()
49447-}
49448-
49449-func (c clientConnV2) Notify(ctx context.Context, method string, params interface{}) error {
49450-	return c.conn.Notify(ctx, method, params)
49451-}
49452-
49453-func (c clientConnV2) Call(ctx context.Context, method string, params interface{}, result interface{}) error {
49454-	call := c.conn.Call(ctx, method, params)
49455-	err := call.Await(ctx, result)
49456-	if ctx.Err() != nil {
49457-		detached := xcontext.Detach(ctx)
49458-		c.conn.Notify(detached, "$/cancelRequest", &CancelParams{ID: call.ID().Raw()})
49459-	}
49460-	return err
49461-}
49462-
49463-// ServerDispatcher returns a Server that dispatches LSP requests across the
49464-// given jsonrpc2 connection.
49465-func ServerDispatcher(conn jsonrpc2.Conn) Server {
49466-	return &serverDispatcher{sender: clientConn{conn}}
49467-}
49468-
49469-func ServerDispatcherV2(conn *jsonrpc2_v2.Connection) Server {
49470-	return &serverDispatcher{sender: clientConnV2{conn}}
49471-}
49472-
49473-type serverDispatcher struct {
49474-	sender connSender
49475-}
49476-
49477-func ClientHandler(client Client, handler jsonrpc2.Handler) jsonrpc2.Handler {
49478-	return func(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error {
49479-		if ctx.Err() != nil {
49480-			ctx := xcontext.Detach(ctx)
49481-			return reply(ctx, nil, RequestCancelledError)
49482-		}
49483-		handled, err := clientDispatch(ctx, client, reply, req)
49484-		if handled || err != nil {
49485-			return err
49486-		}
49487-		return handler(ctx, reply, req)
49488-	}
49489-}
49490-
49491-func ClientHandlerV2(client Client) jsonrpc2_v2.Handler {
49492-	return jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
49493-		if ctx.Err() != nil {
49494-			return nil, RequestCancelledErrorV2
49495-		}
49496-		req1 := req2to1(req)
49497-		var (
49498-			result interface{}
49499-			resErr error
49500-		)
49501-		replier := func(_ context.Context, res interface{}, err error) error {
49502-			if err != nil {
49503-				resErr = err
49504-				return nil
49505-			}
49506-			result = res
49507-			return nil
49508-		}
49509-		_, err := clientDispatch(ctx, client, replier, req1)
49510-		if err != nil {
49511-			return nil, err
49512-		}
49513-		return result, resErr
49514-	})
49515-}
49516-
49517-func ServerHandler(server Server, handler jsonrpc2.Handler) jsonrpc2.Handler {
49518-	return func(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error {
49519-		if ctx.Err() != nil {
49520-			ctx := xcontext.Detach(ctx)
49521-			return reply(ctx, nil, RequestCancelledError)
49522-		}
49523-		handled, err := serverDispatch(ctx, server, reply, req)
49524-		if handled || err != nil {
49525-			return err
49526-		}
49527-		//TODO: This code is wrong, it ignores handler and assumes non standard
49528-		// request handles everything
49529-		// non standard request should just be a layered handler.
49530-		var params interface{}
49531-		if err := json.Unmarshal(req.Params(), &params); err != nil {
49532-			return sendParseError(ctx, reply, err)
49533-		}
49534-		resp, err := server.NonstandardRequest(ctx, req.Method(), params)
49535-		return reply(ctx, resp, err)
49536-
49537-	}
49538-}
49539-
49540-func ServerHandlerV2(server Server) jsonrpc2_v2.Handler {
49541-	return jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
49542-		if ctx.Err() != nil {
49543-			return nil, RequestCancelledErrorV2
49544-		}
49545-		req1 := req2to1(req)
49546-		var (
49547-			result interface{}
49548-			resErr error
49549-		)
49550-		replier := func(_ context.Context, res interface{}, err error) error {
49551-			if err != nil {
49552-				resErr = err
49553-				return nil
49554-			}
49555-			result = res
49556-			return nil
49557-		}
49558-		_, err := serverDispatch(ctx, server, replier, req1)
49559-		if err != nil {
49560-			return nil, err
49561-		}
49562-		return result, resErr
49563-	})
49564-}
49565-
49566-func req2to1(req2 *jsonrpc2_v2.Request) jsonrpc2.Request {
49567-	if req2.ID.IsValid() {
49568-		raw := req2.ID.Raw()
49569-		var idv1 jsonrpc2.ID
49570-		switch v := raw.(type) {
49571-		case int64:
49572-			idv1 = jsonrpc2.NewIntID(v)
49573-		case string:
49574-			idv1 = jsonrpc2.NewStringID(v)
49575-		default:
49576-			panic(fmt.Sprintf("unsupported ID type %T", raw))
49577-		}
49578-		req1, err := jsonrpc2.NewCall(idv1, req2.Method, req2.Params)
49579-		if err != nil {
49580-			panic(err)
49581-		}
49582-		return req1
49583-	}
49584-	req1, err := jsonrpc2.NewNotification(req2.Method, req2.Params)
49585-	if err != nil {
49586-		panic(err)
49587-	}
49588-	return req1
49589-}
49590-
49591-func Handlers(handler jsonrpc2.Handler) jsonrpc2.Handler {
49592-	return CancelHandler(
49593-		jsonrpc2.AsyncHandler(
49594-			jsonrpc2.MustReplyHandler(handler)))
49595-}
49596-
49597-func CancelHandler(handler jsonrpc2.Handler) jsonrpc2.Handler {
49598-	handler, canceller := jsonrpc2.CancelHandler(handler)
49599-	return func(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error {
49600-		if req.Method() != "$/cancelRequest" {
49601-			// TODO(iancottrell): See if we can generate a reply for the request to be cancelled
49602-			// at the point of cancellation rather than waiting for gopls to naturally reply.
49603-			// To do that, we need to keep track of whether a reply has been sent already and
49604-			// be careful about racing between the two paths.
49605-			// TODO(iancottrell): Add a test that watches the stream and verifies the response
49606-			// for the cancelled request flows.
49607-			replyWithDetachedContext := func(ctx context.Context, resp interface{}, err error) error {
49608-				// https://microsoft.github.io/language-server-protocol/specifications/specification-current/#cancelRequest
49609-				if ctx.Err() != nil && err == nil {
49610-					err = RequestCancelledError
49611-				}
49612-				ctx = xcontext.Detach(ctx)
49613-				return reply(ctx, resp, err)
49614-			}
49615-			return handler(ctx, replyWithDetachedContext, req)
49616-		}
49617-		var params CancelParams
49618-		if err := json.Unmarshal(req.Params(), &params); err != nil {
49619-			return sendParseError(ctx, reply, err)
49620-		}
49621-		if n, ok := params.ID.(float64); ok {
49622-			canceller(jsonrpc2.NewIntID(int64(n)))
49623-		} else if s, ok := params.ID.(string); ok {
49624-			canceller(jsonrpc2.NewStringID(s))
49625-		} else {
49626-			return sendParseError(ctx, reply, fmt.Errorf("request ID %v malformed", params.ID))
49627-		}
49628-		return reply(ctx, nil, nil)
49629-	}
49630-}
49631-
49632-func Call(ctx context.Context, conn jsonrpc2.Conn, method string, params interface{}, result interface{}) error {
49633-	id, err := conn.Call(ctx, method, params, result)
49634-	if ctx.Err() != nil {
49635-		cancelCall(ctx, clientConn{conn}, id)
49636-	}
49637-	return err
49638-}
49639-
49640-func cancelCall(ctx context.Context, sender connSender, id jsonrpc2.ID) {
49641-	ctx = xcontext.Detach(ctx)
49642-	ctx, done := event.Start(ctx, "protocol.canceller")
49643-	defer done()
49644-	// Note that only *jsonrpc2.ID implements json.Marshaler.
49645-	sender.Notify(ctx, "$/cancelRequest", &CancelParams{ID: &id})
49646-}
49647-
49648-func sendParseError(ctx context.Context, reply jsonrpc2.Replier, err error) error {
49649-	return reply(ctx, nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err))
49650-}
49651diff -urN a/gopls/internal/lsp/protocol/span.go b/gopls/internal/lsp/protocol/span.go
49652--- a/gopls/internal/lsp/protocol/span.go	2000-01-01 00:00:00.000000000 -0000
49653+++ b/gopls/internal/lsp/protocol/span.go	1970-01-01 00:00:00.000000000 +0000
49654@@ -1,118 +0,0 @@
49655-// Copyright 2018 The Go Authors. All rights reserved.
49656-// Use of this source code is governed by a BSD-style
49657-// license that can be found in the LICENSE file.
49658-
49659-package protocol
49660-
49661-import (
49662-	"fmt"
49663-	"unicode/utf8"
49664-
49665-	"golang.org/x/tools/gopls/internal/span"
49666-)
49667-
49668-func URIFromSpanURI(uri span.URI) DocumentURI {
49669-	return DocumentURI(uri) // simple conversion
49670-}
49671-
49672-func URIFromPath(path string) DocumentURI {
49673-	return URIFromSpanURI(span.URIFromPath(path)) // normalizing conversion
49674-}
49675-
49676-func (u DocumentURI) SpanURI() span.URI {
49677-	return span.URIFromURI(string(u)) // normalizing conversion
49678-}
49679-
49680-func IsPoint(r Range) bool {
49681-	return r.Start.Line == r.End.Line && r.Start.Character == r.End.Character
49682-}
49683-
49684-// CompareLocation defines a three-valued comparison over locations,
49685-// lexicographically ordered by (URI, Range).
49686-func CompareLocation(x, y Location) int {
49687-	if x.URI != y.URI {
49688-		if x.URI < y.URI {
49689-			return -1
49690-		} else {
49691-			return +1
49692-		}
49693-	}
49694-	return CompareRange(x.Range, y.Range)
49695-}
49696-
49697-// CompareRange returns -1 if a is before b, 0 if a == b, and 1 if a is after b.
49698-//
49699-// A range a is defined to be 'before' b if a.Start is before b.Start, or
49700-// a.Start == b.Start and a.End is before b.End.
49701-func CompareRange(a, b Range) int {
49702-	if r := ComparePosition(a.Start, b.Start); r != 0 {
49703-		return r
49704-	}
49705-	return ComparePosition(a.End, b.End)
49706-}
49707-
49708-// ComparePosition returns -1 if a is before b, 0 if a == b, and 1 if a is after b.
49709-func ComparePosition(a, b Position) int {
49710-	if a.Line != b.Line {
49711-		if a.Line < b.Line {
49712-			return -1
49713-		} else {
49714-			return +1
49715-		}
49716-	}
49717-	if a.Character != b.Character {
49718-		if a.Character < b.Character {
49719-			return -1
49720-		} else {
49721-			return +1
49722-		}
49723-	}
49724-	return 0
49725-}
49726-
49727-func Intersect(a, b Range) bool {
49728-	if a.Start.Line > b.End.Line || a.End.Line < b.Start.Line {
49729-		return false
49730-	}
49731-	return !((a.Start.Line == b.End.Line) && a.Start.Character > b.End.Character ||
49732-		(a.End.Line == b.Start.Line) && a.End.Character < b.Start.Character)
49733-}
49734-
49735-// Format implements fmt.Formatter.
49736-//
49737-// Note: Formatter is implemented instead of Stringer (presumably) for
49738-// performance reasons, though it is not clear that it matters in practice.
49739-func (r Range) Format(f fmt.State, _ rune) {
49740-	fmt.Fprintf(f, "%v-%v", r.Start, r.End)
49741-}
49742-
49743-// Format implements fmt.Formatter.
49744-//
49745-// See Range.Format for discussion of why the Formatter interface is
49746-// implemented rather than Stringer.
49747-func (p Position) Format(f fmt.State, _ rune) {
49748-	fmt.Fprintf(f, "%v:%v", p.Line, p.Character)
49749-}
49750-
49751-// -- implementation helpers --
49752-
49753-// UTF16Len returns the number of codes in the UTF-16 transcoding of s.
49754-func UTF16Len(s []byte) int {
49755-	var n int
49756-	for len(s) > 0 {
49757-		n++
49758-
49759-		// Fast path for ASCII.
49760-		if s[0] < 0x80 {
49761-			s = s[1:]
49762-			continue
49763-		}
49764-
49765-		r, size := utf8.DecodeRune(s)
49766-		if r >= 0x10000 {
49767-			n++ // surrogate pair
49768-		}
49769-		s = s[size:]
49770-	}
49771-	return n
49772-}
49773diff -urN a/gopls/internal/lsp/protocol/tsclient.go b/gopls/internal/lsp/protocol/tsclient.go
49774--- a/gopls/internal/lsp/protocol/tsclient.go	2000-01-01 00:00:00.000000000 -0000
49775+++ b/gopls/internal/lsp/protocol/tsclient.go	1970-01-01 00:00:00.000000000 +0000
49776@@ -1,249 +0,0 @@
49777-// Copyright 2023 The Go Authors. All rights reserved.
49778-// Use of this source code is governed by a BSD-style
49779-// license that can be found in the LICENSE file.
49780-
49781-// Code generated for LSP. DO NOT EDIT.
49782-
49783-package protocol
49784-
49785-// Code generated from protocol/metaModel.json at ref release/protocol/3.17.3-next.6 (hash 56c23c557e3568a9f56f42435fd5a80f9458957f).
49786-// https://github.com/microsoft/vscode-languageserver-node/blob/release/protocol/3.17.3-next.6/protocol/metaModel.json
49787-// LSP metaData.version = 3.17.0.
49788-
49789-import (
49790-	"context"
49791-	"encoding/json"
49792-
49793-	"golang.org/x/tools/internal/jsonrpc2"
49794-)
49795-
49796-type Client interface {
49797-	LogTrace(context.Context, *LogTraceParams) error                                           // $/logTrace
49798-	Progress(context.Context, *ProgressParams) error                                           // $/progress
49799-	RegisterCapability(context.Context, *RegistrationParams) error                             // client/registerCapability
49800-	UnregisterCapability(context.Context, *UnregistrationParams) error                         // client/unregisterCapability
49801-	Event(context.Context, *interface{}) error                                                 // telemetry/event
49802-	PublishDiagnostics(context.Context, *PublishDiagnosticsParams) error                       // textDocument/publishDiagnostics
49803-	LogMessage(context.Context, *LogMessageParams) error                                       // window/logMessage
49804-	ShowDocument(context.Context, *ShowDocumentParams) (*ShowDocumentResult, error)            // window/showDocument
49805-	ShowMessage(context.Context, *ShowMessageParams) error                                     // window/showMessage
49806-	ShowMessageRequest(context.Context, *ShowMessageRequestParams) (*MessageActionItem, error) // window/showMessageRequest
49807-	WorkDoneProgressCreate(context.Context, *WorkDoneProgressCreateParams) error               // window/workDoneProgress/create
49808-	ApplyEdit(context.Context, *ApplyWorkspaceEditParams) (*ApplyWorkspaceEditResult, error)   // workspace/applyEdit
49809-	CodeLensRefresh(context.Context) error                                                     // workspace/codeLens/refresh
49810-	Configuration(context.Context, *ParamConfiguration) ([]LSPAny, error)                      // workspace/configuration
49811-	DiagnosticRefresh(context.Context) error                                                   // workspace/diagnostic/refresh
49812-	InlayHintRefresh(context.Context) error                                                    // workspace/inlayHint/refresh
49813-	InlineValueRefresh(context.Context) error                                                  // workspace/inlineValue/refresh
49814-	SemanticTokensRefresh(context.Context) error                                               // workspace/semanticTokens/refresh
49815-	WorkspaceFolders(context.Context) ([]WorkspaceFolder, error)                               // workspace/workspaceFolders
49816-}
49817-
49818-func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier, r jsonrpc2.Request) (bool, error) {
49819-	switch r.Method() {
49820-	case "$/logTrace":
49821-		var params LogTraceParams
49822-		if err := json.Unmarshal(r.Params(), &params); err != nil {
49823-			return true, sendParseError(ctx, reply, err)
49824-		}
49825-		err := client.LogTrace(ctx, &params)
49826-		return true, reply(ctx, nil, err)
49827-	case "$/progress":
49828-		var params ProgressParams
49829-		if err := json.Unmarshal(r.Params(), &params); err != nil {
49830-			return true, sendParseError(ctx, reply, err)
49831-		}
49832-		err := client.Progress(ctx, &params)
49833-		return true, reply(ctx, nil, err)
49834-	case "client/registerCapability":
49835-		var params RegistrationParams
49836-		if err := json.Unmarshal(r.Params(), &params); err != nil {
49837-			return true, sendParseError(ctx, reply, err)
49838-		}
49839-		err := client.RegisterCapability(ctx, &params)
49840-		return true, reply(ctx, nil, err)
49841-	case "client/unregisterCapability":
49842-		var params UnregistrationParams
49843-		if err := json.Unmarshal(r.Params(), &params); err != nil {
49844-			return true, sendParseError(ctx, reply, err)
49845-		}
49846-		err := client.UnregisterCapability(ctx, &params)
49847-		return true, reply(ctx, nil, err)
49848-	case "telemetry/event":
49849-		var params interface{}
49850-		if err := json.Unmarshal(r.Params(), &params); err != nil {
49851-			return true, sendParseError(ctx, reply, err)
49852-		}
49853-		err := client.Event(ctx, &params)
49854-		return true, reply(ctx, nil, err)
49855-	case "textDocument/publishDiagnostics":
49856-		var params PublishDiagnosticsParams
49857-		if err := json.Unmarshal(r.Params(), &params); err != nil {
49858-			return true, sendParseError(ctx, reply, err)
49859-		}
49860-		err := client.PublishDiagnostics(ctx, &params)
49861-		return true, reply(ctx, nil, err)
49862-	case "window/logMessage":
49863-		var params LogMessageParams
49864-		if err := json.Unmarshal(r.Params(), &params); err != nil {
49865-			return true, sendParseError(ctx, reply, err)
49866-		}
49867-		err := client.LogMessage(ctx, &params)
49868-		return true, reply(ctx, nil, err)
49869-	case "window/showDocument":
49870-		var params ShowDocumentParams
49871-		if err := json.Unmarshal(r.Params(), &params); err != nil {
49872-			return true, sendParseError(ctx, reply, err)
49873-		}
49874-		resp, err := client.ShowDocument(ctx, &params)
49875-		if err != nil {
49876-			return true, reply(ctx, nil, err)
49877-		}
49878-		return true, reply(ctx, resp, nil)
49879-	case "window/showMessage":
49880-		var params ShowMessageParams
49881-		if err := json.Unmarshal(r.Params(), &params); err != nil {
49882-			return true, sendParseError(ctx, reply, err)
49883-		}
49884-		err := client.ShowMessage(ctx, &params)
49885-		return true, reply(ctx, nil, err)
49886-	case "window/showMessageRequest":
49887-		var params ShowMessageRequestParams
49888-		if err := json.Unmarshal(r.Params(), &params); err != nil {
49889-			return true, sendParseError(ctx, reply, err)
49890-		}
49891-		resp, err := client.ShowMessageRequest(ctx, &params)
49892-		if err != nil {
49893-			return true, reply(ctx, nil, err)
49894-		}
49895-		return true, reply(ctx, resp, nil)
49896-	case "window/workDoneProgress/create":
49897-		var params WorkDoneProgressCreateParams
49898-		if err := json.Unmarshal(r.Params(), &params); err != nil {
49899-			return true, sendParseError(ctx, reply, err)
49900-		}
49901-		err := client.WorkDoneProgressCreate(ctx, &params)
49902-		return true, reply(ctx, nil, err)
49903-	case "workspace/applyEdit":
49904-		var params ApplyWorkspaceEditParams
49905-		if err := json.Unmarshal(r.Params(), &params); err != nil {
49906-			return true, sendParseError(ctx, reply, err)
49907-		}
49908-		resp, err := client.ApplyEdit(ctx, &params)
49909-		if err != nil {
49910-			return true, reply(ctx, nil, err)
49911-		}
49912-		return true, reply(ctx, resp, nil)
49913-	case "workspace/codeLens/refresh":
49914-		err := client.CodeLensRefresh(ctx)
49915-		return true, reply(ctx, nil, err)
49916-	case "workspace/configuration":
49917-		var params ParamConfiguration
49918-		if err := json.Unmarshal(r.Params(), &params); err != nil {
49919-			return true, sendParseError(ctx, reply, err)
49920-		}
49921-		resp, err := client.Configuration(ctx, &params)
49922-		if err != nil {
49923-			return true, reply(ctx, nil, err)
49924-		}
49925-		return true, reply(ctx, resp, nil)
49926-	case "workspace/diagnostic/refresh":
49927-		err := client.DiagnosticRefresh(ctx)
49928-		return true, reply(ctx, nil, err)
49929-	case "workspace/inlayHint/refresh":
49930-		err := client.InlayHintRefresh(ctx)
49931-		return true, reply(ctx, nil, err)
49932-	case "workspace/inlineValue/refresh":
49933-		err := client.InlineValueRefresh(ctx)
49934-		return true, reply(ctx, nil, err)
49935-	case "workspace/semanticTokens/refresh":
49936-		err := client.SemanticTokensRefresh(ctx)
49937-		return true, reply(ctx, nil, err)
49938-	case "workspace/workspaceFolders":
49939-		resp, err := client.WorkspaceFolders(ctx)
49940-		if err != nil {
49941-			return true, reply(ctx, nil, err)
49942-		}
49943-		return true, reply(ctx, resp, nil)
49944-	default:
49945-		return false, nil
49946-	}
49947-}
49948-
49949-func (s *clientDispatcher) LogTrace(ctx context.Context, params *LogTraceParams) error {
49950-	return s.sender.Notify(ctx, "$/logTrace", params)
49951-}
49952-func (s *clientDispatcher) Progress(ctx context.Context, params *ProgressParams) error {
49953-	return s.sender.Notify(ctx, "$/progress", params)
49954-}
49955-func (s *clientDispatcher) RegisterCapability(ctx context.Context, params *RegistrationParams) error {
49956-	return s.sender.Call(ctx, "client/registerCapability", params, nil)
49957-}
49958-func (s *clientDispatcher) UnregisterCapability(ctx context.Context, params *UnregistrationParams) error {
49959-	return s.sender.Call(ctx, "client/unregisterCapability", params, nil)
49960-}
49961-func (s *clientDispatcher) Event(ctx context.Context, params *interface{}) error {
49962-	return s.sender.Notify(ctx, "telemetry/event", params)
49963-}
49964-func (s *clientDispatcher) PublishDiagnostics(ctx context.Context, params *PublishDiagnosticsParams) error {
49965-	return s.sender.Notify(ctx, "textDocument/publishDiagnostics", params)
49966-}
49967-func (s *clientDispatcher) LogMessage(ctx context.Context, params *LogMessageParams) error {
49968-	return s.sender.Notify(ctx, "window/logMessage", params)
49969-}
49970-func (s *clientDispatcher) ShowDocument(ctx context.Context, params *ShowDocumentParams) (*ShowDocumentResult, error) {
49971-	var result *ShowDocumentResult
49972-	if err := s.sender.Call(ctx, "window/showDocument", params, &result); err != nil {
49973-		return nil, err
49974-	}
49975-	return result, nil
49976-}
49977-func (s *clientDispatcher) ShowMessage(ctx context.Context, params *ShowMessageParams) error {
49978-	return s.sender.Notify(ctx, "window/showMessage", params)
49979-}
49980-func (s *clientDispatcher) ShowMessageRequest(ctx context.Context, params *ShowMessageRequestParams) (*MessageActionItem, error) {
49981-	var result *MessageActionItem
49982-	if err := s.sender.Call(ctx, "window/showMessageRequest", params, &result); err != nil {
49983-		return nil, err
49984-	}
49985-	return result, nil
49986-}
49987-func (s *clientDispatcher) WorkDoneProgressCreate(ctx context.Context, params *WorkDoneProgressCreateParams) error {
49988-	return s.sender.Call(ctx, "window/workDoneProgress/create", params, nil)
49989-}
49990-func (s *clientDispatcher) ApplyEdit(ctx context.Context, params *ApplyWorkspaceEditParams) (*ApplyWorkspaceEditResult, error) {
49991-	var result *ApplyWorkspaceEditResult
49992-	if err := s.sender.Call(ctx, "workspace/applyEdit", params, &result); err != nil {
49993-		return nil, err
49994-	}
49995-	return result, nil
49996-}
49997-func (s *clientDispatcher) CodeLensRefresh(ctx context.Context) error {
49998-	return s.sender.Call(ctx, "workspace/codeLens/refresh", nil, nil)
49999-}
50000-func (s *clientDispatcher) Configuration(ctx context.Context, params *ParamConfiguration) ([]LSPAny, error) {
50001-	var result []LSPAny
50002-	if err := s.sender.Call(ctx, "workspace/configuration", params, &result); err != nil {
50003-		return nil, err
50004-	}
50005-	return result, nil
50006-}
50007-func (s *clientDispatcher) DiagnosticRefresh(ctx context.Context) error {
50008-	return s.sender.Call(ctx, "workspace/diagnostic/refresh", nil, nil)
50009-}
50010-func (s *clientDispatcher) InlayHintRefresh(ctx context.Context) error {
50011-	return s.sender.Call(ctx, "workspace/inlayHint/refresh", nil, nil)
50012-}
50013-func (s *clientDispatcher) InlineValueRefresh(ctx context.Context) error {
50014-	return s.sender.Call(ctx, "workspace/inlineValue/refresh", nil, nil)
50015-}
50016-func (s *clientDispatcher) SemanticTokensRefresh(ctx context.Context) error {
50017-	return s.sender.Call(ctx, "workspace/semanticTokens/refresh", nil, nil)
50018-}
50019-func (s *clientDispatcher) WorkspaceFolders(ctx context.Context) ([]WorkspaceFolder, error) {
50020-	var result []WorkspaceFolder
50021-	if err := s.sender.Call(ctx, "workspace/workspaceFolders", nil, &result); err != nil {
50022-		return nil, err
50023-	}
50024-	return result, nil
50025-}
50026diff -urN a/gopls/internal/lsp/protocol/tsdocument_changes.go b/gopls/internal/lsp/protocol/tsdocument_changes.go
50027--- a/gopls/internal/lsp/protocol/tsdocument_changes.go	2000-01-01 00:00:00.000000000 -0000
50028+++ b/gopls/internal/lsp/protocol/tsdocument_changes.go	1970-01-01 00:00:00.000000000 +0000
50029@@ -1,42 +0,0 @@
50030-// Copyright 2022 The Go Authors. All rights reserved.
50031-// Use of this source code is governed by a BSD-style
50032-// license that can be found in the LICENSE file.
50033-
50034-package protocol
50035-
50036-import (
50037-	"encoding/json"
50038-	"fmt"
50039-)
50040-
50041-// DocumentChanges is a union of a file edit and directory rename operations
50042-// for package renaming feature. At most one field of this struct is non-nil.
50043-type DocumentChanges struct {
50044-	TextDocumentEdit *TextDocumentEdit
50045-	RenameFile       *RenameFile
50046-}
50047-
50048-func (d *DocumentChanges) UnmarshalJSON(data []byte) error {
50049-	var m map[string]interface{}
50050-
50051-	if err := json.Unmarshal(data, &m); err != nil {
50052-		return err
50053-	}
50054-
50055-	if _, ok := m["textDocument"]; ok {
50056-		d.TextDocumentEdit = new(TextDocumentEdit)
50057-		return json.Unmarshal(data, d.TextDocumentEdit)
50058-	}
50059-
50060-	d.RenameFile = new(RenameFile)
50061-	return json.Unmarshal(data, d.RenameFile)
50062-}
50063-
50064-func (d *DocumentChanges) MarshalJSON() ([]byte, error) {
50065-	if d.TextDocumentEdit != nil {
50066-		return json.Marshal(d.TextDocumentEdit)
50067-	} else if d.RenameFile != nil {
50068-		return json.Marshal(d.RenameFile)
50069-	}
50070-	return nil, fmt.Errorf("Empty DocumentChanges union value")
50071-}
50072diff -urN a/gopls/internal/lsp/protocol/tsjson.go b/gopls/internal/lsp/protocol/tsjson.go
50073--- a/gopls/internal/lsp/protocol/tsjson.go	2000-01-01 00:00:00.000000000 -0000
50074+++ b/gopls/internal/lsp/protocol/tsjson.go	1970-01-01 00:00:00.000000000 +0000
50075@@ -1,1997 +0,0 @@
50076-// Copyright 2023 The Go Authors. All rights reserved.
50077-// Use of this source code is governed by a BSD-style
50078-// license that can be found in the LICENSE file.
50079-
50080-// Code generated for LSP. DO NOT EDIT.
50081-
50082-package protocol
50083-
50084-// Code generated from protocol/metaModel.json at ref release/protocol/3.17.3-next.6 (hash 56c23c557e3568a9f56f42435fd5a80f9458957f).
50085-// https://github.com/microsoft/vscode-languageserver-node/blob/release/protocol/3.17.3-next.6/protocol/metaModel.json
50086-// LSP metaData.version = 3.17.0.
50087-
50088-import "encoding/json"
50089-
50090-import "fmt"
50091-
50092-// UnmarshalError indicates that a JSON value did not conform to
50093-// one of the expected cases of an LSP union type.
50094-type UnmarshalError struct {
50095-	msg string
50096-}
50097-
50098-func (e UnmarshalError) Error() string {
50099-	return e.msg
50100-}
50101-
50102-// from line 4769
50103-func (t OrFEditRangePItemDefaults) MarshalJSON() ([]byte, error) {
50104-	switch x := t.Value.(type) {
50105-	case FEditRangePItemDefaults:
50106-		return json.Marshal(x)
50107-	case Range:
50108-		return json.Marshal(x)
50109-	case nil:
50110-		return []byte("null"), nil
50111-	}
50112-	return nil, fmt.Errorf("type %T not one of [FEditRangePItemDefaults Range]", t)
50113-}
50114-
50115-func (t *OrFEditRangePItemDefaults) UnmarshalJSON(x []byte) error {
50116-	if string(x) == "null" {
50117-		t.Value = nil
50118-		return nil
50119-	}
50120-	var h0 FEditRangePItemDefaults
50121-	if err := json.Unmarshal(x, &h0); err == nil {
50122-		t.Value = h0
50123-		return nil
50124-	}
50125-	var h1 Range
50126-	if err := json.Unmarshal(x, &h1); err == nil {
50127-		t.Value = h1
50128-		return nil
50129-	}
50130-	return &UnmarshalError{"unmarshal failed to match one of [FEditRangePItemDefaults Range]"}
50131-}
50132-
50133-// from line 9811
50134-func (t OrFNotebookPNotebookSelector) MarshalJSON() ([]byte, error) {
50135-	switch x := t.Value.(type) {
50136-	case NotebookDocumentFilter:
50137-		return json.Marshal(x)
50138-	case string:
50139-		return json.Marshal(x)
50140-	case nil:
50141-		return []byte("null"), nil
50142-	}
50143-	return nil, fmt.Errorf("type %T not one of [NotebookDocumentFilter string]", t)
50144-}
50145-
50146-func (t *OrFNotebookPNotebookSelector) UnmarshalJSON(x []byte) error {
50147-	if string(x) == "null" {
50148-		t.Value = nil
50149-		return nil
50150-	}
50151-	var h0 NotebookDocumentFilter
50152-	if err := json.Unmarshal(x, &h0); err == nil {
50153-		t.Value = h0
50154-		return nil
50155-	}
50156-	var h1 string
50157-	if err := json.Unmarshal(x, &h1); err == nil {
50158-		t.Value = h1
50159-		return nil
50160-	}
50161-	return &UnmarshalError{"unmarshal failed to match one of [NotebookDocumentFilter string]"}
50162-}
50163-
50164-// from line 5520
50165-func (t OrPLocation_workspace_symbol) MarshalJSON() ([]byte, error) {
50166-	switch x := t.Value.(type) {
50167-	case Location:
50168-		return json.Marshal(x)
50169-	case PLocationMsg_workspace_symbol:
50170-		return json.Marshal(x)
50171-	case nil:
50172-		return []byte("null"), nil
50173-	}
50174-	return nil, fmt.Errorf("type %T not one of [Location PLocationMsg_workspace_symbol]", t)
50175-}
50176-
50177-func (t *OrPLocation_workspace_symbol) UnmarshalJSON(x []byte) error {
50178-	if string(x) == "null" {
50179-		t.Value = nil
50180-		return nil
50181-	}
50182-	var h0 Location
50183-	if err := json.Unmarshal(x, &h0); err == nil {
50184-		t.Value = h0
50185-		return nil
50186-	}
50187-	var h1 PLocationMsg_workspace_symbol
50188-	if err := json.Unmarshal(x, &h1); err == nil {
50189-		t.Value = h1
50190-		return nil
50191-	}
50192-	return &UnmarshalError{"unmarshal failed to match one of [Location PLocationMsg_workspace_symbol]"}
50193-}
50194-
50195-// from line 4163
50196-func (t OrPSection_workspace_didChangeConfiguration) MarshalJSON() ([]byte, error) {
50197-	switch x := t.Value.(type) {
50198-	case []string:
50199-		return json.Marshal(x)
50200-	case string:
50201-		return json.Marshal(x)
50202-	case nil:
50203-		return []byte("null"), nil
50204-	}
50205-	return nil, fmt.Errorf("type %T not one of [[]string string]", t)
50206-}
50207-
50208-func (t *OrPSection_workspace_didChangeConfiguration) UnmarshalJSON(x []byte) error {
50209-	if string(x) == "null" {
50210-		t.Value = nil
50211-		return nil
50212-	}
50213-	var h0 []string
50214-	if err := json.Unmarshal(x, &h0); err == nil {
50215-		t.Value = h0
50216-		return nil
50217-	}
50218-	var h1 string
50219-	if err := json.Unmarshal(x, &h1); err == nil {
50220-		t.Value = h1
50221-		return nil
50222-	}
50223-	return &UnmarshalError{"unmarshal failed to match one of [[]string string]"}
50224-}
50225-
50226-// from line 7075
50227-func (t OrPTooltipPLabel) MarshalJSON() ([]byte, error) {
50228-	switch x := t.Value.(type) {
50229-	case MarkupContent:
50230-		return json.Marshal(x)
50231-	case string:
50232-		return json.Marshal(x)
50233-	case nil:
50234-		return []byte("null"), nil
50235-	}
50236-	return nil, fmt.Errorf("type %T not one of [MarkupContent string]", t)
50237-}
50238-
50239-func (t *OrPTooltipPLabel) UnmarshalJSON(x []byte) error {
50240-	if string(x) == "null" {
50241-		t.Value = nil
50242-		return nil
50243-	}
50244-	var h0 MarkupContent
50245-	if err := json.Unmarshal(x, &h0); err == nil {
50246-		t.Value = h0
50247-		return nil
50248-	}
50249-	var h1 string
50250-	if err := json.Unmarshal(x, &h1); err == nil {
50251-		t.Value = h1
50252-		return nil
50253-	}
50254-	return &UnmarshalError{"unmarshal failed to match one of [MarkupContent string]"}
50255-}
50256-
50257-// from line 3699
50258-func (t OrPTooltip_textDocument_inlayHint) MarshalJSON() ([]byte, error) {
50259-	switch x := t.Value.(type) {
50260-	case MarkupContent:
50261-		return json.Marshal(x)
50262-	case string:
50263-		return json.Marshal(x)
50264-	case nil:
50265-		return []byte("null"), nil
50266-	}
50267-	return nil, fmt.Errorf("type %T not one of [MarkupContent string]", t)
50268-}
50269-
50270-func (t *OrPTooltip_textDocument_inlayHint) UnmarshalJSON(x []byte) error {
50271-	if string(x) == "null" {
50272-		t.Value = nil
50273-		return nil
50274-	}
50275-	var h0 MarkupContent
50276-	if err := json.Unmarshal(x, &h0); err == nil {
50277-		t.Value = h0
50278-		return nil
50279-	}
50280-	var h1 string
50281-	if err := json.Unmarshal(x, &h1); err == nil {
50282-		t.Value = h1
50283-		return nil
50284-	}
50285-	return &UnmarshalError{"unmarshal failed to match one of [MarkupContent string]"}
50286-}
50287-
50288-// from line 6184
50289-func (t Or_CancelParams_id) MarshalJSON() ([]byte, error) {
50290-	switch x := t.Value.(type) {
50291-	case int32:
50292-		return json.Marshal(x)
50293-	case string:
50294-		return json.Marshal(x)
50295-	case nil:
50296-		return []byte("null"), nil
50297-	}
50298-	return nil, fmt.Errorf("type %T not one of [int32 string]", t)
50299-}
50300-
50301-func (t *Or_CancelParams_id) UnmarshalJSON(x []byte) error {
50302-	if string(x) == "null" {
50303-		t.Value = nil
50304-		return nil
50305-	}
50306-	var h0 int32
50307-	if err := json.Unmarshal(x, &h0); err == nil {
50308-		t.Value = h0
50309-		return nil
50310-	}
50311-	var h1 string
50312-	if err := json.Unmarshal(x, &h1); err == nil {
50313-		t.Value = h1
50314-		return nil
50315-	}
50316-	return &UnmarshalError{"unmarshal failed to match one of [int32 string]"}
50317-}
50318-
50319-// from line 4582
50320-func (t Or_CompletionItem_documentation) MarshalJSON() ([]byte, error) {
50321-	switch x := t.Value.(type) {
50322-	case MarkupContent:
50323-		return json.Marshal(x)
50324-	case string:
50325-		return json.Marshal(x)
50326-	case nil:
50327-		return []byte("null"), nil
50328-	}
50329-	return nil, fmt.Errorf("type %T not one of [MarkupContent string]", t)
50330-}
50331-
50332-func (t *Or_CompletionItem_documentation) UnmarshalJSON(x []byte) error {
50333-	if string(x) == "null" {
50334-		t.Value = nil
50335-		return nil
50336-	}
50337-	var h0 MarkupContent
50338-	if err := json.Unmarshal(x, &h0); err == nil {
50339-		t.Value = h0
50340-		return nil
50341-	}
50342-	var h1 string
50343-	if err := json.Unmarshal(x, &h1); err == nil {
50344-		t.Value = h1
50345-		return nil
50346-	}
50347-	return &UnmarshalError{"unmarshal failed to match one of [MarkupContent string]"}
50348-}
50349-
50350-// from line 4665
50351-func (t Or_CompletionItem_textEdit) MarshalJSON() ([]byte, error) {
50352-	switch x := t.Value.(type) {
50353-	case InsertReplaceEdit:
50354-		return json.Marshal(x)
50355-	case TextEdit:
50356-		return json.Marshal(x)
50357-	case nil:
50358-		return []byte("null"), nil
50359-	}
50360-	return nil, fmt.Errorf("type %T not one of [InsertReplaceEdit TextEdit]", t)
50361-}
50362-
50363-func (t *Or_CompletionItem_textEdit) UnmarshalJSON(x []byte) error {
50364-	if string(x) == "null" {
50365-		t.Value = nil
50366-		return nil
50367-	}
50368-	var h0 InsertReplaceEdit
50369-	if err := json.Unmarshal(x, &h0); err == nil {
50370-		t.Value = h0
50371-		return nil
50372-	}
50373-	var h1 TextEdit
50374-	if err := json.Unmarshal(x, &h1); err == nil {
50375-		t.Value = h1
50376-		return nil
50377-	}
50378-	return &UnmarshalError{"unmarshal failed to match one of [InsertReplaceEdit TextEdit]"}
50379-}
50380-
50381-// from line 13753
50382-func (t Or_Definition) MarshalJSON() ([]byte, error) {
50383-	switch x := t.Value.(type) {
50384-	case Location:
50385-		return json.Marshal(x)
50386-	case []Location:
50387-		return json.Marshal(x)
50388-	case nil:
50389-		return []byte("null"), nil
50390-	}
50391-	return nil, fmt.Errorf("type %T not one of [Location []Location]", t)
50392-}
50393-
50394-func (t *Or_Definition) UnmarshalJSON(x []byte) error {
50395-	if string(x) == "null" {
50396-		t.Value = nil
50397-		return nil
50398-	}
50399-	var h0 Location
50400-	if err := json.Unmarshal(x, &h0); err == nil {
50401-		t.Value = h0
50402-		return nil
50403-	}
50404-	var h1 []Location
50405-	if err := json.Unmarshal(x, &h1); err == nil {
50406-		t.Value = h1
50407-		return nil
50408-	}
50409-	return &UnmarshalError{"unmarshal failed to match one of [Location []Location]"}
50410-}
50411-
50412-// from line 8547
50413-func (t Or_Diagnostic_code) MarshalJSON() ([]byte, error) {
50414-	switch x := t.Value.(type) {
50415-	case int32:
50416-		return json.Marshal(x)
50417-	case string:
50418-		return json.Marshal(x)
50419-	case nil:
50420-		return []byte("null"), nil
50421-	}
50422-	return nil, fmt.Errorf("type %T not one of [int32 string]", t)
50423-}
50424-
50425-func (t *Or_Diagnostic_code) UnmarshalJSON(x []byte) error {
50426-	if string(x) == "null" {
50427-		t.Value = nil
50428-		return nil
50429-	}
50430-	var h0 int32
50431-	if err := json.Unmarshal(x, &h0); err == nil {
50432-		t.Value = h0
50433-		return nil
50434-	}
50435-	var h1 string
50436-	if err := json.Unmarshal(x, &h1); err == nil {
50437-		t.Value = h1
50438-		return nil
50439-	}
50440-	return &UnmarshalError{"unmarshal failed to match one of [int32 string]"}
50441-}
50442-
50443-// from line 13885
50444-func (t Or_DocumentDiagnosticReport) MarshalJSON() ([]byte, error) {
50445-	switch x := t.Value.(type) {
50446-	case RelatedFullDocumentDiagnosticReport:
50447-		return json.Marshal(x)
50448-	case RelatedUnchangedDocumentDiagnosticReport:
50449-		return json.Marshal(x)
50450-	case nil:
50451-		return []byte("null"), nil
50452-	}
50453-	return nil, fmt.Errorf("type %T not one of [RelatedFullDocumentDiagnosticReport RelatedUnchangedDocumentDiagnosticReport]", t)
50454-}
50455-
50456-func (t *Or_DocumentDiagnosticReport) UnmarshalJSON(x []byte) error {
50457-	if string(x) == "null" {
50458-		t.Value = nil
50459-		return nil
50460-	}
50461-	var h0 RelatedFullDocumentDiagnosticReport
50462-	if err := json.Unmarshal(x, &h0); err == nil {
50463-		t.Value = h0
50464-		return nil
50465-	}
50466-	var h1 RelatedUnchangedDocumentDiagnosticReport
50467-	if err := json.Unmarshal(x, &h1); err == nil {
50468-		t.Value = h1
50469-		return nil
50470-	}
50471-	return &UnmarshalError{"unmarshal failed to match one of [RelatedFullDocumentDiagnosticReport RelatedUnchangedDocumentDiagnosticReport]"}
50472-}
50473-
50474-// from line 3822
50475-func (t Or_DocumentDiagnosticReportPartialResult_relatedDocuments_Value) MarshalJSON() ([]byte, error) {
50476-	switch x := t.Value.(type) {
50477-	case FullDocumentDiagnosticReport:
50478-		return json.Marshal(x)
50479-	case UnchangedDocumentDiagnosticReport:
50480-		return json.Marshal(x)
50481-	case nil:
50482-		return []byte("null"), nil
50483-	}
50484-	return nil, fmt.Errorf("type %T not one of [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]", t)
50485-}
50486-
50487-func (t *Or_DocumentDiagnosticReportPartialResult_relatedDocuments_Value) UnmarshalJSON(x []byte) error {
50488-	if string(x) == "null" {
50489-		t.Value = nil
50490-		return nil
50491-	}
50492-	var h0 FullDocumentDiagnosticReport
50493-	if err := json.Unmarshal(x, &h0); err == nil {
50494-		t.Value = h0
50495-		return nil
50496-	}
50497-	var h1 UnchangedDocumentDiagnosticReport
50498-	if err := json.Unmarshal(x, &h1); err == nil {
50499-		t.Value = h1
50500-		return nil
50501-	}
50502-	return &UnmarshalError{"unmarshal failed to match one of [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]"}
50503-}
50504-
50505-// from line 14095
50506-func (t Or_DocumentFilter) MarshalJSON() ([]byte, error) {
50507-	switch x := t.Value.(type) {
50508-	case NotebookCellTextDocumentFilter:
50509-		return json.Marshal(x)
50510-	case TextDocumentFilter:
50511-		return json.Marshal(x)
50512-	case nil:
50513-		return []byte("null"), nil
50514-	}
50515-	return nil, fmt.Errorf("type %T not one of [NotebookCellTextDocumentFilter TextDocumentFilter]", t)
50516-}
50517-
50518-func (t *Or_DocumentFilter) UnmarshalJSON(x []byte) error {
50519-	if string(x) == "null" {
50520-		t.Value = nil
50521-		return nil
50522-	}
50523-	var h0 NotebookCellTextDocumentFilter
50524-	if err := json.Unmarshal(x, &h0); err == nil {
50525-		t.Value = h0
50526-		return nil
50527-	}
50528-	var h1 TextDocumentFilter
50529-	if err := json.Unmarshal(x, &h1); err == nil {
50530-		t.Value = h1
50531-		return nil
50532-	}
50533-	return &UnmarshalError{"unmarshal failed to match one of [NotebookCellTextDocumentFilter TextDocumentFilter]"}
50534-}
50535-
50536-// from line 4891
50537-func (t Or_Hover_contents) MarshalJSON() ([]byte, error) {
50538-	switch x := t.Value.(type) {
50539-	case MarkedString:
50540-		return json.Marshal(x)
50541-	case MarkupContent:
50542-		return json.Marshal(x)
50543-	case []MarkedString:
50544-		return json.Marshal(x)
50545-	case nil:
50546-		return []byte("null"), nil
50547-	}
50548-	return nil, fmt.Errorf("type %T not one of [MarkedString MarkupContent []MarkedString]", t)
50549-}
50550-
50551-func (t *Or_Hover_contents) UnmarshalJSON(x []byte) error {
50552-	if string(x) == "null" {
50553-		t.Value = nil
50554-		return nil
50555-	}
50556-	var h0 MarkedString
50557-	if err := json.Unmarshal(x, &h0); err == nil {
50558-		t.Value = h0
50559-		return nil
50560-	}
50561-	var h1 MarkupContent
50562-	if err := json.Unmarshal(x, &h1); err == nil {
50563-		t.Value = h1
50564-		return nil
50565-	}
50566-	var h2 []MarkedString
50567-	if err := json.Unmarshal(x, &h2); err == nil {
50568-		t.Value = h2
50569-		return nil
50570-	}
50571-	return &UnmarshalError{"unmarshal failed to match one of [MarkedString MarkupContent []MarkedString]"}
50572-}
50573-
50574-// from line 3658
50575-func (t Or_InlayHint_label) MarshalJSON() ([]byte, error) {
50576-	switch x := t.Value.(type) {
50577-	case []InlayHintLabelPart:
50578-		return json.Marshal(x)
50579-	case string:
50580-		return json.Marshal(x)
50581-	case nil:
50582-		return []byte("null"), nil
50583-	}
50584-	return nil, fmt.Errorf("type %T not one of [[]InlayHintLabelPart string]", t)
50585-}
50586-
50587-func (t *Or_InlayHint_label) UnmarshalJSON(x []byte) error {
50588-	if string(x) == "null" {
50589-		t.Value = nil
50590-		return nil
50591-	}
50592-	var h0 []InlayHintLabelPart
50593-	if err := json.Unmarshal(x, &h0); err == nil {
50594-		t.Value = h0
50595-		return nil
50596-	}
50597-	var h1 string
50598-	if err := json.Unmarshal(x, &h1); err == nil {
50599-		t.Value = h1
50600-		return nil
50601-	}
50602-	return &UnmarshalError{"unmarshal failed to match one of [[]InlayHintLabelPart string]"}
50603-}
50604-
50605-// from line 13863
50606-func (t Or_InlineValue) MarshalJSON() ([]byte, error) {
50607-	switch x := t.Value.(type) {
50608-	case InlineValueEvaluatableExpression:
50609-		return json.Marshal(x)
50610-	case InlineValueText:
50611-		return json.Marshal(x)
50612-	case InlineValueVariableLookup:
50613-		return json.Marshal(x)
50614-	case nil:
50615-		return []byte("null"), nil
50616-	}
50617-	return nil, fmt.Errorf("type %T not one of [InlineValueEvaluatableExpression InlineValueText InlineValueVariableLookup]", t)
50618-}
50619-
50620-func (t *Or_InlineValue) UnmarshalJSON(x []byte) error {
50621-	if string(x) == "null" {
50622-		t.Value = nil
50623-		return nil
50624-	}
50625-	var h0 InlineValueEvaluatableExpression
50626-	if err := json.Unmarshal(x, &h0); err == nil {
50627-		t.Value = h0
50628-		return nil
50629-	}
50630-	var h1 InlineValueText
50631-	if err := json.Unmarshal(x, &h1); err == nil {
50632-		t.Value = h1
50633-		return nil
50634-	}
50635-	var h2 InlineValueVariableLookup
50636-	if err := json.Unmarshal(x, &h2); err == nil {
50637-		t.Value = h2
50638-		return nil
50639-	}
50640-	return &UnmarshalError{"unmarshal failed to match one of [InlineValueEvaluatableExpression InlineValueText InlineValueVariableLookup]"}
50641-}
50642-
50643-// from line 14060
50644-func (t Or_MarkedString) MarshalJSON() ([]byte, error) {
50645-	switch x := t.Value.(type) {
50646-	case Msg_MarkedString:
50647-		return json.Marshal(x)
50648-	case string:
50649-		return json.Marshal(x)
50650-	case nil:
50651-		return []byte("null"), nil
50652-	}
50653-	return nil, fmt.Errorf("type %T not one of [Msg_MarkedString string]", t)
50654-}
50655-
50656-func (t *Or_MarkedString) UnmarshalJSON(x []byte) error {
50657-	if string(x) == "null" {
50658-		t.Value = nil
50659-		return nil
50660-	}
50661-	var h0 Msg_MarkedString
50662-	if err := json.Unmarshal(x, &h0); err == nil {
50663-		t.Value = h0
50664-		return nil
50665-	}
50666-	var h1 string
50667-	if err := json.Unmarshal(x, &h1); err == nil {
50668-		t.Value = h1
50669-		return nil
50670-	}
50671-	return &UnmarshalError{"unmarshal failed to match one of [Msg_MarkedString string]"}
50672-}
50673-
50674-// from line 10118
50675-func (t Or_NotebookCellTextDocumentFilter_notebook) MarshalJSON() ([]byte, error) {
50676-	switch x := t.Value.(type) {
50677-	case NotebookDocumentFilter:
50678-		return json.Marshal(x)
50679-	case string:
50680-		return json.Marshal(x)
50681-	case nil:
50682-		return []byte("null"), nil
50683-	}
50684-	return nil, fmt.Errorf("type %T not one of [NotebookDocumentFilter string]", t)
50685-}
50686-
50687-func (t *Or_NotebookCellTextDocumentFilter_notebook) UnmarshalJSON(x []byte) error {
50688-	if string(x) == "null" {
50689-		t.Value = nil
50690-		return nil
50691-	}
50692-	var h0 NotebookDocumentFilter
50693-	if err := json.Unmarshal(x, &h0); err == nil {
50694-		t.Value = h0
50695-		return nil
50696-	}
50697-	var h1 string
50698-	if err := json.Unmarshal(x, &h1); err == nil {
50699-		t.Value = h1
50700-		return nil
50701-	}
50702-	return &UnmarshalError{"unmarshal failed to match one of [NotebookDocumentFilter string]"}
50703-}
50704-
50705-// from line 9857
50706-func (t Or_NotebookDocumentSyncOptions_notebookSelector_Elem_Item1_notebook) MarshalJSON() ([]byte, error) {
50707-	switch x := t.Value.(type) {
50708-	case NotebookDocumentFilter:
50709-		return json.Marshal(x)
50710-	case string:
50711-		return json.Marshal(x)
50712-	case nil:
50713-		return []byte("null"), nil
50714-	}
50715-	return nil, fmt.Errorf("type %T not one of [NotebookDocumentFilter string]", t)
50716-}
50717-
50718-func (t *Or_NotebookDocumentSyncOptions_notebookSelector_Elem_Item1_notebook) UnmarshalJSON(x []byte) error {
50719-	if string(x) == "null" {
50720-		t.Value = nil
50721-		return nil
50722-	}
50723-	var h0 NotebookDocumentFilter
50724-	if err := json.Unmarshal(x, &h0); err == nil {
50725-		t.Value = h0
50726-		return nil
50727-	}
50728-	var h1 string
50729-	if err := json.Unmarshal(x, &h1); err == nil {
50730-		t.Value = h1
50731-		return nil
50732-	}
50733-	return &UnmarshalError{"unmarshal failed to match one of [NotebookDocumentFilter string]"}
50734-}
50735-
50736-// from line 7168
50737-func (t Or_RelatedFullDocumentDiagnosticReport_relatedDocuments_Value) MarshalJSON() ([]byte, error) {
50738-	switch x := t.Value.(type) {
50739-	case FullDocumentDiagnosticReport:
50740-		return json.Marshal(x)
50741-	case UnchangedDocumentDiagnosticReport:
50742-		return json.Marshal(x)
50743-	case nil:
50744-		return []byte("null"), nil
50745-	}
50746-	return nil, fmt.Errorf("type %T not one of [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]", t)
50747-}
50748-
50749-func (t *Or_RelatedFullDocumentDiagnosticReport_relatedDocuments_Value) UnmarshalJSON(x []byte) error {
50750-	if string(x) == "null" {
50751-		t.Value = nil
50752-		return nil
50753-	}
50754-	var h0 FullDocumentDiagnosticReport
50755-	if err := json.Unmarshal(x, &h0); err == nil {
50756-		t.Value = h0
50757-		return nil
50758-	}
50759-	var h1 UnchangedDocumentDiagnosticReport
50760-	if err := json.Unmarshal(x, &h1); err == nil {
50761-		t.Value = h1
50762-		return nil
50763-	}
50764-	return &UnmarshalError{"unmarshal failed to match one of [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]"}
50765-}
50766-
50767-// from line 7207
50768-func (t Or_RelatedUnchangedDocumentDiagnosticReport_relatedDocuments_Value) MarshalJSON() ([]byte, error) {
50769-	switch x := t.Value.(type) {
50770-	case FullDocumentDiagnosticReport:
50771-		return json.Marshal(x)
50772-	case UnchangedDocumentDiagnosticReport:
50773-		return json.Marshal(x)
50774-	case nil:
50775-		return []byte("null"), nil
50776-	}
50777-	return nil, fmt.Errorf("type %T not one of [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]", t)
50778-}
50779-
50780-func (t *Or_RelatedUnchangedDocumentDiagnosticReport_relatedDocuments_Value) UnmarshalJSON(x []byte) error {
50781-	if string(x) == "null" {
50782-		t.Value = nil
50783-		return nil
50784-	}
50785-	var h0 FullDocumentDiagnosticReport
50786-	if err := json.Unmarshal(x, &h0); err == nil {
50787-		t.Value = h0
50788-		return nil
50789-	}
50790-	var h1 UnchangedDocumentDiagnosticReport
50791-	if err := json.Unmarshal(x, &h1); err == nil {
50792-		t.Value = h1
50793-		return nil
50794-	}
50795-	return &UnmarshalError{"unmarshal failed to match one of [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]"}
50796-}
50797-
50798-// from line 10741
50799-func (t Or_RelativePattern_baseUri) MarshalJSON() ([]byte, error) {
50800-	switch x := t.Value.(type) {
50801-	case URI:
50802-		return json.Marshal(x)
50803-	case WorkspaceFolder:
50804-		return json.Marshal(x)
50805-	case nil:
50806-		return []byte("null"), nil
50807-	}
50808-	return nil, fmt.Errorf("type %T not one of [URI WorkspaceFolder]", t)
50809-}
50810-
50811-func (t *Or_RelativePattern_baseUri) UnmarshalJSON(x []byte) error {
50812-	if string(x) == "null" {
50813-		t.Value = nil
50814-		return nil
50815-	}
50816-	var h0 URI
50817-	if err := json.Unmarshal(x, &h0); err == nil {
50818-		t.Value = h0
50819-		return nil
50820-	}
50821-	var h1 WorkspaceFolder
50822-	if err := json.Unmarshal(x, &h1); err == nil {
50823-		t.Value = h1
50824-		return nil
50825-	}
50826-	return &UnmarshalError{"unmarshal failed to match one of [URI WorkspaceFolder]"}
50827-}
50828-
50829-// from line 1371
50830-func (t Or_Result_textDocument_codeAction_Item0_Elem) MarshalJSON() ([]byte, error) {
50831-	switch x := t.Value.(type) {
50832-	case CodeAction:
50833-		return json.Marshal(x)
50834-	case Command:
50835-		return json.Marshal(x)
50836-	case nil:
50837-		return []byte("null"), nil
50838-	}
50839-	return nil, fmt.Errorf("type %T not one of [CodeAction Command]", t)
50840-}
50841-
50842-func (t *Or_Result_textDocument_codeAction_Item0_Elem) UnmarshalJSON(x []byte) error {
50843-	if string(x) == "null" {
50844-		t.Value = nil
50845-		return nil
50846-	}
50847-	var h0 CodeAction
50848-	if err := json.Unmarshal(x, &h0); err == nil {
50849-		t.Value = h0
50850-		return nil
50851-	}
50852-	var h1 Command
50853-	if err := json.Unmarshal(x, &h1); err == nil {
50854-		t.Value = h1
50855-		return nil
50856-	}
50857-	return &UnmarshalError{"unmarshal failed to match one of [CodeAction Command]"}
50858-}
50859-
50860-// from line 12197
50861-func (t Or_SemanticTokensClientCapabilities_requests_full) MarshalJSON() ([]byte, error) {
50862-	switch x := t.Value.(type) {
50863-	case FFullPRequests:
50864-		return json.Marshal(x)
50865-	case bool:
50866-		return json.Marshal(x)
50867-	case nil:
50868-		return []byte("null"), nil
50869-	}
50870-	return nil, fmt.Errorf("type %T not one of [FFullPRequests bool]", t)
50871-}
50872-
50873-func (t *Or_SemanticTokensClientCapabilities_requests_full) UnmarshalJSON(x []byte) error {
50874-	if string(x) == "null" {
50875-		t.Value = nil
50876-		return nil
50877-	}
50878-	var h0 FFullPRequests
50879-	if err := json.Unmarshal(x, &h0); err == nil {
50880-		t.Value = h0
50881-		return nil
50882-	}
50883-	var h1 bool
50884-	if err := json.Unmarshal(x, &h1); err == nil {
50885-		t.Value = h1
50886-		return nil
50887-	}
50888-	return &UnmarshalError{"unmarshal failed to match one of [FFullPRequests bool]"}
50889-}
50890-
50891-// from line 12177
50892-func (t Or_SemanticTokensClientCapabilities_requests_range) MarshalJSON() ([]byte, error) {
50893-	switch x := t.Value.(type) {
50894-	case FRangePRequests:
50895-		return json.Marshal(x)
50896-	case bool:
50897-		return json.Marshal(x)
50898-	case nil:
50899-		return []byte("null"), nil
50900-	}
50901-	return nil, fmt.Errorf("type %T not one of [FRangePRequests bool]", t)
50902-}
50903-
50904-func (t *Or_SemanticTokensClientCapabilities_requests_range) UnmarshalJSON(x []byte) error {
50905-	if string(x) == "null" {
50906-		t.Value = nil
50907-		return nil
50908-	}
50909-	var h0 FRangePRequests
50910-	if err := json.Unmarshal(x, &h0); err == nil {
50911-		t.Value = h0
50912-		return nil
50913-	}
50914-	var h1 bool
50915-	if err := json.Unmarshal(x, &h1); err == nil {
50916-		t.Value = h1
50917-		return nil
50918-	}
50919-	return &UnmarshalError{"unmarshal failed to match one of [FRangePRequests bool]"}
50920-}
50921-
50922-// from line 6579
50923-func (t Or_SemanticTokensOptions_full) MarshalJSON() ([]byte, error) {
50924-	switch x := t.Value.(type) {
50925-	case PFullESemanticTokensOptions:
50926-		return json.Marshal(x)
50927-	case bool:
50928-		return json.Marshal(x)
50929-	case nil:
50930-		return []byte("null"), nil
50931-	}
50932-	return nil, fmt.Errorf("type %T not one of [PFullESemanticTokensOptions bool]", t)
50933-}
50934-
50935-func (t *Or_SemanticTokensOptions_full) UnmarshalJSON(x []byte) error {
50936-	if string(x) == "null" {
50937-		t.Value = nil
50938-		return nil
50939-	}
50940-	var h0 PFullESemanticTokensOptions
50941-	if err := json.Unmarshal(x, &h0); err == nil {
50942-		t.Value = h0
50943-		return nil
50944-	}
50945-	var h1 bool
50946-	if err := json.Unmarshal(x, &h1); err == nil {
50947-		t.Value = h1
50948-		return nil
50949-	}
50950-	return &UnmarshalError{"unmarshal failed to match one of [PFullESemanticTokensOptions bool]"}
50951-}
50952-
50953-// from line 6559
50954-func (t Or_SemanticTokensOptions_range) MarshalJSON() ([]byte, error) {
50955-	switch x := t.Value.(type) {
50956-	case PRangeESemanticTokensOptions:
50957-		return json.Marshal(x)
50958-	case bool:
50959-		return json.Marshal(x)
50960-	case nil:
50961-		return []byte("null"), nil
50962-	}
50963-	return nil, fmt.Errorf("type %T not one of [PRangeESemanticTokensOptions bool]", t)
50964-}
50965-
50966-func (t *Or_SemanticTokensOptions_range) UnmarshalJSON(x []byte) error {
50967-	if string(x) == "null" {
50968-		t.Value = nil
50969-		return nil
50970-	}
50971-	var h0 PRangeESemanticTokensOptions
50972-	if err := json.Unmarshal(x, &h0); err == nil {
50973-		t.Value = h0
50974-		return nil
50975-	}
50976-	var h1 bool
50977-	if err := json.Unmarshal(x, &h1); err == nil {
50978-		t.Value = h1
50979-		return nil
50980-	}
50981-	return &UnmarshalError{"unmarshal failed to match one of [PRangeESemanticTokensOptions bool]"}
50982-}
50983-
50984-// from line 8227
50985-func (t Or_ServerCapabilities_callHierarchyProvider) MarshalJSON() ([]byte, error) {
50986-	switch x := t.Value.(type) {
50987-	case CallHierarchyOptions:
50988-		return json.Marshal(x)
50989-	case CallHierarchyRegistrationOptions:
50990-		return json.Marshal(x)
50991-	case bool:
50992-		return json.Marshal(x)
50993-	case nil:
50994-		return []byte("null"), nil
50995-	}
50996-	return nil, fmt.Errorf("type %T not one of [CallHierarchyOptions CallHierarchyRegistrationOptions bool]", t)
50997-}
50998-
50999-func (t *Or_ServerCapabilities_callHierarchyProvider) UnmarshalJSON(x []byte) error {
51000-	if string(x) == "null" {
51001-		t.Value = nil
51002-		return nil
51003-	}
51004-	var h0 CallHierarchyOptions
51005-	if err := json.Unmarshal(x, &h0); err == nil {
51006-		t.Value = h0
51007-		return nil
51008-	}
51009-	var h1 CallHierarchyRegistrationOptions
51010-	if err := json.Unmarshal(x, &h1); err == nil {
51011-		t.Value = h1
51012-		return nil
51013-	}
51014-	var h2 bool
51015-	if err := json.Unmarshal(x, &h2); err == nil {
51016-		t.Value = h2
51017-		return nil
51018-	}
51019-	return &UnmarshalError{"unmarshal failed to match one of [CallHierarchyOptions CallHierarchyRegistrationOptions bool]"}
51020-}
51021-
51022-// from line 8035
51023-func (t Or_ServerCapabilities_codeActionProvider) MarshalJSON() ([]byte, error) {
51024-	switch x := t.Value.(type) {
51025-	case CodeActionOptions:
51026-		return json.Marshal(x)
51027-	case bool:
51028-		return json.Marshal(x)
51029-	case nil:
51030-		return []byte("null"), nil
51031-	}
51032-	return nil, fmt.Errorf("type %T not one of [CodeActionOptions bool]", t)
51033-}
51034-
51035-func (t *Or_ServerCapabilities_codeActionProvider) UnmarshalJSON(x []byte) error {
51036-	if string(x) == "null" {
51037-		t.Value = nil
51038-		return nil
51039-	}
51040-	var h0 CodeActionOptions
51041-	if err := json.Unmarshal(x, &h0); err == nil {
51042-		t.Value = h0
51043-		return nil
51044-	}
51045-	var h1 bool
51046-	if err := json.Unmarshal(x, &h1); err == nil {
51047-		t.Value = h1
51048-		return nil
51049-	}
51050-	return &UnmarshalError{"unmarshal failed to match one of [CodeActionOptions bool]"}
51051-}
51052-
51053-// from line 8071
51054-func (t Or_ServerCapabilities_colorProvider) MarshalJSON() ([]byte, error) {
51055-	switch x := t.Value.(type) {
51056-	case DocumentColorOptions:
51057-		return json.Marshal(x)
51058-	case DocumentColorRegistrationOptions:
51059-		return json.Marshal(x)
51060-	case bool:
51061-		return json.Marshal(x)
51062-	case nil:
51063-		return []byte("null"), nil
51064-	}
51065-	return nil, fmt.Errorf("type %T not one of [DocumentColorOptions DocumentColorRegistrationOptions bool]", t)
51066-}
51067-
51068-func (t *Or_ServerCapabilities_colorProvider) UnmarshalJSON(x []byte) error {
51069-	if string(x) == "null" {
51070-		t.Value = nil
51071-		return nil
51072-	}
51073-	var h0 DocumentColorOptions
51074-	if err := json.Unmarshal(x, &h0); err == nil {
51075-		t.Value = h0
51076-		return nil
51077-	}
51078-	var h1 DocumentColorRegistrationOptions
51079-	if err := json.Unmarshal(x, &h1); err == nil {
51080-		t.Value = h1
51081-		return nil
51082-	}
51083-	var h2 bool
51084-	if err := json.Unmarshal(x, &h2); err == nil {
51085-		t.Value = h2
51086-		return nil
51087-	}
51088-	return &UnmarshalError{"unmarshal failed to match one of [DocumentColorOptions DocumentColorRegistrationOptions bool]"}
51089-}
51090-
51091-// from line 7897
51092-func (t Or_ServerCapabilities_declarationProvider) MarshalJSON() ([]byte, error) {
51093-	switch x := t.Value.(type) {
51094-	case DeclarationOptions:
51095-		return json.Marshal(x)
51096-	case DeclarationRegistrationOptions:
51097-		return json.Marshal(x)
51098-	case bool:
51099-		return json.Marshal(x)
51100-	case nil:
51101-		return []byte("null"), nil
51102-	}
51103-	return nil, fmt.Errorf("type %T not one of [DeclarationOptions DeclarationRegistrationOptions bool]", t)
51104-}
51105-
51106-func (t *Or_ServerCapabilities_declarationProvider) UnmarshalJSON(x []byte) error {
51107-	if string(x) == "null" {
51108-		t.Value = nil
51109-		return nil
51110-	}
51111-	var h0 DeclarationOptions
51112-	if err := json.Unmarshal(x, &h0); err == nil {
51113-		t.Value = h0
51114-		return nil
51115-	}
51116-	var h1 DeclarationRegistrationOptions
51117-	if err := json.Unmarshal(x, &h1); err == nil {
51118-		t.Value = h1
51119-		return nil
51120-	}
51121-	var h2 bool
51122-	if err := json.Unmarshal(x, &h2); err == nil {
51123-		t.Value = h2
51124-		return nil
51125-	}
51126-	return &UnmarshalError{"unmarshal failed to match one of [DeclarationOptions DeclarationRegistrationOptions bool]"}
51127-}
51128-
51129-// from line 7919
51130-func (t Or_ServerCapabilities_definitionProvider) MarshalJSON() ([]byte, error) {
51131-	switch x := t.Value.(type) {
51132-	case DefinitionOptions:
51133-		return json.Marshal(x)
51134-	case bool:
51135-		return json.Marshal(x)
51136-	case nil:
51137-		return []byte("null"), nil
51138-	}
51139-	return nil, fmt.Errorf("type %T not one of [DefinitionOptions bool]", t)
51140-}
51141-
51142-func (t *Or_ServerCapabilities_definitionProvider) UnmarshalJSON(x []byte) error {
51143-	if string(x) == "null" {
51144-		t.Value = nil
51145-		return nil
51146-	}
51147-	var h0 DefinitionOptions
51148-	if err := json.Unmarshal(x, &h0); err == nil {
51149-		t.Value = h0
51150-		return nil
51151-	}
51152-	var h1 bool
51153-	if err := json.Unmarshal(x, &h1); err == nil {
51154-		t.Value = h1
51155-		return nil
51156-	}
51157-	return &UnmarshalError{"unmarshal failed to match one of [DefinitionOptions bool]"}
51158-}
51159-
51160-// from line 8384
51161-func (t Or_ServerCapabilities_diagnosticProvider) MarshalJSON() ([]byte, error) {
51162-	switch x := t.Value.(type) {
51163-	case DiagnosticOptions:
51164-		return json.Marshal(x)
51165-	case DiagnosticRegistrationOptions:
51166-		return json.Marshal(x)
51167-	case nil:
51168-		return []byte("null"), nil
51169-	}
51170-	return nil, fmt.Errorf("type %T not one of [DiagnosticOptions DiagnosticRegistrationOptions]", t)
51171-}
51172-
51173-func (t *Or_ServerCapabilities_diagnosticProvider) UnmarshalJSON(x []byte) error {
51174-	if string(x) == "null" {
51175-		t.Value = nil
51176-		return nil
51177-	}
51178-	var h0 DiagnosticOptions
51179-	if err := json.Unmarshal(x, &h0); err == nil {
51180-		t.Value = h0
51181-		return nil
51182-	}
51183-	var h1 DiagnosticRegistrationOptions
51184-	if err := json.Unmarshal(x, &h1); err == nil {
51185-		t.Value = h1
51186-		return nil
51187-	}
51188-	return &UnmarshalError{"unmarshal failed to match one of [DiagnosticOptions DiagnosticRegistrationOptions]"}
51189-}
51190-
51191-// from line 8111
51192-func (t Or_ServerCapabilities_documentFormattingProvider) MarshalJSON() ([]byte, error) {
51193-	switch x := t.Value.(type) {
51194-	case DocumentFormattingOptions:
51195-		return json.Marshal(x)
51196-	case bool:
51197-		return json.Marshal(x)
51198-	case nil:
51199-		return []byte("null"), nil
51200-	}
51201-	return nil, fmt.Errorf("type %T not one of [DocumentFormattingOptions bool]", t)
51202-}
51203-
51204-func (t *Or_ServerCapabilities_documentFormattingProvider) UnmarshalJSON(x []byte) error {
51205-	if string(x) == "null" {
51206-		t.Value = nil
51207-		return nil
51208-	}
51209-	var h0 DocumentFormattingOptions
51210-	if err := json.Unmarshal(x, &h0); err == nil {
51211-		t.Value = h0
51212-		return nil
51213-	}
51214-	var h1 bool
51215-	if err := json.Unmarshal(x, &h1); err == nil {
51216-		t.Value = h1
51217-		return nil
51218-	}
51219-	return &UnmarshalError{"unmarshal failed to match one of [DocumentFormattingOptions bool]"}
51220-}
51221-
51222-// from line 7999
51223-func (t Or_ServerCapabilities_documentHighlightProvider) MarshalJSON() ([]byte, error) {
51224-	switch x := t.Value.(type) {
51225-	case DocumentHighlightOptions:
51226-		return json.Marshal(x)
51227-	case bool:
51228-		return json.Marshal(x)
51229-	case nil:
51230-		return []byte("null"), nil
51231-	}
51232-	return nil, fmt.Errorf("type %T not one of [DocumentHighlightOptions bool]", t)
51233-}
51234-
51235-func (t *Or_ServerCapabilities_documentHighlightProvider) UnmarshalJSON(x []byte) error {
51236-	if string(x) == "null" {
51237-		t.Value = nil
51238-		return nil
51239-	}
51240-	var h0 DocumentHighlightOptions
51241-	if err := json.Unmarshal(x, &h0); err == nil {
51242-		t.Value = h0
51243-		return nil
51244-	}
51245-	var h1 bool
51246-	if err := json.Unmarshal(x, &h1); err == nil {
51247-		t.Value = h1
51248-		return nil
51249-	}
51250-	return &UnmarshalError{"unmarshal failed to match one of [DocumentHighlightOptions bool]"}
51251-}
51252-
51253-// from line 8129
51254-func (t Or_ServerCapabilities_documentRangeFormattingProvider) MarshalJSON() ([]byte, error) {
51255-	switch x := t.Value.(type) {
51256-	case DocumentRangeFormattingOptions:
51257-		return json.Marshal(x)
51258-	case bool:
51259-		return json.Marshal(x)
51260-	case nil:
51261-		return []byte("null"), nil
51262-	}
51263-	return nil, fmt.Errorf("type %T not one of [DocumentRangeFormattingOptions bool]", t)
51264-}
51265-
51266-func (t *Or_ServerCapabilities_documentRangeFormattingProvider) UnmarshalJSON(x []byte) error {
51267-	if string(x) == "null" {
51268-		t.Value = nil
51269-		return nil
51270-	}
51271-	var h0 DocumentRangeFormattingOptions
51272-	if err := json.Unmarshal(x, &h0); err == nil {
51273-		t.Value = h0
51274-		return nil
51275-	}
51276-	var h1 bool
51277-	if err := json.Unmarshal(x, &h1); err == nil {
51278-		t.Value = h1
51279-		return nil
51280-	}
51281-	return &UnmarshalError{"unmarshal failed to match one of [DocumentRangeFormattingOptions bool]"}
51282-}
51283-
51284-// from line 8017
51285-func (t Or_ServerCapabilities_documentSymbolProvider) MarshalJSON() ([]byte, error) {
51286-	switch x := t.Value.(type) {
51287-	case DocumentSymbolOptions:
51288-		return json.Marshal(x)
51289-	case bool:
51290-		return json.Marshal(x)
51291-	case nil:
51292-		return []byte("null"), nil
51293-	}
51294-	return nil, fmt.Errorf("type %T not one of [DocumentSymbolOptions bool]", t)
51295-}
51296-
51297-func (t *Or_ServerCapabilities_documentSymbolProvider) UnmarshalJSON(x []byte) error {
51298-	if string(x) == "null" {
51299-		t.Value = nil
51300-		return nil
51301-	}
51302-	var h0 DocumentSymbolOptions
51303-	if err := json.Unmarshal(x, &h0); err == nil {
51304-		t.Value = h0
51305-		return nil
51306-	}
51307-	var h1 bool
51308-	if err := json.Unmarshal(x, &h1); err == nil {
51309-		t.Value = h1
51310-		return nil
51311-	}
51312-	return &UnmarshalError{"unmarshal failed to match one of [DocumentSymbolOptions bool]"}
51313-}
51314-
51315-// from line 8174
51316-func (t Or_ServerCapabilities_foldingRangeProvider) MarshalJSON() ([]byte, error) {
51317-	switch x := t.Value.(type) {
51318-	case FoldingRangeOptions:
51319-		return json.Marshal(x)
51320-	case FoldingRangeRegistrationOptions:
51321-		return json.Marshal(x)
51322-	case bool:
51323-		return json.Marshal(x)
51324-	case nil:
51325-		return []byte("null"), nil
51326-	}
51327-	return nil, fmt.Errorf("type %T not one of [FoldingRangeOptions FoldingRangeRegistrationOptions bool]", t)
51328-}
51329-
51330-func (t *Or_ServerCapabilities_foldingRangeProvider) UnmarshalJSON(x []byte) error {
51331-	if string(x) == "null" {
51332-		t.Value = nil
51333-		return nil
51334-	}
51335-	var h0 FoldingRangeOptions
51336-	if err := json.Unmarshal(x, &h0); err == nil {
51337-		t.Value = h0
51338-		return nil
51339-	}
51340-	var h1 FoldingRangeRegistrationOptions
51341-	if err := json.Unmarshal(x, &h1); err == nil {
51342-		t.Value = h1
51343-		return nil
51344-	}
51345-	var h2 bool
51346-	if err := json.Unmarshal(x, &h2); err == nil {
51347-		t.Value = h2
51348-		return nil
51349-	}
51350-	return &UnmarshalError{"unmarshal failed to match one of [FoldingRangeOptions FoldingRangeRegistrationOptions bool]"}
51351-}
51352-
51353-// from line 7870
51354-func (t Or_ServerCapabilities_hoverProvider) MarshalJSON() ([]byte, error) {
51355-	switch x := t.Value.(type) {
51356-	case HoverOptions:
51357-		return json.Marshal(x)
51358-	case bool:
51359-		return json.Marshal(x)
51360-	case nil:
51361-		return []byte("null"), nil
51362-	}
51363-	return nil, fmt.Errorf("type %T not one of [HoverOptions bool]", t)
51364-}
51365-
51366-func (t *Or_ServerCapabilities_hoverProvider) UnmarshalJSON(x []byte) error {
51367-	if string(x) == "null" {
51368-		t.Value = nil
51369-		return nil
51370-	}
51371-	var h0 HoverOptions
51372-	if err := json.Unmarshal(x, &h0); err == nil {
51373-		t.Value = h0
51374-		return nil
51375-	}
51376-	var h1 bool
51377-	if err := json.Unmarshal(x, &h1); err == nil {
51378-		t.Value = h1
51379-		return nil
51380-	}
51381-	return &UnmarshalError{"unmarshal failed to match one of [HoverOptions bool]"}
51382-}
51383-
51384-// from line 7959
51385-func (t Or_ServerCapabilities_implementationProvider) MarshalJSON() ([]byte, error) {
51386-	switch x := t.Value.(type) {
51387-	case ImplementationOptions:
51388-		return json.Marshal(x)
51389-	case ImplementationRegistrationOptions:
51390-		return json.Marshal(x)
51391-	case bool:
51392-		return json.Marshal(x)
51393-	case nil:
51394-		return []byte("null"), nil
51395-	}
51396-	return nil, fmt.Errorf("type %T not one of [ImplementationOptions ImplementationRegistrationOptions bool]", t)
51397-}
51398-
51399-func (t *Or_ServerCapabilities_implementationProvider) UnmarshalJSON(x []byte) error {
51400-	if string(x) == "null" {
51401-		t.Value = nil
51402-		return nil
51403-	}
51404-	var h0 ImplementationOptions
51405-	if err := json.Unmarshal(x, &h0); err == nil {
51406-		t.Value = h0
51407-		return nil
51408-	}
51409-	var h1 ImplementationRegistrationOptions
51410-	if err := json.Unmarshal(x, &h1); err == nil {
51411-		t.Value = h1
51412-		return nil
51413-	}
51414-	var h2 bool
51415-	if err := json.Unmarshal(x, &h2); err == nil {
51416-		t.Value = h2
51417-		return nil
51418-	}
51419-	return &UnmarshalError{"unmarshal failed to match one of [ImplementationOptions ImplementationRegistrationOptions bool]"}
51420-}
51421-
51422-// from line 8361
51423-func (t Or_ServerCapabilities_inlayHintProvider) MarshalJSON() ([]byte, error) {
51424-	switch x := t.Value.(type) {
51425-	case InlayHintOptions:
51426-		return json.Marshal(x)
51427-	case InlayHintRegistrationOptions:
51428-		return json.Marshal(x)
51429-	case bool:
51430-		return json.Marshal(x)
51431-	case nil:
51432-		return []byte("null"), nil
51433-	}
51434-	return nil, fmt.Errorf("type %T not one of [InlayHintOptions InlayHintRegistrationOptions bool]", t)
51435-}
51436-
51437-func (t *Or_ServerCapabilities_inlayHintProvider) UnmarshalJSON(x []byte) error {
51438-	if string(x) == "null" {
51439-		t.Value = nil
51440-		return nil
51441-	}
51442-	var h0 InlayHintOptions
51443-	if err := json.Unmarshal(x, &h0); err == nil {
51444-		t.Value = h0
51445-		return nil
51446-	}
51447-	var h1 InlayHintRegistrationOptions
51448-	if err := json.Unmarshal(x, &h1); err == nil {
51449-		t.Value = h1
51450-		return nil
51451-	}
51452-	var h2 bool
51453-	if err := json.Unmarshal(x, &h2); err == nil {
51454-		t.Value = h2
51455-		return nil
51456-	}
51457-	return &UnmarshalError{"unmarshal failed to match one of [InlayHintOptions InlayHintRegistrationOptions bool]"}
51458-}
51459-
51460-// from line 8338
51461-func (t Or_ServerCapabilities_inlineValueProvider) MarshalJSON() ([]byte, error) {
51462-	switch x := t.Value.(type) {
51463-	case InlineValueOptions:
51464-		return json.Marshal(x)
51465-	case InlineValueRegistrationOptions:
51466-		return json.Marshal(x)
51467-	case bool:
51468-		return json.Marshal(x)
51469-	case nil:
51470-		return []byte("null"), nil
51471-	}
51472-	return nil, fmt.Errorf("type %T not one of [InlineValueOptions InlineValueRegistrationOptions bool]", t)
51473-}
51474-
51475-func (t *Or_ServerCapabilities_inlineValueProvider) UnmarshalJSON(x []byte) error {
51476-	if string(x) == "null" {
51477-		t.Value = nil
51478-		return nil
51479-	}
51480-	var h0 InlineValueOptions
51481-	if err := json.Unmarshal(x, &h0); err == nil {
51482-		t.Value = h0
51483-		return nil
51484-	}
51485-	var h1 InlineValueRegistrationOptions
51486-	if err := json.Unmarshal(x, &h1); err == nil {
51487-		t.Value = h1
51488-		return nil
51489-	}
51490-	var h2 bool
51491-	if err := json.Unmarshal(x, &h2); err == nil {
51492-		t.Value = h2
51493-		return nil
51494-	}
51495-	return &UnmarshalError{"unmarshal failed to match one of [InlineValueOptions InlineValueRegistrationOptions bool]"}
51496-}
51497-
51498-// from line 8250
51499-func (t Or_ServerCapabilities_linkedEditingRangeProvider) MarshalJSON() ([]byte, error) {
51500-	switch x := t.Value.(type) {
51501-	case LinkedEditingRangeOptions:
51502-		return json.Marshal(x)
51503-	case LinkedEditingRangeRegistrationOptions:
51504-		return json.Marshal(x)
51505-	case bool:
51506-		return json.Marshal(x)
51507-	case nil:
51508-		return []byte("null"), nil
51509-	}
51510-	return nil, fmt.Errorf("type %T not one of [LinkedEditingRangeOptions LinkedEditingRangeRegistrationOptions bool]", t)
51511-}
51512-
51513-func (t *Or_ServerCapabilities_linkedEditingRangeProvider) UnmarshalJSON(x []byte) error {
51514-	if string(x) == "null" {
51515-		t.Value = nil
51516-		return nil
51517-	}
51518-	var h0 LinkedEditingRangeOptions
51519-	if err := json.Unmarshal(x, &h0); err == nil {
51520-		t.Value = h0
51521-		return nil
51522-	}
51523-	var h1 LinkedEditingRangeRegistrationOptions
51524-	if err := json.Unmarshal(x, &h1); err == nil {
51525-		t.Value = h1
51526-		return nil
51527-	}
51528-	var h2 bool
51529-	if err := json.Unmarshal(x, &h2); err == nil {
51530-		t.Value = h2
51531-		return nil
51532-	}
51533-	return &UnmarshalError{"unmarshal failed to match one of [LinkedEditingRangeOptions LinkedEditingRangeRegistrationOptions bool]"}
51534-}
51535-
51536-// from line 8292
51537-func (t Or_ServerCapabilities_monikerProvider) MarshalJSON() ([]byte, error) {
51538-	switch x := t.Value.(type) {
51539-	case MonikerOptions:
51540-		return json.Marshal(x)
51541-	case MonikerRegistrationOptions:
51542-		return json.Marshal(x)
51543-	case bool:
51544-		return json.Marshal(x)
51545-	case nil:
51546-		return []byte("null"), nil
51547-	}
51548-	return nil, fmt.Errorf("type %T not one of [MonikerOptions MonikerRegistrationOptions bool]", t)
51549-}
51550-
51551-func (t *Or_ServerCapabilities_monikerProvider) UnmarshalJSON(x []byte) error {
51552-	if string(x) == "null" {
51553-		t.Value = nil
51554-		return nil
51555-	}
51556-	var h0 MonikerOptions
51557-	if err := json.Unmarshal(x, &h0); err == nil {
51558-		t.Value = h0
51559-		return nil
51560-	}
51561-	var h1 MonikerRegistrationOptions
51562-	if err := json.Unmarshal(x, &h1); err == nil {
51563-		t.Value = h1
51564-		return nil
51565-	}
51566-	var h2 bool
51567-	if err := json.Unmarshal(x, &h2); err == nil {
51568-		t.Value = h2
51569-		return nil
51570-	}
51571-	return &UnmarshalError{"unmarshal failed to match one of [MonikerOptions MonikerRegistrationOptions bool]"}
51572-}
51573-
51574-// from line 7842
51575-func (t Or_ServerCapabilities_notebookDocumentSync) MarshalJSON() ([]byte, error) {
51576-	switch x := t.Value.(type) {
51577-	case NotebookDocumentSyncOptions:
51578-		return json.Marshal(x)
51579-	case NotebookDocumentSyncRegistrationOptions:
51580-		return json.Marshal(x)
51581-	case nil:
51582-		return []byte("null"), nil
51583-	}
51584-	return nil, fmt.Errorf("type %T not one of [NotebookDocumentSyncOptions NotebookDocumentSyncRegistrationOptions]", t)
51585-}
51586-
51587-func (t *Or_ServerCapabilities_notebookDocumentSync) UnmarshalJSON(x []byte) error {
51588-	if string(x) == "null" {
51589-		t.Value = nil
51590-		return nil
51591-	}
51592-	var h0 NotebookDocumentSyncOptions
51593-	if err := json.Unmarshal(x, &h0); err == nil {
51594-		t.Value = h0
51595-		return nil
51596-	}
51597-	var h1 NotebookDocumentSyncRegistrationOptions
51598-	if err := json.Unmarshal(x, &h1); err == nil {
51599-		t.Value = h1
51600-		return nil
51601-	}
51602-	return &UnmarshalError{"unmarshal failed to match one of [NotebookDocumentSyncOptions NotebookDocumentSyncRegistrationOptions]"}
51603-}
51604-
51605-// from line 7981
51606-func (t Or_ServerCapabilities_referencesProvider) MarshalJSON() ([]byte, error) {
51607-	switch x := t.Value.(type) {
51608-	case ReferenceOptions:
51609-		return json.Marshal(x)
51610-	case bool:
51611-		return json.Marshal(x)
51612-	case nil:
51613-		return []byte("null"), nil
51614-	}
51615-	return nil, fmt.Errorf("type %T not one of [ReferenceOptions bool]", t)
51616-}
51617-
51618-func (t *Or_ServerCapabilities_referencesProvider) UnmarshalJSON(x []byte) error {
51619-	if string(x) == "null" {
51620-		t.Value = nil
51621-		return nil
51622-	}
51623-	var h0 ReferenceOptions
51624-	if err := json.Unmarshal(x, &h0); err == nil {
51625-		t.Value = h0
51626-		return nil
51627-	}
51628-	var h1 bool
51629-	if err := json.Unmarshal(x, &h1); err == nil {
51630-		t.Value = h1
51631-		return nil
51632-	}
51633-	return &UnmarshalError{"unmarshal failed to match one of [ReferenceOptions bool]"}
51634-}
51635-
51636-// from line 8156
51637-func (t Or_ServerCapabilities_renameProvider) MarshalJSON() ([]byte, error) {
51638-	switch x := t.Value.(type) {
51639-	case RenameOptions:
51640-		return json.Marshal(x)
51641-	case bool:
51642-		return json.Marshal(x)
51643-	case nil:
51644-		return []byte("null"), nil
51645-	}
51646-	return nil, fmt.Errorf("type %T not one of [RenameOptions bool]", t)
51647-}
51648-
51649-func (t *Or_ServerCapabilities_renameProvider) UnmarshalJSON(x []byte) error {
51650-	if string(x) == "null" {
51651-		t.Value = nil
51652-		return nil
51653-	}
51654-	var h0 RenameOptions
51655-	if err := json.Unmarshal(x, &h0); err == nil {
51656-		t.Value = h0
51657-		return nil
51658-	}
51659-	var h1 bool
51660-	if err := json.Unmarshal(x, &h1); err == nil {
51661-		t.Value = h1
51662-		return nil
51663-	}
51664-	return &UnmarshalError{"unmarshal failed to match one of [RenameOptions bool]"}
51665-}
51666-
51667-// from line 8196
51668-func (t Or_ServerCapabilities_selectionRangeProvider) MarshalJSON() ([]byte, error) {
51669-	switch x := t.Value.(type) {
51670-	case SelectionRangeOptions:
51671-		return json.Marshal(x)
51672-	case SelectionRangeRegistrationOptions:
51673-		return json.Marshal(x)
51674-	case bool:
51675-		return json.Marshal(x)
51676-	case nil:
51677-		return []byte("null"), nil
51678-	}
51679-	return nil, fmt.Errorf("type %T not one of [SelectionRangeOptions SelectionRangeRegistrationOptions bool]", t)
51680-}
51681-
51682-func (t *Or_ServerCapabilities_selectionRangeProvider) UnmarshalJSON(x []byte) error {
51683-	if string(x) == "null" {
51684-		t.Value = nil
51685-		return nil
51686-	}
51687-	var h0 SelectionRangeOptions
51688-	if err := json.Unmarshal(x, &h0); err == nil {
51689-		t.Value = h0
51690-		return nil
51691-	}
51692-	var h1 SelectionRangeRegistrationOptions
51693-	if err := json.Unmarshal(x, &h1); err == nil {
51694-		t.Value = h1
51695-		return nil
51696-	}
51697-	var h2 bool
51698-	if err := json.Unmarshal(x, &h2); err == nil {
51699-		t.Value = h2
51700-		return nil
51701-	}
51702-	return &UnmarshalError{"unmarshal failed to match one of [SelectionRangeOptions SelectionRangeRegistrationOptions bool]"}
51703-}
51704-
51705-// from line 8273
51706-func (t Or_ServerCapabilities_semanticTokensProvider) MarshalJSON() ([]byte, error) {
51707-	switch x := t.Value.(type) {
51708-	case SemanticTokensOptions:
51709-		return json.Marshal(x)
51710-	case SemanticTokensRegistrationOptions:
51711-		return json.Marshal(x)
51712-	case nil:
51713-		return []byte("null"), nil
51714-	}
51715-	return nil, fmt.Errorf("type %T not one of [SemanticTokensOptions SemanticTokensRegistrationOptions]", t)
51716-}
51717-
51718-func (t *Or_ServerCapabilities_semanticTokensProvider) UnmarshalJSON(x []byte) error {
51719-	if string(x) == "null" {
51720-		t.Value = nil
51721-		return nil
51722-	}
51723-	var h0 SemanticTokensOptions
51724-	if err := json.Unmarshal(x, &h0); err == nil {
51725-		t.Value = h0
51726-		return nil
51727-	}
51728-	var h1 SemanticTokensRegistrationOptions
51729-	if err := json.Unmarshal(x, &h1); err == nil {
51730-		t.Value = h1
51731-		return nil
51732-	}
51733-	return &UnmarshalError{"unmarshal failed to match one of [SemanticTokensOptions SemanticTokensRegistrationOptions]"}
51734-}
51735-
51736-// from line 7824
51737-func (t Or_ServerCapabilities_textDocumentSync) MarshalJSON() ([]byte, error) {
51738-	switch x := t.Value.(type) {
51739-	case TextDocumentSyncKind:
51740-		return json.Marshal(x)
51741-	case TextDocumentSyncOptions:
51742-		return json.Marshal(x)
51743-	case nil:
51744-		return []byte("null"), nil
51745-	}
51746-	return nil, fmt.Errorf("type %T not one of [TextDocumentSyncKind TextDocumentSyncOptions]", t)
51747-}
51748-
51749-func (t *Or_ServerCapabilities_textDocumentSync) UnmarshalJSON(x []byte) error {
51750-	if string(x) == "null" {
51751-		t.Value = nil
51752-		return nil
51753-	}
51754-	var h0 TextDocumentSyncKind
51755-	if err := json.Unmarshal(x, &h0); err == nil {
51756-		t.Value = h0
51757-		return nil
51758-	}
51759-	var h1 TextDocumentSyncOptions
51760-	if err := json.Unmarshal(x, &h1); err == nil {
51761-		t.Value = h1
51762-		return nil
51763-	}
51764-	return &UnmarshalError{"unmarshal failed to match one of [TextDocumentSyncKind TextDocumentSyncOptions]"}
51765-}
51766-
51767-// from line 7937
51768-func (t Or_ServerCapabilities_typeDefinitionProvider) MarshalJSON() ([]byte, error) {
51769-	switch x := t.Value.(type) {
51770-	case TypeDefinitionOptions:
51771-		return json.Marshal(x)
51772-	case TypeDefinitionRegistrationOptions:
51773-		return json.Marshal(x)
51774-	case bool:
51775-		return json.Marshal(x)
51776-	case nil:
51777-		return []byte("null"), nil
51778-	}
51779-	return nil, fmt.Errorf("type %T not one of [TypeDefinitionOptions TypeDefinitionRegistrationOptions bool]", t)
51780-}
51781-
51782-func (t *Or_ServerCapabilities_typeDefinitionProvider) UnmarshalJSON(x []byte) error {
51783-	if string(x) == "null" {
51784-		t.Value = nil
51785-		return nil
51786-	}
51787-	var h0 TypeDefinitionOptions
51788-	if err := json.Unmarshal(x, &h0); err == nil {
51789-		t.Value = h0
51790-		return nil
51791-	}
51792-	var h1 TypeDefinitionRegistrationOptions
51793-	if err := json.Unmarshal(x, &h1); err == nil {
51794-		t.Value = h1
51795-		return nil
51796-	}
51797-	var h2 bool
51798-	if err := json.Unmarshal(x, &h2); err == nil {
51799-		t.Value = h2
51800-		return nil
51801-	}
51802-	return &UnmarshalError{"unmarshal failed to match one of [TypeDefinitionOptions TypeDefinitionRegistrationOptions bool]"}
51803-}
51804-
51805-// from line 8315
51806-func (t Or_ServerCapabilities_typeHierarchyProvider) MarshalJSON() ([]byte, error) {
51807-	switch x := t.Value.(type) {
51808-	case TypeHierarchyOptions:
51809-		return json.Marshal(x)
51810-	case TypeHierarchyRegistrationOptions:
51811-		return json.Marshal(x)
51812-	case bool:
51813-		return json.Marshal(x)
51814-	case nil:
51815-		return []byte("null"), nil
51816-	}
51817-	return nil, fmt.Errorf("type %T not one of [TypeHierarchyOptions TypeHierarchyRegistrationOptions bool]", t)
51818-}
51819-
51820-func (t *Or_ServerCapabilities_typeHierarchyProvider) UnmarshalJSON(x []byte) error {
51821-	if string(x) == "null" {
51822-		t.Value = nil
51823-		return nil
51824-	}
51825-	var h0 TypeHierarchyOptions
51826-	if err := json.Unmarshal(x, &h0); err == nil {
51827-		t.Value = h0
51828-		return nil
51829-	}
51830-	var h1 TypeHierarchyRegistrationOptions
51831-	if err := json.Unmarshal(x, &h1); err == nil {
51832-		t.Value = h1
51833-		return nil
51834-	}
51835-	var h2 bool
51836-	if err := json.Unmarshal(x, &h2); err == nil {
51837-		t.Value = h2
51838-		return nil
51839-	}
51840-	return &UnmarshalError{"unmarshal failed to match one of [TypeHierarchyOptions TypeHierarchyRegistrationOptions bool]"}
51841-}
51842-
51843-// from line 8093
51844-func (t Or_ServerCapabilities_workspaceSymbolProvider) MarshalJSON() ([]byte, error) {
51845-	switch x := t.Value.(type) {
51846-	case WorkspaceSymbolOptions:
51847-		return json.Marshal(x)
51848-	case bool:
51849-		return json.Marshal(x)
51850-	case nil:
51851-		return []byte("null"), nil
51852-	}
51853-	return nil, fmt.Errorf("type %T not one of [WorkspaceSymbolOptions bool]", t)
51854-}
51855-
51856-func (t *Or_ServerCapabilities_workspaceSymbolProvider) UnmarshalJSON(x []byte) error {
51857-	if string(x) == "null" {
51858-		t.Value = nil
51859-		return nil
51860-	}
51861-	var h0 WorkspaceSymbolOptions
51862-	if err := json.Unmarshal(x, &h0); err == nil {
51863-		t.Value = h0
51864-		return nil
51865-	}
51866-	var h1 bool
51867-	if err := json.Unmarshal(x, &h1); err == nil {
51868-		t.Value = h1
51869-		return nil
51870-	}
51871-	return &UnmarshalError{"unmarshal failed to match one of [WorkspaceSymbolOptions bool]"}
51872-}
51873-
51874-// from line 8841
51875-func (t Or_SignatureInformation_documentation) MarshalJSON() ([]byte, error) {
51876-	switch x := t.Value.(type) {
51877-	case MarkupContent:
51878-		return json.Marshal(x)
51879-	case string:
51880-		return json.Marshal(x)
51881-	case nil:
51882-		return []byte("null"), nil
51883-	}
51884-	return nil, fmt.Errorf("type %T not one of [MarkupContent string]", t)
51885-}
51886-
51887-func (t *Or_SignatureInformation_documentation) UnmarshalJSON(x []byte) error {
51888-	if string(x) == "null" {
51889-		t.Value = nil
51890-		return nil
51891-	}
51892-	var h0 MarkupContent
51893-	if err := json.Unmarshal(x, &h0); err == nil {
51894-		t.Value = h0
51895-		return nil
51896-	}
51897-	var h1 string
51898-	if err := json.Unmarshal(x, &h1); err == nil {
51899-		t.Value = h1
51900-		return nil
51901-	}
51902-	return &UnmarshalError{"unmarshal failed to match one of [MarkupContent string]"}
51903-}
51904-
51905-// from line 6692
51906-func (t Or_TextDocumentEdit_edits_Elem) MarshalJSON() ([]byte, error) {
51907-	switch x := t.Value.(type) {
51908-	case AnnotatedTextEdit:
51909-		return json.Marshal(x)
51910-	case TextEdit:
51911-		return json.Marshal(x)
51912-	case nil:
51913-		return []byte("null"), nil
51914-	}
51915-	return nil, fmt.Errorf("type %T not one of [AnnotatedTextEdit TextEdit]", t)
51916-}
51917-
51918-func (t *Or_TextDocumentEdit_edits_Elem) UnmarshalJSON(x []byte) error {
51919-	if string(x) == "null" {
51920-		t.Value = nil
51921-		return nil
51922-	}
51923-	var h0 AnnotatedTextEdit
51924-	if err := json.Unmarshal(x, &h0); err == nil {
51925-		t.Value = h0
51926-		return nil
51927-	}
51928-	var h1 TextEdit
51929-	if err := json.Unmarshal(x, &h1); err == nil {
51930-		t.Value = h1
51931-		return nil
51932-	}
51933-	return &UnmarshalError{"unmarshal failed to match one of [AnnotatedTextEdit TextEdit]"}
51934-}
51935-
51936-// from line 9777
51937-func (t Or_TextDocumentSyncOptions_save) MarshalJSON() ([]byte, error) {
51938-	switch x := t.Value.(type) {
51939-	case SaveOptions:
51940-		return json.Marshal(x)
51941-	case bool:
51942-		return json.Marshal(x)
51943-	case nil:
51944-		return []byte("null"), nil
51945-	}
51946-	return nil, fmt.Errorf("type %T not one of [SaveOptions bool]", t)
51947-}
51948-
51949-func (t *Or_TextDocumentSyncOptions_save) UnmarshalJSON(x []byte) error {
51950-	if string(x) == "null" {
51951-		t.Value = nil
51952-		return nil
51953-	}
51954-	var h0 SaveOptions
51955-	if err := json.Unmarshal(x, &h0); err == nil {
51956-		t.Value = h0
51957-		return nil
51958-	}
51959-	var h1 bool
51960-	if err := json.Unmarshal(x, &h1); err == nil {
51961-		t.Value = h1
51962-		return nil
51963-	}
51964-	return &UnmarshalError{"unmarshal failed to match one of [SaveOptions bool]"}
51965-}
51966-
51967-// from line 13986
51968-func (t Or_WorkspaceDocumentDiagnosticReport) MarshalJSON() ([]byte, error) {
51969-	switch x := t.Value.(type) {
51970-	case WorkspaceFullDocumentDiagnosticReport:
51971-		return json.Marshal(x)
51972-	case WorkspaceUnchangedDocumentDiagnosticReport:
51973-		return json.Marshal(x)
51974-	case nil:
51975-		return []byte("null"), nil
51976-	}
51977-	return nil, fmt.Errorf("type %T not one of [WorkspaceFullDocumentDiagnosticReport WorkspaceUnchangedDocumentDiagnosticReport]", t)
51978-}
51979-
51980-func (t *Or_WorkspaceDocumentDiagnosticReport) UnmarshalJSON(x []byte) error {
51981-	if string(x) == "null" {
51982-		t.Value = nil
51983-		return nil
51984-	}
51985-	var h0 WorkspaceFullDocumentDiagnosticReport
51986-	if err := json.Unmarshal(x, &h0); err == nil {
51987-		t.Value = h0
51988-		return nil
51989-	}
51990-	var h1 WorkspaceUnchangedDocumentDiagnosticReport
51991-	if err := json.Unmarshal(x, &h1); err == nil {
51992-		t.Value = h1
51993-		return nil
51994-	}
51995-	return &UnmarshalError{"unmarshal failed to match one of [WorkspaceFullDocumentDiagnosticReport WorkspaceUnchangedDocumentDiagnosticReport]"}
51996-}
51997-
51998-// from line 3219
51999-func (t Or_WorkspaceEdit_documentChanges_Elem) MarshalJSON() ([]byte, error) {
52000-	switch x := t.Value.(type) {
52001-	case CreateFile:
52002-		return json.Marshal(x)
52003-	case DeleteFile:
52004-		return json.Marshal(x)
52005-	case RenameFile:
52006-		return json.Marshal(x)
52007-	case TextDocumentEdit:
52008-		return json.Marshal(x)
52009-	case nil:
52010-		return []byte("null"), nil
52011-	}
52012-	return nil, fmt.Errorf("type %T not one of [CreateFile DeleteFile RenameFile TextDocumentEdit]", t)
52013-}
52014-
52015-func (t *Or_WorkspaceEdit_documentChanges_Elem) UnmarshalJSON(x []byte) error {
52016-	if string(x) == "null" {
52017-		t.Value = nil
52018-		return nil
52019-	}
52020-	var h0 CreateFile
52021-	if err := json.Unmarshal(x, &h0); err == nil {
52022-		t.Value = h0
52023-		return nil
52024-	}
52025-	var h1 DeleteFile
52026-	if err := json.Unmarshal(x, &h1); err == nil {
52027-		t.Value = h1
52028-		return nil
52029-	}
52030-	var h2 RenameFile
52031-	if err := json.Unmarshal(x, &h2); err == nil {
52032-		t.Value = h2
52033-		return nil
52034-	}
52035-	var h3 TextDocumentEdit
52036-	if err := json.Unmarshal(x, &h3); err == nil {
52037-		t.Value = h3
52038-		return nil
52039-	}
52040-	return &UnmarshalError{"unmarshal failed to match one of [CreateFile DeleteFile RenameFile TextDocumentEdit]"}
52041-}
52042-
52043-// from line 248
52044-func (t Or_textDocument_declaration) MarshalJSON() ([]byte, error) {
52045-	switch x := t.Value.(type) {
52046-	case Declaration:
52047-		return json.Marshal(x)
52048-	case []DeclarationLink:
52049-		return json.Marshal(x)
52050-	case nil:
52051-		return []byte("null"), nil
52052-	}
52053-	return nil, fmt.Errorf("type %T not one of [Declaration []DeclarationLink]", t)
52054-}
52055-
52056-func (t *Or_textDocument_declaration) UnmarshalJSON(x []byte) error {
52057-	if string(x) == "null" {
52058-		t.Value = nil
52059-		return nil
52060-	}
52061-	var h0 Declaration
52062-	if err := json.Unmarshal(x, &h0); err == nil {
52063-		t.Value = h0
52064-		return nil
52065-	}
52066-	var h1 []DeclarationLink
52067-	if err := json.Unmarshal(x, &h1); err == nil {
52068-		t.Value = h1
52069-		return nil
52070-	}
52071-	return &UnmarshalError{"unmarshal failed to match one of [Declaration []DeclarationLink]"}
52072-}
52073diff -urN a/gopls/internal/lsp/protocol/tsprotocol.go b/gopls/internal/lsp/protocol/tsprotocol.go
52074--- a/gopls/internal/lsp/protocol/tsprotocol.go	2000-01-01 00:00:00.000000000 -0000
52075+++ b/gopls/internal/lsp/protocol/tsprotocol.go	1970-01-01 00:00:00.000000000 +0000
52076@@ -1,5450 +0,0 @@
52077-// Copyright 2023 The Go Authors. All rights reserved.
52078-// Use of this source code is governed by a BSD-style
52079-// license that can be found in the LICENSE file.
52080-
52081-// Code generated for LSP. DO NOT EDIT.
52082-
52083-package protocol
52084-
52085-// Code generated from protocol/metaModel.json at ref release/protocol/3.17.3-next.6 (hash 56c23c557e3568a9f56f42435fd5a80f9458957f).
52086-// https://github.com/microsoft/vscode-languageserver-node/blob/release/protocol/3.17.3-next.6/protocol/metaModel.json
52087-// LSP metaData.version = 3.17.0.
52088-
52089-import "encoding/json"
52090-
52091-// A special text edit with an additional change annotation.
52092-//
52093-// @since 3.16.0.
52094-type AnnotatedTextEdit struct { // line 9372
52095-	// The actual identifier of the change annotation
52096-	AnnotationID ChangeAnnotationIdentifier `json:"annotationId"`
52097-	TextEdit
52098-}
52099-
52100-// The parameters passed via a apply workspace edit request.
52101-type ApplyWorkspaceEditParams struct { // line 5984
52102-	// An optional label of the workspace edit. This label is
52103-	// presented in the user interface for example on an undo
52104-	// stack to undo the workspace edit.
52105-	Label string `json:"label,omitempty"`
52106-	// The edits to apply.
52107-	Edit WorkspaceEdit `json:"edit"`
52108-}
52109-
52110-// The result returned from the apply workspace edit request.
52111-//
52112-// @since 3.17 renamed from ApplyWorkspaceEditResponse
52113-type ApplyWorkspaceEditResult struct { // line 6007
52114-	// Indicates whether the edit was applied or not.
52115-	Applied bool `json:"applied"`
52116-	// An optional textual description for why the edit was not applied.
52117-	// This may be used by the server for diagnostic logging or to provide
52118-	// a suitable error for a request that triggered the edit.
52119-	FailureReason string `json:"failureReason,omitempty"`
52120-	// Depending on the client's failure handling strategy `failedChange` might
52121-	// contain the index of the change that failed. This property is only available
52122-	// if the client signals a `failureHandlingStrategy` in its client capabilities.
52123-	FailedChange uint32 `json:"failedChange,omitempty"`
52124-}
52125-
52126-// A base for all symbol information.
52127-type BaseSymbolInformation struct { // line 8966
52128-	// The name of this symbol.
52129-	Name string `json:"name"`
52130-	// The kind of this symbol.
52131-	Kind SymbolKind `json:"kind"`
52132-	// Tags for this symbol.
52133-	//
52134-	// @since 3.16.0
52135-	Tags []SymbolTag `json:"tags,omitempty"`
52136-	// The name of the symbol containing this symbol. This information is for
52137-	// user interface purposes (e.g. to render a qualifier in the user interface
52138-	// if necessary). It can't be used to re-infer a hierarchy for the document
52139-	// symbols.
52140-	ContainerName string `json:"containerName,omitempty"`
52141-}
52142-
52143-// @since 3.16.0
52144-type CallHierarchyClientCapabilities struct { // line 12141
52145-	// Whether implementation supports dynamic registration. If this is set to `true`
52146-	// the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
52147-	// return value for the corresponding server capability as well.
52148-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
52149-}
52150-
52151-// Represents an incoming call, e.g. a caller of a method or constructor.
52152-//
52153-// @since 3.16.0
52154-type CallHierarchyIncomingCall struct { // line 2779
52155-	// The item that makes the call.
52156-	From CallHierarchyItem `json:"from"`
52157-	// The ranges at which the calls appear. This is relative to the caller
52158-	// denoted by {@link CallHierarchyIncomingCall.from `this.from`}.
52159-	FromRanges []Range `json:"fromRanges"`
52160-}
52161-
52162-// The parameter of a `callHierarchy/incomingCalls` request.
52163-//
52164-// @since 3.16.0
52165-type CallHierarchyIncomingCallsParams struct { // line 2755
52166-	Item CallHierarchyItem `json:"item"`
52167-	WorkDoneProgressParams
52168-	PartialResultParams
52169-}
52170-
52171-// Represents programming constructs like functions or constructors in the context
52172-// of call hierarchy.
52173-//
52174-// @since 3.16.0
52175-type CallHierarchyItem struct { // line 2656
52176-	// The name of this item.
52177-	Name string `json:"name"`
52178-	// The kind of this item.
52179-	Kind SymbolKind `json:"kind"`
52180-	// Tags for this item.
52181-	Tags []SymbolTag `json:"tags,omitempty"`
52182-	// More detail for this item, e.g. the signature of a function.
52183-	Detail string `json:"detail,omitempty"`
52184-	// The resource identifier of this item.
52185-	URI DocumentURI `json:"uri"`
52186-	// The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code.
52187-	Range Range `json:"range"`
52188-	// The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function.
52189-	// Must be contained by the {@link CallHierarchyItem.range `range`}.
52190-	SelectionRange Range `json:"selectionRange"`
52191-	// A data entry field that is preserved between a call hierarchy prepare and
52192-	// incoming calls or outgoing calls requests.
52193-	Data interface{} `json:"data,omitempty"`
52194-}
52195-
52196-// Call hierarchy options used during static registration.
52197-//
52198-// @since 3.16.0
52199-type CallHierarchyOptions struct { // line 6534
52200-	WorkDoneProgressOptions
52201-}
52202-
52203-// Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc.
52204-//
52205-// @since 3.16.0
52206-type CallHierarchyOutgoingCall struct { // line 2829
52207-	// The item that is called.
52208-	To CallHierarchyItem `json:"to"`
52209-	// The range at which this item is called. This is the range relative to the caller, e.g the item
52210-	// passed to {@link CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls `provideCallHierarchyOutgoingCalls`}
52211-	// and not {@link CallHierarchyOutgoingCall.to `this.to`}.
52212-	FromRanges []Range `json:"fromRanges"`
52213-}
52214-
52215-// The parameter of a `callHierarchy/outgoingCalls` request.
52216-//
52217-// @since 3.16.0
52218-type CallHierarchyOutgoingCallsParams struct { // line 2805
52219-	Item CallHierarchyItem `json:"item"`
52220-	WorkDoneProgressParams
52221-	PartialResultParams
52222-}
52223-
52224-// The parameter of a `textDocument/prepareCallHierarchy` request.
52225-//
52226-// @since 3.16.0
52227-type CallHierarchyPrepareParams struct { // line 2638
52228-	TextDocumentPositionParams
52229-	WorkDoneProgressParams
52230-}
52231-
52232-// Call hierarchy options used during static or dynamic registration.
52233-//
52234-// @since 3.16.0
52235-type CallHierarchyRegistrationOptions struct { // line 2733
52236-	TextDocumentRegistrationOptions
52237-	CallHierarchyOptions
52238-	StaticRegistrationOptions
52239-}
52240-type CancelParams struct { // line 6179
52241-	// The request id to cancel.
52242-	ID interface{} `json:"id"`
52243-}
52244-
52245-// Additional information that describes document changes.
52246-//
52247-// @since 3.16.0
52248-type ChangeAnnotation struct { // line 6831
52249-	// A human-readable string describing the actual change. The string
52250-	// is rendered prominent in the user interface.
52251-	Label string `json:"label"`
52252-	// A flag which indicates that user confirmation is needed
52253-	// before applying the change.
52254-	NeedsConfirmation bool `json:"needsConfirmation,omitempty"`
52255-	// A human-readable string which is rendered less prominent in
52256-	// the user interface.
52257-	Description string `json:"description,omitempty"`
52258-}
52259-
52260-// An identifier to refer to a change annotation stored with a workspace edit.
52261-type ChangeAnnotationIdentifier = string // (alias) line 13976
52262-// Defines the capabilities provided by the client.
52263-type ClientCapabilities struct { // line 9674
52264-	// Workspace specific client capabilities.
52265-	Workspace WorkspaceClientCapabilities `json:"workspace,omitempty"`
52266-	// Text document specific client capabilities.
52267-	TextDocument TextDocumentClientCapabilities `json:"textDocument,omitempty"`
52268-	// Capabilities specific to the notebook document support.
52269-	//
52270-	// @since 3.17.0
52271-	NotebookDocument *NotebookDocumentClientCapabilities `json:"notebookDocument,omitempty"`
52272-	// Window specific client capabilities.
52273-	Window WindowClientCapabilities `json:"window,omitempty"`
52274-	// General client capabilities.
52275-	//
52276-	// @since 3.16.0
52277-	General *GeneralClientCapabilities `json:"general,omitempty"`
52278-	// Experimental client capabilities.
52279-	Experimental interface{} `json:"experimental,omitempty"`
52280-}
52281-
52282-// A code action represents a change that can be performed in code, e.g. to fix a problem or
52283-// to refactor code.
52284-//
52285-// A CodeAction must set either `edit` and/or a `command`. If both are supplied, the `edit` is applied first, then the `command` is executed.
52286-type CodeAction struct { // line 5382
52287-	// A short, human-readable, title for this code action.
52288-	Title string `json:"title"`
52289-	// The kind of the code action.
52290-	//
52291-	// Used to filter code actions.
52292-	Kind CodeActionKind `json:"kind,omitempty"`
52293-	// The diagnostics that this code action resolves.
52294-	Diagnostics []Diagnostic `json:"diagnostics,omitempty"`
52295-	// Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted
52296-	// by keybindings.
52297-	//
52298-	// A quick fix should be marked preferred if it properly addresses the underlying error.
52299-	// A refactoring should be marked preferred if it is the most reasonable choice of actions to take.
52300-	//
52301-	// @since 3.15.0
52302-	IsPreferred bool `json:"isPreferred,omitempty"`
52303-	// Marks that the code action cannot currently be applied.
52304-	//
52305-	// Clients should follow the following guidelines regarding disabled code actions:
52306-	//
52307-	//   - Disabled code actions are not shown in automatic [lightbulbs](https://code.visualstudio.com/docs/editor/editingevolved#_code-action)
52308-	//     code action menus.
52309-	//
52310-	//   - Disabled actions are shown as faded out in the code action menu when the user requests a more specific type
52311-	//     of code action, such as refactorings.
52312-	//
52313-	//   - If the user has a [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions)
52314-	//     that auto applies a code action and only disabled code actions are returned, the client should show the user an
52315-	//     error message with `reason` in the editor.
52316-	//
52317-	// @since 3.16.0
52318-	Disabled *PDisabledMsg_textDocument_codeAction `json:"disabled,omitempty"`
52319-	// The workspace edit this code action performs.
52320-	Edit *WorkspaceEdit `json:"edit,omitempty"`
52321-	// A command this code action executes. If a code action
52322-	// provides an edit and a command, first the edit is
52323-	// executed and then the command.
52324-	Command *Command `json:"command,omitempty"`
52325-	// A data entry field that is preserved on a code action between
52326-	// a `textDocument/codeAction` and a `codeAction/resolve` request.
52327-	//
52328-	// @since 3.16.0
52329-	Data interface{} `json:"data,omitempty"`
52330-}
52331-
52332-// The Client Capabilities of a {@link CodeActionRequest}.
52333-type CodeActionClientCapabilities struct { // line 11721
52334-	// Whether code action supports dynamic registration.
52335-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
52336-	// The client support code action literals of type `CodeAction` as a valid
52337-	// response of the `textDocument/codeAction` request. If the property is not
52338-	// set the request can only return `Command` literals.
52339-	//
52340-	// @since 3.8.0
52341-	CodeActionLiteralSupport PCodeActionLiteralSupportPCodeAction `json:"codeActionLiteralSupport,omitempty"`
52342-	// Whether code action supports the `isPreferred` property.
52343-	//
52344-	// @since 3.15.0
52345-	IsPreferredSupport bool `json:"isPreferredSupport,omitempty"`
52346-	// Whether code action supports the `disabled` property.
52347-	//
52348-	// @since 3.16.0
52349-	DisabledSupport bool `json:"disabledSupport,omitempty"`
52350-	// Whether code action supports the `data` property which is
52351-	// preserved between a `textDocument/codeAction` and a
52352-	// `codeAction/resolve` request.
52353-	//
52354-	// @since 3.16.0
52355-	DataSupport bool `json:"dataSupport,omitempty"`
52356-	// Whether the client supports resolving additional code action
52357-	// properties via a separate `codeAction/resolve` request.
52358-	//
52359-	// @since 3.16.0
52360-	ResolveSupport *PResolveSupportPCodeAction `json:"resolveSupport,omitempty"`
52361-	// Whether the client honors the change annotations in
52362-	// text edits and resource operations returned via the
52363-	// `CodeAction#edit` property by for example presenting
52364-	// the workspace edit in the user interface and asking
52365-	// for confirmation.
52366-	//
52367-	// @since 3.16.0
52368-	HonorsChangeAnnotations bool `json:"honorsChangeAnnotations,omitempty"`
52369-}
52370-
52371-// Contains additional diagnostic information about the context in which
52372-// a {@link CodeActionProvider.provideCodeActions code action} is run.
52373-type CodeActionContext struct { // line 9032
52374-	// An array of diagnostics known on the client side overlapping the range provided to the
52375-	// `textDocument/codeAction` request. They are provided so that the server knows which
52376-	// errors are currently presented to the user for the given range. There is no guarantee
52377-	// that these accurately reflect the error state of the resource. The primary parameter
52378-	// to compute code actions is the provided range.
52379-	Diagnostics []Diagnostic `json:"diagnostics"`
52380-	// Requested kind of actions to return.
52381-	//
52382-	// Actions not of this kind are filtered out by the client before being shown. So servers
52383-	// can omit computing them.
52384-	Only []CodeActionKind `json:"only,omitempty"`
52385-	// The reason why code actions were requested.
52386-	//
52387-	// @since 3.17.0
52388-	TriggerKind *CodeActionTriggerKind `json:"triggerKind,omitempty"`
52389-}
52390-
52391-// A set of predefined code action kinds
52392-type CodeActionKind string // line 13326
52393-// Provider options for a {@link CodeActionRequest}.
52394-type CodeActionOptions struct { // line 9071
52395-	// CodeActionKinds that this server may return.
52396-	//
52397-	// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server
52398-	// may list out every specific kind they provide.
52399-	CodeActionKinds []CodeActionKind `json:"codeActionKinds,omitempty"`
52400-	// The server provides support to resolve additional
52401-	// information for a code action.
52402-	//
52403-	// @since 3.16.0
52404-	ResolveProvider bool `json:"resolveProvider,omitempty"`
52405-	WorkDoneProgressOptions
52406-}
52407-
52408-// The parameters of a {@link CodeActionRequest}.
52409-type CodeActionParams struct { // line 5308
52410-	// The document in which the command was invoked.
52411-	TextDocument TextDocumentIdentifier `json:"textDocument"`
52412-	// The range for which the command was invoked.
52413-	Range Range `json:"range"`
52414-	// Context carrying additional information.
52415-	Context CodeActionContext `json:"context"`
52416-	WorkDoneProgressParams
52417-	PartialResultParams
52418-}
52419-
52420-// Registration options for a {@link CodeActionRequest}.
52421-type CodeActionRegistrationOptions struct { // line 5476
52422-	TextDocumentRegistrationOptions
52423-	CodeActionOptions
52424-}
52425-
52426-// The reason why code actions were requested.
52427-//
52428-// @since 3.17.0
52429-type CodeActionTriggerKind uint32 // line 13606
52430-// Structure to capture a description for an error code.
52431-//
52432-// @since 3.16.0
52433-type CodeDescription struct { // line 10026
52434-	// An URI to open with more information about the diagnostic error.
52435-	Href URI `json:"href"`
52436-}
52437-
52438-// A code lens represents a {@link Command command} that should be shown along with
52439-// source text, like the number of references, a way to run tests, etc.
52440-//
52441-// A code lens is _unresolved_ when no command is associated to it. For performance
52442-// reasons the creation of a code lens and resolving should be done in two stages.
52443-type CodeLens struct { // line 5599
52444-	// The range in which this code lens is valid. Should only span a single line.
52445-	Range Range `json:"range"`
52446-	// The command this code lens represents.
52447-	Command *Command `json:"command,omitempty"`
52448-	// A data entry field that is preserved on a code lens item between
52449-	// a {@link CodeLensRequest} and a [CodeLensResolveRequest]
52450-	// (#CodeLensResolveRequest)
52451-	Data interface{} `json:"data,omitempty"`
52452-}
52453-
52454-// The client capabilities  of a {@link CodeLensRequest}.
52455-type CodeLensClientCapabilities struct { // line 11835
52456-	// Whether code lens supports dynamic registration.
52457-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
52458-}
52459-
52460-// Code Lens provider options of a {@link CodeLensRequest}.
52461-type CodeLensOptions struct { // line 9127
52462-	// Code lens has a resolve provider as well.
52463-	ResolveProvider bool `json:"resolveProvider,omitempty"`
52464-	WorkDoneProgressOptions
52465-}
52466-
52467-// The parameters of a {@link CodeLensRequest}.
52468-type CodeLensParams struct { // line 5575
52469-	// The document to request code lens for.
52470-	TextDocument TextDocumentIdentifier `json:"textDocument"`
52471-	WorkDoneProgressParams
52472-	PartialResultParams
52473-}
52474-
52475-// Registration options for a {@link CodeLensRequest}.
52476-type CodeLensRegistrationOptions struct { // line 5631
52477-	TextDocumentRegistrationOptions
52478-	CodeLensOptions
52479-}
52480-
52481-// @since 3.16.0
52482-type CodeLensWorkspaceClientCapabilities struct { // line 10993
52483-	// Whether the client implementation supports a refresh request sent from the
52484-	// server to the client.
52485-	//
52486-	// Note that this event is global and will force the client to refresh all
52487-	// code lenses currently shown. It should be used with absolute care and is
52488-	// useful for situation where a server for example detect a project wide
52489-	// change that requires such a calculation.
52490-	RefreshSupport bool `json:"refreshSupport,omitempty"`
52491-}
52492-
52493-// Represents a color in RGBA space.
52494-type Color struct { // line 6433
52495-	// The red component of this color in the range [0-1].
52496-	Red float64 `json:"red"`
52497-	// The green component of this color in the range [0-1].
52498-	Green float64 `json:"green"`
52499-	// The blue component of this color in the range [0-1].
52500-	Blue float64 `json:"blue"`
52501-	// The alpha component of this color in the range [0-1].
52502-	Alpha float64 `json:"alpha"`
52503-}
52504-
52505-// Represents a color range from a document.
52506-type ColorInformation struct { // line 2239
52507-	// The range in the document where this color appears.
52508-	Range Range `json:"range"`
52509-	// The actual color value for this color range.
52510-	Color Color `json:"color"`
52511-}
52512-type ColorPresentation struct { // line 2321
52513-	// The label of this color presentation. It will be shown on the color
52514-	// picker header. By default this is also the text that is inserted when selecting
52515-	// this color presentation.
52516-	Label string `json:"label"`
52517-	// An {@link TextEdit edit} which is applied to a document when selecting
52518-	// this presentation for the color.  When `falsy` the {@link ColorPresentation.label label}
52519-	// is used.
52520-	TextEdit *TextEdit `json:"textEdit,omitempty"`
52521-	// An optional array of additional {@link TextEdit text edits} that are applied when
52522-	// selecting this color presentation. Edits must not overlap with the main {@link ColorPresentation.textEdit edit} nor with themselves.
52523-	AdditionalTextEdits []TextEdit `json:"additionalTextEdits,omitempty"`
52524-}
52525-
52526-// Parameters for a {@link ColorPresentationRequest}.
52527-type ColorPresentationParams struct { // line 2281
52528-	// The text document.
52529-	TextDocument TextDocumentIdentifier `json:"textDocument"`
52530-	// The color to request presentations for.
52531-	Color Color `json:"color"`
52532-	// The range where the color would be inserted. Serves as a context.
52533-	Range Range `json:"range"`
52534-	WorkDoneProgressParams
52535-	PartialResultParams
52536-}
52537-
52538-// Represents a reference to a command. Provides a title which
52539-// will be used to represent a command in the UI and, optionally,
52540-// an array of arguments which will be passed to the command handler
52541-// function when invoked.
52542-type Command struct { // line 5348
52543-	// Title of the command, like `save`.
52544-	Title string `json:"title"`
52545-	// The identifier of the actual command handler.
52546-	Command string `json:"command"`
52547-	// Arguments that the command handler should be
52548-	// invoked with.
52549-	Arguments []json.RawMessage `json:"arguments,omitempty"`
52550-}
52551-
52552-// Completion client capabilities
52553-type CompletionClientCapabilities struct { // line 11168
52554-	// Whether completion supports dynamic registration.
52555-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
52556-	// The client supports the following `CompletionItem` specific
52557-	// capabilities.
52558-	CompletionItem     PCompletionItemPCompletion      `json:"completionItem,omitempty"`
52559-	CompletionItemKind *PCompletionItemKindPCompletion `json:"completionItemKind,omitempty"`
52560-	// Defines how the client handles whitespace and indentation
52561-	// when accepting a completion item that uses multi line
52562-	// text in either `insertText` or `textEdit`.
52563-	//
52564-	// @since 3.17.0
52565-	InsertTextMode InsertTextMode `json:"insertTextMode,omitempty"`
52566-	// The client supports to send additional context information for a
52567-	// `textDocument/completion` request.
52568-	ContextSupport bool `json:"contextSupport,omitempty"`
52569-	// The client supports the following `CompletionList` specific
52570-	// capabilities.
52571-	//
52572-	// @since 3.17.0
52573-	CompletionList *PCompletionListPCompletion `json:"completionList,omitempty"`
52574-}
52575-
52576-// Contains additional information about the context in which a completion request is triggered.
52577-type CompletionContext struct { // line 8628
52578-	// How the completion was triggered.
52579-	TriggerKind CompletionTriggerKind `json:"triggerKind"`
52580-	// The trigger character (a single character) that has trigger code complete.
52581-	// Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
52582-	TriggerCharacter string `json:"triggerCharacter,omitempty"`
52583-}
52584-
52585-// A completion item represents a text snippet that is
52586-// proposed to complete text that is being typed.
52587-type CompletionItem struct { // line 4528
52588-	// The label of this completion item.
52589-	//
52590-	// The label property is also by default the text that
52591-	// is inserted when selecting this completion.
52592-	//
52593-	// If label details are provided the label itself should
52594-	// be an unqualified name of the completion item.
52595-	Label string `json:"label"`
52596-	// Additional details for the label
52597-	//
52598-	// @since 3.17.0
52599-	LabelDetails *CompletionItemLabelDetails `json:"labelDetails,omitempty"`
52600-	// The kind of this completion item. Based of the kind
52601-	// an icon is chosen by the editor.
52602-	Kind CompletionItemKind `json:"kind,omitempty"`
52603-	// Tags for this completion item.
52604-	//
52605-	// @since 3.15.0
52606-	Tags []CompletionItemTag `json:"tags,omitempty"`
52607-	// A human-readable string with additional information
52608-	// about this item, like type or symbol information.
52609-	Detail string `json:"detail,omitempty"`
52610-	// A human-readable string that represents a doc-comment.
52611-	Documentation *Or_CompletionItem_documentation `json:"documentation,omitempty"`
52612-	// Indicates if this item is deprecated.
52613-	// @deprecated Use `tags` instead.
52614-	Deprecated bool `json:"deprecated,omitempty"`
52615-	// Select this item when showing.
52616-	//
52617-	// *Note* that only one completion item can be selected and that the
52618-	// tool / client decides which item that is. The rule is that the *first*
52619-	// item of those that match best is selected.
52620-	Preselect bool `json:"preselect,omitempty"`
52621-	// A string that should be used when comparing this item
52622-	// with other items. When `falsy` the {@link CompletionItem.label label}
52623-	// is used.
52624-	SortText string `json:"sortText,omitempty"`
52625-	// A string that should be used when filtering a set of
52626-	// completion items. When `falsy` the {@link CompletionItem.label label}
52627-	// is used.
52628-	FilterText string `json:"filterText,omitempty"`
52629-	// A string that should be inserted into a document when selecting
52630-	// this completion. When `falsy` the {@link CompletionItem.label label}
52631-	// is used.
52632-	//
52633-	// The `insertText` is subject to interpretation by the client side.
52634-	// Some tools might not take the string literally. For example
52635-	// VS Code when code complete is requested in this example
52636-	// `con<cursor position>` and a completion item with an `insertText` of
52637-	// `console` is provided it will only insert `sole`. Therefore it is
52638-	// recommended to use `textEdit` instead since it avoids additional client
52639-	// side interpretation.
52640-	InsertText string `json:"insertText,omitempty"`
52641-	// The format of the insert text. The format applies to both the
52642-	// `insertText` property and the `newText` property of a provided
52643-	// `textEdit`. If omitted defaults to `InsertTextFormat.PlainText`.
52644-	//
52645-	// Please note that the insertTextFormat doesn't apply to
52646-	// `additionalTextEdits`.
52647-	InsertTextFormat *InsertTextFormat `json:"insertTextFormat,omitempty"`
52648-	// How whitespace and indentation is handled during completion
52649-	// item insertion. If not provided the clients default value depends on
52650-	// the `textDocument.completion.insertTextMode` client capability.
52651-	//
52652-	// @since 3.16.0
52653-	InsertTextMode *InsertTextMode `json:"insertTextMode,omitempty"`
52654-	// An {@link TextEdit edit} which is applied to a document when selecting
52655-	// this completion. When an edit is provided the value of
52656-	// {@link CompletionItem.insertText insertText} is ignored.
52657-	//
52658-	// Most editors support two different operations when accepting a completion
52659-	// item. One is to insert a completion text and the other is to replace an
52660-	// existing text with a completion text. Since this can usually not be
52661-	// predetermined by a server it can report both ranges. Clients need to
52662-	// signal support for `InsertReplaceEdits` via the
52663-	// `textDocument.completion.insertReplaceSupport` client capability
52664-	// property.
52665-	//
52666-	// *Note 1:* The text edit's range as well as both ranges from an insert
52667-	// replace edit must be a [single line] and they must contain the position
52668-	// at which completion has been requested.
52669-	// *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range
52670-	// must be a prefix of the edit's replace range, that means it must be
52671-	// contained and starting at the same position.
52672-	//
52673-	// @since 3.16.0 additional type `InsertReplaceEdit`
52674-	TextEdit *TextEdit `json:"textEdit,omitempty"`
52675-	// The edit text used if the completion item is part of a CompletionList and
52676-	// CompletionList defines an item default for the text edit range.
52677-	//
52678-	// Clients will only honor this property if they opt into completion list
52679-	// item defaults using the capability `completionList.itemDefaults`.
52680-	//
52681-	// If not provided and a list's default range is provided the label
52682-	// property is used as a text.
52683-	//
52684-	// @since 3.17.0
52685-	TextEditText string `json:"textEditText,omitempty"`
52686-	// An optional array of additional {@link TextEdit text edits} that are applied when
52687-	// selecting this completion. Edits must not overlap (including the same insert position)
52688-	// with the main {@link CompletionItem.textEdit edit} nor with themselves.
52689-	//
52690-	// Additional text edits should be used to change text unrelated to the current cursor position
52691-	// (for example adding an import statement at the top of the file if the completion item will
52692-	// insert an unqualified type).
52693-	AdditionalTextEdits []TextEdit `json:"additionalTextEdits,omitempty"`
52694-	// An optional set of characters that when pressed while this completion is active will accept it first and
52695-	// then type that character. *Note* that all commit characters should have `length=1` and that superfluous
52696-	// characters will be ignored.
52697-	CommitCharacters []string `json:"commitCharacters,omitempty"`
52698-	// An optional {@link Command command} that is executed *after* inserting this completion. *Note* that
52699-	// additional modifications to the current document should be described with the
52700-	// {@link CompletionItem.additionalTextEdits additionalTextEdits}-property.
52701-	Command *Command `json:"command,omitempty"`
52702-	// A data entry field that is preserved on a completion item between a
52703-	// {@link CompletionRequest} and a {@link CompletionResolveRequest}.
52704-	Data interface{} `json:"data,omitempty"`
52705-}
52706-
52707-// The kind of a completion entry.
52708-type CompletionItemKind uint32 // line 13134
52709-// Additional details for a completion item label.
52710-//
52711-// @since 3.17.0
52712-type CompletionItemLabelDetails struct { // line 8651
52713-	// An optional string which is rendered less prominently directly after {@link CompletionItem.label label},
52714-	// without any spacing. Should be used for function signatures and type annotations.
52715-	Detail string `json:"detail,omitempty"`
52716-	// An optional string which is rendered less prominently after {@link CompletionItem.detail}. Should be used
52717-	// for fully qualified names and file paths.
52718-	Description string `json:"description,omitempty"`
52719-}
52720-
52721-// Completion item tags are extra annotations that tweak the rendering of a completion
52722-// item.
52723-//
52724-// @since 3.15.0
52725-type CompletionItemTag uint32 // line 13244
52726-// Represents a collection of {@link CompletionItem completion items} to be presented
52727-// in the editor.
52728-type CompletionList struct { // line 4737
52729-	// This list it not complete. Further typing results in recomputing this list.
52730-	//
52731-	// Recomputed lists have all their items replaced (not appended) in the
52732-	// incomplete completion sessions.
52733-	IsIncomplete bool `json:"isIncomplete"`
52734-	// In many cases the items of an actual completion result share the same
52735-	// value for properties like `commitCharacters` or the range of a text
52736-	// edit. A completion list can therefore define item defaults which will
52737-	// be used if a completion item itself doesn't specify the value.
52738-	//
52739-	// If a completion list specifies a default value and a completion item
52740-	// also specifies a corresponding value the one from the item is used.
52741-	//
52742-	// Servers are only allowed to return default values if the client
52743-	// signals support for this via the `completionList.itemDefaults`
52744-	// capability.
52745-	//
52746-	// @since 3.17.0
52747-	ItemDefaults *PItemDefaultsMsg_textDocument_completion `json:"itemDefaults,omitempty"`
52748-	// The completion items.
52749-	Items []CompletionItem `json:"items"`
52750-}
52751-
52752-// Completion options.
52753-type CompletionOptions struct { // line 8707
52754-	// Most tools trigger completion request automatically without explicitly requesting
52755-	// it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user
52756-	// starts to type an identifier. For example if the user types `c` in a JavaScript file
52757-	// code complete will automatically pop up present `console` besides others as a
52758-	// completion item. Characters that make up identifiers don't need to be listed here.
52759-	//
52760-	// If code complete should automatically be trigger on characters not being valid inside
52761-	// an identifier (for example `.` in JavaScript) list them in `triggerCharacters`.
52762-	TriggerCharacters []string `json:"triggerCharacters,omitempty"`
52763-	// The list of all possible characters that commit a completion. This field can be used
52764-	// if clients don't support individual commit characters per completion item. See
52765-	// `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport`
52766-	//
52767-	// If a server provides both `allCommitCharacters` and commit characters on an individual
52768-	// completion item the ones on the completion item win.
52769-	//
52770-	// @since 3.2.0
52771-	AllCommitCharacters []string `json:"allCommitCharacters,omitempty"`
52772-	// The server provides support to resolve additional
52773-	// information for a completion item.
52774-	ResolveProvider bool `json:"resolveProvider,omitempty"`
52775-	// The server supports the following `CompletionItem` specific
52776-	// capabilities.
52777-	//
52778-	// @since 3.17.0
52779-	CompletionItem *PCompletionItemPCompletionProvider `json:"completionItem,omitempty"`
52780-	WorkDoneProgressOptions
52781-}
52782-
52783-// Completion parameters
52784-type CompletionParams struct { // line 4497
52785-	// The completion context. This is only available it the client specifies
52786-	// to send this using the client capability `textDocument.completion.contextSupport === true`
52787-	Context CompletionContext `json:"context,omitempty"`
52788-	TextDocumentPositionParams
52789-	WorkDoneProgressParams
52790-	PartialResultParams
52791-}
52792-
52793-// Registration options for a {@link CompletionRequest}.
52794-type CompletionRegistrationOptions struct { // line 4854
52795-	TextDocumentRegistrationOptions
52796-	CompletionOptions
52797-}
52798-
52799-// How a completion was triggered
52800-type CompletionTriggerKind uint32 // line 13555
52801-type ConfigurationItem struct {   // line 6396
52802-	// The scope to get the configuration section for.
52803-	ScopeURI string `json:"scopeUri,omitempty"`
52804-	// The configuration section asked for.
52805-	Section string `json:"section,omitempty"`
52806-}
52807-
52808-// The parameters of a configuration request.
52809-type ConfigurationParams struct { // line 2199
52810-	Items []ConfigurationItem `json:"items"`
52811-}
52812-
52813-// Create file operation.
52814-type CreateFile struct { // line 6712
52815-	// A create
52816-	Kind string `json:"kind"`
52817-	// The resource to create.
52818-	URI DocumentURI `json:"uri"`
52819-	// Additional options
52820-	Options *CreateFileOptions `json:"options,omitempty"`
52821-	ResourceOperation
52822-}
52823-
52824-// Options to create a file.
52825-type CreateFileOptions struct { // line 9417
52826-	// Overwrite existing file. Overwrite wins over `ignoreIfExists`
52827-	Overwrite bool `json:"overwrite,omitempty"`
52828-	// Ignore if exists.
52829-	IgnoreIfExists bool `json:"ignoreIfExists,omitempty"`
52830-}
52831-
52832-// The parameters sent in notifications/requests for user-initiated creation of
52833-// files.
52834-//
52835-// @since 3.16.0
52836-type CreateFilesParams struct { // line 3175
52837-	// An array of all files/folders created in this operation.
52838-	Files []FileCreate `json:"files"`
52839-}
52840-
52841-// The declaration of a symbol representation as one or many {@link Location locations}.
52842-type Declaration = []Location // (alias) line 13833
52843-// @since 3.14.0
52844-type DeclarationClientCapabilities struct { // line 11509
52845-	// Whether declaration supports dynamic registration. If this is set to `true`
52846-	// the client supports the new `DeclarationRegistrationOptions` return value
52847-	// for the corresponding server capability as well.
52848-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
52849-	// The client supports additional metadata in the form of declaration links.
52850-	LinkSupport bool `json:"linkSupport,omitempty"`
52851-}
52852-
52853-// Information about where a symbol is declared.
52854-//
52855-// Provides additional metadata over normal {@link Location location} declarations, including the range of
52856-// the declaring symbol.
52857-//
52858-// Servers should prefer returning `DeclarationLink` over `Declaration` if supported
52859-// by the client.
52860-type DeclarationLink = LocationLink // (alias) line 13853
52861-type DeclarationOptions struct {    // line 6491
52862-	WorkDoneProgressOptions
52863-}
52864-type DeclarationParams struct { // line 2494
52865-	TextDocumentPositionParams
52866-	WorkDoneProgressParams
52867-	PartialResultParams
52868-}
52869-type DeclarationRegistrationOptions struct { // line 2514
52870-	DeclarationOptions
52871-	TextDocumentRegistrationOptions
52872-	StaticRegistrationOptions
52873-}
52874-
52875-// The definition of a symbol represented as one or many {@link Location locations}.
52876-// For most programming languages there is only one location at which a symbol is
52877-// defined.
52878-//
52879-// Servers should prefer returning `DefinitionLink` over `Definition` if supported
52880-// by the client.
52881-type Definition = Or_Definition // (alias) line 13751
52882-// Client Capabilities for a {@link DefinitionRequest}.
52883-type DefinitionClientCapabilities struct { // line 11534
52884-	// Whether definition supports dynamic registration.
52885-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
52886-	// The client supports additional metadata in the form of definition links.
52887-	//
52888-	// @since 3.14.0
52889-	LinkSupport bool `json:"linkSupport,omitempty"`
52890-}
52891-
52892-// Information about where a symbol is defined.
52893-//
52894-// Provides additional metadata over normal {@link Location location} definitions, including the range of
52895-// the defining symbol
52896-type DefinitionLink = LocationLink // (alias) line 13771
52897-// Server Capabilities for a {@link DefinitionRequest}.
52898-type DefinitionOptions struct { // line 8919
52899-	WorkDoneProgressOptions
52900-}
52901-
52902-// Parameters for a {@link DefinitionRequest}.
52903-type DefinitionParams struct { // line 5018
52904-	TextDocumentPositionParams
52905-	WorkDoneProgressParams
52906-	PartialResultParams
52907-}
52908-
52909-// Registration options for a {@link DefinitionRequest}.
52910-type DefinitionRegistrationOptions struct { // line 5039
52911-	TextDocumentRegistrationOptions
52912-	DefinitionOptions
52913-}
52914-
52915-// Delete file operation
52916-type DeleteFile struct { // line 6794
52917-	// A delete
52918-	Kind string `json:"kind"`
52919-	// The file to delete.
52920-	URI DocumentURI `json:"uri"`
52921-	// Delete options.
52922-	Options *DeleteFileOptions `json:"options,omitempty"`
52923-	ResourceOperation
52924-}
52925-
52926-// Delete file options
52927-type DeleteFileOptions struct { // line 9465
52928-	// Delete the content recursively if a folder is denoted.
52929-	Recursive bool `json:"recursive,omitempty"`
52930-	// Ignore the operation if the file doesn't exist.
52931-	IgnoreIfNotExists bool `json:"ignoreIfNotExists,omitempty"`
52932-}
52933-
52934-// The parameters sent in notifications/requests for user-initiated deletes of
52935-// files.
52936-//
52937-// @since 3.16.0
52938-type DeleteFilesParams struct { // line 3300
52939-	// An array of all files/folders deleted in this operation.
52940-	Files []FileDelete `json:"files"`
52941-}
52942-
52943-// Represents a diagnostic, such as a compiler error or warning. Diagnostic objects
52944-// are only valid in the scope of a resource.
52945-type Diagnostic struct { // line 8525
52946-	// The range at which the message applies
52947-	Range Range `json:"range"`
52948-	// The diagnostic's severity. Can be omitted. If omitted it is up to the
52949-	// client to interpret diagnostics as error, warning, info or hint.
52950-	Severity DiagnosticSeverity `json:"severity,omitempty"`
52951-	// The diagnostic's code, which usually appear in the user interface.
52952-	Code interface{} `json:"code,omitempty"`
52953-	// An optional property to describe the error code.
52954-	// Requires the code field (above) to be present/not null.
52955-	//
52956-	// @since 3.16.0
52957-	CodeDescription *CodeDescription `json:"codeDescription,omitempty"`
52958-	// A human-readable string describing the source of this
52959-	// diagnostic, e.g. 'typescript' or 'super lint'. It usually
52960-	// appears in the user interface.
52961-	Source string `json:"source,omitempty"`
52962-	// The diagnostic's message. It usually appears in the user interface
52963-	Message string `json:"message"`
52964-	// Additional metadata about the diagnostic.
52965-	//
52966-	// @since 3.15.0
52967-	Tags []DiagnosticTag `json:"tags,omitempty"`
52968-	// An array of related diagnostic information, e.g. when symbol-names within
52969-	// a scope collide all definitions can be marked via this property.
52970-	RelatedInformation []DiagnosticRelatedInformation `json:"relatedInformation,omitempty"`
52971-	// A data entry field that is preserved between a `textDocument/publishDiagnostics`
52972-	// notification and `textDocument/codeAction` request.
52973-	//
52974-	// @since 3.16.0
52975-	Data interface{} `json:"data,omitempty"`
52976-}
52977-
52978-// Client capabilities specific to diagnostic pull requests.
52979-//
52980-// @since 3.17.0
52981-type DiagnosticClientCapabilities struct { // line 12408
52982-	// Whether implementation supports dynamic registration. If this is set to `true`
52983-	// the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
52984-	// return value for the corresponding server capability as well.
52985-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
52986-	// Whether the clients supports related documents for document diagnostic pulls.
52987-	RelatedDocumentSupport bool `json:"relatedDocumentSupport,omitempty"`
52988-}
52989-
52990-// Diagnostic options.
52991-//
52992-// @since 3.17.0
52993-type DiagnosticOptions struct { // line 7293
52994-	// An optional identifier under which the diagnostics are
52995-	// managed by the client.
52996-	Identifier string `json:"identifier,omitempty"`
52997-	// Whether the language has inter file dependencies meaning that
52998-	// editing code in one file can result in a different diagnostic
52999-	// set in another file. Inter file dependencies are common for
53000-	// most programming languages and typically uncommon for linters.
53001-	InterFileDependencies bool `json:"interFileDependencies"`
53002-	// The server provides support for workspace diagnostics as well.
53003-	WorkspaceDiagnostics bool `json:"workspaceDiagnostics"`
53004-	WorkDoneProgressOptions
53005-}
53006-
53007-// Diagnostic registration options.
53008-//
53009-// @since 3.17.0
53010-type DiagnosticRegistrationOptions struct { // line 3855
53011-	TextDocumentRegistrationOptions
53012-	DiagnosticOptions
53013-	StaticRegistrationOptions
53014-}
53015-
53016-// Represents a related message and source code location for a diagnostic. This should be
53017-// used to point to code locations that cause or related to a diagnostics, e.g when duplicating
53018-// a symbol in a scope.
53019-type DiagnosticRelatedInformation struct { // line 10041
53020-	// The location of this related diagnostic information.
53021-	Location Location `json:"location"`
53022-	// The message of this related diagnostic information.
53023-	Message string `json:"message"`
53024-}
53025-
53026-// Cancellation data returned from a diagnostic request.
53027-//
53028-// @since 3.17.0
53029-type DiagnosticServerCancellationData struct { // line 3841
53030-	RetriggerRequest bool `json:"retriggerRequest"`
53031-}
53032-
53033-// The diagnostic's severity.
53034-type DiagnosticSeverity uint32 // line 13504
53035-// The diagnostic tags.
53036-//
53037-// @since 3.15.0
53038-type DiagnosticTag uint32 // line 13534
53039-// Workspace client capabilities specific to diagnostic pull requests.
53040-//
53041-// @since 3.17.0
53042-type DiagnosticWorkspaceClientCapabilities struct { // line 11111
53043-	// Whether the client implementation supports a refresh request sent from
53044-	// the server to the client.
53045-	//
53046-	// Note that this event is global and will force the client to refresh all
53047-	// pulled diagnostics currently shown. It should be used with absolute care and
53048-	// is useful for situation where a server for example detects a project wide
53049-	// change that requires such a calculation.
53050-	RefreshSupport bool `json:"refreshSupport,omitempty"`
53051-}
53052-type DidChangeConfigurationClientCapabilities struct { // line 10837
53053-	// Did change configuration notification supports dynamic registration.
53054-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53055-}
53056-
53057-// The parameters of a change configuration notification.
53058-type DidChangeConfigurationParams struct { // line 4144
53059-	// The actual changed settings
53060-	Settings interface{} `json:"settings"`
53061-}
53062-type DidChangeConfigurationRegistrationOptions struct { // line 4158
53063-	Section *OrPSection_workspace_didChangeConfiguration `json:"section,omitempty"`
53064-}
53065-
53066-// The params sent in a change notebook document notification.
53067-//
53068-// @since 3.17.0
53069-type DidChangeNotebookDocumentParams struct { // line 3974
53070-	// The notebook document that did change. The version number points
53071-	// to the version after all provided changes have been applied. If
53072-	// only the text document content of a cell changes the notebook version
53073-	// doesn't necessarily have to change.
53074-	NotebookDocument VersionedNotebookDocumentIdentifier `json:"notebookDocument"`
53075-	// The actual changes to the notebook document.
53076-	//
53077-	// The changes describe single state changes to the notebook document.
53078-	// So if there are two changes c1 (at array index 0) and c2 (at array
53079-	// index 1) for a notebook in state S then c1 moves the notebook from
53080-	// S to S' and c2 from S' to S''. So c1 is computed on the state S and
53081-	// c2 is computed on the state S'.
53082-	//
53083-	// To mirror the content of a notebook using change events use the following approach:
53084-	//
53085-	//  - start with the same initial content
53086-	//  - apply the 'notebookDocument/didChange' notifications in the order you receive them.
53087-	//  - apply the `NotebookChangeEvent`s in a single notification in the order
53088-	//   you receive them.
53089-	Change NotebookDocumentChangeEvent `json:"change"`
53090-}
53091-
53092-// The change text document notification's parameters.
53093-type DidChangeTextDocumentParams struct { // line 4287
53094-	// The document that did change. The version number points
53095-	// to the version after all provided content changes have
53096-	// been applied.
53097-	TextDocument VersionedTextDocumentIdentifier `json:"textDocument"`
53098-	// The actual content changes. The content changes describe single state changes
53099-	// to the document. So if there are two content changes c1 (at array index 0) and
53100-	// c2 (at array index 1) for a document in state S then c1 moves the document from
53101-	// S to S' and c2 from S' to S''. So c1 is computed on the state S and c2 is computed
53102-	// on the state S'.
53103-	//
53104-	// To mirror the content of a document using change events use the following approach:
53105-	//
53106-	//  - start with the same initial content
53107-	//  - apply the 'textDocument/didChange' notifications in the order you receive them.
53108-	//  - apply the `TextDocumentContentChangeEvent`s in a single notification in the order
53109-	//   you receive them.
53110-	ContentChanges []TextDocumentContentChangeEvent `json:"contentChanges"`
53111-}
53112-type DidChangeWatchedFilesClientCapabilities struct { // line 10851
53113-	// Did change watched files notification supports dynamic registration. Please note
53114-	// that the current protocol doesn't support static configuration for file changes
53115-	// from the server side.
53116-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53117-	// Whether the client has support for {@link  RelativePattern relative pattern}
53118-	// or not.
53119-	//
53120-	// @since 3.17.0
53121-	RelativePatternSupport bool `json:"relativePatternSupport,omitempty"`
53122-}
53123-
53124-// The watched files change notification's parameters.
53125-type DidChangeWatchedFilesParams struct { // line 4428
53126-	// The actual file events.
53127-	Changes []FileEvent `json:"changes"`
53128-}
53129-
53130-// Describe options to be used when registered for text document change events.
53131-type DidChangeWatchedFilesRegistrationOptions struct { // line 4445
53132-	// The watchers to register.
53133-	Watchers []FileSystemWatcher `json:"watchers"`
53134-}
53135-
53136-// The parameters of a `workspace/didChangeWorkspaceFolders` notification.
53137-type DidChangeWorkspaceFoldersParams struct { // line 2185
53138-	// The actual workspace folder change event.
53139-	Event WorkspaceFoldersChangeEvent `json:"event"`
53140-}
53141-
53142-// The params sent in a close notebook document notification.
53143-//
53144-// @since 3.17.0
53145-type DidCloseNotebookDocumentParams struct { // line 4012
53146-	// The notebook document that got closed.
53147-	NotebookDocument NotebookDocumentIdentifier `json:"notebookDocument"`
53148-	// The text documents that represent the content
53149-	// of a notebook cell that got closed.
53150-	CellTextDocuments []TextDocumentIdentifier `json:"cellTextDocuments"`
53151-}
53152-
53153-// The parameters sent in a close text document notification
53154-type DidCloseTextDocumentParams struct { // line 4332
53155-	// The document that was closed.
53156-	TextDocument TextDocumentIdentifier `json:"textDocument"`
53157-}
53158-
53159-// The params sent in an open notebook document notification.
53160-//
53161-// @since 3.17.0
53162-type DidOpenNotebookDocumentParams struct { // line 3948
53163-	// The notebook document that got opened.
53164-	NotebookDocument NotebookDocument `json:"notebookDocument"`
53165-	// The text documents that represent the content
53166-	// of a notebook cell.
53167-	CellTextDocuments []TextDocumentItem `json:"cellTextDocuments"`
53168-}
53169-
53170-// The parameters sent in an open text document notification
53171-type DidOpenTextDocumentParams struct { // line 4273
53172-	// The document that was opened.
53173-	TextDocument TextDocumentItem `json:"textDocument"`
53174-}
53175-
53176-// The params sent in a save notebook document notification.
53177-//
53178-// @since 3.17.0
53179-type DidSaveNotebookDocumentParams struct { // line 3997
53180-	// The notebook document that got saved.
53181-	NotebookDocument NotebookDocumentIdentifier `json:"notebookDocument"`
53182-}
53183-
53184-// The parameters sent in a save text document notification
53185-type DidSaveTextDocumentParams struct { // line 4346
53186-	// The document that was saved.
53187-	TextDocument TextDocumentIdentifier `json:"textDocument"`
53188-	// Optional the content when saved. Depends on the includeText value
53189-	// when the save notification was requested.
53190-	Text *string `json:"text,omitempty"`
53191-}
53192-type DocumentColorClientCapabilities struct { // line 11875
53193-	// Whether implementation supports dynamic registration. If this is set to `true`
53194-	// the client supports the new `DocumentColorRegistrationOptions` return value
53195-	// for the corresponding server capability as well.
53196-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53197-}
53198-type DocumentColorOptions struct { // line 6471
53199-	WorkDoneProgressOptions
53200-}
53201-
53202-// Parameters for a {@link DocumentColorRequest}.
53203-type DocumentColorParams struct { // line 2215
53204-	// The text document.
53205-	TextDocument TextDocumentIdentifier `json:"textDocument"`
53206-	WorkDoneProgressParams
53207-	PartialResultParams
53208-}
53209-type DocumentColorRegistrationOptions struct { // line 2261
53210-	TextDocumentRegistrationOptions
53211-	DocumentColorOptions
53212-	StaticRegistrationOptions
53213-}
53214-
53215-// Parameters of the document diagnostic request.
53216-//
53217-// @since 3.17.0
53218-type DocumentDiagnosticParams struct { // line 3768
53219-	// The text document.
53220-	TextDocument TextDocumentIdentifier `json:"textDocument"`
53221-	// The additional identifier  provided during registration.
53222-	Identifier string `json:"identifier,omitempty"`
53223-	// The result id of a previous response if provided.
53224-	PreviousResultID string `json:"previousResultId,omitempty"`
53225-	WorkDoneProgressParams
53226-	PartialResultParams
53227-}
53228-type DocumentDiagnosticReport = Or_DocumentDiagnosticReport // (alias) line 13909
53229-// The document diagnostic report kinds.
53230-//
53231-// @since 3.17.0
53232-type DocumentDiagnosticReportKind string // line 12722
53233-// A partial result for a document diagnostic report.
53234-//
53235-// @since 3.17.0
53236-type DocumentDiagnosticReportPartialResult struct { // line 3811
53237-	RelatedDocuments map[DocumentURI]interface{} `json:"relatedDocuments"`
53238-}
53239-
53240-// A document filter describes a top level text document or
53241-// a notebook cell document.
53242-//
53243-// @since 3.17.0 - proposed support for NotebookCellTextDocumentFilter.
53244-type DocumentFilter = Or_DocumentFilter // (alias) line 14093
53245-// Client capabilities of a {@link DocumentFormattingRequest}.
53246-type DocumentFormattingClientCapabilities struct { // line 11889
53247-	// Whether formatting supports dynamic registration.
53248-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53249-}
53250-
53251-// Provider options for a {@link DocumentFormattingRequest}.
53252-type DocumentFormattingOptions struct { // line 9221
53253-	WorkDoneProgressOptions
53254-}
53255-
53256-// The parameters of a {@link DocumentFormattingRequest}.
53257-type DocumentFormattingParams struct { // line 5727
53258-	// The document to format.
53259-	TextDocument TextDocumentIdentifier `json:"textDocument"`
53260-	// The format options.
53261-	Options FormattingOptions `json:"options"`
53262-	WorkDoneProgressParams
53263-}
53264-
53265-// Registration options for a {@link DocumentFormattingRequest}.
53266-type DocumentFormattingRegistrationOptions struct { // line 5755
53267-	TextDocumentRegistrationOptions
53268-	DocumentFormattingOptions
53269-}
53270-
53271-// A document highlight is a range inside a text document which deserves
53272-// special attention. Usually a document highlight is visualized by changing
53273-// the background color of its range.
53274-type DocumentHighlight struct { // line 5119
53275-	// The range this highlight applies to.
53276-	Range Range `json:"range"`
53277-	// The highlight kind, default is {@link DocumentHighlightKind.Text text}.
53278-	Kind DocumentHighlightKind `json:"kind,omitempty"`
53279-}
53280-
53281-// Client Capabilities for a {@link DocumentHighlightRequest}.
53282-type DocumentHighlightClientCapabilities struct { // line 11624
53283-	// Whether document highlight supports dynamic registration.
53284-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53285-}
53286-
53287-// A document highlight kind.
53288-type DocumentHighlightKind uint32 // line 13301
53289-// Provider options for a {@link DocumentHighlightRequest}.
53290-type DocumentHighlightOptions struct { // line 8955
53291-	WorkDoneProgressOptions
53292-}
53293-
53294-// Parameters for a {@link DocumentHighlightRequest}.
53295-type DocumentHighlightParams struct { // line 5098
53296-	TextDocumentPositionParams
53297-	WorkDoneProgressParams
53298-	PartialResultParams
53299-}
53300-
53301-// Registration options for a {@link DocumentHighlightRequest}.
53302-type DocumentHighlightRegistrationOptions struct { // line 5142
53303-	TextDocumentRegistrationOptions
53304-	DocumentHighlightOptions
53305-}
53306-
53307-// A document link is a range in a text document that links to an internal or external resource, like another
53308-// text document or a web site.
53309-type DocumentLink struct { // line 5670
53310-	// The range this link applies to.
53311-	Range Range `json:"range"`
53312-	// The uri this link points to. If missing a resolve request is sent later.
53313-	Target string `json:"target,omitempty"`
53314-	// The tooltip text when you hover over this link.
53315-	//
53316-	// If a tooltip is provided, is will be displayed in a string that includes instructions on how to
53317-	// trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary depending on OS,
53318-	// user settings, and localization.
53319-	//
53320-	// @since 3.15.0
53321-	Tooltip string `json:"tooltip,omitempty"`
53322-	// A data entry field that is preserved on a document link between a
53323-	// DocumentLinkRequest and a DocumentLinkResolveRequest.
53324-	Data interface{} `json:"data,omitempty"`
53325-}
53326-
53327-// The client capabilities of a {@link DocumentLinkRequest}.
53328-type DocumentLinkClientCapabilities struct { // line 11850
53329-	// Whether document link supports dynamic registration.
53330-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53331-	// Whether the client supports the `tooltip` property on `DocumentLink`.
53332-	//
53333-	// @since 3.15.0
53334-	TooltipSupport bool `json:"tooltipSupport,omitempty"`
53335-}
53336-
53337-// Provider options for a {@link DocumentLinkRequest}.
53338-type DocumentLinkOptions struct { // line 9148
53339-	// Document links have a resolve provider as well.
53340-	ResolveProvider bool `json:"resolveProvider,omitempty"`
53341-	WorkDoneProgressOptions
53342-}
53343-
53344-// The parameters of a {@link DocumentLinkRequest}.
53345-type DocumentLinkParams struct { // line 5646
53346-	// The document to provide document links for.
53347-	TextDocument TextDocumentIdentifier `json:"textDocument"`
53348-	WorkDoneProgressParams
53349-	PartialResultParams
53350-}
53351-
53352-// Registration options for a {@link DocumentLinkRequest}.
53353-type DocumentLinkRegistrationOptions struct { // line 5712
53354-	TextDocumentRegistrationOptions
53355-	DocumentLinkOptions
53356-}
53357-
53358-// Client capabilities of a {@link DocumentOnTypeFormattingRequest}.
53359-type DocumentOnTypeFormattingClientCapabilities struct { // line 11919
53360-	// Whether on type formatting supports dynamic registration.
53361-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53362-}
53363-
53364-// Provider options for a {@link DocumentOnTypeFormattingRequest}.
53365-type DocumentOnTypeFormattingOptions struct { // line 9243
53366-	// A character on which formatting should be triggered, like `{`.
53367-	FirstTriggerCharacter string `json:"firstTriggerCharacter"`
53368-	// More trigger characters.
53369-	MoreTriggerCharacter []string `json:"moreTriggerCharacter,omitempty"`
53370-}
53371-
53372-// The parameters of a {@link DocumentOnTypeFormattingRequest}.
53373-type DocumentOnTypeFormattingParams struct { // line 5821
53374-	// The document to format.
53375-	TextDocument TextDocumentIdentifier `json:"textDocument"`
53376-	// The position around which the on type formatting should happen.
53377-	// This is not necessarily the exact position where the character denoted
53378-	// by the property `ch` got typed.
53379-	Position Position `json:"position"`
53380-	// The character that has been typed that triggered the formatting
53381-	// on type request. That is not necessarily the last character that
53382-	// got inserted into the document since the client could auto insert
53383-	// characters as well (e.g. like automatic brace completion).
53384-	Ch string `json:"ch"`
53385-	// The formatting options.
53386-	Options FormattingOptions `json:"options"`
53387-}
53388-
53389-// Registration options for a {@link DocumentOnTypeFormattingRequest}.
53390-type DocumentOnTypeFormattingRegistrationOptions struct { // line 5859
53391-	TextDocumentRegistrationOptions
53392-	DocumentOnTypeFormattingOptions
53393-}
53394-
53395-// Client capabilities of a {@link DocumentRangeFormattingRequest}.
53396-type DocumentRangeFormattingClientCapabilities struct { // line 11904
53397-	// Whether range formatting supports dynamic registration.
53398-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53399-}
53400-
53401-// Provider options for a {@link DocumentRangeFormattingRequest}.
53402-type DocumentRangeFormattingOptions struct { // line 9232
53403-	WorkDoneProgressOptions
53404-}
53405-
53406-// The parameters of a {@link DocumentRangeFormattingRequest}.
53407-type DocumentRangeFormattingParams struct { // line 5770
53408-	// The document to format.
53409-	TextDocument TextDocumentIdentifier `json:"textDocument"`
53410-	// The range to format
53411-	Range Range `json:"range"`
53412-	// The format options
53413-	Options FormattingOptions `json:"options"`
53414-	WorkDoneProgressParams
53415-}
53416-
53417-// Registration options for a {@link DocumentRangeFormattingRequest}.
53418-type DocumentRangeFormattingRegistrationOptions struct { // line 5806
53419-	TextDocumentRegistrationOptions
53420-	DocumentRangeFormattingOptions
53421-}
53422-
53423-// A document selector is the combination of one or many document filters.
53424-//
53425-// @sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language: 'json', pattern: '**∕tsconfig.json' }]`;
53426-//
53427-// The use of a string as a document filter is deprecated @since 3.16.0.
53428-type DocumentSelector = []DocumentFilter // (alias) line 13948
53429-// Represents programming constructs like variables, classes, interfaces etc.
53430-// that appear in a document. Document symbols can be hierarchical and they
53431-// have two ranges: one that encloses its definition and one that points to
53432-// its most interesting range, e.g. the range of an identifier.
53433-type DocumentSymbol struct { // line 5211
53434-	// The name of this symbol. Will be displayed in the user interface and therefore must not be
53435-	// an empty string or a string only consisting of white spaces.
53436-	Name string `json:"name"`
53437-	// More detail for this symbol, e.g the signature of a function.
53438-	Detail string `json:"detail,omitempty"`
53439-	// The kind of this symbol.
53440-	Kind SymbolKind `json:"kind"`
53441-	// Tags for this document symbol.
53442-	//
53443-	// @since 3.16.0
53444-	Tags []SymbolTag `json:"tags,omitempty"`
53445-	// Indicates if this symbol is deprecated.
53446-	//
53447-	// @deprecated Use tags instead
53448-	Deprecated bool `json:"deprecated,omitempty"`
53449-	// The range enclosing this symbol not including leading/trailing whitespace but everything else
53450-	// like comments. This information is typically used to determine if the clients cursor is
53451-	// inside the symbol to reveal in the symbol in the UI.
53452-	Range Range `json:"range"`
53453-	// The range that should be selected and revealed when this symbol is being picked, e.g the name of a function.
53454-	// Must be contained by the `range`.
53455-	SelectionRange Range `json:"selectionRange"`
53456-	// Children of this symbol, e.g. properties of a class.
53457-	Children []DocumentSymbol `json:"children,omitempty"`
53458-}
53459-
53460-// Client Capabilities for a {@link DocumentSymbolRequest}.
53461-type DocumentSymbolClientCapabilities struct { // line 11639
53462-	// Whether document symbol supports dynamic registration.
53463-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53464-	// Specific capabilities for the `SymbolKind` in the
53465-	// `textDocument/documentSymbol` request.
53466-	SymbolKind *PSymbolKindPDocumentSymbol `json:"symbolKind,omitempty"`
53467-	// The client supports hierarchical document symbols.
53468-	HierarchicalDocumentSymbolSupport bool `json:"hierarchicalDocumentSymbolSupport,omitempty"`
53469-	// The client supports tags on `SymbolInformation`. Tags are supported on
53470-	// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true.
53471-	// Clients supporting tags have to handle unknown tags gracefully.
53472-	//
53473-	// @since 3.16.0
53474-	TagSupport *PTagSupportPDocumentSymbol `json:"tagSupport,omitempty"`
53475-	// The client supports an additional label presented in the UI when
53476-	// registering a document symbol provider.
53477-	//
53478-	// @since 3.16.0
53479-	LabelSupport bool `json:"labelSupport,omitempty"`
53480-}
53481-
53482-// Provider options for a {@link DocumentSymbolRequest}.
53483-type DocumentSymbolOptions struct { // line 9010
53484-	// A human-readable string that is shown when multiple outlines trees
53485-	// are shown for the same document.
53486-	//
53487-	// @since 3.16.0
53488-	Label string `json:"label,omitempty"`
53489-	WorkDoneProgressOptions
53490-}
53491-
53492-// Parameters for a {@link DocumentSymbolRequest}.
53493-type DocumentSymbolParams struct { // line 5157
53494-	// The text document.
53495-	TextDocument TextDocumentIdentifier `json:"textDocument"`
53496-	WorkDoneProgressParams
53497-	PartialResultParams
53498-}
53499-
53500-// Registration options for a {@link DocumentSymbolRequest}.
53501-type DocumentSymbolRegistrationOptions struct { // line 5293
53502-	TextDocumentRegistrationOptions
53503-	DocumentSymbolOptions
53504-}
53505-type DocumentURI string
53506-
53507-// Predefined error codes.
53508-type ErrorCodes int32 // line 12743
53509-// The client capabilities of a {@link ExecuteCommandRequest}.
53510-type ExecuteCommandClientCapabilities struct { // line 10962
53511-	// Execute command supports dynamic registration.
53512-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53513-}
53514-
53515-// The server capabilities of a {@link ExecuteCommandRequest}.
53516-type ExecuteCommandOptions struct { // line 9291
53517-	// The commands to be executed on the server
53518-	Commands []string `json:"commands"`
53519-	WorkDoneProgressOptions
53520-}
53521-
53522-// The parameters of a {@link ExecuteCommandRequest}.
53523-type ExecuteCommandParams struct { // line 5941
53524-	// The identifier of the actual command handler.
53525-	Command string `json:"command"`
53526-	// Arguments that the command should be invoked with.
53527-	Arguments []json.RawMessage `json:"arguments,omitempty"`
53528-	WorkDoneProgressParams
53529-}
53530-
53531-// Registration options for a {@link ExecuteCommandRequest}.
53532-type ExecuteCommandRegistrationOptions struct { // line 5973
53533-	ExecuteCommandOptions
53534-}
53535-type ExecutionSummary struct { // line 10162
53536-	// A strict monotonically increasing value
53537-	// indicating the execution order of a cell
53538-	// inside a notebook.
53539-	ExecutionOrder uint32 `json:"executionOrder"`
53540-	// Whether the execution was successful or
53541-	// not if known by the client.
53542-	Success bool `json:"success,omitempty"`
53543-}
53544-
53545-// created for Literal (Lit_CodeActionClientCapabilities_codeActionLiteralSupport_codeActionKind)
53546-type FCodeActionKindPCodeActionLiteralSupport struct { // line 11742
53547-	// The code action kind values the client supports. When this
53548-	// property exists the client also guarantees that it will
53549-	// handle values outside its set gracefully and falls back
53550-	// to a default value when unknown.
53551-	ValueSet []CodeActionKind `json:"valueSet"`
53552-}
53553-
53554-// created for Literal (Lit_CompletionList_itemDefaults_editRange_Item1)
53555-type FEditRangePItemDefaults struct { // line 4777
53556-	Insert  Range `json:"insert"`
53557-	Replace Range `json:"replace"`
53558-}
53559-
53560-// created for Literal (Lit_SemanticTokensClientCapabilities_requests_full_Item1)
53561-type FFullPRequests struct { // line 12205
53562-	// The client will send the `textDocument/semanticTokens/full/delta` request if
53563-	// the server provides a corresponding handler.
53564-	Delta bool `json:"delta"`
53565-}
53566-
53567-// created for Literal (Lit_CompletionClientCapabilities_completionItem_insertTextModeSupport)
53568-type FInsertTextModeSupportPCompletionItem struct { // line 11295
53569-	ValueSet []InsertTextMode `json:"valueSet"`
53570-}
53571-
53572-// created for Literal (Lit_SignatureHelpClientCapabilities_signatureInformation_parameterInformation)
53573-type FParameterInformationPSignatureInformation struct { // line 11461
53574-	// The client supports processing label offsets instead of a
53575-	// simple label string.
53576-	//
53577-	// @since 3.14.0
53578-	LabelOffsetSupport bool `json:"labelOffsetSupport,omitempty"`
53579-}
53580-
53581-// created for Literal (Lit_SemanticTokensClientCapabilities_requests_range_Item1)
53582-type FRangePRequests struct { // line 12185
53583-}
53584-
53585-// created for Literal (Lit_CompletionClientCapabilities_completionItem_resolveSupport)
53586-type FResolveSupportPCompletionItem struct { // line 11271
53587-	// The properties that a client can resolve lazily.
53588-	Properties []string `json:"properties"`
53589-}
53590-
53591-// created for Literal (Lit_NotebookDocumentChangeEvent_cells_structure)
53592-type FStructurePCells struct { // line 7487
53593-	// The change to the cell array.
53594-	Array NotebookCellArrayChange `json:"array"`
53595-	// Additional opened cell text documents.
53596-	DidOpen []TextDocumentItem `json:"didOpen,omitempty"`
53597-	// Additional closed cell text documents.
53598-	DidClose []TextDocumentIdentifier `json:"didClose,omitempty"`
53599-}
53600-
53601-// created for Literal (Lit_CompletionClientCapabilities_completionItem_tagSupport)
53602-type FTagSupportPCompletionItem struct { // line 11237
53603-	// The tags supported by the client.
53604-	ValueSet []CompletionItemTag `json:"valueSet"`
53605-}
53606-type FailureHandlingKind string // line 13693
53607-// The file event type
53608-type FileChangeType uint32 // line 13454
53609-// Represents information on a file/folder create.
53610-//
53611-// @since 3.16.0
53612-type FileCreate struct { // line 6662
53613-	// A file:// URI for the location of the file/folder being created.
53614-	URI string `json:"uri"`
53615-}
53616-
53617-// Represents information on a file/folder delete.
53618-//
53619-// @since 3.16.0
53620-type FileDelete struct { // line 6911
53621-	// A file:// URI for the location of the file/folder being deleted.
53622-	URI string `json:"uri"`
53623-}
53624-
53625-// An event describing a file change.
53626-type FileEvent struct { // line 8480
53627-	// The file's uri.
53628-	URI DocumentURI `json:"uri"`
53629-	// The change type.
53630-	Type FileChangeType `json:"type"`
53631-}
53632-
53633-// Capabilities relating to events from file operations by the user in the client.
53634-//
53635-// These events do not come from the file system, they come from user operations
53636-// like renaming a file in the UI.
53637-//
53638-// @since 3.16.0
53639-type FileOperationClientCapabilities struct { // line 11009
53640-	// Whether the client supports dynamic registration for file requests/notifications.
53641-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53642-	// The client has support for sending didCreateFiles notifications.
53643-	DidCreate bool `json:"didCreate,omitempty"`
53644-	// The client has support for sending willCreateFiles requests.
53645-	WillCreate bool `json:"willCreate,omitempty"`
53646-	// The client has support for sending didRenameFiles notifications.
53647-	DidRename bool `json:"didRename,omitempty"`
53648-	// The client has support for sending willRenameFiles requests.
53649-	WillRename bool `json:"willRename,omitempty"`
53650-	// The client has support for sending didDeleteFiles notifications.
53651-	DidDelete bool `json:"didDelete,omitempty"`
53652-	// The client has support for sending willDeleteFiles requests.
53653-	WillDelete bool `json:"willDelete,omitempty"`
53654-}
53655-
53656-// A filter to describe in which file operation requests or notifications
53657-// the server is interested in receiving.
53658-//
53659-// @since 3.16.0
53660-type FileOperationFilter struct { // line 6864
53661-	// A Uri scheme like `file` or `untitled`.
53662-	Scheme string `json:"scheme,omitempty"`
53663-	// The actual file operation pattern.
53664-	Pattern FileOperationPattern `json:"pattern"`
53665-}
53666-
53667-// Options for notifications/requests for user operations on files.
53668-//
53669-// @since 3.16.0
53670-type FileOperationOptions struct { // line 9965
53671-	// The server is interested in receiving didCreateFiles notifications.
53672-	DidCreate *FileOperationRegistrationOptions `json:"didCreate,omitempty"`
53673-	// The server is interested in receiving willCreateFiles requests.
53674-	WillCreate *FileOperationRegistrationOptions `json:"willCreate,omitempty"`
53675-	// The server is interested in receiving didRenameFiles notifications.
53676-	DidRename *FileOperationRegistrationOptions `json:"didRename,omitempty"`
53677-	// The server is interested in receiving willRenameFiles requests.
53678-	WillRename *FileOperationRegistrationOptions `json:"willRename,omitempty"`
53679-	// The server is interested in receiving didDeleteFiles file notifications.
53680-	DidDelete *FileOperationRegistrationOptions `json:"didDelete,omitempty"`
53681-	// The server is interested in receiving willDeleteFiles file requests.
53682-	WillDelete *FileOperationRegistrationOptions `json:"willDelete,omitempty"`
53683-}
53684-
53685-// A pattern to describe in which file operation requests or notifications
53686-// the server is interested in receiving.
53687-//
53688-// @since 3.16.0
53689-type FileOperationPattern struct { // line 9489
53690-	// The glob pattern to match. Glob patterns can have the following syntax:
53691-	//
53692-	//  - `*` to match one or more characters in a path segment
53693-	//  - `?` to match on one character in a path segment
53694-	//  - `**` to match any number of path segments, including none
53695-	//  - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files)
53696-	//  - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
53697-	//  - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
53698-	Glob string `json:"glob"`
53699-	// Whether to match files or folders with this pattern.
53700-	//
53701-	// Matches both if undefined.
53702-	Matches *FileOperationPatternKind `json:"matches,omitempty"`
53703-	// Additional options used during matching.
53704-	Options *FileOperationPatternOptions `json:"options,omitempty"`
53705-}
53706-
53707-// A pattern kind describing if a glob pattern matches a file a folder or
53708-// both.
53709-//
53710-// @since 3.16.0
53711-type FileOperationPatternKind string // line 13627
53712-// Matching options for the file operation pattern.
53713-//
53714-// @since 3.16.0
53715-type FileOperationPatternOptions struct { // line 10146
53716-	// The pattern should be matched ignoring casing.
53717-	IgnoreCase bool `json:"ignoreCase,omitempty"`
53718-}
53719-
53720-// The options to register for file operations.
53721-//
53722-// @since 3.16.0
53723-type FileOperationRegistrationOptions struct { // line 3264
53724-	// The actual filters.
53725-	Filters []FileOperationFilter `json:"filters"`
53726-}
53727-
53728-// Represents information on a file/folder rename.
53729-//
53730-// @since 3.16.0
53731-type FileRename struct { // line 6888
53732-	// A file:// URI for the original location of the file/folder being renamed.
53733-	OldURI string `json:"oldUri"`
53734-	// A file:// URI for the new location of the file/folder being renamed.
53735-	NewURI string `json:"newUri"`
53736-}
53737-type FileSystemWatcher struct { // line 8502
53738-	// The glob pattern to watch. See {@link GlobPattern glob pattern} for more detail.
53739-	//
53740-	// @since 3.17.0 support for relative patterns.
53741-	GlobPattern GlobPattern `json:"globPattern"`
53742-	// The kind of events of interest. If omitted it defaults
53743-	// to WatchKind.Create | WatchKind.Change | WatchKind.Delete
53744-	// which is 7.
53745-	Kind *WatchKind `json:"kind,omitempty"`
53746-}
53747-
53748-// Represents a folding range. To be valid, start and end line must be bigger than zero and smaller
53749-// than the number of lines in the document. Clients are free to ignore invalid ranges.
53750-type FoldingRange struct { // line 2415
53751-	// The zero-based start line of the range to fold. The folded area starts after the line's last character.
53752-	// To be valid, the end must be zero or larger and smaller than the number of lines in the document.
53753-	StartLine uint32 `json:"startLine"`
53754-	// The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line.
53755-	StartCharacter uint32 `json:"startCharacter,omitempty"`
53756-	// The zero-based end line of the range to fold. The folded area ends with the line's last character.
53757-	// To be valid, the end must be zero or larger and smaller than the number of lines in the document.
53758-	EndLine uint32 `json:"endLine"`
53759-	// The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line.
53760-	EndCharacter uint32 `json:"endCharacter,omitempty"`
53761-	// Describes the kind of the folding range such as `comment' or 'region'. The kind
53762-	// is used to categorize folding ranges and used by commands like 'Fold all comments'.
53763-	// See {@link FoldingRangeKind} for an enumeration of standardized kinds.
53764-	Kind string `json:"kind,omitempty"`
53765-	// The text that the client should show when the specified range is
53766-	// collapsed. If not defined or not supported by the client, a default
53767-	// will be chosen by the client.
53768-	//
53769-	// @since 3.17.0
53770-	CollapsedText string `json:"collapsedText,omitempty"`
53771-}
53772-type FoldingRangeClientCapabilities struct { // line 11978
53773-	// Whether implementation supports dynamic registration for folding range
53774-	// providers. If this is set to `true` the client supports the new
53775-	// `FoldingRangeRegistrationOptions` return value for the corresponding
53776-	// server capability as well.
53777-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53778-	// The maximum number of folding ranges that the client prefers to receive
53779-	// per document. The value serves as a hint, servers are free to follow the
53780-	// limit.
53781-	RangeLimit uint32 `json:"rangeLimit,omitempty"`
53782-	// If set, the client signals that it only supports folding complete lines.
53783-	// If set, client will ignore specified `startCharacter` and `endCharacter`
53784-	// properties in a FoldingRange.
53785-	LineFoldingOnly bool `json:"lineFoldingOnly,omitempty"`
53786-	// Specific options for the folding range kind.
53787-	//
53788-	// @since 3.17.0
53789-	FoldingRangeKind *PFoldingRangeKindPFoldingRange `json:"foldingRangeKind,omitempty"`
53790-	// Specific options for the folding range.
53791-	//
53792-	// @since 3.17.0
53793-	FoldingRange *PFoldingRangePFoldingRange `json:"foldingRange,omitempty"`
53794-}
53795-
53796-// A set of predefined range kinds.
53797-type FoldingRangeKind string      // line 12815
53798-type FoldingRangeOptions struct { // line 6481
53799-	WorkDoneProgressOptions
53800-}
53801-
53802-// Parameters for a {@link FoldingRangeRequest}.
53803-type FoldingRangeParams struct { // line 2391
53804-	// The text document.
53805-	TextDocument TextDocumentIdentifier `json:"textDocument"`
53806-	WorkDoneProgressParams
53807-	PartialResultParams
53808-}
53809-type FoldingRangeRegistrationOptions struct { // line 2474
53810-	TextDocumentRegistrationOptions
53811-	FoldingRangeOptions
53812-	StaticRegistrationOptions
53813-}
53814-
53815-// Value-object describing what options formatting should use.
53816-type FormattingOptions struct { // line 9169
53817-	// Size of a tab in spaces.
53818-	TabSize uint32 `json:"tabSize"`
53819-	// Prefer spaces over tabs.
53820-	InsertSpaces bool `json:"insertSpaces"`
53821-	// Trim trailing whitespace on a line.
53822-	//
53823-	// @since 3.15.0
53824-	TrimTrailingWhitespace bool `json:"trimTrailingWhitespace,omitempty"`
53825-	// Insert a newline character at the end of the file if one does not exist.
53826-	//
53827-	// @since 3.15.0
53828-	InsertFinalNewline bool `json:"insertFinalNewline,omitempty"`
53829-	// Trim all newlines after the final newline at the end of the file.
53830-	//
53831-	// @since 3.15.0
53832-	TrimFinalNewlines bool `json:"trimFinalNewlines,omitempty"`
53833-}
53834-
53835-// A diagnostic report with a full set of problems.
53836-//
53837-// @since 3.17.0
53838-type FullDocumentDiagnosticReport struct { // line 7235
53839-	// A full document diagnostic report.
53840-	Kind string `json:"kind"`
53841-	// An optional result id. If provided it will
53842-	// be sent on the next diagnostic request for the
53843-	// same document.
53844-	ResultID string `json:"resultId,omitempty"`
53845-	// The actual items.
53846-	Items []Diagnostic `json:"items"`
53847-}
53848-
53849-// General client capabilities.
53850-//
53851-// @since 3.16.0
53852-type GeneralClientCapabilities struct { // line 10664
53853-	// Client capability that signals how the client
53854-	// handles stale requests (e.g. a request
53855-	// for which the client will not process the response
53856-	// anymore since the information is outdated).
53857-	//
53858-	// @since 3.17.0
53859-	StaleRequestSupport *PStaleRequestSupportPGeneral `json:"staleRequestSupport,omitempty"`
53860-	// Client capabilities specific to regular expressions.
53861-	//
53862-	// @since 3.16.0
53863-	RegularExpressions *RegularExpressionsClientCapabilities `json:"regularExpressions,omitempty"`
53864-	// Client capabilities specific to the client's markdown parser.
53865-	//
53866-	// @since 3.16.0
53867-	Markdown *MarkdownClientCapabilities `json:"markdown,omitempty"`
53868-	// The position encodings supported by the client. Client and server
53869-	// have to agree on the same position encoding to ensure that offsets
53870-	// (e.g. character position in a line) are interpreted the same on both
53871-	// sides.
53872-	//
53873-	// To keep the protocol backwards compatible the following applies: if
53874-	// the value 'utf-16' is missing from the array of position encodings
53875-	// servers can assume that the client supports UTF-16. UTF-16 is
53876-	// therefore a mandatory encoding.
53877-	//
53878-	// If omitted it defaults to ['utf-16'].
53879-	//
53880-	// Implementation considerations: since the conversion from one encoding
53881-	// into another requires the content of the file / line the conversion
53882-	// is best done where the file is read which is usually on the server
53883-	// side.
53884-	//
53885-	// @since 3.17.0
53886-	PositionEncodings []PositionEncodingKind `json:"positionEncodings,omitempty"`
53887-}
53888-
53889-// The glob pattern. Either a string pattern or a relative pattern.
53890-//
53891-// @since 3.17.0
53892-type GlobPattern = string // (alias) line 14127
53893-// The result of a hover request.
53894-type Hover struct { // line 4886
53895-	// The hover's content
53896-	Contents MarkupContent `json:"contents"`
53897-	// An optional range inside the text document that is used to
53898-	// visualize the hover, e.g. by changing the background color.
53899-	Range Range `json:"range,omitempty"`
53900-}
53901-type HoverClientCapabilities struct { // line 11402
53902-	// Whether hover supports dynamic registration.
53903-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53904-	// Client supports the following content formats for the content
53905-	// property. The order describes the preferred format of the client.
53906-	ContentFormat []MarkupKind `json:"contentFormat,omitempty"`
53907-}
53908-
53909-// Hover options.
53910-type HoverOptions struct { // line 8776
53911-	WorkDoneProgressOptions
53912-}
53913-
53914-// Parameters for a {@link HoverRequest}.
53915-type HoverParams struct { // line 4869
53916-	TextDocumentPositionParams
53917-	WorkDoneProgressParams
53918-}
53919-
53920-// Registration options for a {@link HoverRequest}.
53921-type HoverRegistrationOptions struct { // line 4925
53922-	TextDocumentRegistrationOptions
53923-	HoverOptions
53924-}
53925-
53926-// @since 3.6.0
53927-type ImplementationClientCapabilities struct { // line 11583
53928-	// Whether implementation supports dynamic registration. If this is set to `true`
53929-	// the client supports the new `ImplementationRegistrationOptions` return value
53930-	// for the corresponding server capability as well.
53931-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
53932-	// The client supports additional metadata in the form of definition links.
53933-	//
53934-	// @since 3.14.0
53935-	LinkSupport bool `json:"linkSupport,omitempty"`
53936-}
53937-type ImplementationOptions struct { // line 6333
53938-	WorkDoneProgressOptions
53939-}
53940-type ImplementationParams struct { // line 2063
53941-	TextDocumentPositionParams
53942-	WorkDoneProgressParams
53943-	PartialResultParams
53944-}
53945-type ImplementationRegistrationOptions struct { // line 2103
53946-	TextDocumentRegistrationOptions
53947-	ImplementationOptions
53948-	StaticRegistrationOptions
53949-}
53950-
53951-// The data type of the ResponseError if the
53952-// initialize request fails.
53953-type InitializeError struct { // line 4126
53954-	// Indicates whether the client execute the following retry logic:
53955-	// (1) show the message provided by the ResponseError to the user
53956-	// (2) user selects retry or cancel
53957-	// (3) if user selected retry the initialize method is sent again.
53958-	Retry bool `json:"retry"`
53959-}
53960-type InitializeParams struct { // line 4068
53961-	XInitializeParams
53962-	WorkspaceFoldersInitializeParams
53963-}
53964-
53965-// The result returned from an initialize request.
53966-type InitializeResult struct { // line 4082
53967-	// The capabilities the language server provides.
53968-	Capabilities ServerCapabilities `json:"capabilities"`
53969-	// Information about the server.
53970-	//
53971-	// @since 3.15.0
53972-	ServerInfo *PServerInfoMsg_initialize `json:"serverInfo,omitempty"`
53973-}
53974-type InitializedParams struct { // line 4140
53975-}
53976-
53977-// Inlay hint information.
53978-//
53979-// @since 3.17.0
53980-type InlayHint struct { // line 3645
53981-	// The position of this hint.
53982-	Position Position `json:"position"`
53983-	// The label of this hint. A human readable string or an array of
53984-	// InlayHintLabelPart label parts.
53985-	//
53986-	// *Note* that neither the string nor the label part can be empty.
53987-	Label []InlayHintLabelPart `json:"label"`
53988-	// The kind of this hint. Can be omitted in which case the client
53989-	// should fall back to a reasonable default.
53990-	Kind InlayHintKind `json:"kind,omitempty"`
53991-	// Optional text edits that are performed when accepting this inlay hint.
53992-	//
53993-	// *Note* that edits are expected to change the document so that the inlay
53994-	// hint (or its nearest variant) is now part of the document and the inlay
53995-	// hint itself is now obsolete.
53996-	TextEdits []TextEdit `json:"textEdits,omitempty"`
53997-	// The tooltip text when you hover over this item.
53998-	Tooltip *OrPTooltip_textDocument_inlayHint `json:"tooltip,omitempty"`
53999-	// Render padding before the hint.
54000-	//
54001-	// Note: Padding should use the editor's background color, not the
54002-	// background color of the hint itself. That means padding can be used
54003-	// to visually align/separate an inlay hint.
54004-	PaddingLeft bool `json:"paddingLeft,omitempty"`
54005-	// Render padding after the hint.
54006-	//
54007-	// Note: Padding should use the editor's background color, not the
54008-	// background color of the hint itself. That means padding can be used
54009-	// to visually align/separate an inlay hint.
54010-	PaddingRight bool `json:"paddingRight,omitempty"`
54011-	// A data entry field that is preserved on an inlay hint between
54012-	// a `textDocument/inlayHint` and a `inlayHint/resolve` request.
54013-	Data interface{} `json:"data,omitempty"`
54014-}
54015-
54016-// Inlay hint client capabilities.
54017-//
54018-// @since 3.17.0
54019-type InlayHintClientCapabilities struct { // line 12369
54020-	// Whether inlay hints support dynamic registration.
54021-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
54022-	// Indicates which properties a client can resolve lazily on an inlay
54023-	// hint.
54024-	ResolveSupport *PResolveSupportPInlayHint `json:"resolveSupport,omitempty"`
54025-}
54026-
54027-// Inlay hint kinds.
54028-//
54029-// @since 3.17.0
54030-type InlayHintKind uint32 // line 13033
54031-// An inlay hint label part allows for interactive and composite labels
54032-// of inlay hints.
54033-//
54034-// @since 3.17.0
54035-type InlayHintLabelPart struct { // line 7062
54036-	// The value of this label part.
54037-	Value string `json:"value"`
54038-	// The tooltip text when you hover over this label part. Depending on
54039-	// the client capability `inlayHint.resolveSupport` clients might resolve
54040-	// this property late using the resolve request.
54041-	Tooltip *OrPTooltipPLabel `json:"tooltip,omitempty"`
54042-	// An optional source code location that represents this
54043-	// label part.
54044-	//
54045-	// The editor will use this location for the hover and for code navigation
54046-	// features: This part will become a clickable link that resolves to the
54047-	// definition of the symbol at the given location (not necessarily the
54048-	// location itself), it shows the hover that shows at the given location,
54049-	// and it shows a context menu with further code navigation commands.
54050-	//
54051-	// Depending on the client capability `inlayHint.resolveSupport` clients
54052-	// might resolve this property late using the resolve request.
54053-	Location *Location `json:"location,omitempty"`
54054-	// An optional command for this label part.
54055-	//
54056-	// Depending on the client capability `inlayHint.resolveSupport` clients
54057-	// might resolve this property late using the resolve request.
54058-	Command *Command `json:"command,omitempty"`
54059-}
54060-
54061-// Inlay hint options used during static registration.
54062-//
54063-// @since 3.17.0
54064-type InlayHintOptions struct { // line 7135
54065-	// The server provides support to resolve additional
54066-	// information for an inlay hint item.
54067-	ResolveProvider bool `json:"resolveProvider,omitempty"`
54068-	WorkDoneProgressOptions
54069-}
54070-
54071-// A parameter literal used in inlay hint requests.
54072-//
54073-// @since 3.17.0
54074-type InlayHintParams struct { // line 3616
54075-	// The text document.
54076-	TextDocument TextDocumentIdentifier `json:"textDocument"`
54077-	// The document range for which inlay hints should be computed.
54078-	Range Range `json:"range"`
54079-	WorkDoneProgressParams
54080-}
54081-
54082-// Inlay hint options used during static or dynamic registration.
54083-//
54084-// @since 3.17.0
54085-type InlayHintRegistrationOptions struct { // line 3746
54086-	InlayHintOptions
54087-	TextDocumentRegistrationOptions
54088-	StaticRegistrationOptions
54089-}
54090-
54091-// Client workspace capabilities specific to inlay hints.
54092-//
54093-// @since 3.17.0
54094-type InlayHintWorkspaceClientCapabilities struct { // line 11095
54095-	// Whether the client implementation supports a refresh request sent from
54096-	// the server to the client.
54097-	//
54098-	// Note that this event is global and will force the client to refresh all
54099-	// inlay hints currently shown. It should be used with absolute care and
54100-	// is useful for situation where a server for example detects a project wide
54101-	// change that requires such a calculation.
54102-	RefreshSupport bool `json:"refreshSupport,omitempty"`
54103-}
54104-
54105-// Inline value information can be provided by different means:
54106-//
54107-//   - directly as a text value (class InlineValueText).
54108-//   - as a name to use for a variable lookup (class InlineValueVariableLookup)
54109-//   - as an evaluatable expression (class InlineValueEvaluatableExpression)
54110-//
54111-// The InlineValue types combines all inline value types into one type.
54112-//
54113-// @since 3.17.0
54114-type InlineValue = Or_InlineValue // (alias) line 13861
54115-// Client capabilities specific to inline values.
54116-//
54117-// @since 3.17.0
54118-type InlineValueClientCapabilities struct { // line 12353
54119-	// Whether implementation supports dynamic registration for inline value providers.
54120-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
54121-}
54122-
54123-// @since 3.17.0
54124-type InlineValueContext struct { // line 6948
54125-	// The stack frame (as a DAP Id) where the execution has stopped.
54126-	FrameID int32 `json:"frameId"`
54127-	// The document range where execution has stopped.
54128-	// Typically the end position of the range denotes the line where the inline values are shown.
54129-	StoppedLocation Range `json:"stoppedLocation"`
54130-}
54131-
54132-// Provide an inline value through an expression evaluation.
54133-// If only a range is specified, the expression will be extracted from the underlying document.
54134-// An optional expression can be used to override the extracted expression.
54135-//
54136-// @since 3.17.0
54137-type InlineValueEvaluatableExpression struct { // line 7026
54138-	// The document range for which the inline value applies.
54139-	// The range is used to extract the evaluatable expression from the underlying document.
54140-	Range Range `json:"range"`
54141-	// If specified the expression overrides the extracted expression.
54142-	Expression string `json:"expression,omitempty"`
54143-}
54144-
54145-// Inline value options used during static registration.
54146-//
54147-// @since 3.17.0
54148-type InlineValueOptions struct { // line 7050
54149-	WorkDoneProgressOptions
54150-}
54151-
54152-// A parameter literal used in inline value requests.
54153-//
54154-// @since 3.17.0
54155-type InlineValueParams struct { // line 3557
54156-	// The text document.
54157-	TextDocument TextDocumentIdentifier `json:"textDocument"`
54158-	// The document range for which inline values should be computed.
54159-	Range Range `json:"range"`
54160-	// Additional information about the context in which inline values were
54161-	// requested.
54162-	Context InlineValueContext `json:"context"`
54163-	WorkDoneProgressParams
54164-}
54165-
54166-// Inline value options used during static or dynamic registration.
54167-//
54168-// @since 3.17.0
54169-type InlineValueRegistrationOptions struct { // line 3594
54170-	InlineValueOptions
54171-	TextDocumentRegistrationOptions
54172-	StaticRegistrationOptions
54173-}
54174-
54175-// Provide inline value as text.
54176-//
54177-// @since 3.17.0
54178-type InlineValueText struct { // line 6971
54179-	// The document range for which the inline value applies.
54180-	Range Range `json:"range"`
54181-	// The text of the inline value.
54182-	Text string `json:"text"`
54183-}
54184-
54185-// Provide inline value through a variable lookup.
54186-// If only a range is specified, the variable name will be extracted from the underlying document.
54187-// An optional variable name can be used to override the extracted name.
54188-//
54189-// @since 3.17.0
54190-type InlineValueVariableLookup struct { // line 6994
54191-	// The document range for which the inline value applies.
54192-	// The range is used to extract the variable name from the underlying document.
54193-	Range Range `json:"range"`
54194-	// If specified the name of the variable to look up.
54195-	VariableName string `json:"variableName,omitempty"`
54196-	// How to perform the lookup.
54197-	CaseSensitiveLookup bool `json:"caseSensitiveLookup"`
54198-}
54199-
54200-// Client workspace capabilities specific to inline values.
54201-//
54202-// @since 3.17.0
54203-type InlineValueWorkspaceClientCapabilities struct { // line 11079
54204-	// Whether the client implementation supports a refresh request sent from the
54205-	// server to the client.
54206-	//
54207-	// Note that this event is global and will force the client to refresh all
54208-	// inline values currently shown. It should be used with absolute care and is
54209-	// useful for situation where a server for example detects a project wide
54210-	// change that requires such a calculation.
54211-	RefreshSupport bool `json:"refreshSupport,omitempty"`
54212-}
54213-
54214-// A special text edit to provide an insert and a replace operation.
54215-//
54216-// @since 3.16.0
54217-type InsertReplaceEdit struct { // line 8676
54218-	// The string to be inserted.
54219-	NewText string `json:"newText"`
54220-	// The range if the insert is requested
54221-	Insert Range `json:"insert"`
54222-	// The range if the replace is requested.
54223-	Replace Range `json:"replace"`
54224-}
54225-
54226-// Defines whether the insert text in a completion item should be interpreted as
54227-// plain text or a snippet.
54228-type InsertTextFormat uint32 // line 13260
54229-// How whitespace and indentation is handled during completion
54230-// item insertion.
54231-//
54232-// @since 3.16.0
54233-type InsertTextMode uint32 // line 13280
54234-type LSPAny = interface{}
54235-
54236-// LSP arrays.
54237-// @since 3.17.0
54238-type LSPArray = []interface{} // (alias) line 13779
54239-type LSPErrorCodes int32      // line 12783
54240-// LSP object definition.
54241-// @since 3.17.0
54242-type LSPObject = map[string]LSPAny // (alias) line 14111
54243-// Client capabilities for the linked editing range request.
54244-//
54245-// @since 3.16.0
54246-type LinkedEditingRangeClientCapabilities struct { // line 12305
54247-	// Whether implementation supports dynamic registration. If this is set to `true`
54248-	// the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
54249-	// return value for the corresponding server capability as well.
54250-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
54251-}
54252-type LinkedEditingRangeOptions struct { // line 6652
54253-	WorkDoneProgressOptions
54254-}
54255-type LinkedEditingRangeParams struct { // line 3112
54256-	TextDocumentPositionParams
54257-	WorkDoneProgressParams
54258-}
54259-type LinkedEditingRangeRegistrationOptions struct { // line 3155
54260-	TextDocumentRegistrationOptions
54261-	LinkedEditingRangeOptions
54262-	StaticRegistrationOptions
54263-}
54264-
54265-// The result of a linked editing range request.
54266-//
54267-// @since 3.16.0
54268-type LinkedEditingRanges struct { // line 3128
54269-	// A list of ranges that can be edited together. The ranges must have
54270-	// identical length and contain identical text content. The ranges cannot overlap.
54271-	Ranges []Range `json:"ranges"`
54272-	// An optional word pattern (regular expression) that describes valid contents for
54273-	// the given ranges. If no pattern is provided, the client configuration's word
54274-	// pattern will be used.
54275-	WordPattern string `json:"wordPattern,omitempty"`
54276-}
54277-
54278-// created for Literal (Lit_NotebookDocumentChangeEvent_cells_textContent_Elem)
54279-type Lit_NotebookDocumentChangeEvent_cells_textContent_Elem struct { // line 7545
54280-	Document VersionedTextDocumentIdentifier  `json:"document"`
54281-	Changes  []TextDocumentContentChangeEvent `json:"changes"`
54282-}
54283-
54284-// created for Literal (Lit_NotebookDocumentFilter_Item1)
54285-type Lit_NotebookDocumentFilter_Item1 struct { // line 14293
54286-	// The type of the enclosing notebook.
54287-	NotebookType string `json:"notebookType,omitempty"`
54288-	// A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.
54289-	Scheme string `json:"scheme"`
54290-	// A glob pattern.
54291-	Pattern string `json:"pattern,omitempty"`
54292-}
54293-
54294-// created for Literal (Lit_NotebookDocumentFilter_Item2)
54295-type Lit_NotebookDocumentFilter_Item2 struct { // line 14326
54296-	// The type of the enclosing notebook.
54297-	NotebookType string `json:"notebookType,omitempty"`
54298-	// A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.
54299-	Scheme string `json:"scheme,omitempty"`
54300-	// A glob pattern.
54301-	Pattern string `json:"pattern"`
54302-}
54303-
54304-// created for Literal (Lit_NotebookDocumentSyncOptions_notebookSelector_Elem_Item0_cells_Elem)
54305-type Lit_NotebookDocumentSyncOptions_notebookSelector_Elem_Item0_cells_Elem struct { // line 9831
54306-	Language string `json:"language"`
54307-}
54308-
54309-// created for Literal (Lit_NotebookDocumentSyncOptions_notebookSelector_Elem_Item1)
54310-type Lit_NotebookDocumentSyncOptions_notebookSelector_Elem_Item1 struct { // line 9852
54311-	// The notebook to be synced If a string
54312-	// value is provided it matches against the
54313-	// notebook type. '*' matches every notebook.
54314-	Notebook *Or_NotebookDocumentSyncOptions_notebookSelector_Elem_Item1_notebook `json:"notebook,omitempty"`
54315-	// The cells of the matching notebook to be synced.
54316-	Cells []Lit_NotebookDocumentSyncOptions_notebookSelector_Elem_Item1_cells_Elem `json:"cells"`
54317-}
54318-
54319-// created for Literal (Lit_NotebookDocumentSyncOptions_notebookSelector_Elem_Item1_cells_Elem)
54320-type Lit_NotebookDocumentSyncOptions_notebookSelector_Elem_Item1_cells_Elem struct { // line 9878
54321-	Language string `json:"language"`
54322-}
54323-
54324-// created for Literal (Lit_PrepareRenameResult_Item2)
54325-type Lit_PrepareRenameResult_Item2 struct { // line 13932
54326-	DefaultBehavior bool `json:"defaultBehavior"`
54327-}
54328-
54329-// created for Literal (Lit_TextDocumentContentChangeEvent_Item1)
54330-type Lit_TextDocumentContentChangeEvent_Item1 struct { // line 14040
54331-	// The new text of the whole document.
54332-	Text string `json:"text"`
54333-}
54334-
54335-// created for Literal (Lit_TextDocumentFilter_Item2)
54336-type Lit_TextDocumentFilter_Item2 struct { // line 14217
54337-	// A language id, like `typescript`.
54338-	Language string `json:"language,omitempty"`
54339-	// A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.
54340-	Scheme string `json:"scheme,omitempty"`
54341-	// A glob pattern, like `*.{ts,js}`.
54342-	Pattern string `json:"pattern"`
54343-}
54344-
54345-// Represents a location inside a resource, such as a line
54346-// inside a text file.
54347-type Location struct { // line 2083
54348-	URI   DocumentURI `json:"uri"`
54349-	Range Range       `json:"range"`
54350-}
54351-
54352-// Represents the connection of two locations. Provides additional metadata over normal {@link Location locations},
54353-// including an origin range.
54354-type LocationLink struct { // line 6272
54355-	// Span of the origin of this link.
54356-	//
54357-	// Used as the underlined span for mouse interaction. Defaults to the word range at
54358-	// the definition position.
54359-	OriginSelectionRange *Range `json:"originSelectionRange,omitempty"`
54360-	// The target resource identifier of this link.
54361-	TargetURI DocumentURI `json:"targetUri"`
54362-	// The full target range of this link. If the target for example is a symbol then target range is the
54363-	// range enclosing this symbol not including leading/trailing whitespace but everything else
54364-	// like comments. This information is typically used to highlight the range in the editor.
54365-	TargetRange Range `json:"targetRange"`
54366-	// The range that should be selected and revealed when this link is being followed, e.g the name of a function.
54367-	// Must be contained by the `targetRange`. See also `DocumentSymbol#range`
54368-	TargetSelectionRange Range `json:"targetSelectionRange"`
54369-}
54370-
54371-// The log message parameters.
54372-type LogMessageParams struct { // line 4251
54373-	// The message type. See {@link MessageType}
54374-	Type MessageType `json:"type"`
54375-	// The actual message.
54376-	Message string `json:"message"`
54377-}
54378-type LogTraceParams struct { // line 6159
54379-	Message string `json:"message"`
54380-	Verbose string `json:"verbose,omitempty"`
54381-}
54382-
54383-// Client capabilities specific to the used markdown parser.
54384-//
54385-// @since 3.16.0
54386-type MarkdownClientCapabilities struct { // line 12524
54387-	// The name of the parser.
54388-	Parser string `json:"parser"`
54389-	// The version of the parser.
54390-	Version string `json:"version,omitempty"`
54391-	// A list of HTML tags that the client allows / supports in
54392-	// Markdown.
54393-	//
54394-	// @since 3.17.0
54395-	AllowedTags []string `json:"allowedTags,omitempty"`
54396-}
54397-
54398-// MarkedString can be used to render human readable text. It is either a markdown string
54399-// or a code-block that provides a language and a code snippet. The language identifier
54400-// is semantically equal to the optional language identifier in fenced code blocks in GitHub
54401-// issues. See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting
54402-//
54403-// The pair of a language and a value is an equivalent to markdown:
54404-// ```${language}
54405-// ${value}
54406-// ```
54407-//
54408-// Note that markdown strings will be sanitized - that means html will be escaped.
54409-// @deprecated use MarkupContent instead.
54410-type MarkedString = Or_MarkedString // (alias) line 14058
54411-// A `MarkupContent` literal represents a string value which content is interpreted base on its
54412-// kind flag. Currently the protocol supports `plaintext` and `markdown` as markup kinds.
54413-//
54414-// If the kind is `markdown` then the value can contain fenced code blocks like in GitHub issues.
54415-// See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting
54416-//
54417-// Here is an example how such a string can be constructed using JavaScript / TypeScript:
54418-// ```ts
54419-//
54420-//	let markdown: MarkdownContent = {
54421-//	 kind: MarkupKind.Markdown,
54422-//	 value: [
54423-//	   '# Header',
54424-//	   'Some text',
54425-//	   '```typescript',
54426-//	   'someCode();',
54427-//	   '```'
54428-//	 ].join('\n')
54429-//	};
54430-//
54431-// ```
54432-//
54433-// *Please Note* that clients might sanitize the return markdown. A client could decide to
54434-// remove HTML from the markdown to avoid script execution.
54435-type MarkupContent struct { // line 7113
54436-	// The type of the Markup
54437-	Kind MarkupKind `json:"kind"`
54438-	// The content itself
54439-	Value string `json:"value"`
54440-}
54441-
54442-// Describes the content type that a client supports in various
54443-// result literals like `Hover`, `ParameterInfo` or `CompletionItem`.
54444-//
54445-// Please note that `MarkupKinds` must not start with a `$`. This kinds
54446-// are reserved for internal usage.
54447-type MarkupKind string          // line 13407
54448-type MessageActionItem struct { // line 4238
54449-	// A short title like 'Retry', 'Open Log' etc.
54450-	Title string `json:"title"`
54451-}
54452-
54453-// The message type
54454-type MessageType uint32 // line 13054
54455-// Moniker definition to match LSIF 0.5 moniker definition.
54456-//
54457-// @since 3.16.0
54458-type Moniker struct { // line 3338
54459-	// The scheme of the moniker. For example tsc or .Net
54460-	Scheme string `json:"scheme"`
54461-	// The identifier of the moniker. The value is opaque in LSIF however
54462-	// schema owners are allowed to define the structure if they want.
54463-	Identifier string `json:"identifier"`
54464-	// The scope in which the moniker is unique
54465-	Unique UniquenessLevel `json:"unique"`
54466-	// The moniker kind if known.
54467-	Kind *MonikerKind `json:"kind,omitempty"`
54468-}
54469-
54470-// Client capabilities specific to the moniker request.
54471-//
54472-// @since 3.16.0
54473-type MonikerClientCapabilities struct { // line 12321
54474-	// Whether moniker supports dynamic registration. If this is set to `true`
54475-	// the client supports the new `MonikerRegistrationOptions` return value
54476-	// for the corresponding server capability as well.
54477-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
54478-}
54479-
54480-// The moniker kind.
54481-//
54482-// @since 3.16.0
54483-type MonikerKind string      // line 13007
54484-type MonikerOptions struct { // line 6926
54485-	WorkDoneProgressOptions
54486-}
54487-type MonikerParams struct { // line 3318
54488-	TextDocumentPositionParams
54489-	WorkDoneProgressParams
54490-	PartialResultParams
54491-}
54492-type MonikerRegistrationOptions struct { // line 3378
54493-	TextDocumentRegistrationOptions
54494-	MonikerOptions
54495-}
54496-
54497-// created for Literal (Lit_MarkedString_Item1)
54498-type Msg_MarkedString struct { // line 14068
54499-	Language string `json:"language"`
54500-	Value    string `json:"value"`
54501-}
54502-
54503-// created for Literal (Lit_NotebookDocumentFilter_Item0)
54504-type Msg_NotebookDocumentFilter struct { // line 14260
54505-	// The type of the enclosing notebook.
54506-	NotebookType string `json:"notebookType"`
54507-	// A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.
54508-	Scheme string `json:"scheme,omitempty"`
54509-	// A glob pattern.
54510-	Pattern string `json:"pattern,omitempty"`
54511-}
54512-
54513-// created for Literal (Lit_PrepareRenameResult_Item1)
54514-type Msg_PrepareRename2Gn struct { // line 13911
54515-	Range       Range  `json:"range"`
54516-	Placeholder string `json:"placeholder"`
54517-}
54518-
54519-// created for Literal (Lit_TextDocumentContentChangeEvent_Item0)
54520-type Msg_TextDocumentContentChangeEvent struct { // line 14008
54521-	// The range of the document that changed.
54522-	Range *Range `json:"range"`
54523-	// The optional length of the range that got replaced.
54524-	//
54525-	// @deprecated use range instead.
54526-	RangeLength uint32 `json:"rangeLength,omitempty"`
54527-	// The new text for the provided range.
54528-	Text string `json:"text"`
54529-}
54530-
54531-// created for Literal (Lit_TextDocumentFilter_Item1)
54532-type Msg_TextDocumentFilter struct { // line 14184
54533-	// A language id, like `typescript`.
54534-	Language string `json:"language,omitempty"`
54535-	// A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.
54536-	Scheme string `json:"scheme"`
54537-	// A glob pattern, like `*.{ts,js}`.
54538-	Pattern string `json:"pattern,omitempty"`
54539-}
54540-
54541-// created for Literal (Lit__InitializeParams_clientInfo)
54542-type Msg_XInitializeParams_clientInfo struct { // line 7673
54543-	// The name of the client as defined by the client.
54544-	Name string `json:"name"`
54545-	// The client's version as defined by the client.
54546-	Version string `json:"version,omitempty"`
54547-}
54548-
54549-// A notebook cell.
54550-//
54551-// A cell's document URI must be unique across ALL notebook
54552-// cells and can therefore be used to uniquely identify a
54553-// notebook cell or the cell's text document.
54554-//
54555-// @since 3.17.0
54556-type NotebookCell struct { // line 9598
54557-	// The cell's kind
54558-	Kind NotebookCellKind `json:"kind"`
54559-	// The URI of the cell's text document
54560-	// content.
54561-	Document DocumentURI `json:"document"`
54562-	// Additional metadata stored with the cell.
54563-	//
54564-	// Note: should always be an object literal (e.g. LSPObject)
54565-	Metadata *LSPObject `json:"metadata,omitempty"`
54566-	// Additional execution summary information
54567-	// if supported by the client.
54568-	ExecutionSummary *ExecutionSummary `json:"executionSummary,omitempty"`
54569-}
54570-
54571-// A change describing how to move a `NotebookCell`
54572-// array from state S to S'.
54573-//
54574-// @since 3.17.0
54575-type NotebookCellArrayChange struct { // line 9639
54576-	// The start oftest of the cell that changed.
54577-	Start uint32 `json:"start"`
54578-	// The deleted cells
54579-	DeleteCount uint32 `json:"deleteCount"`
54580-	// The new cells, if any
54581-	Cells []NotebookCell `json:"cells,omitempty"`
54582-}
54583-
54584-// A notebook cell kind.
54585-//
54586-// @since 3.17.0
54587-type NotebookCellKind uint32 // line 13648
54588-// A notebook cell text document filter denotes a cell text
54589-// document by different properties.
54590-//
54591-// @since 3.17.0
54592-type NotebookCellTextDocumentFilter struct { // line 10113
54593-	// A filter that matches against the notebook
54594-	// containing the notebook cell. If a string
54595-	// value is provided it matches against the
54596-	// notebook type. '*' matches every notebook.
54597-	Notebook Or_NotebookCellTextDocumentFilter_notebook `json:"notebook"`
54598-	// A language id like `python`.
54599-	//
54600-	// Will be matched against the language id of the
54601-	// notebook cell document. '*' matches every language.
54602-	Language string `json:"language,omitempty"`
54603-}
54604-
54605-// A notebook document.
54606-//
54607-// @since 3.17.0
54608-type NotebookDocument struct { // line 7354
54609-	// The notebook document's uri.
54610-	URI URI `json:"uri"`
54611-	// The type of the notebook.
54612-	NotebookType string `json:"notebookType"`
54613-	// The version number of this document (it will increase after each
54614-	// change, including undo/redo).
54615-	Version int32 `json:"version"`
54616-	// Additional metadata stored with the notebook
54617-	// document.
54618-	//
54619-	// Note: should always be an object literal (e.g. LSPObject)
54620-	Metadata *LSPObject `json:"metadata,omitempty"`
54621-	// The cells of a notebook.
54622-	Cells []NotebookCell `json:"cells"`
54623-}
54624-
54625-// A change event for a notebook document.
54626-//
54627-// @since 3.17.0
54628-type NotebookDocumentChangeEvent struct { // line 7466
54629-	// The changed meta data if any.
54630-	//
54631-	// Note: should always be an object literal (e.g. LSPObject)
54632-	Metadata *LSPObject `json:"metadata,omitempty"`
54633-	// Changes to cells
54634-	Cells *PCellsPChange `json:"cells,omitempty"`
54635-}
54636-
54637-// Capabilities specific to the notebook document support.
54638-//
54639-// @since 3.17.0
54640-type NotebookDocumentClientCapabilities struct { // line 10613
54641-	// Capabilities specific to notebook document synchronization
54642-	//
54643-	// @since 3.17.0
54644-	Synchronization NotebookDocumentSyncClientCapabilities `json:"synchronization"`
54645-}
54646-
54647-// A notebook document filter denotes a notebook document by
54648-// different properties. The properties will be match
54649-// against the notebook's URI (same as with documents)
54650-//
54651-// @since 3.17.0
54652-type NotebookDocumentFilter = Msg_NotebookDocumentFilter // (alias) line 14254
54653-// A literal to identify a notebook document in the client.
54654-//
54655-// @since 3.17.0
54656-type NotebookDocumentIdentifier struct { // line 7582
54657-	// The notebook document's uri.
54658-	URI URI `json:"uri"`
54659-}
54660-
54661-// Notebook specific client capabilities.
54662-//
54663-// @since 3.17.0
54664-type NotebookDocumentSyncClientCapabilities struct { // line 12433
54665-	// Whether implementation supports dynamic registration. If this is
54666-	// set to `true` the client supports the new
54667-	// `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
54668-	// return value for the corresponding server capability as well.
54669-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
54670-	// The client supports sending execution summary data per cell.
54671-	ExecutionSummarySupport bool `json:"executionSummarySupport,omitempty"`
54672-}
54673-
54674-// Options specific to a notebook plus its cells
54675-// to be synced to the server.
54676-//
54677-// If a selector provides a notebook document
54678-// filter but no cell selector all cells of a
54679-// matching notebook document will be synced.
54680-//
54681-// If a selector provides no notebook document
54682-// filter but only a cell selector all notebook
54683-// document that contain at least one matching
54684-// cell will be synced.
54685-//
54686-// @since 3.17.0
54687-type NotebookDocumentSyncOptions struct { // line 9795
54688-	// The notebooks to be synced
54689-	NotebookSelector []PNotebookSelectorPNotebookDocumentSync `json:"notebookSelector"`
54690-	// Whether save notification should be forwarded to
54691-	// the server. Will only be honored if mode === `notebook`.
54692-	Save bool `json:"save,omitempty"`
54693-}
54694-
54695-// Registration options specific to a notebook.
54696-//
54697-// @since 3.17.0
54698-type NotebookDocumentSyncRegistrationOptions struct { // line 9915
54699-	NotebookDocumentSyncOptions
54700-	StaticRegistrationOptions
54701-}
54702-
54703-// A text document identifier to optionally denote a specific version of a text document.
54704-type OptionalVersionedTextDocumentIdentifier struct { // line 9343
54705-	// The version number of this document. If a versioned text document identifier
54706-	// is sent from the server to the client and the file is not open in the editor
54707-	// (the server has not received an open notification before) the server can send
54708-	// `null` to indicate that the version is unknown and the content on disk is the
54709-	// truth (as specified with document content ownership).
54710-	Version int32 `json:"version"`
54711-	TextDocumentIdentifier
54712-}
54713-
54714-// created for Or [FEditRangePItemDefaults Range]
54715-type OrFEditRangePItemDefaults struct { // line 4770
54716-	Value interface{} `json:"value"`
54717-}
54718-
54719-// created for Or [NotebookDocumentFilter string]
54720-type OrFNotebookPNotebookSelector struct { // line 9812
54721-	Value interface{} `json:"value"`
54722-}
54723-
54724-// created for Or [Location PLocationMsg_workspace_symbol]
54725-type OrPLocation_workspace_symbol struct { // line 5521
54726-	Value interface{} `json:"value"`
54727-}
54728-
54729-// created for Or [[]string string]
54730-type OrPSection_workspace_didChangeConfiguration struct { // line 4164
54731-	Value interface{} `json:"value"`
54732-}
54733-
54734-// created for Or [MarkupContent string]
54735-type OrPTooltipPLabel struct { // line 7076
54736-	Value interface{} `json:"value"`
54737-}
54738-
54739-// created for Or [MarkupContent string]
54740-type OrPTooltip_textDocument_inlayHint struct { // line 3700
54741-	Value interface{} `json:"value"`
54742-}
54743-
54744-// created for Or [int32 string]
54745-type Or_CancelParams_id struct { // line 6185
54746-	Value interface{} `json:"value"`
54747-}
54748-
54749-// created for Or [MarkupContent string]
54750-type Or_CompletionItem_documentation struct { // line 4583
54751-	Value interface{} `json:"value"`
54752-}
54753-
54754-// created for Or [InsertReplaceEdit TextEdit]
54755-type Or_CompletionItem_textEdit struct { // line 4666
54756-	Value interface{} `json:"value"`
54757-}
54758-
54759-// created for Or [Location []Location]
54760-type Or_Definition struct { // line 13754
54761-	Value interface{} `json:"value"`
54762-}
54763-
54764-// created for Or [int32 string]
54765-type Or_Diagnostic_code struct { // line 8548
54766-	Value interface{} `json:"value"`
54767-}
54768-
54769-// created for Or [RelatedFullDocumentDiagnosticReport RelatedUnchangedDocumentDiagnosticReport]
54770-type Or_DocumentDiagnosticReport struct { // line 13886
54771-	Value interface{} `json:"value"`
54772-}
54773-
54774-// created for Or [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]
54775-type Or_DocumentDiagnosticReportPartialResult_relatedDocuments_Value struct { // line 3823
54776-	Value interface{} `json:"value"`
54777-}
54778-
54779-// created for Or [NotebookCellTextDocumentFilter TextDocumentFilter]
54780-type Or_DocumentFilter struct { // line 14096
54781-	Value interface{} `json:"value"`
54782-}
54783-
54784-// created for Or [MarkedString MarkupContent []MarkedString]
54785-type Or_Hover_contents struct { // line 4892
54786-	Value interface{} `json:"value"`
54787-}
54788-
54789-// created for Or [[]InlayHintLabelPart string]
54790-type Or_InlayHint_label struct { // line 3659
54791-	Value interface{} `json:"value"`
54792-}
54793-
54794-// created for Or [InlineValueEvaluatableExpression InlineValueText InlineValueVariableLookup]
54795-type Or_InlineValue struct { // line 13864
54796-	Value interface{} `json:"value"`
54797-}
54798-
54799-// created for Or [Msg_MarkedString string]
54800-type Or_MarkedString struct { // line 14061
54801-	Value interface{} `json:"value"`
54802-}
54803-
54804-// created for Or [NotebookDocumentFilter string]
54805-type Or_NotebookCellTextDocumentFilter_notebook struct { // line 10119
54806-	Value interface{} `json:"value"`
54807-}
54808-
54809-// created for Or [NotebookDocumentFilter string]
54810-type Or_NotebookDocumentSyncOptions_notebookSelector_Elem_Item1_notebook struct { // line 9858
54811-	Value interface{} `json:"value"`
54812-}
54813-
54814-// created for Or [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]
54815-type Or_RelatedFullDocumentDiagnosticReport_relatedDocuments_Value struct { // line 7169
54816-	Value interface{} `json:"value"`
54817-}
54818-
54819-// created for Or [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]
54820-type Or_RelatedUnchangedDocumentDiagnosticReport_relatedDocuments_Value struct { // line 7208
54821-	Value interface{} `json:"value"`
54822-}
54823-
54824-// created for Or [URI WorkspaceFolder]
54825-type Or_RelativePattern_baseUri struct { // line 10742
54826-	Value interface{} `json:"value"`
54827-}
54828-
54829-// created for Or [CodeAction Command]
54830-type Or_Result_textDocument_codeAction_Item0_Elem struct { // line 1372
54831-	Value interface{} `json:"value"`
54832-}
54833-
54834-// created for Or [FFullPRequests bool]
54835-type Or_SemanticTokensClientCapabilities_requests_full struct { // line 12198
54836-	Value interface{} `json:"value"`
54837-}
54838-
54839-// created for Or [FRangePRequests bool]
54840-type Or_SemanticTokensClientCapabilities_requests_range struct { // line 12178
54841-	Value interface{} `json:"value"`
54842-}
54843-
54844-// created for Or [PFullESemanticTokensOptions bool]
54845-type Or_SemanticTokensOptions_full struct { // line 6580
54846-	Value interface{} `json:"value"`
54847-}
54848-
54849-// created for Or [PRangeESemanticTokensOptions bool]
54850-type Or_SemanticTokensOptions_range struct { // line 6560
54851-	Value interface{} `json:"value"`
54852-}
54853-
54854-// created for Or [CallHierarchyOptions CallHierarchyRegistrationOptions bool]
54855-type Or_ServerCapabilities_callHierarchyProvider struct { // line 8228
54856-	Value interface{} `json:"value"`
54857-}
54858-
54859-// created for Or [CodeActionOptions bool]
54860-type Or_ServerCapabilities_codeActionProvider struct { // line 8036
54861-	Value interface{} `json:"value"`
54862-}
54863-
54864-// created for Or [DocumentColorOptions DocumentColorRegistrationOptions bool]
54865-type Or_ServerCapabilities_colorProvider struct { // line 8072
54866-	Value interface{} `json:"value"`
54867-}
54868-
54869-// created for Or [DeclarationOptions DeclarationRegistrationOptions bool]
54870-type Or_ServerCapabilities_declarationProvider struct { // line 7898
54871-	Value interface{} `json:"value"`
54872-}
54873-
54874-// created for Or [DefinitionOptions bool]
54875-type Or_ServerCapabilities_definitionProvider struct { // line 7920
54876-	Value interface{} `json:"value"`
54877-}
54878-
54879-// created for Or [DiagnosticOptions DiagnosticRegistrationOptions]
54880-type Or_ServerCapabilities_diagnosticProvider struct { // line 8385
54881-	Value interface{} `json:"value"`
54882-}
54883-
54884-// created for Or [DocumentFormattingOptions bool]
54885-type Or_ServerCapabilities_documentFormattingProvider struct { // line 8112
54886-	Value interface{} `json:"value"`
54887-}
54888-
54889-// created for Or [DocumentHighlightOptions bool]
54890-type Or_ServerCapabilities_documentHighlightProvider struct { // line 8000
54891-	Value interface{} `json:"value"`
54892-}
54893-
54894-// created for Or [DocumentRangeFormattingOptions bool]
54895-type Or_ServerCapabilities_documentRangeFormattingProvider struct { // line 8130
54896-	Value interface{} `json:"value"`
54897-}
54898-
54899-// created for Or [DocumentSymbolOptions bool]
54900-type Or_ServerCapabilities_documentSymbolProvider struct { // line 8018
54901-	Value interface{} `json:"value"`
54902-}
54903-
54904-// created for Or [FoldingRangeOptions FoldingRangeRegistrationOptions bool]
54905-type Or_ServerCapabilities_foldingRangeProvider struct { // line 8175
54906-	Value interface{} `json:"value"`
54907-}
54908-
54909-// created for Or [HoverOptions bool]
54910-type Or_ServerCapabilities_hoverProvider struct { // line 7871
54911-	Value interface{} `json:"value"`
54912-}
54913-
54914-// created for Or [ImplementationOptions ImplementationRegistrationOptions bool]
54915-type Or_ServerCapabilities_implementationProvider struct { // line 7960
54916-	Value interface{} `json:"value"`
54917-}
54918-
54919-// created for Or [InlayHintOptions InlayHintRegistrationOptions bool]
54920-type Or_ServerCapabilities_inlayHintProvider struct { // line 8362
54921-	Value interface{} `json:"value"`
54922-}
54923-
54924-// created for Or [InlineValueOptions InlineValueRegistrationOptions bool]
54925-type Or_ServerCapabilities_inlineValueProvider struct { // line 8339
54926-	Value interface{} `json:"value"`
54927-}
54928-
54929-// created for Or [LinkedEditingRangeOptions LinkedEditingRangeRegistrationOptions bool]
54930-type Or_ServerCapabilities_linkedEditingRangeProvider struct { // line 8251
54931-	Value interface{} `json:"value"`
54932-}
54933-
54934-// created for Or [MonikerOptions MonikerRegistrationOptions bool]
54935-type Or_ServerCapabilities_monikerProvider struct { // line 8293
54936-	Value interface{} `json:"value"`
54937-}
54938-
54939-// created for Or [NotebookDocumentSyncOptions NotebookDocumentSyncRegistrationOptions]
54940-type Or_ServerCapabilities_notebookDocumentSync struct { // line 7843
54941-	Value interface{} `json:"value"`
54942-}
54943-
54944-// created for Or [ReferenceOptions bool]
54945-type Or_ServerCapabilities_referencesProvider struct { // line 7982
54946-	Value interface{} `json:"value"`
54947-}
54948-
54949-// created for Or [RenameOptions bool]
54950-type Or_ServerCapabilities_renameProvider struct { // line 8157
54951-	Value interface{} `json:"value"`
54952-}
54953-
54954-// created for Or [SelectionRangeOptions SelectionRangeRegistrationOptions bool]
54955-type Or_ServerCapabilities_selectionRangeProvider struct { // line 8197
54956-	Value interface{} `json:"value"`
54957-}
54958-
54959-// created for Or [SemanticTokensOptions SemanticTokensRegistrationOptions]
54960-type Or_ServerCapabilities_semanticTokensProvider struct { // line 8274
54961-	Value interface{} `json:"value"`
54962-}
54963-
54964-// created for Or [TextDocumentSyncKind TextDocumentSyncOptions]
54965-type Or_ServerCapabilities_textDocumentSync struct { // line 7825
54966-	Value interface{} `json:"value"`
54967-}
54968-
54969-// created for Or [TypeDefinitionOptions TypeDefinitionRegistrationOptions bool]
54970-type Or_ServerCapabilities_typeDefinitionProvider struct { // line 7938
54971-	Value interface{} `json:"value"`
54972-}
54973-
54974-// created for Or [TypeHierarchyOptions TypeHierarchyRegistrationOptions bool]
54975-type Or_ServerCapabilities_typeHierarchyProvider struct { // line 8316
54976-	Value interface{} `json:"value"`
54977-}
54978-
54979-// created for Or [WorkspaceSymbolOptions bool]
54980-type Or_ServerCapabilities_workspaceSymbolProvider struct { // line 8094
54981-	Value interface{} `json:"value"`
54982-}
54983-
54984-// created for Or [MarkupContent string]
54985-type Or_SignatureInformation_documentation struct { // line 8842
54986-	Value interface{} `json:"value"`
54987-}
54988-
54989-// created for Or [AnnotatedTextEdit TextEdit]
54990-type Or_TextDocumentEdit_edits_Elem struct { // line 6693
54991-	Value interface{} `json:"value"`
54992-}
54993-
54994-// created for Or [SaveOptions bool]
54995-type Or_TextDocumentSyncOptions_save struct { // line 9778
54996-	Value interface{} `json:"value"`
54997-}
54998-
54999-// created for Or [WorkspaceFullDocumentDiagnosticReport WorkspaceUnchangedDocumentDiagnosticReport]
55000-type Or_WorkspaceDocumentDiagnosticReport struct { // line 13987
55001-	Value interface{} `json:"value"`
55002-}
55003-
55004-// created for Or [CreateFile DeleteFile RenameFile TextDocumentEdit]
55005-type Or_WorkspaceEdit_documentChanges_Elem struct { // line 3220
55006-	Value interface{} `json:"value"`
55007-}
55008-
55009-// created for Or [Declaration []DeclarationLink]
55010-type Or_textDocument_declaration struct { // line 249
55011-	Value interface{} `json:"value"`
55012-}
55013-
55014-// created for Literal (Lit_NotebookDocumentChangeEvent_cells)
55015-type PCellsPChange struct { // line 7481
55016-	// Changes to the cell structure to add or
55017-	// remove cells.
55018-	Structure *FStructurePCells `json:"structure,omitempty"`
55019-	// Changes to notebook cells properties like its
55020-	// kind, execution summary or metadata.
55021-	Data []NotebookCell `json:"data,omitempty"`
55022-	// Changes to the text content of notebook cells.
55023-	TextContent []Lit_NotebookDocumentChangeEvent_cells_textContent_Elem `json:"textContent,omitempty"`
55024-}
55025-
55026-// created for Literal (Lit_WorkspaceEditClientCapabilities_changeAnnotationSupport)
55027-type PChangeAnnotationSupportPWorkspaceEdit struct { // line 10816
55028-	// Whether the client groups edits with equal labels into tree nodes,
55029-	// for instance all edits labelled with "Changes in Strings" would
55030-	// be a tree node.
55031-	GroupsOnLabel bool `json:"groupsOnLabel,omitempty"`
55032-}
55033-
55034-// created for Literal (Lit_CodeActionClientCapabilities_codeActionLiteralSupport)
55035-type PCodeActionLiteralSupportPCodeAction struct { // line 11736
55036-	// The code action kind is support with the following value
55037-	// set.
55038-	CodeActionKind FCodeActionKindPCodeActionLiteralSupport `json:"codeActionKind"`
55039-}
55040-
55041-// created for Literal (Lit_CompletionClientCapabilities_completionItemKind)
55042-type PCompletionItemKindPCompletion struct { // line 11334
55043-	// The completion item kind values the client supports. When this
55044-	// property exists the client also guarantees that it will
55045-	// handle values outside its set gracefully and falls back
55046-	// to a default value when unknown.
55047-	//
55048-	// If this property is not present the client only supports
55049-	// the completion items kinds from `Text` to `Reference` as defined in
55050-	// the initial version of the protocol.
55051-	ValueSet []CompletionItemKind `json:"valueSet,omitempty"`
55052-}
55053-
55054-// created for Literal (Lit_CompletionClientCapabilities_completionItem)
55055-type PCompletionItemPCompletion struct { // line 11183
55056-	// Client supports snippets as insert text.
55057-	//
55058-	// A snippet can define tab stops and placeholders with `$1`, `$2`
55059-	// and `${3:foo}`. `$0` defines the final tab stop, it defaults to
55060-	// the end of the snippet. Placeholders with equal identifiers are linked,
55061-	// that is typing in one will update others too.
55062-	SnippetSupport bool `json:"snippetSupport,omitempty"`
55063-	// Client supports commit characters on a completion item.
55064-	CommitCharactersSupport bool `json:"commitCharactersSupport,omitempty"`
55065-	// Client supports the following content formats for the documentation
55066-	// property. The order describes the preferred format of the client.
55067-	DocumentationFormat []MarkupKind `json:"documentationFormat,omitempty"`
55068-	// Client supports the deprecated property on a completion item.
55069-	DeprecatedSupport bool `json:"deprecatedSupport,omitempty"`
55070-	// Client supports the preselect property on a completion item.
55071-	PreselectSupport bool `json:"preselectSupport,omitempty"`
55072-	// Client supports the tag property on a completion item. Clients supporting
55073-	// tags have to handle unknown tags gracefully. Clients especially need to
55074-	// preserve unknown tags when sending a completion item back to the server in
55075-	// a resolve call.
55076-	//
55077-	// @since 3.15.0
55078-	TagSupport FTagSupportPCompletionItem `json:"tagSupport"`
55079-	// Client support insert replace edit to control different behavior if a
55080-	// completion item is inserted in the text or should replace text.
55081-	//
55082-	// @since 3.16.0
55083-	InsertReplaceSupport bool `json:"insertReplaceSupport,omitempty"`
55084-	// Indicates which properties a client can resolve lazily on a completion
55085-	// item. Before version 3.16.0 only the predefined properties `documentation`
55086-	// and `details` could be resolved lazily.
55087-	//
55088-	// @since 3.16.0
55089-	ResolveSupport *FResolveSupportPCompletionItem `json:"resolveSupport,omitempty"`
55090-	// The client supports the `insertTextMode` property on
55091-	// a completion item to override the whitespace handling mode
55092-	// as defined by the client (see `insertTextMode`).
55093-	//
55094-	// @since 3.16.0
55095-	InsertTextModeSupport *FInsertTextModeSupportPCompletionItem `json:"insertTextModeSupport,omitempty"`
55096-	// The client has support for completion item label
55097-	// details (see also `CompletionItemLabelDetails`).
55098-	//
55099-	// @since 3.17.0
55100-	LabelDetailsSupport bool `json:"labelDetailsSupport,omitempty"`
55101-}
55102-
55103-// created for Literal (Lit_CompletionOptions_completionItem)
55104-type PCompletionItemPCompletionProvider struct { // line 8747
55105-	// The server has support for completion item label
55106-	// details (see also `CompletionItemLabelDetails`) when
55107-	// receiving a completion item in a resolve call.
55108-	//
55109-	// @since 3.17.0
55110-	LabelDetailsSupport bool `json:"labelDetailsSupport,omitempty"`
55111-}
55112-
55113-// created for Literal (Lit_CompletionClientCapabilities_completionList)
55114-type PCompletionListPCompletion struct { // line 11376
55115-	// The client supports the following itemDefaults on
55116-	// a completion list.
55117-	//
55118-	// The value lists the supported property names of the
55119-	// `CompletionList.itemDefaults` object. If omitted
55120-	// no properties are supported.
55121-	//
55122-	// @since 3.17.0
55123-	ItemDefaults []string `json:"itemDefaults,omitempty"`
55124-}
55125-
55126-// created for Literal (Lit_CodeAction_disabled)
55127-type PDisabledMsg_textDocument_codeAction struct { // line 5427
55128-	// Human readable description of why the code action is currently disabled.
55129-	//
55130-	// This is displayed in the code actions UI.
55131-	Reason string `json:"reason"`
55132-}
55133-
55134-// created for Literal (Lit_FoldingRangeClientCapabilities_foldingRangeKind)
55135-type PFoldingRangeKindPFoldingRange struct { // line 12011
55136-	// The folding range kind values the client supports. When this
55137-	// property exists the client also guarantees that it will
55138-	// handle values outside its set gracefully and falls back
55139-	// to a default value when unknown.
55140-	ValueSet []FoldingRangeKind `json:"valueSet,omitempty"`
55141-}
55142-
55143-// created for Literal (Lit_FoldingRangeClientCapabilities_foldingRange)
55144-type PFoldingRangePFoldingRange struct { // line 12036
55145-	// If set, the client signals that it supports setting collapsedText on
55146-	// folding ranges to display custom labels instead of the default text.
55147-	//
55148-	// @since 3.17.0
55149-	CollapsedText bool `json:"collapsedText,omitempty"`
55150-}
55151-
55152-// created for Literal (Lit_SemanticTokensOptions_full_Item1)
55153-type PFullESemanticTokensOptions struct { // line 6587
55154-	// The server supports deltas for full documents.
55155-	Delta bool `json:"delta"`
55156-}
55157-
55158-// created for Literal (Lit_CompletionList_itemDefaults)
55159-type PItemDefaultsMsg_textDocument_completion struct { // line 4751
55160-	// A default commit character set.
55161-	//
55162-	// @since 3.17.0
55163-	CommitCharacters []string `json:"commitCharacters,omitempty"`
55164-	// A default edit range.
55165-	//
55166-	// @since 3.17.0
55167-	EditRange *OrFEditRangePItemDefaults `json:"editRange,omitempty"`
55168-	// A default insert text format.
55169-	//
55170-	// @since 3.17.0
55171-	InsertTextFormat *InsertTextFormat `json:"insertTextFormat,omitempty"`
55172-	// A default insert text mode.
55173-	//
55174-	// @since 3.17.0
55175-	InsertTextMode *InsertTextMode `json:"insertTextMode,omitempty"`
55176-	// A default data value.
55177-	//
55178-	// @since 3.17.0
55179-	Data interface{} `json:"data,omitempty"`
55180-}
55181-
55182-// created for Literal (Lit_WorkspaceSymbol_location_Item1)
55183-type PLocationMsg_workspace_symbol struct { // line 5528
55184-	URI DocumentURI `json:"uri"`
55185-}
55186-
55187-// created for Literal (Lit_ShowMessageRequestClientCapabilities_messageActionItem)
55188-type PMessageActionItemPShowMessage struct { // line 12464
55189-	// Whether the client supports additional attributes which
55190-	// are preserved and send back to the server in the
55191-	// request's response.
55192-	AdditionalPropertiesSupport bool `json:"additionalPropertiesSupport,omitempty"`
55193-}
55194-
55195-// created for Literal (Lit_NotebookDocumentSyncOptions_notebookSelector_Elem_Item0)
55196-type PNotebookSelectorPNotebookDocumentSync struct { // line 9806
55197-	// The notebook to be synced If a string
55198-	// value is provided it matches against the
55199-	// notebook type. '*' matches every notebook.
55200-	Notebook OrFNotebookPNotebookSelector `json:"notebook"`
55201-	// The cells of the matching notebook to be synced.
55202-	Cells []Lit_NotebookDocumentSyncOptions_notebookSelector_Elem_Item0_cells_Elem `json:"cells,omitempty"`
55203-}
55204-
55205-// created for Literal (Lit_SemanticTokensOptions_range_Item1)
55206-type PRangeESemanticTokensOptions struct { // line 6567
55207-}
55208-
55209-// created for Literal (Lit_SemanticTokensClientCapabilities_requests)
55210-type PRequestsPSemanticTokens struct { // line 12172
55211-	// The client will send the `textDocument/semanticTokens/range` request if
55212-	// the server provides a corresponding handler.
55213-	Range Or_SemanticTokensClientCapabilities_requests_range `json:"range"`
55214-	// The client will send the `textDocument/semanticTokens/full` request if
55215-	// the server provides a corresponding handler.
55216-	Full Or_SemanticTokensClientCapabilities_requests_full `json:"full"`
55217-}
55218-
55219-// created for Literal (Lit_CodeActionClientCapabilities_resolveSupport)
55220-type PResolveSupportPCodeAction struct { // line 11801
55221-	// The properties that a client can resolve lazily.
55222-	Properties []string `json:"properties"`
55223-}
55224-
55225-// created for Literal (Lit_InlayHintClientCapabilities_resolveSupport)
55226-type PResolveSupportPInlayHint struct { // line 12384
55227-	// The properties that a client can resolve lazily.
55228-	Properties []string `json:"properties"`
55229-}
55230-
55231-// created for Literal (Lit_WorkspaceSymbolClientCapabilities_resolveSupport)
55232-type PResolveSupportPSymbol struct { // line 10938
55233-	// The properties that a client can resolve lazily. Usually
55234-	// `location.range`
55235-	Properties []string `json:"properties"`
55236-}
55237-
55238-// created for Literal (Lit_InitializeResult_serverInfo)
55239-type PServerInfoMsg_initialize struct { // line 4096
55240-	// The name of the server as defined by the server.
55241-	Name string `json:"name"`
55242-	// The server's version as defined by the server.
55243-	Version string `json:"version,omitempty"`
55244-}
55245-
55246-// created for Literal (Lit_SignatureHelpClientCapabilities_signatureInformation)
55247-type PSignatureInformationPSignatureHelp struct { // line 11443
55248-	// Client supports the following content formats for the documentation
55249-	// property. The order describes the preferred format of the client.
55250-	DocumentationFormat []MarkupKind `json:"documentationFormat,omitempty"`
55251-	// Client capabilities specific to parameter information.
55252-	ParameterInformation *FParameterInformationPSignatureInformation `json:"parameterInformation,omitempty"`
55253-	// The client supports the `activeParameter` property on `SignatureInformation`
55254-	// literal.
55255-	//
55256-	// @since 3.16.0
55257-	ActiveParameterSupport bool `json:"activeParameterSupport,omitempty"`
55258-}
55259-
55260-// created for Literal (Lit_GeneralClientCapabilities_staleRequestSupport)
55261-type PStaleRequestSupportPGeneral struct { // line 10670
55262-	// The client will actively cancel the request.
55263-	Cancel bool `json:"cancel"`
55264-	// The list of requests for which the client
55265-	// will retry the request if it receives a
55266-	// response with error code `ContentModified`
55267-	RetryOnContentModified []string `json:"retryOnContentModified"`
55268-}
55269-
55270-// created for Literal (Lit_DocumentSymbolClientCapabilities_symbolKind)
55271-type PSymbolKindPDocumentSymbol struct { // line 11654
55272-	// The symbol kind values the client supports. When this
55273-	// property exists the client also guarantees that it will
55274-	// handle values outside its set gracefully and falls back
55275-	// to a default value when unknown.
55276-	//
55277-	// If this property is not present the client only supports
55278-	// the symbol kinds from `File` to `Array` as defined in
55279-	// the initial version of the protocol.
55280-	ValueSet []SymbolKind `json:"valueSet,omitempty"`
55281-}
55282-
55283-// created for Literal (Lit_WorkspaceSymbolClientCapabilities_symbolKind)
55284-type PSymbolKindPSymbol struct { // line 10890
55285-	// The symbol kind values the client supports. When this
55286-	// property exists the client also guarantees that it will
55287-	// handle values outside its set gracefully and falls back
55288-	// to a default value when unknown.
55289-	//
55290-	// If this property is not present the client only supports
55291-	// the symbol kinds from `File` to `Array` as defined in
55292-	// the initial version of the protocol.
55293-	ValueSet []SymbolKind `json:"valueSet,omitempty"`
55294-}
55295-
55296-// created for Literal (Lit_DocumentSymbolClientCapabilities_tagSupport)
55297-type PTagSupportPDocumentSymbol struct { // line 11687
55298-	// The tags supported by the client.
55299-	ValueSet []SymbolTag `json:"valueSet"`
55300-}
55301-
55302-// created for Literal (Lit_PublishDiagnosticsClientCapabilities_tagSupport)
55303-type PTagSupportPPublishDiagnostics struct { // line 12087
55304-	// The tags supported by the client.
55305-	ValueSet []DiagnosticTag `json:"valueSet"`
55306-}
55307-
55308-// created for Literal (Lit_WorkspaceSymbolClientCapabilities_tagSupport)
55309-type PTagSupportPSymbol struct { // line 10914
55310-	// The tags supported by the client.
55311-	ValueSet []SymbolTag `json:"valueSet"`
55312-}
55313-
55314-// The parameters of a configuration request.
55315-type ParamConfiguration struct { // line 2199
55316-	Items []ConfigurationItem `json:"items"`
55317-}
55318-type ParamInitialize struct { // line 4068
55319-	XInitializeParams
55320-	WorkspaceFoldersInitializeParams
55321-}
55322-
55323-// Represents a parameter of a callable-signature. A parameter can
55324-// have a label and a doc-comment.
55325-type ParameterInformation struct { // line 10063
55326-	// The label of this parameter information.
55327-	//
55328-	// Either a string or an inclusive start and exclusive end offsets within its containing
55329-	// signature label. (see SignatureInformation.label). The offsets are based on a UTF-16
55330-	// string representation as `Position` and `Range` does.
55331-	//
55332-	// *Note*: a label of type string should be a substring of its containing signature label.
55333-	// Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`.
55334-	Label string `json:"label"`
55335-	// The human-readable doc-comment of this parameter. Will be shown
55336-	// in the UI but can be omitted.
55337-	Documentation string `json:"documentation,omitempty"`
55338-}
55339-type PartialResultParams struct { // line 6258
55340-	// An optional token that a server can use to report partial results (e.g. streaming) to
55341-	// the client.
55342-	PartialResultToken *ProgressToken `json:"partialResultToken,omitempty"`
55343-}
55344-
55345-// The glob pattern to watch relative to the base path. Glob patterns can have the following syntax:
55346-//
55347-//   - `*` to match one or more characters in a path segment
55348-//   - `?` to match on one character in a path segment
55349-//   - `**` to match any number of path segments, including none
55350-//   - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files)
55351-//   - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
55352-//   - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
55353-//
55354-// @since 3.17.0
55355-type Pattern = string // (alias) line 14363
55356-// Position in a text document expressed as zero-based line and character
55357-// offset. Prior to 3.17 the offsets were always based on a UTF-16 string
55358-// representation. So a string of the form `a��b` the character offset of the
55359-// character `a` is 0, the character offset of `��` is 1 and the character
55360-// offset of b is 3 since `��` is represented using two code units in UTF-16.
55361-// Since 3.17 clients and servers can agree on a different string encoding
55362-// representation (e.g. UTF-8). The client announces it's supported encoding
55363-// via the client capability [`general.positionEncodings`](#clientCapabilities).
55364-// The value is an array of position encodings the client supports, with
55365-// decreasing preference (e.g. the encoding at index `0` is the most preferred
55366-// one). To stay backwards compatible the only mandatory encoding is UTF-16
55367-// represented via the string `utf-16`. The server can pick one of the
55368-// encodings offered by the client and signals that encoding back to the
55369-// client via the initialize result's property
55370-// [`capabilities.positionEncoding`](#serverCapabilities). If the string value
55371-// `utf-16` is missing from the client's capability `general.positionEncodings`
55372-// servers can safely assume that the client supports UTF-16. If the server
55373-// omits the position encoding in its initialize result the encoding defaults
55374-// to the string value `utf-16`. Implementation considerations: since the
55375-// conversion from one encoding into another requires the content of the
55376-// file / line the conversion is best done where the file is read which is
55377-// usually on the server side.
55378-//
55379-// Positions are line end character agnostic. So you can not specify a position
55380-// that denotes `\r|\n` or `\n|` where `|` represents the character offset.
55381-//
55382-// @since 3.17.0 - support for negotiated position encoding.
55383-type Position struct { // line 6501
55384-	// Line position in a document (zero-based).
55385-	//
55386-	// If a line number is greater than the number of lines in a document, it defaults back to the number of lines in the document.
55387-	// If a line number is negative, it defaults to 0.
55388-	Line uint32 `json:"line"`
55389-	// Character offset on a line in a document (zero-based).
55390-	//
55391-	// The meaning of this offset is determined by the negotiated
55392-	// `PositionEncodingKind`.
55393-	//
55394-	// If the character value is greater than the line length it defaults back to the
55395-	// line length.
55396-	Character uint32 `json:"character"`
55397-}
55398-
55399-// A set of predefined position encoding kinds.
55400-//
55401-// @since 3.17.0
55402-type PositionEncodingKind string             // line 13427
55403-type PrepareRename2Gn = Msg_PrepareRename2Gn // (alias) line 13927
55404-type PrepareRenameParams struct {            // line 5925
55405-	TextDocumentPositionParams
55406-	WorkDoneProgressParams
55407-}
55408-type PrepareRenameResult = Msg_PrepareRename2Gn // (alias) line 13927
55409-type PrepareSupportDefaultBehavior uint32       // line 13722
55410-// A previous result id in a workspace pull request.
55411-//
55412-// @since 3.17.0
55413-type PreviousResultID struct { // line 7331
55414-	// The URI for which the client knowns a
55415-	// result id.
55416-	URI DocumentURI `json:"uri"`
55417-	// The value of the previous result id.
55418-	Value string `json:"value"`
55419-}
55420-
55421-// A previous result id in a workspace pull request.
55422-//
55423-// @since 3.17.0
55424-type PreviousResultId struct { // line 7331
55425-	// The URI for which the client knowns a
55426-	// result id.
55427-	URI DocumentURI `json:"uri"`
55428-	// The value of the previous result id.
55429-	Value string `json:"value"`
55430-}
55431-type ProgressParams struct { // line 6201
55432-	// The progress token provided by the client or server.
55433-	Token ProgressToken `json:"token"`
55434-	// The progress data.
55435-	Value interface{} `json:"value"`
55436-}
55437-type ProgressToken = interface{} // (alias) line 13960
55438-// The publish diagnostic client capabilities.
55439-type PublishDiagnosticsClientCapabilities struct { // line 12072
55440-	// Whether the clients accepts diagnostics with related information.
55441-	RelatedInformation bool `json:"relatedInformation,omitempty"`
55442-	// Client supports the tag property to provide meta data about a diagnostic.
55443-	// Clients supporting tags have to handle unknown tags gracefully.
55444-	//
55445-	// @since 3.15.0
55446-	TagSupport *PTagSupportPPublishDiagnostics `json:"tagSupport,omitempty"`
55447-	// Whether the client interprets the version property of the
55448-	// `textDocument/publishDiagnostics` notification's parameter.
55449-	//
55450-	// @since 3.15.0
55451-	VersionSupport bool `json:"versionSupport,omitempty"`
55452-	// Client supports a codeDescription property
55453-	//
55454-	// @since 3.16.0
55455-	CodeDescriptionSupport bool `json:"codeDescriptionSupport,omitempty"`
55456-	// Whether code action supports the `data` property which is
55457-	// preserved between a `textDocument/publishDiagnostics` and
55458-	// `textDocument/codeAction` request.
55459-	//
55460-	// @since 3.16.0
55461-	DataSupport bool `json:"dataSupport,omitempty"`
55462-}
55463-
55464-// The publish diagnostic notification's parameters.
55465-type PublishDiagnosticsParams struct { // line 4462
55466-	// The URI for which diagnostic information is reported.
55467-	URI DocumentURI `json:"uri"`
55468-	// Optional the version number of the document the diagnostics are published for.
55469-	//
55470-	// @since 3.15.0
55471-	Version int32 `json:"version,omitempty"`
55472-	// An array of diagnostic information items.
55473-	Diagnostics []Diagnostic `json:"diagnostics"`
55474-}
55475-
55476-// A range in a text document expressed as (zero-based) start and end positions.
55477-//
55478-// If you want to specify a range that contains a line including the line ending
55479-// character(s) then use an end position denoting the start of the next line.
55480-// For example:
55481-// ```ts
55482-//
55483-//	{
55484-//	    start: { line: 5, character: 23 }
55485-//	    end : { line 6, character : 0 }
55486-//	}
55487-//
55488-// ```
55489-type Range struct { // line 6311
55490-	// The range's start position.
55491-	Start Position `json:"start"`
55492-	// The range's end position.
55493-	End Position `json:"end"`
55494-}
55495-
55496-// Client Capabilities for a {@link ReferencesRequest}.
55497-type ReferenceClientCapabilities struct { // line 11609
55498-	// Whether references supports dynamic registration.
55499-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
55500-}
55501-
55502-// Value-object that contains additional information when
55503-// requesting references.
55504-type ReferenceContext struct { // line 8930
55505-	// Include the declaration of the current symbol.
55506-	IncludeDeclaration bool `json:"includeDeclaration"`
55507-}
55508-
55509-// Reference options.
55510-type ReferenceOptions struct { // line 8944
55511-	WorkDoneProgressOptions
55512-}
55513-
55514-// Parameters for a {@link ReferencesRequest}.
55515-type ReferenceParams struct { // line 5054
55516-	Context ReferenceContext `json:"context"`
55517-	TextDocumentPositionParams
55518-	WorkDoneProgressParams
55519-	PartialResultParams
55520-}
55521-
55522-// Registration options for a {@link ReferencesRequest}.
55523-type ReferenceRegistrationOptions struct { // line 5083
55524-	TextDocumentRegistrationOptions
55525-	ReferenceOptions
55526-}
55527-
55528-// General parameters to to register for an notification or to register a provider.
55529-type Registration struct { // line 7597
55530-	// The id used to register the request. The id can be used to deregister
55531-	// the request again.
55532-	ID string `json:"id"`
55533-	// The method / capability to register for.
55534-	Method string `json:"method"`
55535-	// Options necessary for the registration.
55536-	RegisterOptions interface{} `json:"registerOptions,omitempty"`
55537-}
55538-type RegistrationParams struct { // line 4038
55539-	Registrations []Registration `json:"registrations"`
55540-}
55541-
55542-// Client capabilities specific to regular expressions.
55543-//
55544-// @since 3.16.0
55545-type RegularExpressionsClientCapabilities struct { // line 12500
55546-	// The engine's name.
55547-	Engine string `json:"engine"`
55548-	// The engine's version.
55549-	Version string `json:"version,omitempty"`
55550-}
55551-
55552-// A full diagnostic report with a set of related documents.
55553-//
55554-// @since 3.17.0
55555-type RelatedFullDocumentDiagnosticReport struct { // line 7157
55556-	// Diagnostics of related documents. This information is useful
55557-	// in programming languages where code in a file A can generate
55558-	// diagnostics in a file B which A depends on. An example of
55559-	// such a language is C/C++ where marco definitions in a file
55560-	// a.cpp and result in errors in a header file b.hpp.
55561-	//
55562-	// @since 3.17.0
55563-	RelatedDocuments map[DocumentURI]interface{} `json:"relatedDocuments,omitempty"`
55564-	FullDocumentDiagnosticReport
55565-}
55566-
55567-// An unchanged diagnostic report with a set of related documents.
55568-//
55569-// @since 3.17.0
55570-type RelatedUnchangedDocumentDiagnosticReport struct { // line 7196
55571-	// Diagnostics of related documents. This information is useful
55572-	// in programming languages where code in a file A can generate
55573-	// diagnostics in a file B which A depends on. An example of
55574-	// such a language is C/C++ where marco definitions in a file
55575-	// a.cpp and result in errors in a header file b.hpp.
55576-	//
55577-	// @since 3.17.0
55578-	RelatedDocuments map[DocumentURI]interface{} `json:"relatedDocuments,omitempty"`
55579-	UnchangedDocumentDiagnosticReport
55580-}
55581-
55582-// A relative pattern is a helper to construct glob patterns that are matched
55583-// relatively to a base URI. The common value for a `baseUri` is a workspace
55584-// folder root, but it can be another absolute URI as well.
55585-//
55586-// @since 3.17.0
55587-type RelativePattern struct { // line 10736
55588-	// A workspace folder or a base URI to which this pattern will be matched
55589-	// against relatively.
55590-	BaseURI Or_RelativePattern_baseUri `json:"baseUri"`
55591-	// The actual glob pattern;
55592-	Pattern Pattern `json:"pattern"`
55593-}
55594-type RenameClientCapabilities struct { // line 11934
55595-	// Whether rename supports dynamic registration.
55596-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
55597-	// Client supports testing for validity of rename operations
55598-	// before execution.
55599-	//
55600-	// @since 3.12.0
55601-	PrepareSupport bool `json:"prepareSupport,omitempty"`
55602-	// Client supports the default behavior result.
55603-	//
55604-	// The value indicates the default behavior used by the
55605-	// client.
55606-	//
55607-	// @since 3.16.0
55608-	PrepareSupportDefaultBehavior *PrepareSupportDefaultBehavior `json:"prepareSupportDefaultBehavior,omitempty"`
55609-	// Whether the client honors the change annotations in
55610-	// text edits and resource operations returned via the
55611-	// rename request's workspace edit by for example presenting
55612-	// the workspace edit in the user interface and asking
55613-	// for confirmation.
55614-	//
55615-	// @since 3.16.0
55616-	HonorsChangeAnnotations bool `json:"honorsChangeAnnotations,omitempty"`
55617-}
55618-
55619-// Rename file operation
55620-type RenameFile struct { // line 6749
55621-	// A rename
55622-	Kind string `json:"kind"`
55623-	// The old (existing) location.
55624-	OldURI DocumentURI `json:"oldUri"`
55625-	// The new location.
55626-	NewURI DocumentURI `json:"newUri"`
55627-	// Rename options.
55628-	Options *RenameFileOptions `json:"options,omitempty"`
55629-	ResourceOperation
55630-}
55631-
55632-// Rename file options
55633-type RenameFileOptions struct { // line 9441
55634-	// Overwrite target if existing. Overwrite wins over `ignoreIfExists`
55635-	Overwrite bool `json:"overwrite,omitempty"`
55636-	// Ignores if target exists.
55637-	IgnoreIfExists bool `json:"ignoreIfExists,omitempty"`
55638-}
55639-
55640-// The parameters sent in notifications/requests for user-initiated renames of
55641-// files.
55642-//
55643-// @since 3.16.0
55644-type RenameFilesParams struct { // line 3282
55645-	// An array of all files/folders renamed in this operation. When a folder is renamed, only
55646-	// the folder will be included, and not its children.
55647-	Files []FileRename `json:"files"`
55648-}
55649-
55650-// Provider options for a {@link RenameRequest}.
55651-type RenameOptions struct { // line 9269
55652-	// Renames should be checked and tested before being executed.
55653-	//
55654-	// @since version 3.12.0
55655-	PrepareProvider bool `json:"prepareProvider,omitempty"`
55656-	WorkDoneProgressOptions
55657-}
55658-
55659-// The parameters of a {@link RenameRequest}.
55660-type RenameParams struct { // line 5874
55661-	// The document to rename.
55662-	TextDocument TextDocumentIdentifier `json:"textDocument"`
55663-	// The position at which this request was sent.
55664-	Position Position `json:"position"`
55665-	// The new name of the symbol. If the given name is not valid the
55666-	// request must return a {@link ResponseError} with an
55667-	// appropriate message set.
55668-	NewName string `json:"newName"`
55669-	WorkDoneProgressParams
55670-}
55671-
55672-// Registration options for a {@link RenameRequest}.
55673-type RenameRegistrationOptions struct { // line 5910
55674-	TextDocumentRegistrationOptions
55675-	RenameOptions
55676-}
55677-
55678-// A generic resource operation.
55679-type ResourceOperation struct { // line 9393
55680-	// The resource operation kind.
55681-	Kind string `json:"kind"`
55682-	// An optional annotation identifier describing the operation.
55683-	//
55684-	// @since 3.16.0
55685-	AnnotationID *ChangeAnnotationIdentifier `json:"annotationId,omitempty"`
55686-}
55687-type ResourceOperationKind string // line 13669
55688-// Save options.
55689-type SaveOptions struct { // line 8465
55690-	// The client is supposed to include the content on save.
55691-	IncludeText bool `json:"includeText,omitempty"`
55692-}
55693-
55694-// A selection range represents a part of a selection hierarchy. A selection range
55695-// may have a parent selection range that contains it.
55696-type SelectionRange struct { // line 2569
55697-	// The {@link Range range} of this selection range.
55698-	Range Range `json:"range"`
55699-	// The parent selection range containing this range. Therefore `parent.range` must contain `this.range`.
55700-	Parent *SelectionRange `json:"parent,omitempty"`
55701-}
55702-type SelectionRangeClientCapabilities struct { // line 12058
55703-	// Whether implementation supports dynamic registration for selection range providers. If this is set to `true`
55704-	// the client supports the new `SelectionRangeRegistrationOptions` return value for the corresponding server
55705-	// capability as well.
55706-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
55707-}
55708-type SelectionRangeOptions struct { // line 6524
55709-	WorkDoneProgressOptions
55710-}
55711-
55712-// A parameter literal used in selection range requests.
55713-type SelectionRangeParams struct { // line 2534
55714-	// The text document.
55715-	TextDocument TextDocumentIdentifier `json:"textDocument"`
55716-	// The positions inside the text document.
55717-	Positions []Position `json:"positions"`
55718-	WorkDoneProgressParams
55719-	PartialResultParams
55720-}
55721-type SelectionRangeRegistrationOptions struct { // line 2592
55722-	SelectionRangeOptions
55723-	TextDocumentRegistrationOptions
55724-	StaticRegistrationOptions
55725-}
55726-
55727-// A set of predefined token modifiers. This set is not fixed
55728-// an clients can specify additional token types via the
55729-// corresponding client capabilities.
55730-//
55731-// @since 3.16.0
55732-type SemanticTokenModifiers string // line 12670
55733-// A set of predefined token types. This set is not fixed
55734-// an clients can specify additional token types via the
55735-// corresponding client capabilities.
55736-//
55737-// @since 3.16.0
55738-type SemanticTokenTypes string // line 12563
55739-// @since 3.16.0
55740-type SemanticTokens struct { // line 2880
55741-	// An optional result id. If provided and clients support delta updating
55742-	// the client will include the result id in the next semantic token request.
55743-	// A server can then instead of computing all semantic tokens again simply
55744-	// send a delta.
55745-	ResultID string `json:"resultId,omitempty"`
55746-	// The actual tokens.
55747-	Data []uint32 `json:"data"`
55748-}
55749-
55750-// @since 3.16.0
55751-type SemanticTokensClientCapabilities struct { // line 12157
55752-	// Whether implementation supports dynamic registration. If this is set to `true`
55753-	// the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
55754-	// return value for the corresponding server capability as well.
55755-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
55756-	// Which requests the client supports and might send to the server
55757-	// depending on the server's capability. Please note that clients might not
55758-	// show semantic tokens or degrade some of the user experience if a range
55759-	// or full request is advertised by the client but not provided by the
55760-	// server. If for example the client capability `requests.full` and
55761-	// `request.range` are both set to true but the server only provides a
55762-	// range provider the client might not render a minimap correctly or might
55763-	// even decide to not show any semantic tokens at all.
55764-	Requests PRequestsPSemanticTokens `json:"requests"`
55765-	// The token types that the client supports.
55766-	TokenTypes []string `json:"tokenTypes"`
55767-	// The token modifiers that the client supports.
55768-	TokenModifiers []string `json:"tokenModifiers"`
55769-	// The token formats the clients supports.
55770-	Formats []TokenFormat `json:"formats"`
55771-	// Whether the client supports tokens that can overlap each other.
55772-	OverlappingTokenSupport bool `json:"overlappingTokenSupport,omitempty"`
55773-	// Whether the client supports tokens that can span multiple lines.
55774-	MultilineTokenSupport bool `json:"multilineTokenSupport,omitempty"`
55775-	// Whether the client allows the server to actively cancel a
55776-	// semantic token request, e.g. supports returning
55777-	// LSPErrorCodes.ServerCancelled. If a server does the client
55778-	// needs to retrigger the request.
55779-	//
55780-	// @since 3.17.0
55781-	ServerCancelSupport bool `json:"serverCancelSupport,omitempty"`
55782-	// Whether the client uses semantic tokens to augment existing
55783-	// syntax tokens. If set to `true` client side created syntax
55784-	// tokens and semantic tokens are both used for colorization. If
55785-	// set to `false` the client only uses the returned semantic tokens
55786-	// for colorization.
55787-	//
55788-	// If the value is `undefined` then the client behavior is not
55789-	// specified.
55790-	//
55791-	// @since 3.17.0
55792-	AugmentsSyntaxTokens bool `json:"augmentsSyntaxTokens,omitempty"`
55793-}
55794-
55795-// @since 3.16.0
55796-type SemanticTokensDelta struct { // line 2979
55797-	ResultID string `json:"resultId,omitempty"`
55798-	// The semantic token edits to transform a previous result into a new result.
55799-	Edits []SemanticTokensEdit `json:"edits"`
55800-}
55801-
55802-// @since 3.16.0
55803-type SemanticTokensDeltaParams struct { // line 2946
55804-	// The text document.
55805-	TextDocument TextDocumentIdentifier `json:"textDocument"`
55806-	// The result id of a previous response. The result Id can either point to a full response
55807-	// or a delta response depending on what was received last.
55808-	PreviousResultID string `json:"previousResultId"`
55809-	WorkDoneProgressParams
55810-	PartialResultParams
55811-}
55812-
55813-// @since 3.16.0
55814-type SemanticTokensDeltaPartialResult struct { // line 3005
55815-	Edits []SemanticTokensEdit `json:"edits"`
55816-}
55817-
55818-// @since 3.16.0
55819-type SemanticTokensEdit struct { // line 6617
55820-	// The start offset of the edit.
55821-	Start uint32 `json:"start"`
55822-	// The count of elements to remove.
55823-	DeleteCount uint32 `json:"deleteCount"`
55824-	// The elements to insert.
55825-	Data []uint32 `json:"data,omitempty"`
55826-}
55827-
55828-// @since 3.16.0
55829-type SemanticTokensLegend struct { // line 9314
55830-	// The token types a server uses.
55831-	TokenTypes []string `json:"tokenTypes"`
55832-	// The token modifiers a server uses.
55833-	TokenModifiers []string `json:"tokenModifiers"`
55834-}
55835-
55836-// @since 3.16.0
55837-type SemanticTokensOptions struct { // line 6546
55838-	// The legend used by the server
55839-	Legend SemanticTokensLegend `json:"legend"`
55840-	// Server supports providing semantic tokens for a specific range
55841-	// of a document.
55842-	Range *Or_SemanticTokensOptions_range `json:"range,omitempty"`
55843-	// Server supports providing semantic tokens for a full document.
55844-	Full *Or_SemanticTokensOptions_full `json:"full,omitempty"`
55845-	WorkDoneProgressOptions
55846-}
55847-
55848-// @since 3.16.0
55849-type SemanticTokensParams struct { // line 2855
55850-	// The text document.
55851-	TextDocument TextDocumentIdentifier `json:"textDocument"`
55852-	WorkDoneProgressParams
55853-	PartialResultParams
55854-}
55855-
55856-// @since 3.16.0
55857-type SemanticTokensPartialResult struct { // line 2907
55858-	Data []uint32 `json:"data"`
55859-}
55860-
55861-// @since 3.16.0
55862-type SemanticTokensRangeParams struct { // line 3022
55863-	// The text document.
55864-	TextDocument TextDocumentIdentifier `json:"textDocument"`
55865-	// The range the semantic tokens are requested for.
55866-	Range Range `json:"range"`
55867-	WorkDoneProgressParams
55868-	PartialResultParams
55869-}
55870-
55871-// @since 3.16.0
55872-type SemanticTokensRegistrationOptions struct { // line 2924
55873-	TextDocumentRegistrationOptions
55874-	SemanticTokensOptions
55875-	StaticRegistrationOptions
55876-}
55877-
55878-// @since 3.16.0
55879-type SemanticTokensWorkspaceClientCapabilities struct { // line 10977
55880-	// Whether the client implementation supports a refresh request sent from
55881-	// the server to the client.
55882-	//
55883-	// Note that this event is global and will force the client to refresh all
55884-	// semantic tokens currently shown. It should be used with absolute care
55885-	// and is useful for situation where a server for example detects a project
55886-	// wide change that requires such a calculation.
55887-	RefreshSupport bool `json:"refreshSupport,omitempty"`
55888-}
55889-
55890-// Defines the capabilities provided by a language
55891-// server.
55892-type ServerCapabilities struct { // line 7809
55893-	// The position encoding the server picked from the encodings offered
55894-	// by the client via the client capability `general.positionEncodings`.
55895-	//
55896-	// If the client didn't provide any position encodings the only valid
55897-	// value that a server can return is 'utf-16'.
55898-	//
55899-	// If omitted it defaults to 'utf-16'.
55900-	//
55901-	// @since 3.17.0
55902-	PositionEncoding *PositionEncodingKind `json:"positionEncoding,omitempty"`
55903-	// Defines how text documents are synced. Is either a detailed structure
55904-	// defining each notification or for backwards compatibility the
55905-	// TextDocumentSyncKind number.
55906-	TextDocumentSync interface{} `json:"textDocumentSync,omitempty"`
55907-	// Defines how notebook documents are synced.
55908-	//
55909-	// @since 3.17.0
55910-	NotebookDocumentSync *Or_ServerCapabilities_notebookDocumentSync `json:"notebookDocumentSync,omitempty"`
55911-	// The server provides completion support.
55912-	CompletionProvider *CompletionOptions `json:"completionProvider,omitempty"`
55913-	// The server provides hover support.
55914-	HoverProvider *Or_ServerCapabilities_hoverProvider `json:"hoverProvider,omitempty"`
55915-	// The server provides signature help support.
55916-	SignatureHelpProvider *SignatureHelpOptions `json:"signatureHelpProvider,omitempty"`
55917-	// The server provides Goto Declaration support.
55918-	DeclarationProvider *Or_ServerCapabilities_declarationProvider `json:"declarationProvider,omitempty"`
55919-	// The server provides goto definition support.
55920-	DefinitionProvider *Or_ServerCapabilities_definitionProvider `json:"definitionProvider,omitempty"`
55921-	// The server provides Goto Type Definition support.
55922-	TypeDefinitionProvider *Or_ServerCapabilities_typeDefinitionProvider `json:"typeDefinitionProvider,omitempty"`
55923-	// The server provides Goto Implementation support.
55924-	ImplementationProvider *Or_ServerCapabilities_implementationProvider `json:"implementationProvider,omitempty"`
55925-	// The server provides find references support.
55926-	ReferencesProvider *Or_ServerCapabilities_referencesProvider `json:"referencesProvider,omitempty"`
55927-	// The server provides document highlight support.
55928-	DocumentHighlightProvider *Or_ServerCapabilities_documentHighlightProvider `json:"documentHighlightProvider,omitempty"`
55929-	// The server provides document symbol support.
55930-	DocumentSymbolProvider *Or_ServerCapabilities_documentSymbolProvider `json:"documentSymbolProvider,omitempty"`
55931-	// The server provides code actions. CodeActionOptions may only be
55932-	// specified if the client states that it supports
55933-	// `codeActionLiteralSupport` in its initial `initialize` request.
55934-	CodeActionProvider interface{} `json:"codeActionProvider,omitempty"`
55935-	// The server provides code lens.
55936-	CodeLensProvider *CodeLensOptions `json:"codeLensProvider,omitempty"`
55937-	// The server provides document link support.
55938-	DocumentLinkProvider *DocumentLinkOptions `json:"documentLinkProvider,omitempty"`
55939-	// The server provides color provider support.
55940-	ColorProvider *Or_ServerCapabilities_colorProvider `json:"colorProvider,omitempty"`
55941-	// The server provides workspace symbol support.
55942-	WorkspaceSymbolProvider *Or_ServerCapabilities_workspaceSymbolProvider `json:"workspaceSymbolProvider,omitempty"`
55943-	// The server provides document formatting.
55944-	DocumentFormattingProvider *Or_ServerCapabilities_documentFormattingProvider `json:"documentFormattingProvider,omitempty"`
55945-	// The server provides document range formatting.
55946-	DocumentRangeFormattingProvider *Or_ServerCapabilities_documentRangeFormattingProvider `json:"documentRangeFormattingProvider,omitempty"`
55947-	// The server provides document formatting on typing.
55948-	DocumentOnTypeFormattingProvider *DocumentOnTypeFormattingOptions `json:"documentOnTypeFormattingProvider,omitempty"`
55949-	// The server provides rename support. RenameOptions may only be
55950-	// specified if the client states that it supports
55951-	// `prepareSupport` in its initial `initialize` request.
55952-	RenameProvider interface{} `json:"renameProvider,omitempty"`
55953-	// The server provides folding provider support.
55954-	FoldingRangeProvider *Or_ServerCapabilities_foldingRangeProvider `json:"foldingRangeProvider,omitempty"`
55955-	// The server provides selection range support.
55956-	SelectionRangeProvider *Or_ServerCapabilities_selectionRangeProvider `json:"selectionRangeProvider,omitempty"`
55957-	// The server provides execute command support.
55958-	ExecuteCommandProvider *ExecuteCommandOptions `json:"executeCommandProvider,omitempty"`
55959-	// The server provides call hierarchy support.
55960-	//
55961-	// @since 3.16.0
55962-	CallHierarchyProvider *Or_ServerCapabilities_callHierarchyProvider `json:"callHierarchyProvider,omitempty"`
55963-	// The server provides linked editing range support.
55964-	//
55965-	// @since 3.16.0
55966-	LinkedEditingRangeProvider *Or_ServerCapabilities_linkedEditingRangeProvider `json:"linkedEditingRangeProvider,omitempty"`
55967-	// The server provides semantic tokens support.
55968-	//
55969-	// @since 3.16.0
55970-	SemanticTokensProvider interface{} `json:"semanticTokensProvider,omitempty"`
55971-	// The server provides moniker support.
55972-	//
55973-	// @since 3.16.0
55974-	MonikerProvider *Or_ServerCapabilities_monikerProvider `json:"monikerProvider,omitempty"`
55975-	// The server provides type hierarchy support.
55976-	//
55977-	// @since 3.17.0
55978-	TypeHierarchyProvider *Or_ServerCapabilities_typeHierarchyProvider `json:"typeHierarchyProvider,omitempty"`
55979-	// The server provides inline values.
55980-	//
55981-	// @since 3.17.0
55982-	InlineValueProvider *Or_ServerCapabilities_inlineValueProvider `json:"inlineValueProvider,omitempty"`
55983-	// The server provides inlay hints.
55984-	//
55985-	// @since 3.17.0
55986-	InlayHintProvider interface{} `json:"inlayHintProvider,omitempty"`
55987-	// The server has support for pull model diagnostics.
55988-	//
55989-	// @since 3.17.0
55990-	DiagnosticProvider *Or_ServerCapabilities_diagnosticProvider `json:"diagnosticProvider,omitempty"`
55991-	// Workspace specific server capabilities.
55992-	Workspace *Workspace6Gn `json:"workspace,omitempty"`
55993-	// Experimental server capabilities.
55994-	Experimental interface{} `json:"experimental,omitempty"`
55995-}
55996-type SetTraceParams struct { // line 6147
55997-	Value TraceValues `json:"value"`
55998-}
55999-
56000-// Client capabilities for the showDocument request.
56001-//
56002-// @since 3.16.0
56003-type ShowDocumentClientCapabilities struct { // line 12485
56004-	// The client has support for the showDocument
56005-	// request.
56006-	Support bool `json:"support"`
56007-}
56008-
56009-// Params to show a document.
56010-//
56011-// @since 3.16.0
56012-type ShowDocumentParams struct { // line 3055
56013-	// The document uri to show.
56014-	URI URI `json:"uri"`
56015-	// Indicates to show the resource in an external program.
56016-	// To show for example `https://code.visualstudio.com/`
56017-	// in the default WEB browser set `external` to `true`.
56018-	External bool `json:"external,omitempty"`
56019-	// An optional property to indicate whether the editor
56020-	// showing the document should take focus or not.
56021-	// Clients might ignore this property if an external
56022-	// program is started.
56023-	TakeFocus bool `json:"takeFocus,omitempty"`
56024-	// An optional selection range if the document is a text
56025-	// document. Clients might ignore the property if an
56026-	// external program is started or the file is not a text
56027-	// file.
56028-	Selection *Range `json:"selection,omitempty"`
56029-}
56030-
56031-// The result of a showDocument request.
56032-//
56033-// @since 3.16.0
56034-type ShowDocumentResult struct { // line 3097
56035-	// A boolean indicating if the show was successful.
56036-	Success bool `json:"success"`
56037-}
56038-
56039-// The parameters of a notification message.
56040-type ShowMessageParams struct { // line 4183
56041-	// The message type. See {@link MessageType}
56042-	Type MessageType `json:"type"`
56043-	// The actual message.
56044-	Message string `json:"message"`
56045-}
56046-
56047-// Show message request client capabilities
56048-type ShowMessageRequestClientCapabilities struct { // line 12458
56049-	// Capabilities specific to the `MessageActionItem` type.
56050-	MessageActionItem *PMessageActionItemPShowMessage `json:"messageActionItem,omitempty"`
56051-}
56052-type ShowMessageRequestParams struct { // line 4205
56053-	// The message type. See {@link MessageType}
56054-	Type MessageType `json:"type"`
56055-	// The actual message.
56056-	Message string `json:"message"`
56057-	// The message action items to present.
56058-	Actions []MessageActionItem `json:"actions,omitempty"`
56059-}
56060-
56061-// Signature help represents the signature of something
56062-// callable. There can be multiple signature but only one
56063-// active and only one active parameter.
56064-type SignatureHelp struct { // line 4968
56065-	// One or more signatures.
56066-	Signatures []SignatureInformation `json:"signatures"`
56067-	// The active signature. If omitted or the value lies outside the
56068-	// range of `signatures` the value defaults to zero or is ignored if
56069-	// the `SignatureHelp` has no signatures.
56070-	//
56071-	// Whenever possible implementors should make an active decision about
56072-	// the active signature and shouldn't rely on a default value.
56073-	//
56074-	// In future version of the protocol this property might become
56075-	// mandatory to better express this.
56076-	ActiveSignature uint32 `json:"activeSignature,omitempty"`
56077-	// The active parameter of the active signature. If omitted or the value
56078-	// lies outside the range of `signatures[activeSignature].parameters`
56079-	// defaults to 0 if the active signature has parameters. If
56080-	// the active signature has no parameters it is ignored.
56081-	// In future version of the protocol this property might become
56082-	// mandatory to better express the active parameter if the
56083-	// active signature does have any.
56084-	ActiveParameter uint32 `json:"activeParameter,omitempty"`
56085-}
56086-
56087-// Client Capabilities for a {@link SignatureHelpRequest}.
56088-type SignatureHelpClientCapabilities struct { // line 11428
56089-	// Whether signature help supports dynamic registration.
56090-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
56091-	// The client supports the following `SignatureInformation`
56092-	// specific properties.
56093-	SignatureInformation *PSignatureInformationPSignatureHelp `json:"signatureInformation,omitempty"`
56094-	// The client supports to send additional context information for a
56095-	// `textDocument/signatureHelp` request. A client that opts into
56096-	// contextSupport will also support the `retriggerCharacters` on
56097-	// `SignatureHelpOptions`.
56098-	//
56099-	// @since 3.15.0
56100-	ContextSupport bool `json:"contextSupport,omitempty"`
56101-}
56102-
56103-// Additional information about the context in which a signature help request was triggered.
56104-//
56105-// @since 3.15.0
56106-type SignatureHelpContext struct { // line 8787
56107-	// Action that caused signature help to be triggered.
56108-	TriggerKind SignatureHelpTriggerKind `json:"triggerKind"`
56109-	// Character that caused signature help to be triggered.
56110-	//
56111-	// This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter`
56112-	TriggerCharacter string `json:"triggerCharacter,omitempty"`
56113-	// `true` if signature help was already showing when it was triggered.
56114-	//
56115-	// Retriggers occurs when the signature help is already active and can be caused by actions such as
56116-	// typing a trigger character, a cursor move, or document content changes.
56117-	IsRetrigger bool `json:"isRetrigger"`
56118-	// The currently active `SignatureHelp`.
56119-	//
56120-	// The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on
56121-	// the user navigating through available signatures.
56122-	ActiveSignatureHelp *SignatureHelp `json:"activeSignatureHelp,omitempty"`
56123-}
56124-
56125-// Server Capabilities for a {@link SignatureHelpRequest}.
56126-type SignatureHelpOptions struct { // line 8882
56127-	// List of characters that trigger signature help automatically.
56128-	TriggerCharacters []string `json:"triggerCharacters,omitempty"`
56129-	// List of characters that re-trigger signature help.
56130-	//
56131-	// These trigger characters are only active when signature help is already showing. All trigger characters
56132-	// are also counted as re-trigger characters.
56133-	//
56134-	// @since 3.15.0
56135-	RetriggerCharacters []string `json:"retriggerCharacters,omitempty"`
56136-	WorkDoneProgressOptions
56137-}
56138-
56139-// Parameters for a {@link SignatureHelpRequest}.
56140-type SignatureHelpParams struct { // line 4940
56141-	// The signature help context. This is only available if the client specifies
56142-	// to send this using the client capability `textDocument.signatureHelp.contextSupport === true`
56143-	//
56144-	// @since 3.15.0
56145-	Context *SignatureHelpContext `json:"context,omitempty"`
56146-	TextDocumentPositionParams
56147-	WorkDoneProgressParams
56148-}
56149-
56150-// Registration options for a {@link SignatureHelpRequest}.
56151-type SignatureHelpRegistrationOptions struct { // line 5003
56152-	TextDocumentRegistrationOptions
56153-	SignatureHelpOptions
56154-}
56155-
56156-// How a signature help was triggered.
56157-//
56158-// @since 3.15.0
56159-type SignatureHelpTriggerKind uint32 // line 13580
56160-// Represents the signature of something callable. A signature
56161-// can have a label, like a function-name, a doc-comment, and
56162-// a set of parameters.
56163-type SignatureInformation struct { // line 8828
56164-	// The label of this signature. Will be shown in
56165-	// the UI.
56166-	Label string `json:"label"`
56167-	// The human-readable doc-comment of this signature. Will be shown
56168-	// in the UI but can be omitted.
56169-	Documentation *Or_SignatureInformation_documentation `json:"documentation,omitempty"`
56170-	// The parameters of this signature.
56171-	Parameters []ParameterInformation `json:"parameters,omitempty"`
56172-	// The index of the active parameter.
56173-	//
56174-	// If provided, this is used in place of `SignatureHelp.activeParameter`.
56175-	//
56176-	// @since 3.16.0
56177-	ActiveParameter uint32 `json:"activeParameter,omitempty"`
56178-}
56179-
56180-// Static registration options to be returned in the initialize
56181-// request.
56182-type StaticRegistrationOptions struct { // line 6343
56183-	// The id used to register the request. The id can be used to deregister
56184-	// the request again. See also Registration#id.
56185-	ID string `json:"id,omitempty"`
56186-}
56187-
56188-// Represents information about programming constructs like variables, classes,
56189-// interfaces etc.
56190-type SymbolInformation struct { // line 5181
56191-	// extends BaseSymbolInformation
56192-	// Indicates if this symbol is deprecated.
56193-	//
56194-	// @deprecated Use tags instead
56195-	Deprecated bool `json:"deprecated,omitempty"`
56196-	// The location of this symbol. The location's range is used by a tool
56197-	// to reveal the location in the editor. If the symbol is selected in the
56198-	// tool the range's start information is used to position the cursor. So
56199-	// the range usually spans more than the actual symbol's name and does
56200-	// normally include things like visibility modifiers.
56201-	//
56202-	// The range doesn't have to denote a node range in the sense of an abstract
56203-	// syntax tree. It can therefore not be used to re-construct a hierarchy of
56204-	// the symbols.
56205-	Location Location `json:"location"`
56206-	// The name of this symbol.
56207-	Name string `json:"name"`
56208-	// The kind of this symbol.
56209-	Kind SymbolKind `json:"kind"`
56210-	// Tags for this symbol.
56211-	//
56212-	// @since 3.16.0
56213-	Tags []SymbolTag `json:"tags,omitempty"`
56214-	// The name of the symbol containing this symbol. This information is for
56215-	// user interface purposes (e.g. to render a qualifier in the user interface
56216-	// if necessary). It can't be used to re-infer a hierarchy for the document
56217-	// symbols.
56218-	ContainerName string `json:"containerName,omitempty"`
56219-}
56220-
56221-// A symbol kind.
56222-type SymbolKind uint32 // line 12841
56223-// Symbol tags are extra annotations that tweak the rendering of a symbol.
56224-//
56225-// @since 3.16
56226-type SymbolTag uint32 // line 12955
56227-// Describe options to be used when registered for text document change events.
56228-type TextDocumentChangeRegistrationOptions struct { // line 4312
56229-	// How documents are synced to the server.
56230-	SyncKind TextDocumentSyncKind `json:"syncKind"`
56231-	TextDocumentRegistrationOptions
56232-}
56233-
56234-// Text document specific client capabilities.
56235-type TextDocumentClientCapabilities struct { // line 10323
56236-	// Defines which synchronization capabilities the client supports.
56237-	Synchronization *TextDocumentSyncClientCapabilities `json:"synchronization,omitempty"`
56238-	// Capabilities specific to the `textDocument/completion` request.
56239-	Completion CompletionClientCapabilities `json:"completion,omitempty"`
56240-	// Capabilities specific to the `textDocument/hover` request.
56241-	Hover *HoverClientCapabilities `json:"hover,omitempty"`
56242-	// Capabilities specific to the `textDocument/signatureHelp` request.
56243-	SignatureHelp *SignatureHelpClientCapabilities `json:"signatureHelp,omitempty"`
56244-	// Capabilities specific to the `textDocument/declaration` request.
56245-	//
56246-	// @since 3.14.0
56247-	Declaration *DeclarationClientCapabilities `json:"declaration,omitempty"`
56248-	// Capabilities specific to the `textDocument/definition` request.
56249-	Definition *DefinitionClientCapabilities `json:"definition,omitempty"`
56250-	// Capabilities specific to the `textDocument/typeDefinition` request.
56251-	//
56252-	// @since 3.6.0
56253-	TypeDefinition *TypeDefinitionClientCapabilities `json:"typeDefinition,omitempty"`
56254-	// Capabilities specific to the `textDocument/implementation` request.
56255-	//
56256-	// @since 3.6.0
56257-	Implementation *ImplementationClientCapabilities `json:"implementation,omitempty"`
56258-	// Capabilities specific to the `textDocument/references` request.
56259-	References *ReferenceClientCapabilities `json:"references,omitempty"`
56260-	// Capabilities specific to the `textDocument/documentHighlight` request.
56261-	DocumentHighlight *DocumentHighlightClientCapabilities `json:"documentHighlight,omitempty"`
56262-	// Capabilities specific to the `textDocument/documentSymbol` request.
56263-	DocumentSymbol DocumentSymbolClientCapabilities `json:"documentSymbol,omitempty"`
56264-	// Capabilities specific to the `textDocument/codeAction` request.
56265-	CodeAction CodeActionClientCapabilities `json:"codeAction,omitempty"`
56266-	// Capabilities specific to the `textDocument/codeLens` request.
56267-	CodeLens *CodeLensClientCapabilities `json:"codeLens,omitempty"`
56268-	// Capabilities specific to the `textDocument/documentLink` request.
56269-	DocumentLink *DocumentLinkClientCapabilities `json:"documentLink,omitempty"`
56270-	// Capabilities specific to the `textDocument/documentColor` and the
56271-	// `textDocument/colorPresentation` request.
56272-	//
56273-	// @since 3.6.0
56274-	ColorProvider *DocumentColorClientCapabilities `json:"colorProvider,omitempty"`
56275-	// Capabilities specific to the `textDocument/formatting` request.
56276-	Formatting *DocumentFormattingClientCapabilities `json:"formatting,omitempty"`
56277-	// Capabilities specific to the `textDocument/rangeFormatting` request.
56278-	RangeFormatting *DocumentRangeFormattingClientCapabilities `json:"rangeFormatting,omitempty"`
56279-	// Capabilities specific to the `textDocument/onTypeFormatting` request.
56280-	OnTypeFormatting *DocumentOnTypeFormattingClientCapabilities `json:"onTypeFormatting,omitempty"`
56281-	// Capabilities specific to the `textDocument/rename` request.
56282-	Rename *RenameClientCapabilities `json:"rename,omitempty"`
56283-	// Capabilities specific to the `textDocument/foldingRange` request.
56284-	//
56285-	// @since 3.10.0
56286-	FoldingRange *FoldingRangeClientCapabilities `json:"foldingRange,omitempty"`
56287-	// Capabilities specific to the `textDocument/selectionRange` request.
56288-	//
56289-	// @since 3.15.0
56290-	SelectionRange *SelectionRangeClientCapabilities `json:"selectionRange,omitempty"`
56291-	// Capabilities specific to the `textDocument/publishDiagnostics` notification.
56292-	PublishDiagnostics PublishDiagnosticsClientCapabilities `json:"publishDiagnostics,omitempty"`
56293-	// Capabilities specific to the various call hierarchy requests.
56294-	//
56295-	// @since 3.16.0
56296-	CallHierarchy *CallHierarchyClientCapabilities `json:"callHierarchy,omitempty"`
56297-	// Capabilities specific to the various semantic token request.
56298-	//
56299-	// @since 3.16.0
56300-	SemanticTokens SemanticTokensClientCapabilities `json:"semanticTokens,omitempty"`
56301-	// Capabilities specific to the `textDocument/linkedEditingRange` request.
56302-	//
56303-	// @since 3.16.0
56304-	LinkedEditingRange *LinkedEditingRangeClientCapabilities `json:"linkedEditingRange,omitempty"`
56305-	// Client capabilities specific to the `textDocument/moniker` request.
56306-	//
56307-	// @since 3.16.0
56308-	Moniker *MonikerClientCapabilities `json:"moniker,omitempty"`
56309-	// Capabilities specific to the various type hierarchy requests.
56310-	//
56311-	// @since 3.17.0
56312-	TypeHierarchy *TypeHierarchyClientCapabilities `json:"typeHierarchy,omitempty"`
56313-	// Capabilities specific to the `textDocument/inlineValue` request.
56314-	//
56315-	// @since 3.17.0
56316-	InlineValue *InlineValueClientCapabilities `json:"inlineValue,omitempty"`
56317-	// Capabilities specific to the `textDocument/inlayHint` request.
56318-	//
56319-	// @since 3.17.0
56320-	InlayHint *InlayHintClientCapabilities `json:"inlayHint,omitempty"`
56321-	// Capabilities specific to the diagnostic pull model.
56322-	//
56323-	// @since 3.17.0
56324-	Diagnostic *DiagnosticClientCapabilities `json:"diagnostic,omitempty"`
56325-}
56326-
56327-// An event describing a change to a text document. If only a text is provided
56328-// it is considered to be the full content of the document.
56329-type TextDocumentContentChangeEvent = Msg_TextDocumentContentChangeEvent // (alias) line 14002
56330-// Describes textual changes on a text document. A TextDocumentEdit describes all changes
56331-// on a document version Si and after they are applied move the document to version Si+1.
56332-// So the creator of a TextDocumentEdit doesn't need to sort the array of edits or do any
56333-// kind of ordering. However the edits must be non overlapping.
56334-type TextDocumentEdit struct { // line 6677
56335-	// The text document to change.
56336-	TextDocument OptionalVersionedTextDocumentIdentifier `json:"textDocument"`
56337-	// The edits to be applied.
56338-	//
56339-	// @since 3.16.0 - support for AnnotatedTextEdit. This is guarded using a
56340-	// client capability.
56341-	Edits []TextEdit `json:"edits"`
56342-}
56343-
56344-// A document filter denotes a document by different properties like
56345-// the {@link TextDocument.languageId language}, the {@link Uri.scheme scheme} of
56346-// its resource, or a glob-pattern that is applied to the {@link TextDocument.fileName path}.
56347-//
56348-// Glob patterns can have the following syntax:
56349-//
56350-//   - `*` to match one or more characters in a path segment
56351-//   - `?` to match on one character in a path segment
56352-//   - `**` to match any number of path segments, including none
56353-//   - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files)
56354-//   - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
56355-//   - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
56356-//
56357-// @sample A language filter that applies to typescript files on disk: `{ language: 'typescript', scheme: 'file' }`
56358-// @sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**package.json' }`
56359-//
56360-// @since 3.17.0
56361-type TextDocumentFilter = Msg_TextDocumentFilter // (alias) line 14145
56362-// A literal to identify a text document in the client.
56363-type TextDocumentIdentifier struct { // line 6419
56364-	// The text document's uri.
56365-	URI DocumentURI `json:"uri"`
56366-}
56367-
56368-// An item to transfer a text document from the client to the
56369-// server.
56370-type TextDocumentItem struct { // line 7405
56371-	// The text document's uri.
56372-	URI DocumentURI `json:"uri"`
56373-	// The text document's language identifier.
56374-	LanguageID string `json:"languageId"`
56375-	// The version number of this document (it will increase after each
56376-	// change, including undo/redo).
56377-	Version int32 `json:"version"`
56378-	// The content of the opened text document.
56379-	Text string `json:"text"`
56380-}
56381-
56382-// A parameter literal used in requests to pass a text document and a position inside that
56383-// document.
56384-type TextDocumentPositionParams struct { // line 6222
56385-	// The text document.
56386-	TextDocument TextDocumentIdentifier `json:"textDocument"`
56387-	// The position inside the text document.
56388-	Position Position `json:"position"`
56389-}
56390-
56391-// General text document registration options.
56392-type TextDocumentRegistrationOptions struct { // line 2368
56393-	// A document selector to identify the scope of the registration. If set to null
56394-	// the document selector provided on the client side will be used.
56395-	DocumentSelector DocumentSelector `json:"documentSelector"`
56396-}
56397-
56398-// Represents reasons why a text document is saved.
56399-type TextDocumentSaveReason uint32 // line 13109
56400-// Save registration options.
56401-type TextDocumentSaveRegistrationOptions struct { // line 4369
56402-	TextDocumentRegistrationOptions
56403-	SaveOptions
56404-}
56405-type TextDocumentSyncClientCapabilities struct { // line 11127
56406-	// Whether text document synchronization supports dynamic registration.
56407-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
56408-	// The client supports sending will save notifications.
56409-	WillSave bool `json:"willSave,omitempty"`
56410-	// The client supports sending a will save request and
56411-	// waits for a response providing text edits which will
56412-	// be applied to the document before it is saved.
56413-	WillSaveWaitUntil bool `json:"willSaveWaitUntil,omitempty"`
56414-	// The client supports did save notifications.
56415-	DidSave bool `json:"didSave,omitempty"`
56416-}
56417-
56418-// Defines how the host (editor) should sync
56419-// document changes to the language server.
56420-type TextDocumentSyncKind uint32      // line 13084
56421-type TextDocumentSyncOptions struct { // line 9736
56422-	// Open and close notifications are sent to the server. If omitted open close notification should not
56423-	// be sent.
56424-	OpenClose bool `json:"openClose,omitempty"`
56425-	// Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full
56426-	// and TextDocumentSyncKind.Incremental. If omitted it defaults to TextDocumentSyncKind.None.
56427-	Change TextDocumentSyncKind `json:"change,omitempty"`
56428-	// If present will save notifications are sent to the server. If omitted the notification should not be
56429-	// sent.
56430-	WillSave bool `json:"willSave,omitempty"`
56431-	// If present will save wait until requests are sent to the server. If omitted the request should not be
56432-	// sent.
56433-	WillSaveWaitUntil bool `json:"willSaveWaitUntil,omitempty"`
56434-	// If present save notifications are sent to the server. If omitted the notification should not be
56435-	// sent.
56436-	Save *SaveOptions `json:"save,omitempty"`
56437-}
56438-
56439-// A text edit applicable to a text document.
56440-type TextEdit struct { // line 4406
56441-	// The range of the text document to be manipulated. To insert
56442-	// text into a document create a range where start === end.
56443-	Range Range `json:"range"`
56444-	// The string to be inserted. For delete operations use an
56445-	// empty string.
56446-	NewText string `json:"newText"`
56447-}
56448-type TokenFormat string // line 13736
56449-type TraceValues string // line 13383
56450-// Since 3.6.0
56451-type TypeDefinitionClientCapabilities struct { // line 11559
56452-	// Whether implementation supports dynamic registration. If this is set to `true`
56453-	// the client supports the new `TypeDefinitionRegistrationOptions` return value
56454-	// for the corresponding server capability as well.
56455-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
56456-	// The client supports additional metadata in the form of definition links.
56457-	//
56458-	// Since 3.14.0
56459-	LinkSupport bool `json:"linkSupport,omitempty"`
56460-}
56461-type TypeDefinitionOptions struct { // line 6358
56462-	WorkDoneProgressOptions
56463-}
56464-type TypeDefinitionParams struct { // line 2123
56465-	TextDocumentPositionParams
56466-	WorkDoneProgressParams
56467-	PartialResultParams
56468-}
56469-type TypeDefinitionRegistrationOptions struct { // line 2143
56470-	TextDocumentRegistrationOptions
56471-	TypeDefinitionOptions
56472-	StaticRegistrationOptions
56473-}
56474-
56475-// @since 3.17.0
56476-type TypeHierarchyClientCapabilities struct { // line 12337
56477-	// Whether implementation supports dynamic registration. If this is set to `true`
56478-	// the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
56479-	// return value for the corresponding server capability as well.
56480-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
56481-}
56482-
56483-// @since 3.17.0
56484-type TypeHierarchyItem struct { // line 3410
56485-	// The name of this item.
56486-	Name string `json:"name"`
56487-	// The kind of this item.
56488-	Kind SymbolKind `json:"kind"`
56489-	// Tags for this item.
56490-	Tags []SymbolTag `json:"tags,omitempty"`
56491-	// More detail for this item, e.g. the signature of a function.
56492-	Detail string `json:"detail,omitempty"`
56493-	// The resource identifier of this item.
56494-	URI DocumentURI `json:"uri"`
56495-	// The range enclosing this symbol not including leading/trailing whitespace
56496-	// but everything else, e.g. comments and code.
56497-	Range Range `json:"range"`
56498-	// The range that should be selected and revealed when this symbol is being
56499-	// picked, e.g. the name of a function. Must be contained by the
56500-	// {@link TypeHierarchyItem.range `range`}.
56501-	SelectionRange Range `json:"selectionRange"`
56502-	// A data entry field that is preserved between a type hierarchy prepare and
56503-	// supertypes or subtypes requests. It could also be used to identify the
56504-	// type hierarchy in the server, helping improve the performance on
56505-	// resolving supertypes and subtypes.
56506-	Data interface{} `json:"data,omitempty"`
56507-}
56508-
56509-// Type hierarchy options used during static registration.
56510-//
56511-// @since 3.17.0
56512-type TypeHierarchyOptions struct { // line 6936
56513-	WorkDoneProgressOptions
56514-}
56515-
56516-// The parameter of a `textDocument/prepareTypeHierarchy` request.
56517-//
56518-// @since 3.17.0
56519-type TypeHierarchyPrepareParams struct { // line 3392
56520-	TextDocumentPositionParams
56521-	WorkDoneProgressParams
56522-}
56523-
56524-// Type hierarchy options used during static or dynamic registration.
56525-//
56526-// @since 3.17.0
56527-type TypeHierarchyRegistrationOptions struct { // line 3487
56528-	TextDocumentRegistrationOptions
56529-	TypeHierarchyOptions
56530-	StaticRegistrationOptions
56531-}
56532-
56533-// The parameter of a `typeHierarchy/subtypes` request.
56534-//
56535-// @since 3.17.0
56536-type TypeHierarchySubtypesParams struct { // line 3533
56537-	Item TypeHierarchyItem `json:"item"`
56538-	WorkDoneProgressParams
56539-	PartialResultParams
56540-}
56541-
56542-// The parameter of a `typeHierarchy/supertypes` request.
56543-//
56544-// @since 3.17.0
56545-type TypeHierarchySupertypesParams struct { // line 3509
56546-	Item TypeHierarchyItem `json:"item"`
56547-	WorkDoneProgressParams
56548-	PartialResultParams
56549-}
56550-
56551-// created for Tuple
56552-type UIntCommaUInt struct { // line 10076
56553-	Fld0 uint32 `json:"fld0"`
56554-	Fld1 uint32 `json:"fld1"`
56555-}
56556-type URI = string
56557-
56558-// A diagnostic report indicating that the last returned
56559-// report is still accurate.
56560-//
56561-// @since 3.17.0
56562-type UnchangedDocumentDiagnosticReport struct { // line 7270
56563-	// A document diagnostic report indicating
56564-	// no changes to the last result. A server can
56565-	// only return `unchanged` if result ids are
56566-	// provided.
56567-	Kind string `json:"kind"`
56568-	// A result id which will be sent on the next
56569-	// diagnostic request for the same document.
56570-	ResultID string `json:"resultId"`
56571-}
56572-
56573-// Moniker uniqueness level to define scope of the moniker.
56574-//
56575-// @since 3.16.0
56576-type UniquenessLevel string // line 12971
56577-// General parameters to unregister a request or notification.
56578-type Unregistration struct { // line 7628
56579-	// The id used to unregister the request or notification. Usually an id
56580-	// provided during the register request.
56581-	ID string `json:"id"`
56582-	// The method to unregister for.
56583-	Method string `json:"method"`
56584-}
56585-type UnregistrationParams struct { // line 4053
56586-	Unregisterations []Unregistration `json:"unregisterations"`
56587-}
56588-
56589-// A versioned notebook document identifier.
56590-//
56591-// @since 3.17.0
56592-type VersionedNotebookDocumentIdentifier struct { // line 7443
56593-	// The version number of this notebook document.
56594-	Version int32 `json:"version"`
56595-	// The notebook document's uri.
56596-	URI URI `json:"uri"`
56597-}
56598-
56599-// A text document identifier to denote a specific version of a text document.
56600-type VersionedTextDocumentIdentifier struct { // line 8445
56601-	// The version number of this document.
56602-	Version int32 `json:"version"`
56603-	TextDocumentIdentifier
56604-}
56605-type WatchKind = uint32                  // line 13505// The parameters sent in a will save text document notification.
56606-type WillSaveTextDocumentParams struct { // line 4384
56607-	// The document that will be saved.
56608-	TextDocument TextDocumentIdentifier `json:"textDocument"`
56609-	// The 'TextDocumentSaveReason'.
56610-	Reason TextDocumentSaveReason `json:"reason"`
56611-}
56612-type WindowClientCapabilities struct { // line 10629
56613-	// It indicates whether the client supports server initiated
56614-	// progress using the `window/workDoneProgress/create` request.
56615-	//
56616-	// The capability also controls Whether client supports handling
56617-	// of progress notifications. If set servers are allowed to report a
56618-	// `workDoneProgress` property in the request specific server
56619-	// capabilities.
56620-	//
56621-	// @since 3.15.0
56622-	WorkDoneProgress bool `json:"workDoneProgress,omitempty"`
56623-	// Capabilities specific to the showMessage request.
56624-	//
56625-	// @since 3.16.0
56626-	ShowMessage *ShowMessageRequestClientCapabilities `json:"showMessage,omitempty"`
56627-	// Capabilities specific to the showDocument request.
56628-	//
56629-	// @since 3.16.0
56630-	ShowDocument *ShowDocumentClientCapabilities `json:"showDocument,omitempty"`
56631-}
56632-type WorkDoneProgressBegin struct { // line 6040
56633-	Kind string `json:"kind"`
56634-	// Mandatory title of the progress operation. Used to briefly inform about
56635-	// the kind of operation being performed.
56636-	//
56637-	// Examples: "Indexing" or "Linking dependencies".
56638-	Title string `json:"title"`
56639-	// Controls if a cancel button should show to allow the user to cancel the
56640-	// long running operation. Clients that don't support cancellation are allowed
56641-	// to ignore the setting.
56642-	Cancellable bool `json:"cancellable,omitempty"`
56643-	// Optional, more detailed associated progress message. Contains
56644-	// complementary information to the `title`.
56645-	//
56646-	// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
56647-	// If unset, the previous progress message (if any) is still valid.
56648-	Message string `json:"message,omitempty"`
56649-	// Optional progress percentage to display (value 100 is considered 100%).
56650-	// If not provided infinite progress is assumed and clients are allowed
56651-	// to ignore the `percentage` value in subsequent in report notifications.
56652-	//
56653-	// The value should be steadily rising. Clients are free to ignore values
56654-	// that are not following this rule. The value range is [0, 100].
56655-	Percentage uint32 `json:"percentage,omitempty"`
56656-}
56657-type WorkDoneProgressCancelParams struct { // line 2625
56658-	// The token to be used to report progress.
56659-	Token ProgressToken `json:"token"`
56660-}
56661-type WorkDoneProgressCreateParams struct { // line 2612
56662-	// The token to be used to report progress.
56663-	Token ProgressToken `json:"token"`
56664-}
56665-type WorkDoneProgressEnd struct { // line 6126
56666-	Kind string `json:"kind"`
56667-	// Optional, a final message indicating to for example indicate the outcome
56668-	// of the operation.
56669-	Message string `json:"message,omitempty"`
56670-}
56671-type WorkDoneProgressOptions struct { // line 2355
56672-	WorkDoneProgress bool `json:"workDoneProgress,omitempty"`
56673-}
56674-
56675-// created for And
56676-type WorkDoneProgressOptionsAndTextDocumentRegistrationOptions struct { // line 196
56677-	WorkDoneProgressOptions
56678-	TextDocumentRegistrationOptions
56679-}
56680-type WorkDoneProgressParams struct { // line 6244
56681-	// An optional token that a server can use to report work done progress.
56682-	WorkDoneToken ProgressToken `json:"workDoneToken,omitempty"`
56683-}
56684-type WorkDoneProgressReport struct { // line 6087
56685-	Kind string `json:"kind"`
56686-	// Controls enablement state of a cancel button.
56687-	//
56688-	// Clients that don't support cancellation or don't support controlling the button's
56689-	// enablement state are allowed to ignore the property.
56690-	Cancellable bool `json:"cancellable,omitempty"`
56691-	// Optional, more detailed associated progress message. Contains
56692-	// complementary information to the `title`.
56693-	//
56694-	// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
56695-	// If unset, the previous progress message (if any) is still valid.
56696-	Message string `json:"message,omitempty"`
56697-	// Optional progress percentage to display (value 100 is considered 100%).
56698-	// If not provided infinite progress is assumed and clients are allowed
56699-	// to ignore the `percentage` value in subsequent in report notifications.
56700-	//
56701-	// The value should be steadily rising. Clients are free to ignore values
56702-	// that are not following this rule. The value range is [0, 100]
56703-	Percentage uint32 `json:"percentage,omitempty"`
56704-}
56705-
56706-// created for Literal (Lit_ServerCapabilities_workspace)
56707-type Workspace6Gn struct { // line 8404
56708-	// The server supports workspace folder.
56709-	//
56710-	// @since 3.6.0
56711-	WorkspaceFolders *WorkspaceFolders5Gn `json:"workspaceFolders,omitempty"`
56712-	// The server is interested in notifications/requests for operations on files.
56713-	//
56714-	// @since 3.16.0
56715-	FileOperations *FileOperationOptions `json:"fileOperations,omitempty"`
56716-}
56717-
56718-// Workspace specific client capabilities.
56719-type WorkspaceClientCapabilities struct { // line 10184
56720-	// The client supports applying batch edits
56721-	// to the workspace by supporting the request
56722-	// 'workspace/applyEdit'
56723-	ApplyEdit bool `json:"applyEdit,omitempty"`
56724-	// Capabilities specific to `WorkspaceEdit`s.
56725-	WorkspaceEdit *WorkspaceEditClientCapabilities `json:"workspaceEdit,omitempty"`
56726-	// Capabilities specific to the `workspace/didChangeConfiguration` notification.
56727-	DidChangeConfiguration DidChangeConfigurationClientCapabilities `json:"didChangeConfiguration,omitempty"`
56728-	// Capabilities specific to the `workspace/didChangeWatchedFiles` notification.
56729-	DidChangeWatchedFiles DidChangeWatchedFilesClientCapabilities `json:"didChangeWatchedFiles,omitempty"`
56730-	// Capabilities specific to the `workspace/symbol` request.
56731-	Symbol *WorkspaceSymbolClientCapabilities `json:"symbol,omitempty"`
56732-	// Capabilities specific to the `workspace/executeCommand` request.
56733-	ExecuteCommand *ExecuteCommandClientCapabilities `json:"executeCommand,omitempty"`
56734-	// The client has support for workspace folders.
56735-	//
56736-	// @since 3.6.0
56737-	WorkspaceFolders bool `json:"workspaceFolders,omitempty"`
56738-	// The client supports `workspace/configuration` requests.
56739-	//
56740-	// @since 3.6.0
56741-	Configuration bool `json:"configuration,omitempty"`
56742-	// Capabilities specific to the semantic token requests scoped to the
56743-	// workspace.
56744-	//
56745-	// @since 3.16.0.
56746-	SemanticTokens *SemanticTokensWorkspaceClientCapabilities `json:"semanticTokens,omitempty"`
56747-	// Capabilities specific to the code lens requests scoped to the
56748-	// workspace.
56749-	//
56750-	// @since 3.16.0.
56751-	CodeLens *CodeLensWorkspaceClientCapabilities `json:"codeLens,omitempty"`
56752-	// The client has support for file notifications/requests for user operations on files.
56753-	//
56754-	// Since 3.16.0
56755-	FileOperations *FileOperationClientCapabilities `json:"fileOperations,omitempty"`
56756-	// Capabilities specific to the inline values requests scoped to the
56757-	// workspace.
56758-	//
56759-	// @since 3.17.0.
56760-	InlineValue *InlineValueWorkspaceClientCapabilities `json:"inlineValue,omitempty"`
56761-	// Capabilities specific to the inlay hint requests scoped to the
56762-	// workspace.
56763-	//
56764-	// @since 3.17.0.
56765-	InlayHint *InlayHintWorkspaceClientCapabilities `json:"inlayHint,omitempty"`
56766-	// Capabilities specific to the diagnostic requests scoped to the
56767-	// workspace.
56768-	//
56769-	// @since 3.17.0.
56770-	Diagnostics *DiagnosticWorkspaceClientCapabilities `json:"diagnostics,omitempty"`
56771-}
56772-
56773-// Parameters of the workspace diagnostic request.
56774-//
56775-// @since 3.17.0
56776-type WorkspaceDiagnosticParams struct { // line 3877
56777-	// The additional identifier provided during registration.
56778-	Identifier string `json:"identifier,omitempty"`
56779-	// The currently known diagnostic reports with their
56780-	// previous result ids.
56781-	PreviousResultIds []PreviousResultID `json:"previousResultIds"`
56782-	WorkDoneProgressParams
56783-	PartialResultParams
56784-}
56785-
56786-// A workspace diagnostic report.
56787-//
56788-// @since 3.17.0
56789-type WorkspaceDiagnosticReport struct { // line 3914
56790-	Items []WorkspaceDocumentDiagnosticReport `json:"items"`
56791-}
56792-
56793-// A partial result for a workspace diagnostic report.
56794-//
56795-// @since 3.17.0
56796-type WorkspaceDiagnosticReportPartialResult struct { // line 3931
56797-	Items []WorkspaceDocumentDiagnosticReport `json:"items"`
56798-}
56799-
56800-// A workspace diagnostic document report.
56801-//
56802-// @since 3.17.0
56803-type WorkspaceDocumentDiagnosticReport = Or_WorkspaceDocumentDiagnosticReport // (alias) line 13984
56804-// A workspace edit represents changes to many resources managed in the workspace. The edit
56805-// should either provide `changes` or `documentChanges`. If documentChanges are present
56806-// they are preferred over `changes` if the client can handle versioned document edits.
56807-//
56808-// Since version 3.13.0 a workspace edit can contain resource operations as well. If resource
56809-// operations are present clients need to execute the operations in the order in which they
56810-// are provided. So a workspace edit for example can consist of the following two changes:
56811-// (1) a create file a.txt and (2) a text document edit which insert text into file a.txt.
56812-//
56813-// An invalid sequence (e.g. (1) delete file a.txt and (2) insert text into file a.txt) will
56814-// cause failure of the operation. How the client recovers from the failure is described by
56815-// the client capability: `workspace.workspaceEdit.failureHandling`
56816-type WorkspaceEdit struct { // line 3193
56817-	// Holds changes to existing resources.
56818-	Changes map[DocumentURI][]TextEdit `json:"changes,omitempty"`
56819-	// Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes
56820-	// are either an array of `TextDocumentEdit`s to express changes to n different text documents
56821-	// where each text document edit addresses a specific version of a text document. Or it can contain
56822-	// above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations.
56823-	//
56824-	// Whether a client supports versioned document edits is expressed via
56825-	// `workspace.workspaceEdit.documentChanges` client capability.
56826-	//
56827-	// If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then
56828-	// only plain `TextEdit`s using the `changes` property are supported.
56829-	DocumentChanges []DocumentChanges `json:"documentChanges,omitempty"`
56830-	// A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and
56831-	// delete file / folder operations.
56832-	//
56833-	// Whether clients honor this property depends on the client capability `workspace.changeAnnotationSupport`.
56834-	//
56835-	// @since 3.16.0
56836-	ChangeAnnotations map[ChangeAnnotationIdentifier]ChangeAnnotation `json:"changeAnnotations,omitempty"`
56837-}
56838-type WorkspaceEditClientCapabilities struct { // line 10768
56839-	// The client supports versioned document changes in `WorkspaceEdit`s
56840-	DocumentChanges bool `json:"documentChanges,omitempty"`
56841-	// The resource operations the client supports. Clients should at least
56842-	// support 'create', 'rename' and 'delete' files and folders.
56843-	//
56844-	// @since 3.13.0
56845-	ResourceOperations []ResourceOperationKind `json:"resourceOperations,omitempty"`
56846-	// The failure handling strategy of a client if applying the workspace edit
56847-	// fails.
56848-	//
56849-	// @since 3.13.0
56850-	FailureHandling *FailureHandlingKind `json:"failureHandling,omitempty"`
56851-	// Whether the client normalizes line endings to the client specific
56852-	// setting.
56853-	// If set to `true` the client will normalize line ending characters
56854-	// in a workspace edit to the client-specified new line
56855-	// character.
56856-	//
56857-	// @since 3.16.0
56858-	NormalizesLineEndings bool `json:"normalizesLineEndings,omitempty"`
56859-	// Whether the client in general supports change annotations on text edits,
56860-	// create file, rename file and delete file changes.
56861-	//
56862-	// @since 3.16.0
56863-	ChangeAnnotationSupport *PChangeAnnotationSupportPWorkspaceEdit `json:"changeAnnotationSupport,omitempty"`
56864-}
56865-
56866-// A workspace folder inside a client.
56867-type WorkspaceFolder struct { // line 2163
56868-	// The associated URI for this workspace folder.
56869-	URI URI `json:"uri"`
56870-	// The name of the workspace folder. Used to refer to this
56871-	// workspace folder in the user interface.
56872-	Name string `json:"name"`
56873-}
56874-type WorkspaceFolders5Gn struct { // line 9933
56875-	// The server has support for workspace folders
56876-	Supported bool `json:"supported,omitempty"`
56877-	// Whether the server wants to receive workspace folder
56878-	// change notifications.
56879-	//
56880-	// If a string is provided the string is treated as an ID
56881-	// under which the notification is registered on the client
56882-	// side. The ID can be used to unregister for these events
56883-	// using the `client/unregisterCapability` request.
56884-	ChangeNotifications string `json:"changeNotifications,omitempty"`
56885-}
56886-
56887-// The workspace folder change event.
56888-type WorkspaceFoldersChangeEvent struct { // line 6368
56889-	// The array of added workspace folders
56890-	Added []WorkspaceFolder `json:"added"`
56891-	// The array of the removed workspace folders
56892-	Removed []WorkspaceFolder `json:"removed"`
56893-}
56894-type WorkspaceFoldersInitializeParams struct { // line 7782
56895-	// The workspace folders configured in the client when the server starts.
56896-	//
56897-	// This property is only available if the client supports workspace folders.
56898-	// It can be `null` if the client supports workspace folders but none are
56899-	// configured.
56900-	//
56901-	// @since 3.6.0
56902-	WorkspaceFolders []WorkspaceFolder `json:"workspaceFolders,omitempty"`
56903-}
56904-type WorkspaceFoldersServerCapabilities struct { // line 9933
56905-	// The server has support for workspace folders
56906-	Supported bool `json:"supported,omitempty"`
56907-	// Whether the server wants to receive workspace folder
56908-	// change notifications.
56909-	//
56910-	// If a string is provided the string is treated as an ID
56911-	// under which the notification is registered on the client
56912-	// side. The ID can be used to unregister for these events
56913-	// using the `client/unregisterCapability` request.
56914-	ChangeNotifications string `json:"changeNotifications,omitempty"`
56915-}
56916-
56917-// A full document diagnostic report for a workspace diagnostic result.
56918-//
56919-// @since 3.17.0
56920-type WorkspaceFullDocumentDiagnosticReport struct { // line 9522
56921-	// The URI for which diagnostic information is reported.
56922-	URI DocumentURI `json:"uri"`
56923-	// The version number for which the diagnostics are reported.
56924-	// If the document is not marked as open `null` can be provided.
56925-	Version int32 `json:"version"`
56926-	FullDocumentDiagnosticReport
56927-}
56928-
56929-// A special workspace symbol that supports locations without a range.
56930-//
56931-// See also SymbolInformation.
56932-//
56933-// @since 3.17.0
56934-type WorkspaceSymbol struct { // line 5515
56935-	// The location of the symbol. Whether a server is allowed to
56936-	// return a location without a range depends on the client
56937-	// capability `workspace.symbol.resolveSupport`.
56938-	//
56939-	// See SymbolInformation#location for more details.
56940-	Location OrPLocation_workspace_symbol `json:"location"`
56941-	// A data entry field that is preserved on a workspace symbol between a
56942-	// workspace symbol request and a workspace symbol resolve request.
56943-	Data interface{} `json:"data,omitempty"`
56944-	BaseSymbolInformation
56945-}
56946-
56947-// Client capabilities for a {@link WorkspaceSymbolRequest}.
56948-type WorkspaceSymbolClientCapabilities struct { // line 10875
56949-	// Symbol request supports dynamic registration.
56950-	DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
56951-	// Specific capabilities for the `SymbolKind` in the `workspace/symbol` request.
56952-	SymbolKind *PSymbolKindPSymbol `json:"symbolKind,omitempty"`
56953-	// The client supports tags on `SymbolInformation`.
56954-	// Clients supporting tags have to handle unknown tags gracefully.
56955-	//
56956-	// @since 3.16.0
56957-	TagSupport *PTagSupportPSymbol `json:"tagSupport,omitempty"`
56958-	// The client support partial workspace symbols. The client will send the
56959-	// request `workspaceSymbol/resolve` to the server to resolve additional
56960-	// properties.
56961-	//
56962-	// @since 3.17.0
56963-	ResolveSupport *PResolveSupportPSymbol `json:"resolveSupport,omitempty"`
56964-}
56965-
56966-// Server capabilities for a {@link WorkspaceSymbolRequest}.
56967-type WorkspaceSymbolOptions struct { // line 9105
56968-	// The server provides support to resolve additional
56969-	// information for a workspace symbol.
56970-	//
56971-	// @since 3.17.0
56972-	ResolveProvider bool `json:"resolveProvider,omitempty"`
56973-	WorkDoneProgressOptions
56974-}
56975-
56976-// The parameters of a {@link WorkspaceSymbolRequest}.
56977-type WorkspaceSymbolParams struct { // line 5491
56978-	// A query string to filter symbols by. Clients may send an empty
56979-	// string here to request all symbols.
56980-	Query string `json:"query"`
56981-	WorkDoneProgressParams
56982-	PartialResultParams
56983-}
56984-
56985-// Registration options for a {@link WorkspaceSymbolRequest}.
56986-type WorkspaceSymbolRegistrationOptions struct { // line 5564
56987-	WorkspaceSymbolOptions
56988-}
56989-
56990-// An unchanged document diagnostic report for a workspace diagnostic result.
56991-//
56992-// @since 3.17.0
56993-type WorkspaceUnchangedDocumentDiagnosticReport struct { // line 9560
56994-	// The URI for which diagnostic information is reported.
56995-	URI DocumentURI `json:"uri"`
56996-	// The version number for which the diagnostics are reported.
56997-	// If the document is not marked as open `null` can be provided.
56998-	Version int32 `json:"version"`
56999-	UnchangedDocumentDiagnosticReport
57000-}
57001-
57002-// The initialize parameters
57003-type XInitializeParams struct { // line 7650
57004-	// The process Id of the parent process that started
57005-	// the server.
57006-	//
57007-	// Is `null` if the process has not been started by another process.
57008-	// If the parent process is not alive then the server should exit.
57009-	ProcessID int32 `json:"processId"`
57010-	// Information about the client
57011-	//
57012-	// @since 3.15.0
57013-	ClientInfo *Msg_XInitializeParams_clientInfo `json:"clientInfo,omitempty"`
57014-	// The locale the client is currently showing the user interface
57015-	// in. This must not necessarily be the locale of the operating
57016-	// system.
57017-	//
57018-	// Uses IETF language tags as the value's syntax
57019-	// (See https://en.wikipedia.org/wiki/IETF_language_tag)
57020-	//
57021-	// @since 3.16.0
57022-	Locale string `json:"locale,omitempty"`
57023-	// The rootPath of the workspace. Is null
57024-	// if no folder is open.
57025-	//
57026-	// @deprecated in favour of rootUri.
57027-	RootPath string `json:"rootPath,omitempty"`
57028-	// The rootUri of the workspace. Is null if no
57029-	// folder is open. If both `rootPath` and `rootUri` are set
57030-	// `rootUri` wins.
57031-	//
57032-	// @deprecated in favour of workspaceFolders.
57033-	RootURI DocumentURI `json:"rootUri"`
57034-	// The capabilities provided by the client (editor or tool)
57035-	Capabilities ClientCapabilities `json:"capabilities"`
57036-	// User provided initialization options.
57037-	InitializationOptions interface{} `json:"initializationOptions,omitempty"`
57038-	// The initial trace setting. If omitted trace is disabled ('off').
57039-	Trace *TraceValues `json:"trace,omitempty"`
57040-	WorkDoneProgressParams
57041-}
57042-
57043-// The initialize parameters
57044-type _InitializeParams struct { // line 7650
57045-	// The process Id of the parent process that started
57046-	// the server.
57047-	//
57048-	// Is `null` if the process has not been started by another process.
57049-	// If the parent process is not alive then the server should exit.
57050-	ProcessID int32 `json:"processId"`
57051-	// Information about the client
57052-	//
57053-	// @since 3.15.0
57054-	ClientInfo *Msg_XInitializeParams_clientInfo `json:"clientInfo,omitempty"`
57055-	// The locale the client is currently showing the user interface
57056-	// in. This must not necessarily be the locale of the operating
57057-	// system.
57058-	//
57059-	// Uses IETF language tags as the value's syntax
57060-	// (See https://en.wikipedia.org/wiki/IETF_language_tag)
57061-	//
57062-	// @since 3.16.0
57063-	Locale string `json:"locale,omitempty"`
57064-	// The rootPath of the workspace. Is null
57065-	// if no folder is open.
57066-	//
57067-	// @deprecated in favour of rootUri.
57068-	RootPath string `json:"rootPath,omitempty"`
57069-	// The rootUri of the workspace. Is null if no
57070-	// folder is open. If both `rootPath` and `rootUri` are set
57071-	// `rootUri` wins.
57072-	//
57073-	// @deprecated in favour of workspaceFolders.
57074-	RootURI DocumentURI `json:"rootUri"`
57075-	// The capabilities provided by the client (editor or tool)
57076-	Capabilities ClientCapabilities `json:"capabilities"`
57077-	// User provided initialization options.
57078-	InitializationOptions interface{} `json:"initializationOptions,omitempty"`
57079-	// The initial trace setting. If omitted trace is disabled ('off').
57080-	Trace *TraceValues `json:"trace,omitempty"`
57081-	WorkDoneProgressParams
57082-}
57083-
57084-const (
57085-	// A set of predefined code action kinds
57086-	// Empty kind.
57087-	Empty CodeActionKind = "" // line 13333
57088-	// Base kind for quickfix actions: 'quickfix'
57089-	QuickFix CodeActionKind = "quickfix" // line 13338
57090-	// Base kind for refactoring actions: 'refactor'
57091-	Refactor CodeActionKind = "refactor" // line 13343
57092-	// Base kind for refactoring extraction actions: 'refactor.extract'
57093-	//
57094-	// Example extract actions:
57095-	//
57096-	//
57097-	//  - Extract method
57098-	//  - Extract function
57099-	//  - Extract variable
57100-	//  - Extract interface from class
57101-	//  - ...
57102-	RefactorExtract CodeActionKind = "refactor.extract" // line 13348
57103-	// Base kind for refactoring inline actions: 'refactor.inline'
57104-	//
57105-	// Example inline actions:
57106-	//
57107-	//
57108-	//  - Inline function
57109-	//  - Inline variable
57110-	//  - Inline constant
57111-	//  - ...
57112-	RefactorInline CodeActionKind = "refactor.inline" // line 13353
57113-	// Base kind for refactoring rewrite actions: 'refactor.rewrite'
57114-	//
57115-	// Example rewrite actions:
57116-	//
57117-	//
57118-	//  - Convert JavaScript function to class
57119-	//  - Add or remove parameter
57120-	//  - Encapsulate field
57121-	//  - Make method static
57122-	//  - Move method to base class
57123-	//  - ...
57124-	RefactorRewrite CodeActionKind = "refactor.rewrite" // line 13358
57125-	// Base kind for source actions: `source`
57126-	//
57127-	// Source code actions apply to the entire file.
57128-	Source CodeActionKind = "source" // line 13363
57129-	// Base kind for an organize imports source action: `source.organizeImports`
57130-	SourceOrganizeImports CodeActionKind = "source.organizeImports" // line 13368
57131-	// Base kind for auto-fix source actions: `source.fixAll`.
57132-	//
57133-	// Fix all actions automatically fix errors that have a clear fix that do not require user input.
57134-	// They should not suppress errors or perform unsafe fixes such as generating new types or classes.
57135-	//
57136-	// @since 3.15.0
57137-	SourceFixAll CodeActionKind = "source.fixAll" // line 13373
57138-	// The reason why code actions were requested.
57139-	//
57140-	// @since 3.17.0
57141-	// Code actions were explicitly requested by the user or by an extension.
57142-	CodeActionInvoked CodeActionTriggerKind = 1 // line 13613
57143-	// Code actions were requested automatically.
57144-	//
57145-	// This typically happens when current selection in a file changes, but can
57146-	// also be triggered when file content changes.
57147-	CodeActionAutomatic CodeActionTriggerKind = 2 // line 13618
57148-	// The kind of a completion entry.
57149-	TextCompletion          CompletionItemKind = 1  // line 13141
57150-	MethodCompletion        CompletionItemKind = 2  // line 13145
57151-	FunctionCompletion      CompletionItemKind = 3  // line 13149
57152-	ConstructorCompletion   CompletionItemKind = 4  // line 13153
57153-	FieldCompletion         CompletionItemKind = 5  // line 13157
57154-	VariableCompletion      CompletionItemKind = 6  // line 13161
57155-	ClassCompletion         CompletionItemKind = 7  // line 13165
57156-	InterfaceCompletion     CompletionItemKind = 8  // line 13169
57157-	ModuleCompletion        CompletionItemKind = 9  // line 13173
57158-	PropertyCompletion      CompletionItemKind = 10 // line 13177
57159-	UnitCompletion          CompletionItemKind = 11 // line 13181
57160-	ValueCompletion         CompletionItemKind = 12 // line 13185
57161-	EnumCompletion          CompletionItemKind = 13 // line 13189
57162-	KeywordCompletion       CompletionItemKind = 14 // line 13193
57163-	SnippetCompletion       CompletionItemKind = 15 // line 13197
57164-	ColorCompletion         CompletionItemKind = 16 // line 13201
57165-	FileCompletion          CompletionItemKind = 17 // line 13205
57166-	ReferenceCompletion     CompletionItemKind = 18 // line 13209
57167-	FolderCompletion        CompletionItemKind = 19 // line 13213
57168-	EnumMemberCompletion    CompletionItemKind = 20 // line 13217
57169-	ConstantCompletion      CompletionItemKind = 21 // line 13221
57170-	StructCompletion        CompletionItemKind = 22 // line 13225
57171-	EventCompletion         CompletionItemKind = 23 // line 13229
57172-	OperatorCompletion      CompletionItemKind = 24 // line 13233
57173-	TypeParameterCompletion CompletionItemKind = 25 // line 13237
57174-	// Completion item tags are extra annotations that tweak the rendering of a completion
57175-	// item.
57176-	//
57177-	// @since 3.15.0
57178-	// Render a completion as obsolete, usually using a strike-out.
57179-	ComplDeprecated CompletionItemTag = 1 // line 13251
57180-	// How a completion was triggered
57181-	// Completion was triggered by typing an identifier (24x7 code
57182-	// complete), manual invocation (e.g Ctrl+Space) or via API.
57183-	Invoked CompletionTriggerKind = 1 // line 13562
57184-	// Completion was triggered by a trigger character specified by
57185-	// the `triggerCharacters` properties of the `CompletionRegistrationOptions`.
57186-	TriggerCharacter CompletionTriggerKind = 2 // line 13567
57187-	// Completion was re-triggered as current completion list is incomplete
57188-	TriggerForIncompleteCompletions CompletionTriggerKind = 3 // line 13572
57189-	// The diagnostic's severity.
57190-	// Reports an error.
57191-	SeverityError DiagnosticSeverity = 1 // line 13511
57192-	// Reports a warning.
57193-	SeverityWarning DiagnosticSeverity = 2 // line 13516
57194-	// Reports an information.
57195-	SeverityInformation DiagnosticSeverity = 3 // line 13521
57196-	// Reports a hint.
57197-	SeverityHint DiagnosticSeverity = 4 // line 13526
57198-	// The diagnostic tags.
57199-	//
57200-	// @since 3.15.0
57201-	// Unused or unnecessary code.
57202-	//
57203-	// Clients are allowed to render diagnostics with this tag faded out instead of having
57204-	// an error squiggle.
57205-	Unnecessary DiagnosticTag = 1 // line 13541
57206-	// Deprecated or obsolete code.
57207-	//
57208-	// Clients are allowed to rendered diagnostics with this tag strike through.
57209-	Deprecated DiagnosticTag = 2 // line 13546
57210-	// The document diagnostic report kinds.
57211-	//
57212-	// @since 3.17.0
57213-	// A diagnostic report with a full
57214-	// set of problems.
57215-	DiagnosticFull DocumentDiagnosticReportKind = "full" // line 12729
57216-	// A report indicating that the last
57217-	// returned report is still accurate.
57218-	DiagnosticUnchanged DocumentDiagnosticReportKind = "unchanged" // line 12734
57219-	// A document highlight kind.
57220-	// A textual occurrence.
57221-	Text DocumentHighlightKind = 1 // line 13308
57222-	// Read-access of a symbol, like reading a variable.
57223-	Read DocumentHighlightKind = 2 // line 13313
57224-	// Write-access of a symbol, like writing to a variable.
57225-	Write DocumentHighlightKind = 3 // line 13318
57226-	// Predefined error codes.
57227-	ParseError     ErrorCodes = -32700 // line 12750
57228-	InvalidRequest ErrorCodes = -32600 // line 12754
57229-	MethodNotFound ErrorCodes = -32601 // line 12758
57230-	InvalidParams  ErrorCodes = -32602 // line 12762
57231-	InternalError  ErrorCodes = -32603 // line 12766
57232-	// Error code indicating that a server received a notification or
57233-	// request before the server has received the `initialize` request.
57234-	ServerNotInitialized ErrorCodes = -32002 // line 12770
57235-	UnknownErrorCode     ErrorCodes = -32001 // line 12775
57236-	// Applying the workspace change is simply aborted if one of the changes provided
57237-	// fails. All operations executed before the failing operation stay executed.
57238-	Abort FailureHandlingKind = "abort" // line 13700
57239-	// All operations are executed transactional. That means they either all
57240-	// succeed or no changes at all are applied to the workspace.
57241-	Transactional FailureHandlingKind = "transactional" // line 13705
57242-	// If the workspace edit contains only textual file changes they are executed transactional.
57243-	// If resource changes (create, rename or delete file) are part of the change the failure
57244-	// handling strategy is abort.
57245-	TextOnlyTransactional FailureHandlingKind = "textOnlyTransactional" // line 13710
57246-	// The client tries to undo the operations already executed. But there is no
57247-	// guarantee that this is succeeding.
57248-	Undo FailureHandlingKind = "undo" // line 13715
57249-	// The file event type
57250-	// The file got created.
57251-	Created FileChangeType = 1 // line 13461
57252-	// The file got changed.
57253-	Changed FileChangeType = 2 // line 13466
57254-	// The file got deleted.
57255-	Deleted FileChangeType = 3 // line 13471
57256-	// A pattern kind describing if a glob pattern matches a file a folder or
57257-	// both.
57258-	//
57259-	// @since 3.16.0
57260-	// The pattern matches a file only.
57261-	FilePattern FileOperationPatternKind = "file" // line 13634
57262-	// The pattern matches a folder only.
57263-	FolderPattern FileOperationPatternKind = "folder" // line 13639
57264-	// A set of predefined range kinds.
57265-	// Folding range for a comment
57266-	Comment FoldingRangeKind = "comment" // line 12822
57267-	// Folding range for an import or include
57268-	Imports FoldingRangeKind = "imports" // line 12827
57269-	// Folding range for a region (e.g. `#region`)
57270-	Region FoldingRangeKind = "region" // line 12832
57271-	// Inlay hint kinds.
57272-	//
57273-	// @since 3.17.0
57274-	// An inlay hint that for a type annotation.
57275-	Type InlayHintKind = 1 // line 13040
57276-	// An inlay hint that is for a parameter.
57277-	Parameter InlayHintKind = 2 // line 13045
57278-	// Defines whether the insert text in a completion item should be interpreted as
57279-	// plain text or a snippet.
57280-	// The primary text to be inserted is treated as a plain string.
57281-	PlainTextTextFormat InsertTextFormat = 1 // line 13267
57282-	// The primary text to be inserted is treated as a snippet.
57283-	//
57284-	// A snippet can define tab stops and placeholders with `$1`, `$2`
57285-	// and `${3:foo}`. `$0` defines the final tab stop, it defaults to
57286-	// the end of the snippet. Placeholders with equal identifiers are linked,
57287-	// that is typing in one will update others too.
57288-	//
57289-	// See also: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#snippet_syntax
57290-	SnippetTextFormat InsertTextFormat = 2 // line 13272
57291-	// How whitespace and indentation is handled during completion
57292-	// item insertion.
57293-	//
57294-	// @since 3.16.0
57295-	// The insertion or replace strings is taken as it is. If the
57296-	// value is multi line the lines below the cursor will be
57297-	// inserted using the indentation defined in the string value.
57298-	// The client will not apply any kind of adjustments to the
57299-	// string.
57300-	AsIs InsertTextMode = 1 // line 13287
57301-	// The editor adjusts leading whitespace of new lines so that
57302-	// they match the indentation up to the cursor of the line for
57303-	// which the item is accepted.
57304-	//
57305-	// Consider a line like this: <2tabs><cursor><3tabs>foo. Accepting a
57306-	// multi line completion item is indented using 2 tabs and all
57307-	// following lines inserted will be indented using 2 tabs as well.
57308-	AdjustIndentation InsertTextMode = 2 // line 13292
57309-	// A request failed but it was syntactically correct, e.g the
57310-	// method name was known and the parameters were valid. The error
57311-	// message should contain human readable information about why
57312-	// the request failed.
57313-	//
57314-	// @since 3.17.0
57315-	RequestFailed LSPErrorCodes = -32803 // line 12790
57316-	// The server cancelled the request. This error code should
57317-	// only be used for requests that explicitly support being
57318-	// server cancellable.
57319-	//
57320-	// @since 3.17.0
57321-	ServerCancelled LSPErrorCodes = -32802 // line 12796
57322-	// The server detected that the content of a document got
57323-	// modified outside normal conditions. A server should
57324-	// NOT send this error code if it detects a content change
57325-	// in it unprocessed messages. The result even computed
57326-	// on an older state might still be useful for the client.
57327-	//
57328-	// If a client decides that a result is not of any use anymore
57329-	// the client should cancel the request.
57330-	ContentModified LSPErrorCodes = -32801 // line 12802
57331-	// The client has canceled a request and a server as detected
57332-	// the cancel.
57333-	RequestCancelled LSPErrorCodes = -32800 // line 12807
57334-	// Describes the content type that a client supports in various
57335-	// result literals like `Hover`, `ParameterInfo` or `CompletionItem`.
57336-	//
57337-	// Please note that `MarkupKinds` must not start with a `$`. This kinds
57338-	// are reserved for internal usage.
57339-	// Plain text is supported as a content format
57340-	PlainText MarkupKind = "plaintext" // line 13414
57341-	// Markdown is supported as a content format
57342-	Markdown MarkupKind = "markdown" // line 13419
57343-	// The message type
57344-	// An error message.
57345-	Error MessageType = 1 // line 13061
57346-	// A warning message.
57347-	Warning MessageType = 2 // line 13066
57348-	// An information message.
57349-	Info MessageType = 3 // line 13071
57350-	// A log message.
57351-	Log MessageType = 4 // line 13076
57352-	// The moniker kind.
57353-	//
57354-	// @since 3.16.0
57355-	// The moniker represent a symbol that is imported into a project
57356-	Import MonikerKind = "import" // line 13014
57357-	// The moniker represents a symbol that is exported from a project
57358-	Export MonikerKind = "export" // line 13019
57359-	// The moniker represents a symbol that is local to a project (e.g. a local
57360-	// variable of a function, a class not visible outside the project, ...)
57361-	Local MonikerKind = "local" // line 13024
57362-	// A notebook cell kind.
57363-	//
57364-	// @since 3.17.0
57365-	// A markup-cell is formatted source that is used for display.
57366-	Markup NotebookCellKind = 1 // line 13655
57367-	// A code-cell is source code.
57368-	Code NotebookCellKind = 2 // line 13660
57369-	// A set of predefined position encoding kinds.
57370-	//
57371-	// @since 3.17.0
57372-	// Character offsets count UTF-8 code units.
57373-	UTF8 PositionEncodingKind = "utf-8" // line 13434
57374-	// Character offsets count UTF-16 code units.
57375-	//
57376-	// This is the default and must always be supported
57377-	// by servers
57378-	UTF16 PositionEncodingKind = "utf-16" // line 13439
57379-	// Character offsets count UTF-32 code units.
57380-	//
57381-	// Implementation note: these are the same as Unicode code points,
57382-	// so this `PositionEncodingKind` may also be used for an
57383-	// encoding-agnostic representation of character offsets.
57384-	UTF32 PositionEncodingKind = "utf-32" // line 13444
57385-	// The client's default behavior is to select the identifier
57386-	// according the to language's syntax rule.
57387-	Identifier PrepareSupportDefaultBehavior = 1 // line 13729
57388-	// Supports creating new files and folders.
57389-	Create ResourceOperationKind = "create" // line 13676
57390-	// Supports renaming existing files and folders.
57391-	Rename ResourceOperationKind = "rename" // line 13681
57392-	// Supports deleting existing files and folders.
57393-	Delete ResourceOperationKind = "delete" // line 13686
57394-	// A set of predefined token modifiers. This set is not fixed
57395-	// an clients can specify additional token types via the
57396-	// corresponding client capabilities.
57397-	//
57398-	// @since 3.16.0
57399-	ModDeclaration    SemanticTokenModifiers = "declaration"    // line 12677
57400-	ModDefinition     SemanticTokenModifiers = "definition"     // line 12681
57401-	ModReadonly       SemanticTokenModifiers = "readonly"       // line 12685
57402-	ModStatic         SemanticTokenModifiers = "static"         // line 12689
57403-	ModDeprecated     SemanticTokenModifiers = "deprecated"     // line 12693
57404-	ModAbstract       SemanticTokenModifiers = "abstract"       // line 12697
57405-	ModAsync          SemanticTokenModifiers = "async"          // line 12701
57406-	ModModification   SemanticTokenModifiers = "modification"   // line 12705
57407-	ModDocumentation  SemanticTokenModifiers = "documentation"  // line 12709
57408-	ModDefaultLibrary SemanticTokenModifiers = "defaultLibrary" // line 12713
57409-	// A set of predefined token types. This set is not fixed
57410-	// an clients can specify additional token types via the
57411-	// corresponding client capabilities.
57412-	//
57413-	// @since 3.16.0
57414-	NamespaceType SemanticTokenTypes = "namespace" // line 12570
57415-	// Represents a generic type. Acts as a fallback for types which can't be mapped to
57416-	// a specific type like class or enum.
57417-	TypeType          SemanticTokenTypes = "type"          // line 12574
57418-	ClassType         SemanticTokenTypes = "class"         // line 12579
57419-	EnumType          SemanticTokenTypes = "enum"          // line 12583
57420-	InterfaceType     SemanticTokenTypes = "interface"     // line 12587
57421-	StructType        SemanticTokenTypes = "struct"        // line 12591
57422-	TypeParameterType SemanticTokenTypes = "typeParameter" // line 12595
57423-	ParameterType     SemanticTokenTypes = "parameter"     // line 12599
57424-	VariableType      SemanticTokenTypes = "variable"      // line 12603
57425-	PropertyType      SemanticTokenTypes = "property"      // line 12607
57426-	EnumMemberType    SemanticTokenTypes = "enumMember"    // line 12611
57427-	EventType         SemanticTokenTypes = "event"         // line 12615
57428-	FunctionType      SemanticTokenTypes = "function"      // line 12619
57429-	MethodType        SemanticTokenTypes = "method"        // line 12623
57430-	MacroType         SemanticTokenTypes = "macro"         // line 12627
57431-	KeywordType       SemanticTokenTypes = "keyword"       // line 12631
57432-	ModifierType      SemanticTokenTypes = "modifier"      // line 12635
57433-	CommentType       SemanticTokenTypes = "comment"       // line 12639
57434-	StringType        SemanticTokenTypes = "string"        // line 12643
57435-	NumberType        SemanticTokenTypes = "number"        // line 12647
57436-	RegexpType        SemanticTokenTypes = "regexp"        // line 12651
57437-	OperatorType      SemanticTokenTypes = "operator"      // line 12655
57438-	// @since 3.17.0
57439-	DecoratorType SemanticTokenTypes = "decorator" // line 12659
57440-	// How a signature help was triggered.
57441-	//
57442-	// @since 3.15.0
57443-	// Signature help was invoked manually by the user or by a command.
57444-	SigInvoked SignatureHelpTriggerKind = 1 // line 13587
57445-	// Signature help was triggered by a trigger character.
57446-	SigTriggerCharacter SignatureHelpTriggerKind = 2 // line 13592
57447-	// Signature help was triggered by the cursor moving or by the document content changing.
57448-	SigContentChange SignatureHelpTriggerKind = 3 // line 13597
57449-	// A symbol kind.
57450-	File          SymbolKind = 1  // line 12848
57451-	Module        SymbolKind = 2  // line 12852
57452-	Namespace     SymbolKind = 3  // line 12856
57453-	Package       SymbolKind = 4  // line 12860
57454-	Class         SymbolKind = 5  // line 12864
57455-	Method        SymbolKind = 6  // line 12868
57456-	Property      SymbolKind = 7  // line 12872
57457-	Field         SymbolKind = 8  // line 12876
57458-	Constructor   SymbolKind = 9  // line 12880
57459-	Enum          SymbolKind = 10 // line 12884
57460-	Interface     SymbolKind = 11 // line 12888
57461-	Function      SymbolKind = 12 // line 12892
57462-	Variable      SymbolKind = 13 // line 12896
57463-	Constant      SymbolKind = 14 // line 12900
57464-	String        SymbolKind = 15 // line 12904
57465-	Number        SymbolKind = 16 // line 12908
57466-	Boolean       SymbolKind = 17 // line 12912
57467-	Array         SymbolKind = 18 // line 12916
57468-	Object        SymbolKind = 19 // line 12920
57469-	Key           SymbolKind = 20 // line 12924
57470-	Null          SymbolKind = 21 // line 12928
57471-	EnumMember    SymbolKind = 22 // line 12932
57472-	Struct        SymbolKind = 23 // line 12936
57473-	Event         SymbolKind = 24 // line 12940
57474-	Operator      SymbolKind = 25 // line 12944
57475-	TypeParameter SymbolKind = 26 // line 12948
57476-	// Symbol tags are extra annotations that tweak the rendering of a symbol.
57477-	//
57478-	// @since 3.16
57479-	// Render a symbol as obsolete, usually using a strike-out.
57480-	DeprecatedSymbol SymbolTag = 1 // line 12962
57481-	// Represents reasons why a text document is saved.
57482-	// Manually triggered, e.g. by the user pressing save, by starting debugging,
57483-	// or by an API call.
57484-	Manual TextDocumentSaveReason = 1 // line 13116
57485-	// Automatic after a delay.
57486-	AfterDelay TextDocumentSaveReason = 2 // line 13121
57487-	// When the editor lost focus.
57488-	FocusOut TextDocumentSaveReason = 3 // line 13126
57489-	// Defines how the host (editor) should sync
57490-	// document changes to the language server.
57491-	// Documents should not be synced at all.
57492-	None TextDocumentSyncKind = 0 // line 13091
57493-	// Documents are synced by always sending the full content
57494-	// of the document.
57495-	Full TextDocumentSyncKind = 1 // line 13096
57496-	// Documents are synced by sending the full content on open.
57497-	// After that only incremental updates to the document are
57498-	// send.
57499-	Incremental TextDocumentSyncKind = 2          // line 13101
57500-	Relative    TokenFormat          = "relative" // line 13743
57501-	// Turn tracing off.
57502-	Off TraceValues = "off" // line 13390
57503-	// Trace messages only.
57504-	Messages TraceValues = "messages" // line 13395
57505-	// Verbose message tracing.
57506-	Verbose TraceValues = "verbose" // line 13400
57507-	// Moniker uniqueness level to define scope of the moniker.
57508-	//
57509-	// @since 3.16.0
57510-	// The moniker is only unique inside a document
57511-	Document UniquenessLevel = "document" // line 12978
57512-	// The moniker is unique inside a project for which a dump got created
57513-	Project UniquenessLevel = "project" // line 12983
57514-	// The moniker is unique inside the group to which a project belongs
57515-	Group UniquenessLevel = "group" // line 12988
57516-	// The moniker is unique inside the moniker scheme.
57517-	Scheme UniquenessLevel = "scheme" // line 12993
57518-	// The moniker is globally unique
57519-	Global UniquenessLevel = "global" // line 12998
57520-	// Interested in create events.
57521-	WatchCreate WatchKind = 1 // line 13486
57522-	// Interested in change events
57523-	WatchChange WatchKind = 2 // line 13491
57524-	// Interested in delete events
57525-	WatchDelete WatchKind = 4 // line 13496
57526-)
57527diff -urN a/gopls/internal/lsp/protocol/tsserver.go b/gopls/internal/lsp/protocol/tsserver.go
57528--- a/gopls/internal/lsp/protocol/tsserver.go	2000-01-01 00:00:00.000000000 -0000
57529+++ b/gopls/internal/lsp/protocol/tsserver.go	1970-01-01 00:00:00.000000000 +0000
57530@@ -1,1160 +0,0 @@
57531-// Copyright 2023 The Go Authors. All rights reserved.
57532-// Use of this source code is governed by a BSD-style
57533-// license that can be found in the LICENSE file.
57534-
57535-// Code generated for LSP. DO NOT EDIT.
57536-
57537-package protocol
57538-
57539-// Code generated from protocol/metaModel.json at ref release/protocol/3.17.3-next.6 (hash 56c23c557e3568a9f56f42435fd5a80f9458957f).
57540-// https://github.com/microsoft/vscode-languageserver-node/blob/release/protocol/3.17.3-next.6/protocol/metaModel.json
57541-// LSP metaData.version = 3.17.0.
57542-
57543-import (
57544-	"context"
57545-	"encoding/json"
57546-
57547-	"golang.org/x/tools/internal/jsonrpc2"
57548-)
57549-
57550-type Server interface {
57551-	Progress(context.Context, *ProgressParams) error                                                       // $/progress
57552-	SetTrace(context.Context, *SetTraceParams) error                                                       // $/setTrace
57553-	IncomingCalls(context.Context, *CallHierarchyIncomingCallsParams) ([]CallHierarchyIncomingCall, error) // callHierarchy/incomingCalls
57554-	OutgoingCalls(context.Context, *CallHierarchyOutgoingCallsParams) ([]CallHierarchyOutgoingCall, error) // callHierarchy/outgoingCalls
57555-	ResolveCodeAction(context.Context, *CodeAction) (*CodeAction, error)                                   // codeAction/resolve
57556-	ResolveCodeLens(context.Context, *CodeLens) (*CodeLens, error)                                         // codeLens/resolve
57557-	ResolveCompletionItem(context.Context, *CompletionItem) (*CompletionItem, error)                       // completionItem/resolve
57558-	ResolveDocumentLink(context.Context, *DocumentLink) (*DocumentLink, error)                             // documentLink/resolve
57559-	Exit(context.Context) error                                                                            // exit
57560-	Initialize(context.Context, *ParamInitialize) (*InitializeResult, error)                               // initialize
57561-	Initialized(context.Context, *InitializedParams) error                                                 // initialized
57562-	Resolve(context.Context, *InlayHint) (*InlayHint, error)                                               // inlayHint/resolve
57563-	DidChangeNotebookDocument(context.Context, *DidChangeNotebookDocumentParams) error                     // notebookDocument/didChange
57564-	DidCloseNotebookDocument(context.Context, *DidCloseNotebookDocumentParams) error                       // notebookDocument/didClose
57565-	DidOpenNotebookDocument(context.Context, *DidOpenNotebookDocumentParams) error                         // notebookDocument/didOpen
57566-	DidSaveNotebookDocument(context.Context, *DidSaveNotebookDocumentParams) error                         // notebookDocument/didSave
57567-	Shutdown(context.Context) error                                                                        // shutdown
57568-	CodeAction(context.Context, *CodeActionParams) ([]CodeAction, error)                                   // textDocument/codeAction
57569-	CodeLens(context.Context, *CodeLensParams) ([]CodeLens, error)                                         // textDocument/codeLens
57570-	ColorPresentation(context.Context, *ColorPresentationParams) ([]ColorPresentation, error)              // textDocument/colorPresentation
57571-	Completion(context.Context, *CompletionParams) (*CompletionList, error)                                // textDocument/completion
57572-	Declaration(context.Context, *DeclarationParams) (*Or_textDocument_declaration, error)                 // textDocument/declaration
57573-	Definition(context.Context, *DefinitionParams) ([]Location, error)                                     // textDocument/definition
57574-	Diagnostic(context.Context, *string) (*string, error)                                                  // textDocument/diagnostic
57575-	DidChange(context.Context, *DidChangeTextDocumentParams) error                                         // textDocument/didChange
57576-	DidClose(context.Context, *DidCloseTextDocumentParams) error                                           // textDocument/didClose
57577-	DidOpen(context.Context, *DidOpenTextDocumentParams) error                                             // textDocument/didOpen
57578-	DidSave(context.Context, *DidSaveTextDocumentParams) error                                             // textDocument/didSave
57579-	DocumentColor(context.Context, *DocumentColorParams) ([]ColorInformation, error)                       // textDocument/documentColor
57580-	DocumentHighlight(context.Context, *DocumentHighlightParams) ([]DocumentHighlight, error)              // textDocument/documentHighlight
57581-	DocumentLink(context.Context, *DocumentLinkParams) ([]DocumentLink, error)                             // textDocument/documentLink
57582-	DocumentSymbol(context.Context, *DocumentSymbolParams) ([]interface{}, error)                          // textDocument/documentSymbol
57583-	FoldingRange(context.Context, *FoldingRangeParams) ([]FoldingRange, error)                             // textDocument/foldingRange
57584-	Formatting(context.Context, *DocumentFormattingParams) ([]TextEdit, error)                             // textDocument/formatting
57585-	Hover(context.Context, *HoverParams) (*Hover, error)                                                   // textDocument/hover
57586-	Implementation(context.Context, *ImplementationParams) ([]Location, error)                             // textDocument/implementation
57587-	InlayHint(context.Context, *InlayHintParams) ([]InlayHint, error)                                      // textDocument/inlayHint
57588-	InlineValue(context.Context, *InlineValueParams) ([]InlineValue, error)                                // textDocument/inlineValue
57589-	LinkedEditingRange(context.Context, *LinkedEditingRangeParams) (*LinkedEditingRanges, error)           // textDocument/linkedEditingRange
57590-	Moniker(context.Context, *MonikerParams) ([]Moniker, error)                                            // textDocument/moniker
57591-	OnTypeFormatting(context.Context, *DocumentOnTypeFormattingParams) ([]TextEdit, error)                 // textDocument/onTypeFormatting
57592-	PrepareCallHierarchy(context.Context, *CallHierarchyPrepareParams) ([]CallHierarchyItem, error)        // textDocument/prepareCallHierarchy
57593-	PrepareRename(context.Context, *PrepareRenameParams) (*PrepareRename2Gn, error)                        // textDocument/prepareRename
57594-	PrepareTypeHierarchy(context.Context, *TypeHierarchyPrepareParams) ([]TypeHierarchyItem, error)        // textDocument/prepareTypeHierarchy
57595-	RangeFormatting(context.Context, *DocumentRangeFormattingParams) ([]TextEdit, error)                   // textDocument/rangeFormatting
57596-	References(context.Context, *ReferenceParams) ([]Location, error)                                      // textDocument/references
57597-	Rename(context.Context, *RenameParams) (*WorkspaceEdit, error)                                         // textDocument/rename
57598-	SelectionRange(context.Context, *SelectionRangeParams) ([]SelectionRange, error)                       // textDocument/selectionRange
57599-	SemanticTokensFull(context.Context, *SemanticTokensParams) (*SemanticTokens, error)                    // textDocument/semanticTokens/full
57600-	SemanticTokensFullDelta(context.Context, *SemanticTokensDeltaParams) (interface{}, error)              // textDocument/semanticTokens/full/delta
57601-	SemanticTokensRange(context.Context, *SemanticTokensRangeParams) (*SemanticTokens, error)              // textDocument/semanticTokens/range
57602-	SignatureHelp(context.Context, *SignatureHelpParams) (*SignatureHelp, error)                           // textDocument/signatureHelp
57603-	TypeDefinition(context.Context, *TypeDefinitionParams) ([]Location, error)                             // textDocument/typeDefinition
57604-	WillSave(context.Context, *WillSaveTextDocumentParams) error                                           // textDocument/willSave
57605-	WillSaveWaitUntil(context.Context, *WillSaveTextDocumentParams) ([]TextEdit, error)                    // textDocument/willSaveWaitUntil
57606-	Subtypes(context.Context, *TypeHierarchySubtypesParams) ([]TypeHierarchyItem, error)                   // typeHierarchy/subtypes
57607-	Supertypes(context.Context, *TypeHierarchySupertypesParams) ([]TypeHierarchyItem, error)               // typeHierarchy/supertypes
57608-	WorkDoneProgressCancel(context.Context, *WorkDoneProgressCancelParams) error                           // window/workDoneProgress/cancel
57609-	DiagnosticWorkspace(context.Context, *WorkspaceDiagnosticParams) (*WorkspaceDiagnosticReport, error)   // workspace/diagnostic
57610-	DidChangeConfiguration(context.Context, *DidChangeConfigurationParams) error                           // workspace/didChangeConfiguration
57611-	DidChangeWatchedFiles(context.Context, *DidChangeWatchedFilesParams) error                             // workspace/didChangeWatchedFiles
57612-	DidChangeWorkspaceFolders(context.Context, *DidChangeWorkspaceFoldersParams) error                     // workspace/didChangeWorkspaceFolders
57613-	DidCreateFiles(context.Context, *CreateFilesParams) error                                              // workspace/didCreateFiles
57614-	DidDeleteFiles(context.Context, *DeleteFilesParams) error                                              // workspace/didDeleteFiles
57615-	DidRenameFiles(context.Context, *RenameFilesParams) error                                              // workspace/didRenameFiles
57616-	ExecuteCommand(context.Context, *ExecuteCommandParams) (interface{}, error)                            // workspace/executeCommand
57617-	Symbol(context.Context, *WorkspaceSymbolParams) ([]SymbolInformation, error)                           // workspace/symbol
57618-	WillCreateFiles(context.Context, *CreateFilesParams) (*WorkspaceEdit, error)                           // workspace/willCreateFiles
57619-	WillDeleteFiles(context.Context, *DeleteFilesParams) (*WorkspaceEdit, error)                           // workspace/willDeleteFiles
57620-	WillRenameFiles(context.Context, *RenameFilesParams) (*WorkspaceEdit, error)                           // workspace/willRenameFiles
57621-	ResolveWorkspaceSymbol(context.Context, *WorkspaceSymbol) (*WorkspaceSymbol, error)                    // workspaceSymbol/resolve
57622-	NonstandardRequest(ctx context.Context, method string, params interface{}) (interface{}, error)
57623-}
57624-
57625-func serverDispatch(ctx context.Context, server Server, reply jsonrpc2.Replier, r jsonrpc2.Request) (bool, error) {
57626-	switch r.Method() {
57627-	case "$/progress":
57628-		var params ProgressParams
57629-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57630-			return true, sendParseError(ctx, reply, err)
57631-		}
57632-		err := server.Progress(ctx, &params)
57633-		return true, reply(ctx, nil, err)
57634-	case "$/setTrace":
57635-		var params SetTraceParams
57636-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57637-			return true, sendParseError(ctx, reply, err)
57638-		}
57639-		err := server.SetTrace(ctx, &params)
57640-		return true, reply(ctx, nil, err)
57641-	case "callHierarchy/incomingCalls":
57642-		var params CallHierarchyIncomingCallsParams
57643-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57644-			return true, sendParseError(ctx, reply, err)
57645-		}
57646-		resp, err := server.IncomingCalls(ctx, &params)
57647-		if err != nil {
57648-			return true, reply(ctx, nil, err)
57649-		}
57650-		return true, reply(ctx, resp, nil)
57651-	case "callHierarchy/outgoingCalls":
57652-		var params CallHierarchyOutgoingCallsParams
57653-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57654-			return true, sendParseError(ctx, reply, err)
57655-		}
57656-		resp, err := server.OutgoingCalls(ctx, &params)
57657-		if err != nil {
57658-			return true, reply(ctx, nil, err)
57659-		}
57660-		return true, reply(ctx, resp, nil)
57661-	case "codeAction/resolve":
57662-		var params CodeAction
57663-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57664-			return true, sendParseError(ctx, reply, err)
57665-		}
57666-		resp, err := server.ResolveCodeAction(ctx, &params)
57667-		if err != nil {
57668-			return true, reply(ctx, nil, err)
57669-		}
57670-		return true, reply(ctx, resp, nil)
57671-	case "codeLens/resolve":
57672-		var params CodeLens
57673-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57674-			return true, sendParseError(ctx, reply, err)
57675-		}
57676-		resp, err := server.ResolveCodeLens(ctx, &params)
57677-		if err != nil {
57678-			return true, reply(ctx, nil, err)
57679-		}
57680-		return true, reply(ctx, resp, nil)
57681-	case "completionItem/resolve":
57682-		var params CompletionItem
57683-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57684-			return true, sendParseError(ctx, reply, err)
57685-		}
57686-		resp, err := server.ResolveCompletionItem(ctx, &params)
57687-		if err != nil {
57688-			return true, reply(ctx, nil, err)
57689-		}
57690-		return true, reply(ctx, resp, nil)
57691-	case "documentLink/resolve":
57692-		var params DocumentLink
57693-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57694-			return true, sendParseError(ctx, reply, err)
57695-		}
57696-		resp, err := server.ResolveDocumentLink(ctx, &params)
57697-		if err != nil {
57698-			return true, reply(ctx, nil, err)
57699-		}
57700-		return true, reply(ctx, resp, nil)
57701-	case "exit":
57702-		err := server.Exit(ctx)
57703-		return true, reply(ctx, nil, err)
57704-	case "initialize":
57705-		var params ParamInitialize
57706-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57707-			return true, sendParseError(ctx, reply, err)
57708-		}
57709-		resp, err := server.Initialize(ctx, &params)
57710-		if err != nil {
57711-			return true, reply(ctx, nil, err)
57712-		}
57713-		return true, reply(ctx, resp, nil)
57714-	case "initialized":
57715-		var params InitializedParams
57716-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57717-			return true, sendParseError(ctx, reply, err)
57718-		}
57719-		err := server.Initialized(ctx, &params)
57720-		return true, reply(ctx, nil, err)
57721-	case "inlayHint/resolve":
57722-		var params InlayHint
57723-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57724-			return true, sendParseError(ctx, reply, err)
57725-		}
57726-		resp, err := server.Resolve(ctx, &params)
57727-		if err != nil {
57728-			return true, reply(ctx, nil, err)
57729-		}
57730-		return true, reply(ctx, resp, nil)
57731-	case "notebookDocument/didChange":
57732-		var params DidChangeNotebookDocumentParams
57733-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57734-			return true, sendParseError(ctx, reply, err)
57735-		}
57736-		err := server.DidChangeNotebookDocument(ctx, &params)
57737-		return true, reply(ctx, nil, err)
57738-	case "notebookDocument/didClose":
57739-		var params DidCloseNotebookDocumentParams
57740-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57741-			return true, sendParseError(ctx, reply, err)
57742-		}
57743-		err := server.DidCloseNotebookDocument(ctx, &params)
57744-		return true, reply(ctx, nil, err)
57745-	case "notebookDocument/didOpen":
57746-		var params DidOpenNotebookDocumentParams
57747-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57748-			return true, sendParseError(ctx, reply, err)
57749-		}
57750-		err := server.DidOpenNotebookDocument(ctx, &params)
57751-		return true, reply(ctx, nil, err)
57752-	case "notebookDocument/didSave":
57753-		var params DidSaveNotebookDocumentParams
57754-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57755-			return true, sendParseError(ctx, reply, err)
57756-		}
57757-		err := server.DidSaveNotebookDocument(ctx, &params)
57758-		return true, reply(ctx, nil, err)
57759-	case "shutdown":
57760-		err := server.Shutdown(ctx)
57761-		return true, reply(ctx, nil, err)
57762-	case "textDocument/codeAction":
57763-		var params CodeActionParams
57764-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57765-			return true, sendParseError(ctx, reply, err)
57766-		}
57767-		resp, err := server.CodeAction(ctx, &params)
57768-		if err != nil {
57769-			return true, reply(ctx, nil, err)
57770-		}
57771-		return true, reply(ctx, resp, nil)
57772-	case "textDocument/codeLens":
57773-		var params CodeLensParams
57774-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57775-			return true, sendParseError(ctx, reply, err)
57776-		}
57777-		resp, err := server.CodeLens(ctx, &params)
57778-		if err != nil {
57779-			return true, reply(ctx, nil, err)
57780-		}
57781-		return true, reply(ctx, resp, nil)
57782-	case "textDocument/colorPresentation":
57783-		var params ColorPresentationParams
57784-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57785-			return true, sendParseError(ctx, reply, err)
57786-		}
57787-		resp, err := server.ColorPresentation(ctx, &params)
57788-		if err != nil {
57789-			return true, reply(ctx, nil, err)
57790-		}
57791-		return true, reply(ctx, resp, nil)
57792-	case "textDocument/completion":
57793-		var params CompletionParams
57794-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57795-			return true, sendParseError(ctx, reply, err)
57796-		}
57797-		resp, err := server.Completion(ctx, &params)
57798-		if err != nil {
57799-			return true, reply(ctx, nil, err)
57800-		}
57801-		return true, reply(ctx, resp, nil)
57802-	case "textDocument/declaration":
57803-		var params DeclarationParams
57804-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57805-			return true, sendParseError(ctx, reply, err)
57806-		}
57807-		resp, err := server.Declaration(ctx, &params)
57808-		if err != nil {
57809-			return true, reply(ctx, nil, err)
57810-		}
57811-		return true, reply(ctx, resp, nil)
57812-	case "textDocument/definition":
57813-		var params DefinitionParams
57814-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57815-			return true, sendParseError(ctx, reply, err)
57816-		}
57817-		resp, err := server.Definition(ctx, &params)
57818-		if err != nil {
57819-			return true, reply(ctx, nil, err)
57820-		}
57821-		return true, reply(ctx, resp, nil)
57822-	case "textDocument/diagnostic":
57823-		var params string
57824-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57825-			return true, sendParseError(ctx, reply, err)
57826-		}
57827-		resp, err := server.Diagnostic(ctx, &params)
57828-		if err != nil {
57829-			return true, reply(ctx, nil, err)
57830-		}
57831-		return true, reply(ctx, resp, nil)
57832-	case "textDocument/didChange":
57833-		var params DidChangeTextDocumentParams
57834-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57835-			return true, sendParseError(ctx, reply, err)
57836-		}
57837-		err := server.DidChange(ctx, &params)
57838-		return true, reply(ctx, nil, err)
57839-	case "textDocument/didClose":
57840-		var params DidCloseTextDocumentParams
57841-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57842-			return true, sendParseError(ctx, reply, err)
57843-		}
57844-		err := server.DidClose(ctx, &params)
57845-		return true, reply(ctx, nil, err)
57846-	case "textDocument/didOpen":
57847-		var params DidOpenTextDocumentParams
57848-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57849-			return true, sendParseError(ctx, reply, err)
57850-		}
57851-		err := server.DidOpen(ctx, &params)
57852-		return true, reply(ctx, nil, err)
57853-	case "textDocument/didSave":
57854-		var params DidSaveTextDocumentParams
57855-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57856-			return true, sendParseError(ctx, reply, err)
57857-		}
57858-		err := server.DidSave(ctx, &params)
57859-		return true, reply(ctx, nil, err)
57860-	case "textDocument/documentColor":
57861-		var params DocumentColorParams
57862-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57863-			return true, sendParseError(ctx, reply, err)
57864-		}
57865-		resp, err := server.DocumentColor(ctx, &params)
57866-		if err != nil {
57867-			return true, reply(ctx, nil, err)
57868-		}
57869-		return true, reply(ctx, resp, nil)
57870-	case "textDocument/documentHighlight":
57871-		var params DocumentHighlightParams
57872-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57873-			return true, sendParseError(ctx, reply, err)
57874-		}
57875-		resp, err := server.DocumentHighlight(ctx, &params)
57876-		if err != nil {
57877-			return true, reply(ctx, nil, err)
57878-		}
57879-		return true, reply(ctx, resp, nil)
57880-	case "textDocument/documentLink":
57881-		var params DocumentLinkParams
57882-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57883-			return true, sendParseError(ctx, reply, err)
57884-		}
57885-		resp, err := server.DocumentLink(ctx, &params)
57886-		if err != nil {
57887-			return true, reply(ctx, nil, err)
57888-		}
57889-		return true, reply(ctx, resp, nil)
57890-	case "textDocument/documentSymbol":
57891-		var params DocumentSymbolParams
57892-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57893-			return true, sendParseError(ctx, reply, err)
57894-		}
57895-		resp, err := server.DocumentSymbol(ctx, &params)
57896-		if err != nil {
57897-			return true, reply(ctx, nil, err)
57898-		}
57899-		return true, reply(ctx, resp, nil)
57900-	case "textDocument/foldingRange":
57901-		var params FoldingRangeParams
57902-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57903-			return true, sendParseError(ctx, reply, err)
57904-		}
57905-		resp, err := server.FoldingRange(ctx, &params)
57906-		if err != nil {
57907-			return true, reply(ctx, nil, err)
57908-		}
57909-		return true, reply(ctx, resp, nil)
57910-	case "textDocument/formatting":
57911-		var params DocumentFormattingParams
57912-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57913-			return true, sendParseError(ctx, reply, err)
57914-		}
57915-		resp, err := server.Formatting(ctx, &params)
57916-		if err != nil {
57917-			return true, reply(ctx, nil, err)
57918-		}
57919-		return true, reply(ctx, resp, nil)
57920-	case "textDocument/hover":
57921-		var params HoverParams
57922-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57923-			return true, sendParseError(ctx, reply, err)
57924-		}
57925-		resp, err := server.Hover(ctx, &params)
57926-		if err != nil {
57927-			return true, reply(ctx, nil, err)
57928-		}
57929-		return true, reply(ctx, resp, nil)
57930-	case "textDocument/implementation":
57931-		var params ImplementationParams
57932-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57933-			return true, sendParseError(ctx, reply, err)
57934-		}
57935-		resp, err := server.Implementation(ctx, &params)
57936-		if err != nil {
57937-			return true, reply(ctx, nil, err)
57938-		}
57939-		return true, reply(ctx, resp, nil)
57940-	case "textDocument/inlayHint":
57941-		var params InlayHintParams
57942-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57943-			return true, sendParseError(ctx, reply, err)
57944-		}
57945-		resp, err := server.InlayHint(ctx, &params)
57946-		if err != nil {
57947-			return true, reply(ctx, nil, err)
57948-		}
57949-		return true, reply(ctx, resp, nil)
57950-	case "textDocument/inlineValue":
57951-		var params InlineValueParams
57952-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57953-			return true, sendParseError(ctx, reply, err)
57954-		}
57955-		resp, err := server.InlineValue(ctx, &params)
57956-		if err != nil {
57957-			return true, reply(ctx, nil, err)
57958-		}
57959-		return true, reply(ctx, resp, nil)
57960-	case "textDocument/linkedEditingRange":
57961-		var params LinkedEditingRangeParams
57962-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57963-			return true, sendParseError(ctx, reply, err)
57964-		}
57965-		resp, err := server.LinkedEditingRange(ctx, &params)
57966-		if err != nil {
57967-			return true, reply(ctx, nil, err)
57968-		}
57969-		return true, reply(ctx, resp, nil)
57970-	case "textDocument/moniker":
57971-		var params MonikerParams
57972-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57973-			return true, sendParseError(ctx, reply, err)
57974-		}
57975-		resp, err := server.Moniker(ctx, &params)
57976-		if err != nil {
57977-			return true, reply(ctx, nil, err)
57978-		}
57979-		return true, reply(ctx, resp, nil)
57980-	case "textDocument/onTypeFormatting":
57981-		var params DocumentOnTypeFormattingParams
57982-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57983-			return true, sendParseError(ctx, reply, err)
57984-		}
57985-		resp, err := server.OnTypeFormatting(ctx, &params)
57986-		if err != nil {
57987-			return true, reply(ctx, nil, err)
57988-		}
57989-		return true, reply(ctx, resp, nil)
57990-	case "textDocument/prepareCallHierarchy":
57991-		var params CallHierarchyPrepareParams
57992-		if err := json.Unmarshal(r.Params(), &params); err != nil {
57993-			return true, sendParseError(ctx, reply, err)
57994-		}
57995-		resp, err := server.PrepareCallHierarchy(ctx, &params)
57996-		if err != nil {
57997-			return true, reply(ctx, nil, err)
57998-		}
57999-		return true, reply(ctx, resp, nil)
58000-	case "textDocument/prepareRename":
58001-		var params PrepareRenameParams
58002-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58003-			return true, sendParseError(ctx, reply, err)
58004-		}
58005-		resp, err := server.PrepareRename(ctx, &params)
58006-		if err != nil {
58007-			return true, reply(ctx, nil, err)
58008-		}
58009-		return true, reply(ctx, resp, nil)
58010-	case "textDocument/prepareTypeHierarchy":
58011-		var params TypeHierarchyPrepareParams
58012-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58013-			return true, sendParseError(ctx, reply, err)
58014-		}
58015-		resp, err := server.PrepareTypeHierarchy(ctx, &params)
58016-		if err != nil {
58017-			return true, reply(ctx, nil, err)
58018-		}
58019-		return true, reply(ctx, resp, nil)
58020-	case "textDocument/rangeFormatting":
58021-		var params DocumentRangeFormattingParams
58022-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58023-			return true, sendParseError(ctx, reply, err)
58024-		}
58025-		resp, err := server.RangeFormatting(ctx, &params)
58026-		if err != nil {
58027-			return true, reply(ctx, nil, err)
58028-		}
58029-		return true, reply(ctx, resp, nil)
58030-	case "textDocument/references":
58031-		var params ReferenceParams
58032-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58033-			return true, sendParseError(ctx, reply, err)
58034-		}
58035-		resp, err := server.References(ctx, &params)
58036-		if err != nil {
58037-			return true, reply(ctx, nil, err)
58038-		}
58039-		return true, reply(ctx, resp, nil)
58040-	case "textDocument/rename":
58041-		var params RenameParams
58042-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58043-			return true, sendParseError(ctx, reply, err)
58044-		}
58045-		resp, err := server.Rename(ctx, &params)
58046-		if err != nil {
58047-			return true, reply(ctx, nil, err)
58048-		}
58049-		return true, reply(ctx, resp, nil)
58050-	case "textDocument/selectionRange":
58051-		var params SelectionRangeParams
58052-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58053-			return true, sendParseError(ctx, reply, err)
58054-		}
58055-		resp, err := server.SelectionRange(ctx, &params)
58056-		if err != nil {
58057-			return true, reply(ctx, nil, err)
58058-		}
58059-		return true, reply(ctx, resp, nil)
58060-	case "textDocument/semanticTokens/full":
58061-		var params SemanticTokensParams
58062-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58063-			return true, sendParseError(ctx, reply, err)
58064-		}
58065-		resp, err := server.SemanticTokensFull(ctx, &params)
58066-		if err != nil {
58067-			return true, reply(ctx, nil, err)
58068-		}
58069-		return true, reply(ctx, resp, nil)
58070-	case "textDocument/semanticTokens/full/delta":
58071-		var params SemanticTokensDeltaParams
58072-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58073-			return true, sendParseError(ctx, reply, err)
58074-		}
58075-		resp, err := server.SemanticTokensFullDelta(ctx, &params)
58076-		if err != nil {
58077-			return true, reply(ctx, nil, err)
58078-		}
58079-		return true, reply(ctx, resp, nil)
58080-	case "textDocument/semanticTokens/range":
58081-		var params SemanticTokensRangeParams
58082-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58083-			return true, sendParseError(ctx, reply, err)
58084-		}
58085-		resp, err := server.SemanticTokensRange(ctx, &params)
58086-		if err != nil {
58087-			return true, reply(ctx, nil, err)
58088-		}
58089-		return true, reply(ctx, resp, nil)
58090-	case "textDocument/signatureHelp":
58091-		var params SignatureHelpParams
58092-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58093-			return true, sendParseError(ctx, reply, err)
58094-		}
58095-		resp, err := server.SignatureHelp(ctx, &params)
58096-		if err != nil {
58097-			return true, reply(ctx, nil, err)
58098-		}
58099-		return true, reply(ctx, resp, nil)
58100-	case "textDocument/typeDefinition":
58101-		var params TypeDefinitionParams
58102-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58103-			return true, sendParseError(ctx, reply, err)
58104-		}
58105-		resp, err := server.TypeDefinition(ctx, &params)
58106-		if err != nil {
58107-			return true, reply(ctx, nil, err)
58108-		}
58109-		return true, reply(ctx, resp, nil)
58110-	case "textDocument/willSave":
58111-		var params WillSaveTextDocumentParams
58112-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58113-			return true, sendParseError(ctx, reply, err)
58114-		}
58115-		err := server.WillSave(ctx, &params)
58116-		return true, reply(ctx, nil, err)
58117-	case "textDocument/willSaveWaitUntil":
58118-		var params WillSaveTextDocumentParams
58119-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58120-			return true, sendParseError(ctx, reply, err)
58121-		}
58122-		resp, err := server.WillSaveWaitUntil(ctx, &params)
58123-		if err != nil {
58124-			return true, reply(ctx, nil, err)
58125-		}
58126-		return true, reply(ctx, resp, nil)
58127-	case "typeHierarchy/subtypes":
58128-		var params TypeHierarchySubtypesParams
58129-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58130-			return true, sendParseError(ctx, reply, err)
58131-		}
58132-		resp, err := server.Subtypes(ctx, &params)
58133-		if err != nil {
58134-			return true, reply(ctx, nil, err)
58135-		}
58136-		return true, reply(ctx, resp, nil)
58137-	case "typeHierarchy/supertypes":
58138-		var params TypeHierarchySupertypesParams
58139-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58140-			return true, sendParseError(ctx, reply, err)
58141-		}
58142-		resp, err := server.Supertypes(ctx, &params)
58143-		if err != nil {
58144-			return true, reply(ctx, nil, err)
58145-		}
58146-		return true, reply(ctx, resp, nil)
58147-	case "window/workDoneProgress/cancel":
58148-		var params WorkDoneProgressCancelParams
58149-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58150-			return true, sendParseError(ctx, reply, err)
58151-		}
58152-		err := server.WorkDoneProgressCancel(ctx, &params)
58153-		return true, reply(ctx, nil, err)
58154-	case "workspace/diagnostic":
58155-		var params WorkspaceDiagnosticParams
58156-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58157-			return true, sendParseError(ctx, reply, err)
58158-		}
58159-		resp, err := server.DiagnosticWorkspace(ctx, &params)
58160-		if err != nil {
58161-			return true, reply(ctx, nil, err)
58162-		}
58163-		return true, reply(ctx, resp, nil)
58164-	case "workspace/didChangeConfiguration":
58165-		var params DidChangeConfigurationParams
58166-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58167-			return true, sendParseError(ctx, reply, err)
58168-		}
58169-		err := server.DidChangeConfiguration(ctx, &params)
58170-		return true, reply(ctx, nil, err)
58171-	case "workspace/didChangeWatchedFiles":
58172-		var params DidChangeWatchedFilesParams
58173-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58174-			return true, sendParseError(ctx, reply, err)
58175-		}
58176-		err := server.DidChangeWatchedFiles(ctx, &params)
58177-		return true, reply(ctx, nil, err)
58178-	case "workspace/didChangeWorkspaceFolders":
58179-		var params DidChangeWorkspaceFoldersParams
58180-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58181-			return true, sendParseError(ctx, reply, err)
58182-		}
58183-		err := server.DidChangeWorkspaceFolders(ctx, &params)
58184-		return true, reply(ctx, nil, err)
58185-	case "workspace/didCreateFiles":
58186-		var params CreateFilesParams
58187-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58188-			return true, sendParseError(ctx, reply, err)
58189-		}
58190-		err := server.DidCreateFiles(ctx, &params)
58191-		return true, reply(ctx, nil, err)
58192-	case "workspace/didDeleteFiles":
58193-		var params DeleteFilesParams
58194-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58195-			return true, sendParseError(ctx, reply, err)
58196-		}
58197-		err := server.DidDeleteFiles(ctx, &params)
58198-		return true, reply(ctx, nil, err)
58199-	case "workspace/didRenameFiles":
58200-		var params RenameFilesParams
58201-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58202-			return true, sendParseError(ctx, reply, err)
58203-		}
58204-		err := server.DidRenameFiles(ctx, &params)
58205-		return true, reply(ctx, nil, err)
58206-	case "workspace/executeCommand":
58207-		var params ExecuteCommandParams
58208-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58209-			return true, sendParseError(ctx, reply, err)
58210-		}
58211-		resp, err := server.ExecuteCommand(ctx, &params)
58212-		if err != nil {
58213-			return true, reply(ctx, nil, err)
58214-		}
58215-		return true, reply(ctx, resp, nil)
58216-	case "workspace/symbol":
58217-		var params WorkspaceSymbolParams
58218-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58219-			return true, sendParseError(ctx, reply, err)
58220-		}
58221-		resp, err := server.Symbol(ctx, &params)
58222-		if err != nil {
58223-			return true, reply(ctx, nil, err)
58224-		}
58225-		return true, reply(ctx, resp, nil)
58226-	case "workspace/willCreateFiles":
58227-		var params CreateFilesParams
58228-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58229-			return true, sendParseError(ctx, reply, err)
58230-		}
58231-		resp, err := server.WillCreateFiles(ctx, &params)
58232-		if err != nil {
58233-			return true, reply(ctx, nil, err)
58234-		}
58235-		return true, reply(ctx, resp, nil)
58236-	case "workspace/willDeleteFiles":
58237-		var params DeleteFilesParams
58238-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58239-			return true, sendParseError(ctx, reply, err)
58240-		}
58241-		resp, err := server.WillDeleteFiles(ctx, &params)
58242-		if err != nil {
58243-			return true, reply(ctx, nil, err)
58244-		}
58245-		return true, reply(ctx, resp, nil)
58246-	case "workspace/willRenameFiles":
58247-		var params RenameFilesParams
58248-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58249-			return true, sendParseError(ctx, reply, err)
58250-		}
58251-		resp, err := server.WillRenameFiles(ctx, &params)
58252-		if err != nil {
58253-			return true, reply(ctx, nil, err)
58254-		}
58255-		return true, reply(ctx, resp, nil)
58256-	case "workspaceSymbol/resolve":
58257-		var params WorkspaceSymbol
58258-		if err := json.Unmarshal(r.Params(), &params); err != nil {
58259-			return true, sendParseError(ctx, reply, err)
58260-		}
58261-		resp, err := server.ResolveWorkspaceSymbol(ctx, &params)
58262-		if err != nil {
58263-			return true, reply(ctx, nil, err)
58264-		}
58265-		return true, reply(ctx, resp, nil)
58266-	default:
58267-		return false, nil
58268-	}
58269-}
58270-
58271-func (s *serverDispatcher) Progress(ctx context.Context, params *ProgressParams) error {
58272-	return s.sender.Notify(ctx, "$/progress", params)
58273-}
58274-func (s *serverDispatcher) SetTrace(ctx context.Context, params *SetTraceParams) error {
58275-	return s.sender.Notify(ctx, "$/setTrace", params)
58276-}
58277-func (s *serverDispatcher) IncomingCalls(ctx context.Context, params *CallHierarchyIncomingCallsParams) ([]CallHierarchyIncomingCall, error) {
58278-	var result []CallHierarchyIncomingCall
58279-	if err := s.sender.Call(ctx, "callHierarchy/incomingCalls", params, &result); err != nil {
58280-		return nil, err
58281-	}
58282-	return result, nil
58283-}
58284-func (s *serverDispatcher) OutgoingCalls(ctx context.Context, params *CallHierarchyOutgoingCallsParams) ([]CallHierarchyOutgoingCall, error) {
58285-	var result []CallHierarchyOutgoingCall
58286-	if err := s.sender.Call(ctx, "callHierarchy/outgoingCalls", params, &result); err != nil {
58287-		return nil, err
58288-	}
58289-	return result, nil
58290-}
58291-func (s *serverDispatcher) ResolveCodeAction(ctx context.Context, params *CodeAction) (*CodeAction, error) {
58292-	var result *CodeAction
58293-	if err := s.sender.Call(ctx, "codeAction/resolve", params, &result); err != nil {
58294-		return nil, err
58295-	}
58296-	return result, nil
58297-}
58298-func (s *serverDispatcher) ResolveCodeLens(ctx context.Context, params *CodeLens) (*CodeLens, error) {
58299-	var result *CodeLens
58300-	if err := s.sender.Call(ctx, "codeLens/resolve", params, &result); err != nil {
58301-		return nil, err
58302-	}
58303-	return result, nil
58304-}
58305-func (s *serverDispatcher) ResolveCompletionItem(ctx context.Context, params *CompletionItem) (*CompletionItem, error) {
58306-	var result *CompletionItem
58307-	if err := s.sender.Call(ctx, "completionItem/resolve", params, &result); err != nil {
58308-		return nil, err
58309-	}
58310-	return result, nil
58311-}
58312-func (s *serverDispatcher) ResolveDocumentLink(ctx context.Context, params *DocumentLink) (*DocumentLink, error) {
58313-	var result *DocumentLink
58314-	if err := s.sender.Call(ctx, "documentLink/resolve", params, &result); err != nil {
58315-		return nil, err
58316-	}
58317-	return result, nil
58318-}
58319-func (s *serverDispatcher) Exit(ctx context.Context) error {
58320-	return s.sender.Notify(ctx, "exit", nil)
58321-}
58322-func (s *serverDispatcher) Initialize(ctx context.Context, params *ParamInitialize) (*InitializeResult, error) {
58323-	var result *InitializeResult
58324-	if err := s.sender.Call(ctx, "initialize", params, &result); err != nil {
58325-		return nil, err
58326-	}
58327-	return result, nil
58328-}
58329-func (s *serverDispatcher) Initialized(ctx context.Context, params *InitializedParams) error {
58330-	return s.sender.Notify(ctx, "initialized", params)
58331-}
58332-func (s *serverDispatcher) Resolve(ctx context.Context, params *InlayHint) (*InlayHint, error) {
58333-	var result *InlayHint
58334-	if err := s.sender.Call(ctx, "inlayHint/resolve", params, &result); err != nil {
58335-		return nil, err
58336-	}
58337-	return result, nil
58338-}
58339-func (s *serverDispatcher) DidChangeNotebookDocument(ctx context.Context, params *DidChangeNotebookDocumentParams) error {
58340-	return s.sender.Notify(ctx, "notebookDocument/didChange", params)
58341-}
58342-func (s *serverDispatcher) DidCloseNotebookDocument(ctx context.Context, params *DidCloseNotebookDocumentParams) error {
58343-	return s.sender.Notify(ctx, "notebookDocument/didClose", params)
58344-}
58345-func (s *serverDispatcher) DidOpenNotebookDocument(ctx context.Context, params *DidOpenNotebookDocumentParams) error {
58346-	return s.sender.Notify(ctx, "notebookDocument/didOpen", params)
58347-}
58348-func (s *serverDispatcher) DidSaveNotebookDocument(ctx context.Context, params *DidSaveNotebookDocumentParams) error {
58349-	return s.sender.Notify(ctx, "notebookDocument/didSave", params)
58350-}
58351-func (s *serverDispatcher) Shutdown(ctx context.Context) error {
58352-	return s.sender.Call(ctx, "shutdown", nil, nil)
58353-}
58354-func (s *serverDispatcher) CodeAction(ctx context.Context, params *CodeActionParams) ([]CodeAction, error) {
58355-	var result []CodeAction
58356-	if err := s.sender.Call(ctx, "textDocument/codeAction", params, &result); err != nil {
58357-		return nil, err
58358-	}
58359-	return result, nil
58360-}
58361-func (s *serverDispatcher) CodeLens(ctx context.Context, params *CodeLensParams) ([]CodeLens, error) {
58362-	var result []CodeLens
58363-	if err := s.sender.Call(ctx, "textDocument/codeLens", params, &result); err != nil {
58364-		return nil, err
58365-	}
58366-	return result, nil
58367-}
58368-func (s *serverDispatcher) ColorPresentation(ctx context.Context, params *ColorPresentationParams) ([]ColorPresentation, error) {
58369-	var result []ColorPresentation
58370-	if err := s.sender.Call(ctx, "textDocument/colorPresentation", params, &result); err != nil {
58371-		return nil, err
58372-	}
58373-	return result, nil
58374-}
58375-func (s *serverDispatcher) Completion(ctx context.Context, params *CompletionParams) (*CompletionList, error) {
58376-	var result *CompletionList
58377-	if err := s.sender.Call(ctx, "textDocument/completion", params, &result); err != nil {
58378-		return nil, err
58379-	}
58380-	return result, nil
58381-}
58382-func (s *serverDispatcher) Declaration(ctx context.Context, params *DeclarationParams) (*Or_textDocument_declaration, error) {
58383-	var result *Or_textDocument_declaration
58384-	if err := s.sender.Call(ctx, "textDocument/declaration", params, &result); err != nil {
58385-		return nil, err
58386-	}
58387-	return result, nil
58388-}
58389-func (s *serverDispatcher) Definition(ctx context.Context, params *DefinitionParams) ([]Location, error) {
58390-	var result []Location
58391-	if err := s.sender.Call(ctx, "textDocument/definition", params, &result); err != nil {
58392-		return nil, err
58393-	}
58394-	return result, nil
58395-}
58396-func (s *serverDispatcher) Diagnostic(ctx context.Context, params *string) (*string, error) {
58397-	var result *string
58398-	if err := s.sender.Call(ctx, "textDocument/diagnostic", params, &result); err != nil {
58399-		return nil, err
58400-	}
58401-	return result, nil
58402-}
58403-func (s *serverDispatcher) DidChange(ctx context.Context, params *DidChangeTextDocumentParams) error {
58404-	return s.sender.Notify(ctx, "textDocument/didChange", params)
58405-}
58406-func (s *serverDispatcher) DidClose(ctx context.Context, params *DidCloseTextDocumentParams) error {
58407-	return s.sender.Notify(ctx, "textDocument/didClose", params)
58408-}
58409-func (s *serverDispatcher) DidOpen(ctx context.Context, params *DidOpenTextDocumentParams) error {
58410-	return s.sender.Notify(ctx, "textDocument/didOpen", params)
58411-}
58412-func (s *serverDispatcher) DidSave(ctx context.Context, params *DidSaveTextDocumentParams) error {
58413-	return s.sender.Notify(ctx, "textDocument/didSave", params)
58414-}
58415-func (s *serverDispatcher) DocumentColor(ctx context.Context, params *DocumentColorParams) ([]ColorInformation, error) {
58416-	var result []ColorInformation
58417-	if err := s.sender.Call(ctx, "textDocument/documentColor", params, &result); err != nil {
58418-		return nil, err
58419-	}
58420-	return result, nil
58421-}
58422-func (s *serverDispatcher) DocumentHighlight(ctx context.Context, params *DocumentHighlightParams) ([]DocumentHighlight, error) {
58423-	var result []DocumentHighlight
58424-	if err := s.sender.Call(ctx, "textDocument/documentHighlight", params, &result); err != nil {
58425-		return nil, err
58426-	}
58427-	return result, nil
58428-}
58429-func (s *serverDispatcher) DocumentLink(ctx context.Context, params *DocumentLinkParams) ([]DocumentLink, error) {
58430-	var result []DocumentLink
58431-	if err := s.sender.Call(ctx, "textDocument/documentLink", params, &result); err != nil {
58432-		return nil, err
58433-	}
58434-	return result, nil
58435-}
58436-func (s *serverDispatcher) DocumentSymbol(ctx context.Context, params *DocumentSymbolParams) ([]interface{}, error) {
58437-	var result []interface{}
58438-	if err := s.sender.Call(ctx, "textDocument/documentSymbol", params, &result); err != nil {
58439-		return nil, err
58440-	}
58441-	return result, nil
58442-}
58443-func (s *serverDispatcher) FoldingRange(ctx context.Context, params *FoldingRangeParams) ([]FoldingRange, error) {
58444-	var result []FoldingRange
58445-	if err := s.sender.Call(ctx, "textDocument/foldingRange", params, &result); err != nil {
58446-		return nil, err
58447-	}
58448-	return result, nil
58449-}
58450-func (s *serverDispatcher) Formatting(ctx context.Context, params *DocumentFormattingParams) ([]TextEdit, error) {
58451-	var result []TextEdit
58452-	if err := s.sender.Call(ctx, "textDocument/formatting", params, &result); err != nil {
58453-		return nil, err
58454-	}
58455-	return result, nil
58456-}
58457-func (s *serverDispatcher) Hover(ctx context.Context, params *HoverParams) (*Hover, error) {
58458-	var result *Hover
58459-	if err := s.sender.Call(ctx, "textDocument/hover", params, &result); err != nil {
58460-		return nil, err
58461-	}
58462-	return result, nil
58463-}
58464-func (s *serverDispatcher) Implementation(ctx context.Context, params *ImplementationParams) ([]Location, error) {
58465-	var result []Location
58466-	if err := s.sender.Call(ctx, "textDocument/implementation", params, &result); err != nil {
58467-		return nil, err
58468-	}
58469-	return result, nil
58470-}
58471-func (s *serverDispatcher) InlayHint(ctx context.Context, params *InlayHintParams) ([]InlayHint, error) {
58472-	var result []InlayHint
58473-	if err := s.sender.Call(ctx, "textDocument/inlayHint", params, &result); err != nil {
58474-		return nil, err
58475-	}
58476-	return result, nil
58477-}
58478-func (s *serverDispatcher) InlineValue(ctx context.Context, params *InlineValueParams) ([]InlineValue, error) {
58479-	var result []InlineValue
58480-	if err := s.sender.Call(ctx, "textDocument/inlineValue", params, &result); err != nil {
58481-		return nil, err
58482-	}
58483-	return result, nil
58484-}
58485-func (s *serverDispatcher) LinkedEditingRange(ctx context.Context, params *LinkedEditingRangeParams) (*LinkedEditingRanges, error) {
58486-	var result *LinkedEditingRanges
58487-	if err := s.sender.Call(ctx, "textDocument/linkedEditingRange", params, &result); err != nil {
58488-		return nil, err
58489-	}
58490-	return result, nil
58491-}
58492-func (s *serverDispatcher) Moniker(ctx context.Context, params *MonikerParams) ([]Moniker, error) {
58493-	var result []Moniker
58494-	if err := s.sender.Call(ctx, "textDocument/moniker", params, &result); err != nil {
58495-		return nil, err
58496-	}
58497-	return result, nil
58498-}
58499-func (s *serverDispatcher) OnTypeFormatting(ctx context.Context, params *DocumentOnTypeFormattingParams) ([]TextEdit, error) {
58500-	var result []TextEdit
58501-	if err := s.sender.Call(ctx, "textDocument/onTypeFormatting", params, &result); err != nil {
58502-		return nil, err
58503-	}
58504-	return result, nil
58505-}
58506-func (s *serverDispatcher) PrepareCallHierarchy(ctx context.Context, params *CallHierarchyPrepareParams) ([]CallHierarchyItem, error) {
58507-	var result []CallHierarchyItem
58508-	if err := s.sender.Call(ctx, "textDocument/prepareCallHierarchy", params, &result); err != nil {
58509-		return nil, err
58510-	}
58511-	return result, nil
58512-}
58513-func (s *serverDispatcher) PrepareRename(ctx context.Context, params *PrepareRenameParams) (*PrepareRename2Gn, error) {
58514-	var result *PrepareRename2Gn
58515-	if err := s.sender.Call(ctx, "textDocument/prepareRename", params, &result); err != nil {
58516-		return nil, err
58517-	}
58518-	return result, nil
58519-}
58520-func (s *serverDispatcher) PrepareTypeHierarchy(ctx context.Context, params *TypeHierarchyPrepareParams) ([]TypeHierarchyItem, error) {
58521-	var result []TypeHierarchyItem
58522-	if err := s.sender.Call(ctx, "textDocument/prepareTypeHierarchy", params, &result); err != nil {
58523-		return nil, err
58524-	}
58525-	return result, nil
58526-}
58527-func (s *serverDispatcher) RangeFormatting(ctx context.Context, params *DocumentRangeFormattingParams) ([]TextEdit, error) {
58528-	var result []TextEdit
58529-	if err := s.sender.Call(ctx, "textDocument/rangeFormatting", params, &result); err != nil {
58530-		return nil, err
58531-	}
58532-	return result, nil
58533-}
58534-func (s *serverDispatcher) References(ctx context.Context, params *ReferenceParams) ([]Location, error) {
58535-	var result []Location
58536-	if err := s.sender.Call(ctx, "textDocument/references", params, &result); err != nil {
58537-		return nil, err
58538-	}
58539-	return result, nil
58540-}
58541-func (s *serverDispatcher) Rename(ctx context.Context, params *RenameParams) (*WorkspaceEdit, error) {
58542-	var result *WorkspaceEdit
58543-	if err := s.sender.Call(ctx, "textDocument/rename", params, &result); err != nil {
58544-		return nil, err
58545-	}
58546-	return result, nil
58547-}
58548-func (s *serverDispatcher) SelectionRange(ctx context.Context, params *SelectionRangeParams) ([]SelectionRange, error) {
58549-	var result []SelectionRange
58550-	if err := s.sender.Call(ctx, "textDocument/selectionRange", params, &result); err != nil {
58551-		return nil, err
58552-	}
58553-	return result, nil
58554-}
58555-func (s *serverDispatcher) SemanticTokensFull(ctx context.Context, params *SemanticTokensParams) (*SemanticTokens, error) {
58556-	var result *SemanticTokens
58557-	if err := s.sender.Call(ctx, "textDocument/semanticTokens/full", params, &result); err != nil {
58558-		return nil, err
58559-	}
58560-	return result, nil
58561-}
58562-func (s *serverDispatcher) SemanticTokensFullDelta(ctx context.Context, params *SemanticTokensDeltaParams) (interface{}, error) {
58563-	var result interface{}
58564-	if err := s.sender.Call(ctx, "textDocument/semanticTokens/full/delta", params, &result); err != nil {
58565-		return nil, err
58566-	}
58567-	return result, nil
58568-}
58569-func (s *serverDispatcher) SemanticTokensRange(ctx context.Context, params *SemanticTokensRangeParams) (*SemanticTokens, error) {
58570-	var result *SemanticTokens
58571-	if err := s.sender.Call(ctx, "textDocument/semanticTokens/range", params, &result); err != nil {
58572-		return nil, err
58573-	}
58574-	return result, nil
58575-}
58576-func (s *serverDispatcher) SignatureHelp(ctx context.Context, params *SignatureHelpParams) (*SignatureHelp, error) {
58577-	var result *SignatureHelp
58578-	if err := s.sender.Call(ctx, "textDocument/signatureHelp", params, &result); err != nil {
58579-		return nil, err
58580-	}
58581-	return result, nil
58582-}
58583-func (s *serverDispatcher) TypeDefinition(ctx context.Context, params *TypeDefinitionParams) ([]Location, error) {
58584-	var result []Location
58585-	if err := s.sender.Call(ctx, "textDocument/typeDefinition", params, &result); err != nil {
58586-		return nil, err
58587-	}
58588-	return result, nil
58589-}
58590-func (s *serverDispatcher) WillSave(ctx context.Context, params *WillSaveTextDocumentParams) error {
58591-	return s.sender.Notify(ctx, "textDocument/willSave", params)
58592-}
58593-func (s *serverDispatcher) WillSaveWaitUntil(ctx context.Context, params *WillSaveTextDocumentParams) ([]TextEdit, error) {
58594-	var result []TextEdit
58595-	if err := s.sender.Call(ctx, "textDocument/willSaveWaitUntil", params, &result); err != nil {
58596-		return nil, err
58597-	}
58598-	return result, nil
58599-}
58600-func (s *serverDispatcher) Subtypes(ctx context.Context, params *TypeHierarchySubtypesParams) ([]TypeHierarchyItem, error) {
58601-	var result []TypeHierarchyItem
58602-	if err := s.sender.Call(ctx, "typeHierarchy/subtypes", params, &result); err != nil {
58603-		return nil, err
58604-	}
58605-	return result, nil
58606-}
58607-func (s *serverDispatcher) Supertypes(ctx context.Context, params *TypeHierarchySupertypesParams) ([]TypeHierarchyItem, error) {
58608-	var result []TypeHierarchyItem
58609-	if err := s.sender.Call(ctx, "typeHierarchy/supertypes", params, &result); err != nil {
58610-		return nil, err
58611-	}
58612-	return result, nil
58613-}
58614-func (s *serverDispatcher) WorkDoneProgressCancel(ctx context.Context, params *WorkDoneProgressCancelParams) error {
58615-	return s.sender.Notify(ctx, "window/workDoneProgress/cancel", params)
58616-}
58617-func (s *serverDispatcher) DiagnosticWorkspace(ctx context.Context, params *WorkspaceDiagnosticParams) (*WorkspaceDiagnosticReport, error) {
58618-	var result *WorkspaceDiagnosticReport
58619-	if err := s.sender.Call(ctx, "workspace/diagnostic", params, &result); err != nil {
58620-		return nil, err
58621-	}
58622-	return result, nil
58623-}
58624-func (s *serverDispatcher) DidChangeConfiguration(ctx context.Context, params *DidChangeConfigurationParams) error {
58625-	return s.sender.Notify(ctx, "workspace/didChangeConfiguration", params)
58626-}
58627-func (s *serverDispatcher) DidChangeWatchedFiles(ctx context.Context, params *DidChangeWatchedFilesParams) error {
58628-	return s.sender.Notify(ctx, "workspace/didChangeWatchedFiles", params)
58629-}
58630-func (s *serverDispatcher) DidChangeWorkspaceFolders(ctx context.Context, params *DidChangeWorkspaceFoldersParams) error {
58631-	return s.sender.Notify(ctx, "workspace/didChangeWorkspaceFolders", params)
58632-}
58633-func (s *serverDispatcher) DidCreateFiles(ctx context.Context, params *CreateFilesParams) error {
58634-	return s.sender.Notify(ctx, "workspace/didCreateFiles", params)
58635-}
58636-func (s *serverDispatcher) DidDeleteFiles(ctx context.Context, params *DeleteFilesParams) error {
58637-	return s.sender.Notify(ctx, "workspace/didDeleteFiles", params)
58638-}
58639-func (s *serverDispatcher) DidRenameFiles(ctx context.Context, params *RenameFilesParams) error {
58640-	return s.sender.Notify(ctx, "workspace/didRenameFiles", params)
58641-}
58642-func (s *serverDispatcher) ExecuteCommand(ctx context.Context, params *ExecuteCommandParams) (interface{}, error) {
58643-	var result interface{}
58644-	if err := s.sender.Call(ctx, "workspace/executeCommand", params, &result); err != nil {
58645-		return nil, err
58646-	}
58647-	return result, nil
58648-}
58649-func (s *serverDispatcher) Symbol(ctx context.Context, params *WorkspaceSymbolParams) ([]SymbolInformation, error) {
58650-	var result []SymbolInformation
58651-	if err := s.sender.Call(ctx, "workspace/symbol", params, &result); err != nil {
58652-		return nil, err
58653-	}
58654-	return result, nil
58655-}
58656-func (s *serverDispatcher) WillCreateFiles(ctx context.Context, params *CreateFilesParams) (*WorkspaceEdit, error) {
58657-	var result *WorkspaceEdit
58658-	if err := s.sender.Call(ctx, "workspace/willCreateFiles", params, &result); err != nil {
58659-		return nil, err
58660-	}
58661-	return result, nil
58662-}
58663-func (s *serverDispatcher) WillDeleteFiles(ctx context.Context, params *DeleteFilesParams) (*WorkspaceEdit, error) {
58664-	var result *WorkspaceEdit
58665-	if err := s.sender.Call(ctx, "workspace/willDeleteFiles", params, &result); err != nil {
58666-		return nil, err
58667-	}
58668-	return result, nil
58669-}
58670-func (s *serverDispatcher) WillRenameFiles(ctx context.Context, params *RenameFilesParams) (*WorkspaceEdit, error) {
58671-	var result *WorkspaceEdit
58672-	if err := s.sender.Call(ctx, "workspace/willRenameFiles", params, &result); err != nil {
58673-		return nil, err
58674-	}
58675-	return result, nil
58676-}
58677-func (s *serverDispatcher) ResolveWorkspaceSymbol(ctx context.Context, params *WorkspaceSymbol) (*WorkspaceSymbol, error) {
58678-	var result *WorkspaceSymbol
58679-	if err := s.sender.Call(ctx, "workspaceSymbol/resolve", params, &result); err != nil {
58680-		return nil, err
58681-	}
58682-	return result, nil
58683-}
58684-func (s *serverDispatcher) NonstandardRequest(ctx context.Context, method string, params interface{}) (interface{}, error) {
58685-	var result interface{}
58686-	if err := s.sender.Call(ctx, method, params, &result); err != nil {
58687-		return nil, err
58688-	}
58689-	return result, nil
58690-}
58691diff -urN a/gopls/internal/lsp/README.md b/gopls/internal/lsp/README.md
58692--- a/gopls/internal/lsp/README.md	2000-01-01 00:00:00.000000000 -0000
58693+++ b/gopls/internal/lsp/README.md	1970-01-01 00:00:00.000000000 +0000
58694@@ -1,7 +0,0 @@
58695-# lsp
58696-
58697-internal/lsp provides much of the Language Server Protocol (lsp) implementation
58698-for gopls.
58699-
58700-Documentation for users and contributors can be found in the
58701-[`gopls/doc`](../../gopls/doc) directory.
58702diff -urN a/gopls/internal/lsp/references.go b/gopls/internal/lsp/references.go
58703--- a/gopls/internal/lsp/references.go	2000-01-01 00:00:00.000000000 -0000
58704+++ b/gopls/internal/lsp/references.go	1970-01-01 00:00:00.000000000 +0000
58705@@ -1,25 +0,0 @@
58706-// Copyright 2019 The Go Authors. All rights reserved.
58707-// Use of this source code is governed by a BSD-style
58708-// license that can be found in the LICENSE file.
58709-
58710-package lsp
58711-
58712-import (
58713-	"context"
58714-
58715-	"golang.org/x/tools/gopls/internal/lsp/protocol"
58716-	"golang.org/x/tools/gopls/internal/lsp/source"
58717-	"golang.org/x/tools/gopls/internal/lsp/template"
58718-)
58719-
58720-func (s *Server) references(ctx context.Context, params *protocol.ReferenceParams) ([]protocol.Location, error) {
58721-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.UnknownKind)
58722-	defer release()
58723-	if !ok {
58724-		return nil, err
58725-	}
58726-	if snapshot.View().FileKind(fh) == source.Tmpl {
58727-		return template.References(ctx, snapshot, fh, params)
58728-	}
58729-	return source.References(ctx, snapshot, fh, params.Position, params.Context.IncludeDeclaration)
58730-}
58731diff -urN a/gopls/internal/lsp/regtest/doc.go b/gopls/internal/lsp/regtest/doc.go
58732--- a/gopls/internal/lsp/regtest/doc.go	2000-01-01 00:00:00.000000000 -0000
58733+++ b/gopls/internal/lsp/regtest/doc.go	1970-01-01 00:00:00.000000000 +0000
58734@@ -1,157 +0,0 @@
58735-// Copyright 2020 The Go Authors. All rights reserved.
58736-// Use of this source code is governed by a BSD-style
58737-// license that can be found in the LICENSE file.
58738-
58739-// Package regtest provides a framework for writing gopls regression tests.
58740-//
58741-// User reported regressions are often expressed in terms of editor
58742-// interactions. For example: "When I open my editor in this directory,
58743-// navigate to this file, and change this line, I get a diagnostic that doesn't
58744-// make sense". In these cases reproducing, diagnosing, and writing a test to
58745-// protect against this regression can be difficult.
58746-//
58747-// The regtest package provides an API for developers to express these types of
58748-// user interactions in ordinary Go tests, validate them, and run them in a
58749-// variety of execution modes.
58750-//
58751-// # Test package setup
58752-//
58753-// The regression test package uses a couple of uncommon patterns to reduce
58754-// boilerplate in test bodies. First, it is intended to be imported as "." so
58755-// that helpers do not need to be qualified. Second, it requires some setup
58756-// that is currently implemented in the regtest.Main function, which must be
58757-// invoked by TestMain. Therefore, a minimal regtest testing package looks
58758-// like this:
58759-//
58760-//	package lsptests
58761-//
58762-//	import (
58763-//		"fmt"
58764-//		"testing"
58765-//
58766-//		"golang.org/x/tools/gopls/internal/hooks"
58767-//		. "golang.org/x/tools/gopls/internal/lsp/regtest"
58768-//	)
58769-//
58770-//	func TestMain(m *testing.M) {
58771-//		Main(m, hooks.Options)
58772-//	}
58773-//
58774-// # Writing a simple regression test
58775-//
58776-// To run a regression test use the regtest.Run function, which accepts a
58777-// txtar-encoded archive defining the initial workspace state. This function
58778-// sets up the workspace in a temporary directory, creates a fake text editor,
58779-// starts gopls, and initializes an LSP session. It then invokes the provided
58780-// test function with an *Env handle encapsulating the newly created
58781-// environment. Because gopls may be run in various modes (as a sidecar or
58782-// daemon process, with different settings), the test runner may perform this
58783-// process multiple times, re-running the test function each time with a new
58784-// environment.
58785-//
58786-//	func TestOpenFile(t *testing.T) {
58787-//		const files = `
58788-//	-- go.mod --
58789-//	module mod.com
58790-//
58791-//	go 1.12
58792-//	-- foo.go --
58793-//	package foo
58794-//	`
58795-//		Run(t, files, func(t *testing.T, env *Env) {
58796-//			env.OpenFile("foo.go")
58797-//		})
58798-//	}
58799-//
58800-// # Configuring Regtest Execution
58801-//
58802-// The regtest package exposes several options that affect the setup process
58803-// described above. To use these options, use the WithOptions function:
58804-//
58805-//	WithOptions(opts...).Run(...)
58806-//
58807-// See options.go for a full list of available options.
58808-//
58809-// # Operating on editor state
58810-//
58811-// To operate on editor state within the test body, the Env type provides
58812-// access to the workspace directory (Env.SandBox), text editor (Env.Editor),
58813-// LSP server (Env.Server), and 'awaiter' (Env.Awaiter).
58814-//
58815-// In most cases, operations on these primitive building blocks of the
58816-// regression test environment expect a Context (which should be a child of
58817-// env.Ctx), and return an error. To avoid boilerplate, the Env exposes a set
58818-// of wrappers in wrappers.go for use in scripting:
58819-//
58820-//	env.CreateBuffer("c/c.go", "")
58821-//	env.EditBuffer("c/c.go", fake.Edit{
58822-//		Text: `package c`,
58823-//	})
58824-//
58825-// These wrappers thread through Env.Ctx, and call t.Fatal on any errors.
58826-//
58827-// # Expressing expectations
58828-//
58829-// The general pattern for a regression test is to script interactions with the
58830-// fake editor and sandbox, and assert that gopls behaves correctly after each
58831-// state change. Unfortunately, this is complicated by the fact that state
58832-// changes are communicated to gopls via unidirectional client->server
58833-// notifications (didOpen, didChange, etc.), and resulting gopls behavior such
58834-// as diagnostics, logs, or messages is communicated back via server->client
58835-// notifications. Therefore, within regression tests we must be able to say "do
58836-// this, and then eventually gopls should do that". To achieve this, the
58837-// regtest package provides a framework for expressing conditions that must
58838-// eventually be met, in terms of the Expectation type.
58839-//
58840-// To express the assertion that "eventually gopls must meet these
58841-// expectations", use env.Await(...):
58842-//
58843-//	env.RegexpReplace("x/x.go", `package x`, `package main`)
58844-//	env.Await(env.DiagnosticAtRegexp("x/main.go", `fmt`))
58845-//
58846-// Await evaluates the provided expectations atomically, whenever the client
58847-// receives a state-changing notification from gopls. See expectation.go for a
58848-// full list of available expectations.
58849-//
58850-// A fundamental problem with this model is that if gopls never meets the
58851-// provided expectations, the test runner will hang until the test timeout
58852-// (which defaults to 10m). There are two ways to work around this poor
58853-// behavior:
58854-//
58855-//  1. Use a precondition to define precisely when we expect conditions to be
58856-//     met. Gopls provides the OnceMet(precondition, expectations...) pattern
58857-//     to express ("once this precondition is met, the following expectations
58858-//     must all hold"). To instrument preconditions, gopls uses verbose
58859-//     progress notifications to inform the client about ongoing work (see
58860-//     CompletedWork). The most common precondition is to wait for gopls to be
58861-//     done processing all change notifications, for which the regtest package
58862-//     provides the AfterChange helper. For example:
58863-//
58864-//     // We expect diagnostics to be cleared after gopls is done processing the
58865-//     // didSave notification.
58866-//     env.SaveBuffer("a/go.mod")
58867-//     env.AfterChange(EmptyDiagnostics("a/go.mod"))
58868-//
58869-//  2. Set a shorter timeout during development, if you expect to be breaking
58870-//     tests. By setting the environment variable GOPLS_REGTEST_TIMEOUT=5s,
58871-//     regression tests will time out after 5 seconds.
58872-//
58873-// # Tips & Tricks
58874-//
58875-// Here are some tips and tricks for working with regression tests:
58876-//
58877-//  1. Set the environment variable GOPLS_REGTEST_TIMEOUT=5s during development.
58878-//  2. Run tests with  -short. This will only run regression tests in the
58879-//     default gopls execution mode.
58880-//  3. Use capture groups to narrow regexp positions. All regular-expression
58881-//     based positions (such as DiagnosticAtRegexp) will match the position of
58882-//     the first capture group, if any are provided. This can be used to
58883-//     identify a specific position in the code for a pattern that may occur in
58884-//     multiple places. For example `var (mu) sync.Mutex` matches the position
58885-//     of "mu" within the variable declaration.
58886-//  4. Read diagnostics into a variable to implement more complicated
58887-//     assertions about diagnostic state in the editor. To do this, use the
58888-//     pattern OnceMet(precondition, ReadDiagnostics("file.go", &d)) to capture
58889-//     the current diagnostics as soon as the precondition is met. This is
58890-//     preferable to accessing the diagnostics directly, as it avoids races.
58891-package regtest
58892diff -urN a/gopls/internal/lsp/regtest/env.go b/gopls/internal/lsp/regtest/env.go
58893--- a/gopls/internal/lsp/regtest/env.go	2000-01-01 00:00:00.000000000 -0000
58894+++ b/gopls/internal/lsp/regtest/env.go	1970-01-01 00:00:00.000000000 +0000
58895@@ -1,391 +0,0 @@
58896-// Copyright 2020 The Go Authors. All rights reserved.
58897-// Use of this source code is governed by a BSD-style
58898-// license that can be found in the LICENSE file.
58899-
58900-package regtest
58901-
58902-import (
58903-	"context"
58904-	"fmt"
58905-	"strings"
58906-	"sync"
58907-	"testing"
58908-
58909-	"golang.org/x/tools/gopls/internal/lsp/fake"
58910-	"golang.org/x/tools/gopls/internal/lsp/protocol"
58911-	"golang.org/x/tools/internal/jsonrpc2/servertest"
58912-)
58913-
58914-// Env holds the building blocks of an editor testing environment, providing
58915-// wrapper methods that hide the boilerplate of plumbing contexts and checking
58916-// errors.
58917-type Env struct {
58918-	T   testing.TB // TODO(rfindley): rename to TB
58919-	Ctx context.Context
58920-
58921-	// Most tests should not need to access the scratch area, editor, server, or
58922-	// connection, but they are available if needed.
58923-	Sandbox *fake.Sandbox
58924-	Server  servertest.Connector
58925-
58926-	// Editor is owned by the Env, and shut down
58927-	Editor *fake.Editor
58928-
58929-	Awaiter *Awaiter
58930-}
58931-
58932-// An Awaiter keeps track of relevant LSP state, so that it may be asserted
58933-// upon with Expectations.
58934-//
58935-// Wire it into a fake.Editor using Awaiter.Hooks().
58936-//
58937-// TODO(rfindley): consider simply merging Awaiter with the fake.Editor. It
58938-// probably is not worth its own abstraction.
58939-type Awaiter struct {
58940-	workdir *fake.Workdir
58941-
58942-	mu sync.Mutex
58943-	// For simplicity, each waiter gets a unique ID.
58944-	nextWaiterID int
58945-	state        State
58946-	waiters      map[int]*condition
58947-}
58948-
58949-func NewAwaiter(workdir *fake.Workdir) *Awaiter {
58950-	return &Awaiter{
58951-		workdir: workdir,
58952-		state: State{
58953-			diagnostics: make(map[string]*protocol.PublishDiagnosticsParams),
58954-			work:        make(map[protocol.ProgressToken]*workProgress),
58955-		},
58956-		waiters: make(map[int]*condition),
58957-	}
58958-}
58959-
58960-// Hooks returns LSP client hooks required for awaiting asynchronous expectations.
58961-func (a *Awaiter) Hooks() fake.ClientHooks {
58962-	return fake.ClientHooks{
58963-		OnDiagnostics:            a.onDiagnostics,
58964-		OnLogMessage:             a.onLogMessage,
58965-		OnWorkDoneProgressCreate: a.onWorkDoneProgressCreate,
58966-		OnProgress:               a.onProgress,
58967-		OnShowMessage:            a.onShowMessage,
58968-		OnShowMessageRequest:     a.onShowMessageRequest,
58969-		OnRegisterCapability:     a.onRegisterCapability,
58970-		OnUnregisterCapability:   a.onUnregisterCapability,
58971-		OnApplyEdit:              a.onApplyEdit,
58972-	}
58973-}
58974-
58975-// State encapsulates the server state TODO: explain more
58976-type State struct {
58977-	// diagnostics are a map of relative path->diagnostics params
58978-	diagnostics        map[string]*protocol.PublishDiagnosticsParams
58979-	logs               []*protocol.LogMessageParams
58980-	showMessage        []*protocol.ShowMessageParams
58981-	showMessageRequest []*protocol.ShowMessageRequestParams
58982-
58983-	registrations          []*protocol.RegistrationParams
58984-	registeredCapabilities map[string]protocol.Registration
58985-	unregistrations        []*protocol.UnregistrationParams
58986-	documentChanges        []protocol.DocumentChanges // collected from ApplyEdit downcalls
58987-
58988-	// outstandingWork is a map of token->work summary. All tokens are assumed to
58989-	// be string, though the spec allows for numeric tokens as well.  When work
58990-	// completes, it is deleted from this map.
58991-	work map[protocol.ProgressToken]*workProgress
58992-}
58993-
58994-// outstandingWork counts started but not complete work items by title.
58995-func (s State) outstandingWork() map[string]uint64 {
58996-	outstanding := make(map[string]uint64)
58997-	for _, work := range s.work {
58998-		if !work.complete {
58999-			outstanding[work.title]++
59000-		}
59001-	}
59002-	return outstanding
59003-}
59004-
59005-// completedWork counts complete work items by title.
59006-func (s State) completedWork() map[string]uint64 {
59007-	completed := make(map[string]uint64)
59008-	for _, work := range s.work {
59009-		if work.complete {
59010-			completed[work.title]++
59011-		}
59012-	}
59013-	return completed
59014-}
59015-
59016-// startedWork counts started (and possibly complete) work items.
59017-func (s State) startedWork() map[string]uint64 {
59018-	started := make(map[string]uint64)
59019-	for _, work := range s.work {
59020-		started[work.title]++
59021-	}
59022-	return started
59023-}
59024-
59025-type workProgress struct {
59026-	title, msg, endMsg string
59027-	percent            float64
59028-	complete           bool // seen 'end'.
59029-}
59030-
59031-// This method, provided for debugging, accesses mutable fields without a lock,
59032-// so it must not be called concurrent with any State mutation.
59033-func (s State) String() string {
59034-	var b strings.Builder
59035-	b.WriteString("#### log messages (see RPC logs for full text):\n")
59036-	for _, msg := range s.logs {
59037-		summary := fmt.Sprintf("%v: %q", msg.Type, msg.Message)
59038-		if len(summary) > 60 {
59039-			summary = summary[:57] + "..."
59040-		}
59041-		// Some logs are quite long, and since they should be reproduced in the RPC
59042-		// logs on any failure we include here just a short summary.
59043-		fmt.Fprint(&b, "\t"+summary+"\n")
59044-	}
59045-	b.WriteString("\n")
59046-	b.WriteString("#### diagnostics:\n")
59047-	for name, params := range s.diagnostics {
59048-		fmt.Fprintf(&b, "\t%s (version %d):\n", name, int(params.Version))
59049-		for _, d := range params.Diagnostics {
59050-			fmt.Fprintf(&b, "\t\t(%d, %d) [%s]: %s\n", int(d.Range.Start.Line), int(d.Range.Start.Character), d.Source, d.Message)
59051-		}
59052-	}
59053-	b.WriteString("\n")
59054-	b.WriteString("#### outstanding work:\n")
59055-	for token, state := range s.work {
59056-		if state.complete {
59057-			continue
59058-		}
59059-		name := state.title
59060-		if name == "" {
59061-			name = fmt.Sprintf("!NO NAME(token: %s)", token)
59062-		}
59063-		fmt.Fprintf(&b, "\t%s: %.2f\n", name, state.percent)
59064-	}
59065-	b.WriteString("#### completed work:\n")
59066-	for name, count := range s.completedWork() {
59067-		fmt.Fprintf(&b, "\t%s: %d\n", name, count)
59068-	}
59069-	return b.String()
59070-}
59071-
59072-// A condition is satisfied when all expectations are simultaneously
59073-// met. At that point, the 'met' channel is closed. On any failure, err is set
59074-// and the failed channel is closed.
59075-type condition struct {
59076-	expectations []Expectation
59077-	verdict      chan Verdict
59078-}
59079-
59080-func (a *Awaiter) onApplyEdit(_ context.Context, params *protocol.ApplyWorkspaceEditParams) error {
59081-	a.mu.Lock()
59082-	defer a.mu.Unlock()
59083-
59084-	a.state.documentChanges = append(a.state.documentChanges, params.Edit.DocumentChanges...)
59085-	a.checkConditionsLocked()
59086-	return nil
59087-}
59088-
59089-func (a *Awaiter) onDiagnostics(_ context.Context, d *protocol.PublishDiagnosticsParams) error {
59090-	a.mu.Lock()
59091-	defer a.mu.Unlock()
59092-
59093-	pth := a.workdir.URIToPath(d.URI)
59094-	a.state.diagnostics[pth] = d
59095-	a.checkConditionsLocked()
59096-	return nil
59097-}
59098-
59099-func (a *Awaiter) onShowMessage(_ context.Context, m *protocol.ShowMessageParams) error {
59100-	a.mu.Lock()
59101-	defer a.mu.Unlock()
59102-
59103-	a.state.showMessage = append(a.state.showMessage, m)
59104-	a.checkConditionsLocked()
59105-	return nil
59106-}
59107-
59108-func (a *Awaiter) onShowMessageRequest(_ context.Context, m *protocol.ShowMessageRequestParams) error {
59109-	a.mu.Lock()
59110-	defer a.mu.Unlock()
59111-
59112-	a.state.showMessageRequest = append(a.state.showMessageRequest, m)
59113-	a.checkConditionsLocked()
59114-	return nil
59115-}
59116-
59117-func (a *Awaiter) onLogMessage(_ context.Context, m *protocol.LogMessageParams) error {
59118-	a.mu.Lock()
59119-	defer a.mu.Unlock()
59120-
59121-	a.state.logs = append(a.state.logs, m)
59122-	a.checkConditionsLocked()
59123-	return nil
59124-}
59125-
59126-func (a *Awaiter) onWorkDoneProgressCreate(_ context.Context, m *protocol.WorkDoneProgressCreateParams) error {
59127-	a.mu.Lock()
59128-	defer a.mu.Unlock()
59129-
59130-	a.state.work[m.Token] = &workProgress{}
59131-	return nil
59132-}
59133-
59134-func (a *Awaiter) onProgress(_ context.Context, m *protocol.ProgressParams) error {
59135-	a.mu.Lock()
59136-	defer a.mu.Unlock()
59137-	work, ok := a.state.work[m.Token]
59138-	if !ok {
59139-		panic(fmt.Sprintf("got progress report for unknown report %v: %v", m.Token, m))
59140-	}
59141-	v := m.Value.(map[string]interface{})
59142-	switch kind := v["kind"]; kind {
59143-	case "begin":
59144-		work.title = v["title"].(string)
59145-		if msg, ok := v["message"]; ok {
59146-			work.msg = msg.(string)
59147-		}
59148-	case "report":
59149-		if pct, ok := v["percentage"]; ok {
59150-			work.percent = pct.(float64)
59151-		}
59152-		if msg, ok := v["message"]; ok {
59153-			work.msg = msg.(string)
59154-		}
59155-	case "end":
59156-		work.complete = true
59157-		if msg, ok := v["message"]; ok {
59158-			work.endMsg = msg.(string)
59159-		}
59160-	}
59161-	a.checkConditionsLocked()
59162-	return nil
59163-}
59164-
59165-func (a *Awaiter) onRegisterCapability(_ context.Context, m *protocol.RegistrationParams) error {
59166-	a.mu.Lock()
59167-	defer a.mu.Unlock()
59168-
59169-	a.state.registrations = append(a.state.registrations, m)
59170-	if a.state.registeredCapabilities == nil {
59171-		a.state.registeredCapabilities = make(map[string]protocol.Registration)
59172-	}
59173-	for _, reg := range m.Registrations {
59174-		a.state.registeredCapabilities[reg.Method] = reg
59175-	}
59176-	a.checkConditionsLocked()
59177-	return nil
59178-}
59179-
59180-func (a *Awaiter) onUnregisterCapability(_ context.Context, m *protocol.UnregistrationParams) error {
59181-	a.mu.Lock()
59182-	defer a.mu.Unlock()
59183-
59184-	a.state.unregistrations = append(a.state.unregistrations, m)
59185-	a.checkConditionsLocked()
59186-	return nil
59187-}
59188-
59189-func (a *Awaiter) checkConditionsLocked() {
59190-	for id, condition := range a.waiters {
59191-		if v, _ := checkExpectations(a.state, condition.expectations); v != Unmet {
59192-			delete(a.waiters, id)
59193-			condition.verdict <- v
59194-		}
59195-	}
59196-}
59197-
59198-// takeDocumentChanges returns any accumulated document changes (from
59199-// server ApplyEdit RPC downcalls) and resets the list.
59200-func (a *Awaiter) takeDocumentChanges() []protocol.DocumentChanges {
59201-	a.mu.Lock()
59202-	defer a.mu.Unlock()
59203-
59204-	res := a.state.documentChanges
59205-	a.state.documentChanges = nil
59206-	return res
59207-}
59208-
59209-// checkExpectations reports whether s meets all expectations.
59210-func checkExpectations(s State, expectations []Expectation) (Verdict, string) {
59211-	finalVerdict := Met
59212-	var summary strings.Builder
59213-	for _, e := range expectations {
59214-		v := e.Check(s)
59215-		if v > finalVerdict {
59216-			finalVerdict = v
59217-		}
59218-		fmt.Fprintf(&summary, "%v: %s\n", v, e.Description)
59219-	}
59220-	return finalVerdict, summary.String()
59221-}
59222-
59223-// Await blocks until the given expectations are all simultaneously met.
59224-//
59225-// Generally speaking Await should be avoided because it blocks indefinitely if
59226-// gopls ends up in a state where the expectations are never going to be met.
59227-// Use AfterChange or OnceMet instead, so that the runner knows when to stop
59228-// waiting.
59229-func (e *Env) Await(expectations ...Expectation) {
59230-	e.T.Helper()
59231-	if err := e.Awaiter.Await(e.Ctx, expectations...); err != nil {
59232-		e.T.Fatal(err)
59233-	}
59234-}
59235-
59236-// OnceMet blocks until the precondition is met by the state or becomes
59237-// unmeetable. If it was met, OnceMet checks that the state meets all
59238-// expectations in mustMeets.
59239-func (e *Env) OnceMet(precondition Expectation, mustMeets ...Expectation) {
59240-	e.Await(OnceMet(precondition, mustMeets...))
59241-}
59242-
59243-// Await waits for all expectations to simultaneously be met. It should only be
59244-// called from the main test goroutine.
59245-func (a *Awaiter) Await(ctx context.Context, expectations ...Expectation) error {
59246-	a.mu.Lock()
59247-	// Before adding the waiter, we check if the condition is currently met or
59248-	// failed to avoid a race where the condition was realized before Await was
59249-	// called.
59250-	switch verdict, summary := checkExpectations(a.state, expectations); verdict {
59251-	case Met:
59252-		a.mu.Unlock()
59253-		return nil
59254-	case Unmeetable:
59255-		err := fmt.Errorf("unmeetable expectations:\n%s\nstate:\n%v", summary, a.state)
59256-		a.mu.Unlock()
59257-		return err
59258-	}
59259-	cond := &condition{
59260-		expectations: expectations,
59261-		verdict:      make(chan Verdict),
59262-	}
59263-	a.waiters[a.nextWaiterID] = cond
59264-	a.nextWaiterID++
59265-	a.mu.Unlock()
59266-
59267-	var err error
59268-	select {
59269-	case <-ctx.Done():
59270-		err = ctx.Err()
59271-	case v := <-cond.verdict:
59272-		if v != Met {
59273-			err = fmt.Errorf("condition has final verdict %v", v)
59274-		}
59275-	}
59276-	a.mu.Lock()
59277-	defer a.mu.Unlock()
59278-	_, summary := checkExpectations(a.state, expectations)
59279-
59280-	// Debugging an unmet expectation can be tricky, so we put some effort into
59281-	// nicely formatting the failure.
59282-	if err != nil {
59283-		return fmt.Errorf("waiting on:\n%s\nerr:%v\n\nstate:\n%v", summary, err, a.state)
59284-	}
59285-	return nil
59286-}
59287diff -urN a/gopls/internal/lsp/regtest/env_test.go b/gopls/internal/lsp/regtest/env_test.go
59288--- a/gopls/internal/lsp/regtest/env_test.go	2000-01-01 00:00:00.000000000 -0000
59289+++ b/gopls/internal/lsp/regtest/env_test.go	1970-01-01 00:00:00.000000000 +0000
59290@@ -1,66 +0,0 @@
59291-// Copyright 2020 The Go Authors. All rights reserved.
59292-// Use of this source code is governed by a BSD-style
59293-// license that can be found in the LICENSE file.
59294-
59295-package regtest
59296-
59297-import (
59298-	"context"
59299-	"encoding/json"
59300-	"testing"
59301-
59302-	"golang.org/x/tools/gopls/internal/lsp/protocol"
59303-)
59304-
59305-func TestProgressUpdating(t *testing.T) {
59306-	a := &Awaiter{
59307-		state: State{
59308-			work: make(map[protocol.ProgressToken]*workProgress),
59309-		},
59310-	}
59311-	ctx := context.Background()
59312-	if err := a.onWorkDoneProgressCreate(ctx, &protocol.WorkDoneProgressCreateParams{
59313-		Token: "foo",
59314-	}); err != nil {
59315-		t.Fatal(err)
59316-	}
59317-	if err := a.onWorkDoneProgressCreate(ctx, &protocol.WorkDoneProgressCreateParams{
59318-		Token: "bar",
59319-	}); err != nil {
59320-		t.Fatal(err)
59321-	}
59322-	updates := []struct {
59323-		token string
59324-		value interface{}
59325-	}{
59326-		{"foo", protocol.WorkDoneProgressBegin{Kind: "begin", Title: "foo work"}},
59327-		{"bar", protocol.WorkDoneProgressBegin{Kind: "begin", Title: "bar work"}},
59328-		{"foo", protocol.WorkDoneProgressEnd{Kind: "end"}},
59329-		{"bar", protocol.WorkDoneProgressReport{Kind: "report", Percentage: 42}},
59330-	}
59331-	for _, update := range updates {
59332-		params := &protocol.ProgressParams{
59333-			Token: update.token,
59334-			Value: update.value,
59335-		}
59336-		data, err := json.Marshal(params)
59337-		if err != nil {
59338-			t.Fatal(err)
59339-		}
59340-		var unmarshaled protocol.ProgressParams
59341-		if err := json.Unmarshal(data, &unmarshaled); err != nil {
59342-			t.Fatal(err)
59343-		}
59344-		if err := a.onProgress(ctx, &unmarshaled); err != nil {
59345-			t.Fatal(err)
59346-		}
59347-	}
59348-	if !a.state.work["foo"].complete {
59349-		t.Error("work entry \"foo\" is incomplete, want complete")
59350-	}
59351-	got := *a.state.work["bar"]
59352-	want := workProgress{title: "bar work", percent: 42}
59353-	if got != want {
59354-		t.Errorf("work progress for \"bar\": %v, want %v", got, want)
59355-	}
59356-}
59357diff -urN a/gopls/internal/lsp/regtest/expectation.go b/gopls/internal/lsp/regtest/expectation.go
59358--- a/gopls/internal/lsp/regtest/expectation.go	2000-01-01 00:00:00.000000000 -0000
59359+++ b/gopls/internal/lsp/regtest/expectation.go	1970-01-01 00:00:00.000000000 +0000
59360@@ -1,769 +0,0 @@
59361-// Copyright 2020 The Go Authors. All rights reserved.
59362-// Use of this source code is governed by a BSD-style
59363-// license that can be found in the LICENSE file.
59364-
59365-package regtest
59366-
59367-import (
59368-	"fmt"
59369-	"regexp"
59370-	"sort"
59371-	"strings"
59372-
59373-	"golang.org/x/tools/gopls/internal/lsp"
59374-	"golang.org/x/tools/gopls/internal/lsp/protocol"
59375-)
59376-
59377-var (
59378-	// InitialWorkspaceLoad is an expectation that the workspace initial load has
59379-	// completed. It is verified via workdone reporting.
59380-	InitialWorkspaceLoad = CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromInitialWorkspaceLoad), 1, false)
59381-)
59382-
59383-// A Verdict is the result of checking an expectation against the current
59384-// editor state.
59385-type Verdict int
59386-
59387-// Order matters for the following constants: verdicts are sorted in order of
59388-// decisiveness.
59389-const (
59390-	// Met indicates that an expectation is satisfied by the current state.
59391-	Met Verdict = iota
59392-	// Unmet indicates that an expectation is not currently met, but could be met
59393-	// in the future.
59394-	Unmet
59395-	// Unmeetable indicates that an expectation cannot be satisfied in the
59396-	// future.
59397-	Unmeetable
59398-)
59399-
59400-func (v Verdict) String() string {
59401-	switch v {
59402-	case Met:
59403-		return "Met"
59404-	case Unmet:
59405-		return "Unmet"
59406-	case Unmeetable:
59407-		return "Unmeetable"
59408-	}
59409-	return fmt.Sprintf("unrecognized verdict %d", v)
59410-}
59411-
59412-// An Expectation is an expected property of the state of the LSP client.
59413-// The Check function reports whether the property is met.
59414-//
59415-// Expectations are combinators. By composing them, tests may express
59416-// complex expectations in terms of simpler ones.
59417-//
59418-// TODO(rfindley): as expectations are combined, it becomes harder to identify
59419-// why they failed. A better signature for Check would be
59420-//
59421-//	func(State) (Verdict, string)
59422-//
59423-// returning a reason for the verdict that can be composed similarly to
59424-// descriptions.
59425-type Expectation struct {
59426-	Check func(State) Verdict
59427-
59428-	// Description holds a noun-phrase identifying what the expectation checks.
59429-	//
59430-	// TODO(rfindley): revisit existing descriptions to ensure they compose nicely.
59431-	Description string
59432-}
59433-
59434-// OnceMet returns an Expectation that, once the precondition is met, asserts
59435-// that mustMeet is met.
59436-func OnceMet(precondition Expectation, mustMeets ...Expectation) Expectation {
59437-	check := func(s State) Verdict {
59438-		switch pre := precondition.Check(s); pre {
59439-		case Unmeetable:
59440-			return Unmeetable
59441-		case Met:
59442-			for _, mustMeet := range mustMeets {
59443-				verdict := mustMeet.Check(s)
59444-				if verdict != Met {
59445-					return Unmeetable
59446-				}
59447-			}
59448-			return Met
59449-		default:
59450-			return Unmet
59451-		}
59452-	}
59453-	description := describeExpectations(mustMeets...)
59454-	return Expectation{
59455-		Check:       check,
59456-		Description: fmt.Sprintf("once %q is met, must have:\n%s", precondition.Description, description),
59457-	}
59458-}
59459-
59460-func describeExpectations(expectations ...Expectation) string {
59461-	var descriptions []string
59462-	for _, e := range expectations {
59463-		descriptions = append(descriptions, e.Description)
59464-	}
59465-	return strings.Join(descriptions, "\n")
59466-}
59467-
59468-// AnyOf returns an expectation that is satisfied when any of the given
59469-// expectations is met.
59470-func AnyOf(anyOf ...Expectation) Expectation {
59471-	check := func(s State) Verdict {
59472-		for _, e := range anyOf {
59473-			verdict := e.Check(s)
59474-			if verdict == Met {
59475-				return Met
59476-			}
59477-		}
59478-		return Unmet
59479-	}
59480-	description := describeExpectations(anyOf...)
59481-	return Expectation{
59482-		Check:       check,
59483-		Description: fmt.Sprintf("Any of:\n%s", description),
59484-	}
59485-}
59486-
59487-// AllOf expects that all given expectations are met.
59488-//
59489-// TODO(rfindley): the problem with these types of combinators (OnceMet, AnyOf
59490-// and AllOf) is that we lose the information of *why* they failed: the Awaiter
59491-// is not smart enough to look inside.
59492-//
59493-// Refactor the API such that the Check function is responsible for explaining
59494-// why an expectation failed. This should allow us to significantly improve
59495-// test output: we won't need to summarize state at all, as the verdict
59496-// explanation itself should describe clearly why the expectation not met.
59497-func AllOf(allOf ...Expectation) Expectation {
59498-	check := func(s State) Verdict {
59499-		verdict := Met
59500-		for _, e := range allOf {
59501-			if v := e.Check(s); v > verdict {
59502-				verdict = v
59503-			}
59504-		}
59505-		return verdict
59506-	}
59507-	description := describeExpectations(allOf...)
59508-	return Expectation{
59509-		Check:       check,
59510-		Description: fmt.Sprintf("All of:\n%s", description),
59511-	}
59512-}
59513-
59514-// ReadDiagnostics is an Expectation that stores the current diagnostics for
59515-// fileName in into, whenever it is evaluated.
59516-//
59517-// It can be used in combination with OnceMet or AfterChange to capture the
59518-// state of diagnostics when other expectations are satisfied.
59519-func ReadDiagnostics(fileName string, into *protocol.PublishDiagnosticsParams) Expectation {
59520-	check := func(s State) Verdict {
59521-		diags, ok := s.diagnostics[fileName]
59522-		if !ok {
59523-			return Unmeetable
59524-		}
59525-		*into = *diags
59526-		return Met
59527-	}
59528-	return Expectation{
59529-		Check:       check,
59530-		Description: fmt.Sprintf("read diagnostics for %q", fileName),
59531-	}
59532-}
59533-
59534-// ReadAllDiagnostics is an expectation that stores all published diagnostics
59535-// into the provided map, whenever it is evaluated.
59536-//
59537-// It can be used in combination with OnceMet or AfterChange to capture the
59538-// state of diagnostics when other expectations are satisfied.
59539-func ReadAllDiagnostics(into *map[string]*protocol.PublishDiagnosticsParams) Expectation {
59540-	check := func(s State) Verdict {
59541-		allDiags := make(map[string]*protocol.PublishDiagnosticsParams)
59542-		for name, diags := range s.diagnostics {
59543-			allDiags[name] = diags
59544-		}
59545-		*into = allDiags
59546-		return Met
59547-	}
59548-	return Expectation{
59549-		Check:       check,
59550-		Description: "read all diagnostics",
59551-	}
59552-}
59553-
59554-// NoOutstandingWork asserts that there is no work initiated using the LSP
59555-// $/progress API that has not completed.
59556-func NoOutstandingWork() Expectation {
59557-	check := func(s State) Verdict {
59558-		if len(s.outstandingWork()) == 0 {
59559-			return Met
59560-		}
59561-		return Unmet
59562-	}
59563-	return Expectation{
59564-		Check:       check,
59565-		Description: "no outstanding work",
59566-	}
59567-}
59568-
59569-// NoShownMessage asserts that the editor has not received a ShowMessage.
59570-func NoShownMessage(subString string) Expectation {
59571-	check := func(s State) Verdict {
59572-		for _, m := range s.showMessage {
59573-			if strings.Contains(m.Message, subString) {
59574-				return Unmeetable
59575-			}
59576-		}
59577-		return Met
59578-	}
59579-	return Expectation{
59580-		Check:       check,
59581-		Description: fmt.Sprintf("no ShowMessage received containing %q", subString),
59582-	}
59583-}
59584-
59585-// ShownMessage asserts that the editor has received a ShowMessageRequest
59586-// containing the given substring.
59587-func ShownMessage(containing string) Expectation {
59588-	check := func(s State) Verdict {
59589-		for _, m := range s.showMessage {
59590-			if strings.Contains(m.Message, containing) {
59591-				return Met
59592-			}
59593-		}
59594-		return Unmet
59595-	}
59596-	return Expectation{
59597-		Check:       check,
59598-		Description: "received ShowMessage",
59599-	}
59600-}
59601-
59602-// ShowMessageRequest asserts that the editor has received a ShowMessageRequest
59603-// with an action item that has the given title.
59604-func ShowMessageRequest(title string) Expectation {
59605-	check := func(s State) Verdict {
59606-		if len(s.showMessageRequest) == 0 {
59607-			return Unmet
59608-		}
59609-		// Only check the most recent one.
59610-		m := s.showMessageRequest[len(s.showMessageRequest)-1]
59611-		if len(m.Actions) == 0 || len(m.Actions) > 1 {
59612-			return Unmet
59613-		}
59614-		if m.Actions[0].Title == title {
59615-			return Met
59616-		}
59617-		return Unmet
59618-	}
59619-	return Expectation{
59620-		Check:       check,
59621-		Description: "received ShowMessageRequest",
59622-	}
59623-}
59624-
59625-// DoneDiagnosingChanges expects that diagnostics are complete from common
59626-// change notifications: didOpen, didChange, didSave, didChangeWatchedFiles,
59627-// and didClose.
59628-//
59629-// This can be used when multiple notifications may have been sent, such as
59630-// when a didChange is immediately followed by a didSave. It is insufficient to
59631-// simply await NoOutstandingWork, because the LSP client has no control over
59632-// when the server starts processing a notification. Therefore, we must keep
59633-// track of
59634-func (e *Env) DoneDiagnosingChanges() Expectation {
59635-	stats := e.Editor.Stats()
59636-	statsBySource := map[lsp.ModificationSource]uint64{
59637-		lsp.FromDidOpen:               stats.DidOpen,
59638-		lsp.FromDidChange:             stats.DidChange,
59639-		lsp.FromDidSave:               stats.DidSave,
59640-		lsp.FromDidChangeWatchedFiles: stats.DidChangeWatchedFiles,
59641-		lsp.FromDidClose:              stats.DidClose,
59642-	}
59643-
59644-	var expected []lsp.ModificationSource
59645-	for k, v := range statsBySource {
59646-		if v > 0 {
59647-			expected = append(expected, k)
59648-		}
59649-	}
59650-
59651-	// Sort for stability.
59652-	sort.Slice(expected, func(i, j int) bool {
59653-		return expected[i] < expected[j]
59654-	})
59655-
59656-	var all []Expectation
59657-	for _, source := range expected {
59658-		all = append(all, CompletedWork(lsp.DiagnosticWorkTitle(source), statsBySource[source], true))
59659-	}
59660-
59661-	return AllOf(all...)
59662-}
59663-
59664-// AfterChange expects that the given expectations will be met after all
59665-// state-changing notifications have been processed by the server.
59666-//
59667-// It awaits the completion of all anticipated work before checking the given
59668-// expectations.
59669-func (e *Env) AfterChange(expectations ...Expectation) {
59670-	e.T.Helper()
59671-	e.OnceMet(
59672-		e.DoneDiagnosingChanges(),
59673-		expectations...,
59674-	)
59675-}
59676-
59677-// DoneWithOpen expects all didOpen notifications currently sent by the editor
59678-// to be completely processed.
59679-func (e *Env) DoneWithOpen() Expectation {
59680-	opens := e.Editor.Stats().DidOpen
59681-	return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), opens, true)
59682-}
59683-
59684-// StartedChange expects that the server has at least started processing all
59685-// didChange notifications sent from the client.
59686-func (e *Env) StartedChange() Expectation {
59687-	changes := e.Editor.Stats().DidChange
59688-	return StartedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), changes)
59689-}
59690-
59691-// DoneWithChange expects all didChange notifications currently sent by the
59692-// editor to be completely processed.
59693-func (e *Env) DoneWithChange() Expectation {
59694-	changes := e.Editor.Stats().DidChange
59695-	return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), changes, true)
59696-}
59697-
59698-// DoneWithSave expects all didSave notifications currently sent by the editor
59699-// to be completely processed.
59700-func (e *Env) DoneWithSave() Expectation {
59701-	saves := e.Editor.Stats().DidSave
59702-	return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidSave), saves, true)
59703-}
59704-
59705-// StartedChangeWatchedFiles expects that the server has at least started
59706-// processing all didChangeWatchedFiles notifications sent from the client.
59707-func (e *Env) StartedChangeWatchedFiles() Expectation {
59708-	changes := e.Editor.Stats().DidChangeWatchedFiles
59709-	return StartedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChangeWatchedFiles), changes)
59710-}
59711-
59712-// DoneWithChangeWatchedFiles expects all didChangeWatchedFiles notifications
59713-// currently sent by the editor to be completely processed.
59714-func (e *Env) DoneWithChangeWatchedFiles() Expectation {
59715-	changes := e.Editor.Stats().DidChangeWatchedFiles
59716-	return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChangeWatchedFiles), changes, true)
59717-}
59718-
59719-// DoneWithClose expects all didClose notifications currently sent by the
59720-// editor to be completely processed.
59721-func (e *Env) DoneWithClose() Expectation {
59722-	changes := e.Editor.Stats().DidClose
59723-	return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidClose), changes, true)
59724-}
59725-
59726-// StartedWork expect a work item to have been started >= atLeast times.
59727-//
59728-// See CompletedWork.
59729-func StartedWork(title string, atLeast uint64) Expectation {
59730-	check := func(s State) Verdict {
59731-		if s.startedWork()[title] >= atLeast {
59732-			return Met
59733-		}
59734-		return Unmet
59735-	}
59736-	return Expectation{
59737-		Check:       check,
59738-		Description: fmt.Sprintf("started work %q at least %d time(s)", title, atLeast),
59739-	}
59740-}
59741-
59742-// CompletedWork expects a work item to have been completed >= atLeast times.
59743-//
59744-// Since the Progress API doesn't include any hidden metadata, we must use the
59745-// progress notification title to identify the work we expect to be completed.
59746-func CompletedWork(title string, count uint64, atLeast bool) Expectation {
59747-	check := func(s State) Verdict {
59748-		completed := s.completedWork()
59749-		if completed[title] == count || atLeast && completed[title] > count {
59750-			return Met
59751-		}
59752-		return Unmet
59753-	}
59754-	desc := fmt.Sprintf("completed work %q %v times", title, count)
59755-	if atLeast {
59756-		desc = fmt.Sprintf("completed work %q at least %d time(s)", title, count)
59757-	}
59758-	return Expectation{
59759-		Check:       check,
59760-		Description: desc,
59761-	}
59762-}
59763-
59764-type WorkStatus struct {
59765-	// Last seen message from either `begin` or `report` progress.
59766-	Msg string
59767-	// Message sent with `end` progress message.
59768-	EndMsg string
59769-}
59770-
59771-// CompletedProgress expects that workDone progress is complete for the given
59772-// progress token. When non-nil WorkStatus is provided, it will be filled
59773-// when the expectation is met.
59774-//
59775-// If the token is not a progress token that the client has seen, this
59776-// expectation is Unmeetable.
59777-func CompletedProgress(token protocol.ProgressToken, into *WorkStatus) Expectation {
59778-	check := func(s State) Verdict {
59779-		work, ok := s.work[token]
59780-		if !ok {
59781-			return Unmeetable // TODO(rfindley): refactor to allow the verdict to explain this result
59782-		}
59783-		if work.complete {
59784-			if into != nil {
59785-				into.Msg = work.msg
59786-				into.EndMsg = work.endMsg
59787-			}
59788-			return Met
59789-		}
59790-		return Unmet
59791-	}
59792-	desc := fmt.Sprintf("completed work for token %v", token)
59793-	return Expectation{
59794-		Check:       check,
59795-		Description: desc,
59796-	}
59797-}
59798-
59799-// OutstandingWork expects a work item to be outstanding. The given title must
59800-// be an exact match, whereas the given msg must only be contained in the work
59801-// item's message.
59802-func OutstandingWork(title, msg string) Expectation {
59803-	check := func(s State) Verdict {
59804-		for _, work := range s.work {
59805-			if work.complete {
59806-				continue
59807-			}
59808-			if work.title == title && strings.Contains(work.msg, msg) {
59809-				return Met
59810-			}
59811-		}
59812-		return Unmet
59813-	}
59814-	return Expectation{
59815-		Check:       check,
59816-		Description: fmt.Sprintf("outstanding work: %q containing %q", title, msg),
59817-	}
59818-}
59819-
59820-// NoErrorLogs asserts that the client has not received any log messages of
59821-// error severity.
59822-func NoErrorLogs() Expectation {
59823-	return NoLogMatching(protocol.Error, "")
59824-}
59825-
59826-// LogMatching asserts that the client has received a log message
59827-// of type typ matching the regexp re a certain number of times.
59828-//
59829-// The count argument specifies the expected number of matching logs. If
59830-// atLeast is set, this is a lower bound, otherwise there must be exactly count
59831-// matching logs.
59832-func LogMatching(typ protocol.MessageType, re string, count int, atLeast bool) Expectation {
59833-	rec, err := regexp.Compile(re)
59834-	if err != nil {
59835-		panic(err)
59836-	}
59837-	check := func(state State) Verdict {
59838-		var found int
59839-		for _, msg := range state.logs {
59840-			if msg.Type == typ && rec.Match([]byte(msg.Message)) {
59841-				found++
59842-			}
59843-		}
59844-		// Check for an exact or "at least" match.
59845-		if found == count || (found >= count && atLeast) {
59846-			return Met
59847-		}
59848-		return Unmet
59849-	}
59850-	desc := fmt.Sprintf("log message matching %q expected %v times", re, count)
59851-	if atLeast {
59852-		desc = fmt.Sprintf("log message matching %q expected at least %v times", re, count)
59853-	}
59854-	return Expectation{
59855-		Check:       check,
59856-		Description: desc,
59857-	}
59858-}
59859-
59860-// NoLogMatching asserts that the client has not received a log message
59861-// of type typ matching the regexp re. If re is an empty string, any log
59862-// message is considered a match.
59863-func NoLogMatching(typ protocol.MessageType, re string) Expectation {
59864-	var r *regexp.Regexp
59865-	if re != "" {
59866-		var err error
59867-		r, err = regexp.Compile(re)
59868-		if err != nil {
59869-			panic(err)
59870-		}
59871-	}
59872-	check := func(state State) Verdict {
59873-		for _, msg := range state.logs {
59874-			if msg.Type != typ {
59875-				continue
59876-			}
59877-			if r == nil || r.Match([]byte(msg.Message)) {
59878-				return Unmeetable
59879-			}
59880-		}
59881-		return Met
59882-	}
59883-	return Expectation{
59884-		Check:       check,
59885-		Description: fmt.Sprintf("no log message matching %q", re),
59886-	}
59887-}
59888-
59889-// FileWatchMatching expects that a file registration matches re.
59890-func FileWatchMatching(re string) Expectation {
59891-	return Expectation{
59892-		Check:       checkFileWatch(re, Met, Unmet),
59893-		Description: fmt.Sprintf("file watch matching %q", re),
59894-	}
59895-}
59896-
59897-// NoFileWatchMatching expects that no file registration matches re.
59898-func NoFileWatchMatching(re string) Expectation {
59899-	return Expectation{
59900-		Check:       checkFileWatch(re, Unmet, Met),
59901-		Description: fmt.Sprintf("no file watch matching %q", re),
59902-	}
59903-}
59904-
59905-func checkFileWatch(re string, onMatch, onNoMatch Verdict) func(State) Verdict {
59906-	rec := regexp.MustCompile(re)
59907-	return func(s State) Verdict {
59908-		r := s.registeredCapabilities["workspace/didChangeWatchedFiles"]
59909-		watchers := jsonProperty(r.RegisterOptions, "watchers").([]interface{})
59910-		for _, watcher := range watchers {
59911-			pattern := jsonProperty(watcher, "globPattern").(string)
59912-			if rec.MatchString(pattern) {
59913-				return onMatch
59914-			}
59915-		}
59916-		return onNoMatch
59917-	}
59918-}
59919-
59920-// jsonProperty extracts a value from a path of JSON property names, assuming
59921-// the default encoding/json unmarshaling to the empty interface (i.e.: that
59922-// JSON objects are unmarshalled as map[string]interface{})
59923-//
59924-// For example, if obj is unmarshalled from the following json:
59925-//
59926-//	{
59927-//		"foo": { "bar": 3 }
59928-//	}
59929-//
59930-// Then jsonProperty(obj, "foo", "bar") will be 3.
59931-func jsonProperty(obj interface{}, path ...string) interface{} {
59932-	if len(path) == 0 || obj == nil {
59933-		return obj
59934-	}
59935-	m := obj.(map[string]interface{})
59936-	return jsonProperty(m[path[0]], path[1:]...)
59937-}
59938-
59939-// RegistrationMatching asserts that the client has received a capability
59940-// registration matching the given regexp.
59941-//
59942-// TODO(rfindley): remove this once TestWatchReplaceTargets has been revisited.
59943-//
59944-// Deprecated: use (No)FileWatchMatching
59945-func RegistrationMatching(re string) Expectation {
59946-	rec := regexp.MustCompile(re)
59947-	check := func(s State) Verdict {
59948-		for _, p := range s.registrations {
59949-			for _, r := range p.Registrations {
59950-				if rec.Match([]byte(r.Method)) {
59951-					return Met
59952-				}
59953-			}
59954-		}
59955-		return Unmet
59956-	}
59957-	return Expectation{
59958-		Check:       check,
59959-		Description: fmt.Sprintf("registration matching %q", re),
59960-	}
59961-}
59962-
59963-// UnregistrationMatching asserts that the client has received an
59964-// unregistration whose ID matches the given regexp.
59965-func UnregistrationMatching(re string) Expectation {
59966-	rec := regexp.MustCompile(re)
59967-	check := func(s State) Verdict {
59968-		for _, p := range s.unregistrations {
59969-			for _, r := range p.Unregisterations {
59970-				if rec.Match([]byte(r.Method)) {
59971-					return Met
59972-				}
59973-			}
59974-		}
59975-		return Unmet
59976-	}
59977-	return Expectation{
59978-		Check:       check,
59979-		Description: fmt.Sprintf("unregistration matching %q", re),
59980-	}
59981-}
59982-
59983-// Diagnostics asserts that there is at least one diagnostic matching the given
59984-// filters.
59985-func Diagnostics(filters ...DiagnosticFilter) Expectation {
59986-	check := func(s State) Verdict {
59987-		diags := flattenDiagnostics(s)
59988-		for _, filter := range filters {
59989-			var filtered []flatDiagnostic
59990-			for _, d := range diags {
59991-				if filter.check(d.name, d.diag) {
59992-					filtered = append(filtered, d)
59993-				}
59994-			}
59995-			if len(filtered) == 0 {
59996-				// TODO(rfindley): if/when expectations describe their own failure, we
59997-				// can provide more useful information here as to which filter caused
59998-				// the failure.
59999-				return Unmet
60000-			}
60001-			diags = filtered
60002-		}
60003-		return Met
60004-	}
60005-	var descs []string
60006-	for _, filter := range filters {
60007-		descs = append(descs, filter.desc)
60008-	}
60009-	return Expectation{
60010-		Check:       check,
60011-		Description: "any diagnostics " + strings.Join(descs, ", "),
60012-	}
60013-}
60014-
60015-// NoDiagnostics asserts that there are no diagnostics matching the given
60016-// filters. Notably, if no filters are supplied this assertion checks that
60017-// there are no diagnostics at all, for any file.
60018-func NoDiagnostics(filters ...DiagnosticFilter) Expectation {
60019-	check := func(s State) Verdict {
60020-		diags := flattenDiagnostics(s)
60021-		for _, filter := range filters {
60022-			var filtered []flatDiagnostic
60023-			for _, d := range diags {
60024-				if filter.check(d.name, d.diag) {
60025-					filtered = append(filtered, d)
60026-				}
60027-			}
60028-			diags = filtered
60029-		}
60030-		if len(diags) > 0 {
60031-			return Unmet
60032-		}
60033-		return Met
60034-	}
60035-	var descs []string
60036-	for _, filter := range filters {
60037-		descs = append(descs, filter.desc)
60038-	}
60039-	return Expectation{
60040-		Check:       check,
60041-		Description: "no diagnostics " + strings.Join(descs, ", "),
60042-	}
60043-}
60044-
60045-type flatDiagnostic struct {
60046-	name string
60047-	diag protocol.Diagnostic
60048-}
60049-
60050-func flattenDiagnostics(state State) []flatDiagnostic {
60051-	var result []flatDiagnostic
60052-	for name, diags := range state.diagnostics {
60053-		for _, diag := range diags.Diagnostics {
60054-			result = append(result, flatDiagnostic{name, diag})
60055-		}
60056-	}
60057-	return result
60058-}
60059-
60060-// -- Diagnostic filters --
60061-
60062-// A DiagnosticFilter filters the set of diagnostics, for assertion with
60063-// Diagnostics or NoDiagnostics.
60064-type DiagnosticFilter struct {
60065-	desc  string
60066-	check func(name string, _ protocol.Diagnostic) bool
60067-}
60068-
60069-// ForFile filters to diagnostics matching the sandbox-relative file name.
60070-func ForFile(name string) DiagnosticFilter {
60071-	return DiagnosticFilter{
60072-		desc: fmt.Sprintf("for file %q", name),
60073-		check: func(diagName string, _ protocol.Diagnostic) bool {
60074-			return diagName == name
60075-		},
60076-	}
60077-}
60078-
60079-// FromSource filters to diagnostics matching the given diagnostics source.
60080-func FromSource(source string) DiagnosticFilter {
60081-	return DiagnosticFilter{
60082-		desc: fmt.Sprintf("with source %q", source),
60083-		check: func(_ string, d protocol.Diagnostic) bool {
60084-			return d.Source == source
60085-		},
60086-	}
60087-}
60088-
60089-// AtRegexp filters to diagnostics in the file with sandbox-relative path name,
60090-// at the first position matching the given regexp pattern.
60091-//
60092-// TODO(rfindley): pass in the editor to expectations, so that they may depend
60093-// on editor state and AtRegexp can be a function rather than a method.
60094-func (e *Env) AtRegexp(name, pattern string) DiagnosticFilter {
60095-	loc := e.RegexpSearch(name, pattern)
60096-	return DiagnosticFilter{
60097-		desc: fmt.Sprintf("at the first position matching %#q in %q", pattern, name),
60098-		check: func(diagName string, d protocol.Diagnostic) bool {
60099-			return diagName == name && d.Range.Start == loc.Range.Start
60100-		},
60101-	}
60102-}
60103-
60104-// AtPosition filters to diagnostics at location name:line:character, for a
60105-// sandbox-relative path name.
60106-//
60107-// Line and character are 0-based, and character measures UTF-16 codes.
60108-//
60109-// Note: prefer the more readable AtRegexp.
60110-func AtPosition(name string, line, character uint32) DiagnosticFilter {
60111-	pos := protocol.Position{Line: line, Character: character}
60112-	return DiagnosticFilter{
60113-		desc: fmt.Sprintf("at %s:%d:%d", name, line, character),
60114-		check: func(diagName string, d protocol.Diagnostic) bool {
60115-			return diagName == name && d.Range.Start == pos
60116-		},
60117-	}
60118-}
60119-
60120-// WithMessage filters to diagnostics whose message contains the given
60121-// substring.
60122-func WithMessage(substring string) DiagnosticFilter {
60123-	return DiagnosticFilter{
60124-		desc: fmt.Sprintf("with message containing %q", substring),
60125-		check: func(_ string, d protocol.Diagnostic) bool {
60126-			return strings.Contains(d.Message, substring)
60127-		},
60128-	}
60129-}
60130diff -urN a/gopls/internal/lsp/regtest/marker.go b/gopls/internal/lsp/regtest/marker.go
60131--- a/gopls/internal/lsp/regtest/marker.go	2000-01-01 00:00:00.000000000 -0000
60132+++ b/gopls/internal/lsp/regtest/marker.go	1970-01-01 00:00:00.000000000 +0000
60133@@ -1,1273 +0,0 @@
60134-// Copyright 2023 The Go Authors. All rights reserved.
60135-// Use of this source code is governed by a BSD-style
60136-// license that can be found in the LICENSE file.
60137-
60138-package regtest
60139-
60140-import (
60141-	"bytes"
60142-	"context"
60143-	"encoding/json"
60144-	"flag"
60145-	"fmt"
60146-	"go/token"
60147-	"io/fs"
60148-	"os"
60149-	"path"
60150-	"path/filepath"
60151-	"reflect"
60152-	"regexp"
60153-	"sort"
60154-	"strings"
60155-	"testing"
60156-
60157-	"golang.org/x/tools/go/expect"
60158-	"golang.org/x/tools/gopls/internal/hooks"
60159-	"golang.org/x/tools/gopls/internal/lsp/cache"
60160-	"golang.org/x/tools/gopls/internal/lsp/debug"
60161-	"golang.org/x/tools/gopls/internal/lsp/fake"
60162-	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
60163-	"golang.org/x/tools/gopls/internal/lsp/protocol"
60164-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
60165-	"golang.org/x/tools/gopls/internal/lsp/source"
60166-	"golang.org/x/tools/gopls/internal/lsp/tests"
60167-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
60168-	"golang.org/x/tools/internal/jsonrpc2"
60169-	"golang.org/x/tools/internal/jsonrpc2/servertest"
60170-	"golang.org/x/tools/internal/testenv"
60171-	"golang.org/x/tools/txtar"
60172-)
60173-
60174-var update = flag.Bool("update", false, "if set, update test data during marker tests")
60175-
60176-// RunMarkerTests runs "marker" tests in the given test data directory.
60177-//
60178-// A marker test uses the '//@' marker syntax of the x/tools/go/expect package
60179-// to annotate source code with various information such as locations and
60180-// arguments of LSP operations to be executed by the test. The syntax following
60181-// '@' is parsed as a comma-separated list of ordinary Go function calls, for
60182-// example
60183-//
60184-//	//@foo(a, "b", 3),bar(0)
60185-//
60186-// and delegates to a corresponding function to perform LSP-related operations.
60187-// See the Marker types documentation below for a list of supported markers.
60188-//
60189-// Each call argument is converted to the type of the corresponding parameter of
60190-// the designated function. The conversion logic may use the surrounding context,
60191-// such as the position or nearby text. See the Argument conversion section below
60192-// for the full set of special conversions. As a special case, the blank
60193-// identifier '_' is treated as the zero value of the parameter type.
60194-//
60195-// The test runner collects test cases by searching the given directory for
60196-// files with the .txt extension. Each file is interpreted as a txtar archive,
60197-// which is extracted to a temporary directory. The relative path to the .txt
60198-// file is used as the subtest name. The preliminary section of the file
60199-// (before the first archive entry) is a free-form comment.
60200-//
60201-// These tests were inspired by (and in many places copied from) a previous
60202-// iteration of the marker tests built on top of the packagestest framework.
60203-// Key design decisions motivating this reimplementation are as follows:
60204-//   - The old tests had a single global session, causing interaction at a
60205-//     distance and several awkward workarounds.
60206-//   - The old tests could not be safely parallelized, because certain tests
60207-//     manipulated the server options
60208-//   - Relatedly, the old tests did not have a logic grouping of assertions into
60209-//     a single unit, resulting in clusters of files serving clusters of
60210-//     entangled assertions.
60211-//   - The old tests used locations in the source as test names and as the
60212-//     identity of golden content, meaning that a single edit could change the
60213-//     name of an arbitrary number of subtests, and making it difficult to
60214-//     manually edit golden content.
60215-//   - The old tests did not hew closely to LSP concepts, resulting in, for
60216-//     example, each marker implementation doing its own position
60217-//     transformations, and inventing its own mechanism for configuration.
60218-//   - The old tests had an ad-hoc session initialization process. The regtest
60219-//     environment has had more time devoted to its initialization, and has a
60220-//     more convenient API.
60221-//   - The old tests lacked documentation, and often had failures that were hard
60222-//     to understand. By starting from scratch, we can revisit these aspects.
60223-//
60224-// # Special files
60225-//
60226-// There are three types of file within the test archive that are given special
60227-// treatment by the test runner:
60228-//   - "flags": this file is treated as a whitespace-separated list of flags
60229-//     that configure the MarkerTest instance. For example, -min_go=go1.18 sets
60230-//     the minimum required Go version for the test.
60231-//     TODO(rfindley): support flag values containing whitespace.
60232-//   - "settings.json": this file is parsed as JSON, and used as the
60233-//     session configuration (see gopls/doc/settings.md)
60234-//   - "env": this file is parsed as a list of VAR=VALUE fields specifying the
60235-//     editor environment.
60236-//   - Golden files: Within the archive, file names starting with '@' are
60237-//     treated as "golden" content, and are not written to disk, but instead are
60238-//     made available to test methods expecting an argument of type *Golden,
60239-//     using the identifier following '@'. For example, if the first parameter of
60240-//     Foo were of type *Golden, the test runner would convert the identifier a
60241-//     in the call @foo(a, "b", 3) into a *Golden by collecting golden file
60242-//     data starting with "@a/".
60243-//
60244-// # Marker types
60245-//
60246-// The following markers are supported within marker tests:
60247-//
60248-//   - diag(location, regexp): specifies an expected diagnostic matching the
60249-//     given regexp at the given location. The test runner requires
60250-//     a 1:1 correspondence between observed diagnostics and diag annotations
60251-//
60252-//   - def(src, dst location): perform a textDocument/definition request at
60253-//     the src location, and check the the result points to the dst location.
60254-//
60255-//   - hover(src, dst location, g Golden): perform a textDocument/hover at the
60256-//     src location, and checks that the result is the dst location, with hover
60257-//     content matching "hover.md" in the golden data g.
60258-//
60259-//   - loc(name, location): specifies the name for a location in the source. These
60260-//     locations may be referenced by other markers.
60261-//
60262-//   - rename(location, new, golden): specifies a renaming of the
60263-//     identifier at the specified location to the new name.
60264-//     The golden directory contains the transformed files.
60265-//
60266-//   - renameerr(location, new, wantError): specifies a renaming that
60267-//     fails with an error that matches the expectation.
60268-//
60269-//   - suggestedfix(location, regexp, kind, golden): like diag, the location and
60270-//     regexp identify an expected diagnostic. This diagnostic must
60271-//     to have exactly one associated code action of the specified kind.
60272-//     This action is executed for its editing effects on the source files.
60273-//     Like rename, the golden directory contains the expected transformed files.
60274-//
60275-// # Argument conversion
60276-//
60277-// Marker arguments are first parsed by the go/expect package, which accepts
60278-// the following tokens as defined by the Go spec:
60279-//   - string, int64, float64, and rune literals
60280-//   - true and false
60281-//   - nil
60282-//   - identifiers (type expect.Identifier)
60283-//   - regular expressions, denoted the two tokens re"abc" (type *regexp.Regexp)
60284-//
60285-// These values are passed as arguments to the corresponding parameter of the
60286-// test function. Additional value conversions may occur for these argument ->
60287-// parameter type pairs:
60288-//   - string->regexp: the argument is parsed as a regular expressions.
60289-//   - string->location: the argument is converted to the location of the first
60290-//     instance of the argument in the partial line preceding the note.
60291-//   - regexp->location: the argument is converted to the location of the first
60292-//     match for the argument in the partial line preceding the note. If the
60293-//     regular expression contains exactly one subgroup, the position of the
60294-//     subgroup is used rather than the position of the submatch.
60295-//   - name->location: the argument is replaced by the named location.
60296-//   - name->Golden: the argument is used to look up golden content prefixed by
60297-//     @<argument>.
60298-//   - {string,regexp,identifier}->wantError: a wantError type specifies
60299-//     an expected error message, either in the form of a substring that
60300-//     must be present, a regular expression that it must match, or an
60301-//     identifier (e.g. foo) such that the archive entry @foo
60302-//     exists and contains the exact expected error.
60303-//
60304-// # Example
60305-//
60306-// Here is a complete example:
60307-//
60308-//	-- a.go --
60309-//	package a
60310-//
60311-//	const abc = 0x2a //@hover("b", "abc", abc),hover(" =", "abc", abc)
60312-//	-- @abc/hover.md --
60313-//	```go
60314-//	const abc untyped int = 42
60315-//	```
60316-//
60317-//	@hover("b", "abc", abc),hover(" =", "abc", abc)
60318-//
60319-// In this example, the @hover annotation tells the test runner to run the
60320-// hoverMarker function, which has parameters:
60321-//
60322-//	(mark marker, src, dsc protocol.Location, g *Golden).
60323-//
60324-// The first argument holds the test context, including fake editor with open
60325-// files, and sandboxed directory.
60326-//
60327-// Argument converters translate the "b" and "abc" arguments into locations by
60328-// interpreting each one as a regular expression and finding the location of
60329-// its first match on the preceding portion of the line, and the abc identifier
60330-// into a dictionary of golden content containing "hover.md". Then the
60331-// hoverMarker method executes a textDocument/hover LSP request at the src
60332-// position, and ensures the result spans "abc", with the markdown content from
60333-// hover.md. (Note that the markdown content includes the expect annotation as
60334-// the doc comment.)
60335-//
60336-// The next hover on the same line asserts the same result, but initiates the
60337-// hover immediately after "abc" in the source. This tests that we find the
60338-// preceding identifier when hovering.
60339-//
60340-// # Updating golden files
60341-//
60342-// To update golden content in the test archive, it is easier to regenerate
60343-// content automatically rather than edit it by hand. To do this, run the
60344-// tests with the -update flag. Only tests that actually run will be updated.
60345-//
60346-// In some cases, golden content will vary by Go version (for example, gopls
60347-// produces different markdown at Go versions before the 1.19 go/doc update).
60348-// By convention, the golden content in test archives should match the output
60349-// at Go tip. Each test function can normalize golden content for older Go
60350-// versions.
60351-//
60352-// Note that -update does not cause missing @diag or @loc markers to be added.
60353-//
60354-// # TODO
60355-//
60356-// This API is a work-in-progress, as we migrate existing marker tests from
60357-// internal/lsp/tests.
60358-//
60359-// Remaining TODO:
60360-//   - parallelize/optimize test execution
60361-//   - reorganize regtest packages (and rename to just 'test'?)
60362-//   - Rename the files .txtar.
60363-//
60364-// Existing marker tests to port:
60365-//   - CallHierarchy
60366-//   - CodeLens
60367-//   - Diagnostics
60368-//   - CompletionItems
60369-//   - Completions
60370-//   - CompletionSnippets
60371-//   - UnimportedCompletions
60372-//   - DeepCompletions
60373-//   - FuzzyCompletions
60374-//   - CaseSensitiveCompletions
60375-//   - RankCompletions
60376-//   - FoldingRanges
60377-//   - Formats
60378-//   - Imports
60379-//   - SemanticTokens
60380-//   - SuggestedFixes
60381-//   - FunctionExtractions
60382-//   - MethodExtractions
60383-//   - Definitions
60384-//   - Implementations
60385-//   - Highlights
60386-//   - References
60387-//   - Renames
60388-//   - PrepareRenames
60389-//   - Symbols
60390-//   - InlayHints
60391-//   - WorkspaceSymbols
60392-//   - Signatures
60393-//   - Links
60394-//   - AddImport
60395-//   - SelectionRanges
60396-func RunMarkerTests(t *testing.T, dir string) {
60397-	// The marker tests must be able to run go/packages.Load.
60398-	testenv.NeedsGoPackages(t)
60399-
60400-	tests, err := loadMarkerTests(dir)
60401-	if err != nil {
60402-		t.Fatal(err)
60403-	}
60404-
60405-	// Opt: use a shared cache.
60406-	// TODO(rfindley): opt: use a memoize store with no eviction.
60407-	cache := cache.New(nil)
60408-
60409-	for _, test := range tests {
60410-		t.Run(test.name, func(t *testing.T) {
60411-			// TODO(rfindley): it may be more useful to have full support for build
60412-			// constraints.
60413-			if test.minGoVersion != "" {
60414-				var go1point int
60415-				if _, err := fmt.Sscanf(test.minGoVersion, "go1.%d", &go1point); err != nil {
60416-					t.Fatalf("parsing -min_go version: %v", err)
60417-				}
60418-				testenv.NeedsGo1Point(t, 18)
60419-			}
60420-			config := fake.EditorConfig{
60421-				Settings: test.settings,
60422-				Env:      test.env,
60423-			}
60424-			run := &markerTestRun{
60425-				test: test,
60426-				env:  newEnv(t, cache, test.files, config),
60427-
60428-				locations: make(map[expect.Identifier]protocol.Location),
60429-				diags:     make(map[protocol.Location][]protocol.Diagnostic),
60430-			}
60431-			// TODO(rfindley): make it easier to clean up the regtest environment.
60432-			defer run.env.Editor.Shutdown(context.Background()) // ignore error
60433-			defer run.env.Sandbox.Close()                       // ignore error
60434-
60435-			// Open all files so that we operate consistently with LSP clients, and
60436-			// (pragmatically) so that we have a Mapper available via the fake
60437-			// editor.
60438-			//
60439-			// This also allows avoiding mutating the editor state in tests.
60440-			for file := range test.files {
60441-				run.env.OpenFile(file)
60442-			}
60443-
60444-			// Pre-process locations.
60445-			var markers []marker
60446-			for _, note := range test.notes {
60447-				mark := marker{run: run, note: note}
60448-				switch note.Name {
60449-				case "loc":
60450-					mark.execute()
60451-				default:
60452-					markers = append(markers, mark)
60453-				}
60454-			}
60455-
60456-			// Wait for the didOpen notifications to be processed, then collect
60457-			// diagnostics.
60458-			var diags map[string]*protocol.PublishDiagnosticsParams
60459-			run.env.AfterChange(ReadAllDiagnostics(&diags))
60460-			for path, params := range diags {
60461-				uri := run.env.Sandbox.Workdir.URI(path)
60462-				for _, diag := range params.Diagnostics {
60463-					loc := protocol.Location{
60464-						URI:   uri,
60465-						Range: diag.Range,
60466-					}
60467-					run.diags[loc] = append(run.diags[loc], diag)
60468-				}
60469-			}
60470-
60471-			// Invoke each remaining marker in the test.
60472-			for _, mark := range markers {
60473-				mark.execute()
60474-			}
60475-
60476-			// Any remaining (un-eliminated) diagnostics are an error.
60477-			for loc, diags := range run.diags {
60478-				for _, diag := range diags {
60479-					t.Errorf("%s: unexpected diagnostic: %q", run.fmtLoc(loc), diag.Message)
60480-				}
60481-			}
60482-
60483-			formatted, err := formatTest(test)
60484-			if err != nil {
60485-				t.Errorf("formatTest: %v", err)
60486-			} else if *update {
60487-				filename := filepath.Join(dir, test.name)
60488-				if err := os.WriteFile(filename, formatted, 0644); err != nil {
60489-					t.Error(err)
60490-				}
60491-			} else {
60492-				// On go 1.19 and later, verify that the testdata has not changed.
60493-				//
60494-				// On earlier Go versions, the golden test data varies due to different
60495-				// markdown escaping.
60496-				//
60497-				// Only check this if the test hasn't already failed, otherwise we'd
60498-				// report duplicate mismatches of golden data.
60499-				if testenv.Go1Point() >= 19 && !t.Failed() {
60500-					// Otherwise, verify that formatted content matches.
60501-					if diff := compare.NamedText("formatted", "on-disk", string(formatted), string(test.content)); diff != "" {
60502-						t.Errorf("formatted test does not match on-disk content:\n%s", diff)
60503-					}
60504-				}
60505-			}
60506-		})
60507-	}
60508-}
60509-
60510-// A marker holds state for the execution of a single @marker
60511-// annotation in the source.
60512-type marker struct {
60513-	run  *markerTestRun
60514-	note *expect.Note
60515-}
60516-
60517-// errorf reports an error with a prefix indicating the position of the marker note.
60518-func (mark marker) errorf(format string, args ...interface{}) {
60519-	msg := fmt.Sprintf(format, args...)
60520-	// TODO(adonovan): consider using fmt.Fprintf(os.Stderr)+t.Fail instead of
60521-	// t.Errorf to avoid reporting uninteresting positions in the Go source of
60522-	// the driver. However, this loses the order of stderr wrt "FAIL: TestFoo"
60523-	// subtest dividers.
60524-	mark.run.env.T.Errorf("%s: %s", mark.run.fmtPos(mark.note.Pos), msg)
60525-}
60526-
60527-// execute invokes the marker's function with the arguments from note.
60528-func (mark marker) execute() {
60529-	fn, ok := markerFuncs[mark.note.Name]
60530-	if !ok {
60531-		mark.errorf("no marker function named %s", mark.note.Name)
60532-		return
60533-	}
60534-
60535-	// The first converter corresponds to the *Env argument.
60536-	// All others must be converted from the marker syntax.
60537-	if got, want := len(mark.note.Args), len(fn.converters); got != want {
60538-		mark.errorf("got %d arguments to %s, expect %d", got, mark.note.Name, want)
60539-		return
60540-	}
60541-
60542-	args := []reflect.Value{reflect.ValueOf(mark)}
60543-	for i, in := range mark.note.Args {
60544-		// Special handling for the blank identifier: treat it as the zero
60545-		// value.
60546-		if ident, ok := in.(expect.Identifier); ok && ident == "_" {
60547-			zero := reflect.Zero(fn.paramTypes[i])
60548-			args = append(args, zero)
60549-			continue
60550-		}
60551-		out, err := fn.converters[i](mark, in)
60552-		if err != nil {
60553-			mark.errorf("converting argument #%d of %s (%v): %v", i, mark.note.Name, in, err)
60554-			return
60555-		}
60556-		args = append(args, reflect.ValueOf(out))
60557-	}
60558-
60559-	fn.fn.Call(args)
60560-}
60561-
60562-// Supported marker functions.
60563-//
60564-// Each marker function must accept a marker as its first argument, with
60565-// subsequent arguments converted from the marker arguments.
60566-//
60567-// Marker funcs should not mutate the test environment (e.g. via opening files
60568-// or applying edits in the editor).
60569-var markerFuncs = map[string]markerFunc{
60570-	"def":          makeMarkerFunc(defMarker),
60571-	"diag":         makeMarkerFunc(diagMarker),
60572-	"hover":        makeMarkerFunc(hoverMarker),
60573-	"loc":          makeMarkerFunc(locMarker),
60574-	"rename":       makeMarkerFunc(renameMarker),
60575-	"renameerr":    makeMarkerFunc(renameErrMarker),
60576-	"suggestedfix": makeMarkerFunc(suggestedfixMarker),
60577-}
60578-
60579-// markerTest holds all the test data extracted from a test txtar archive.
60580-//
60581-// See the documentation for RunMarkerTests for more information on the archive
60582-// format.
60583-type markerTest struct {
60584-	name     string                 // relative path to the txtar file in the testdata dir
60585-	fset     *token.FileSet         // fileset used for parsing notes
60586-	content  []byte                 // raw test content
60587-	archive  *txtar.Archive         // original test archive
60588-	settings map[string]interface{} // gopls settings
60589-	env      map[string]string      // editor environment
60590-	files    map[string][]byte      // data files from the archive (excluding special files)
60591-	notes    []*expect.Note         // extracted notes from data files
60592-	golden   map[string]*Golden     // extracted golden content, by identifier name
60593-
60594-	// flags holds flags extracted from the special "flags" archive file.
60595-	flags []string
60596-	// Parsed flags values.
60597-	minGoVersion string
60598-}
60599-
60600-// flagSet returns the flagset used for parsing the special "flags" file in the
60601-// test archive.
60602-func (t *markerTest) flagSet() *flag.FlagSet {
60603-	flags := flag.NewFlagSet(t.name, flag.ContinueOnError)
60604-	flags.StringVar(&t.minGoVersion, "min_go", "", "if set, the minimum go1.X version required for this test")
60605-	return flags
60606-}
60607-
60608-func (t *markerTest) getGolden(id string) *Golden {
60609-	golden, ok := t.golden[id]
60610-	// If there was no golden content for this identifier, we must create one
60611-	// to handle the case where -update is set: we need a place to store
60612-	// the updated content.
60613-	if !ok {
60614-		golden = &Golden{id: id}
60615-
60616-		// TODO(adonovan): the separation of markerTest (the
60617-		// static aspects) from markerTestRun (the dynamic
60618-		// ones) is evidently bogus because here we modify
60619-		// markerTest during execution. Let's merge the two.
60620-		t.golden[id] = golden
60621-	}
60622-	return golden
60623-}
60624-
60625-// Golden holds extracted golden content for a single @<name> prefix.
60626-//
60627-// When -update is set, golden captures the updated golden contents for later
60628-// writing.
60629-type Golden struct {
60630-	id      string
60631-	data    map[string][]byte // key "" => @id itself
60632-	updated map[string][]byte
60633-}
60634-
60635-// Get returns golden content for the given name, which corresponds to the
60636-// relative path following the golden prefix @<name>/. For example, to access
60637-// the content of @foo/path/to/result.json from the Golden associated with
60638-// @foo, name should be "path/to/result.json".
60639-//
60640-// If -update is set, the given update function will be called to get the
60641-// updated golden content that should be written back to testdata.
60642-//
60643-// Marker functions must use this method instead of accessing data entries
60644-// directly otherwise the -update operation will delete those entries.
60645-//
60646-// TODO(rfindley): rethink the logic here. We may want to separate Get and Set,
60647-// and not delete golden content that isn't set.
60648-func (g *Golden) Get(t testing.TB, name string, updated []byte) ([]byte, bool) {
60649-	if existing, ok := g.updated[name]; ok {
60650-		// Multiple tests may reference the same golden data, but if they do they
60651-		// must agree about its expected content.
60652-		if diff := compare.NamedText("existing", "updated", string(existing), string(updated)); diff != "" {
60653-			t.Errorf("conflicting updates for golden data %s/%s:\n%s", g.id, name, diff)
60654-		}
60655-	}
60656-	if g.updated == nil {
60657-		g.updated = make(map[string][]byte)
60658-	}
60659-	g.updated[name] = updated
60660-	if *update {
60661-		return updated, true
60662-	}
60663-
60664-	res, ok := g.data[name]
60665-	return res, ok
60666-}
60667-
60668-// loadMarkerTests walks the given dir looking for .txt files, which it
60669-// interprets as a txtar archive.
60670-//
60671-// See the documentation for RunMarkerTests for more details on the test data
60672-// archive.
60673-//
60674-// TODO(rfindley): this test could sanity check the results. For example, it is
60675-// too easy to write "// @" instead of "//@", which we will happy skip silently.
60676-func loadMarkerTests(dir string) ([]*markerTest, error) {
60677-	var tests []*markerTest
60678-	err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
60679-		if strings.HasSuffix(path, ".txt") {
60680-			content, err := os.ReadFile(path)
60681-			if err != nil {
60682-				return err
60683-			}
60684-			name := strings.TrimPrefix(path, dir+string(filepath.Separator))
60685-			test, err := loadMarkerTest(name, content)
60686-			if err != nil {
60687-				return fmt.Errorf("%s: %v", path, err)
60688-			}
60689-			tests = append(tests, test)
60690-		}
60691-		return nil
60692-	})
60693-	return tests, err
60694-}
60695-
60696-func loadMarkerTest(name string, content []byte) (*markerTest, error) {
60697-	archive := txtar.Parse(content)
60698-	test := &markerTest{
60699-		name:    name,
60700-		fset:    token.NewFileSet(),
60701-		content: content,
60702-		archive: archive,
60703-		files:   make(map[string][]byte),
60704-		golden:  make(map[string]*Golden),
60705-	}
60706-	for _, file := range archive.Files {
60707-		switch {
60708-		case file.Name == "flags":
60709-			test.flags = strings.Fields(string(file.Data))
60710-			if err := test.flagSet().Parse(test.flags); err != nil {
60711-				return nil, fmt.Errorf("parsing flags: %v", err)
60712-			}
60713-
60714-		case file.Name == "settings.json":
60715-			if err := json.Unmarshal(file.Data, &test.settings); err != nil {
60716-				return nil, err
60717-			}
60718-
60719-		case file.Name == "env":
60720-			test.env = make(map[string]string)
60721-			fields := strings.Fields(string(file.Data))
60722-			for _, field := range fields {
60723-				// TODO: use strings.Cut once we are on 1.18+.
60724-				key, value, ok := cut(field, "=")
60725-				if !ok {
60726-					return nil, fmt.Errorf("env vars must be formatted as var=value, got %q", field)
60727-				}
60728-				test.env[key] = value
60729-			}
60730-
60731-		case strings.HasPrefix(file.Name, "@"): // golden content
60732-			id, name, _ := cut(file.Name[len("@"):], "/")
60733-			// Note that a file.Name of just "@id" gives (id, name) = ("id", "").
60734-			if _, ok := test.golden[id]; !ok {
60735-				test.golden[id] = &Golden{
60736-					id:   id,
60737-					data: make(map[string][]byte),
60738-				}
60739-			}
60740-			test.golden[id].data[name] = file.Data
60741-
60742-		default: // ordinary file content
60743-			notes, err := expect.Parse(test.fset, file.Name, file.Data)
60744-			if err != nil {
60745-				return nil, fmt.Errorf("parsing notes in %q: %v", file.Name, err)
60746-			}
60747-			test.notes = append(test.notes, notes...)
60748-			test.files[file.Name] = file.Data
60749-		}
60750-	}
60751-
60752-	return test, nil
60753-}
60754-
60755-// cut is a copy of strings.Cut.
60756-//
60757-// TODO: once we only support Go 1.18+, just use strings.Cut.
60758-func cut(s, sep string) (before, after string, found bool) {
60759-	if i := strings.Index(s, sep); i >= 0 {
60760-		return s[:i], s[i+len(sep):], true
60761-	}
60762-	return s, "", false
60763-}
60764-
60765-// formatTest formats the test as a txtar archive.
60766-func formatTest(test *markerTest) ([]byte, error) {
60767-	arch := &txtar.Archive{
60768-		Comment: test.archive.Comment,
60769-	}
60770-
60771-	updatedGolden := make(map[string][]byte)
60772-	for id, g := range test.golden {
60773-		for name, data := range g.updated {
60774-			filename := "@" + path.Join(id, name) // name may be ""
60775-			updatedGolden[filename] = data
60776-		}
60777-	}
60778-
60779-	// Preserve the original ordering of archive files.
60780-	for _, file := range test.archive.Files {
60781-		switch file.Name {
60782-		// Preserve configuration files exactly as they were. They must have parsed
60783-		// if we got this far.
60784-		case "flags", "settings.json", "env":
60785-			arch.Files = append(arch.Files, file)
60786-		default:
60787-			if _, ok := test.files[file.Name]; ok { // ordinary file
60788-				arch.Files = append(arch.Files, file)
60789-			} else if data, ok := updatedGolden[file.Name]; ok { // golden file
60790-				arch.Files = append(arch.Files, txtar.File{Name: file.Name, Data: data})
60791-				delete(updatedGolden, file.Name)
60792-			}
60793-		}
60794-	}
60795-
60796-	// ...followed by any new golden files.
60797-	var newGoldenFiles []txtar.File
60798-	for filename, data := range updatedGolden {
60799-		newGoldenFiles = append(newGoldenFiles, txtar.File{Name: filename, Data: data})
60800-	}
60801-	// Sort new golden files lexically.
60802-	sort.Slice(newGoldenFiles, func(i, j int) bool {
60803-		return newGoldenFiles[i].Name < newGoldenFiles[j].Name
60804-	})
60805-	arch.Files = append(arch.Files, newGoldenFiles...)
60806-
60807-	return txtar.Format(arch), nil
60808-}
60809-
60810-// newEnv creates a new environment for a marker test.
60811-//
60812-// TODO(rfindley): simplify and refactor the construction of testing
60813-// environments across regtests, marker tests, and benchmarks.
60814-func newEnv(t *testing.T, cache *cache.Cache, files map[string][]byte, config fake.EditorConfig) *Env {
60815-	sandbox, err := fake.NewSandbox(&fake.SandboxConfig{
60816-		RootDir: t.TempDir(),
60817-		GOPROXY: "https://proxy.golang.org",
60818-		Files:   files,
60819-	})
60820-	if err != nil {
60821-		t.Fatal(err)
60822-	}
60823-
60824-	// Put a debug instance in the context to prevent logging to stderr.
60825-	// See associated TODO in runner.go: we should revisit this pattern.
60826-	ctx := context.Background()
60827-	ctx = debug.WithInstance(ctx, "", "off")
60828-
60829-	awaiter := NewAwaiter(sandbox.Workdir)
60830-	ss := lsprpc.NewStreamServer(cache, false, hooks.Options)
60831-	server := servertest.NewPipeServer(ss, jsonrpc2.NewRawStream)
60832-	const skipApplyEdits = true // capture edits but don't apply them
60833-	editor, err := fake.NewEditor(sandbox, config).Connect(ctx, server, awaiter.Hooks(), skipApplyEdits)
60834-	if err != nil {
60835-		sandbox.Close() // ignore error
60836-		t.Fatal(err)
60837-	}
60838-	if err := awaiter.Await(ctx, InitialWorkspaceLoad); err != nil {
60839-		sandbox.Close() // ignore error
60840-		t.Fatal(err)
60841-	}
60842-	return &Env{
60843-		T:       t,
60844-		Ctx:     ctx,
60845-		Editor:  editor,
60846-		Sandbox: sandbox,
60847-		Awaiter: awaiter,
60848-	}
60849-}
60850-
60851-// A markerFunc is a reflectively callable @mark implementation function.
60852-type markerFunc struct {
60853-	fn         reflect.Value  // the func to invoke
60854-	paramTypes []reflect.Type // parameter types, for zero values
60855-	converters []converter    // to convert non-blank arguments
60856-}
60857-
60858-// A markerTestRun holds the state of one run of a marker test archive.
60859-type markerTestRun struct {
60860-	test *markerTest
60861-	env  *Env
60862-
60863-	// Collected information.
60864-	// Each @diag/@suggestedfix marker eliminates an entry from diags.
60865-	locations map[expect.Identifier]protocol.Location
60866-	diags     map[protocol.Location][]protocol.Diagnostic
60867-}
60868-
60869-// fmtLoc formats the given pos in the context of the test, using
60870-// archive-relative paths for files and including the line number in the full
60871-// archive file.
60872-func (run *markerTestRun) fmtPos(pos token.Pos) string {
60873-	file := run.test.fset.File(pos)
60874-	if file == nil {
60875-		run.env.T.Errorf("position %d not in test fileset", pos)
60876-		return "<invalid location>"
60877-	}
60878-	m, err := run.env.Editor.Mapper(file.Name())
60879-	if err != nil {
60880-		run.env.T.Errorf("%s", err)
60881-		return "<invalid location>"
60882-	}
60883-	loc, err := m.PosLocation(file, pos, pos)
60884-	if err != nil {
60885-		run.env.T.Errorf("Mapper(%s).PosLocation failed: %v", file.Name(), err)
60886-	}
60887-	return run.fmtLoc(loc)
60888-}
60889-
60890-// fmtLoc formats the given location in the context of the test, using
60891-// archive-relative paths for files and including the line number in the full
60892-// archive file.
60893-func (run *markerTestRun) fmtLoc(loc protocol.Location) string {
60894-	if loc == (protocol.Location{}) {
60895-		return "<missing location>"
60896-	}
60897-	lines := bytes.Count(run.test.archive.Comment, []byte("\n"))
60898-	var name string
60899-	for _, f := range run.test.archive.Files {
60900-		lines++ // -- separator --
60901-		uri := run.env.Sandbox.Workdir.URI(f.Name)
60902-		if uri == loc.URI {
60903-			name = f.Name
60904-			break
60905-		}
60906-		lines += bytes.Count(f.Data, []byte("\n"))
60907-	}
60908-	if name == "" {
60909-		run.env.T.Errorf("unable to find %s in test archive", loc)
60910-		return "<invalid location>"
60911-	}
60912-	m, err := run.env.Editor.Mapper(name)
60913-	if err != nil {
60914-		run.env.T.Errorf("internal error: %v", err)
60915-		return "<invalid location>"
60916-	}
60917-	s, err := m.LocationSpan(loc)
60918-	if err != nil {
60919-		run.env.T.Errorf("error formatting location %s: %v", loc, err)
60920-		return "<invalid location>"
60921-	}
60922-
60923-	innerSpan := fmt.Sprintf("%d:%d", s.Start().Line(), s.Start().Column())       // relative to the embedded file
60924-	outerSpan := fmt.Sprintf("%d:%d", lines+s.Start().Line(), s.Start().Column()) // relative to the archive file
60925-	if s.Start() != s.End() {
60926-		if s.End().Line() == s.Start().Line() {
60927-			innerSpan += fmt.Sprintf("-%d", s.End().Column())
60928-			outerSpan += fmt.Sprintf("-%d", s.End().Column())
60929-		} else {
60930-			innerSpan += fmt.Sprintf("-%d:%d", s.End().Line(), s.End().Column())
60931-			innerSpan += fmt.Sprintf("-%d:%d", lines+s.End().Line(), s.End().Column())
60932-		}
60933-	}
60934-
60935-	return fmt.Sprintf("%s:%s (%s:%s)", name, innerSpan, run.test.name, outerSpan)
60936-}
60937-
60938-// makeMarkerFunc uses reflection to create a markerFunc for the given func value.
60939-func makeMarkerFunc(fn interface{}) markerFunc {
60940-	mi := markerFunc{
60941-		fn: reflect.ValueOf(fn),
60942-	}
60943-	mtyp := mi.fn.Type()
60944-	if mtyp.NumIn() == 0 || mtyp.In(0) != markerType {
60945-		panic(fmt.Sprintf("marker function %#v must accept marker as its first argument", mi.fn))
60946-	}
60947-	if mtyp.NumOut() != 0 {
60948-		panic(fmt.Sprintf("marker function %#v must not have results", mi.fn))
60949-	}
60950-	for a := 1; a < mtyp.NumIn(); a++ {
60951-		in := mtyp.In(a)
60952-		mi.paramTypes = append(mi.paramTypes, in)
60953-		c := makeConverter(in)
60954-		mi.converters = append(mi.converters, c)
60955-	}
60956-	return mi
60957-}
60958-
60959-// ---- converters ----
60960-
60961-// converter is the signature of argument converters.
60962-// A converter should return an error rather than calling marker.errorf().
60963-type converter func(marker, interface{}) (interface{}, error)
60964-
60965-// Types with special conversions.
60966-var (
60967-	goldenType    = reflect.TypeOf(&Golden{})
60968-	locationType  = reflect.TypeOf(protocol.Location{})
60969-	markerType    = reflect.TypeOf(marker{})
60970-	regexpType    = reflect.TypeOf(&regexp.Regexp{})
60971-	wantErrorType = reflect.TypeOf(wantError{})
60972-)
60973-
60974-func makeConverter(paramType reflect.Type) converter {
60975-	switch paramType {
60976-	case goldenType:
60977-		return goldenConverter
60978-	case locationType:
60979-		return locationConverter
60980-	case wantErrorType:
60981-		return wantErrorConverter
60982-	default:
60983-		return func(_ marker, arg interface{}) (interface{}, error) {
60984-			if argType := reflect.TypeOf(arg); argType != paramType {
60985-				return nil, fmt.Errorf("cannot convert type %s to %s", argType, paramType)
60986-			}
60987-			return arg, nil
60988-		}
60989-	}
60990-}
60991-
60992-// locationConverter converts a string argument into the protocol location
60993-// corresponding to the first position of the string in the line preceding the
60994-// note.
60995-func locationConverter(mark marker, arg interface{}) (interface{}, error) {
60996-	switch arg := arg.(type) {
60997-	case string:
60998-		startOff, preceding, m, err := linePreceding(mark.run, mark.note.Pos)
60999-		if err != nil {
61000-			return protocol.Location{}, err
61001-		}
61002-		idx := bytes.Index(preceding, []byte(arg))
61003-		if idx < 0 {
61004-			return nil, fmt.Errorf("substring %q not found in %q", arg, preceding)
61005-		}
61006-		off := startOff + idx
61007-		return m.OffsetLocation(off, off+len(arg))
61008-	case *regexp.Regexp:
61009-		return findRegexpInLine(mark.run, mark.note.Pos, arg)
61010-	case expect.Identifier:
61011-		loc, ok := mark.run.locations[arg]
61012-		if !ok {
61013-			return nil, fmt.Errorf("no location named %q", arg)
61014-		}
61015-		return loc, nil
61016-	default:
61017-		return nil, fmt.Errorf("cannot convert argument type %T to location (must be a string to match the preceding line)", arg)
61018-	}
61019-}
61020-
61021-// findRegexpInLine searches the partial line preceding pos for a match for the
61022-// regular expression re, returning a location spanning the first match. If re
61023-// contains exactly one subgroup, the position of this subgroup match is
61024-// returned rather than the position of the full match.
61025-func findRegexpInLine(run *markerTestRun, pos token.Pos, re *regexp.Regexp) (protocol.Location, error) {
61026-	startOff, preceding, m, err := linePreceding(run, pos)
61027-	if err != nil {
61028-		return protocol.Location{}, err
61029-	}
61030-
61031-	matches := re.FindSubmatchIndex(preceding)
61032-	if len(matches) == 0 {
61033-		return protocol.Location{}, fmt.Errorf("no match for regexp %q found in %q", re, string(preceding))
61034-	}
61035-	var start, end int
61036-	switch len(matches) {
61037-	case 2:
61038-		// no subgroups: return the range of the regexp expression
61039-		start, end = matches[0], matches[1]
61040-	case 4:
61041-		// one subgroup: return its range
61042-		start, end = matches[2], matches[3]
61043-	default:
61044-		return protocol.Location{}, fmt.Errorf("invalid location regexp %q: expect either 0 or 1 subgroups, got %d", re, len(matches)/2-1)
61045-	}
61046-
61047-	return m.OffsetLocation(start+startOff, end+startOff)
61048-}
61049-
61050-func linePreceding(run *markerTestRun, pos token.Pos) (int, []byte, *protocol.Mapper, error) {
61051-	file := run.test.fset.File(pos)
61052-	posn := safetoken.Position(file, pos)
61053-	lineStart := file.LineStart(posn.Line)
61054-	startOff, endOff, err := safetoken.Offsets(file, lineStart, pos)
61055-	if err != nil {
61056-		return 0, nil, nil, err
61057-	}
61058-	m, err := run.env.Editor.Mapper(file.Name())
61059-	if err != nil {
61060-		return 0, nil, nil, err
61061-	}
61062-	return startOff, m.Content[startOff:endOff], m, nil
61063-}
61064-
61065-// wantErrorConverter converts a string, regexp, or identifier
61066-// argument into a wantError. The string is a substring of the
61067-// expected error, the regexp is a pattern than matches the expected
61068-// error, and the identifier is a golden file containing the expected
61069-// error.
61070-func wantErrorConverter(mark marker, arg interface{}) (interface{}, error) {
61071-	switch arg := arg.(type) {
61072-	case string:
61073-		return wantError{substr: arg}, nil
61074-	case *regexp.Regexp:
61075-		return wantError{pattern: arg}, nil
61076-	case expect.Identifier:
61077-		golden := mark.run.test.getGolden(string(arg))
61078-		return wantError{golden: golden}, nil
61079-	default:
61080-		return nil, fmt.Errorf("cannot convert %T to wantError (want: string, regexp, or identifier)", arg)
61081-	}
61082-}
61083-
61084-// A wantError represents an expectation of a specific error message.
61085-//
61086-// It may be indicated in one of three ways, in 'expect' notation:
61087-// - an identifier 'foo', to compare with the contents of the golden section @foo;
61088-// - a pattern expression re"ab.*c", to match against a regular expression;
61089-// - a string literal "abc", to check for a substring.
61090-type wantError struct {
61091-	golden  *Golden
61092-	pattern *regexp.Regexp
61093-	substr  string
61094-}
61095-
61096-func (we wantError) String() string {
61097-	if we.golden != nil {
61098-		return fmt.Sprintf("error from @%s entry", we.golden.id)
61099-	} else if we.pattern != nil {
61100-		return fmt.Sprintf("error matching %#q", we.pattern)
61101-	} else {
61102-		return fmt.Sprintf("error with substring %q", we.substr)
61103-	}
61104-}
61105-
61106-// check asserts that 'err' matches the wantError's expectations.
61107-func (we wantError) check(mark marker, err error) {
61108-	if err == nil {
61109-		mark.errorf("@%s succeeded unexpectedly, want %v", mark.note.Name, we)
61110-		return
61111-	}
61112-	got := err.Error()
61113-
61114-	if we.golden != nil {
61115-		// Error message must match @id golden file.
61116-		wantBytes, ok := we.golden.Get(mark.run.env.T, "", []byte(got))
61117-		if !ok {
61118-			mark.errorf("@%s: missing @%s entry", mark.note.Name, we.golden.id)
61119-			return
61120-		}
61121-		want := strings.TrimSpace(string(wantBytes))
61122-		if got != want {
61123-			// (ignore leading/trailing space)
61124-			mark.errorf("@%s failed with wrong error: got:\n%s\nwant:\n%s\ndiff:\n%s",
61125-				mark.note.Name, got, want, compare.Text(want, got))
61126-		}
61127-
61128-	} else if we.pattern != nil {
61129-		// Error message must match regular expression pattern.
61130-		if !we.pattern.MatchString(got) {
61131-			mark.errorf("got error %q, does not match pattern %#q", got, we.pattern)
61132-		}
61133-
61134-	} else if !strings.Contains(got, we.substr) {
61135-		// Error message must contain expected substring.
61136-		mark.errorf("got error %q, want substring %q", got, we.substr)
61137-	}
61138-}
61139-
61140-// goldenConverter converts an identifier into the Golden directory of content
61141-// prefixed by @<ident> in the test archive file.
61142-func goldenConverter(mark marker, arg interface{}) (interface{}, error) {
61143-	switch arg := arg.(type) {
61144-	case expect.Identifier:
61145-		return mark.run.test.getGolden(string(arg)), nil
61146-	default:
61147-		return nil, fmt.Errorf("invalid input type %T: golden key must be an identifier", arg)
61148-	}
61149-}
61150-
61151-// checkChangedFiles compares the files changed by an operation with their expected (golden) state.
61152-func checkChangedFiles(mark marker, changed map[string][]byte, golden *Golden) {
61153-	// Check changed files match expectations.
61154-	for filename, got := range changed {
61155-		if want, ok := golden.Get(mark.run.env.T, filename, got); !ok {
61156-			mark.errorf("%s: unexpected change to file %s; got:\n%s",
61157-				mark.note.Name, filename, got)
61158-
61159-		} else if string(got) != string(want) {
61160-			mark.errorf("%s: wrong file content for %s: got:\n%s\nwant:\n%s\ndiff:\n%s",
61161-				mark.note.Name, filename, got, want,
61162-				compare.Bytes(want, got))
61163-		}
61164-	}
61165-
61166-	// Report unmet expectations.
61167-	for filename := range golden.data {
61168-		if _, ok := changed[filename]; !ok {
61169-			want, _ := golden.Get(mark.run.env.T, filename, nil)
61170-			mark.errorf("%s: missing change to file %s; want:\n%s",
61171-				mark.note.Name, filename, want)
61172-		}
61173-	}
61174-}
61175-
61176-// ---- marker functions ----
61177-
61178-// defMarker implements the @godef marker, running textDocument/definition at
61179-// the given src location and asserting that there is exactly one resulting
61180-// location, matching dst.
61181-//
61182-// TODO(rfindley): support a variadic destination set.
61183-func defMarker(mark marker, src, dst protocol.Location) {
61184-	got := mark.run.env.GoToDefinition(src)
61185-	if got != dst {
61186-		mark.errorf("definition location does not match:\n\tgot: %s\n\twant %s",
61187-			mark.run.fmtLoc(got), mark.run.fmtLoc(dst))
61188-	}
61189-}
61190-
61191-// hoverMarker implements the @hover marker, running textDocument/hover at the
61192-// given src location and asserting that the resulting hover is over the dst
61193-// location (typically a span surrounding src), and that the markdown content
61194-// matches the golden content.
61195-func hoverMarker(mark marker, src, dst protocol.Location, golden *Golden) {
61196-	content, gotDst := mark.run.env.Hover(src)
61197-	if gotDst != dst {
61198-		mark.errorf("hover location does not match:\n\tgot: %s\n\twant %s)", mark.run.fmtLoc(gotDst), mark.run.fmtLoc(dst))
61199-	}
61200-	gotMD := ""
61201-	if content != nil {
61202-		gotMD = content.Value
61203-	}
61204-	wantMD := ""
61205-	if golden != nil {
61206-		wantBytes, _ := golden.Get(mark.run.env.T, "hover.md", []byte(gotMD))
61207-		wantMD = string(wantBytes)
61208-	}
61209-	// Normalize newline termination: archive files can't express non-newline
61210-	// terminated files.
61211-	if strings.HasSuffix(wantMD, "\n") && !strings.HasSuffix(gotMD, "\n") {
61212-		gotMD += "\n"
61213-	}
61214-	if diff := tests.DiffMarkdown(wantMD, gotMD); diff != "" {
61215-		mark.errorf("hover markdown mismatch (-want +got):\n%s", diff)
61216-	}
61217-}
61218-
61219-// locMarker implements the @loc marker. It is executed before other
61220-// markers, so that locations are available.
61221-func locMarker(mark marker, name expect.Identifier, loc protocol.Location) {
61222-	mark.run.locations[name] = loc
61223-}
61224-
61225-// diagMarker implements the @diag marker. It eliminates diagnostics from
61226-// the observed set in mark.test.
61227-func diagMarker(mark marker, loc protocol.Location, re *regexp.Regexp) {
61228-	if _, err := removeDiagnostic(mark, loc, re); err != nil {
61229-		mark.errorf("%v", err)
61230-	}
61231-}
61232-
61233-func removeDiagnostic(mark marker, loc protocol.Location, re *regexp.Regexp) (protocol.Diagnostic, error) {
61234-	diags := mark.run.diags[loc]
61235-	for i, diag := range diags {
61236-		if re.MatchString(diag.Message) {
61237-			mark.run.diags[loc] = append(diags[:i], diags[i+1:]...)
61238-			return diag, nil
61239-		}
61240-	}
61241-	return protocol.Diagnostic{}, fmt.Errorf("no diagnostic matches %q", re)
61242-}
61243-
61244-// renameMarker implements the @rename(location, new, golden) marker.
61245-func renameMarker(mark marker, loc protocol.Location, newName expect.Identifier, golden *Golden) {
61246-	changed, err := rename(mark.run.env, loc, string(newName))
61247-	if err != nil {
61248-		mark.errorf("rename failed: %v. (Use @renameerr for expected errors.)", err)
61249-		return
61250-	}
61251-	checkChangedFiles(mark, changed, golden)
61252-}
61253-
61254-// renameErrMarker implements the @renamererr(location, new, error) marker.
61255-func renameErrMarker(mark marker, loc protocol.Location, newName expect.Identifier, wantErr wantError) {
61256-	_, err := rename(mark.run.env, loc, string(newName))
61257-	wantErr.check(mark, err)
61258-}
61259-
61260-// rename returns the new contents of the files that would be modified
61261-// by renaming the identifier at loc to newName.
61262-func rename(env *Env, loc protocol.Location, newName string) (map[string][]byte, error) {
61263-	// We call Server.Rename directly, instead of
61264-	//   env.Editor.Rename(env.Ctx, loc, newName)
61265-	// to isolate Rename from PrepareRename, and because we don't
61266-	// want to modify the file system in a scenario with multiple
61267-	// @rename markers.
61268-
61269-	editMap, err := env.Editor.Server.Rename(env.Ctx, &protocol.RenameParams{
61270-		TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI},
61271-		Position:     loc.Range.Start,
61272-		NewName:      string(newName),
61273-	})
61274-	if err != nil {
61275-		return nil, err
61276-	}
61277-
61278-	return applyDocumentChanges(env, editMap.DocumentChanges)
61279-}
61280-
61281-// applyDocumentChanges returns the effect of applying the document
61282-// changes to the contents of the Editor buffers. The actual editor
61283-// buffers are unchanged.
61284-func applyDocumentChanges(env *Env, changes []protocol.DocumentChanges) (map[string][]byte, error) {
61285-	result := make(map[string][]byte)
61286-	for _, change := range changes {
61287-		if change.RenameFile != nil {
61288-			// rename
61289-			oldFile := env.Sandbox.Workdir.URIToPath(change.RenameFile.OldURI)
61290-			newFile := env.Sandbox.Workdir.URIToPath(change.RenameFile.NewURI)
61291-			mapper, err := env.Editor.Mapper(oldFile)
61292-			if err != nil {
61293-				return nil, err
61294-			}
61295-			result[newFile] = mapper.Content
61296-
61297-		} else {
61298-			// edit
61299-			filename := env.Sandbox.Workdir.URIToPath(change.TextDocumentEdit.TextDocument.URI)
61300-			mapper, err := env.Editor.Mapper(filename)
61301-			if err != nil {
61302-				return nil, err
61303-			}
61304-			patched, _, err := source.ApplyProtocolEdits(mapper, change.TextDocumentEdit.Edits)
61305-			if err != nil {
61306-				return nil, err
61307-			}
61308-			result[filename] = patched
61309-		}
61310-	}
61311-
61312-	return result, nil
61313-}
61314-
61315-// suggestedfixMarker implements the @suggestedfix(location, regexp,
61316-// kind, golden) marker. It acts like @diag(location, regexp), to set
61317-// the expectation of a diagnostic, but then it applies the first code
61318-// action of the specified kind suggested by the matched diagnostic.
61319-func suggestedfixMarker(mark marker, loc protocol.Location, re *regexp.Regexp, actionKind string, golden *Golden) {
61320-	// Find and remove the matching diagnostic.
61321-	diag, err := removeDiagnostic(mark, loc, re)
61322-	if err != nil {
61323-		mark.errorf("%v", err)
61324-		return
61325-	}
61326-
61327-	// Apply the fix it suggests.
61328-	changed, err := suggestedfix(mark.run.env, loc, diag, actionKind)
61329-	if err != nil {
61330-		mark.errorf("suggestedfix failed: %v. (Use @suggestedfixerr for expected errors.)", err)
61331-		return
61332-	}
61333-
61334-	// Check the file state.
61335-	checkChangedFiles(mark, changed, golden)
61336-}
61337-
61338-func suggestedfix(env *Env, loc protocol.Location, diag protocol.Diagnostic, actionKind string) (map[string][]byte, error) {
61339-
61340-	// Request all code actions that apply to the diagnostic.
61341-	// (The protocol supports filtering using Context.Only={actionKind}
61342-	// but we can give a better error if we don't filter.)
61343-	actions, err := env.Editor.Server.CodeAction(env.Ctx, &protocol.CodeActionParams{
61344-		TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI},
61345-		Range:        diag.Range,
61346-		Context: protocol.CodeActionContext{
61347-			Only:        nil, // => all kinds
61348-			Diagnostics: []protocol.Diagnostic{diag},
61349-		},
61350-	})
61351-	if err != nil {
61352-		return nil, err
61353-	}
61354-
61355-	// Find the sole candidates CodeAction of the specified kind (e.g. refactor.rewrite).
61356-	var candidates []protocol.CodeAction
61357-	for _, act := range actions {
61358-		if act.Kind == protocol.CodeActionKind(actionKind) {
61359-			candidates = append(candidates, act)
61360-		}
61361-	}
61362-	if len(candidates) != 1 {
61363-		for _, act := range actions {
61364-			env.T.Logf("found CodeAction Kind=%s Title=%q", act.Kind, act.Title)
61365-		}
61366-		return nil, fmt.Errorf("found %d CodeActions of kind %s for this diagnostic, want 1", len(candidates), actionKind)
61367-	}
61368-	action := candidates[0]
61369-
61370-	// An action may specify an edit and/or a command, to be
61371-	// applied in that order. But since applyDocumentChanges(env,
61372-	// action.Edit.DocumentChanges) doesn't compose, for now we
61373-	// assert that all commands used in the @suggestedfix tests
61374-	// return only a command.
61375-	if action.Edit.DocumentChanges != nil {
61376-		env.T.Errorf("internal error: discarding unexpected CodeAction{Kind=%s, Title=%q}.Edit.DocumentChanges", action.Kind, action.Title)
61377-	}
61378-	if action.Command == nil {
61379-		return nil, fmt.Errorf("missing CodeAction{Kind=%s, Title=%q}.Command", action.Kind, action.Title)
61380-	}
61381-
61382-	// This is a typical CodeAction command:
61383-	//
61384-	//   Title:     "Implement error"
61385-	//   Command:   gopls.apply_fix
61386-	//   Arguments: [{"Fix":"stub_methods","URI":".../a.go","Range":...}}]
61387-	//
61388-	// The client makes an ExecuteCommand RPC to the server,
61389-	// which dispatches it to the ApplyFix handler.
61390-	// ApplyFix dispatches to the "stub_methods" suggestedfix hook (the meat).
61391-	// The server then makes an ApplyEdit RPC to the client,
61392-	// whose Awaiter hook gathers the edits instead of applying them.
61393-
61394-	_ = env.Awaiter.takeDocumentChanges() // reset (assuming Env is confined to this thread)
61395-
61396-	if _, err := env.Editor.Server.ExecuteCommand(env.Ctx, &protocol.ExecuteCommandParams{
61397-		Command:   action.Command.Command,
61398-		Arguments: action.Command.Arguments,
61399-	}); err != nil {
61400-		env.T.Fatalf("error converting command %q to edits: %v", action.Command.Command, err)
61401-	}
61402-
61403-	return applyDocumentChanges(env, env.Awaiter.takeDocumentChanges())
61404-}
61405-
61406-// TODO(adonovan): suggestedfixerr
61407diff -urN a/gopls/internal/lsp/regtest/options.go b/gopls/internal/lsp/regtest/options.go
61408--- a/gopls/internal/lsp/regtest/options.go	2000-01-01 00:00:00.000000000 -0000
61409+++ b/gopls/internal/lsp/regtest/options.go	1970-01-01 00:00:00.000000000 +0000
61410@@ -1,105 +0,0 @@
61411-// Copyright 2022 The Go Authors. All rights reserved.
61412-// Use of this source code is governed by a BSD-style
61413-// license that can be found in the LICENSE file.
61414-
61415-package regtest
61416-
61417-import "golang.org/x/tools/gopls/internal/lsp/fake"
61418-
61419-type runConfig struct {
61420-	editor    fake.EditorConfig
61421-	sandbox   fake.SandboxConfig
61422-	modes     Mode
61423-	skipHooks bool
61424-}
61425-
61426-// A RunOption augments the behavior of the test runner.
61427-type RunOption interface {
61428-	set(*runConfig)
61429-}
61430-
61431-type optionSetter func(*runConfig)
61432-
61433-func (f optionSetter) set(opts *runConfig) {
61434-	f(opts)
61435-}
61436-
61437-// ProxyFiles configures a file proxy using the given txtar-encoded string.
61438-func ProxyFiles(txt string) RunOption {
61439-	return optionSetter(func(opts *runConfig) {
61440-		opts.sandbox.ProxyFiles = fake.UnpackTxt(txt)
61441-	})
61442-}
61443-
61444-// Modes configures the execution modes that the test should run in.
61445-//
61446-// By default, modes are configured by the test runner. If this option is set,
61447-// it overrides the set of default modes and the test runs in exactly these
61448-// modes.
61449-func Modes(modes Mode) RunOption {
61450-	return optionSetter(func(opts *runConfig) {
61451-		if opts.modes != 0 {
61452-			panic("modes set more than once")
61453-		}
61454-		opts.modes = modes
61455-	})
61456-}
61457-
61458-// WindowsLineEndings configures the editor to use windows line endings.
61459-func WindowsLineEndings() RunOption {
61460-	return optionSetter(func(opts *runConfig) {
61461-		opts.editor.WindowsLineEndings = true
61462-	})
61463-}
61464-
61465-// Settings is a RunOption that sets user-provided configuration for the LSP
61466-// server.
61467-//
61468-// As a special case, the env setting must not be provided via Settings: use
61469-// EnvVars instead.
61470-type Settings map[string]interface{}
61471-
61472-func (s Settings) set(opts *runConfig) {
61473-	if opts.editor.Settings == nil {
61474-		opts.editor.Settings = make(map[string]interface{})
61475-	}
61476-	for k, v := range s {
61477-		opts.editor.Settings[k] = v
61478-	}
61479-}
61480-
61481-// WorkspaceFolders configures the workdir-relative workspace folders to send
61482-// to the LSP server. By default the editor sends a single workspace folder
61483-// corresponding to the workdir root. To explicitly configure no workspace
61484-// folders, use WorkspaceFolders with no arguments.
61485-func WorkspaceFolders(relFolders ...string) RunOption {
61486-	if len(relFolders) == 0 {
61487-		// Use an empty non-nil slice to signal explicitly no folders.
61488-		relFolders = []string{}
61489-	}
61490-	return optionSetter(func(opts *runConfig) {
61491-		opts.editor.WorkspaceFolders = relFolders
61492-	})
61493-}
61494-
61495-// EnvVars sets environment variables for the LSP session. When applying these
61496-// variables to the session, the special string $SANDBOX_WORKDIR is replaced by
61497-// the absolute path to the sandbox working directory.
61498-type EnvVars map[string]string
61499-
61500-func (e EnvVars) set(opts *runConfig) {
61501-	if opts.editor.Env == nil {
61502-		opts.editor.Env = make(map[string]string)
61503-	}
61504-	for k, v := range e {
61505-		opts.editor.Env[k] = v
61506-	}
61507-}
61508-
61509-// InGOPATH configures the workspace working directory to be GOPATH, rather
61510-// than a separate working directory for use with modules.
61511-func InGOPATH() RunOption {
61512-	return optionSetter(func(opts *runConfig) {
61513-		opts.sandbox.InGoPath = true
61514-	})
61515-}
61516diff -urN a/gopls/internal/lsp/regtest/regtest.go b/gopls/internal/lsp/regtest/regtest.go
61517--- a/gopls/internal/lsp/regtest/regtest.go	2000-01-01 00:00:00.000000000 -0000
61518+++ b/gopls/internal/lsp/regtest/regtest.go	1970-01-01 00:00:00.000000000 +0000
61519@@ -1,153 +0,0 @@
61520-// Copyright 2020 The Go Authors. All rights reserved.
61521-// Use of this source code is governed by a BSD-style
61522-// license that can be found in the LICENSE file.
61523-
61524-package regtest
61525-
61526-import (
61527-	"context"
61528-	"flag"
61529-	"fmt"
61530-	"io/ioutil"
61531-	"os"
61532-	"runtime"
61533-	"testing"
61534-	"time"
61535-
61536-	"golang.org/x/tools/gopls/internal/lsp/cmd"
61537-	"golang.org/x/tools/gopls/internal/lsp/source"
61538-	"golang.org/x/tools/internal/gocommand"
61539-	"golang.org/x/tools/internal/memoize"
61540-	"golang.org/x/tools/internal/testenv"
61541-	"golang.org/x/tools/internal/tool"
61542-)
61543-
61544-var (
61545-	runSubprocessTests       = flag.Bool("enable_gopls_subprocess_tests", false, "run regtests against a gopls subprocess")
61546-	goplsBinaryPath          = flag.String("gopls_test_binary", "", "path to the gopls binary for use as a remote, for use with the -enable_gopls_subprocess_tests flag")
61547-	regtestTimeout           = flag.Duration("regtest_timeout", defaultRegtestTimeout(), "if nonzero, default timeout for each regtest; defaults to GOPLS_REGTEST_TIMEOUT")
61548-	skipCleanup              = flag.Bool("regtest_skip_cleanup", false, "whether to skip cleaning up temp directories")
61549-	printGoroutinesOnFailure = flag.Bool("regtest_print_goroutines", false, "whether to print goroutines info on failure")
61550-	printLogs                = flag.Bool("regtest_print_logs", false, "whether to print LSP logs")
61551-)
61552-
61553-func defaultRegtestTimeout() time.Duration {
61554-	s := os.Getenv("GOPLS_REGTEST_TIMEOUT")
61555-	if s == "" {
61556-		return 0
61557-	}
61558-	d, err := time.ParseDuration(s)
61559-	if err != nil {
61560-		fmt.Fprintf(os.Stderr, "invalid GOPLS_REGTEST_TIMEOUT %q: %v\n", s, err)
61561-		os.Exit(2)
61562-	}
61563-	return d
61564-}
61565-
61566-var runner *Runner
61567-
61568-type regtestRunner interface {
61569-	Run(t *testing.T, files string, f TestFunc)
61570-}
61571-
61572-func Run(t *testing.T, files string, f TestFunc) {
61573-	runner.Run(t, files, f)
61574-}
61575-
61576-func WithOptions(opts ...RunOption) configuredRunner {
61577-	return configuredRunner{opts: opts}
61578-}
61579-
61580-type configuredRunner struct {
61581-	opts []RunOption
61582-}
61583-
61584-func (r configuredRunner) Run(t *testing.T, files string, f TestFunc) {
61585-	runner.Run(t, files, f, r.opts...)
61586-}
61587-
61588-type RunMultiple []struct {
61589-	Name   string
61590-	Runner regtestRunner
61591-}
61592-
61593-func (r RunMultiple) Run(t *testing.T, files string, f TestFunc) {
61594-	for _, runner := range r {
61595-		t.Run(runner.Name, func(t *testing.T) {
61596-			runner.Runner.Run(t, files, f)
61597-		})
61598-	}
61599-}
61600-
61601-// DefaultModes returns the default modes to run for each regression test (they
61602-// may be reconfigured by the tests themselves).
61603-func DefaultModes() Mode {
61604-	modes := Default
61605-	if !testing.Short() {
61606-		modes |= Experimental | Forwarded
61607-	}
61608-	if *runSubprocessTests {
61609-		modes |= SeparateProcess
61610-	}
61611-	return modes
61612-}
61613-
61614-// Main sets up and tears down the shared regtest state.
61615-func Main(m *testing.M, hook func(*source.Options)) {
61616-	// golang/go#54461: enable additional debugging around hanging Go commands.
61617-	gocommand.DebugHangingGoCommands = true
61618-
61619-	// If this magic environment variable is set, run gopls instead of the test
61620-	// suite. See the documentation for runTestAsGoplsEnvvar for more details.
61621-	if os.Getenv(runTestAsGoplsEnvvar) == "true" {
61622-		tool.Main(context.Background(), cmd.New("gopls", "", nil, hook), os.Args[1:])
61623-		os.Exit(0)
61624-	}
61625-
61626-	testenv.ExitIfSmallMachine()
61627-
61628-	// Disable GOPACKAGESDRIVER, as it can cause spurious test failures.
61629-	os.Setenv("GOPACKAGESDRIVER", "off")
61630-
61631-	flag.Parse()
61632-
61633-	runner = &Runner{
61634-		DefaultModes:             DefaultModes(),
61635-		Timeout:                  *regtestTimeout,
61636-		PrintGoroutinesOnFailure: *printGoroutinesOnFailure,
61637-		SkipCleanup:              *skipCleanup,
61638-		OptionsHook:              hook,
61639-		store:                    memoize.NewStore(memoize.NeverEvict),
61640-	}
61641-
61642-	runner.goplsPath = *goplsBinaryPath
61643-	if runner.goplsPath == "" {
61644-		var err error
61645-		runner.goplsPath, err = os.Executable()
61646-		if err != nil {
61647-			panic(fmt.Sprintf("finding test binary path: %v", err))
61648-		}
61649-	}
61650-
61651-	dir, err := ioutil.TempDir("", "gopls-regtest-")
61652-	if err != nil {
61653-		panic(fmt.Errorf("creating regtest temp directory: %v", err))
61654-	}
61655-	runner.tempDir = dir
61656-
61657-	var code int
61658-	defer func() {
61659-		if err := runner.Close(); err != nil {
61660-			fmt.Fprintf(os.Stderr, "closing test runner: %v\n", err)
61661-			// Regtest cleanup is broken in go1.12 and earlier, and sometimes flakes on
61662-			// Windows due to file locking, but this is OK for our CI.
61663-			//
61664-			// Fail on go1.13+, except for windows and android which have shutdown problems.
61665-			if testenv.Go1Point() >= 13 && runtime.GOOS != "windows" && runtime.GOOS != "android" {
61666-				os.Exit(1)
61667-			}
61668-		}
61669-		os.Exit(code)
61670-	}()
61671-	code = m.Run()
61672-}
61673diff -urN a/gopls/internal/lsp/regtest/runner.go b/gopls/internal/lsp/regtest/runner.go
61674--- a/gopls/internal/lsp/regtest/runner.go	2000-01-01 00:00:00.000000000 -0000
61675+++ b/gopls/internal/lsp/regtest/runner.go	1970-01-01 00:00:00.000000000 +0000
61676@@ -1,437 +0,0 @@
61677-// Copyright 2020 The Go Authors. All rights reserved.
61678-// Use of this source code is governed by a BSD-style
61679-// license that can be found in the LICENSE file.
61680-
61681-package regtest
61682-
61683-import (
61684-	"bytes"
61685-	"context"
61686-	"fmt"
61687-	"io"
61688-	"io/ioutil"
61689-	"net"
61690-	"os"
61691-	"path/filepath"
61692-	"runtime"
61693-	"runtime/pprof"
61694-	"strings"
61695-	"sync"
61696-	"testing"
61697-	"time"
61698-
61699-	exec "golang.org/x/sys/execabs"
61700-
61701-	"golang.org/x/tools/gopls/internal/lsp/cache"
61702-	"golang.org/x/tools/gopls/internal/lsp/debug"
61703-	"golang.org/x/tools/gopls/internal/lsp/fake"
61704-	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
61705-	"golang.org/x/tools/gopls/internal/lsp/protocol"
61706-	"golang.org/x/tools/gopls/internal/lsp/source"
61707-	"golang.org/x/tools/internal/jsonrpc2"
61708-	"golang.org/x/tools/internal/jsonrpc2/servertest"
61709-	"golang.org/x/tools/internal/memoize"
61710-	"golang.org/x/tools/internal/testenv"
61711-	"golang.org/x/tools/internal/xcontext"
61712-)
61713-
61714-// Mode is a bitmask that defines for which execution modes a test should run.
61715-//
61716-// Each mode controls several aspects of gopls' configuration:
61717-//   - Which server options to use for gopls sessions
61718-//   - Whether to use a shared cache
61719-//   - Whether to use a shared server
61720-//   - Whether to run the server in-process or in a separate process
61721-//
61722-// The behavior of each mode with respect to these aspects is summarized below.
61723-// TODO(rfindley, cleanup): rather than using arbitrary names for these modes,
61724-// we can compose them explicitly out of the features described here, allowing
61725-// individual tests more freedom in constructing problematic execution modes.
61726-// For example, a test could assert on a certain behavior when running with
61727-// experimental options on a separate process. Moreover, we could unify 'Modes'
61728-// with 'Options', and use RunMultiple rather than a hard-coded loop through
61729-// modes.
61730-//
61731-// Mode            | Options      | Shared Cache? | Shared Server? | In-process?
61732-// ---------------------------------------------------------------------------
61733-// Default         | Default      | Y             | N              | Y
61734-// Forwarded       | Default      | Y             | Y              | Y
61735-// SeparateProcess | Default      | Y             | Y              | N
61736-// Experimental    | Experimental | N             | N              | Y
61737-type Mode int
61738-
61739-const (
61740-	// Default mode runs gopls with the default options, communicating over pipes
61741-	// to emulate the lsp sidecar execution mode, which communicates over
61742-	// stdin/stdout.
61743-	//
61744-	// It uses separate servers for each test, but a shared cache, to avoid
61745-	// duplicating work when processing GOROOT.
61746-	Default Mode = 1 << iota
61747-
61748-	// Forwarded uses the default options, but forwards connections to a shared
61749-	// in-process gopls server.
61750-	Forwarded
61751-
61752-	// SeparateProcess uses the default options, but forwards connection to an
61753-	// external gopls daemon.
61754-	//
61755-	// Only supported on GOOS=linux.
61756-	SeparateProcess
61757-
61758-	// Experimental enables all of the experimental configurations that are
61759-	// being developed, and runs gopls in sidecar mode.
61760-	//
61761-	// It uses a separate cache for each test, to exercise races that may only
61762-	// appear with cache misses.
61763-	Experimental
61764-)
61765-
61766-func (m Mode) String() string {
61767-	switch m {
61768-	case Default:
61769-		return "default"
61770-	case Forwarded:
61771-		return "forwarded"
61772-	case SeparateProcess:
61773-		return "separate process"
61774-	case Experimental:
61775-		return "experimental"
61776-	default:
61777-		return "unknown mode"
61778-	}
61779-}
61780-
61781-// A Runner runs tests in gopls execution environments, as specified by its
61782-// modes. For modes that share state (for example, a shared cache or common
61783-// remote), any tests that execute on the same Runner will share the same
61784-// state.
61785-type Runner struct {
61786-	// Configuration
61787-	DefaultModes             Mode                  // modes to run for each test
61788-	Timeout                  time.Duration         // per-test timeout, if set
61789-	PrintGoroutinesOnFailure bool                  // whether to dump goroutines on test failure
61790-	SkipCleanup              bool                  // if set, don't delete test data directories when the test exits
61791-	OptionsHook              func(*source.Options) // if set, use these options when creating gopls sessions
61792-
61793-	// Immutable state shared across test invocations
61794-	goplsPath string         // path to the gopls executable (for SeparateProcess mode)
61795-	tempDir   string         // shared parent temp directory
61796-	store     *memoize.Store // shared store
61797-
61798-	// Lazily allocated resources
61799-	tsOnce sync.Once
61800-	ts     *servertest.TCPServer // shared in-process test server ("forwarded" mode)
61801-
61802-	startRemoteOnce sync.Once
61803-	remoteSocket    string // unix domain socket for shared daemon ("separate process" mode)
61804-	remoteErr       error
61805-	cancelRemote    func()
61806-}
61807-
61808-type TestFunc func(t *testing.T, env *Env)
61809-
61810-// Run executes the test function in the default configured gopls execution
61811-// modes. For each a test run, a new workspace is created containing the
61812-// un-txtared files specified by filedata.
61813-func (r *Runner) Run(t *testing.T, files string, test TestFunc, opts ...RunOption) {
61814-	// TODO(rfindley): this function has gotten overly complicated, and warrants
61815-	// refactoring.
61816-	t.Helper()
61817-	checkBuilder(t)
61818-	testenv.NeedsGoPackages(t)
61819-
61820-	tests := []struct {
61821-		name      string
61822-		mode      Mode
61823-		getServer func(func(*source.Options)) jsonrpc2.StreamServer
61824-	}{
61825-		{"default", Default, r.defaultServer},
61826-		{"forwarded", Forwarded, r.forwardedServer},
61827-		{"separate_process", SeparateProcess, r.separateProcessServer},
61828-		{"experimental", Experimental, r.experimentalServer},
61829-	}
61830-
61831-	for _, tc := range tests {
61832-		tc := tc
61833-		var config runConfig
61834-		for _, opt := range opts {
61835-			opt.set(&config)
61836-		}
61837-		modes := r.DefaultModes
61838-		if config.modes != 0 {
61839-			modes = config.modes
61840-		}
61841-		if modes&tc.mode == 0 {
61842-			continue
61843-		}
61844-
61845-		t.Run(tc.name, func(t *testing.T) {
61846-			// TODO(rfindley): once jsonrpc2 shutdown is fixed, we should not leak
61847-			// goroutines in this test function.
61848-			// stacktest.NoLeak(t)
61849-
61850-			ctx := context.Background()
61851-			if r.Timeout != 0 {
61852-				var cancel context.CancelFunc
61853-				ctx, cancel = context.WithTimeout(ctx, r.Timeout)
61854-				defer cancel()
61855-			} else if d, ok := testenv.Deadline(t); ok {
61856-				timeout := time.Until(d) * 19 / 20 // Leave an arbitrary 5% for cleanup.
61857-				var cancel context.CancelFunc
61858-				ctx, cancel = context.WithTimeout(ctx, timeout)
61859-				defer cancel()
61860-			}
61861-
61862-			// TODO(rfindley): do we need an instance at all? Can it be removed?
61863-			ctx = debug.WithInstance(ctx, "", "off")
61864-
61865-			rootDir := filepath.Join(r.tempDir, filepath.FromSlash(t.Name()))
61866-			if err := os.MkdirAll(rootDir, 0755); err != nil {
61867-				t.Fatal(err)
61868-			}
61869-
61870-			files := fake.UnpackTxt(files)
61871-			if config.editor.WindowsLineEndings {
61872-				for name, data := range files {
61873-					files[name] = bytes.ReplaceAll(data, []byte("\n"), []byte("\r\n"))
61874-				}
61875-			}
61876-			config.sandbox.Files = files
61877-			config.sandbox.RootDir = rootDir
61878-			sandbox, err := fake.NewSandbox(&config.sandbox)
61879-			if err != nil {
61880-				t.Fatal(err)
61881-			}
61882-			defer func() {
61883-				if !r.SkipCleanup {
61884-					if err := sandbox.Close(); err != nil {
61885-						pprof.Lookup("goroutine").WriteTo(os.Stderr, 1)
61886-						t.Errorf("closing the sandbox: %v", err)
61887-					}
61888-				}
61889-			}()
61890-
61891-			ss := tc.getServer(r.OptionsHook)
61892-
61893-			framer := jsonrpc2.NewRawStream
61894-			ls := &loggingFramer{}
61895-			framer = ls.framer(jsonrpc2.NewRawStream)
61896-			ts := servertest.NewPipeServer(ss, framer)
61897-
61898-			awaiter := NewAwaiter(sandbox.Workdir)
61899-			const skipApplyEdits = false
61900-			editor, err := fake.NewEditor(sandbox, config.editor).Connect(ctx, ts, awaiter.Hooks(), skipApplyEdits)
61901-			if err != nil {
61902-				t.Fatal(err)
61903-			}
61904-			env := &Env{
61905-				T:       t,
61906-				Ctx:     ctx,
61907-				Sandbox: sandbox,
61908-				Editor:  editor,
61909-				Server:  ts,
61910-				Awaiter: awaiter,
61911-			}
61912-			defer func() {
61913-				if t.Failed() && r.PrintGoroutinesOnFailure {
61914-					pprof.Lookup("goroutine").WriteTo(os.Stderr, 1)
61915-				}
61916-				if t.Failed() || *printLogs {
61917-					ls.printBuffers(t.Name(), os.Stderr)
61918-				}
61919-				// For tests that failed due to a timeout, don't fail to shutdown
61920-				// because ctx is done.
61921-				//
61922-				// There is little point to setting an arbitrary timeout for closing
61923-				// the editor: in general we want to clean up before proceeding to the
61924-				// next test, and if there is a deadlock preventing closing it will
61925-				// eventually be handled by the `go test` timeout.
61926-				if err := editor.Close(xcontext.Detach(ctx)); err != nil {
61927-					t.Errorf("closing editor: %v", err)
61928-				}
61929-			}()
61930-			// Always await the initial workspace load.
61931-			env.Await(InitialWorkspaceLoad)
61932-			test(t, env)
61933-		})
61934-	}
61935-}
61936-
61937-// longBuilders maps builders that are skipped when -short is set to a
61938-// (possibly empty) justification.
61939-var longBuilders = map[string]string{
61940-	"openbsd-amd64-64":        "golang.org/issues/42789",
61941-	"openbsd-386-64":          "golang.org/issues/42789",
61942-	"openbsd-386-68":          "golang.org/issues/42789",
61943-	"openbsd-amd64-68":        "golang.org/issues/42789",
61944-	"darwin-amd64-10_12":      "",
61945-	"freebsd-amd64-race":      "",
61946-	"illumos-amd64":           "",
61947-	"netbsd-arm-bsiegert":     "",
61948-	"solaris-amd64-oraclerel": "",
61949-	"windows-arm-zx2c4":       "",
61950-}
61951-
61952-func checkBuilder(t *testing.T) {
61953-	t.Helper()
61954-	builder := os.Getenv("GO_BUILDER_NAME")
61955-	if reason, ok := longBuilders[builder]; ok && testing.Short() {
61956-		if reason != "" {
61957-			t.Skipf("Skipping %s with -short due to %s", builder, reason)
61958-		} else {
61959-			t.Skipf("Skipping %s with -short", builder)
61960-		}
61961-	}
61962-}
61963-
61964-type loggingFramer struct {
61965-	mu  sync.Mutex
61966-	buf *safeBuffer
61967-}
61968-
61969-// safeBuffer is a threadsafe buffer for logs.
61970-type safeBuffer struct {
61971-	mu  sync.Mutex
61972-	buf bytes.Buffer
61973-}
61974-
61975-func (b *safeBuffer) Write(p []byte) (int, error) {
61976-	b.mu.Lock()
61977-	defer b.mu.Unlock()
61978-	return b.buf.Write(p)
61979-}
61980-
61981-func (s *loggingFramer) framer(f jsonrpc2.Framer) jsonrpc2.Framer {
61982-	return func(nc net.Conn) jsonrpc2.Stream {
61983-		s.mu.Lock()
61984-		framed := false
61985-		if s.buf == nil {
61986-			s.buf = &safeBuffer{buf: bytes.Buffer{}}
61987-			framed = true
61988-		}
61989-		s.mu.Unlock()
61990-		stream := f(nc)
61991-		if framed {
61992-			return protocol.LoggingStream(stream, s.buf)
61993-		}
61994-		return stream
61995-	}
61996-}
61997-
61998-func (s *loggingFramer) printBuffers(testname string, w io.Writer) {
61999-	s.mu.Lock()
62000-	defer s.mu.Unlock()
62001-
62002-	if s.buf == nil {
62003-		return
62004-	}
62005-	fmt.Fprintf(os.Stderr, "#### Start Gopls Test Logs for %q\n", testname)
62006-	s.buf.mu.Lock()
62007-	io.Copy(w, &s.buf.buf)
62008-	s.buf.mu.Unlock()
62009-	fmt.Fprintf(os.Stderr, "#### End Gopls Test Logs for %q\n", testname)
62010-}
62011-
62012-// defaultServer handles the Default execution mode.
62013-func (r *Runner) defaultServer(optsHook func(*source.Options)) jsonrpc2.StreamServer {
62014-	return lsprpc.NewStreamServer(cache.New(r.store), false, optsHook)
62015-}
62016-
62017-// experimentalServer handles the Experimental execution mode.
62018-func (r *Runner) experimentalServer(optsHook func(*source.Options)) jsonrpc2.StreamServer {
62019-	options := func(o *source.Options) {
62020-		optsHook(o)
62021-		o.EnableAllExperiments()
62022-	}
62023-	return lsprpc.NewStreamServer(cache.New(nil), false, options)
62024-}
62025-
62026-// forwardedServer handles the Forwarded execution mode.
62027-func (r *Runner) forwardedServer(optsHook func(*source.Options)) jsonrpc2.StreamServer {
62028-	r.tsOnce.Do(func() {
62029-		ctx := context.Background()
62030-		ctx = debug.WithInstance(ctx, "", "off")
62031-		ss := lsprpc.NewStreamServer(cache.New(nil), false, optsHook)
62032-		r.ts = servertest.NewTCPServer(ctx, ss, nil)
62033-	})
62034-	return newForwarder("tcp", r.ts.Addr)
62035-}
62036-
62037-// runTestAsGoplsEnvvar triggers TestMain to run gopls instead of running
62038-// tests. It's a trick to allow tests to find a binary to use to start a gopls
62039-// subprocess.
62040-const runTestAsGoplsEnvvar = "_GOPLS_TEST_BINARY_RUN_AS_GOPLS"
62041-
62042-// separateProcessServer handles the SeparateProcess execution mode.
62043-func (r *Runner) separateProcessServer(optsHook func(*source.Options)) jsonrpc2.StreamServer {
62044-	if runtime.GOOS != "linux" {
62045-		panic("separate process execution mode is only supported on linux")
62046-	}
62047-
62048-	r.startRemoteOnce.Do(func() {
62049-		socketDir, err := ioutil.TempDir(r.tempDir, "gopls-regtest-socket")
62050-		if err != nil {
62051-			r.remoteErr = err
62052-			return
62053-		}
62054-		r.remoteSocket = filepath.Join(socketDir, "gopls-test-daemon")
62055-
62056-		// The server should be killed by when the test runner exits, but to be
62057-		// conservative also set a listen timeout.
62058-		args := []string{"serve", "-listen", "unix;" + r.remoteSocket, "-listen.timeout", "1m"}
62059-
62060-		ctx, cancel := context.WithCancel(context.Background())
62061-		cmd := exec.CommandContext(ctx, r.goplsPath, args...)
62062-		cmd.Env = append(os.Environ(), runTestAsGoplsEnvvar+"=true")
62063-
62064-		// Start the external gopls process. This is still somewhat racy, as we
62065-		// don't know when gopls binds to the socket, but the gopls forwarder
62066-		// client has built-in retry behavior that should mostly mitigate this
62067-		// problem (and if it doesn't, we probably want to improve the retry
62068-		// behavior).
62069-		if err := cmd.Start(); err != nil {
62070-			cancel()
62071-			r.remoteSocket = ""
62072-			r.remoteErr = err
62073-		} else {
62074-			r.cancelRemote = cancel
62075-			// Spin off a goroutine to wait, so that we free up resources when the
62076-			// server exits.
62077-			go cmd.Wait()
62078-		}
62079-	})
62080-
62081-	return newForwarder("unix", r.remoteSocket)
62082-}
62083-
62084-func newForwarder(network, address string) *lsprpc.Forwarder {
62085-	server, err := lsprpc.NewForwarder(network+";"+address, nil)
62086-	if err != nil {
62087-		// This should never happen, as we are passing an explicit address.
62088-		panic(fmt.Sprintf("internal error: unable to create forwarder: %v", err))
62089-	}
62090-	return server
62091-}
62092-
62093-// Close cleans up resource that have been allocated to this workspace.
62094-func (r *Runner) Close() error {
62095-	var errmsgs []string
62096-	if r.ts != nil {
62097-		if err := r.ts.Close(); err != nil {
62098-			errmsgs = append(errmsgs, err.Error())
62099-		}
62100-	}
62101-	if r.cancelRemote != nil {
62102-		r.cancelRemote()
62103-	}
62104-	if !r.SkipCleanup {
62105-		if err := os.RemoveAll(r.tempDir); err != nil {
62106-			errmsgs = append(errmsgs, err.Error())
62107-		}
62108-	}
62109-	if len(errmsgs) > 0 {
62110-		return fmt.Errorf("errors closing the test runner:\n\t%s", strings.Join(errmsgs, "\n\t"))
62111-	}
62112-	return nil
62113-}
62114diff -urN a/gopls/internal/lsp/regtest/wrappers.go b/gopls/internal/lsp/regtest/wrappers.go
62115--- a/gopls/internal/lsp/regtest/wrappers.go	2000-01-01 00:00:00.000000000 -0000
62116+++ b/gopls/internal/lsp/regtest/wrappers.go	1970-01-01 00:00:00.000000000 +0000
62117@@ -1,489 +0,0 @@
62118-// Copyright 2020 The Go Authors. All rights reserved.
62119-// Use of this source code is governed by a BSD-style
62120-// license that can be found in the LICENSE file.
62121-
62122-package regtest
62123-
62124-import (
62125-	"encoding/json"
62126-	"path"
62127-
62128-	"golang.org/x/tools/gopls/internal/lsp/command"
62129-	"golang.org/x/tools/gopls/internal/lsp/fake"
62130-	"golang.org/x/tools/gopls/internal/lsp/protocol"
62131-	"golang.org/x/tools/internal/xcontext"
62132-)
62133-
62134-// RemoveWorkspaceFile deletes a file on disk but does nothing in the
62135-// editor. It calls t.Fatal on any error.
62136-func (e *Env) RemoveWorkspaceFile(name string) {
62137-	e.T.Helper()
62138-	if err := e.Sandbox.Workdir.RemoveFile(e.Ctx, name); err != nil {
62139-		e.T.Fatal(err)
62140-	}
62141-}
62142-
62143-// ReadWorkspaceFile reads a file from the workspace, calling t.Fatal on any
62144-// error.
62145-func (e *Env) ReadWorkspaceFile(name string) string {
62146-	e.T.Helper()
62147-	content, err := e.Sandbox.Workdir.ReadFile(name)
62148-	if err != nil {
62149-		e.T.Fatal(err)
62150-	}
62151-	return string(content)
62152-}
62153-
62154-// WriteWorkspaceFile writes a file to disk but does nothing in the editor.
62155-// It calls t.Fatal on any error.
62156-func (e *Env) WriteWorkspaceFile(name, content string) {
62157-	e.T.Helper()
62158-	if err := e.Sandbox.Workdir.WriteFile(e.Ctx, name, content); err != nil {
62159-		e.T.Fatal(err)
62160-	}
62161-}
62162-
62163-// WriteWorkspaceFiles deletes a file on disk but does nothing in the
62164-// editor. It calls t.Fatal on any error.
62165-func (e *Env) WriteWorkspaceFiles(files map[string]string) {
62166-	e.T.Helper()
62167-	if err := e.Sandbox.Workdir.WriteFiles(e.Ctx, files); err != nil {
62168-		e.T.Fatal(err)
62169-	}
62170-}
62171-
62172-// ListFiles lists relative paths to files in the given directory.
62173-// It calls t.Fatal on any error.
62174-func (e *Env) ListFiles(dir string) []string {
62175-	e.T.Helper()
62176-	paths, err := e.Sandbox.Workdir.ListFiles(dir)
62177-	if err != nil {
62178-		e.T.Fatal(err)
62179-	}
62180-	return paths
62181-}
62182-
62183-// OpenFile opens a file in the editor, calling t.Fatal on any error.
62184-func (e *Env) OpenFile(name string) {
62185-	e.T.Helper()
62186-	if err := e.Editor.OpenFile(e.Ctx, name); err != nil {
62187-		e.T.Fatal(err)
62188-	}
62189-}
62190-
62191-// CreateBuffer creates a buffer in the editor, calling t.Fatal on any error.
62192-func (e *Env) CreateBuffer(name string, content string) {
62193-	e.T.Helper()
62194-	if err := e.Editor.CreateBuffer(e.Ctx, name, content); err != nil {
62195-		e.T.Fatal(err)
62196-	}
62197-}
62198-
62199-// BufferText returns the current buffer contents for the file with the given
62200-// relative path, calling t.Fatal if the file is not open in a buffer.
62201-func (e *Env) BufferText(name string) string {
62202-	e.T.Helper()
62203-	text, ok := e.Editor.BufferText(name)
62204-	if !ok {
62205-		e.T.Fatalf("buffer %q is not open", name)
62206-	}
62207-	return text
62208-}
62209-
62210-// CloseBuffer closes an editor buffer without saving, calling t.Fatal on any
62211-// error.
62212-func (e *Env) CloseBuffer(name string) {
62213-	e.T.Helper()
62214-	if err := e.Editor.CloseBuffer(e.Ctx, name); err != nil {
62215-		e.T.Fatal(err)
62216-	}
62217-}
62218-
62219-// EditBuffer applies edits to an editor buffer, calling t.Fatal on any error.
62220-func (e *Env) EditBuffer(name string, edits ...protocol.TextEdit) {
62221-	e.T.Helper()
62222-	if err := e.Editor.EditBuffer(e.Ctx, name, edits); err != nil {
62223-		e.T.Fatal(err)
62224-	}
62225-}
62226-
62227-func (e *Env) SetBufferContent(name string, content string) {
62228-	e.T.Helper()
62229-	if err := e.Editor.SetBufferContent(e.Ctx, name, content); err != nil {
62230-		e.T.Fatal(err)
62231-	}
62232-}
62233-
62234-// RegexpSearch returns the starting position of the first match for re in the
62235-// buffer specified by name, calling t.Fatal on any error. It first searches
62236-// for the position in open buffers, then in workspace files.
62237-func (e *Env) RegexpSearch(name, re string) protocol.Location {
62238-	e.T.Helper()
62239-	loc, err := e.Editor.RegexpSearch(name, re)
62240-	if err == fake.ErrUnknownBuffer {
62241-		loc, err = e.Sandbox.Workdir.RegexpSearch(name, re)
62242-	}
62243-	if err != nil {
62244-		e.T.Fatalf("RegexpSearch: %v, %v for %q", name, err, re)
62245-	}
62246-	return loc
62247-}
62248-
62249-// RegexpReplace replaces the first group in the first match of regexpStr with
62250-// the replace text, calling t.Fatal on any error.
62251-func (e *Env) RegexpReplace(name, regexpStr, replace string) {
62252-	e.T.Helper()
62253-	if err := e.Editor.RegexpReplace(e.Ctx, name, regexpStr, replace); err != nil {
62254-		e.T.Fatalf("RegexpReplace: %v", err)
62255-	}
62256-}
62257-
62258-// SaveBuffer saves an editor buffer, calling t.Fatal on any error.
62259-func (e *Env) SaveBuffer(name string) {
62260-	e.T.Helper()
62261-	if err := e.Editor.SaveBuffer(e.Ctx, name); err != nil {
62262-		e.T.Fatal(err)
62263-	}
62264-}
62265-
62266-func (e *Env) SaveBufferWithoutActions(name string) {
62267-	e.T.Helper()
62268-	if err := e.Editor.SaveBufferWithoutActions(e.Ctx, name); err != nil {
62269-		e.T.Fatal(err)
62270-	}
62271-}
62272-
62273-// GoToDefinition goes to definition in the editor, calling t.Fatal on any
62274-// error. It returns the path and position of the resulting jump.
62275-func (e *Env) GoToDefinition(loc protocol.Location) protocol.Location {
62276-	e.T.Helper()
62277-	loc, err := e.Editor.GoToDefinition(e.Ctx, loc)
62278-	if err != nil {
62279-		e.T.Fatal(err)
62280-	}
62281-	return loc
62282-}
62283-
62284-// FormatBuffer formats the editor buffer, calling t.Fatal on any error.
62285-func (e *Env) FormatBuffer(name string) {
62286-	e.T.Helper()
62287-	if err := e.Editor.FormatBuffer(e.Ctx, name); err != nil {
62288-		e.T.Fatal(err)
62289-	}
62290-}
62291-
62292-// OrganizeImports processes the source.organizeImports codeAction, calling
62293-// t.Fatal on any error.
62294-func (e *Env) OrganizeImports(name string) {
62295-	e.T.Helper()
62296-	if err := e.Editor.OrganizeImports(e.Ctx, name); err != nil {
62297-		e.T.Fatal(err)
62298-	}
62299-}
62300-
62301-// ApplyQuickFixes processes the quickfix codeAction, calling t.Fatal on any error.
62302-func (e *Env) ApplyQuickFixes(path string, diagnostics []protocol.Diagnostic) {
62303-	e.T.Helper()
62304-	loc := protocol.Location{URI: e.Sandbox.Workdir.URI(path)} // zero Range => whole file
62305-	if err := e.Editor.ApplyQuickFixes(e.Ctx, loc, diagnostics); err != nil {
62306-		e.T.Fatal(err)
62307-	}
62308-}
62309-
62310-// ApplyCodeAction applies the given code action.
62311-func (e *Env) ApplyCodeAction(action protocol.CodeAction) {
62312-	e.T.Helper()
62313-	if err := e.Editor.ApplyCodeAction(e.Ctx, action); err != nil {
62314-		e.T.Fatal(err)
62315-	}
62316-}
62317-
62318-// GetQuickFixes returns the available quick fix code actions.
62319-func (e *Env) GetQuickFixes(path string, diagnostics []protocol.Diagnostic) []protocol.CodeAction {
62320-	e.T.Helper()
62321-	loc := protocol.Location{URI: e.Sandbox.Workdir.URI(path)} // zero Range => whole file
62322-	actions, err := e.Editor.GetQuickFixes(e.Ctx, loc, diagnostics)
62323-	if err != nil {
62324-		e.T.Fatal(err)
62325-	}
62326-	return actions
62327-}
62328-
62329-// Hover in the editor, calling t.Fatal on any error.
62330-func (e *Env) Hover(loc protocol.Location) (*protocol.MarkupContent, protocol.Location) {
62331-	e.T.Helper()
62332-	c, loc, err := e.Editor.Hover(e.Ctx, loc)
62333-	if err != nil {
62334-		e.T.Fatal(err)
62335-	}
62336-	return c, loc
62337-}
62338-
62339-func (e *Env) DocumentLink(name string) []protocol.DocumentLink {
62340-	e.T.Helper()
62341-	links, err := e.Editor.DocumentLink(e.Ctx, name)
62342-	if err != nil {
62343-		e.T.Fatal(err)
62344-	}
62345-	return links
62346-}
62347-
62348-func (e *Env) DocumentHighlight(loc protocol.Location) []protocol.DocumentHighlight {
62349-	e.T.Helper()
62350-	highlights, err := e.Editor.DocumentHighlight(e.Ctx, loc)
62351-	if err != nil {
62352-		e.T.Fatal(err)
62353-	}
62354-	return highlights
62355-}
62356-
62357-// RunGenerate runs "go generate" in the given dir, calling t.Fatal on any error.
62358-// It waits for the generate command to complete and checks for file changes
62359-// before returning.
62360-func (e *Env) RunGenerate(dir string) {
62361-	e.T.Helper()
62362-	if err := e.Editor.RunGenerate(e.Ctx, dir); err != nil {
62363-		e.T.Fatal(err)
62364-	}
62365-	e.Await(NoOutstandingWork())
62366-	// Ideally the fake.Workspace would handle all synthetic file watching, but
62367-	// we help it out here as we need to wait for the generate command to
62368-	// complete before checking the filesystem.
62369-	e.CheckForFileChanges()
62370-}
62371-
62372-// RunGoCommand runs the given command in the sandbox's default working
62373-// directory.
62374-func (e *Env) RunGoCommand(verb string, args ...string) {
62375-	e.T.Helper()
62376-	if err := e.Sandbox.RunGoCommand(e.Ctx, "", verb, args, true); err != nil {
62377-		e.T.Fatal(err)
62378-	}
62379-}
62380-
62381-// RunGoCommandInDir is like RunGoCommand, but executes in the given
62382-// relative directory of the sandbox.
62383-func (e *Env) RunGoCommandInDir(dir, verb string, args ...string) {
62384-	e.T.Helper()
62385-	if err := e.Sandbox.RunGoCommand(e.Ctx, dir, verb, args, true); err != nil {
62386-		e.T.Fatal(err)
62387-	}
62388-}
62389-
62390-// GoVersion checks the version of the go command.
62391-// It returns the X in Go 1.X.
62392-func (e *Env) GoVersion() int {
62393-	e.T.Helper()
62394-	v, err := e.Sandbox.GoVersion(e.Ctx)
62395-	if err != nil {
62396-		e.T.Fatal(err)
62397-	}
62398-	return v
62399-}
62400-
62401-// DumpGoSum prints the correct go.sum contents for dir in txtar format,
62402-// for use in creating regtests.
62403-func (e *Env) DumpGoSum(dir string) {
62404-	e.T.Helper()
62405-
62406-	if err := e.Sandbox.RunGoCommand(e.Ctx, dir, "list", []string{"-mod=mod", "..."}, true); err != nil {
62407-		e.T.Fatal(err)
62408-	}
62409-	sumFile := path.Join(dir, "/go.sum")
62410-	e.T.Log("\n\n-- " + sumFile + " --\n" + e.ReadWorkspaceFile(sumFile))
62411-	e.T.Fatal("see contents above")
62412-}
62413-
62414-// CheckForFileChanges triggers a manual poll of the workspace for any file
62415-// changes since creation, or since last polling. It is a workaround for the
62416-// lack of true file watching support in the fake workspace.
62417-func (e *Env) CheckForFileChanges() {
62418-	e.T.Helper()
62419-	if err := e.Sandbox.Workdir.CheckForFileChanges(e.Ctx); err != nil {
62420-		e.T.Fatal(err)
62421-	}
62422-}
62423-
62424-// CodeLens calls textDocument/codeLens for the given path, calling t.Fatal on
62425-// any error.
62426-func (e *Env) CodeLens(path string) []protocol.CodeLens {
62427-	e.T.Helper()
62428-	lens, err := e.Editor.CodeLens(e.Ctx, path)
62429-	if err != nil {
62430-		e.T.Fatal(err)
62431-	}
62432-	return lens
62433-}
62434-
62435-// ExecuteCodeLensCommand executes the command for the code lens matching the
62436-// given command name.
62437-func (e *Env) ExecuteCodeLensCommand(path string, cmd command.Command, result interface{}) {
62438-	e.T.Helper()
62439-	lenses := e.CodeLens(path)
62440-	var lens protocol.CodeLens
62441-	var found bool
62442-	for _, l := range lenses {
62443-		if l.Command.Command == cmd.ID() {
62444-			lens = l
62445-			found = true
62446-		}
62447-	}
62448-	if !found {
62449-		e.T.Fatalf("found no command with the ID %s", cmd.ID())
62450-	}
62451-	e.ExecuteCommand(&protocol.ExecuteCommandParams{
62452-		Command:   lens.Command.Command,
62453-		Arguments: lens.Command.Arguments,
62454-	}, result)
62455-}
62456-
62457-func (e *Env) ExecuteCommand(params *protocol.ExecuteCommandParams, result interface{}) {
62458-	e.T.Helper()
62459-	response, err := e.Editor.ExecuteCommand(e.Ctx, params)
62460-	if err != nil {
62461-		e.T.Fatal(err)
62462-	}
62463-	if result == nil {
62464-		return
62465-	}
62466-	// Hack: The result of an executeCommand request will be unmarshaled into
62467-	// maps. Re-marshal and unmarshal into the type we expect.
62468-	//
62469-	// This could be improved by generating a jsonrpc2 command client from the
62470-	// command.Interface, but that should only be done if we're consolidating
62471-	// this part of the tsprotocol generation.
62472-	data, err := json.Marshal(response)
62473-	if err != nil {
62474-		e.T.Fatal(err)
62475-	}
62476-	if err := json.Unmarshal(data, result); err != nil {
62477-		e.T.Fatal(err)
62478-	}
62479-}
62480-
62481-// InlayHints calls textDocument/inlayHints for the given path, calling t.Fatal on
62482-// any error.
62483-func (e *Env) InlayHints(path string) []protocol.InlayHint {
62484-	e.T.Helper()
62485-	hints, err := e.Editor.InlayHint(e.Ctx, path)
62486-	if err != nil {
62487-		e.T.Fatal(err)
62488-	}
62489-	return hints
62490-}
62491-
62492-// Symbol calls workspace/symbol
62493-func (e *Env) Symbol(query string) []protocol.SymbolInformation {
62494-	e.T.Helper()
62495-	ans, err := e.Editor.Symbols(e.Ctx, query)
62496-	if err != nil {
62497-		e.T.Fatal(err)
62498-	}
62499-	return ans
62500-}
62501-
62502-// References wraps Editor.References, calling t.Fatal on any error.
62503-func (e *Env) References(loc protocol.Location) []protocol.Location {
62504-	e.T.Helper()
62505-	locations, err := e.Editor.References(e.Ctx, loc)
62506-	if err != nil {
62507-		e.T.Fatal(err)
62508-	}
62509-	return locations
62510-}
62511-
62512-// Rename wraps Editor.Rename, calling t.Fatal on any error.
62513-func (e *Env) Rename(loc protocol.Location, newName string) {
62514-	e.T.Helper()
62515-	if err := e.Editor.Rename(e.Ctx, loc, newName); err != nil {
62516-		e.T.Fatal(err)
62517-	}
62518-}
62519-
62520-// Implementations wraps Editor.Implementations, calling t.Fatal on any error.
62521-func (e *Env) Implementations(loc protocol.Location) []protocol.Location {
62522-	e.T.Helper()
62523-	locations, err := e.Editor.Implementations(e.Ctx, loc)
62524-	if err != nil {
62525-		e.T.Fatal(err)
62526-	}
62527-	return locations
62528-}
62529-
62530-// RenameFile wraps Editor.RenameFile, calling t.Fatal on any error.
62531-func (e *Env) RenameFile(oldPath, newPath string) {
62532-	e.T.Helper()
62533-	if err := e.Editor.RenameFile(e.Ctx, oldPath, newPath); err != nil {
62534-		e.T.Fatal(err)
62535-	}
62536-}
62537-
62538-// SignatureHelp wraps Editor.SignatureHelp, calling t.Fatal on error
62539-func (e *Env) SignatureHelp(loc protocol.Location) *protocol.SignatureHelp {
62540-	e.T.Helper()
62541-	sighelp, err := e.Editor.SignatureHelp(e.Ctx, loc)
62542-	if err != nil {
62543-		e.T.Fatal(err)
62544-	}
62545-	return sighelp
62546-}
62547-
62548-// Completion executes a completion request on the server.
62549-func (e *Env) Completion(loc protocol.Location) *protocol.CompletionList {
62550-	e.T.Helper()
62551-	completions, err := e.Editor.Completion(e.Ctx, loc)
62552-	if err != nil {
62553-		e.T.Fatal(err)
62554-	}
62555-	return completions
62556-}
62557-
62558-// AcceptCompletion accepts a completion for the given item at the given
62559-// position.
62560-func (e *Env) AcceptCompletion(loc protocol.Location, item protocol.CompletionItem) {
62561-	e.T.Helper()
62562-	if err := e.Editor.AcceptCompletion(e.Ctx, loc, item); err != nil {
62563-		e.T.Fatal(err)
62564-	}
62565-}
62566-
62567-// CodeAction calls testDocument/codeAction for the given path, and calls
62568-// t.Fatal if there are errors.
62569-func (e *Env) CodeAction(path string, diagnostics []protocol.Diagnostic) []protocol.CodeAction {
62570-	e.T.Helper()
62571-	loc := protocol.Location{URI: e.Sandbox.Workdir.URI(path)} // no Range => whole file
62572-	actions, err := e.Editor.CodeAction(e.Ctx, loc, diagnostics)
62573-	if err != nil {
62574-		e.T.Fatal(err)
62575-	}
62576-	return actions
62577-}
62578-
62579-// ChangeConfiguration updates the editor config, calling t.Fatal on any error.
62580-func (e *Env) ChangeConfiguration(newConfig fake.EditorConfig) {
62581-	e.T.Helper()
62582-	if err := e.Editor.ChangeConfiguration(e.Ctx, newConfig); err != nil {
62583-		e.T.Fatal(err)
62584-	}
62585-}
62586-
62587-// ChangeWorkspaceFolders updates the editor workspace folders, calling t.Fatal
62588-// on any error.
62589-func (e *Env) ChangeWorkspaceFolders(newFolders ...string) {
62590-	e.T.Helper()
62591-	if err := e.Editor.ChangeWorkspaceFolders(e.Ctx, newFolders); err != nil {
62592-		e.T.Fatal(err)
62593-	}
62594-}
62595-
62596-// Close shuts down the editor session and cleans up the sandbox directory,
62597-// calling t.Error on any error.
62598-func (e *Env) Close() {
62599-	ctx := xcontext.Detach(e.Ctx)
62600-	if err := e.Editor.Close(ctx); err != nil {
62601-		e.T.Errorf("closing editor: %v", err)
62602-	}
62603-	if err := e.Sandbox.Close(); err != nil {
62604-		e.T.Errorf("cleaning up sandbox: %v", err)
62605-	}
62606-}
62607diff -urN a/gopls/internal/lsp/rename.go b/gopls/internal/lsp/rename.go
62608--- a/gopls/internal/lsp/rename.go	2000-01-01 00:00:00.000000000 -0000
62609+++ b/gopls/internal/lsp/rename.go	1970-01-01 00:00:00.000000000 +0000
62610@@ -1,78 +0,0 @@
62611-// Copyright 2019 The Go Authors. All rights reserved.
62612-// Use of this source code is governed by a BSD-style
62613-// license that can be found in the LICENSE file.
62614-
62615-package lsp
62616-
62617-import (
62618-	"context"
62619-	"path/filepath"
62620-
62621-	"golang.org/x/tools/gopls/internal/lsp/protocol"
62622-	"golang.org/x/tools/gopls/internal/lsp/source"
62623-)
62624-
62625-func (s *Server) rename(ctx context.Context, params *protocol.RenameParams) (*protocol.WorkspaceEdit, error) {
62626-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.Go)
62627-	defer release()
62628-	if !ok {
62629-		return nil, err
62630-	}
62631-	// Because we don't handle directory renaming within source.Rename, source.Rename returns
62632-	// boolean value isPkgRenaming to determine whether an DocumentChanges of type RenameFile should
62633-	// be added to the return protocol.WorkspaceEdit value.
62634-	edits, isPkgRenaming, err := source.Rename(ctx, snapshot, fh, params.Position, params.NewName)
62635-	if err != nil {
62636-		return nil, err
62637-	}
62638-
62639-	var docChanges []protocol.DocumentChanges
62640-	for uri, e := range edits {
62641-		fh, err := snapshot.GetFile(ctx, uri)
62642-		if err != nil {
62643-			return nil, err
62644-		}
62645-		docChanges = append(docChanges, documentChanges(fh, e)...)
62646-	}
62647-	if isPkgRenaming {
62648-		// Update the last component of the file's enclosing directory.
62649-		oldBase := filepath.Dir(fh.URI().Filename())
62650-		newURI := filepath.Join(filepath.Dir(oldBase), params.NewName)
62651-		docChanges = append(docChanges, protocol.DocumentChanges{
62652-			RenameFile: &protocol.RenameFile{
62653-				Kind:   "rename",
62654-				OldURI: protocol.URIFromPath(oldBase),
62655-				NewURI: protocol.URIFromPath(newURI),
62656-			},
62657-		})
62658-	}
62659-	return &protocol.WorkspaceEdit{
62660-		DocumentChanges: docChanges,
62661-	}, nil
62662-}
62663-
62664-// prepareRename implements the textDocument/prepareRename handler. It may
62665-// return (nil, nil) if there is no rename at the cursor position, but it is
62666-// not desirable to display an error to the user.
62667-//
62668-// TODO(rfindley): why wouldn't we want to show an error to the user, if the
62669-// user initiated a rename request at the cursor?
62670-func (s *Server) prepareRename(ctx context.Context, params *protocol.PrepareRenameParams) (*protocol.PrepareRename2Gn, error) {
62671-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.Go)
62672-	defer release()
62673-	if !ok {
62674-		return nil, err
62675-	}
62676-	// Do not return errors here, as it adds clutter.
62677-	// Returning a nil result means there is not a valid rename.
62678-	item, usererr, err := source.PrepareRename(ctx, snapshot, fh, params.Position)
62679-	if err != nil {
62680-		// Return usererr here rather than err, to avoid cluttering the UI with
62681-		// internal error details.
62682-		return nil, usererr
62683-	}
62684-	return &protocol.PrepareRename2Gn{
62685-		Range:       item.Range,
62686-		Placeholder: item.Text,
62687-	}, nil
62688-}
62689diff -urN a/gopls/internal/lsp/reset_golden.sh b/gopls/internal/lsp/reset_golden.sh
62690--- a/gopls/internal/lsp/reset_golden.sh	2000-01-01 00:00:00.000000000 -0000
62691+++ b/gopls/internal/lsp/reset_golden.sh	1970-01-01 00:00:00.000000000 +0000
62692@@ -1,30 +0,0 @@
62693-#!/bin/bash
62694-#
62695-# Copyright 2022 The Go Authors. All rights reserved.
62696-# Use of this source code is governed by a BSD-style
62697-# license that can be found in the LICENSE file.
62698-#
62699-# Updates the *.golden files ... to match the tests' current behavior.
62700-
62701-set -eu
62702-
62703-GO117BIN="go1.17.9"
62704-
62705-command -v $GO117BIN >/dev/null 2>&1 || {
62706-  go install golang.org/dl/$GO117BIN@latest
62707-  $GO117BIN download
62708-}
62709-
62710-find ./internal/lsp/testdata -name *.golden ! -name summary*.txt.golden -delete
62711-# Here we intentionally do not run the ./internal/lsp/source tests with
62712-# -golden. Eventually these tests will be deleted, and in the meantime they are
62713-# redundant with the ./internal/lsp tests.
62714-#
62715-# Note: go1.17.9 tests must be run *before* go tests, as by convention the
62716-# golden output should match the output of gopls built with the most recent
62717-# version of Go. If output differs at 1.17, tests must be tolerant of the 1.17
62718-# output.
62719-$GO117BIN test ./internal/lsp -golden
62720-go test ./internal/lsp -golden
62721-$GO117BIN test ./test  -golden
62722-go test ./test  -golden
62723diff -urN a/gopls/internal/lsp/safetoken/safetoken.go b/gopls/internal/lsp/safetoken/safetoken.go
62724--- a/gopls/internal/lsp/safetoken/safetoken.go	2000-01-01 00:00:00.000000000 -0000
62725+++ b/gopls/internal/lsp/safetoken/safetoken.go	1970-01-01 00:00:00.000000000 +0000
62726@@ -1,122 +0,0 @@
62727-// Copyright 2022 The Go Authors. All rights reserved.
62728-// Use of this source code is governed by a BSD-style
62729-// license that can be found in the LICENSE file.
62730-
62731-// Package safetoken provides wrappers around methods in go/token,
62732-// that return errors rather than panicking.
62733-//
62734-// It also provides a central place for workarounds in the underlying
62735-// packages. The use of this package's functions instead of methods of
62736-// token.File (such as Offset, Position, and PositionFor) is mandatory
62737-// throughout the gopls codebase and enforced by a static check.
62738-package safetoken
62739-
62740-import (
62741-	"fmt"
62742-	"go/token"
62743-)
62744-
62745-// Offset returns f.Offset(pos), but first checks that the file
62746-// contains the pos.
62747-//
62748-// The definition of "contains" here differs from that of token.File
62749-// in order to work around a bug in the parser (issue #57490): during
62750-// error recovery, the parser may create syntax nodes whose computed
62751-// End position is 1 byte beyond EOF, which would cause
62752-// token.File.Offset to panic. The workaround is that this function
62753-// accepts a Pos that is exactly 1 byte beyond EOF and maps it to the
62754-// EOF offset.
62755-func Offset(f *token.File, pos token.Pos) (int, error) {
62756-	if !inRange(f, pos) {
62757-		// Accept a Pos that is 1 byte beyond EOF,
62758-		// and map it to the EOF offset.
62759-		// (Workaround for #57490.)
62760-		if int(pos) == f.Base()+f.Size()+1 {
62761-			return f.Size(), nil
62762-		}
62763-
62764-		return -1, fmt.Errorf("pos %d is not in range [%d:%d] of file %s",
62765-			pos, f.Base(), f.Base()+f.Size(), f.Name())
62766-	}
62767-	return int(pos) - f.Base(), nil
62768-}
62769-
62770-// Offsets returns Offset(start) and Offset(end).
62771-func Offsets(f *token.File, start, end token.Pos) (int, int, error) {
62772-	startOffset, err := Offset(f, start)
62773-	if err != nil {
62774-		return 0, 0, fmt.Errorf("start: %v", err)
62775-	}
62776-	endOffset, err := Offset(f, end)
62777-	if err != nil {
62778-		return 0, 0, fmt.Errorf("end: %v", err)
62779-	}
62780-	return startOffset, endOffset, nil
62781-}
62782-
62783-// Pos returns f.Pos(offset), but first checks that the offset is
62784-// non-negative and not larger than the size of the file.
62785-func Pos(f *token.File, offset int) (token.Pos, error) {
62786-	if !(0 <= offset && offset <= f.Size()) {
62787-		return token.NoPos, fmt.Errorf("offset %d is not in range for file %s of size %d", offset, f.Name(), f.Size())
62788-	}
62789-	return token.Pos(f.Base() + offset), nil
62790-}
62791-
62792-// inRange reports whether file f contains position pos,
62793-// according to the invariants of token.File.
62794-//
62795-// This function is not public because of the ambiguity it would
62796-// create w.r.t. the definition of "contains". Use Offset instead.
62797-func inRange(f *token.File, pos token.Pos) bool {
62798-	return token.Pos(f.Base()) <= pos && pos <= token.Pos(f.Base()+f.Size())
62799-}
62800-
62801-// Position returns the Position for the pos value in the given file.
62802-//
62803-// p must be NoPos, a valid Pos in the range of f, or exactly 1 byte
62804-// beyond the end of f. (See [Offset] for explanation.)
62805-// Any other value causes a panic.
62806-//
62807-// Line directives (//line comments) are ignored.
62808-func Position(f *token.File, pos token.Pos) token.Position {
62809-	// Work around issue #57490.
62810-	if int(pos) == f.Base()+f.Size()+1 {
62811-		pos--
62812-	}
62813-
62814-	// TODO(adonovan): centralize the workaround for
62815-	// golang/go#41029 (newline at EOF) here too.
62816-
62817-	return f.PositionFor(pos, false)
62818-}
62819-
62820-// StartPosition converts a start Pos in the FileSet into a Position.
62821-//
62822-// Call this function only if start represents the start of a token or
62823-// parse tree, such as the result of Node.Pos().  If start is the end of
62824-// an interval, such as Node.End(), call EndPosition instead, as it
62825-// may need the correction described at [Position].
62826-func StartPosition(fset *token.FileSet, start token.Pos) (_ token.Position) {
62827-	if f := fset.File(start); f != nil {
62828-		return Position(f, start)
62829-	}
62830-	return
62831-}
62832-
62833-// EndPosition converts an end Pos in the FileSet into a Position.
62834-//
62835-// Call this function only if pos represents the end of
62836-// a non-empty interval, such as the result of Node.End().
62837-func EndPosition(fset *token.FileSet, end token.Pos) (_ token.Position) {
62838-	if f := fset.File(end); f != nil && int(end) > f.Base() {
62839-		return Position(f, end)
62840-	}
62841-
62842-	// Work around issue #57490.
62843-	if f := fset.File(end - 1); f != nil {
62844-		return Position(f, end)
62845-	}
62846-
62847-	return
62848-}
62849diff -urN a/gopls/internal/lsp/safetoken/safetoken_test.go b/gopls/internal/lsp/safetoken/safetoken_test.go
62850--- a/gopls/internal/lsp/safetoken/safetoken_test.go	2000-01-01 00:00:00.000000000 -0000
62851+++ b/gopls/internal/lsp/safetoken/safetoken_test.go	1970-01-01 00:00:00.000000000 +0000
62852@@ -1,121 +0,0 @@
62853-// Copyright 2021 The Go Authors. All rights reserved.
62854-// Use of this source code is governed by a BSD-style
62855-// license that can be found in the LICENSE file.
62856-
62857-package safetoken_test
62858-
62859-import (
62860-	"fmt"
62861-	"go/parser"
62862-	"go/token"
62863-	"go/types"
62864-	"os"
62865-	"testing"
62866-
62867-	"golang.org/x/tools/go/packages"
62868-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
62869-	"golang.org/x/tools/internal/testenv"
62870-)
62871-
62872-func TestWorkaroundIssue57490(t *testing.T) {
62873-	// During error recovery the parser synthesizes various close
62874-	// tokens at EOF, causing the End position of incomplete
62875-	// syntax nodes, computed as Rbrace+len("}"), to be beyond EOF.
62876-	src := `package p; func f() { var x struct`
62877-	fset := token.NewFileSet()
62878-	file, _ := parser.ParseFile(fset, "a.go", src, 0)
62879-	tf := fset.File(file.Pos())
62880-
62881-	// Add another file to the FileSet.
62882-	file2, _ := parser.ParseFile(fset, "b.go", "package q", 0)
62883-
62884-	// This is the ambiguity of #57490...
62885-	if file.End() != file2.Pos() {
62886-		t.Errorf("file.End() %d != %d file2.Pos()", file.End(), file2.Pos())
62887-	}
62888-	// ...which causes these statements to panic.
62889-	if false {
62890-		tf.Offset(file.End())   // panic: invalid Pos value 36 (should be in [1, 35])
62891-		tf.Position(file.End()) // panic: invalid Pos value 36 (should be in [1, 35])
62892-	}
62893-
62894-	// The offset of the EOF position is the file size.
62895-	offset, err := safetoken.Offset(tf, file.End()-1)
62896-	if err != nil || offset != tf.Size() {
62897-		t.Errorf("Offset(EOF) = (%d, %v), want token.File.Size %d", offset, err, tf.Size())
62898-	}
62899-
62900-	// The offset of the file.End() position, 1 byte beyond EOF,
62901-	// is also the size of the file.
62902-	offset, err = safetoken.Offset(tf, file.End())
62903-	if err != nil || offset != tf.Size() {
62904-		t.Errorf("Offset(ast.File.End()) = (%d, %v), want token.File.Size %d", offset, err, tf.Size())
62905-	}
62906-
62907-	if got, want := safetoken.Position(tf, file.End()).String(), "a.go:1:35"; got != want {
62908-		t.Errorf("Position(ast.File.End()) = %s, want %s", got, want)
62909-	}
62910-
62911-	if got, want := safetoken.EndPosition(fset, file.End()).String(), "a.go:1:35"; got != want {
62912-		t.Errorf("EndPosition(ast.File.End()) = %s, want %s", got, want)
62913-	}
62914-
62915-	// Note that calling StartPosition on an end may yield the wrong file:
62916-	if got, want := safetoken.StartPosition(fset, file.End()).String(), "b.go:1:1"; got != want {
62917-		t.Errorf("StartPosition(ast.File.End()) = %s, want %s", got, want)
62918-	}
62919-}
62920-
62921-// To reduce the risk of panic, or bugs for which this package
62922-// provides a workaround, this test statically reports references to
62923-// forbidden methods of token.File or FileSet throughout gopls and
62924-// suggests alternatives.
62925-func TestGoplsSourceDoesNotCallTokenFileMethods(t *testing.T) {
62926-	testenv.NeedsGoPackages(t)
62927-
62928-	pkgs, err := packages.Load(&packages.Config{
62929-		Mode: packages.NeedName | packages.NeedModule | packages.NeedCompiledGoFiles | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedImports | packages.NeedDeps,
62930-	}, "go/token", "golang.org/x/tools/gopls/...")
62931-	if err != nil {
62932-		t.Fatal(err)
62933-	}
62934-	var tokenPkg *packages.Package
62935-	for _, pkg := range pkgs {
62936-		if pkg.PkgPath == "go/token" {
62937-			tokenPkg = pkg
62938-			break
62939-		}
62940-	}
62941-	if tokenPkg == nil {
62942-		t.Fatal("missing package go/token")
62943-	}
62944-
62945-	File := tokenPkg.Types.Scope().Lookup("File")
62946-	FileSet := tokenPkg.Types.Scope().Lookup("FileSet")
62947-
62948-	alternative := make(map[types.Object]string)
62949-	setAlternative := func(recv types.Object, old, new string) {
62950-		oldMethod, _, _ := types.LookupFieldOrMethod(recv.Type(), true, recv.Pkg(), old)
62951-		alternative[oldMethod] = new
62952-	}
62953-	setAlternative(File, "Offset", "safetoken.Offset")
62954-	setAlternative(File, "Position", "safetoken.Position")
62955-	setAlternative(File, "PositionFor", "safetoken.Position")
62956-	setAlternative(FileSet, "Position", "safetoken.StartPosition or EndPosition")
62957-	setAlternative(FileSet, "PositionFor", "safetoken.StartPosition or EndPosition")
62958-
62959-	for _, pkg := range pkgs {
62960-		switch pkg.PkgPath {
62961-		case "go/token", "golang.org/x/tools/gopls/internal/lsp/safetoken":
62962-			continue // allow calls within these packages
62963-		}
62964-
62965-		for ident, obj := range pkg.TypesInfo.Uses {
62966-			if alt, ok := alternative[obj]; ok {
62967-				posn := safetoken.StartPosition(pkg.Fset, ident.Pos())
62968-				fmt.Fprintf(os.Stderr, "%s: forbidden use of %v; use %s instead.\n", posn, obj, alt)
62969-				t.Fail()
62970-			}
62971-		}
62972-	}
62973-}
62974diff -urN a/gopls/internal/lsp/selection_range.go b/gopls/internal/lsp/selection_range.go
62975--- a/gopls/internal/lsp/selection_range.go	2000-01-01 00:00:00.000000000 -0000
62976+++ b/gopls/internal/lsp/selection_range.go	1970-01-01 00:00:00.000000000 +0000
62977@@ -1,69 +0,0 @@
62978-// Copyright 2022 The Go Authors. All rights reserved.
62979-// Use of this source code is governed by a BSD-style
62980-// license that can be found in the LICENSE file.
62981-
62982-package lsp
62983-
62984-import (
62985-	"context"
62986-
62987-	"golang.org/x/tools/go/ast/astutil"
62988-	"golang.org/x/tools/gopls/internal/lsp/protocol"
62989-	"golang.org/x/tools/gopls/internal/lsp/source"
62990-	"golang.org/x/tools/internal/event"
62991-)
62992-
62993-// selectionRange defines the textDocument/selectionRange feature,
62994-// which, given a list of positions within a file,
62995-// reports a linked list of enclosing syntactic blocks, innermost first.
62996-//
62997-// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_selectionRange.
62998-//
62999-// This feature can be used by a client to implement "expand selection" in a
63000-// language-aware fashion. Multiple input positions are supported to allow
63001-// for multiple cursors, and the entire path up to the whole document is
63002-// returned for each cursor to avoid multiple round-trips when the user is
63003-// likely to issue this command multiple times in quick succession.
63004-func (s *Server) selectionRange(ctx context.Context, params *protocol.SelectionRangeParams) ([]protocol.SelectionRange, error) {
63005-	ctx, done := event.Start(ctx, "lsp.Server.documentSymbol")
63006-	defer done()
63007-
63008-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.UnknownKind)
63009-	defer release()
63010-	if !ok {
63011-		return nil, err
63012-	}
63013-
63014-	pgf, err := snapshot.ParseGo(ctx, fh, source.ParseFull)
63015-	if err != nil {
63016-		return nil, err
63017-	}
63018-
63019-	result := make([]protocol.SelectionRange, len(params.Positions))
63020-	for i, protocolPos := range params.Positions {
63021-		pos, err := pgf.PositionPos(protocolPos)
63022-		if err != nil {
63023-			return nil, err
63024-		}
63025-
63026-		path, _ := astutil.PathEnclosingInterval(pgf.File, pos, pos)
63027-
63028-		tail := &result[i] // tail of the Parent linked list, built head first
63029-
63030-		for j, node := range path {
63031-			rng, err := pgf.NodeRange(node)
63032-			if err != nil {
63033-				return nil, err
63034-			}
63035-
63036-			// Add node to tail.
63037-			if j > 0 {
63038-				tail.Parent = &protocol.SelectionRange{}
63039-				tail = tail.Parent
63040-			}
63041-			tail.Range = rng
63042-		}
63043-	}
63044-
63045-	return result, nil
63046-}
63047diff -urN a/gopls/internal/lsp/semantic.go b/gopls/internal/lsp/semantic.go
63048--- a/gopls/internal/lsp/semantic.go	2000-01-01 00:00:00.000000000 -0000
63049+++ b/gopls/internal/lsp/semantic.go	1970-01-01 00:00:00.000000000 +0000
63050@@ -1,1003 +0,0 @@
63051-// Copyright 2020 The Go Authors. All rights reserved.
63052-// Use of this source code is governed by a BSD-style
63053-// license that can be found in the LICENSE file.
63054-
63055-package lsp
63056-
63057-import (
63058-	"bytes"
63059-	"context"
63060-	"errors"
63061-	"fmt"
63062-	"go/ast"
63063-	"go/token"
63064-	"go/types"
63065-	"log"
63066-	"path/filepath"
63067-	"sort"
63068-	"strings"
63069-	"time"
63070-
63071-	"golang.org/x/tools/gopls/internal/lsp/protocol"
63072-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
63073-	"golang.org/x/tools/gopls/internal/lsp/source"
63074-	"golang.org/x/tools/gopls/internal/lsp/template"
63075-	"golang.org/x/tools/internal/event"
63076-	"golang.org/x/tools/internal/typeparams"
63077-)
63078-
63079-// The LSP says that errors for the semantic token requests should only be returned
63080-// for exceptions (a word not otherwise defined). This code treats a too-large file
63081-// as an exception. On parse errors, the code does what it can.
63082-
63083-// reject full semantic token requests for large files
63084-const maxFullFileSize int = 100000
63085-
63086-// to control comprehensive logging of decisions (gopls semtok foo.go > /dev/null shows log output)
63087-// semDebug should NEVER be true in checked-in code
63088-const semDebug = false
63089-
63090-func (s *Server) semanticTokensFull(ctx context.Context, p *protocol.SemanticTokensParams) (*protocol.SemanticTokens, error) {
63091-	ret, err := s.computeSemanticTokens(ctx, p.TextDocument, nil)
63092-	return ret, err
63093-}
63094-
63095-func (s *Server) semanticTokensFullDelta(ctx context.Context, p *protocol.SemanticTokensDeltaParams) (interface{}, error) {
63096-	return nil, fmt.Errorf("implement SemanticTokensFullDelta")
63097-}
63098-
63099-func (s *Server) semanticTokensRange(ctx context.Context, p *protocol.SemanticTokensRangeParams) (*protocol.SemanticTokens, error) {
63100-	ret, err := s.computeSemanticTokens(ctx, p.TextDocument, &p.Range)
63101-	return ret, err
63102-}
63103-
63104-func (s *Server) semanticTokensRefresh(ctx context.Context) error {
63105-	// in the code, but not in the protocol spec
63106-	return fmt.Errorf("implement SemanticTokensRefresh")
63107-}
63108-
63109-func (s *Server) computeSemanticTokens(ctx context.Context, td protocol.TextDocumentIdentifier, rng *protocol.Range) (*protocol.SemanticTokens, error) {
63110-	ans := protocol.SemanticTokens{
63111-		Data: []uint32{},
63112-	}
63113-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, td.URI, source.UnknownKind)
63114-	defer release()
63115-	if !ok {
63116-		return nil, err
63117-	}
63118-	vv := snapshot.View()
63119-	if !vv.Options().SemanticTokens {
63120-		// return an error, so if the option changes
63121-		// the client won't remember the wrong answer
63122-		return nil, fmt.Errorf("semantictokens are disabled")
63123-	}
63124-	kind := snapshot.View().FileKind(fh)
63125-	if kind == source.Tmpl {
63126-		// this is a little cumbersome to avoid both exporting 'encoded' and its methods
63127-		// and to avoid import cycles
63128-		e := &encoded{
63129-			ctx:            ctx,
63130-			metadataSource: snapshot,
63131-			rng:            rng,
63132-			tokTypes:       s.session.Options().SemanticTypes,
63133-			tokMods:        s.session.Options().SemanticMods,
63134-		}
63135-		add := func(line, start uint32, len uint32) {
63136-			e.add(line, start, len, tokMacro, nil)
63137-		}
63138-		data := func() []uint32 {
63139-			return e.Data()
63140-		}
63141-		return template.SemanticTokens(ctx, snapshot, fh.URI(), add, data)
63142-	}
63143-	if kind != source.Go {
63144-		return nil, nil
63145-	}
63146-	pkg, pgf, err := source.PackageForFile(ctx, snapshot, fh.URI(), source.NarrowestPackage)
63147-	if err != nil {
63148-		return nil, err
63149-	}
63150-
63151-	if rng == nil && len(pgf.Src) > maxFullFileSize {
63152-		err := fmt.Errorf("semantic tokens: file %s too large for full (%d>%d)",
63153-			fh.URI().Filename(), len(pgf.Src), maxFullFileSize)
63154-		return nil, err
63155-	}
63156-	e := &encoded{
63157-		ctx:            ctx,
63158-		metadataSource: snapshot,
63159-		pgf:            pgf,
63160-		rng:            rng,
63161-		ti:             pkg.GetTypesInfo(),
63162-		pkg:            pkg,
63163-		fset:           pkg.FileSet(),
63164-		tokTypes:       s.session.Options().SemanticTypes,
63165-		tokMods:        s.session.Options().SemanticMods,
63166-		noStrings:      vv.Options().NoSemanticString,
63167-		noNumbers:      vv.Options().NoSemanticNumber,
63168-	}
63169-	if err := e.init(); err != nil {
63170-		// e.init should never return an error, unless there's some
63171-		// seemingly impossible race condition
63172-		return nil, err
63173-	}
63174-	e.semantics()
63175-	ans.Data = e.Data()
63176-	// For delta requests, but we've never seen any.
63177-	ans.ResultID = fmt.Sprintf("%v", time.Now())
63178-	return &ans, nil
63179-}
63180-
63181-func (e *encoded) semantics() {
63182-	f := e.pgf.File
63183-	// may not be in range, but harmless
63184-	e.token(f.Package, len("package"), tokKeyword, nil)
63185-	e.token(f.Name.NamePos, len(f.Name.Name), tokNamespace, nil)
63186-	inspect := func(n ast.Node) bool {
63187-		return e.inspector(n)
63188-	}
63189-	for _, d := range f.Decls {
63190-		// only look at the decls that overlap the range
63191-		start, end := d.Pos(), d.End()
63192-		if end <= e.start || start >= e.end {
63193-			continue
63194-		}
63195-		ast.Inspect(d, inspect)
63196-	}
63197-	for _, cg := range f.Comments {
63198-		for _, c := range cg.List {
63199-			if !strings.Contains(c.Text, "\n") {
63200-				e.token(c.Pos(), len(c.Text), tokComment, nil)
63201-				continue
63202-			}
63203-			e.multiline(c.Pos(), c.End(), c.Text, tokComment)
63204-		}
63205-	}
63206-}
63207-
63208-type tokenType string
63209-
63210-const (
63211-	tokNamespace tokenType = "namespace"
63212-	tokType      tokenType = "type"
63213-	tokInterface tokenType = "interface"
63214-	tokTypeParam tokenType = "typeParameter"
63215-	tokParameter tokenType = "parameter"
63216-	tokVariable  tokenType = "variable"
63217-	tokMethod    tokenType = "method"
63218-	tokFunction  tokenType = "function"
63219-	tokKeyword   tokenType = "keyword"
63220-	tokComment   tokenType = "comment"
63221-	tokString    tokenType = "string"
63222-	tokNumber    tokenType = "number"
63223-	tokOperator  tokenType = "operator"
63224-
63225-	tokMacro tokenType = "macro" // for templates
63226-)
63227-
63228-func (e *encoded) token(start token.Pos, leng int, typ tokenType, mods []string) {
63229-	if !start.IsValid() {
63230-		// This is not worth reporting. TODO(pjw): does it still happen?
63231-		return
63232-	}
63233-	if start >= e.end || start+token.Pos(leng) <= e.start {
63234-		return
63235-	}
63236-	// want a line and column from start (in LSP coordinates). Ignore line directives.
63237-	lspRange, err := e.pgf.PosRange(start, start+token.Pos(leng))
63238-	if err != nil {
63239-		event.Error(e.ctx, "failed to convert to range", err)
63240-		return
63241-	}
63242-	if lspRange.End.Line != lspRange.Start.Line {
63243-		// this happens if users are typing at the end of the file, but report nothing
63244-		return
63245-	}
63246-	// token is all on one line
63247-	length := lspRange.End.Character - lspRange.Start.Character
63248-	e.add(lspRange.Start.Line, lspRange.Start.Character, length, typ, mods)
63249-}
63250-
63251-func (e *encoded) add(line, start uint32, len uint32, tok tokenType, mod []string) {
63252-	x := semItem{line, start, len, tok, mod}
63253-	e.items = append(e.items, x)
63254-}
63255-
63256-// semItem represents a token found walking the parse tree
63257-type semItem struct {
63258-	line, start uint32
63259-	len         uint32
63260-	typeStr     tokenType
63261-	mods        []string
63262-}
63263-
63264-type encoded struct {
63265-	// the generated data
63266-	items []semItem
63267-
63268-	noStrings bool
63269-	noNumbers bool
63270-
63271-	ctx context.Context
63272-	// metadataSource is used to resolve imports
63273-	metadataSource    source.MetadataSource
63274-	tokTypes, tokMods []string
63275-	pgf               *source.ParsedGoFile
63276-	rng               *protocol.Range
63277-	ti                *types.Info
63278-	pkg               source.Package
63279-	fset              *token.FileSet
63280-	// allowed starting and ending token.Pos, set by init
63281-	// used to avoid looking at declarations not in range
63282-	start, end token.Pos
63283-	// path from the root of the parse tree, used for debugging
63284-	stack []ast.Node
63285-}
63286-
63287-// convert the stack to a string, for debugging
63288-func (e *encoded) strStack() string {
63289-	msg := []string{"["}
63290-	for i := len(e.stack) - 1; i >= 0; i-- {
63291-		s := e.stack[i]
63292-		msg = append(msg, fmt.Sprintf("%T", s)[5:])
63293-	}
63294-	if len(e.stack) > 0 {
63295-		loc := e.stack[len(e.stack)-1].Pos()
63296-		if _, err := safetoken.Offset(e.pgf.Tok, loc); err != nil {
63297-			msg = append(msg, fmt.Sprintf("invalid position %v for %s", loc, e.pgf.URI))
63298-		} else {
63299-			add := safetoken.Position(e.pgf.Tok, loc)
63300-			nm := filepath.Base(add.Filename)
63301-			msg = append(msg, fmt.Sprintf("(%s:%d,col:%d)", nm, add.Line, add.Column))
63302-		}
63303-	}
63304-	msg = append(msg, "]")
63305-	return strings.Join(msg, " ")
63306-}
63307-
63308-// find the line in the source
63309-func (e *encoded) srcLine(x ast.Node) string {
63310-	file := e.pgf.Tok
63311-	line := file.Line(x.Pos())
63312-	start, err := safetoken.Offset(file, file.LineStart(line))
63313-	if err != nil {
63314-		return ""
63315-	}
63316-	end := start
63317-	for ; end < len(e.pgf.Src) && e.pgf.Src[end] != '\n'; end++ {
63318-
63319-	}
63320-	ans := e.pgf.Src[start:end]
63321-	return string(ans)
63322-}
63323-
63324-func (e *encoded) inspector(n ast.Node) bool {
63325-	pop := func() {
63326-		e.stack = e.stack[:len(e.stack)-1]
63327-	}
63328-	if n == nil {
63329-		pop()
63330-		return true
63331-	}
63332-	e.stack = append(e.stack, n)
63333-	switch x := n.(type) {
63334-	case *ast.ArrayType:
63335-	case *ast.AssignStmt:
63336-		e.token(x.TokPos, len(x.Tok.String()), tokOperator, nil)
63337-	case *ast.BasicLit:
63338-		if strings.Contains(x.Value, "\n") {
63339-			// has to be a string.
63340-			e.multiline(x.Pos(), x.End(), x.Value, tokString)
63341-			break
63342-		}
63343-		ln := len(x.Value)
63344-		what := tokNumber
63345-		if x.Kind == token.STRING {
63346-			what = tokString
63347-		}
63348-		e.token(x.Pos(), ln, what, nil)
63349-	case *ast.BinaryExpr:
63350-		e.token(x.OpPos, len(x.Op.String()), tokOperator, nil)
63351-	case *ast.BlockStmt:
63352-	case *ast.BranchStmt:
63353-		e.token(x.TokPos, len(x.Tok.String()), tokKeyword, nil)
63354-		// There's no semantic encoding for labels
63355-	case *ast.CallExpr:
63356-		if x.Ellipsis != token.NoPos {
63357-			e.token(x.Ellipsis, len("..."), tokOperator, nil)
63358-		}
63359-	case *ast.CaseClause:
63360-		iam := "case"
63361-		if x.List == nil {
63362-			iam = "default"
63363-		}
63364-		e.token(x.Case, len(iam), tokKeyword, nil)
63365-	case *ast.ChanType:
63366-		// chan | chan <- | <- chan
63367-		switch {
63368-		case x.Arrow == token.NoPos:
63369-			e.token(x.Begin, len("chan"), tokKeyword, nil)
63370-		case x.Arrow == x.Begin:
63371-			e.token(x.Arrow, 2, tokOperator, nil)
63372-			pos := e.findKeyword("chan", x.Begin+2, x.Value.Pos())
63373-			e.token(pos, len("chan"), tokKeyword, nil)
63374-		case x.Arrow != x.Begin:
63375-			e.token(x.Begin, len("chan"), tokKeyword, nil)
63376-			e.token(x.Arrow, 2, tokOperator, nil)
63377-		}
63378-	case *ast.CommClause:
63379-		iam := len("case")
63380-		if x.Comm == nil {
63381-			iam = len("default")
63382-		}
63383-		e.token(x.Case, iam, tokKeyword, nil)
63384-	case *ast.CompositeLit:
63385-	case *ast.DeclStmt:
63386-	case *ast.DeferStmt:
63387-		e.token(x.Defer, len("defer"), tokKeyword, nil)
63388-	case *ast.Ellipsis:
63389-		e.token(x.Ellipsis, len("..."), tokOperator, nil)
63390-	case *ast.EmptyStmt:
63391-	case *ast.ExprStmt:
63392-	case *ast.Field:
63393-	case *ast.FieldList:
63394-	case *ast.ForStmt:
63395-		e.token(x.For, len("for"), tokKeyword, nil)
63396-	case *ast.FuncDecl:
63397-	case *ast.FuncLit:
63398-	case *ast.FuncType:
63399-		if x.Func != token.NoPos {
63400-			e.token(x.Func, len("func"), tokKeyword, nil)
63401-		}
63402-	case *ast.GenDecl:
63403-		e.token(x.TokPos, len(x.Tok.String()), tokKeyword, nil)
63404-	case *ast.GoStmt:
63405-		e.token(x.Go, len("go"), tokKeyword, nil)
63406-	case *ast.Ident:
63407-		e.ident(x)
63408-	case *ast.IfStmt:
63409-		e.token(x.If, len("if"), tokKeyword, nil)
63410-		if x.Else != nil {
63411-			// x.Body.End() or x.Body.End()+1, not that it matters
63412-			pos := e.findKeyword("else", x.Body.End(), x.Else.Pos())
63413-			e.token(pos, len("else"), tokKeyword, nil)
63414-		}
63415-	case *ast.ImportSpec:
63416-		e.importSpec(x)
63417-		pop()
63418-		return false
63419-	case *ast.IncDecStmt:
63420-		e.token(x.TokPos, len(x.Tok.String()), tokOperator, nil)
63421-	case *ast.IndexExpr:
63422-	case *typeparams.IndexListExpr:
63423-	case *ast.InterfaceType:
63424-		e.token(x.Interface, len("interface"), tokKeyword, nil)
63425-	case *ast.KeyValueExpr:
63426-	case *ast.LabeledStmt:
63427-	case *ast.MapType:
63428-		e.token(x.Map, len("map"), tokKeyword, nil)
63429-	case *ast.ParenExpr:
63430-	case *ast.RangeStmt:
63431-		e.token(x.For, len("for"), tokKeyword, nil)
63432-		// x.TokPos == token.NoPos is legal (for range foo {})
63433-		offset := x.TokPos
63434-		if offset == token.NoPos {
63435-			offset = x.For
63436-		}
63437-		pos := e.findKeyword("range", offset, x.X.Pos())
63438-		e.token(pos, len("range"), tokKeyword, nil)
63439-	case *ast.ReturnStmt:
63440-		e.token(x.Return, len("return"), tokKeyword, nil)
63441-	case *ast.SelectStmt:
63442-		e.token(x.Select, len("select"), tokKeyword, nil)
63443-	case *ast.SelectorExpr:
63444-	case *ast.SendStmt:
63445-		e.token(x.Arrow, len("<-"), tokOperator, nil)
63446-	case *ast.SliceExpr:
63447-	case *ast.StarExpr:
63448-		e.token(x.Star, len("*"), tokOperator, nil)
63449-	case *ast.StructType:
63450-		e.token(x.Struct, len("struct"), tokKeyword, nil)
63451-	case *ast.SwitchStmt:
63452-		e.token(x.Switch, len("switch"), tokKeyword, nil)
63453-	case *ast.TypeAssertExpr:
63454-		if x.Type == nil {
63455-			pos := e.findKeyword("type", x.Lparen, x.Rparen)
63456-			e.token(pos, len("type"), tokKeyword, nil)
63457-		}
63458-	case *ast.TypeSpec:
63459-	case *ast.TypeSwitchStmt:
63460-		e.token(x.Switch, len("switch"), tokKeyword, nil)
63461-	case *ast.UnaryExpr:
63462-		e.token(x.OpPos, len(x.Op.String()), tokOperator, nil)
63463-	case *ast.ValueSpec:
63464-	// things only seen with parsing or type errors, so ignore them
63465-	case *ast.BadDecl, *ast.BadExpr, *ast.BadStmt:
63466-		return true
63467-	// not going to see these
63468-	case *ast.File, *ast.Package:
63469-		e.unexpected(fmt.Sprintf("implement %T %s", x, safetoken.Position(e.pgf.Tok, x.Pos())))
63470-	// other things we knowingly ignore
63471-	case *ast.Comment, *ast.CommentGroup:
63472-		pop()
63473-		return false
63474-	default:
63475-		e.unexpected(fmt.Sprintf("failed to implement %T", x))
63476-	}
63477-	return true
63478-}
63479-
63480-func (e *encoded) ident(x *ast.Ident) {
63481-	if e.ti == nil {
63482-		what, mods := e.unkIdent(x)
63483-		if what != "" {
63484-			e.token(x.Pos(), len(x.String()), what, mods)
63485-		}
63486-		if semDebug {
63487-			log.Printf(" nil %s/nil/nil %q %v %s", x.String(), what, mods, e.strStack())
63488-		}
63489-		return
63490-	}
63491-	def := e.ti.Defs[x]
63492-	if def != nil {
63493-		what, mods := e.definitionFor(x, def)
63494-		if what != "" {
63495-			e.token(x.Pos(), len(x.String()), what, mods)
63496-		}
63497-		if semDebug {
63498-			log.Printf(" for %s/%T/%T got %s %v (%s)", x.String(), def, def.Type(), what, mods, e.strStack())
63499-		}
63500-		return
63501-	}
63502-	use := e.ti.Uses[x]
63503-	tok := func(pos token.Pos, lng int, tok tokenType, mods []string) {
63504-		e.token(pos, lng, tok, mods)
63505-		q := "nil"
63506-		if use != nil {
63507-			q = fmt.Sprintf("%T", use.Type())
63508-		}
63509-		if semDebug {
63510-			log.Printf(" use %s/%T/%s got %s %v (%s)", x.String(), use, q, tok, mods, e.strStack())
63511-		}
63512-	}
63513-
63514-	switch y := use.(type) {
63515-	case nil:
63516-		what, mods := e.unkIdent(x)
63517-		if what != "" {
63518-			tok(x.Pos(), len(x.String()), what, mods)
63519-		} else if semDebug {
63520-			// tok() wasn't called, so didn't log
63521-			log.Printf(" nil %s/%T/nil %q %v (%s)", x.String(), use, what, mods, e.strStack())
63522-		}
63523-		return
63524-	case *types.Builtin:
63525-		tok(x.NamePos, len(x.Name), tokFunction, []string{"defaultLibrary"})
63526-	case *types.Const:
63527-		mods := []string{"readonly"}
63528-		tt := y.Type()
63529-		if _, ok := tt.(*types.Basic); ok {
63530-			tok(x.Pos(), len(x.String()), tokVariable, mods)
63531-			break
63532-		}
63533-		if ttx, ok := tt.(*types.Named); ok {
63534-			if x.String() == "iota" {
63535-				e.unexpected(fmt.Sprintf("iota:%T", ttx))
63536-			}
63537-			if _, ok := ttx.Underlying().(*types.Basic); ok {
63538-				tok(x.Pos(), len(x.String()), tokVariable, mods)
63539-				break
63540-			}
63541-			e.unexpected(fmt.Sprintf("%q/%T", x.String(), tt))
63542-		}
63543-		// can this happen? Don't think so
63544-		e.unexpected(fmt.Sprintf("%s %T %#v", x.String(), tt, tt))
63545-	case *types.Func:
63546-		tok(x.Pos(), len(x.Name), tokFunction, nil)
63547-	case *types.Label:
63548-		// nothing to map it to
63549-	case *types.Nil:
63550-		// nil is a predeclared identifier
63551-		tok(x.Pos(), len("nil"), tokVariable, []string{"readonly", "defaultLibrary"})
63552-	case *types.PkgName:
63553-		tok(x.Pos(), len(x.Name), tokNamespace, nil)
63554-	case *types.TypeName: // could be a tokTpeParam
63555-		var mods []string
63556-		if _, ok := y.Type().(*types.Basic); ok {
63557-			mods = []string{"defaultLibrary"}
63558-		} else if _, ok := y.Type().(*typeparams.TypeParam); ok {
63559-			tok(x.Pos(), len(x.String()), tokTypeParam, mods)
63560-			break
63561-		}
63562-		tok(x.Pos(), len(x.String()), tokType, mods)
63563-	case *types.Var:
63564-		if isSignature(y) {
63565-			tok(x.Pos(), len(x.Name), tokFunction, nil)
63566-		} else if e.isParam(use.Pos()) {
63567-			// variable, unless use.pos is the pos of a Field in an ancestor FuncDecl
63568-			// or FuncLit and then it's a parameter
63569-			tok(x.Pos(), len(x.Name), tokParameter, nil)
63570-		} else {
63571-			tok(x.Pos(), len(x.Name), tokVariable, nil)
63572-		}
63573-
63574-	default:
63575-		// can't happen
63576-		if use == nil {
63577-			msg := fmt.Sprintf("%#v %#v %#v", x, e.ti.Defs[x], e.ti.Uses[x])
63578-			e.unexpected(msg)
63579-		}
63580-		if use.Type() != nil {
63581-			e.unexpected(fmt.Sprintf("%s %T/%T,%#v", x.String(), use, use.Type(), use))
63582-		} else {
63583-			e.unexpected(fmt.Sprintf("%s %T", x.String(), use))
63584-		}
63585-	}
63586-}
63587-
63588-func (e *encoded) isParam(pos token.Pos) bool {
63589-	for i := len(e.stack) - 1; i >= 0; i-- {
63590-		switch n := e.stack[i].(type) {
63591-		case *ast.FuncDecl:
63592-			for _, f := range n.Type.Params.List {
63593-				for _, id := range f.Names {
63594-					if id.Pos() == pos {
63595-						return true
63596-					}
63597-				}
63598-			}
63599-		case *ast.FuncLit:
63600-			for _, f := range n.Type.Params.List {
63601-				for _, id := range f.Names {
63602-					if id.Pos() == pos {
63603-						return true
63604-					}
63605-				}
63606-			}
63607-		}
63608-	}
63609-	return false
63610-}
63611-
63612-func isSignature(use types.Object) bool {
63613-	if _, ok := use.(*types.Var); !ok {
63614-		return false
63615-	}
63616-	v := use.Type()
63617-	if v == nil {
63618-		return false
63619-	}
63620-	if _, ok := v.(*types.Signature); ok {
63621-		return true
63622-	}
63623-	return false
63624-}
63625-
63626-// both e.ti.Defs and e.ti.Uses are nil. use the parse stack.
63627-// a lot of these only happen when the package doesn't compile
63628-// but in that case it is all best-effort from the parse tree
63629-func (e *encoded) unkIdent(x *ast.Ident) (tokenType, []string) {
63630-	def := []string{"definition"}
63631-	n := len(e.stack) - 2 // parent of Ident
63632-	if n < 0 {
63633-		e.unexpected("no stack?")
63634-		return "", nil
63635-	}
63636-	switch nd := e.stack[n].(type) {
63637-	case *ast.BinaryExpr, *ast.UnaryExpr, *ast.ParenExpr, *ast.StarExpr,
63638-		*ast.IncDecStmt, *ast.SliceExpr, *ast.ExprStmt, *ast.IndexExpr,
63639-		*ast.ReturnStmt, *ast.ChanType, *ast.SendStmt,
63640-		*ast.ForStmt,      // possibly incomplete
63641-		*ast.IfStmt,       /* condition */
63642-		*ast.KeyValueExpr: // either key or value
63643-		return tokVariable, nil
63644-	case *typeparams.IndexListExpr:
63645-		return tokVariable, nil
63646-	case *ast.Ellipsis:
63647-		return tokType, nil
63648-	case *ast.CaseClause:
63649-		if n-2 >= 0 {
63650-			if _, ok := e.stack[n-2].(*ast.TypeSwitchStmt); ok {
63651-				return tokType, nil
63652-			}
63653-		}
63654-		return tokVariable, nil
63655-	case *ast.ArrayType:
63656-		if x == nd.Len {
63657-			// or maybe a Type Param, but we can't just from the parse tree
63658-			return tokVariable, nil
63659-		} else {
63660-			return tokType, nil
63661-		}
63662-	case *ast.MapType:
63663-		return tokType, nil
63664-	case *ast.CallExpr:
63665-		if x == nd.Fun {
63666-			return tokFunction, nil
63667-		}
63668-		return tokVariable, nil
63669-	case *ast.SwitchStmt:
63670-		return tokVariable, nil
63671-	case *ast.TypeAssertExpr:
63672-		if x == nd.X {
63673-			return tokVariable, nil
63674-		} else if x == nd.Type {
63675-			return tokType, nil
63676-		}
63677-	case *ast.ValueSpec:
63678-		for _, p := range nd.Names {
63679-			if p == x {
63680-				return tokVariable, def
63681-			}
63682-		}
63683-		for _, p := range nd.Values {
63684-			if p == x {
63685-				return tokVariable, nil
63686-			}
63687-		}
63688-		return tokType, nil
63689-	case *ast.SelectorExpr: // e.ti.Selections[nd] is nil, so no help
63690-		if n-1 >= 0 {
63691-			if ce, ok := e.stack[n-1].(*ast.CallExpr); ok {
63692-				// ... CallExpr SelectorExpr Ident (_.x())
63693-				if ce.Fun == nd && nd.Sel == x {
63694-					return tokFunction, nil
63695-				}
63696-			}
63697-		}
63698-		return tokVariable, nil
63699-	case *ast.AssignStmt:
63700-		for _, p := range nd.Lhs {
63701-			// x := ..., or x = ...
63702-			if p == x {
63703-				if nd.Tok != token.DEFINE {
63704-					def = nil
63705-				}
63706-				return tokVariable, def // '_' in _ = ...
63707-			}
63708-		}
63709-		// RHS, = x
63710-		return tokVariable, nil
63711-	case *ast.TypeSpec: // it's a type if it is either the Name or the Type
63712-		if x == nd.Type {
63713-			def = nil
63714-		}
63715-		return tokType, def
63716-	case *ast.Field:
63717-		// ident could be type in a field, or a method in an interface type, or a variable
63718-		if x == nd.Type {
63719-			return tokType, nil
63720-		}
63721-		if n-2 >= 0 {
63722-			_, okit := e.stack[n-2].(*ast.InterfaceType)
63723-			_, okfl := e.stack[n-1].(*ast.FieldList)
63724-			if okit && okfl {
63725-				return tokMethod, def
63726-			}
63727-		}
63728-		return tokVariable, nil
63729-	case *ast.LabeledStmt, *ast.BranchStmt:
63730-		// nothing to report
63731-	case *ast.CompositeLit:
63732-		if nd.Type == x {
63733-			return tokType, nil
63734-		}
63735-		return tokVariable, nil
63736-	case *ast.RangeStmt:
63737-		if nd.Tok != token.DEFINE {
63738-			def = nil
63739-		}
63740-		return tokVariable, def
63741-	case *ast.FuncDecl:
63742-		return tokFunction, def
63743-	default:
63744-		msg := fmt.Sprintf("%T undexpected: %s %s%q", nd, x.Name, e.strStack(), e.srcLine(x))
63745-		e.unexpected(msg)
63746-	}
63747-	return "", nil
63748-}
63749-
63750-func isDeprecated(n *ast.CommentGroup) bool {
63751-	if n == nil {
63752-		return false
63753-	}
63754-	for _, c := range n.List {
63755-		if strings.HasPrefix(c.Text, "// Deprecated") {
63756-			return true
63757-		}
63758-	}
63759-	return false
63760-}
63761-
63762-func (e *encoded) definitionFor(x *ast.Ident, def types.Object) (tokenType, []string) {
63763-	// PJW: def == types.Label? probably a nothing
63764-	// PJW: look into replacing these syntactic tests with types more generally
63765-	mods := []string{"definition"}
63766-	for i := len(e.stack) - 1; i >= 0; i-- {
63767-		s := e.stack[i]
63768-		switch y := s.(type) {
63769-		case *ast.AssignStmt, *ast.RangeStmt:
63770-			if x.Name == "_" {
63771-				return "", nil // not really a variable
63772-			}
63773-			return tokVariable, mods
63774-		case *ast.GenDecl:
63775-			if isDeprecated(y.Doc) {
63776-				mods = append(mods, "deprecated")
63777-			}
63778-			if y.Tok == token.CONST {
63779-				mods = append(mods, "readonly")
63780-			}
63781-			return tokVariable, mods
63782-		case *ast.FuncDecl:
63783-			// If x is immediately under a FuncDecl, it is a function or method
63784-			if i == len(e.stack)-2 {
63785-				if isDeprecated(y.Doc) {
63786-					mods = append(mods, "deprecated")
63787-				}
63788-				if y.Recv != nil {
63789-					return tokMethod, mods
63790-				}
63791-				return tokFunction, mods
63792-			}
63793-			// if x < ... < FieldList < FuncDecl, this is the receiver, a variable
63794-			// PJW: maybe not. it might be a typeparameter in the type of the receiver
63795-			if _, ok := e.stack[i+1].(*ast.FieldList); ok {
63796-				if _, ok := def.(*types.TypeName); ok {
63797-					return tokTypeParam, mods
63798-				}
63799-				return tokVariable, nil
63800-			}
63801-			// if x < ... < FieldList < FuncType < FuncDecl, this is a param
63802-			return tokParameter, mods
63803-		case *ast.FuncType: // is it in the TypeParams?
63804-			if isTypeParam(x, y) {
63805-				return tokTypeParam, mods
63806-			}
63807-			return tokParameter, mods
63808-		case *ast.InterfaceType:
63809-			return tokMethod, mods
63810-		case *ast.TypeSpec:
63811-			// GenDecl/Typespec/FuncType/FieldList/Field/Ident
63812-			// (type A func(b uint64)) (err error)
63813-			// b and err should not be tokType, but tokVaraible
63814-			// and in GenDecl/TpeSpec/StructType/FieldList/Field/Ident
63815-			// (type A struct{b uint64}
63816-			// but on type B struct{C}), C is a type, but is not being defined.
63817-			// GenDecl/TypeSpec/FieldList/Field/Ident is a typeParam
63818-			if _, ok := e.stack[i+1].(*ast.FieldList); ok {
63819-				return tokTypeParam, mods
63820-			}
63821-			fldm := e.stack[len(e.stack)-2]
63822-			if fld, ok := fldm.(*ast.Field); ok {
63823-				// if len(fld.names) == 0 this is a tokType, being used
63824-				if len(fld.Names) == 0 {
63825-					return tokType, nil
63826-				}
63827-				return tokVariable, mods
63828-			}
63829-			return tokType, mods
63830-		}
63831-	}
63832-	// can't happen
63833-	msg := fmt.Sprintf("failed to find the decl for %s", safetoken.Position(e.pgf.Tok, x.Pos()))
63834-	e.unexpected(msg)
63835-	return "", []string{""}
63836-}
63837-
63838-func isTypeParam(x *ast.Ident, y *ast.FuncType) bool {
63839-	tp := typeparams.ForFuncType(y)
63840-	if tp == nil {
63841-		return false
63842-	}
63843-	for _, p := range tp.List {
63844-		for _, n := range p.Names {
63845-			if x == n {
63846-				return true
63847-			}
63848-		}
63849-	}
63850-	return false
63851-}
63852-
63853-func (e *encoded) multiline(start, end token.Pos, val string, tok tokenType) {
63854-	f := e.fset.File(start)
63855-	// the hard part is finding the lengths of lines. include the \n
63856-	leng := func(line int) int {
63857-		n := f.LineStart(line)
63858-		if line >= f.LineCount() {
63859-			return f.Size() - int(n)
63860-		}
63861-		return int(f.LineStart(line+1) - n)
63862-	}
63863-	spos := safetoken.StartPosition(e.fset, start)
63864-	epos := safetoken.EndPosition(e.fset, end)
63865-	sline := spos.Line
63866-	eline := epos.Line
63867-	// first line is from spos.Column to end
63868-	e.token(start, leng(sline)-spos.Column, tok, nil) // leng(sline)-1 - (spos.Column-1)
63869-	for i := sline + 1; i < eline; i++ {
63870-		// intermediate lines are from 1 to end
63871-		e.token(f.LineStart(i), leng(i)-1, tok, nil) // avoid the newline
63872-	}
63873-	// last line is from 1 to epos.Column
63874-	e.token(f.LineStart(eline), epos.Column-1, tok, nil) // columns are 1-based
63875-}
63876-
63877-// findKeyword finds a keyword rather than guessing its location
63878-func (e *encoded) findKeyword(keyword string, start, end token.Pos) token.Pos {
63879-	offset := int(start) - e.pgf.Tok.Base()
63880-	last := int(end) - e.pgf.Tok.Base()
63881-	buf := e.pgf.Src
63882-	idx := bytes.Index(buf[offset:last], []byte(keyword))
63883-	if idx != -1 {
63884-		return start + token.Pos(idx)
63885-	}
63886-	//(in unparsable programs: type _ <-<-chan int)
63887-	e.unexpected(fmt.Sprintf("not found:%s %v", keyword, safetoken.StartPosition(e.fset, start)))
63888-	return token.NoPos
63889-}
63890-
63891-func (e *encoded) init() error {
63892-	e.start = token.Pos(e.pgf.Tok.Base())
63893-	e.end = e.start + token.Pos(e.pgf.Tok.Size())
63894-	if e.rng == nil {
63895-		return nil
63896-	}
63897-	span, err := e.pgf.Mapper.RangeSpan(*e.rng)
63898-	if err != nil {
63899-		return fmt.Errorf("range span (%w) error for %s", err, e.pgf.File.Name)
63900-	}
63901-	e.end = e.start + token.Pos(span.End().Offset())
63902-	e.start += token.Pos(span.Start().Offset())
63903-	return nil
63904-}
63905-
63906-func (e *encoded) Data() []uint32 {
63907-	// binary operators, at least, will be out of order
63908-	sort.Slice(e.items, func(i, j int) bool {
63909-		if e.items[i].line != e.items[j].line {
63910-			return e.items[i].line < e.items[j].line
63911-		}
63912-		return e.items[i].start < e.items[j].start
63913-	})
63914-	typeMap, modMap := e.maps()
63915-	// each semantic token needs five values
63916-	// (see Integer Encoding for Tokens in the LSP spec)
63917-	x := make([]uint32, 5*len(e.items))
63918-	var j int
63919-	var last semItem
63920-	for i := 0; i < len(e.items); i++ {
63921-		item := e.items[i]
63922-		typ, ok := typeMap[item.typeStr]
63923-		if !ok {
63924-			continue // client doesn't want typeStr
63925-		}
63926-		if item.typeStr == tokString && e.noStrings {
63927-			continue
63928-		}
63929-		if item.typeStr == tokNumber && e.noNumbers {
63930-			continue
63931-		}
63932-		if j == 0 {
63933-			x[0] = e.items[0].line
63934-		} else {
63935-			x[j] = item.line - last.line
63936-		}
63937-		x[j+1] = item.start
63938-		if j > 0 && x[j] == 0 {
63939-			x[j+1] = item.start - last.start
63940-		}
63941-		x[j+2] = item.len
63942-		x[j+3] = uint32(typ)
63943-		mask := 0
63944-		for _, s := range item.mods {
63945-			// modMap[s] is 0 if the client doesn't want this modifier
63946-			mask |= modMap[s]
63947-		}
63948-		x[j+4] = uint32(mask)
63949-		j += 5
63950-		last = item
63951-	}
63952-	return x[:j]
63953-}
63954-
63955-func (e *encoded) importSpec(d *ast.ImportSpec) {
63956-	// a local package name or the last component of the Path
63957-	if d.Name != nil {
63958-		nm := d.Name.String()
63959-		if nm != "_" && nm != "." {
63960-			e.token(d.Name.Pos(), len(nm), tokNamespace, nil)
63961-		}
63962-		return // don't mark anything for . or _
63963-	}
63964-	importPath := source.UnquoteImportPath(d)
63965-	if importPath == "" {
63966-		return
63967-	}
63968-	// Import strings are implementation defined. Try to match with parse information.
63969-	depID := e.pkg.Metadata().DepsByImpPath[importPath]
63970-	if depID == "" {
63971-		return
63972-	}
63973-	depMD := e.metadataSource.Metadata(depID)
63974-	if depMD == nil {
63975-		// unexpected, but impact is that maybe some import is not colored
63976-		return
63977-	}
63978-	// Check whether the original literal contains the package's declared name.
63979-	j := strings.LastIndex(d.Path.Value, string(depMD.Name))
63980-	if j == -1 {
63981-		// Package name does not match import path, so there is nothing to report.
63982-		return
63983-	}
63984-	// Report virtual declaration at the position of the substring.
63985-	start := d.Path.Pos() + token.Pos(j)
63986-	e.token(start, len(depMD.Name), tokNamespace, nil)
63987-}
63988-
63989-// log unexpected state
63990-func (e *encoded) unexpected(msg string) {
63991-	if semDebug {
63992-		panic(msg)
63993-	}
63994-	event.Error(e.ctx, e.strStack(), errors.New(msg))
63995-}
63996-
63997-// SemType returns a string equivalent of the type, for gopls semtok
63998-func SemType(n int) string {
63999-	tokTypes := SemanticTypes()
64000-	tokMods := SemanticModifiers()
64001-	if n >= 0 && n < len(tokTypes) {
64002-		return tokTypes[n]
64003-	}
64004-	// not found for some reason
64005-	return fmt.Sprintf("?%d[%d,%d]?", n, len(tokTypes), len(tokMods))
64006-}
64007-
64008-// SemMods returns the []string equivalent of the mods, for gopls semtok.
64009-func SemMods(n int) []string {
64010-	tokMods := SemanticModifiers()
64011-	mods := []string{}
64012-	for i := 0; i < len(tokMods); i++ {
64013-		if (n & (1 << uint(i))) != 0 {
64014-			mods = append(mods, tokMods[i])
64015-		}
64016-	}
64017-	return mods
64018-}
64019-
64020-func (e *encoded) maps() (map[tokenType]int, map[string]int) {
64021-	tmap := make(map[tokenType]int)
64022-	mmap := make(map[string]int)
64023-	for i, t := range e.tokTypes {
64024-		tmap[tokenType(t)] = i
64025-	}
64026-	for i, m := range e.tokMods {
64027-		mmap[m] = 1 << uint(i) // go 1.12 compatibility
64028-	}
64029-	return tmap, mmap
64030-}
64031-
64032-// SemanticTypes to use in case there is no client, as in the command line, or tests
64033-func SemanticTypes() []string {
64034-	return semanticTypes[:]
64035-}
64036-
64037-// SemanticModifiers to use in case there is no client.
64038-func SemanticModifiers() []string {
64039-	return semanticModifiers[:]
64040-}
64041-
64042-var (
64043-	semanticTypes = [...]string{
64044-		"namespace", "type", "class", "enum", "interface",
64045-		"struct", "typeParameter", "parameter", "variable", "property", "enumMember",
64046-		"event", "function", "method", "macro", "keyword", "modifier", "comment",
64047-		"string", "number", "regexp", "operator",
64048-	}
64049-	semanticModifiers = [...]string{
64050-		"declaration", "definition", "readonly", "static",
64051-		"deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary",
64052-	}
64053-)
64054diff -urN a/gopls/internal/lsp/server_gen.go b/gopls/internal/lsp/server_gen.go
64055--- a/gopls/internal/lsp/server_gen.go	2000-01-01 00:00:00.000000000 -0000
64056+++ b/gopls/internal/lsp/server_gen.go	1970-01-01 00:00:00.000000000 +0000
64057@@ -1,301 +0,0 @@
64058-// Copyright 2021 The Go Authors. All rights reserved.
64059-// Use of this source code is governed by a BSD-style
64060-// license that can be found in the LICENSE file.
64061-
64062-package lsp
64063-
64064-// code generated by helper. DO NOT EDIT.
64065-
64066-import (
64067-	"context"
64068-
64069-	"golang.org/x/tools/gopls/internal/lsp/protocol"
64070-)
64071-
64072-func (s *Server) CodeAction(ctx context.Context, params *protocol.CodeActionParams) ([]protocol.CodeAction, error) {
64073-	return s.codeAction(ctx, params)
64074-}
64075-
64076-func (s *Server) CodeLens(ctx context.Context, params *protocol.CodeLensParams) ([]protocol.CodeLens, error) {
64077-	return s.codeLens(ctx, params)
64078-}
64079-
64080-func (s *Server) ColorPresentation(context.Context, *protocol.ColorPresentationParams) ([]protocol.ColorPresentation, error) {
64081-	return nil, notImplemented("ColorPresentation")
64082-}
64083-
64084-func (s *Server) Completion(ctx context.Context, params *protocol.CompletionParams) (*protocol.CompletionList, error) {
64085-	return s.completion(ctx, params)
64086-}
64087-
64088-func (s *Server) Declaration(context.Context, *protocol.DeclarationParams) (*protocol.Or_textDocument_declaration, error) {
64089-	return nil, notImplemented("Declaration")
64090-}
64091-
64092-func (s *Server) Definition(ctx context.Context, params *protocol.DefinitionParams) ([]protocol.Location, error) {
64093-	return s.definition(ctx, params)
64094-}
64095-
64096-func (s *Server) Diagnostic(context.Context, *string) (*string, error) {
64097-	return nil, notImplemented("Diagnostic")
64098-}
64099-
64100-func (s *Server) DiagnosticWorkspace(context.Context, *protocol.WorkspaceDiagnosticParams) (*protocol.WorkspaceDiagnosticReport, error) {
64101-	return nil, notImplemented("DiagnosticWorkspace")
64102-}
64103-
64104-func (s *Server) DidChange(ctx context.Context, params *protocol.DidChangeTextDocumentParams) error {
64105-	return s.didChange(ctx, params)
64106-}
64107-
64108-func (s *Server) DidChangeConfiguration(ctx context.Context, _gen *protocol.DidChangeConfigurationParams) error {
64109-	return s.didChangeConfiguration(ctx, _gen)
64110-}
64111-
64112-func (s *Server) DidChangeNotebookDocument(context.Context, *protocol.DidChangeNotebookDocumentParams) error {
64113-	return notImplemented("DidChangeNotebookDocument")
64114-}
64115-
64116-func (s *Server) DidChangeWatchedFiles(ctx context.Context, params *protocol.DidChangeWatchedFilesParams) error {
64117-	return s.didChangeWatchedFiles(ctx, params)
64118-}
64119-
64120-func (s *Server) DidChangeWorkspaceFolders(ctx context.Context, params *protocol.DidChangeWorkspaceFoldersParams) error {
64121-	return s.didChangeWorkspaceFolders(ctx, params)
64122-}
64123-
64124-func (s *Server) DidClose(ctx context.Context, params *protocol.DidCloseTextDocumentParams) error {
64125-	return s.didClose(ctx, params)
64126-}
64127-
64128-func (s *Server) DidCloseNotebookDocument(context.Context, *protocol.DidCloseNotebookDocumentParams) error {
64129-	return notImplemented("DidCloseNotebookDocument")
64130-}
64131-
64132-func (s *Server) DidCreateFiles(context.Context, *protocol.CreateFilesParams) error {
64133-	return notImplemented("DidCreateFiles")
64134-}
64135-
64136-func (s *Server) DidDeleteFiles(context.Context, *protocol.DeleteFilesParams) error {
64137-	return notImplemented("DidDeleteFiles")
64138-}
64139-
64140-func (s *Server) DidOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error {
64141-	return s.didOpen(ctx, params)
64142-}
64143-
64144-func (s *Server) DidOpenNotebookDocument(context.Context, *protocol.DidOpenNotebookDocumentParams) error {
64145-	return notImplemented("DidOpenNotebookDocument")
64146-}
64147-
64148-func (s *Server) DidRenameFiles(context.Context, *protocol.RenameFilesParams) error {
64149-	return notImplemented("DidRenameFiles")
64150-}
64151-
64152-func (s *Server) DidSave(ctx context.Context, params *protocol.DidSaveTextDocumentParams) error {
64153-	return s.didSave(ctx, params)
64154-}
64155-
64156-func (s *Server) DidSaveNotebookDocument(context.Context, *protocol.DidSaveNotebookDocumentParams) error {
64157-	return notImplemented("DidSaveNotebookDocument")
64158-}
64159-
64160-func (s *Server) DocumentColor(context.Context, *protocol.DocumentColorParams) ([]protocol.ColorInformation, error) {
64161-	return nil, notImplemented("DocumentColor")
64162-}
64163-
64164-func (s *Server) DocumentHighlight(ctx context.Context, params *protocol.DocumentHighlightParams) ([]protocol.DocumentHighlight, error) {
64165-	return s.documentHighlight(ctx, params)
64166-}
64167-
64168-func (s *Server) DocumentLink(ctx context.Context, params *protocol.DocumentLinkParams) ([]protocol.DocumentLink, error) {
64169-	return s.documentLink(ctx, params)
64170-}
64171-
64172-func (s *Server) DocumentSymbol(ctx context.Context, params *protocol.DocumentSymbolParams) ([]interface{}, error) {
64173-	return s.documentSymbol(ctx, params)
64174-}
64175-
64176-func (s *Server) ExecuteCommand(ctx context.Context, params *protocol.ExecuteCommandParams) (interface{}, error) {
64177-	return s.executeCommand(ctx, params)
64178-}
64179-
64180-func (s *Server) Exit(ctx context.Context) error {
64181-	return s.exit(ctx)
64182-}
64183-
64184-func (s *Server) FoldingRange(ctx context.Context, params *protocol.FoldingRangeParams) ([]protocol.FoldingRange, error) {
64185-	return s.foldingRange(ctx, params)
64186-}
64187-
64188-func (s *Server) Formatting(ctx context.Context, params *protocol.DocumentFormattingParams) ([]protocol.TextEdit, error) {
64189-	return s.formatting(ctx, params)
64190-}
64191-
64192-func (s *Server) Hover(ctx context.Context, params *protocol.HoverParams) (*protocol.Hover, error) {
64193-	return s.hover(ctx, params)
64194-}
64195-
64196-func (s *Server) Implementation(ctx context.Context, params *protocol.ImplementationParams) ([]protocol.Location, error) {
64197-	return s.implementation(ctx, params)
64198-}
64199-
64200-func (s *Server) IncomingCalls(ctx context.Context, params *protocol.CallHierarchyIncomingCallsParams) ([]protocol.CallHierarchyIncomingCall, error) {
64201-	return s.incomingCalls(ctx, params)
64202-}
64203-
64204-func (s *Server) Initialize(ctx context.Context, params *protocol.ParamInitialize) (*protocol.InitializeResult, error) {
64205-	return s.initialize(ctx, params)
64206-}
64207-
64208-func (s *Server) Initialized(ctx context.Context, params *protocol.InitializedParams) error {
64209-	return s.initialized(ctx, params)
64210-}
64211-
64212-func (s *Server) InlayHint(ctx context.Context, params *protocol.InlayHintParams) ([]protocol.InlayHint, error) {
64213-	return s.inlayHint(ctx, params)
64214-}
64215-
64216-func (s *Server) InlineValue(context.Context, *protocol.InlineValueParams) ([]protocol.InlineValue, error) {
64217-	return nil, notImplemented("InlineValue")
64218-}
64219-
64220-func (s *Server) LinkedEditingRange(context.Context, *protocol.LinkedEditingRangeParams) (*protocol.LinkedEditingRanges, error) {
64221-	return nil, notImplemented("LinkedEditingRange")
64222-}
64223-
64224-func (s *Server) Moniker(context.Context, *protocol.MonikerParams) ([]protocol.Moniker, error) {
64225-	return nil, notImplemented("Moniker")
64226-}
64227-
64228-func (s *Server) NonstandardRequest(ctx context.Context, method string, params interface{}) (interface{}, error) {
64229-	return s.nonstandardRequest(ctx, method, params)
64230-}
64231-
64232-func (s *Server) OnTypeFormatting(context.Context, *protocol.DocumentOnTypeFormattingParams) ([]protocol.TextEdit, error) {
64233-	return nil, notImplemented("OnTypeFormatting")
64234-}
64235-
64236-func (s *Server) OutgoingCalls(ctx context.Context, params *protocol.CallHierarchyOutgoingCallsParams) ([]protocol.CallHierarchyOutgoingCall, error) {
64237-	return s.outgoingCalls(ctx, params)
64238-}
64239-
64240-func (s *Server) PrepareCallHierarchy(ctx context.Context, params *protocol.CallHierarchyPrepareParams) ([]protocol.CallHierarchyItem, error) {
64241-	return s.prepareCallHierarchy(ctx, params)
64242-}
64243-
64244-func (s *Server) PrepareRename(ctx context.Context, params *protocol.PrepareRenameParams) (*protocol.PrepareRename2Gn, error) {
64245-	return s.prepareRename(ctx, params)
64246-}
64247-
64248-func (s *Server) PrepareTypeHierarchy(context.Context, *protocol.TypeHierarchyPrepareParams) ([]protocol.TypeHierarchyItem, error) {
64249-	return nil, notImplemented("PrepareTypeHierarchy")
64250-}
64251-
64252-func (s *Server) Progress(context.Context, *protocol.ProgressParams) error {
64253-	return notImplemented("Progress")
64254-}
64255-
64256-func (s *Server) RangeFormatting(context.Context, *protocol.DocumentRangeFormattingParams) ([]protocol.TextEdit, error) {
64257-	return nil, notImplemented("RangeFormatting")
64258-}
64259-
64260-func (s *Server) References(ctx context.Context, params *protocol.ReferenceParams) ([]protocol.Location, error) {
64261-	return s.references(ctx, params)
64262-}
64263-
64264-func (s *Server) Rename(ctx context.Context, params *protocol.RenameParams) (*protocol.WorkspaceEdit, error) {
64265-	return s.rename(ctx, params)
64266-}
64267-
64268-func (s *Server) Resolve(context.Context, *protocol.InlayHint) (*protocol.InlayHint, error) {
64269-	return nil, notImplemented("Resolve")
64270-}
64271-
64272-func (s *Server) ResolveCodeAction(context.Context, *protocol.CodeAction) (*protocol.CodeAction, error) {
64273-	return nil, notImplemented("ResolveCodeAction")
64274-}
64275-
64276-func (s *Server) ResolveCodeLens(context.Context, *protocol.CodeLens) (*protocol.CodeLens, error) {
64277-	return nil, notImplemented("ResolveCodeLens")
64278-}
64279-
64280-func (s *Server) ResolveCompletionItem(context.Context, *protocol.CompletionItem) (*protocol.CompletionItem, error) {
64281-	return nil, notImplemented("ResolveCompletionItem")
64282-}
64283-
64284-func (s *Server) ResolveDocumentLink(context.Context, *protocol.DocumentLink) (*protocol.DocumentLink, error) {
64285-	return nil, notImplemented("ResolveDocumentLink")
64286-}
64287-
64288-func (s *Server) ResolveWorkspaceSymbol(context.Context, *protocol.WorkspaceSymbol) (*protocol.WorkspaceSymbol, error) {
64289-	return nil, notImplemented("ResolveWorkspaceSymbol")
64290-}
64291-
64292-func (s *Server) SelectionRange(ctx context.Context, params *protocol.SelectionRangeParams) ([]protocol.SelectionRange, error) {
64293-	return s.selectionRange(ctx, params)
64294-}
64295-
64296-func (s *Server) SemanticTokensFull(ctx context.Context, p *protocol.SemanticTokensParams) (*protocol.SemanticTokens, error) {
64297-	return s.semanticTokensFull(ctx, p)
64298-}
64299-
64300-func (s *Server) SemanticTokensFullDelta(ctx context.Context, p *protocol.SemanticTokensDeltaParams) (interface{}, error) {
64301-	return s.semanticTokensFullDelta(ctx, p)
64302-}
64303-
64304-func (s *Server) SemanticTokensRange(ctx context.Context, p *protocol.SemanticTokensRangeParams) (*protocol.SemanticTokens, error) {
64305-	return s.semanticTokensRange(ctx, p)
64306-}
64307-
64308-func (s *Server) SetTrace(context.Context, *protocol.SetTraceParams) error {
64309-	return notImplemented("SetTrace")
64310-}
64311-
64312-func (s *Server) Shutdown(ctx context.Context) error {
64313-	return s.shutdown(ctx)
64314-}
64315-
64316-func (s *Server) SignatureHelp(ctx context.Context, params *protocol.SignatureHelpParams) (*protocol.SignatureHelp, error) {
64317-	return s.signatureHelp(ctx, params)
64318-}
64319-
64320-func (s *Server) Subtypes(context.Context, *protocol.TypeHierarchySubtypesParams) ([]protocol.TypeHierarchyItem, error) {
64321-	return nil, notImplemented("Subtypes")
64322-}
64323-
64324-func (s *Server) Supertypes(context.Context, *protocol.TypeHierarchySupertypesParams) ([]protocol.TypeHierarchyItem, error) {
64325-	return nil, notImplemented("Supertypes")
64326-}
64327-
64328-func (s *Server) Symbol(ctx context.Context, params *protocol.WorkspaceSymbolParams) ([]protocol.SymbolInformation, error) {
64329-	return s.symbol(ctx, params)
64330-}
64331-
64332-func (s *Server) TypeDefinition(ctx context.Context, params *protocol.TypeDefinitionParams) ([]protocol.Location, error) {
64333-	return s.typeDefinition(ctx, params)
64334-}
64335-
64336-func (s *Server) WillCreateFiles(context.Context, *protocol.CreateFilesParams) (*protocol.WorkspaceEdit, error) {
64337-	return nil, notImplemented("WillCreateFiles")
64338-}
64339-
64340-func (s *Server) WillDeleteFiles(context.Context, *protocol.DeleteFilesParams) (*protocol.WorkspaceEdit, error) {
64341-	return nil, notImplemented("WillDeleteFiles")
64342-}
64343-
64344-func (s *Server) WillRenameFiles(context.Context, *protocol.RenameFilesParams) (*protocol.WorkspaceEdit, error) {
64345-	return nil, notImplemented("WillRenameFiles")
64346-}
64347-
64348-func (s *Server) WillSave(context.Context, *protocol.WillSaveTextDocumentParams) error {
64349-	return notImplemented("WillSave")
64350-}
64351-
64352-func (s *Server) WillSaveWaitUntil(context.Context, *protocol.WillSaveTextDocumentParams) ([]protocol.TextEdit, error) {
64353-	return nil, notImplemented("WillSaveWaitUntil")
64354-}
64355-
64356-func (s *Server) WorkDoneProgressCancel(ctx context.Context, params *protocol.WorkDoneProgressCancelParams) error {
64357-	return s.workDoneProgressCancel(ctx, params)
64358-}
64359diff -urN a/gopls/internal/lsp/server.go b/gopls/internal/lsp/server.go
64360--- a/gopls/internal/lsp/server.go	2000-01-01 00:00:00.000000000 -0000
64361+++ b/gopls/internal/lsp/server.go	1970-01-01 00:00:00.000000000 +0000
64362@@ -1,158 +0,0 @@
64363-// Copyright 2018 The Go Authors. All rights reserved.
64364-// Use of this source code is governed by a BSD-style
64365-// license that can be found in the LICENSE file.
64366-
64367-//go:generate go run ./helper -d protocol/tsserver.go -o server_gen.go -u .
64368-
64369-// Package lsp implements LSP for gopls.
64370-package lsp
64371-
64372-import (
64373-	"context"
64374-	"fmt"
64375-	"sync"
64376-
64377-	"golang.org/x/tools/gopls/internal/lsp/cache"
64378-	"golang.org/x/tools/gopls/internal/lsp/progress"
64379-	"golang.org/x/tools/gopls/internal/lsp/protocol"
64380-	"golang.org/x/tools/gopls/internal/lsp/source"
64381-	"golang.org/x/tools/gopls/internal/span"
64382-	"golang.org/x/tools/internal/jsonrpc2"
64383-)
64384-
64385-const concurrentAnalyses = 1
64386-
64387-// NewServer creates an LSP server and binds it to handle incoming client
64388-// messages on on the supplied stream.
64389-func NewServer(session *cache.Session, client protocol.ClientCloser) *Server {
64390-	return &Server{
64391-		diagnostics:           map[span.URI]*fileReports{},
64392-		gcOptimizationDetails: make(map[source.PackageID]struct{}),
64393-		watchedGlobPatterns:   make(map[string]struct{}),
64394-		changedFiles:          make(map[span.URI]struct{}),
64395-		session:               session,
64396-		client:                client,
64397-		diagnosticsSema:       make(chan struct{}, concurrentAnalyses),
64398-		progress:              progress.NewTracker(client),
64399-		diagDebouncer:         newDebouncer(),
64400-	}
64401-}
64402-
64403-type serverState int
64404-
64405-const (
64406-	serverCreated      = serverState(iota)
64407-	serverInitializing // set once the server has received "initialize" request
64408-	serverInitialized  // set once the server has received "initialized" request
64409-	serverShutDown
64410-)
64411-
64412-func (s serverState) String() string {
64413-	switch s {
64414-	case serverCreated:
64415-		return "created"
64416-	case serverInitializing:
64417-		return "initializing"
64418-	case serverInitialized:
64419-		return "initialized"
64420-	case serverShutDown:
64421-		return "shutDown"
64422-	}
64423-	return fmt.Sprintf("(unknown state: %d)", int(s))
64424-}
64425-
64426-// Server implements the protocol.Server interface.
64427-type Server struct {
64428-	client protocol.ClientCloser
64429-
64430-	stateMu sync.Mutex
64431-	state   serverState
64432-	// notifications generated before serverInitialized
64433-	notifications []*protocol.ShowMessageParams
64434-
64435-	session *cache.Session
64436-
64437-	tempDir string
64438-
64439-	// changedFiles tracks files for which there has been a textDocument/didChange.
64440-	changedFilesMu sync.Mutex
64441-	changedFiles   map[span.URI]struct{}
64442-
64443-	// folders is only valid between initialize and initialized, and holds the
64444-	// set of folders to build views for when we are ready
64445-	pendingFolders []protocol.WorkspaceFolder
64446-
64447-	// watchedGlobPatterns is the set of glob patterns that we have requested
64448-	// the client watch on disk. It will be updated as the set of directories
64449-	// that the server should watch changes.
64450-	watchedGlobPatternsMu  sync.Mutex
64451-	watchedGlobPatterns    map[string]struct{}
64452-	watchRegistrationCount int
64453-
64454-	diagnosticsMu sync.Mutex
64455-	diagnostics   map[span.URI]*fileReports
64456-
64457-	// gcOptimizationDetails describes the packages for which we want
64458-	// optimization details to be included in the diagnostics. The key is the
64459-	// ID of the package.
64460-	gcOptimizationDetailsMu sync.Mutex
64461-	gcOptimizationDetails   map[source.PackageID]struct{}
64462-
64463-	// diagnosticsSema limits the concurrency of diagnostics runs, which can be
64464-	// expensive.
64465-	diagnosticsSema chan struct{}
64466-
64467-	progress *progress.Tracker
64468-
64469-	// diagDebouncer is used for debouncing diagnostics.
64470-	diagDebouncer *debouncer
64471-
64472-	// When the workspace fails to load, we show its status through a progress
64473-	// report with an error message.
64474-	criticalErrorStatusMu sync.Mutex
64475-	criticalErrorStatus   *progress.WorkDone
64476-}
64477-
64478-func (s *Server) workDoneProgressCancel(ctx context.Context, params *protocol.WorkDoneProgressCancelParams) error {
64479-	return s.progress.Cancel(params.Token)
64480-}
64481-
64482-func (s *Server) nonstandardRequest(ctx context.Context, method string, params interface{}) (interface{}, error) {
64483-	switch method {
64484-	case "gopls/diagnoseFiles":
64485-		paramMap := params.(map[string]interface{})
64486-		// TODO(adonovan): opt: parallelize FileDiagnostics(URI...), either
64487-		// by calling it in multiple goroutines or, better, by making
64488-		// the relevant APIs accept a set of URIs/packages.
64489-		for _, file := range paramMap["files"].([]interface{}) {
64490-			snapshot, fh, ok, release, err := s.beginFileRequest(ctx, protocol.DocumentURI(file.(string)), source.UnknownKind)
64491-			defer release()
64492-			if !ok {
64493-				return nil, err
64494-			}
64495-
64496-			fileID, diagnostics, err := source.FileDiagnostics(ctx, snapshot, fh.URI())
64497-			if err != nil {
64498-				return nil, err
64499-			}
64500-			if err := s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{
64501-				URI:         protocol.URIFromSpanURI(fh.URI()),
64502-				Diagnostics: toProtocolDiagnostics(diagnostics),
64503-				Version:     fileID.Version(),
64504-			}); err != nil {
64505-				return nil, err
64506-			}
64507-		}
64508-		if err := s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{
64509-			URI: "gopls://diagnostics-done",
64510-		}); err != nil {
64511-			return nil, err
64512-		}
64513-		return struct{}{}, nil
64514-	}
64515-	return nil, notImplemented(method)
64516-}
64517-
64518-func notImplemented(method string) error {
64519-	return fmt.Errorf("%w: %q not yet implemented", jsonrpc2.ErrMethodNotFound, method)
64520-}
64521diff -urN a/gopls/internal/lsp/signature_help.go b/gopls/internal/lsp/signature_help.go
64522--- a/gopls/internal/lsp/signature_help.go	2000-01-01 00:00:00.000000000 -0000
64523+++ b/gopls/internal/lsp/signature_help.go	1970-01-01 00:00:00.000000000 +0000
64524@@ -1,31 +0,0 @@
64525-// Copyright 2018 The Go Authors. All rights reserved.
64526-// Use of this source code is governed by a BSD-style
64527-// license that can be found in the LICENSE file.
64528-
64529-package lsp
64530-
64531-import (
64532-	"context"
64533-
64534-	"golang.org/x/tools/gopls/internal/lsp/protocol"
64535-	"golang.org/x/tools/gopls/internal/lsp/source"
64536-	"golang.org/x/tools/internal/event"
64537-	"golang.org/x/tools/internal/event/tag"
64538-)
64539-
64540-func (s *Server) signatureHelp(ctx context.Context, params *protocol.SignatureHelpParams) (*protocol.SignatureHelp, error) {
64541-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.Go)
64542-	defer release()
64543-	if !ok {
64544-		return nil, err
64545-	}
64546-	info, activeParameter, err := source.SignatureHelp(ctx, snapshot, fh, params.Position)
64547-	if err != nil {
64548-		event.Error(ctx, "no signature help", err, tag.Position.Of(params.Position))
64549-		return nil, nil // sic? There could be many reasons for failure.
64550-	}
64551-	return &protocol.SignatureHelp{
64552-		Signatures:      []protocol.SignatureInformation{*info},
64553-		ActiveParameter: uint32(activeParameter),
64554-	}, nil
64555-}
64556diff -urN a/gopls/internal/lsp/snippet/snippet_builder.go b/gopls/internal/lsp/snippet/snippet_builder.go
64557--- a/gopls/internal/lsp/snippet/snippet_builder.go	2000-01-01 00:00:00.000000000 -0000
64558+++ b/gopls/internal/lsp/snippet/snippet_builder.go	1970-01-01 00:00:00.000000000 +0000
64559@@ -1,111 +0,0 @@
64560-// Copyright 2019 The Go Authors. All rights reserved.
64561-// Use of this source code is governed by a BSD-style
64562-// license that can be found in the LICENSE file.
64563-
64564-// Package snippet implements the specification for the LSP snippet format.
64565-//
64566-// Snippets are "tab stop" templates returned as an optional attribute of LSP
64567-// completion candidates. As the user presses tab, they cycle through a series of
64568-// tab stops defined in the snippet. Each tab stop can optionally have placeholder
64569-// text, which can be pre-selected by editors. For a full description of syntax
64570-// and features, see "Snippet Syntax" at
64571-// https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/#textDocument_completion.
64572-//
64573-// A typical snippet looks like "foo(${1:i int}, ${2:s string})".
64574-package snippet
64575-
64576-import (
64577-	"fmt"
64578-	"strings"
64579-)
64580-
64581-// A Builder is used to build an LSP snippet piecemeal.
64582-// The zero value is ready to use. Do not copy a non-zero Builder.
64583-type Builder struct {
64584-	// currentTabStop is the index of the previous tab stop. The
64585-	// next tab stop will be currentTabStop+1.
64586-	currentTabStop int
64587-	sb             strings.Builder
64588-}
64589-
64590-// Escape characters defined in https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/#textDocument_completion under "Grammar".
64591-var replacer = strings.NewReplacer(
64592-	`\`, `\\`,
64593-	`}`, `\}`,
64594-	`$`, `\$`,
64595-)
64596-
64597-func (b *Builder) WriteText(s string) {
64598-	replacer.WriteString(&b.sb, s)
64599-}
64600-
64601-func (b *Builder) PrependText(s string) {
64602-	rawSnip := b.String()
64603-	b.sb.Reset()
64604-	b.WriteText(s)
64605-	b.sb.WriteString(rawSnip)
64606-}
64607-
64608-func (b *Builder) Write(data []byte) (int, error) {
64609-	return b.sb.Write(data)
64610-}
64611-
64612-// WritePlaceholder writes a tab stop and placeholder value to the Builder.
64613-// The callback style allows for creating nested placeholders. To write an
64614-// empty tab stop, provide a nil callback.
64615-func (b *Builder) WritePlaceholder(fn func(*Builder)) {
64616-	fmt.Fprintf(&b.sb, "${%d:", b.nextTabStop())
64617-	if fn != nil {
64618-		fn(b)
64619-	}
64620-	b.sb.WriteByte('}')
64621-}
64622-
64623-// WriteFinalTabstop marks where cursor ends up after the user has
64624-// cycled through all the normal tab stops. It defaults to the
64625-// character after the snippet.
64626-func (b *Builder) WriteFinalTabstop() {
64627-	fmt.Fprint(&b.sb, "$0")
64628-}
64629-
64630-// In addition to '\', '}', and '$', snippet choices also use '|' and ',' as
64631-// meta characters, so they must be escaped within the choices.
64632-var choiceReplacer = strings.NewReplacer(
64633-	`\`, `\\`,
64634-	`}`, `\}`,
64635-	`$`, `\$`,
64636-	`|`, `\|`,
64637-	`,`, `\,`,
64638-)
64639-
64640-// WriteChoice writes a tab stop and list of text choices to the Builder.
64641-// The user's editor will prompt the user to choose one of the choices.
64642-func (b *Builder) WriteChoice(choices []string) {
64643-	fmt.Fprintf(&b.sb, "${%d|", b.nextTabStop())
64644-	for i, c := range choices {
64645-		if i != 0 {
64646-			b.sb.WriteByte(',')
64647-		}
64648-		choiceReplacer.WriteString(&b.sb, c)
64649-	}
64650-	b.sb.WriteString("|}")
64651-}
64652-
64653-// String returns the built snippet string.
64654-func (b *Builder) String() string {
64655-	return b.sb.String()
64656-}
64657-
64658-// Clone returns a copy of b.
64659-func (b *Builder) Clone() *Builder {
64660-	var clone Builder
64661-	clone.sb.WriteString(b.String())
64662-	return &clone
64663-}
64664-
64665-// nextTabStop returns the next tab stop index for a new placeholder.
64666-func (b *Builder) nextTabStop() int {
64667-	// Tab stops start from 1, so increment before returning.
64668-	b.currentTabStop++
64669-	return b.currentTabStop
64670-}
64671diff -urN a/gopls/internal/lsp/snippet/snippet_builder_test.go b/gopls/internal/lsp/snippet/snippet_builder_test.go
64672--- a/gopls/internal/lsp/snippet/snippet_builder_test.go	2000-01-01 00:00:00.000000000 -0000
64673+++ b/gopls/internal/lsp/snippet/snippet_builder_test.go	1970-01-01 00:00:00.000000000 +0000
64674@@ -1,62 +0,0 @@
64675-// Copyright 2019 The Go Authors. All rights reserved.
64676-// Use of this source code is governed by a BSD-style
64677-// license that can be found in the LICENSE file.
64678-
64679-package snippet
64680-
64681-import (
64682-	"testing"
64683-)
64684-
64685-func TestSnippetBuilder(t *testing.T) {
64686-	expect := func(expected string, fn func(*Builder)) {
64687-		t.Helper()
64688-
64689-		var b Builder
64690-		fn(&b)
64691-		if got := b.String(); got != expected {
64692-			t.Errorf("got %q, expected %q", got, expected)
64693-		}
64694-	}
64695-
64696-	expect("", func(b *Builder) {})
64697-
64698-	expect(`hi { \} \$ | " , / \\`, func(b *Builder) {
64699-		b.WriteText(`hi { } $ | " , / \`)
64700-	})
64701-
64702-	expect("${1:}", func(b *Builder) {
64703-		b.WritePlaceholder(nil)
64704-	})
64705-
64706-	expect("hi ${1:there}", func(b *Builder) {
64707-		b.WriteText("hi ")
64708-		b.WritePlaceholder(func(b *Builder) {
64709-			b.WriteText("there")
64710-		})
64711-	})
64712-
64713-	expect(`${1:id=${2:{your id\}}}`, func(b *Builder) {
64714-		b.WritePlaceholder(func(b *Builder) {
64715-			b.WriteText("id=")
64716-			b.WritePlaceholder(func(b *Builder) {
64717-				b.WriteText("{your id}")
64718-			})
64719-		})
64720-	})
64721-
64722-	expect(`${1|one,{ \} \$ \| " \, / \\,three|}`, func(b *Builder) {
64723-		b.WriteChoice([]string{"one", `{ } $ | " , / \`, "three"})
64724-	})
64725-
64726-	expect("$0 hello", func(b *Builder) {
64727-		b.WriteFinalTabstop()
64728-		b.WriteText(" hello")
64729-	})
64730-
64731-	expect(`prepended \$5 ${1:} hello`, func(b *Builder) {
64732-		b.WritePlaceholder(nil)
64733-		b.WriteText(" hello")
64734-		b.PrependText("prepended $5 ")
64735-	})
64736-}
64737diff -urN a/gopls/internal/lsp/source/add_import.go b/gopls/internal/lsp/source/add_import.go
64738--- a/gopls/internal/lsp/source/add_import.go	2000-01-01 00:00:00.000000000 -0000
64739+++ b/gopls/internal/lsp/source/add_import.go	1970-01-01 00:00:00.000000000 +0000
64740@@ -1,26 +0,0 @@
64741-// Copyright 2020 The Go Authors. All rights reserved.
64742-// Use of this source code is governed by a BSD-style
64743-// license that can be found in the LICENSE file.
64744-
64745-package source
64746-
64747-import (
64748-	"context"
64749-
64750-	"golang.org/x/tools/gopls/internal/lsp/protocol"
64751-	"golang.org/x/tools/internal/imports"
64752-)
64753-
64754-// AddImport adds a single import statement to the given file
64755-func AddImport(ctx context.Context, snapshot Snapshot, fh FileHandle, importPath string) ([]protocol.TextEdit, error) {
64756-	pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
64757-	if err != nil {
64758-		return nil, err
64759-	}
64760-	return ComputeOneImportFixEdits(snapshot, pgf, &imports.ImportFix{
64761-		StmtInfo: imports.ImportInfo{
64762-			ImportPath: importPath,
64763-		},
64764-		FixType: imports.AddImport,
64765-	})
64766-}
64767diff -urN a/gopls/internal/lsp/source/api_json.go b/gopls/internal/lsp/source/api_json.go
64768--- a/gopls/internal/lsp/source/api_json.go	2000-01-01 00:00:00.000000000 -0000
64769+++ b/gopls/internal/lsp/source/api_json.go	1970-01-01 00:00:00.000000000 +0000
64770@@ -1,1118 +0,0 @@
64771-// Code generated by "golang.org/x/tools/gopls/doc/generate"; DO NOT EDIT.
64772-
64773-package source
64774-
64775-var GeneratedAPIJSON = &APIJSON{
64776-	Options: map[string][]*OptionJSON{
64777-		"User": {
64778-			{
64779-				Name:      "buildFlags",
64780-				Type:      "[]string",
64781-				Doc:       "buildFlags is the set of flags passed on to the build system when invoked.\nIt is applied to queries like `go list`, which is used when discovering files.\nThe most common use is to set `-tags`.\n",
64782-				Default:   "[]",
64783-				Hierarchy: "build",
64784-			},
64785-			{
64786-				Name:      "env",
64787-				Type:      "map[string]string",
64788-				Doc:       "env adds environment variables to external commands run by `gopls`, most notably `go list`.\n",
64789-				Default:   "{}",
64790-				Hierarchy: "build",
64791-			},
64792-			{
64793-				Name:      "directoryFilters",
64794-				Type:      "[]string",
64795-				Doc:       "directoryFilters can be used to exclude unwanted directories from the\nworkspace. By default, all directories are included. Filters are an\noperator, `+` to include and `-` to exclude, followed by a path prefix\nrelative to the workspace folder. They are evaluated in order, and\nthe last filter that applies to a path controls whether it is included.\nThe path prefix can be empty, so an initial `-` excludes everything.\n\nDirectoryFilters also supports the `**` operator to match 0 or more directories.\n\nExamples:\n\nExclude node_modules at current depth: `-node_modules`\n\nExclude node_modules at any depth: `-**/node_modules`\n\nInclude only project_a: `-` (exclude everything), `+project_a`\n\nInclude only project_a, but not node_modules inside it: `-`, `+project_a`, `-project_a/node_modules`\n",
64796-				Default:   "[\"-**/node_modules\"]",
64797-				Hierarchy: "build",
64798-			},
64799-			{
64800-				Name:      "templateExtensions",
64801-				Type:      "[]string",
64802-				Doc:       "templateExtensions gives the extensions of file names that are treateed\nas template files. (The extension\nis the part of the file name after the final dot.)\n",
64803-				Default:   "[]",
64804-				Hierarchy: "build",
64805-			},
64806-			{
64807-				Name: "memoryMode",
64808-				Type: "enum",
64809-				Doc:  "memoryMode controls the tradeoff `gopls` makes between memory usage and\ncorrectness.\n\nValues other than `Normal` are untested and may break in surprising ways.\n",
64810-				EnumValues: []EnumValue{
64811-					{
64812-						Value: "\"DegradeClosed\"",
64813-						Doc:   "`\"DegradeClosed\"`: In DegradeClosed mode, `gopls` will collect less information about\npackages without open files. As a result, features like Find\nReferences and Rename will miss results in such packages.\n",
64814-					},
64815-					{Value: "\"Normal\""},
64816-				},
64817-				Default:   "\"Normal\"",
64818-				Status:    "experimental",
64819-				Hierarchy: "build",
64820-			},
64821-			{
64822-				Name:      "expandWorkspaceToModule",
64823-				Type:      "bool",
64824-				Doc:       "expandWorkspaceToModule instructs `gopls` to adjust the scope of the\nworkspace to find the best available module root. `gopls` first looks for\na go.mod file in any parent directory of the workspace folder, expanding\nthe scope to that directory if it exists. If no viable parent directory is\nfound, gopls will check if there is exactly one child directory containing\na go.mod file, narrowing the scope to that directory if it exists.\n",
64825-				Default:   "true",
64826-				Status:    "experimental",
64827-				Hierarchy: "build",
64828-			},
64829-			{
64830-				Name:      "allowModfileModifications",
64831-				Type:      "bool",
64832-				Doc:       "allowModfileModifications disables -mod=readonly, allowing imports from\nout-of-scope modules. This option will eventually be removed.\n",
64833-				Default:   "false",
64834-				Status:    "experimental",
64835-				Hierarchy: "build",
64836-			},
64837-			{
64838-				Name:      "allowImplicitNetworkAccess",
64839-				Type:      "bool",
64840-				Doc:       "allowImplicitNetworkAccess disables GOPROXY=off, allowing implicit module\ndownloads rather than requiring user action. This option will eventually\nbe removed.\n",
64841-				Default:   "false",
64842-				Status:    "experimental",
64843-				Hierarchy: "build",
64844-			},
64845-			{
64846-				Name:      "standaloneTags",
64847-				Type:      "[]string",
64848-				Doc:       "standaloneTags specifies a set of build constraints that identify\nindividual Go source files that make up the entire main package of an\nexecutable.\n\nA common example of standalone main files is the convention of using the\ndirective `//go:build ignore` to denote files that are not intended to be\nincluded in any package, for example because they are invoked directly by\nthe developer using `go run`.\n\nGopls considers a file to be a standalone main file if and only if it has\npackage name \"main\" and has a build directive of the exact form\n\"//go:build tag\" or \"// +build tag\", where tag is among the list of tags\nconfigured by this setting. Notably, if the build constraint is more\ncomplicated than a simple tag (such as the composite constraint\n`//go:build tag && go1.18`), the file is not considered to be a standalone\nmain file.\n\nThis setting is only supported when gopls is built with Go 1.16 or later.\n",
64849-				Default:   "[\"ignore\"]",
64850-				Hierarchy: "build",
64851-			},
64852-			{
64853-				Name: "hoverKind",
64854-				Type: "enum",
64855-				Doc:  "hoverKind controls the information that appears in the hover text.\nSingleLine and Structured are intended for use only by authors of editor plugins.\n",
64856-				EnumValues: []EnumValue{
64857-					{Value: "\"FullDocumentation\""},
64858-					{Value: "\"NoDocumentation\""},
64859-					{Value: "\"SingleLine\""},
64860-					{
64861-						Value: "\"Structured\"",
64862-						Doc:   "`\"Structured\"` is an experimental setting that returns a structured hover format.\nThis format separates the signature from the documentation, so that the client\ncan do more manipulation of these fields.\n\nThis should only be used by clients that support this behavior.\n",
64863-					},
64864-					{Value: "\"SynopsisDocumentation\""},
64865-				},
64866-				Default:   "\"FullDocumentation\"",
64867-				Hierarchy: "ui.documentation",
64868-			},
64869-			{
64870-				Name:      "linkTarget",
64871-				Type:      "string",
64872-				Doc:       "linkTarget controls where documentation links go.\nIt might be one of:\n\n* `\"godoc.org\"`\n* `\"pkg.go.dev\"`\n\nIf company chooses to use its own `godoc.org`, its address can be used as well.\n\nModules matching the GOPRIVATE environment variable will not have\ndocumentation links in hover.\n",
64873-				Default:   "\"pkg.go.dev\"",
64874-				Hierarchy: "ui.documentation",
64875-			},
64876-			{
64877-				Name:      "linksInHover",
64878-				Type:      "bool",
64879-				Doc:       "linksInHover toggles the presence of links to documentation in hover.\n",
64880-				Default:   "true",
64881-				Hierarchy: "ui.documentation",
64882-			},
64883-			{
64884-				Name:      "usePlaceholders",
64885-				Type:      "bool",
64886-				Doc:       "placeholders enables placeholders for function parameters or struct\nfields in completion responses.\n",
64887-				Default:   "false",
64888-				Hierarchy: "ui.completion",
64889-			},
64890-			{
64891-				Name:      "completionBudget",
64892-				Type:      "time.Duration",
64893-				Doc:       "completionBudget is the soft latency goal for completion requests. Most\nrequests finish in a couple milliseconds, but in some cases deep\ncompletions can take much longer. As we use up our budget we\ndynamically reduce the search scope to ensure we return timely\nresults. Zero means unlimited.\n",
64894-				Default:   "\"100ms\"",
64895-				Status:    "debug",
64896-				Hierarchy: "ui.completion",
64897-			},
64898-			{
64899-				Name: "matcher",
64900-				Type: "enum",
64901-				Doc:  "matcher sets the algorithm that is used when calculating completion\ncandidates.\n",
64902-				EnumValues: []EnumValue{
64903-					{Value: "\"CaseInsensitive\""},
64904-					{Value: "\"CaseSensitive\""},
64905-					{Value: "\"Fuzzy\""},
64906-				},
64907-				Default:   "\"Fuzzy\"",
64908-				Status:    "advanced",
64909-				Hierarchy: "ui.completion",
64910-			},
64911-			{
64912-				Name:      "experimentalPostfixCompletions",
64913-				Type:      "bool",
64914-				Doc:       "experimentalPostfixCompletions enables artificial method snippets\nsuch as \"someSlice.sort!\".\n",
64915-				Default:   "true",
64916-				Status:    "experimental",
64917-				Hierarchy: "ui.completion",
64918-			},
64919-			{
64920-				Name: "importShortcut",
64921-				Type: "enum",
64922-				Doc:  "importShortcut specifies whether import statements should link to\ndocumentation or go to definitions.\n",
64923-				EnumValues: []EnumValue{
64924-					{Value: "\"Both\""},
64925-					{Value: "\"Definition\""},
64926-					{Value: "\"Link\""},
64927-				},
64928-				Default:   "\"Both\"",
64929-				Hierarchy: "ui.navigation",
64930-			},
64931-			{
64932-				Name: "symbolMatcher",
64933-				Type: "enum",
64934-				Doc:  "symbolMatcher sets the algorithm that is used when finding workspace symbols.\n",
64935-				EnumValues: []EnumValue{
64936-					{Value: "\"CaseInsensitive\""},
64937-					{Value: "\"CaseSensitive\""},
64938-					{Value: "\"FastFuzzy\""},
64939-					{Value: "\"Fuzzy\""},
64940-				},
64941-				Default:   "\"FastFuzzy\"",
64942-				Status:    "advanced",
64943-				Hierarchy: "ui.navigation",
64944-			},
64945-			{
64946-				Name: "symbolStyle",
64947-				Type: "enum",
64948-				Doc:  "symbolStyle controls how symbols are qualified in symbol responses.\n\nExample Usage:\n\n```json5\n\"gopls\": {\n...\n  \"symbolStyle\": \"Dynamic\",\n...\n}\n```\n",
64949-				EnumValues: []EnumValue{
64950-					{
64951-						Value: "\"Dynamic\"",
64952-						Doc:   "`\"Dynamic\"` uses whichever qualifier results in the highest scoring\nmatch for the given symbol query. Here a \"qualifier\" is any \"/\" or \".\"\ndelimited suffix of the fully qualified symbol. i.e. \"to/pkg.Foo.Field\" or\njust \"Foo.Field\".\n",
64953-					},
64954-					{
64955-						Value: "\"Full\"",
64956-						Doc:   "`\"Full\"` is fully qualified symbols, i.e.\n\"path/to/pkg.Foo.Field\".\n",
64957-					},
64958-					{
64959-						Value: "\"Package\"",
64960-						Doc:   "`\"Package\"` is package qualified symbols i.e.\n\"pkg.Foo.Field\".\n",
64961-					},
64962-				},
64963-				Default:   "\"Dynamic\"",
64964-				Status:    "advanced",
64965-				Hierarchy: "ui.navigation",
64966-			},
64967-			{
64968-				Name: "analyses",
64969-				Type: "map[string]bool",
64970-				Doc:  "analyses specify analyses that the user would like to enable or disable.\nA map of the names of analysis passes that should be enabled/disabled.\nA full list of analyzers that gopls uses can be found in\n[analyzers.md](https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md).\n\nExample Usage:\n\n```json5\n...\n\"analyses\": {\n  \"unreachable\": false, // Disable the unreachable analyzer.\n  \"unusedparams\": true  // Enable the unusedparams analyzer.\n}\n...\n```\n",
64971-				EnumKeys: EnumKeys{
64972-					ValueType: "bool",
64973-					Keys: []EnumKey{
64974-						{
64975-							Name:    "\"asmdecl\"",
64976-							Doc:     "report mismatches between assembly files and Go declarations",
64977-							Default: "true",
64978-						},
64979-						{
64980-							Name:    "\"assign\"",
64981-							Doc:     "check for useless assignments\n\nThis checker reports assignments of the form x = x or a[i] = a[i].\nThese are almost always useless, and even when they aren't they are\nusually a mistake.",
64982-							Default: "true",
64983-						},
64984-						{
64985-							Name:    "\"atomic\"",
64986-							Doc:     "check for common mistakes using the sync/atomic package\n\nThe atomic checker looks for assignment statements of the form:\n\n\tx = atomic.AddUint64(&x, 1)\n\nwhich are not atomic.",
64987-							Default: "true",
64988-						},
64989-						{
64990-							Name:    "\"atomicalign\"",
64991-							Doc:     "check for non-64-bits-aligned arguments to sync/atomic functions",
64992-							Default: "true",
64993-						},
64994-						{
64995-							Name:    "\"bools\"",
64996-							Doc:     "check for common mistakes involving boolean operators",
64997-							Default: "true",
64998-						},
64999-						{
65000-							Name:    "\"buildtag\"",
65001-							Doc:     "check //go:build and // +build directives",
65002-							Default: "true",
65003-						},
65004-						{
65005-							Name:    "\"cgocall\"",
65006-							Doc:     "detect some violations of the cgo pointer passing rules\n\nCheck for invalid cgo pointer passing.\nThis looks for code that uses cgo to call C code passing values\nwhose types are almost always invalid according to the cgo pointer\nsharing rules.\nSpecifically, it warns about attempts to pass a Go chan, map, func,\nor slice to C, either directly, or via a pointer, array, or struct.",
65007-							Default: "true",
65008-						},
65009-						{
65010-							Name:    "\"composites\"",
65011-							Doc:     "check for unkeyed composite literals\n\nThis analyzer reports a diagnostic for composite literals of struct\ntypes imported from another package that do not use the field-keyed\nsyntax. Such literals are fragile because the addition of a new field\n(even if unexported) to the struct will cause compilation to fail.\n\nAs an example,\n\n\terr = &net.DNSConfigError{err}\n\nshould be replaced by:\n\n\terr = &net.DNSConfigError{Err: err}\n",
65012-							Default: "true",
65013-						},
65014-						{
65015-							Name:    "\"copylocks\"",
65016-							Doc:     "check for locks erroneously passed by value\n\nInadvertently copying a value containing a lock, such as sync.Mutex or\nsync.WaitGroup, may cause both copies to malfunction. Generally such\nvalues should be referred to through a pointer.",
65017-							Default: "true",
65018-						},
65019-						{
65020-							Name:    "\"deepequalerrors\"",
65021-							Doc:     "check for calls of reflect.DeepEqual on error values\n\nThe deepequalerrors checker looks for calls of the form:\n\n    reflect.DeepEqual(err1, err2)\n\nwhere err1 and err2 are errors. Using reflect.DeepEqual to compare\nerrors is discouraged.",
65022-							Default: "true",
65023-						},
65024-						{
65025-							Name:    "\"directive\"",
65026-							Doc:     "check Go toolchain directives such as //go:debug\n\nThis analyzer checks for problems with known Go toolchain directives\nin all Go source files in a package directory, even those excluded by\n//go:build constraints, and all non-Go source files too.\n\nFor //go:debug (see https://go.dev/doc/godebug), the analyzer checks\nthat the directives are placed only in Go source files, only above the\npackage comment, and only in package main or *_test.go files.\n\nSupport for other known directives may be added in the future.\n\nThis analyzer does not check //go:build, which is handled by the\nbuildtag analyzer.\n",
65027-							Default: "true",
65028-						},
65029-						{
65030-							Name:    "\"embed\"",
65031-							Doc:     "check for //go:embed directive import\n\nThis analyzer checks that the embed package is imported when source code contains //go:embed comment directives.\nThe embed package must be imported for //go:embed directives to function.import _ \"embed\".",
65032-							Default: "true",
65033-						},
65034-						{
65035-							Name:    "\"errorsas\"",
65036-							Doc:     "report passing non-pointer or non-error values to errors.As\n\nThe errorsas analysis reports calls to errors.As where the type\nof the second argument is not a pointer to a type implementing error.",
65037-							Default: "true",
65038-						},
65039-						{
65040-							Name:    "\"fieldalignment\"",
65041-							Doc:     "find structs that would use less memory if their fields were sorted\n\nThis analyzer find structs that can be rearranged to use less memory, and provides\na suggested edit with the most compact order.\n\nNote that there are two different diagnostics reported. One checks struct size,\nand the other reports \"pointer bytes\" used. Pointer bytes is how many bytes of the\nobject that the garbage collector has to potentially scan for pointers, for example:\n\n\tstruct { uint32; string }\n\nhave 16 pointer bytes because the garbage collector has to scan up through the string's\ninner pointer.\n\n\tstruct { string; *uint32 }\n\nhas 24 pointer bytes because it has to scan further through the *uint32.\n\n\tstruct { string; uint32 }\n\nhas 8 because it can stop immediately after the string pointer.\n\nBe aware that the most compact order is not always the most efficient.\nIn rare cases it may cause two variables each updated by its own goroutine\nto occupy the same CPU cache line, inducing a form of memory contention\nknown as \"false sharing\" that slows down both goroutines.\n",
65042-							Default: "false",
65043-						},
65044-						{
65045-							Name:    "\"httpresponse\"",
65046-							Doc:     "check for mistakes using HTTP responses\n\nA common mistake when using the net/http package is to defer a function\ncall to close the http.Response Body before checking the error that\ndetermines whether the response is valid:\n\n\tresp, err := http.Head(url)\n\tdefer resp.Body.Close()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t// (defer statement belongs here)\n\nThis checker helps uncover latent nil dereference bugs by reporting a\ndiagnostic for such mistakes.",
65047-							Default: "true",
65048-						},
65049-						{
65050-							Name:    "\"ifaceassert\"",
65051-							Doc:     "detect impossible interface-to-interface type assertions\n\nThis checker flags type assertions v.(T) and corresponding type-switch cases\nin which the static type V of v is an interface that cannot possibly implement\nthe target interface T. This occurs when V and T contain methods with the same\nname but different signatures. Example:\n\n\tvar v interface {\n\t\tRead()\n\t}\n\t_ = v.(io.Reader)\n\nThe Read method in v has a different signature than the Read method in\nio.Reader, so this assertion cannot succeed.\n",
65052-							Default: "true",
65053-						},
65054-						{
65055-							Name:    "\"infertypeargs\"",
65056-							Doc:     "check for unnecessary type arguments in call expressions\n\nExplicit type arguments may be omitted from call expressions if they can be\ninferred from function arguments, or from other type arguments:\n\n\tfunc f[T any](T) {}\n\t\n\tfunc _() {\n\t\tf[string](\"foo\") // string could be inferred\n\t}\n",
65057-							Default: "true",
65058-						},
65059-						{
65060-							Name:    "\"loopclosure\"",
65061-							Doc:     "check references to loop variables from within nested functions\n\nThis analyzer reports places where a function literal references the\niteration variable of an enclosing loop, and the loop calls the function\nin such a way (e.g. with go or defer) that it may outlive the loop\niteration and possibly observe the wrong value of the variable.\n\nIn this example, all the deferred functions run after the loop has\ncompleted, so all observe the final value of v.\n\n    for _, v := range list {\n        defer func() {\n            use(v) // incorrect\n        }()\n    }\n\nOne fix is to create a new variable for each iteration of the loop:\n\n    for _, v := range list {\n        v := v // new var per iteration\n        defer func() {\n            use(v) // ok\n        }()\n    }\n\nThe next example uses a go statement and has a similar problem.\nIn addition, it has a data race because the loop updates v\nconcurrent with the goroutines accessing it.\n\n    for _, v := range elem {\n        go func() {\n            use(v)  // incorrect, and a data race\n        }()\n    }\n\nA fix is the same as before. The checker also reports problems\nin goroutines started by golang.org/x/sync/errgroup.Group.\nA hard-to-spot variant of this form is common in parallel tests:\n\n    func Test(t *testing.T) {\n        for _, test := range tests {\n            t.Run(test.name, func(t *testing.T) {\n                t.Parallel()\n                use(test) // incorrect, and a data race\n            })\n        }\n    }\n\nThe t.Parallel() call causes the rest of the function to execute\nconcurrent with the loop.\n\nThe analyzer reports references only in the last statement,\nas it is not deep enough to understand the effects of subsequent\nstatements that might render the reference benign.\n(\"Last statement\" is defined recursively in compound\nstatements such as if, switch, and select.)\n\nSee: https://golang.org/doc/go_faq.html#closures_and_goroutines",
65062-							Default: "true",
65063-						},
65064-						{
65065-							Name:    "\"lostcancel\"",
65066-							Doc:     "check cancel func returned by context.WithCancel is called\n\nThe cancellation function returned by context.WithCancel, WithTimeout,\nand WithDeadline must be called or the new context will remain live\nuntil its parent context is cancelled.\n(The background context is never cancelled.)",
65067-							Default: "true",
65068-						},
65069-						{
65070-							Name:    "\"nilfunc\"",
65071-							Doc:     "check for useless comparisons between functions and nil\n\nA useless comparison is one like f == nil as opposed to f() == nil.",
65072-							Default: "true",
65073-						},
65074-						{
65075-							Name:    "\"nilness\"",
65076-							Doc:     "check for redundant or impossible nil comparisons\n\nThe nilness checker inspects the control-flow graph of each function in\na package and reports nil pointer dereferences, degenerate nil\npointers, and panics with nil values. A degenerate comparison is of the form\nx==nil or x!=nil where x is statically known to be nil or non-nil. These are\noften a mistake, especially in control flow related to errors. Panics with nil\nvalues are checked because they are not detectable by\n\n\tif r := recover(); r != nil {\n\nThis check reports conditions such as:\n\n\tif f == nil { // impossible condition (f is a function)\n\t}\n\nand:\n\n\tp := &v\n\t...\n\tif p != nil { // tautological condition\n\t}\n\nand:\n\n\tif p == nil {\n\t\tprint(*p) // nil dereference\n\t}\n\nand:\n\n\tif p == nil {\n\t\tpanic(p)\n\t}\n",
65077-							Default: "false",
65078-						},
65079-						{
65080-							Name:    "\"printf\"",
65081-							Doc:     "check consistency of Printf format strings and arguments\n\nThe check applies to known functions (for example, those in package fmt)\nas well as any detected wrappers of known functions.\n\nA function that wants to avail itself of printf checking but is not\nfound by this analyzer's heuristics (for example, due to use of\ndynamic calls) can insert a bogus call:\n\n\tif false {\n\t\t_ = fmt.Sprintf(format, args...) // enable printf checking\n\t}\n\nThe -funcs flag specifies a comma-separated list of names of additional\nknown formatting functions or methods. If the name contains a period,\nit must denote a specific function using one of the following forms:\n\n\tdir/pkg.Function\n\tdir/pkg.Type.Method\n\t(*dir/pkg.Type).Method\n\nOtherwise the name is interpreted as a case-insensitive unqualified\nidentifier such as \"errorf\". Either way, if a listed name ends in f, the\nfunction is assumed to be Printf-like, taking a format string before the\nargument list. Otherwise it is assumed to be Print-like, taking a list\nof arguments with no format string.\n",
65082-							Default: "true",
65083-						},
65084-						{
65085-							Name:    "\"shadow\"",
65086-							Doc:     "check for possible unintended shadowing of variables\n\nThis analyzer check for shadowed variables.\nA shadowed variable is a variable declared in an inner scope\nwith the same name and type as a variable in an outer scope,\nand where the outer variable is mentioned after the inner one\nis declared.\n\n(This definition can be refined; the module generates too many\nfalse positives and is not yet enabled by default.)\n\nFor example:\n\n\tfunc BadRead(f *os.File, buf []byte) error {\n\t\tvar err error\n\t\tfor {\n\t\t\tn, err := f.Read(buf) // shadows the function variable 'err'\n\t\t\tif err != nil {\n\t\t\t\tbreak // causes return of wrong value\n\t\t\t}\n\t\t\tfoo(buf)\n\t\t}\n\t\treturn err\n\t}\n",
65087-							Default: "false",
65088-						},
65089-						{
65090-							Name:    "\"shift\"",
65091-							Doc:     "check for shifts that equal or exceed the width of the integer",
65092-							Default: "true",
65093-						},
65094-						{
65095-							Name:    "\"simplifycompositelit\"",
65096-							Doc:     "check for composite literal simplifications\n\nAn array, slice, or map composite literal of the form:\n\t[]T{T{}, T{}}\nwill be simplified to:\n\t[]T{{}, {}}\n\nThis is one of the simplifications that \"gofmt -s\" applies.",
65097-							Default: "true",
65098-						},
65099-						{
65100-							Name:    "\"simplifyrange\"",
65101-							Doc:     "check for range statement simplifications\n\nA range of the form:\n\tfor x, _ = range v {...}\nwill be simplified to:\n\tfor x = range v {...}\n\nA range of the form:\n\tfor _ = range v {...}\nwill be simplified to:\n\tfor range v {...}\n\nThis is one of the simplifications that \"gofmt -s\" applies.",
65102-							Default: "true",
65103-						},
65104-						{
65105-							Name:    "\"simplifyslice\"",
65106-							Doc:     "check for slice simplifications\n\nA slice expression of the form:\n\ts[a:len(s)]\nwill be simplified to:\n\ts[a:]\n\nThis is one of the simplifications that \"gofmt -s\" applies.",
65107-							Default: "true",
65108-						},
65109-						{
65110-							Name:    "\"sortslice\"",
65111-							Doc:     "check the argument type of sort.Slice\n\nsort.Slice requires an argument of a slice type. Check that\nthe interface{} value passed to sort.Slice is actually a slice.",
65112-							Default: "true",
65113-						},
65114-						{
65115-							Name:    "\"stdmethods\"",
65116-							Doc:     "check signature of methods of well-known interfaces\n\nSometimes a type may be intended to satisfy an interface but may fail to\ndo so because of a mistake in its method signature.\nFor example, the result of this WriteTo method should be (int64, error),\nnot error, to satisfy io.WriterTo:\n\n\ttype myWriterTo struct{...}\n        func (myWriterTo) WriteTo(w io.Writer) error { ... }\n\nThis check ensures that each method whose name matches one of several\nwell-known interface methods from the standard library has the correct\nsignature for that interface.\n\nChecked method names include:\n\tFormat GobEncode GobDecode MarshalJSON MarshalXML\n\tPeek ReadByte ReadFrom ReadRune Scan Seek\n\tUnmarshalJSON UnreadByte UnreadRune WriteByte\n\tWriteTo\n",
65117-							Default: "true",
65118-						},
65119-						{
65120-							Name:    "\"stringintconv\"",
65121-							Doc:     "check for string(int) conversions\n\nThis checker flags conversions of the form string(x) where x is an integer\n(but not byte or rune) type. Such conversions are discouraged because they\nreturn the UTF-8 representation of the Unicode code point x, and not a decimal\nstring representation of x as one might expect. Furthermore, if x denotes an\ninvalid code point, the conversion cannot be statically rejected.\n\nFor conversions that intend on using the code point, consider replacing them\nwith string(rune(x)). Otherwise, strconv.Itoa and its equivalents return the\nstring representation of the value in the desired base.\n",
65122-							Default: "true",
65123-						},
65124-						{
65125-							Name:    "\"structtag\"",
65126-							Doc:     "check that struct field tags conform to reflect.StructTag.Get\n\nAlso report certain struct tags (json, xml) used with unexported fields.",
65127-							Default: "true",
65128-						},
65129-						{
65130-							Name:    "\"testinggoroutine\"",
65131-							Doc:     "report calls to (*testing.T).Fatal from goroutines started by a test.\n\nFunctions that abruptly terminate a test, such as the Fatal, Fatalf, FailNow, and\nSkip{,f,Now} methods of *testing.T, must be called from the test goroutine itself.\nThis checker detects calls to these functions that occur within a goroutine\nstarted by the test. For example:\n\nfunc TestFoo(t *testing.T) {\n    go func() {\n        t.Fatal(\"oops\") // error: (*T).Fatal called from non-test goroutine\n    }()\n}\n",
65132-							Default: "true",
65133-						},
65134-						{
65135-							Name:    "\"tests\"",
65136-							Doc:     "check for common mistaken usages of tests and examples\n\nThe tests checker walks Test, Benchmark and Example functions checking\nmalformed names, wrong signatures and examples documenting non-existent\nidentifiers.\n\nPlease see the documentation for package testing in golang.org/pkg/testing\nfor the conventions that are enforced for Tests, Benchmarks, and Examples.",
65137-							Default: "true",
65138-						},
65139-						{
65140-							Name:    "\"timeformat\"",
65141-							Doc:     "check for calls of (time.Time).Format or time.Parse with 2006-02-01\n\nThe timeformat checker looks for time formats with the 2006-02-01 (yyyy-dd-mm)\nformat. Internationally, \"yyyy-dd-mm\" does not occur in common calendar date\nstandards, and so it is more likely that 2006-01-02 (yyyy-mm-dd) was intended.\n",
65142-							Default: "true",
65143-						},
65144-						{
65145-							Name:    "\"unmarshal\"",
65146-							Doc:     "report passing non-pointer or non-interface values to unmarshal\n\nThe unmarshal analysis reports calls to functions such as json.Unmarshal\nin which the argument type is not a pointer or an interface.",
65147-							Default: "true",
65148-						},
65149-						{
65150-							Name:    "\"unreachable\"",
65151-							Doc:     "check for unreachable code\n\nThe unreachable analyzer finds statements that execution can never reach\nbecause they are preceded by an return statement, a call to panic, an\ninfinite loop, or similar constructs.",
65152-							Default: "true",
65153-						},
65154-						{
65155-							Name:    "\"unsafeptr\"",
65156-							Doc:     "check for invalid conversions of uintptr to unsafe.Pointer\n\nThe unsafeptr analyzer reports likely incorrect uses of unsafe.Pointer\nto convert integers to pointers. A conversion from uintptr to\nunsafe.Pointer is invalid if it implies that there is a uintptr-typed\nword in memory that holds a pointer value, because that word will be\ninvisible to stack copying and to the garbage collector.",
65157-							Default: "true",
65158-						},
65159-						{
65160-							Name:    "\"unusedparams\"",
65161-							Doc:     "check for unused parameters of functions\n\nThe unusedparams analyzer checks functions to see if there are\nany parameters that are not being used.\n\nTo reduce false positives it ignores:\n- methods\n- parameters that do not have a name or are underscored\n- functions in test files\n- functions with empty bodies or those with just a return stmt",
65162-							Default: "false",
65163-						},
65164-						{
65165-							Name:    "\"unusedresult\"",
65166-							Doc:     "check for unused results of calls to some functions\n\nSome functions like fmt.Errorf return a result and have no side effects,\nso it is always a mistake to discard the result. This analyzer reports\ncalls to certain functions in which the result of the call is ignored.\n\nThe set of functions may be controlled using flags.",
65167-							Default: "true",
65168-						},
65169-						{
65170-							Name:    "\"unusedwrite\"",
65171-							Doc:     "checks for unused writes\n\nThe analyzer reports instances of writes to struct fields and\narrays that are never read. Specifically, when a struct object\nor an array is copied, its elements are copied implicitly by\nthe compiler, and any element write to this copy does nothing\nwith the original object.\n\nFor example:\n\n\ttype T struct { x int }\n\tfunc f(input []T) {\n\t\tfor i, v := range input {  // v is a copy\n\t\t\tv.x = i  // unused write to field x\n\t\t}\n\t}\n\nAnother example is about non-pointer receiver:\n\n\ttype T struct { x int }\n\tfunc (t T) f() {  // t is a copy\n\t\tt.x = i  // unused write to field x\n\t}\n",
65172-							Default: "false",
65173-						},
65174-						{
65175-							Name:    "\"useany\"",
65176-							Doc:     "check for constraints that could be simplified to \"any\"",
65177-							Default: "false",
65178-						},
65179-						{
65180-							Name:    "\"fillreturns\"",
65181-							Doc:     "suggest fixes for errors due to an incorrect number of return values\n\nThis checker provides suggested fixes for type errors of the\ntype \"wrong number of return values (want %d, got %d)\". For example:\n\tfunc m() (int, string, *bool, error) {\n\t\treturn\n\t}\nwill turn into\n\tfunc m() (int, string, *bool, error) {\n\t\treturn 0, \"\", nil, nil\n\t}\n\nThis functionality is similar to https://github.com/sqs/goreturns.\n",
65182-							Default: "true",
65183-						},
65184-						{
65185-							Name:    "\"nonewvars\"",
65186-							Doc:     "suggested fixes for \"no new vars on left side of :=\"\n\nThis checker provides suggested fixes for type errors of the\ntype \"no new vars on left side of :=\". For example:\n\tz := 1\n\tz := 2\nwill turn into\n\tz := 1\n\tz = 2\n",
65187-							Default: "true",
65188-						},
65189-						{
65190-							Name:    "\"noresultvalues\"",
65191-							Doc:     "suggested fixes for unexpected return values\n\nThis checker provides suggested fixes for type errors of the\ntype \"no result values expected\" or \"too many return values\".\nFor example:\n\tfunc z() { return nil }\nwill turn into\n\tfunc z() { return }\n",
65192-							Default: "true",
65193-						},
65194-						{
65195-							Name:    "\"undeclaredname\"",
65196-							Doc:     "suggested fixes for \"undeclared name: <>\"\n\nThis checker provides suggested fixes for type errors of the\ntype \"undeclared name: <>\". It will either insert a new statement,\nsuch as:\n\n\"<> := \"\n\nor a new function declaration, such as:\n\nfunc <>(inferred parameters) {\n\tpanic(\"implement me!\")\n}\n",
65197-							Default: "true",
65198-						},
65199-						{
65200-							Name:    "\"unusedvariable\"",
65201-							Doc:     "check for unused variables\n\nThe unusedvariable analyzer suggests fixes for unused variables errors.\n",
65202-							Default: "false",
65203-						},
65204-						{
65205-							Name:    "\"fillstruct\"",
65206-							Doc:     "note incomplete struct initializations\n\nThis analyzer provides diagnostics for any struct literals that do not have\nany fields initialized. Because the suggested fix for this analysis is\nexpensive to compute, callers should compute it separately, using the\nSuggestedFix function below.\n",
65207-							Default: "true",
65208-						},
65209-						{
65210-							Name:    "\"stubmethods\"",
65211-							Doc:     "stub methods analyzer\n\nThis analyzer generates method stubs for concrete types\nin order to implement a target interface",
65212-							Default: "true",
65213-						},
65214-					},
65215-				},
65216-				Default:   "{}",
65217-				Hierarchy: "ui.diagnostic",
65218-			},
65219-			{
65220-				Name:      "staticcheck",
65221-				Type:      "bool",
65222-				Doc:       "staticcheck enables additional analyses from staticcheck.io.\nThese analyses are documented on\n[Staticcheck's website](https://staticcheck.io/docs/checks/).\n",
65223-				Default:   "false",
65224-				Status:    "experimental",
65225-				Hierarchy: "ui.diagnostic",
65226-			},
65227-			{
65228-				Name: "annotations",
65229-				Type: "map[string]bool",
65230-				Doc:  "annotations specifies the various kinds of optimization diagnostics\nthat should be reported by the gc_details command.\n",
65231-				EnumKeys: EnumKeys{
65232-					ValueType: "bool",
65233-					Keys: []EnumKey{
65234-						{
65235-							Name:    "\"bounds\"",
65236-							Doc:     "`\"bounds\"` controls bounds checking diagnostics.\n",
65237-							Default: "true",
65238-						},
65239-						{
65240-							Name:    "\"escape\"",
65241-							Doc:     "`\"escape\"` controls diagnostics about escape choices.\n",
65242-							Default: "true",
65243-						},
65244-						{
65245-							Name:    "\"inline\"",
65246-							Doc:     "`\"inline\"` controls diagnostics about inlining choices.\n",
65247-							Default: "true",
65248-						},
65249-						{
65250-							Name:    "\"nil\"",
65251-							Doc:     "`\"nil\"` controls nil checks.\n",
65252-							Default: "true",
65253-						},
65254-					},
65255-				},
65256-				Default:   "{\"bounds\":true,\"escape\":true,\"inline\":true,\"nil\":true}",
65257-				Status:    "experimental",
65258-				Hierarchy: "ui.diagnostic",
65259-			},
65260-			{
65261-				Name: "vulncheck",
65262-				Type: "enum",
65263-				Doc:  "vulncheck enables vulnerability scanning.\n",
65264-				EnumValues: []EnumValue{
65265-					{
65266-						Value: "\"Imports\"",
65267-						Doc:   "`\"Imports\"`: In Imports mode, `gopls` will report vulnerabilities that affect packages\ndirectly and indirectly used by the analyzed main module.\n",
65268-					},
65269-					{
65270-						Value: "\"Off\"",
65271-						Doc:   "`\"Off\"`: Disable vulnerability analysis.\n",
65272-					},
65273-				},
65274-				Default:   "\"Off\"",
65275-				Status:    "experimental",
65276-				Hierarchy: "ui.diagnostic",
65277-			},
65278-			{
65279-				Name:      "diagnosticsDelay",
65280-				Type:      "time.Duration",
65281-				Doc:       "diagnosticsDelay controls the amount of time that gopls waits\nafter the most recent file modification before computing deep diagnostics.\nSimple diagnostics (parsing and type-checking) are always run immediately\non recently modified packages.\n\nThis option must be set to a valid duration string, for example `\"250ms\"`.\n",
65282-				Default:   "\"250ms\"",
65283-				Status:    "advanced",
65284-				Hierarchy: "ui.diagnostic",
65285-			},
65286-			{
65287-				Name: "hints",
65288-				Type: "map[string]bool",
65289-				Doc:  "hints specify inlay hints that users want to see. A full list of hints\nthat gopls uses can be found in\n[inlayHints.md](https://github.com/golang/tools/blob/master/gopls/doc/inlayHints.md).\n",
65290-				EnumKeys: EnumKeys{Keys: []EnumKey{
65291-					{
65292-						Name:    "\"assignVariableTypes\"",
65293-						Doc:     "Enable/disable inlay hints for variable types in assign statements:\n```go\n\ti/* int*/, j/* int*/ := 0, len(r)-1\n```",
65294-						Default: "false",
65295-					},
65296-					{
65297-						Name:    "\"compositeLiteralFields\"",
65298-						Doc:     "Enable/disable inlay hints for composite literal field names:\n```go\n\t{/*in: */\"Hello, world\", /*want: */\"dlrow ,olleH\"}\n```",
65299-						Default: "false",
65300-					},
65301-					{
65302-						Name:    "\"compositeLiteralTypes\"",
65303-						Doc:     "Enable/disable inlay hints for composite literal types:\n```go\n\tfor _, c := range []struct {\n\t\tin, want string\n\t}{\n\t\t/*struct{ in string; want string }*/{\"Hello, world\", \"dlrow ,olleH\"},\n\t}\n```",
65304-						Default: "false",
65305-					},
65306-					{
65307-						Name:    "\"constantValues\"",
65308-						Doc:     "Enable/disable inlay hints for constant values:\n```go\n\tconst (\n\t\tKindNone   Kind = iota/* = 0*/\n\t\tKindPrint/*  = 1*/\n\t\tKindPrintf/* = 2*/\n\t\tKindErrorf/* = 3*/\n\t)\n```",
65309-						Default: "false",
65310-					},
65311-					{
65312-						Name:    "\"functionTypeParameters\"",
65313-						Doc:     "Enable/disable inlay hints for implicit type parameters on generic functions:\n```go\n\tmyFoo/*[int, string]*/(1, \"hello\")\n```",
65314-						Default: "false",
65315-					},
65316-					{
65317-						Name:    "\"parameterNames\"",
65318-						Doc:     "Enable/disable inlay hints for parameter names:\n```go\n\tparseInt(/* str: */ \"123\", /* radix: */ 8)\n```",
65319-						Default: "false",
65320-					},
65321-					{
65322-						Name:    "\"rangeVariableTypes\"",
65323-						Doc:     "Enable/disable inlay hints for variable types in range statements:\n```go\n\tfor k/* int*/, v/* string*/ := range []string{} {\n\t\tfmt.Println(k, v)\n\t}\n```",
65324-						Default: "false",
65325-					},
65326-				}},
65327-				Default:   "{}",
65328-				Status:    "experimental",
65329-				Hierarchy: "ui.inlayhint",
65330-			},
65331-			{
65332-				Name: "codelenses",
65333-				Type: "map[string]bool",
65334-				Doc:  "codelenses overrides the enabled/disabled state of code lenses. See the\n\"Code Lenses\" section of the\n[Settings page](https://github.com/golang/tools/blob/master/gopls/doc/settings.md#code-lenses)\nfor the list of supported lenses.\n\nExample Usage:\n\n```json5\n\"gopls\": {\n...\n  \"codelenses\": {\n    \"generate\": false,  // Don't show the `go generate` lens.\n    \"gc_details\": true  // Show a code lens toggling the display of gc's choices.\n  }\n...\n}\n```\n",
65335-				EnumKeys: EnumKeys{
65336-					ValueType: "bool",
65337-					Keys: []EnumKey{
65338-						{
65339-							Name:    "\"gc_details\"",
65340-							Doc:     "Toggle the calculation of gc annotations.",
65341-							Default: "false",
65342-						},
65343-						{
65344-							Name:    "\"generate\"",
65345-							Doc:     "Runs `go generate` for a given directory.",
65346-							Default: "true",
65347-						},
65348-						{
65349-							Name:    "\"regenerate_cgo\"",
65350-							Doc:     "Regenerates cgo definitions.",
65351-							Default: "true",
65352-						},
65353-						{
65354-							Name:    "\"run_govulncheck\"",
65355-							Doc:     "Run vulnerability check (`govulncheck`).",
65356-							Default: "false",
65357-						},
65358-						{
65359-							Name:    "\"test\"",
65360-							Doc:     "Runs `go test` for a specific set of test or benchmark functions.",
65361-							Default: "false",
65362-						},
65363-						{
65364-							Name:    "\"tidy\"",
65365-							Doc:     "Runs `go mod tidy` for a module.",
65366-							Default: "true",
65367-						},
65368-						{
65369-							Name:    "\"upgrade_dependency\"",
65370-							Doc:     "Upgrades a dependency in the go.mod file for a module.",
65371-							Default: "true",
65372-						},
65373-						{
65374-							Name:    "\"vendor\"",
65375-							Doc:     "Runs `go mod vendor` for a module.",
65376-							Default: "true",
65377-						},
65378-					},
65379-				},
65380-				Default:   "{\"gc_details\":false,\"generate\":true,\"regenerate_cgo\":true,\"tidy\":true,\"upgrade_dependency\":true,\"vendor\":true}",
65381-				Hierarchy: "ui",
65382-			},
65383-			{
65384-				Name:      "semanticTokens",
65385-				Type:      "bool",
65386-				Doc:       "semanticTokens controls whether the LSP server will send\nsemantic tokens to the client.\n",
65387-				Default:   "false",
65388-				Status:    "experimental",
65389-				Hierarchy: "ui",
65390-			},
65391-			{
65392-				Name:      "noSemanticString",
65393-				Type:      "bool",
65394-				Doc:       "noSemanticString turns off the sending of the semantic token 'string'\n",
65395-				Default:   "false",
65396-				Status:    "experimental",
65397-				Hierarchy: "ui",
65398-			},
65399-			{
65400-				Name:      "noSemanticNumber",
65401-				Type:      "bool",
65402-				Doc:       "noSemanticNumber  turns off the sending of the semantic token 'number'\n",
65403-				Default:   "false",
65404-				Status:    "experimental",
65405-				Hierarchy: "ui",
65406-			},
65407-			{
65408-				Name:      "local",
65409-				Type:      "string",
65410-				Doc:       "local is the equivalent of the `goimports -local` flag, which puts\nimports beginning with this string after third-party packages. It should\nbe the prefix of the import path whose imports should be grouped\nseparately.\n",
65411-				Default:   "\"\"",
65412-				Hierarchy: "formatting",
65413-			},
65414-			{
65415-				Name:      "gofumpt",
65416-				Type:      "bool",
65417-				Doc:       "gofumpt indicates if we should run gofumpt formatting.\n",
65418-				Default:   "false",
65419-				Hierarchy: "formatting",
65420-			},
65421-			{
65422-				Name:    "verboseOutput",
65423-				Type:    "bool",
65424-				Doc:     "verboseOutput enables additional debug logging.\n",
65425-				Default: "false",
65426-				Status:  "debug",
65427-			},
65428-		},
65429-	},
65430-	Commands: []*CommandJSON{
65431-		{
65432-			Command: "gopls.add_dependency",
65433-			Title:   "Add a dependency",
65434-			Doc:     "Adds a dependency to the go.mod file for a module.",
65435-			ArgDoc:  "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// Additional args to pass to the go command.\n\t\"GoCmdArgs\": []string,\n\t// Whether to add a require directive.\n\t\"AddRequire\": bool,\n}",
65436-		},
65437-		{
65438-			Command: "gopls.add_import",
65439-			Title:   "Add an import",
65440-			Doc:     "Ask the server to add an import path to a given Go file.  The method will\ncall applyEdit on the client so that clients don't have to apply the edit\nthemselves.",
65441-			ArgDoc:  "{\n\t// ImportPath is the target import path that should\n\t// be added to the URI file\n\t\"ImportPath\": string,\n\t// URI is the file that the ImportPath should be\n\t// added to\n\t\"URI\": string,\n}",
65442-		},
65443-		{
65444-			Command: "gopls.apply_fix",
65445-			Title:   "Apply a fix",
65446-			Doc:     "Applies a fix to a region of source code.",
65447-			ArgDoc:  "{\n\t// The fix to apply.\n\t\"Fix\": string,\n\t// The file URI for the document to fix.\n\t\"URI\": string,\n\t// The document range to scan for fixes.\n\t\"Range\": {\n\t\t\"start\": {\n\t\t\t\"line\": uint32,\n\t\t\t\"character\": uint32,\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": uint32,\n\t\t\t\"character\": uint32,\n\t\t},\n\t},\n}",
65448-		},
65449-		{
65450-			Command: "gopls.check_upgrades",
65451-			Title:   "Check for upgrades",
65452-			Doc:     "Checks for module upgrades.",
65453-			ArgDoc:  "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// The modules to check.\n\t\"Modules\": []string,\n}",
65454-		},
65455-		{
65456-			Command: "gopls.edit_go_directive",
65457-			Title:   "Run go mod edit -go=version",
65458-			Doc:     "Runs `go mod edit -go=version` for a module.",
65459-			ArgDoc:  "{\n\t// Any document URI within the relevant module.\n\t\"URI\": string,\n\t// The version to pass to `go mod edit -go`.\n\t\"Version\": string,\n}",
65460-		},
65461-		{
65462-			Command:   "gopls.fetch_vulncheck_result",
65463-			Title:     "Get known vulncheck result",
65464-			Doc:       "Fetch the result of latest vulnerability check (`govulncheck`).",
65465-			ArgDoc:    "{\n\t// The file URI.\n\t\"URI\": string,\n}",
65466-			ResultDoc: "map[golang.org/x/tools/gopls/internal/lsp/protocol.DocumentURI]*golang.org/x/tools/gopls/internal/govulncheck.Result",
65467-		},
65468-		{
65469-			Command: "gopls.gc_details",
65470-			Title:   "Toggle gc_details",
65471-			Doc:     "Toggle the calculation of gc annotations.",
65472-			ArgDoc:  "string",
65473-		},
65474-		{
65475-			Command: "gopls.generate",
65476-			Title:   "Run go generate",
65477-			Doc:     "Runs `go generate` for a given directory.",
65478-			ArgDoc:  "{\n\t// URI for the directory to generate.\n\t\"Dir\": string,\n\t// Whether to generate recursively (go generate ./...)\n\t\"Recursive\": bool,\n}",
65479-		},
65480-		{
65481-			Command: "gopls.go_get_package",
65482-			Title:   "go get a package",
65483-			Doc:     "Runs `go get` to fetch a package.",
65484-			ArgDoc:  "{\n\t// Any document URI within the relevant module.\n\t\"URI\": string,\n\t// The package to go get.\n\t\"Pkg\": string,\n\t\"AddRequire\": bool,\n}",
65485-		},
65486-		{
65487-			Command:   "gopls.list_imports",
65488-			Title:     "List imports of a file and its package",
65489-			Doc:       "Retrieve a list of imports in the given Go file, and the package it\nbelongs to.",
65490-			ArgDoc:    "{\n\t// The file URI.\n\t\"URI\": string,\n}",
65491-			ResultDoc: "{\n\t// Imports is a list of imports in the requested file.\n\t\"Imports\": []{\n\t\t\"Path\": string,\n\t\t\"Name\": string,\n\t},\n\t// PackageImports is a list of all imports in the requested file's package.\n\t\"PackageImports\": []{\n\t\t\"Path\": string,\n\t},\n}",
65492-		},
65493-		{
65494-			Command:   "gopls.list_known_packages",
65495-			Title:     "List known packages",
65496-			Doc:       "Retrieve a list of packages that are importable from the given URI.",
65497-			ArgDoc:    "{\n\t// The file URI.\n\t\"URI\": string,\n}",
65498-			ResultDoc: "{\n\t// Packages is a list of packages relative\n\t// to the URIArg passed by the command request.\n\t// In other words, it omits paths that are already\n\t// imported or cannot be imported due to compiler\n\t// restrictions.\n\t\"Packages\": []string,\n}",
65499-		},
65500-		{
65501-			Command:   "gopls.mem_stats",
65502-			Title:     "fetch memory statistics",
65503-			Doc:       "Call runtime.GC multiple times and return memory statistics as reported by\nruntime.MemStats.\n\nThis command is used for benchmarking, and may change in the future.",
65504-			ResultDoc: "{\n\t\"HeapAlloc\": uint64,\n\t\"HeapInUse\": uint64,\n}",
65505-		},
65506-		{
65507-			Command: "gopls.regenerate_cgo",
65508-			Title:   "Regenerate cgo",
65509-			Doc:     "Regenerates cgo definitions.",
65510-			ArgDoc:  "{\n\t// The file URI.\n\t\"URI\": string,\n}",
65511-		},
65512-		{
65513-			Command: "gopls.remove_dependency",
65514-			Title:   "Remove a dependency",
65515-			Doc:     "Removes a dependency from the go.mod file of a module.",
65516-			ArgDoc:  "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// The module path to remove.\n\t\"ModulePath\": string,\n\t\"OnlyDiagnostic\": bool,\n}",
65517-		},
65518-		{
65519-			Command: "gopls.reset_go_mod_diagnostics",
65520-			Title:   "Reset go.mod diagnostics",
65521-			Doc:     "Reset diagnostics in the go.mod file of a module.",
65522-			ArgDoc:  "{\n\t\"URIArg\": {\n\t\t\"URI\": string,\n\t},\n\t// Optional: source of the diagnostics to reset.\n\t// If not set, all resettable go.mod diagnostics will be cleared.\n\t\"DiagnosticSource\": string,\n}",
65523-		},
65524-		{
65525-			Command:   "gopls.run_govulncheck",
65526-			Title:     "Run govulncheck.",
65527-			Doc:       "Run vulnerability check (`govulncheck`).",
65528-			ArgDoc:    "{\n\t// Any document in the directory from which govulncheck will run.\n\t\"URI\": string,\n\t// Package pattern. E.g. \"\", \".\", \"./...\".\n\t\"Pattern\": string,\n}",
65529-			ResultDoc: "{\n\t// Token holds the progress token for LSP workDone reporting of the vulncheck\n\t// invocation.\n\t\"Token\": interface{},\n}",
65530-		},
65531-		{
65532-			Command: "gopls.run_tests",
65533-			Title:   "Run test(s)",
65534-			Doc:     "Runs `go test` for a specific set of test or benchmark functions.",
65535-			ArgDoc:  "{\n\t// The test file containing the tests to run.\n\t\"URI\": string,\n\t// Specific test names to run, e.g. TestFoo.\n\t\"Tests\": []string,\n\t// Specific benchmarks to run, e.g. BenchmarkFoo.\n\t\"Benchmarks\": []string,\n}",
65536-		},
65537-		{
65538-			Command:   "gopls.start_debugging",
65539-			Title:     "Start the gopls debug server",
65540-			Doc:       "Start the gopls debug server if it isn't running, and return the debug\naddress.",
65541-			ArgDoc:    "{\n\t// Optional: the address (including port) for the debug server to listen on.\n\t// If not provided, the debug server will bind to \"localhost:0\", and the\n\t// full debug URL will be contained in the result.\n\t// \n\t// If there is more than one gopls instance along the serving path (i.e. you\n\t// are using a daemon), each gopls instance will attempt to start debugging.\n\t// If Addr specifies a port, only the daemon will be able to bind to that\n\t// port, and each intermediate gopls instance will fail to start debugging.\n\t// For this reason it is recommended not to specify a port (or equivalently,\n\t// to specify \":0\").\n\t// \n\t// If the server was already debugging this field has no effect, and the\n\t// result will contain the previously configured debug URL(s).\n\t\"Addr\": string,\n}",
65542-			ResultDoc: "{\n\t// The URLs to use to access the debug servers, for all gopls instances in\n\t// the serving path. For the common case of a single gopls instance (i.e. no\n\t// daemon), this will be exactly one address.\n\t// \n\t// In the case of one or more gopls instances forwarding the LSP to a daemon,\n\t// URLs will contain debug addresses for each server in the serving path, in\n\t// serving order. The daemon debug address will be the last entry in the\n\t// slice. If any intermediate gopls instance fails to start debugging, no\n\t// error will be returned but the debug URL for that server in the URLs slice\n\t// will be empty.\n\t\"URLs\": []string,\n}",
65543-		},
65544-		{
65545-			Command: "gopls.test",
65546-			Title:   "Run test(s) (legacy)",
65547-			Doc:     "Runs `go test` for a specific set of test or benchmark functions.",
65548-			ArgDoc:  "string,\n[]string,\n[]string",
65549-		},
65550-		{
65551-			Command: "gopls.tidy",
65552-			Title:   "Run go mod tidy",
65553-			Doc:     "Runs `go mod tidy` for a module.",
65554-			ArgDoc:  "{\n\t// The file URIs.\n\t\"URIs\": []string,\n}",
65555-		},
65556-		{
65557-			Command: "gopls.toggle_gc_details",
65558-			Title:   "Toggle gc_details",
65559-			Doc:     "Toggle the calculation of gc annotations.",
65560-			ArgDoc:  "{\n\t// The file URI.\n\t\"URI\": string,\n}",
65561-		},
65562-		{
65563-			Command: "gopls.update_go_sum",
65564-			Title:   "Update go.sum",
65565-			Doc:     "Updates the go.sum file for a module.",
65566-			ArgDoc:  "{\n\t// The file URIs.\n\t\"URIs\": []string,\n}",
65567-		},
65568-		{
65569-			Command: "gopls.upgrade_dependency",
65570-			Title:   "Upgrade a dependency",
65571-			Doc:     "Upgrades a dependency in the go.mod file for a module.",
65572-			ArgDoc:  "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// Additional args to pass to the go command.\n\t\"GoCmdArgs\": []string,\n\t// Whether to add a require directive.\n\t\"AddRequire\": bool,\n}",
65573-		},
65574-		{
65575-			Command: "gopls.vendor",
65576-			Title:   "Run go mod vendor",
65577-			Doc:     "Runs `go mod vendor` for a module.",
65578-			ArgDoc:  "{\n\t// The file URI.\n\t\"URI\": string,\n}",
65579-		},
65580-	},
65581-	Lenses: []*LensJSON{
65582-		{
65583-			Lens:  "gc_details",
65584-			Title: "Toggle gc_details",
65585-			Doc:   "Toggle the calculation of gc annotations.",
65586-		},
65587-		{
65588-			Lens:  "generate",
65589-			Title: "Run go generate",
65590-			Doc:   "Runs `go generate` for a given directory.",
65591-		},
65592-		{
65593-			Lens:  "regenerate_cgo",
65594-			Title: "Regenerate cgo",
65595-			Doc:   "Regenerates cgo definitions.",
65596-		},
65597-		{
65598-			Lens:  "run_govulncheck",
65599-			Title: "Run govulncheck.",
65600-			Doc:   "Run vulnerability check (`govulncheck`).",
65601-		},
65602-		{
65603-			Lens:  "test",
65604-			Title: "Run test(s) (legacy)",
65605-			Doc:   "Runs `go test` for a specific set of test or benchmark functions.",
65606-		},
65607-		{
65608-			Lens:  "tidy",
65609-			Title: "Run go mod tidy",
65610-			Doc:   "Runs `go mod tidy` for a module.",
65611-		},
65612-		{
65613-			Lens:  "upgrade_dependency",
65614-			Title: "Upgrade a dependency",
65615-			Doc:   "Upgrades a dependency in the go.mod file for a module.",
65616-		},
65617-		{
65618-			Lens:  "vendor",
65619-			Title: "Run go mod vendor",
65620-			Doc:   "Runs `go mod vendor` for a module.",
65621-		},
65622-	},
65623-	Analyzers: []*AnalyzerJSON{
65624-		{
65625-			Name:    "asmdecl",
65626-			Doc:     "report mismatches between assembly files and Go declarations",
65627-			Default: true,
65628-		},
65629-		{
65630-			Name:    "assign",
65631-			Doc:     "check for useless assignments\n\nThis checker reports assignments of the form x = x or a[i] = a[i].\nThese are almost always useless, and even when they aren't they are\nusually a mistake.",
65632-			Default: true,
65633-		},
65634-		{
65635-			Name:    "atomic",
65636-			Doc:     "check for common mistakes using the sync/atomic package\n\nThe atomic checker looks for assignment statements of the form:\n\n\tx = atomic.AddUint64(&x, 1)\n\nwhich are not atomic.",
65637-			Default: true,
65638-		},
65639-		{
65640-			Name:    "atomicalign",
65641-			Doc:     "check for non-64-bits-aligned arguments to sync/atomic functions",
65642-			Default: true,
65643-		},
65644-		{
65645-			Name:    "bools",
65646-			Doc:     "check for common mistakes involving boolean operators",
65647-			Default: true,
65648-		},
65649-		{
65650-			Name:    "buildtag",
65651-			Doc:     "check //go:build and // +build directives",
65652-			Default: true,
65653-		},
65654-		{
65655-			Name:    "cgocall",
65656-			Doc:     "detect some violations of the cgo pointer passing rules\n\nCheck for invalid cgo pointer passing.\nThis looks for code that uses cgo to call C code passing values\nwhose types are almost always invalid according to the cgo pointer\nsharing rules.\nSpecifically, it warns about attempts to pass a Go chan, map, func,\nor slice to C, either directly, or via a pointer, array, or struct.",
65657-			Default: true,
65658-		},
65659-		{
65660-			Name:    "composites",
65661-			Doc:     "check for unkeyed composite literals\n\nThis analyzer reports a diagnostic for composite literals of struct\ntypes imported from another package that do not use the field-keyed\nsyntax. Such literals are fragile because the addition of a new field\n(even if unexported) to the struct will cause compilation to fail.\n\nAs an example,\n\n\terr = &net.DNSConfigError{err}\n\nshould be replaced by:\n\n\terr = &net.DNSConfigError{Err: err}\n",
65662-			Default: true,
65663-		},
65664-		{
65665-			Name:    "copylocks",
65666-			Doc:     "check for locks erroneously passed by value\n\nInadvertently copying a value containing a lock, such as sync.Mutex or\nsync.WaitGroup, may cause both copies to malfunction. Generally such\nvalues should be referred to through a pointer.",
65667-			Default: true,
65668-		},
65669-		{
65670-			Name:    "deepequalerrors",
65671-			Doc:     "check for calls of reflect.DeepEqual on error values\n\nThe deepequalerrors checker looks for calls of the form:\n\n    reflect.DeepEqual(err1, err2)\n\nwhere err1 and err2 are errors. Using reflect.DeepEqual to compare\nerrors is discouraged.",
65672-			Default: true,
65673-		},
65674-		{
65675-			Name:    "directive",
65676-			Doc:     "check Go toolchain directives such as //go:debug\n\nThis analyzer checks for problems with known Go toolchain directives\nin all Go source files in a package directory, even those excluded by\n//go:build constraints, and all non-Go source files too.\n\nFor //go:debug (see https://go.dev/doc/godebug), the analyzer checks\nthat the directives are placed only in Go source files, only above the\npackage comment, and only in package main or *_test.go files.\n\nSupport for other known directives may be added in the future.\n\nThis analyzer does not check //go:build, which is handled by the\nbuildtag analyzer.\n",
65677-			Default: true,
65678-		},
65679-		{
65680-			Name:    "embed",
65681-			Doc:     "check for //go:embed directive import\n\nThis analyzer checks that the embed package is imported when source code contains //go:embed comment directives.\nThe embed package must be imported for //go:embed directives to function.import _ \"embed\".",
65682-			Default: true,
65683-		},
65684-		{
65685-			Name:    "errorsas",
65686-			Doc:     "report passing non-pointer or non-error values to errors.As\n\nThe errorsas analysis reports calls to errors.As where the type\nof the second argument is not a pointer to a type implementing error.",
65687-			Default: true,
65688-		},
65689-		{
65690-			Name: "fieldalignment",
65691-			Doc:  "find structs that would use less memory if their fields were sorted\n\nThis analyzer find structs that can be rearranged to use less memory, and provides\na suggested edit with the most compact order.\n\nNote that there are two different diagnostics reported. One checks struct size,\nand the other reports \"pointer bytes\" used. Pointer bytes is how many bytes of the\nobject that the garbage collector has to potentially scan for pointers, for example:\n\n\tstruct { uint32; string }\n\nhave 16 pointer bytes because the garbage collector has to scan up through the string's\ninner pointer.\n\n\tstruct { string; *uint32 }\n\nhas 24 pointer bytes because it has to scan further through the *uint32.\n\n\tstruct { string; uint32 }\n\nhas 8 because it can stop immediately after the string pointer.\n\nBe aware that the most compact order is not always the most efficient.\nIn rare cases it may cause two variables each updated by its own goroutine\nto occupy the same CPU cache line, inducing a form of memory contention\nknown as \"false sharing\" that slows down both goroutines.\n",
65692-		},
65693-		{
65694-			Name:    "httpresponse",
65695-			Doc:     "check for mistakes using HTTP responses\n\nA common mistake when using the net/http package is to defer a function\ncall to close the http.Response Body before checking the error that\ndetermines whether the response is valid:\n\n\tresp, err := http.Head(url)\n\tdefer resp.Body.Close()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t// (defer statement belongs here)\n\nThis checker helps uncover latent nil dereference bugs by reporting a\ndiagnostic for such mistakes.",
65696-			Default: true,
65697-		},
65698-		{
65699-			Name:    "ifaceassert",
65700-			Doc:     "detect impossible interface-to-interface type assertions\n\nThis checker flags type assertions v.(T) and corresponding type-switch cases\nin which the static type V of v is an interface that cannot possibly implement\nthe target interface T. This occurs when V and T contain methods with the same\nname but different signatures. Example:\n\n\tvar v interface {\n\t\tRead()\n\t}\n\t_ = v.(io.Reader)\n\nThe Read method in v has a different signature than the Read method in\nio.Reader, so this assertion cannot succeed.\n",
65701-			Default: true,
65702-		},
65703-		{
65704-			Name:    "infertypeargs",
65705-			Doc:     "check for unnecessary type arguments in call expressions\n\nExplicit type arguments may be omitted from call expressions if they can be\ninferred from function arguments, or from other type arguments:\n\n\tfunc f[T any](T) {}\n\t\n\tfunc _() {\n\t\tf[string](\"foo\") // string could be inferred\n\t}\n",
65706-			Default: true,
65707-		},
65708-		{
65709-			Name:    "loopclosure",
65710-			Doc:     "check references to loop variables from within nested functions\n\nThis analyzer reports places where a function literal references the\niteration variable of an enclosing loop, and the loop calls the function\nin such a way (e.g. with go or defer) that it may outlive the loop\niteration and possibly observe the wrong value of the variable.\n\nIn this example, all the deferred functions run after the loop has\ncompleted, so all observe the final value of v.\n\n    for _, v := range list {\n        defer func() {\n            use(v) // incorrect\n        }()\n    }\n\nOne fix is to create a new variable for each iteration of the loop:\n\n    for _, v := range list {\n        v := v // new var per iteration\n        defer func() {\n            use(v) // ok\n        }()\n    }\n\nThe next example uses a go statement and has a similar problem.\nIn addition, it has a data race because the loop updates v\nconcurrent with the goroutines accessing it.\n\n    for _, v := range elem {\n        go func() {\n            use(v)  // incorrect, and a data race\n        }()\n    }\n\nA fix is the same as before. The checker also reports problems\nin goroutines started by golang.org/x/sync/errgroup.Group.\nA hard-to-spot variant of this form is common in parallel tests:\n\n    func Test(t *testing.T) {\n        for _, test := range tests {\n            t.Run(test.name, func(t *testing.T) {\n                t.Parallel()\n                use(test) // incorrect, and a data race\n            })\n        }\n    }\n\nThe t.Parallel() call causes the rest of the function to execute\nconcurrent with the loop.\n\nThe analyzer reports references only in the last statement,\nas it is not deep enough to understand the effects of subsequent\nstatements that might render the reference benign.\n(\"Last statement\" is defined recursively in compound\nstatements such as if, switch, and select.)\n\nSee: https://golang.org/doc/go_faq.html#closures_and_goroutines",
65711-			Default: true,
65712-		},
65713-		{
65714-			Name:    "lostcancel",
65715-			Doc:     "check cancel func returned by context.WithCancel is called\n\nThe cancellation function returned by context.WithCancel, WithTimeout,\nand WithDeadline must be called or the new context will remain live\nuntil its parent context is cancelled.\n(The background context is never cancelled.)",
65716-			Default: true,
65717-		},
65718-		{
65719-			Name:    "nilfunc",
65720-			Doc:     "check for useless comparisons between functions and nil\n\nA useless comparison is one like f == nil as opposed to f() == nil.",
65721-			Default: true,
65722-		},
65723-		{
65724-			Name: "nilness",
65725-			Doc:  "check for redundant or impossible nil comparisons\n\nThe nilness checker inspects the control-flow graph of each function in\na package and reports nil pointer dereferences, degenerate nil\npointers, and panics with nil values. A degenerate comparison is of the form\nx==nil or x!=nil where x is statically known to be nil or non-nil. These are\noften a mistake, especially in control flow related to errors. Panics with nil\nvalues are checked because they are not detectable by\n\n\tif r := recover(); r != nil {\n\nThis check reports conditions such as:\n\n\tif f == nil { // impossible condition (f is a function)\n\t}\n\nand:\n\n\tp := &v\n\t...\n\tif p != nil { // tautological condition\n\t}\n\nand:\n\n\tif p == nil {\n\t\tprint(*p) // nil dereference\n\t}\n\nand:\n\n\tif p == nil {\n\t\tpanic(p)\n\t}\n",
65726-		},
65727-		{
65728-			Name:    "printf",
65729-			Doc:     "check consistency of Printf format strings and arguments\n\nThe check applies to known functions (for example, those in package fmt)\nas well as any detected wrappers of known functions.\n\nA function that wants to avail itself of printf checking but is not\nfound by this analyzer's heuristics (for example, due to use of\ndynamic calls) can insert a bogus call:\n\n\tif false {\n\t\t_ = fmt.Sprintf(format, args...) // enable printf checking\n\t}\n\nThe -funcs flag specifies a comma-separated list of names of additional\nknown formatting functions or methods. If the name contains a period,\nit must denote a specific function using one of the following forms:\n\n\tdir/pkg.Function\n\tdir/pkg.Type.Method\n\t(*dir/pkg.Type).Method\n\nOtherwise the name is interpreted as a case-insensitive unqualified\nidentifier such as \"errorf\". Either way, if a listed name ends in f, the\nfunction is assumed to be Printf-like, taking a format string before the\nargument list. Otherwise it is assumed to be Print-like, taking a list\nof arguments with no format string.\n",
65730-			Default: true,
65731-		},
65732-		{
65733-			Name: "shadow",
65734-			Doc:  "check for possible unintended shadowing of variables\n\nThis analyzer check for shadowed variables.\nA shadowed variable is a variable declared in an inner scope\nwith the same name and type as a variable in an outer scope,\nand where the outer variable is mentioned after the inner one\nis declared.\n\n(This definition can be refined; the module generates too many\nfalse positives and is not yet enabled by default.)\n\nFor example:\n\n\tfunc BadRead(f *os.File, buf []byte) error {\n\t\tvar err error\n\t\tfor {\n\t\t\tn, err := f.Read(buf) // shadows the function variable 'err'\n\t\t\tif err != nil {\n\t\t\t\tbreak // causes return of wrong value\n\t\t\t}\n\t\t\tfoo(buf)\n\t\t}\n\t\treturn err\n\t}\n",
65735-		},
65736-		{
65737-			Name:    "shift",
65738-			Doc:     "check for shifts that equal or exceed the width of the integer",
65739-			Default: true,
65740-		},
65741-		{
65742-			Name:    "simplifycompositelit",
65743-			Doc:     "check for composite literal simplifications\n\nAn array, slice, or map composite literal of the form:\n\t[]T{T{}, T{}}\nwill be simplified to:\n\t[]T{{}, {}}\n\nThis is one of the simplifications that \"gofmt -s\" applies.",
65744-			Default: true,
65745-		},
65746-		{
65747-			Name:    "simplifyrange",
65748-			Doc:     "check for range statement simplifications\n\nA range of the form:\n\tfor x, _ = range v {...}\nwill be simplified to:\n\tfor x = range v {...}\n\nA range of the form:\n\tfor _ = range v {...}\nwill be simplified to:\n\tfor range v {...}\n\nThis is one of the simplifications that \"gofmt -s\" applies.",
65749-			Default: true,
65750-		},
65751-		{
65752-			Name:    "simplifyslice",
65753-			Doc:     "check for slice simplifications\n\nA slice expression of the form:\n\ts[a:len(s)]\nwill be simplified to:\n\ts[a:]\n\nThis is one of the simplifications that \"gofmt -s\" applies.",
65754-			Default: true,
65755-		},
65756-		{
65757-			Name:    "sortslice",
65758-			Doc:     "check the argument type of sort.Slice\n\nsort.Slice requires an argument of a slice type. Check that\nthe interface{} value passed to sort.Slice is actually a slice.",
65759-			Default: true,
65760-		},
65761-		{
65762-			Name:    "stdmethods",
65763-			Doc:     "check signature of methods of well-known interfaces\n\nSometimes a type may be intended to satisfy an interface but may fail to\ndo so because of a mistake in its method signature.\nFor example, the result of this WriteTo method should be (int64, error),\nnot error, to satisfy io.WriterTo:\n\n\ttype myWriterTo struct{...}\n        func (myWriterTo) WriteTo(w io.Writer) error { ... }\n\nThis check ensures that each method whose name matches one of several\nwell-known interface methods from the standard library has the correct\nsignature for that interface.\n\nChecked method names include:\n\tFormat GobEncode GobDecode MarshalJSON MarshalXML\n\tPeek ReadByte ReadFrom ReadRune Scan Seek\n\tUnmarshalJSON UnreadByte UnreadRune WriteByte\n\tWriteTo\n",
65764-			Default: true,
65765-		},
65766-		{
65767-			Name:    "stringintconv",
65768-			Doc:     "check for string(int) conversions\n\nThis checker flags conversions of the form string(x) where x is an integer\n(but not byte or rune) type. Such conversions are discouraged because they\nreturn the UTF-8 representation of the Unicode code point x, and not a decimal\nstring representation of x as one might expect. Furthermore, if x denotes an\ninvalid code point, the conversion cannot be statically rejected.\n\nFor conversions that intend on using the code point, consider replacing them\nwith string(rune(x)). Otherwise, strconv.Itoa and its equivalents return the\nstring representation of the value in the desired base.\n",
65769-			Default: true,
65770-		},
65771-		{
65772-			Name:    "structtag",
65773-			Doc:     "check that struct field tags conform to reflect.StructTag.Get\n\nAlso report certain struct tags (json, xml) used with unexported fields.",
65774-			Default: true,
65775-		},
65776-		{
65777-			Name:    "testinggoroutine",
65778-			Doc:     "report calls to (*testing.T).Fatal from goroutines started by a test.\n\nFunctions that abruptly terminate a test, such as the Fatal, Fatalf, FailNow, and\nSkip{,f,Now} methods of *testing.T, must be called from the test goroutine itself.\nThis checker detects calls to these functions that occur within a goroutine\nstarted by the test. For example:\n\nfunc TestFoo(t *testing.T) {\n    go func() {\n        t.Fatal(\"oops\") // error: (*T).Fatal called from non-test goroutine\n    }()\n}\n",
65779-			Default: true,
65780-		},
65781-		{
65782-			Name:    "tests",
65783-			Doc:     "check for common mistaken usages of tests and examples\n\nThe tests checker walks Test, Benchmark and Example functions checking\nmalformed names, wrong signatures and examples documenting non-existent\nidentifiers.\n\nPlease see the documentation for package testing in golang.org/pkg/testing\nfor the conventions that are enforced for Tests, Benchmarks, and Examples.",
65784-			Default: true,
65785-		},
65786-		{
65787-			Name:    "timeformat",
65788-			Doc:     "check for calls of (time.Time).Format or time.Parse with 2006-02-01\n\nThe timeformat checker looks for time formats with the 2006-02-01 (yyyy-dd-mm)\nformat. Internationally, \"yyyy-dd-mm\" does not occur in common calendar date\nstandards, and so it is more likely that 2006-01-02 (yyyy-mm-dd) was intended.\n",
65789-			Default: true,
65790-		},
65791-		{
65792-			Name:    "unmarshal",
65793-			Doc:     "report passing non-pointer or non-interface values to unmarshal\n\nThe unmarshal analysis reports calls to functions such as json.Unmarshal\nin which the argument type is not a pointer or an interface.",
65794-			Default: true,
65795-		},
65796-		{
65797-			Name:    "unreachable",
65798-			Doc:     "check for unreachable code\n\nThe unreachable analyzer finds statements that execution can never reach\nbecause they are preceded by an return statement, a call to panic, an\ninfinite loop, or similar constructs.",
65799-			Default: true,
65800-		},
65801-		{
65802-			Name:    "unsafeptr",
65803-			Doc:     "check for invalid conversions of uintptr to unsafe.Pointer\n\nThe unsafeptr analyzer reports likely incorrect uses of unsafe.Pointer\nto convert integers to pointers. A conversion from uintptr to\nunsafe.Pointer is invalid if it implies that there is a uintptr-typed\nword in memory that holds a pointer value, because that word will be\ninvisible to stack copying and to the garbage collector.",
65804-			Default: true,
65805-		},
65806-		{
65807-			Name: "unusedparams",
65808-			Doc:  "check for unused parameters of functions\n\nThe unusedparams analyzer checks functions to see if there are\nany parameters that are not being used.\n\nTo reduce false positives it ignores:\n- methods\n- parameters that do not have a name or are underscored\n- functions in test files\n- functions with empty bodies or those with just a return stmt",
65809-		},
65810-		{
65811-			Name:    "unusedresult",
65812-			Doc:     "check for unused results of calls to some functions\n\nSome functions like fmt.Errorf return a result and have no side effects,\nso it is always a mistake to discard the result. This analyzer reports\ncalls to certain functions in which the result of the call is ignored.\n\nThe set of functions may be controlled using flags.",
65813-			Default: true,
65814-		},
65815-		{
65816-			Name: "unusedwrite",
65817-			Doc:  "checks for unused writes\n\nThe analyzer reports instances of writes to struct fields and\narrays that are never read. Specifically, when a struct object\nor an array is copied, its elements are copied implicitly by\nthe compiler, and any element write to this copy does nothing\nwith the original object.\n\nFor example:\n\n\ttype T struct { x int }\n\tfunc f(input []T) {\n\t\tfor i, v := range input {  // v is a copy\n\t\t\tv.x = i  // unused write to field x\n\t\t}\n\t}\n\nAnother example is about non-pointer receiver:\n\n\ttype T struct { x int }\n\tfunc (t T) f() {  // t is a copy\n\t\tt.x = i  // unused write to field x\n\t}\n",
65818-		},
65819-		{
65820-			Name: "useany",
65821-			Doc:  "check for constraints that could be simplified to \"any\"",
65822-		},
65823-		{
65824-			Name:    "fillreturns",
65825-			Doc:     "suggest fixes for errors due to an incorrect number of return values\n\nThis checker provides suggested fixes for type errors of the\ntype \"wrong number of return values (want %d, got %d)\". For example:\n\tfunc m() (int, string, *bool, error) {\n\t\treturn\n\t}\nwill turn into\n\tfunc m() (int, string, *bool, error) {\n\t\treturn 0, \"\", nil, nil\n\t}\n\nThis functionality is similar to https://github.com/sqs/goreturns.\n",
65826-			Default: true,
65827-		},
65828-		{
65829-			Name:    "nonewvars",
65830-			Doc:     "suggested fixes for \"no new vars on left side of :=\"\n\nThis checker provides suggested fixes for type errors of the\ntype \"no new vars on left side of :=\". For example:\n\tz := 1\n\tz := 2\nwill turn into\n\tz := 1\n\tz = 2\n",
65831-			Default: true,
65832-		},
65833-		{
65834-			Name:    "noresultvalues",
65835-			Doc:     "suggested fixes for unexpected return values\n\nThis checker provides suggested fixes for type errors of the\ntype \"no result values expected\" or \"too many return values\".\nFor example:\n\tfunc z() { return nil }\nwill turn into\n\tfunc z() { return }\n",
65836-			Default: true,
65837-		},
65838-		{
65839-			Name:    "undeclaredname",
65840-			Doc:     "suggested fixes for \"undeclared name: <>\"\n\nThis checker provides suggested fixes for type errors of the\ntype \"undeclared name: <>\". It will either insert a new statement,\nsuch as:\n\n\"<> := \"\n\nor a new function declaration, such as:\n\nfunc <>(inferred parameters) {\n\tpanic(\"implement me!\")\n}\n",
65841-			Default: true,
65842-		},
65843-		{
65844-			Name: "unusedvariable",
65845-			Doc:  "check for unused variables\n\nThe unusedvariable analyzer suggests fixes for unused variables errors.\n",
65846-		},
65847-		{
65848-			Name:    "fillstruct",
65849-			Doc:     "note incomplete struct initializations\n\nThis analyzer provides diagnostics for any struct literals that do not have\nany fields initialized. Because the suggested fix for this analysis is\nexpensive to compute, callers should compute it separately, using the\nSuggestedFix function below.\n",
65850-			Default: true,
65851-		},
65852-		{
65853-			Name:    "stubmethods",
65854-			Doc:     "stub methods analyzer\n\nThis analyzer generates method stubs for concrete types\nin order to implement a target interface",
65855-			Default: true,
65856-		},
65857-	},
65858-	Hints: []*HintJSON{
65859-		{
65860-			Name: "assignVariableTypes",
65861-			Doc:  "Enable/disable inlay hints for variable types in assign statements:\n```go\n\ti/* int*/, j/* int*/ := 0, len(r)-1\n```",
65862-		},
65863-		{
65864-			Name: "compositeLiteralFields",
65865-			Doc:  "Enable/disable inlay hints for composite literal field names:\n```go\n\t{/*in: */\"Hello, world\", /*want: */\"dlrow ,olleH\"}\n```",
65866-		},
65867-		{
65868-			Name: "compositeLiteralTypes",
65869-			Doc:  "Enable/disable inlay hints for composite literal types:\n```go\n\tfor _, c := range []struct {\n\t\tin, want string\n\t}{\n\t\t/*struct{ in string; want string }*/{\"Hello, world\", \"dlrow ,olleH\"},\n\t}\n```",
65870-		},
65871-		{
65872-			Name: "constantValues",
65873-			Doc:  "Enable/disable inlay hints for constant values:\n```go\n\tconst (\n\t\tKindNone   Kind = iota/* = 0*/\n\t\tKindPrint/*  = 1*/\n\t\tKindPrintf/* = 2*/\n\t\tKindErrorf/* = 3*/\n\t)\n```",
65874-		},
65875-		{
65876-			Name: "functionTypeParameters",
65877-			Doc:  "Enable/disable inlay hints for implicit type parameters on generic functions:\n```go\n\tmyFoo/*[int, string]*/(1, \"hello\")\n```",
65878-		},
65879-		{
65880-			Name: "parameterNames",
65881-			Doc:  "Enable/disable inlay hints for parameter names:\n```go\n\tparseInt(/* str: */ \"123\", /* radix: */ 8)\n```",
65882-		},
65883-		{
65884-			Name: "rangeVariableTypes",
65885-			Doc:  "Enable/disable inlay hints for variable types in range statements:\n```go\n\tfor k/* int*/, v/* string*/ := range []string{} {\n\t\tfmt.Println(k, v)\n\t}\n```",
65886-		},
65887-	},
65888-}
65889diff -urN a/gopls/internal/lsp/source/call_hierarchy.go b/gopls/internal/lsp/source/call_hierarchy.go
65890--- a/gopls/internal/lsp/source/call_hierarchy.go	2000-01-01 00:00:00.000000000 -0000
65891+++ b/gopls/internal/lsp/source/call_hierarchy.go	1970-01-01 00:00:00.000000000 +0000
65892@@ -1,311 +0,0 @@
65893-// Copyright 2020 The Go Authors. All rights reserved.
65894-// Use of this source code is governed by a BSD-style
65895-// license that can be found in the LICENSE file.
65896-
65897-package source
65898-
65899-import (
65900-	"context"
65901-	"errors"
65902-	"fmt"
65903-	"go/ast"
65904-	"go/token"
65905-	"go/types"
65906-	"path/filepath"
65907-
65908-	"golang.org/x/tools/go/ast/astutil"
65909-	"golang.org/x/tools/gopls/internal/lsp/protocol"
65910-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
65911-	"golang.org/x/tools/gopls/internal/span"
65912-	"golang.org/x/tools/internal/bug"
65913-	"golang.org/x/tools/internal/event"
65914-	"golang.org/x/tools/internal/event/tag"
65915-)
65916-
65917-// PrepareCallHierarchy returns an array of CallHierarchyItem for a file and the position within the file.
65918-func PrepareCallHierarchy(ctx context.Context, snapshot Snapshot, fh FileHandle, pp protocol.Position) ([]protocol.CallHierarchyItem, error) {
65919-	ctx, done := event.Start(ctx, "source.PrepareCallHierarchy")
65920-	defer done()
65921-
65922-	pkg, pgf, err := PackageForFile(ctx, snapshot, fh.URI(), NarrowestPackage)
65923-	if err != nil {
65924-		return nil, err
65925-	}
65926-	pos, err := pgf.PositionPos(pp)
65927-	if err != nil {
65928-		return nil, err
65929-	}
65930-
65931-	_, obj, _ := referencedObject(pkg, pgf, pos)
65932-	if obj == nil {
65933-		return nil, nil
65934-	}
65935-
65936-	if _, ok := obj.Type().Underlying().(*types.Signature); !ok {
65937-		return nil, nil
65938-	}
65939-
65940-	declLoc, err := mapPosition(ctx, pkg.FileSet(), snapshot, obj.Pos(), adjustedObjEnd(obj))
65941-	if err != nil {
65942-		return nil, err
65943-	}
65944-	rng := declLoc.Range
65945-
65946-	callHierarchyItem := protocol.CallHierarchyItem{
65947-		Name:           obj.Name(),
65948-		Kind:           protocol.Function,
65949-		Tags:           []protocol.SymbolTag{},
65950-		Detail:         fmt.Sprintf("%s • %s", obj.Pkg().Path(), filepath.Base(declLoc.URI.SpanURI().Filename())),
65951-		URI:            declLoc.URI,
65952-		Range:          rng,
65953-		SelectionRange: rng,
65954-	}
65955-	return []protocol.CallHierarchyItem{callHierarchyItem}, nil
65956-}
65957-
65958-// IncomingCalls returns an array of CallHierarchyIncomingCall for a file and the position within the file.
65959-func IncomingCalls(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protocol.Position) ([]protocol.CallHierarchyIncomingCall, error) {
65960-	ctx, done := event.Start(ctx, "source.IncomingCalls")
65961-	defer done()
65962-
65963-	refs, err := references(ctx, snapshot, fh, pos, false)
65964-	if err != nil {
65965-		if errors.Is(err, ErrNoIdentFound) || errors.Is(err, errNoObjectFound) {
65966-			return nil, nil
65967-		}
65968-		return nil, err
65969-	}
65970-
65971-	// Group references by their enclosing function declaration.
65972-	incomingCalls := make(map[protocol.Location]*protocol.CallHierarchyIncomingCall)
65973-	for _, ref := range refs {
65974-		callItem, err := enclosingNodeCallItem(ctx, snapshot, ref.pkgPath, ref.location)
65975-		if err != nil {
65976-			event.Error(ctx, "error getting enclosing node", err, tag.Method.Of(string(ref.pkgPath)))
65977-			continue
65978-		}
65979-		loc := protocol.Location{
65980-			URI:   callItem.URI,
65981-			Range: callItem.Range,
65982-		}
65983-		call, ok := incomingCalls[loc]
65984-		if !ok {
65985-			call = &protocol.CallHierarchyIncomingCall{From: callItem}
65986-			incomingCalls[loc] = call
65987-		}
65988-		call.FromRanges = append(call.FromRanges, ref.location.Range)
65989-	}
65990-
65991-	// Flatten the map of pointers into a slice of values.
65992-	incomingCallItems := make([]protocol.CallHierarchyIncomingCall, 0, len(incomingCalls))
65993-	for _, callItem := range incomingCalls {
65994-		incomingCallItems = append(incomingCallItems, *callItem)
65995-	}
65996-	return incomingCallItems, nil
65997-}
65998-
65999-// enclosingNodeCallItem creates a CallHierarchyItem representing the function call at loc.
66000-func enclosingNodeCallItem(ctx context.Context, snapshot Snapshot, pkgPath PackagePath, loc protocol.Location) (protocol.CallHierarchyItem, error) {
66001-	// Parse the file containing the reference.
66002-	fh, err := snapshot.GetFile(ctx, loc.URI.SpanURI())
66003-	if err != nil {
66004-		return protocol.CallHierarchyItem{}, err
66005-	}
66006-	// TODO(adonovan): opt: before parsing, trim the bodies of functions
66007-	// that don't contain the reference, using either a scanner-based
66008-	// implementation such as https://go.dev/play/p/KUrObH1YkX8
66009-	// (~31% speedup), or a byte-oriented implementation (2x speedup).
66010-	pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
66011-	if err != nil {
66012-		return protocol.CallHierarchyItem{}, err
66013-	}
66014-	start, end, err := pgf.RangePos(loc.Range)
66015-	if err != nil {
66016-		return protocol.CallHierarchyItem{}, err
66017-	}
66018-
66019-	// Find the enclosing function, if any, and the number of func literals in between.
66020-	var funcDecl *ast.FuncDecl
66021-	var funcLit *ast.FuncLit // innermost function literal
66022-	var litCount int
66023-	path, _ := astutil.PathEnclosingInterval(pgf.File, start, end)
66024-outer:
66025-	for _, node := range path {
66026-		switch n := node.(type) {
66027-		case *ast.FuncDecl:
66028-			funcDecl = n
66029-			break outer
66030-		case *ast.FuncLit:
66031-			litCount++
66032-			if litCount > 1 {
66033-				continue
66034-			}
66035-			funcLit = n
66036-		}
66037-	}
66038-
66039-	nameIdent := path[len(path)-1].(*ast.File).Name
66040-	kind := protocol.Package
66041-	if funcDecl != nil {
66042-		nameIdent = funcDecl.Name
66043-		kind = protocol.Function
66044-	}
66045-
66046-	nameStart, nameEnd := nameIdent.Pos(), nameIdent.End()
66047-	if funcLit != nil {
66048-		nameStart, nameEnd = funcLit.Type.Func, funcLit.Type.Params.Pos()
66049-		kind = protocol.Function
66050-	}
66051-	rng, err := pgf.PosRange(nameStart, nameEnd)
66052-	if err != nil {
66053-		return protocol.CallHierarchyItem{}, err
66054-	}
66055-
66056-	name := nameIdent.Name
66057-	for i := 0; i < litCount; i++ {
66058-		name += ".func()"
66059-	}
66060-
66061-	return protocol.CallHierarchyItem{
66062-		Name:           name,
66063-		Kind:           kind,
66064-		Tags:           []protocol.SymbolTag{},
66065-		Detail:         fmt.Sprintf("%s • %s", pkgPath, filepath.Base(fh.URI().Filename())),
66066-		URI:            loc.URI,
66067-		Range:          rng,
66068-		SelectionRange: rng,
66069-	}, nil
66070-}
66071-
66072-// OutgoingCalls returns an array of CallHierarchyOutgoingCall for a file and the position within the file.
66073-func OutgoingCalls(ctx context.Context, snapshot Snapshot, fh FileHandle, pp protocol.Position) ([]protocol.CallHierarchyOutgoingCall, error) {
66074-	ctx, done := event.Start(ctx, "source.OutgoingCalls")
66075-	defer done()
66076-
66077-	pkg, pgf, err := PackageForFile(ctx, snapshot, fh.URI(), NarrowestPackage)
66078-	if err != nil {
66079-		return nil, err
66080-	}
66081-	pos, err := pgf.PositionPos(pp)
66082-	if err != nil {
66083-		return nil, err
66084-	}
66085-
66086-	_, obj, _ := referencedObject(pkg, pgf, pos)
66087-	if obj == nil {
66088-		return nil, nil
66089-	}
66090-
66091-	if _, ok := obj.Type().Underlying().(*types.Signature); !ok {
66092-		return nil, nil
66093-	}
66094-
66095-	// Skip builtins.
66096-	if obj.Pkg() == nil {
66097-		return nil, nil
66098-	}
66099-
66100-	if !obj.Pos().IsValid() {
66101-		return nil, bug.Errorf("internal error: object %s.%s missing position", obj.Pkg().Path(), obj.Name())
66102-	}
66103-
66104-	declFile := pkg.FileSet().File(obj.Pos())
66105-	if declFile == nil {
66106-		return nil, bug.Errorf("file not found for %d", obj.Pos())
66107-	}
66108-
66109-	uri := span.URIFromPath(declFile.Name())
66110-	offset, err := safetoken.Offset(declFile, obj.Pos())
66111-	if err != nil {
66112-		return nil, err
66113-	}
66114-
66115-	// Use TypecheckFull as we want to inspect the body of the function declaration.
66116-	declPkg, declPGF, err := PackageForFile(ctx, snapshot, uri, NarrowestPackage)
66117-	if err != nil {
66118-		return nil, err
66119-	}
66120-
66121-	declPos, err := safetoken.Pos(declPGF.Tok, offset)
66122-	if err != nil {
66123-		return nil, err
66124-	}
66125-
66126-	declNode, _, _ := findDeclInfo([]*ast.File{declPGF.File}, declPos)
66127-	if declNode == nil {
66128-		// TODO(rfindley): why don't we return an error here, or even bug.Errorf?
66129-		return nil, nil
66130-		// return nil, bug.Errorf("failed to find declaration for object %s.%s", obj.Pkg().Path(), obj.Name())
66131-	}
66132-
66133-	type callRange struct {
66134-		start, end token.Pos
66135-	}
66136-	callRanges := []callRange{}
66137-	ast.Inspect(declNode, func(n ast.Node) bool {
66138-		if call, ok := n.(*ast.CallExpr); ok {
66139-			var start, end token.Pos
66140-			switch n := call.Fun.(type) {
66141-			case *ast.SelectorExpr:
66142-				start, end = n.Sel.NamePos, call.Lparen
66143-			case *ast.Ident:
66144-				start, end = n.NamePos, call.Lparen
66145-			case *ast.FuncLit:
66146-				// while we don't add the function literal as an 'outgoing' call
66147-				// we still want to traverse into it
66148-				return true
66149-			default:
66150-				// ignore any other kind of call expressions
66151-				// for ex: direct function literal calls since that's not an 'outgoing' call
66152-				return false
66153-			}
66154-			callRanges = append(callRanges, callRange{start: start, end: end})
66155-		}
66156-		return true
66157-	})
66158-
66159-	outgoingCalls := map[token.Pos]*protocol.CallHierarchyOutgoingCall{}
66160-	for _, callRange := range callRanges {
66161-		_, obj, _ := referencedObject(declPkg, declPGF, callRange.start)
66162-		if obj == nil {
66163-			continue
66164-		}
66165-
66166-		// ignore calls to builtin functions
66167-		if obj.Pkg() == nil {
66168-			continue
66169-		}
66170-
66171-		outgoingCall, ok := outgoingCalls[obj.Pos()]
66172-		if !ok {
66173-			loc, err := mapPosition(ctx, declPkg.FileSet(), snapshot, obj.Pos(), obj.Pos()+token.Pos(len(obj.Name())))
66174-			if err != nil {
66175-				return nil, err
66176-			}
66177-			outgoingCall = &protocol.CallHierarchyOutgoingCall{
66178-				To: protocol.CallHierarchyItem{
66179-					Name:           obj.Name(),
66180-					Kind:           protocol.Function,
66181-					Tags:           []protocol.SymbolTag{},
66182-					Detail:         fmt.Sprintf("%s • %s", obj.Pkg().Path(), filepath.Base(loc.URI.SpanURI().Filename())),
66183-					URI:            loc.URI,
66184-					Range:          loc.Range,
66185-					SelectionRange: loc.Range,
66186-				},
66187-			}
66188-			outgoingCalls[obj.Pos()] = outgoingCall
66189-		}
66190-
66191-		rng, err := declPGF.PosRange(callRange.start, callRange.end)
66192-		if err != nil {
66193-			return nil, err
66194-		}
66195-		outgoingCall.FromRanges = append(outgoingCall.FromRanges, rng)
66196-	}
66197-
66198-	outgoingCallItems := make([]protocol.CallHierarchyOutgoingCall, 0, len(outgoingCalls))
66199-	for _, callItem := range outgoingCalls {
66200-		outgoingCallItems = append(outgoingCallItems, *callItem)
66201-	}
66202-	return outgoingCallItems, nil
66203-}
66204diff -urN a/gopls/internal/lsp/source/code_lens.go b/gopls/internal/lsp/source/code_lens.go
66205--- a/gopls/internal/lsp/source/code_lens.go	2000-01-01 00:00:00.000000000 -0000
66206+++ b/gopls/internal/lsp/source/code_lens.go	1970-01-01 00:00:00.000000000 +0000
66207@@ -1,248 +0,0 @@
66208-// Copyright 2020 The Go Authors. All rights reserved.
66209-// Use of this source code is governed by a BSD-style
66210-// license that can be found in the LICENSE file.
66211-
66212-package source
66213-
66214-import (
66215-	"context"
66216-	"go/ast"
66217-	"go/token"
66218-	"go/types"
66219-	"path/filepath"
66220-	"regexp"
66221-	"strings"
66222-
66223-	"golang.org/x/tools/gopls/internal/lsp/command"
66224-	"golang.org/x/tools/gopls/internal/lsp/protocol"
66225-	"golang.org/x/tools/gopls/internal/span"
66226-)
66227-
66228-type LensFunc func(context.Context, Snapshot, FileHandle) ([]protocol.CodeLens, error)
66229-
66230-// LensFuncs returns the supported lensFuncs for Go files.
66231-func LensFuncs() map[command.Command]LensFunc {
66232-	return map[command.Command]LensFunc{
66233-		command.Generate:      goGenerateCodeLens,
66234-		command.Test:          runTestCodeLens,
66235-		command.RegenerateCgo: regenerateCgoLens,
66236-		command.GCDetails:     toggleDetailsCodeLens,
66237-	}
66238-}
66239-
66240-var (
66241-	testRe      = regexp.MustCompile("^Test[^a-z]")
66242-	benchmarkRe = regexp.MustCompile("^Benchmark[^a-z]")
66243-)
66244-
66245-func runTestCodeLens(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]protocol.CodeLens, error) {
66246-	codeLens := make([]protocol.CodeLens, 0)
66247-
66248-	fns, err := TestsAndBenchmarks(ctx, snapshot, fh)
66249-	if err != nil {
66250-		return nil, err
66251-	}
66252-	puri := protocol.URIFromSpanURI(fh.URI())
66253-	for _, fn := range fns.Tests {
66254-		cmd, err := command.NewTestCommand("run test", puri, []string{fn.Name}, nil)
66255-		if err != nil {
66256-			return nil, err
66257-		}
66258-		rng := protocol.Range{Start: fn.Rng.Start, End: fn.Rng.Start}
66259-		codeLens = append(codeLens, protocol.CodeLens{Range: rng, Command: &cmd})
66260-	}
66261-
66262-	for _, fn := range fns.Benchmarks {
66263-		cmd, err := command.NewTestCommand("run benchmark", puri, nil, []string{fn.Name})
66264-		if err != nil {
66265-			return nil, err
66266-		}
66267-		rng := protocol.Range{Start: fn.Rng.Start, End: fn.Rng.Start}
66268-		codeLens = append(codeLens, protocol.CodeLens{Range: rng, Command: &cmd})
66269-	}
66270-
66271-	if len(fns.Benchmarks) > 0 {
66272-		pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
66273-		if err != nil {
66274-			return nil, err
66275-		}
66276-		// add a code lens to the top of the file which runs all benchmarks in the file
66277-		rng, err := pgf.PosRange(pgf.File.Package, pgf.File.Package)
66278-		if err != nil {
66279-			return nil, err
66280-		}
66281-		var benches []string
66282-		for _, fn := range fns.Benchmarks {
66283-			benches = append(benches, fn.Name)
66284-		}
66285-		cmd, err := command.NewTestCommand("run file benchmarks", puri, nil, benches)
66286-		if err != nil {
66287-			return nil, err
66288-		}
66289-		codeLens = append(codeLens, protocol.CodeLens{Range: rng, Command: &cmd})
66290-	}
66291-	return codeLens, nil
66292-}
66293-
66294-type testFn struct {
66295-	Name string
66296-	Rng  protocol.Range
66297-}
66298-
66299-type testFns struct {
66300-	Tests      []testFn
66301-	Benchmarks []testFn
66302-}
66303-
66304-func TestsAndBenchmarks(ctx context.Context, snapshot Snapshot, fh FileHandle) (testFns, error) {
66305-	var out testFns
66306-
66307-	if !strings.HasSuffix(fh.URI().Filename(), "_test.go") {
66308-		return out, nil
66309-	}
66310-	pkg, pgf, err := PackageForFile(ctx, snapshot, fh.URI(), NarrowestPackage)
66311-	if err != nil {
66312-		return out, err
66313-	}
66314-
66315-	for _, d := range pgf.File.Decls {
66316-		fn, ok := d.(*ast.FuncDecl)
66317-		if !ok {
66318-			continue
66319-		}
66320-
66321-		rng, err := pgf.NodeRange(fn)
66322-		if err != nil {
66323-			return out, err
66324-		}
66325-
66326-		if matchTestFunc(fn, pkg, testRe, "T") {
66327-			out.Tests = append(out.Tests, testFn{fn.Name.Name, rng})
66328-		}
66329-
66330-		if matchTestFunc(fn, pkg, benchmarkRe, "B") {
66331-			out.Benchmarks = append(out.Benchmarks, testFn{fn.Name.Name, rng})
66332-		}
66333-	}
66334-
66335-	return out, nil
66336-}
66337-
66338-func matchTestFunc(fn *ast.FuncDecl, pkg Package, nameRe *regexp.Regexp, paramID string) bool {
66339-	// Make sure that the function name matches a test function.
66340-	if !nameRe.MatchString(fn.Name.Name) {
66341-		return false
66342-	}
66343-	info := pkg.GetTypesInfo()
66344-	if info == nil {
66345-		return false
66346-	}
66347-	obj := info.ObjectOf(fn.Name)
66348-	if obj == nil {
66349-		return false
66350-	}
66351-	sig, ok := obj.Type().(*types.Signature)
66352-	if !ok {
66353-		return false
66354-	}
66355-	// Test functions should have only one parameter.
66356-	if sig.Params().Len() != 1 {
66357-		return false
66358-	}
66359-
66360-	// Check the type of the only parameter
66361-	paramTyp, ok := sig.Params().At(0).Type().(*types.Pointer)
66362-	if !ok {
66363-		return false
66364-	}
66365-	named, ok := paramTyp.Elem().(*types.Named)
66366-	if !ok {
66367-		return false
66368-	}
66369-	namedObj := named.Obj()
66370-	if namedObj.Pkg().Path() != "testing" {
66371-		return false
66372-	}
66373-	return namedObj.Id() == paramID
66374-}
66375-
66376-func goGenerateCodeLens(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]protocol.CodeLens, error) {
66377-	pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
66378-	if err != nil {
66379-		return nil, err
66380-	}
66381-	const ggDirective = "//go:generate"
66382-	for _, c := range pgf.File.Comments {
66383-		for _, l := range c.List {
66384-			if !strings.HasPrefix(l.Text, ggDirective) {
66385-				continue
66386-			}
66387-			rng, err := pgf.PosRange(l.Pos(), l.Pos()+token.Pos(len(ggDirective)))
66388-			if err != nil {
66389-				return nil, err
66390-			}
66391-			dir := protocol.URIFromSpanURI(span.URIFromPath(filepath.Dir(fh.URI().Filename())))
66392-			nonRecursiveCmd, err := command.NewGenerateCommand("run go generate", command.GenerateArgs{Dir: dir, Recursive: false})
66393-			if err != nil {
66394-				return nil, err
66395-			}
66396-			recursiveCmd, err := command.NewGenerateCommand("run go generate ./...", command.GenerateArgs{Dir: dir, Recursive: true})
66397-			if err != nil {
66398-				return nil, err
66399-			}
66400-			return []protocol.CodeLens{
66401-				{Range: rng, Command: &recursiveCmd},
66402-				{Range: rng, Command: &nonRecursiveCmd},
66403-			}, nil
66404-
66405-		}
66406-	}
66407-	return nil, nil
66408-}
66409-
66410-func regenerateCgoLens(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]protocol.CodeLens, error) {
66411-	pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
66412-	if err != nil {
66413-		return nil, err
66414-	}
66415-	var c *ast.ImportSpec
66416-	for _, imp := range pgf.File.Imports {
66417-		if imp.Path.Value == `"C"` {
66418-			c = imp
66419-		}
66420-	}
66421-	if c == nil {
66422-		return nil, nil
66423-	}
66424-	rng, err := pgf.NodeRange(c)
66425-	if err != nil {
66426-		return nil, err
66427-	}
66428-	puri := protocol.URIFromSpanURI(fh.URI())
66429-	cmd, err := command.NewRegenerateCgoCommand("regenerate cgo definitions", command.URIArg{URI: puri})
66430-	if err != nil {
66431-		return nil, err
66432-	}
66433-	return []protocol.CodeLens{{Range: rng, Command: &cmd}}, nil
66434-}
66435-
66436-func toggleDetailsCodeLens(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]protocol.CodeLens, error) {
66437-	pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
66438-	if err != nil {
66439-		return nil, err
66440-	}
66441-	if !pgf.File.Package.IsValid() {
66442-		// Without a package name we have nowhere to put the codelens, so give up.
66443-		return nil, nil
66444-	}
66445-	rng, err := pgf.PosRange(pgf.File.Package, pgf.File.Package)
66446-	if err != nil {
66447-		return nil, err
66448-	}
66449-	puri := protocol.URIFromSpanURI(fh.URI())
66450-	cmd, err := command.NewGCDetailsCommand("Toggle gc annotation details", puri)
66451-	if err != nil {
66452-		return nil, err
66453-	}
66454-	return []protocol.CodeLens{{Range: rng, Command: &cmd}}, nil
66455-}
66456diff -urN a/gopls/internal/lsp/source/comment.go b/gopls/internal/lsp/source/comment.go
66457--- a/gopls/internal/lsp/source/comment.go	2000-01-01 00:00:00.000000000 -0000
66458+++ b/gopls/internal/lsp/source/comment.go	1970-01-01 00:00:00.000000000 +0000
66459@@ -1,384 +0,0 @@
66460-// Copyright 2019 The Go Authors. All rights reserved.
66461-// Use of this source code is governed by a BSD-style
66462-// license that can be found in the LICENSE file.
66463-
66464-//go:build !go1.19
66465-// +build !go1.19
66466-
66467-package source
66468-
66469-import (
66470-	"bytes"
66471-	"io"
66472-	"regexp"
66473-	"strings"
66474-	"unicode"
66475-	"unicode/utf8"
66476-)
66477-
66478-// CommentToMarkdown converts comment text to formatted markdown.
66479-// The comment was prepared by DocReader,
66480-// so it is known not to have leading, trailing blank lines
66481-// nor to have trailing spaces at the end of lines.
66482-// The comment markers have already been removed.
66483-//
66484-// Each line is converted into a markdown line and empty lines are just converted to
66485-// newlines. Heading are prefixed with `### ` to make it a markdown heading.
66486-//
66487-// A span of indented lines retains a 4 space prefix block, with the common indent
66488-// prefix removed unless empty, in which case it will be converted to a newline.
66489-//
66490-// URLs in the comment text are converted into links.
66491-func CommentToMarkdown(text string, _ *Options) string {
66492-	buf := &bytes.Buffer{}
66493-	commentToMarkdown(buf, text)
66494-	return buf.String()
66495-}
66496-
66497-var (
66498-	mdNewline   = []byte("\n")
66499-	mdHeader    = []byte("### ")
66500-	mdIndent    = []byte("    ")
66501-	mdLinkStart = []byte("[")
66502-	mdLinkDiv   = []byte("](")
66503-	mdLinkEnd   = []byte(")")
66504-)
66505-
66506-func commentToMarkdown(w io.Writer, text string) {
66507-	blocks := blocks(text)
66508-	for i, b := range blocks {
66509-		switch b.op {
66510-		case opPara:
66511-			for _, line := range b.lines {
66512-				emphasize(w, line, true)
66513-			}
66514-		case opHead:
66515-			// The header block can consist of only one line.
66516-			// However, check the number of lines, just in case.
66517-			if len(b.lines) == 0 {
66518-				// Skip this block.
66519-				continue
66520-			}
66521-			header := b.lines[0]
66522-
66523-			w.Write(mdHeader)
66524-			commentEscape(w, header, true)
66525-			// Header doesn't end with \n unlike the lines of other blocks.
66526-			w.Write(mdNewline)
66527-		case opPre:
66528-			for _, line := range b.lines {
66529-				if isBlank(line) {
66530-					w.Write(mdNewline)
66531-					continue
66532-				}
66533-				w.Write(mdIndent)
66534-				w.Write([]byte(line))
66535-			}
66536-		}
66537-
66538-		if i < len(blocks)-1 {
66539-			w.Write(mdNewline)
66540-		}
66541-	}
66542-}
66543-
66544-const (
66545-	ulquo = "“"
66546-	urquo = "”"
66547-)
66548-
66549-var (
66550-	markdownEscape = regexp.MustCompile(`([\\\x60*{}[\]()#+\-.!_>~|"$%&'\/:;<=?@^])`)
66551-
66552-	unicodeQuoteReplacer = strings.NewReplacer("``", ulquo, "''", urquo)
66553-)
66554-
66555-// commentEscape escapes comment text for markdown. If nice is set,
66556-// also turn double ` and ' into “ and ”.
66557-func commentEscape(w io.Writer, text string, nice bool) {
66558-	if nice {
66559-		text = convertQuotes(text)
66560-	}
66561-	text = escapeRegex(text)
66562-	w.Write([]byte(text))
66563-}
66564-
66565-func convertQuotes(text string) string {
66566-	return unicodeQuoteReplacer.Replace(text)
66567-}
66568-
66569-func escapeRegex(text string) string {
66570-	return markdownEscape.ReplaceAllString(text, `\$1`)
66571-}
66572-
66573-func emphasize(w io.Writer, line string, nice bool) {
66574-	for {
66575-		m := matchRx.FindStringSubmatchIndex(line)
66576-		if m == nil {
66577-			break
66578-		}
66579-		// m >= 6 (two parenthesized sub-regexps in matchRx, 1st one is urlRx)
66580-
66581-		// write text before match
66582-		commentEscape(w, line[0:m[0]], nice)
66583-
66584-		// adjust match for URLs
66585-		match := line[m[0]:m[1]]
66586-		if strings.Contains(match, "://") {
66587-			m0, m1 := m[0], m[1]
66588-			for _, s := range []string{"()", "{}", "[]"} {
66589-				open, close := s[:1], s[1:] // E.g., "(" and ")"
66590-				// require opening parentheses before closing parentheses (#22285)
66591-				if i := strings.Index(match, close); i >= 0 && i < strings.Index(match, open) {
66592-					m1 = m0 + i
66593-					match = line[m0:m1]
66594-				}
66595-				// require balanced pairs of parentheses (#5043)
66596-				for i := 0; strings.Count(match, open) != strings.Count(match, close) && i < 10; i++ {
66597-					m1 = strings.LastIndexAny(line[:m1], s)
66598-					match = line[m0:m1]
66599-				}
66600-			}
66601-			if m1 != m[1] {
66602-				// redo matching with shortened line for correct indices
66603-				m = matchRx.FindStringSubmatchIndex(line[:m[0]+len(match)])
66604-			}
66605-		}
66606-
66607-		// Following code has been modified from go/doc since words is always
66608-		// nil. All html formatting has also been transformed into markdown formatting
66609-
66610-		// analyze match
66611-		url := ""
66612-		if m[2] >= 0 {
66613-			url = match
66614-		}
66615-
66616-		// write match
66617-		if len(url) > 0 {
66618-			w.Write(mdLinkStart)
66619-		}
66620-
66621-		commentEscape(w, match, nice)
66622-
66623-		if len(url) > 0 {
66624-			w.Write(mdLinkDiv)
66625-			w.Write([]byte(urlReplacer.Replace(url)))
66626-			w.Write(mdLinkEnd)
66627-		}
66628-
66629-		// advance
66630-		line = line[m[1]:]
66631-	}
66632-	commentEscape(w, line, nice)
66633-}
66634-
66635-// Everything from here on is a copy of go/doc/comment.go
66636-
66637-const (
66638-	// Regexp for Go identifiers
66639-	identRx = `[\pL_][\pL_0-9]*`
66640-
66641-	// Regexp for URLs
66642-	// Match parens, and check later for balance - see #5043, #22285
66643-	// Match .,:;?! within path, but not at end - see #18139, #16565
66644-	// This excludes some rare yet valid urls ending in common punctuation
66645-	// in order to allow sentences ending in URLs.
66646-
66647-	// protocol (required) e.g. http
66648-	protoPart = `(https?|ftp|file|gopher|mailto|nntp)`
66649-	// host (required) e.g. www.example.com or [::1]:8080
66650-	hostPart = `([a-zA-Z0-9_@\-.\[\]:]+)`
66651-	// path+query+fragment (optional) e.g. /path/index.html?q=foo#bar
66652-	pathPart = `([.,:;?!]*[a-zA-Z0-9$'()*+&#=@~_/\-\[\]%])*`
66653-
66654-	urlRx = protoPart + `://` + hostPart + pathPart
66655-)
66656-
66657-var (
66658-	matchRx     = regexp.MustCompile(`(` + urlRx + `)|(` + identRx + `)`)
66659-	urlReplacer = strings.NewReplacer(`(`, `\(`, `)`, `\)`)
66660-)
66661-
66662-func indentLen(s string) int {
66663-	i := 0
66664-	for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
66665-		i++
66666-	}
66667-	return i
66668-}
66669-
66670-func isBlank(s string) bool {
66671-	return len(s) == 0 || (len(s) == 1 && s[0] == '\n')
66672-}
66673-
66674-func commonPrefix(a, b string) string {
66675-	i := 0
66676-	for i < len(a) && i < len(b) && a[i] == b[i] {
66677-		i++
66678-	}
66679-	return a[0:i]
66680-}
66681-
66682-func unindent(block []string) {
66683-	if len(block) == 0 {
66684-		return
66685-	}
66686-
66687-	// compute maximum common white prefix
66688-	prefix := block[0][0:indentLen(block[0])]
66689-	for _, line := range block {
66690-		if !isBlank(line) {
66691-			prefix = commonPrefix(prefix, line)
66692-		}
66693-	}
66694-	n := len(prefix)
66695-
66696-	// remove
66697-	for i, line := range block {
66698-		if !isBlank(line) {
66699-			block[i] = line[n:]
66700-		}
66701-	}
66702-}
66703-
66704-// heading returns the trimmed line if it passes as a section heading;
66705-// otherwise it returns the empty string.
66706-func heading(line string) string {
66707-	line = strings.TrimSpace(line)
66708-	if len(line) == 0 {
66709-		return ""
66710-	}
66711-
66712-	// a heading must start with an uppercase letter
66713-	r, _ := utf8.DecodeRuneInString(line)
66714-	if !unicode.IsLetter(r) || !unicode.IsUpper(r) {
66715-		return ""
66716-	}
66717-
66718-	// it must end in a letter or digit:
66719-	r, _ = utf8.DecodeLastRuneInString(line)
66720-	if !unicode.IsLetter(r) && !unicode.IsDigit(r) {
66721-		return ""
66722-	}
66723-
66724-	// exclude lines with illegal characters. we allow "(),"
66725-	if strings.ContainsAny(line, ";:!?+*/=[]{}_^°&§~%#@<\">\\") {
66726-		return ""
66727-	}
66728-
66729-	// allow "'" for possessive "'s" only
66730-	for b := line; ; {
66731-		i := strings.IndexRune(b, '\'')
66732-		if i < 0 {
66733-			break
66734-		}
66735-		if i+1 >= len(b) || b[i+1] != 's' || (i+2 < len(b) && b[i+2] != ' ') {
66736-			return "" // not followed by "s "
66737-		}
66738-		b = b[i+2:]
66739-	}
66740-
66741-	// allow "." when followed by non-space
66742-	for b := line; ; {
66743-		i := strings.IndexRune(b, '.')
66744-		if i < 0 {
66745-			break
66746-		}
66747-		if i+1 >= len(b) || b[i+1] == ' ' {
66748-			return "" // not followed by non-space
66749-		}
66750-		b = b[i+1:]
66751-	}
66752-
66753-	return line
66754-}
66755-
66756-type op int
66757-
66758-const (
66759-	opPara op = iota
66760-	opHead
66761-	opPre
66762-)
66763-
66764-type block struct {
66765-	op    op
66766-	lines []string
66767-}
66768-
66769-func blocks(text string) []block {
66770-	var (
66771-		out  []block
66772-		para []string
66773-
66774-		lastWasBlank   = false
66775-		lastWasHeading = false
66776-	)
66777-
66778-	close := func() {
66779-		if para != nil {
66780-			out = append(out, block{opPara, para})
66781-			para = nil
66782-		}
66783-	}
66784-
66785-	lines := strings.SplitAfter(text, "\n")
66786-	unindent(lines)
66787-	for i := 0; i < len(lines); {
66788-		line := lines[i]
66789-		if isBlank(line) {
66790-			// close paragraph
66791-			close()
66792-			i++
66793-			lastWasBlank = true
66794-			continue
66795-		}
66796-		if indentLen(line) > 0 {
66797-			// close paragraph
66798-			close()
66799-
66800-			// count indented or blank lines
66801-			j := i + 1
66802-			for j < len(lines) && (isBlank(lines[j]) || indentLen(lines[j]) > 0) {
66803-				j++
66804-			}
66805-			// but not trailing blank lines
66806-			for j > i && isBlank(lines[j-1]) {
66807-				j--
66808-			}
66809-			pre := lines[i:j]
66810-			i = j
66811-
66812-			unindent(pre)
66813-
66814-			// put those lines in a pre block
66815-			out = append(out, block{opPre, pre})
66816-			lastWasHeading = false
66817-			continue
66818-		}
66819-
66820-		if lastWasBlank && !lastWasHeading && i+2 < len(lines) &&
66821-			isBlank(lines[i+1]) && !isBlank(lines[i+2]) && indentLen(lines[i+2]) == 0 {
66822-			// current line is non-blank, surrounded by blank lines
66823-			// and the next non-blank line is not indented: this
66824-			// might be a heading.
66825-			if head := heading(line); head != "" {
66826-				close()
66827-				out = append(out, block{opHead, []string{head}})
66828-				i += 2
66829-				lastWasHeading = true
66830-				continue
66831-			}
66832-		}
66833-
66834-		// open paragraph
66835-		lastWasBlank = false
66836-		lastWasHeading = false
66837-		para = append(para, lines[i])
66838-		i++
66839-	}
66840-	close()
66841-
66842-	return out
66843-}
66844diff -urN a/gopls/internal/lsp/source/comment_go118_test.go b/gopls/internal/lsp/source/comment_go118_test.go
66845--- a/gopls/internal/lsp/source/comment_go118_test.go	2000-01-01 00:00:00.000000000 -0000
66846+++ b/gopls/internal/lsp/source/comment_go118_test.go	1970-01-01 00:00:00.000000000 +0000
66847@@ -1,371 +0,0 @@
66848-// Copyright 2019 The Go Authors. All rights reserved.
66849-// Use of this source code is governed by a BSD-style
66850-// license that can be found in the LICENSE file.
66851-
66852-//go:build !go1.19
66853-// +build !go1.19
66854-
66855-package source
66856-
66857-import (
66858-	"bytes"
66859-	"reflect"
66860-	"strings"
66861-	"testing"
66862-)
66863-
66864-// This file is a copy of go/doc/comment_test.go with the exception for
66865-// the test cases for TestEmphasize and TestCommentEscape
66866-
66867-var headingTests = []struct {
66868-	line string
66869-	ok   bool
66870-}{
66871-	{"Section", true},
66872-	{"A typical usage", true},
66873-	{"ΔΛΞ is Greek", true},
66874-	{"Foo 42", true},
66875-	{"", false},
66876-	{"section", false},
66877-	{"A typical usage:", false},
66878-	{"This code:", false},
66879-	{"δ is Greek", false},
66880-	{"Foo §", false},
66881-	{"Fermat's Last Sentence", true},
66882-	{"Fermat's", true},
66883-	{"'sX", false},
66884-	{"Ted 'Too' Bar", false},
66885-	{"Use n+m", false},
66886-	{"Scanning:", false},
66887-	{"N:M", false},
66888-}
66889-
66890-func TestIsHeading(t *testing.T) {
66891-	for _, tt := range headingTests {
66892-		if h := heading(tt.line); (len(h) > 0) != tt.ok {
66893-			t.Errorf("isHeading(%q) = %v, want %v", tt.line, h, tt.ok)
66894-		}
66895-	}
66896-}
66897-
66898-var blocksTests = []struct {
66899-	in   string
66900-	out  []block
66901-	text string
66902-}{
66903-	{
66904-		in: `Para 1.
66905-Para 1 line 2.
66906-
66907-Para 2.
66908-
66909-Section
66910-
66911-Para 3.
66912-
66913-	pre
66914-	pre1
66915-
66916-Para 4.
66917-
66918-	pre
66919-	pre1
66920-
66921-	pre2
66922-
66923-Para 5.
66924-
66925-
66926-	pre
66927-
66928-
66929-	pre1
66930-	pre2
66931-
66932-Para 6.
66933-	pre
66934-	pre2
66935-`,
66936-		out: []block{
66937-			{opPara, []string{"Para 1.\n", "Para 1 line 2.\n"}},
66938-			{opPara, []string{"Para 2.\n"}},
66939-			{opHead, []string{"Section"}},
66940-			{opPara, []string{"Para 3.\n"}},
66941-			{opPre, []string{"pre\n", "pre1\n"}},
66942-			{opPara, []string{"Para 4.\n"}},
66943-			{opPre, []string{"pre\n", "pre1\n", "\n", "pre2\n"}},
66944-			{opPara, []string{"Para 5.\n"}},
66945-			{opPre, []string{"pre\n", "\n", "\n", "pre1\n", "pre2\n"}},
66946-			{opPara, []string{"Para 6.\n"}},
66947-			{opPre, []string{"pre\n", "pre2\n"}},
66948-		},
66949-		text: `.   Para 1. Para 1 line 2.
66950-
66951-.   Para 2.
66952-
66953-
66954-.   Section
66955-
66956-.   Para 3.
66957-
66958-$	pre
66959-$	pre1
66960-
66961-.   Para 4.
66962-
66963-$	pre
66964-$	pre1
66965-
66966-$	pre2
66967-
66968-.   Para 5.
66969-
66970-$	pre
66971-
66972-
66973-$	pre1
66974-$	pre2
66975-
66976-.   Para 6.
66977-
66978-$	pre
66979-$	pre2
66980-`,
66981-	},
66982-	{
66983-		in: "Para.\n\tshould not be ``escaped''",
66984-		out: []block{
66985-			{opPara, []string{"Para.\n"}},
66986-			{opPre, []string{"should not be ``escaped''"}},
66987-		},
66988-		text: ".   Para.\n\n$	should not be ``escaped''",
66989-	},
66990-	{
66991-		in: "// A very long line of 46 char for line wrapping.",
66992-		out: []block{
66993-			{opPara, []string{"// A very long line of 46 char for line wrapping."}},
66994-		},
66995-		text: `.   // A very long line of 46 char for line
66996-.   // wrapping.
66997-`,
66998-	},
66999-	{
67000-		in: `/* A very long line of 46 char for line wrapping.
67001-A very long line of 46 char for line wrapping. */`,
67002-		out: []block{
67003-			{opPara, []string{"/* A very long line of 46 char for line wrapping.\n", "A very long line of 46 char for line wrapping. */"}},
67004-		},
67005-		text: `.   /* A very long line of 46 char for line
67006-.   wrapping. A very long line of 46 char
67007-.   for line wrapping. */
67008-`,
67009-	},
67010-}
67011-
67012-func TestBlocks(t *testing.T) {
67013-	for i, tt := range blocksTests {
67014-		b := blocks(tt.in)
67015-		if !reflect.DeepEqual(b, tt.out) {
67016-			t.Errorf("#%d: mismatch\nhave: %v\nwant: %v", i, b, tt.out)
67017-		}
67018-	}
67019-}
67020-
67021-// This has been modified from go/doc to use markdown links instead of html ones
67022-// and use markdown escaping instead oh html
67023-var emphasizeTests = []struct {
67024-	in, out string
67025-}{
67026-	{"", ""},
67027-	{"http://[::1]:8080/foo.txt", `[http\:\/\/\[\:\:1\]\:8080\/foo\.txt](http://[::1]:8080/foo.txt)`},
67028-	{"before (https://www.google.com) after", `before \([https\:\/\/www\.google\.com](https://www.google.com)\) after`},
67029-	{"before https://www.google.com:30/x/y/z:b::c. After", `before [https\:\/\/www\.google\.com\:30\/x\/y\/z\:b\:\:c](https://www.google.com:30/x/y/z:b::c)\. After`},
67030-	{"http://www.google.com/path/:;!-/?query=%34b#093124", `[http\:\/\/www\.google\.com\/path\/\:\;\!\-\/\?query\=\%34b\#093124](http://www.google.com/path/:;!-/?query=%34b#093124)`},
67031-	{"http://www.google.com/path/:;!-/?query=%34bar#093124", `[http\:\/\/www\.google\.com\/path\/\:\;\!\-\/\?query\=\%34bar\#093124](http://www.google.com/path/:;!-/?query=%34bar#093124)`},
67032-	{"http://www.google.com/index.html! After", `[http\:\/\/www\.google\.com\/index\.html](http://www.google.com/index.html)\! After`},
67033-	{"http://www.google.com/", `[http\:\/\/www\.google\.com\/](http://www.google.com/)`},
67034-	{"https://www.google.com/", `[https\:\/\/www\.google\.com\/](https://www.google.com/)`},
67035-	{"http://www.google.com/path.", `[http\:\/\/www\.google\.com\/path](http://www.google.com/path)\.`},
67036-	{"http://en.wikipedia.org/wiki/Camellia_(cipher)", `[http\:\/\/en\.wikipedia\.org\/wiki\/Camellia\_\(cipher\)](http://en.wikipedia.org/wiki/Camellia_\(cipher\))`},
67037-	{"(http://www.google.com/)", `\([http\:\/\/www\.google\.com\/](http://www.google.com/)\)`},
67038-	{"http://gmail.com)", `[http\:\/\/gmail\.com](http://gmail.com)\)`},
67039-	{"((http://gmail.com))", `\(\([http\:\/\/gmail\.com](http://gmail.com)\)\)`},
67040-	{"http://gmail.com ((http://gmail.com)) ()", `[http\:\/\/gmail\.com](http://gmail.com) \(\([http\:\/\/gmail\.com](http://gmail.com)\)\) \(\)`},
67041-	{"Foo bar http://example.com/ quux!", `Foo bar [http\:\/\/example\.com\/](http://example.com/) quux\!`},
67042-	{"Hello http://example.com/%2f/ /world.", `Hello [http\:\/\/example\.com\/\%2f\/](http://example.com/%2f/) \/world\.`},
67043-	{"Lorem http: ipsum //host/path", `Lorem http\: ipsum \/\/host\/path`},
67044-	{"javascript://is/not/linked", `javascript\:\/\/is\/not\/linked`},
67045-	{"http://foo", `[http\:\/\/foo](http://foo)`},
67046-	{"art by [[https://www.example.com/person/][Person Name]]", `art by \[\[[https\:\/\/www\.example\.com\/person\/](https://www.example.com/person/)\]\[Person Name\]\]`},
67047-	{"please visit (http://golang.org/)", `please visit \([http\:\/\/golang\.org\/](http://golang.org/)\)`},
67048-	{"please visit http://golang.org/hello())", `please visit [http\:\/\/golang\.org\/hello\(\)](http://golang.org/hello\(\))\)`},
67049-	{"http://git.qemu.org/?p=qemu.git;a=blob;f=qapi-schema.json;hb=HEAD", `[http\:\/\/git\.qemu\.org\/\?p\=qemu\.git\;a\=blob\;f\=qapi\-schema\.json\;hb\=HEAD](http://git.qemu.org/?p=qemu.git;a=blob;f=qapi-schema.json;hb=HEAD)`},
67050-	{"https://foo.bar/bal/x(])", `[https\:\/\/foo\.bar\/bal\/x\(](https://foo.bar/bal/x\()\]\)`},
67051-	{"foo [ http://bar(])", `foo \[ [http\:\/\/bar\(](http://bar\()\]\)`},
67052-}
67053-
67054-func TestEmphasize(t *testing.T) {
67055-	for i, tt := range emphasizeTests {
67056-		var buf bytes.Buffer
67057-		emphasize(&buf, tt.in, true)
67058-		out := buf.String()
67059-		if out != tt.out {
67060-			t.Errorf("#%d: mismatch\nhave: %v\nwant: %v", i, out, tt.out)
67061-		}
67062-	}
67063-}
67064-
67065-func TestCommentEscape(t *testing.T) {
67066-	//ldquo -> ulquo and rdquo -> urquo
67067-	commentTests := []struct {
67068-		in, out string
67069-	}{
67070-		{"typically invoked as ``go tool asm'',", "typically invoked as " + ulquo + "go tool asm" + urquo + ","},
67071-		{"For more detail, run ``go help test'' and ``go help testflag''", "For more detail, run " + ulquo + "go help test" + urquo + " and " + ulquo + "go help testflag" + urquo}}
67072-	for i, tt := range commentTests {
67073-		var buf strings.Builder
67074-		commentEscape(&buf, tt.in, true)
67075-		out := buf.String()
67076-		if out != tt.out {
67077-			t.Errorf("#%d: mismatch\nhave: %q\nwant: %q", i, out, tt.out)
67078-		}
67079-	}
67080-}
67081-
67082-func TestCommentToMarkdown(t *testing.T) {
67083-	tests := []struct {
67084-		in, out string
67085-	}{
67086-		{
67087-			in:  "F declaration.\n",
67088-			out: "F declaration\\.\n",
67089-		},
67090-		{
67091-			in: `
67092-F declaration. Lorem ipsum dolor sit amet.
67093-Etiam mattis eros at orci mollis molestie.
67094-`,
67095-			out: `
67096-F declaration\. Lorem ipsum dolor sit amet\.
67097-Etiam mattis eros at orci mollis molestie\.
67098-`,
67099-		},
67100-		{
67101-			in: `
67102-F declaration.
67103-
67104-Lorem ipsum dolor sit amet.
67105-Sed id dui turpis.
67106-
67107-
67108-
67109-
67110-Aenean tempus velit non auctor eleifend.
67111-Aenean efficitur a sem id ultricies.
67112-
67113-
67114-Phasellus efficitur mauris et viverra bibendum.
67115-`,
67116-			out: `
67117-F declaration\.
67118-
67119-Lorem ipsum dolor sit amet\.
67120-Sed id dui turpis\.
67121-
67122-Aenean tempus velit non auctor eleifend\.
67123-Aenean efficitur a sem id ultricies\.
67124-
67125-Phasellus efficitur mauris et viverra bibendum\.
67126-`,
67127-		},
67128-		{
67129-			in: `
67130-F declaration.
67131-
67132-Aenean tempus velit non auctor eleifend.
67133-
67134-Section
67135-
67136-Lorem ipsum dolor sit amet, consectetur adipiscing elit.
67137-
67138-  func foo() {}
67139-
67140-
67141-  func bar() {}
67142-
67143-Fusce lorem lacus.
67144-
67145-    func foo() {}
67146-
67147-    func bar() {}
67148-
67149-Maecenas in lobortis lectus.
67150-
67151-	func foo() {}
67152-
67153-	func bar() {}
67154-
67155-Phasellus efficitur mauris et viverra bibendum.
67156-`,
67157-			out: `
67158-F declaration\.
67159-
67160-Aenean tempus velit non auctor eleifend\.
67161-
67162-### Section
67163-
67164-Lorem ipsum dolor sit amet, consectetur adipiscing elit\.
67165-
67166-    func foo() {}
67167-
67168-
67169-    func bar() {}
67170-
67171-Fusce lorem lacus\.
67172-
67173-    func foo() {}
67174-
67175-    func bar() {}
67176-
67177-Maecenas in lobortis lectus\.
67178-
67179-    func foo() {}
67180-
67181-    func bar() {}
67182-
67183-Phasellus efficitur mauris et viverra bibendum\.
67184-`,
67185-		},
67186-		{
67187-			in: `
67188-F declaration.
67189-
67190-	func foo() {
67191-		fmt.Println("foo")
67192-	}
67193-	func bar() {
67194-		fmt.Println("bar")
67195-	}
67196-`,
67197-			out: `
67198-F declaration\.
67199-
67200-    func foo() {
67201-    	fmt.Println("foo")
67202-    }
67203-    func bar() {
67204-    	fmt.Println("bar")
67205-    }
67206-`,
67207-		},
67208-	}
67209-	for i, tt := range tests {
67210-		// Comments start with new lines for better readability. So, we should trim them.
67211-		tt.in = strings.TrimPrefix(tt.in, "\n")
67212-		tt.out = strings.TrimPrefix(tt.out, "\n")
67213-
67214-		if out := CommentToMarkdown(tt.in, nil); out != tt.out {
67215-			t.Errorf("#%d: mismatch\nhave: %q\nwant: %q", i, out, tt.out)
67216-		}
67217-	}
67218-}
67219diff -urN a/gopls/internal/lsp/source/comment_go119.go b/gopls/internal/lsp/source/comment_go119.go
67220--- a/gopls/internal/lsp/source/comment_go119.go	2000-01-01 00:00:00.000000000 -0000
67221+++ b/gopls/internal/lsp/source/comment_go119.go	1970-01-01 00:00:00.000000000 +0000
67222@@ -1,56 +0,0 @@
67223-// Copyright 2022 The Go Authors. All rights reserved.
67224-// Use of this source code is governed by a BSD-style
67225-// license that can be found in the LICENSE file.
67226-
67227-//go:build go1.19
67228-// +build go1.19
67229-
67230-package source
67231-
67232-// Starting with go1.19, the formatting of comments has changed, and there
67233-// is a new package (go/doc/comment) for processing them.
67234-// As long as gopls has to compile under earlier versions, tests
67235-// have to pass with both the old and new code, which produce
67236-// slightly different results. (cmd/test/definition.go, source/comment_test.go,
67237-// and source/source_test.go) Each of the test files checks the results
67238-// with a function, tests.CheckSameMarkdown, that accepts both the old and the new
67239-// results. (The old code escapes many characters the new code does not,
67240-// and the new code sometimes adds a blank line.)
67241-
67242-// When gopls no longer needs to compile with go1.18, the old comment.go should
67243-// be replaced by this file, the golden test files should be updated.
67244-// (and checkSameMarkdown() could be replaced by a simple comparison.)
67245-
67246-import (
67247-	"fmt"
67248-	"go/doc/comment"
67249-)
67250-
67251-// CommentToMarkdown converts comment text to formatted markdown.
67252-// The comment was prepared by DocReader,
67253-// so it is known not to have leading, trailing blank lines
67254-// nor to have trailing spaces at the end of lines.
67255-// The comment markers have already been removed.
67256-func CommentToMarkdown(text string, options *Options) string {
67257-	var p comment.Parser
67258-	doc := p.Parse(text)
67259-	var pr comment.Printer
67260-	// The default produces {#Hdr-...} tags for headings.
67261-	// vscode displays thems, which is undesirable.
67262-	// The godoc for comment.Printer says the tags
67263-	// avoid a security problem.
67264-	pr.HeadingID = func(*comment.Heading) string { return "" }
67265-	pr.DocLinkURL = func(link *comment.DocLink) string {
67266-		msg := fmt.Sprintf("https://%s/%s", options.LinkTarget, link.ImportPath)
67267-		if link.Name != "" {
67268-			msg += "#"
67269-			if link.Recv != "" {
67270-				msg += link.Recv + "."
67271-			}
67272-			msg += link.Name
67273-		}
67274-		return msg
67275-	}
67276-	easy := pr.Markdown(doc)
67277-	return string(easy)
67278-}
67279diff -urN a/gopls/internal/lsp/source/completion/builtin.go b/gopls/internal/lsp/source/completion/builtin.go
67280--- a/gopls/internal/lsp/source/completion/builtin.go	2000-01-01 00:00:00.000000000 -0000
67281+++ b/gopls/internal/lsp/source/completion/builtin.go	1970-01-01 00:00:00.000000000 +0000
67282@@ -1,147 +0,0 @@
67283-// Copyright 2020 The Go Authors. All rights reserved.
67284-// Use of this source code is governed by a BSD-style
67285-// license that can be found in the LICENSE file.
67286-
67287-package completion
67288-
67289-import (
67290-	"context"
67291-	"go/ast"
67292-	"go/types"
67293-)
67294-
67295-// builtinArgKind determines the expected object kind for a builtin
67296-// argument. It attempts to use the AST hints from builtin.go where
67297-// possible.
67298-func (c *completer) builtinArgKind(ctx context.Context, obj types.Object, call *ast.CallExpr) objKind {
67299-	builtin, err := c.snapshot.BuiltinFile(ctx)
67300-	if err != nil {
67301-		return 0
67302-	}
67303-	exprIdx := exprAtPos(c.pos, call.Args)
67304-
67305-	builtinObj := builtin.File.Scope.Lookup(obj.Name())
67306-	if builtinObj == nil {
67307-		return 0
67308-	}
67309-	decl, ok := builtinObj.Decl.(*ast.FuncDecl)
67310-	if !ok || exprIdx >= len(decl.Type.Params.List) {
67311-		return 0
67312-	}
67313-
67314-	switch ptyp := decl.Type.Params.List[exprIdx].Type.(type) {
67315-	case *ast.ChanType:
67316-		return kindChan
67317-	case *ast.ArrayType:
67318-		return kindSlice
67319-	case *ast.MapType:
67320-		return kindMap
67321-	case *ast.Ident:
67322-		switch ptyp.Name {
67323-		case "Type":
67324-			switch obj.Name() {
67325-			case "make":
67326-				return kindChan | kindSlice | kindMap
67327-			case "len":
67328-				return kindSlice | kindMap | kindArray | kindString | kindChan
67329-			case "cap":
67330-				return kindSlice | kindArray | kindChan
67331-			}
67332-		}
67333-	}
67334-
67335-	return 0
67336-}
67337-
67338-// builtinArgType infers the type of an argument to a builtin
67339-// function. parentInf is the inferred type info for the builtin
67340-// call's parent node.
67341-func (c *completer) builtinArgType(obj types.Object, call *ast.CallExpr, parentInf candidateInference) candidateInference {
67342-	var (
67343-		exprIdx = exprAtPos(c.pos, call.Args)
67344-
67345-		// Propagate certain properties from our parent's inference.
67346-		inf = candidateInference{
67347-			typeName:  parentInf.typeName,
67348-			modifiers: parentInf.modifiers,
67349-		}
67350-	)
67351-
67352-	switch obj.Name() {
67353-	case "append":
67354-		if exprIdx <= 0 {
67355-			// Infer first append() arg type as apparent return type of
67356-			// append().
67357-			inf.objType = parentInf.objType
67358-			if parentInf.variadic {
67359-				inf.objType = types.NewSlice(inf.objType)
67360-			}
67361-			break
67362-		}
67363-
67364-		// For non-initial append() args, infer slice type from the first
67365-		// append() arg, or from parent context.
67366-		if len(call.Args) > 0 {
67367-			inf.objType = c.pkg.GetTypesInfo().TypeOf(call.Args[0])
67368-		}
67369-		if inf.objType == nil {
67370-			inf.objType = parentInf.objType
67371-		}
67372-		if inf.objType == nil {
67373-			break
67374-		}
67375-
67376-		inf.objType = deslice(inf.objType)
67377-
67378-		// Check if we are completing the variadic append() param.
67379-		inf.variadic = exprIdx == 1 && len(call.Args) <= 2
67380-
67381-		// Penalize the first append() argument as a candidate. You
67382-		// don't normally append a slice to itself.
67383-		if sliceChain := objChain(c.pkg.GetTypesInfo(), call.Args[0]); len(sliceChain) > 0 {
67384-			inf.penalized = append(inf.penalized, penalizedObj{objChain: sliceChain, penalty: 0.9})
67385-		}
67386-	case "delete":
67387-		if exprIdx > 0 && len(call.Args) > 0 {
67388-			// Try to fill in expected type of map key.
67389-			firstArgType := c.pkg.GetTypesInfo().TypeOf(call.Args[0])
67390-			if firstArgType != nil {
67391-				if mt, ok := firstArgType.Underlying().(*types.Map); ok {
67392-					inf.objType = mt.Key()
67393-				}
67394-			}
67395-		}
67396-	case "copy":
67397-		var t1, t2 types.Type
67398-		if len(call.Args) > 0 {
67399-			t1 = c.pkg.GetTypesInfo().TypeOf(call.Args[0])
67400-			if len(call.Args) > 1 {
67401-				t2 = c.pkg.GetTypesInfo().TypeOf(call.Args[1])
67402-			}
67403-		}
67404-
67405-		// Fill in expected type of either arg if the other is already present.
67406-		if exprIdx == 1 && t1 != nil {
67407-			inf.objType = t1
67408-		} else if exprIdx == 0 && t2 != nil {
67409-			inf.objType = t2
67410-		}
67411-	case "new":
67412-		inf.typeName.wantTypeName = true
67413-		if parentInf.objType != nil {
67414-			// Expected type for "new" is the de-pointered parent type.
67415-			if ptr, ok := parentInf.objType.Underlying().(*types.Pointer); ok {
67416-				inf.objType = ptr.Elem()
67417-			}
67418-		}
67419-	case "make":
67420-		if exprIdx == 0 {
67421-			inf.typeName.wantTypeName = true
67422-			inf.objType = parentInf.objType
67423-		} else {
67424-			inf.objType = types.Typ[types.UntypedInt]
67425-		}
67426-	}
67427-
67428-	return inf
67429-}
67430diff -urN a/gopls/internal/lsp/source/completion/completion.go b/gopls/internal/lsp/source/completion/completion.go
67431--- a/gopls/internal/lsp/source/completion/completion.go	2000-01-01 00:00:00.000000000 -0000
67432+++ b/gopls/internal/lsp/source/completion/completion.go	1970-01-01 00:00:00.000000000 +0000
67433@@ -1,3252 +0,0 @@
67434-// Copyright 2018 The Go Authors. All rights reserved.
67435-// Use of this source code is governed by a BSD-style
67436-// license that can be found in the LICENSE file.
67437-
67438-// Package completion provides core functionality for code completion in Go
67439-// editors and tools.
67440-package completion
67441-
67442-import (
67443-	"bytes"
67444-	"context"
67445-	"fmt"
67446-	"go/ast"
67447-	"go/constant"
67448-	"go/parser"
67449-	"go/scanner"
67450-	"go/token"
67451-	"go/types"
67452-	"math"
67453-	"sort"
67454-	"strconv"
67455-	"strings"
67456-	"sync"
67457-	"sync/atomic"
67458-	"time"
67459-	"unicode"
67460-
67461-	"golang.org/x/sync/errgroup"
67462-	"golang.org/x/tools/go/ast/astutil"
67463-	"golang.org/x/tools/gopls/internal/lsp/protocol"
67464-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
67465-	"golang.org/x/tools/gopls/internal/lsp/snippet"
67466-	"golang.org/x/tools/gopls/internal/lsp/source"
67467-	"golang.org/x/tools/gopls/internal/span"
67468-	"golang.org/x/tools/internal/event"
67469-	"golang.org/x/tools/internal/fuzzy"
67470-	"golang.org/x/tools/internal/imports"
67471-	"golang.org/x/tools/internal/typeparams"
67472-)
67473-
67474-// A CompletionItem represents a possible completion suggested by the algorithm.
67475-type CompletionItem struct {
67476-
67477-	// Invariant: CompletionItem does not refer to syntax or types.
67478-
67479-	// Label is the primary text the user sees for this completion item.
67480-	Label string
67481-
67482-	// Detail is supplemental information to present to the user.
67483-	// This often contains the type or return type of the completion item.
67484-	Detail string
67485-
67486-	// InsertText is the text to insert if this item is selected.
67487-	// Any of the prefix that has already been typed is not trimmed.
67488-	// The insert text does not contain snippets.
67489-	InsertText string
67490-
67491-	Kind       protocol.CompletionItemKind
67492-	Tags       []protocol.CompletionItemTag
67493-	Deprecated bool // Deprecated, prefer Tags if available
67494-
67495-	// An optional array of additional TextEdits that are applied when
67496-	// selecting this completion.
67497-	//
67498-	// Additional text edits should be used to change text unrelated to the current cursor position
67499-	// (for example adding an import statement at the top of the file if the completion item will
67500-	// insert an unqualified type).
67501-	AdditionalTextEdits []protocol.TextEdit
67502-
67503-	// Depth is how many levels were searched to find this completion.
67504-	// For example when completing "foo<>", "fooBar" is depth 0, and
67505-	// "fooBar.Baz" is depth 1.
67506-	Depth int
67507-
67508-	// Score is the internal relevance score.
67509-	// A higher score indicates that this completion item is more relevant.
67510-	Score float64
67511-
67512-	// snippet is the LSP snippet for the completion item. The LSP
67513-	// specification contains details about LSP snippets. For example, a
67514-	// snippet for a function with the following signature:
67515-	//
67516-	//     func foo(a, b, c int)
67517-	//
67518-	// would be:
67519-	//
67520-	//     foo(${1:a int}, ${2: b int}, ${3: c int})
67521-	//
67522-	// If Placeholders is false in the CompletionOptions, the above
67523-	// snippet would instead be:
67524-	//
67525-	//     foo(${1:})
67526-	snippet *snippet.Builder
67527-
67528-	// Documentation is the documentation for the completion item.
67529-	Documentation string
67530-
67531-	// isSlice reports whether the underlying type of the object
67532-	// from which this candidate was derived is a slice.
67533-	// (Used to complete append() calls.)
67534-	isSlice bool
67535-}
67536-
67537-// completionOptions holds completion specific configuration.
67538-type completionOptions struct {
67539-	unimported        bool
67540-	documentation     bool
67541-	fullDocumentation bool
67542-	placeholders      bool
67543-	literal           bool
67544-	snippets          bool
67545-	postfix           bool
67546-	matcher           source.Matcher
67547-	budget            time.Duration
67548-}
67549-
67550-// Snippet is a convenience returns the snippet if available, otherwise
67551-// the InsertText.
67552-// used for an item, depending on if the callee wants placeholders or not.
67553-func (i *CompletionItem) Snippet() string {
67554-	if i.snippet != nil {
67555-		return i.snippet.String()
67556-	}
67557-	return i.InsertText
67558-}
67559-
67560-// Scoring constants are used for weighting the relevance of different candidates.
67561-const (
67562-	// stdScore is the base score for all completion items.
67563-	stdScore float64 = 1.0
67564-
67565-	// highScore indicates a very relevant completion item.
67566-	highScore float64 = 10.0
67567-
67568-	// lowScore indicates an irrelevant or not useful completion item.
67569-	lowScore float64 = 0.01
67570-)
67571-
67572-// matcher matches a candidate's label against the user input. The
67573-// returned score reflects the quality of the match. A score of zero
67574-// indicates no match, and a score of one means a perfect match.
67575-type matcher interface {
67576-	Score(candidateLabel string) (score float32)
67577-}
67578-
67579-// prefixMatcher implements case sensitive prefix matching.
67580-type prefixMatcher string
67581-
67582-func (pm prefixMatcher) Score(candidateLabel string) float32 {
67583-	if strings.HasPrefix(candidateLabel, string(pm)) {
67584-		return 1
67585-	}
67586-	return -1
67587-}
67588-
67589-// insensitivePrefixMatcher implements case insensitive prefix matching.
67590-type insensitivePrefixMatcher string
67591-
67592-func (ipm insensitivePrefixMatcher) Score(candidateLabel string) float32 {
67593-	if strings.HasPrefix(strings.ToLower(candidateLabel), string(ipm)) {
67594-		return 1
67595-	}
67596-	return -1
67597-}
67598-
67599-// completer contains the necessary information for a single completion request.
67600-type completer struct {
67601-	snapshot source.Snapshot
67602-	pkg      source.Package
67603-	qf       types.Qualifier          // for qualifying typed expressions
67604-	mq       source.MetadataQualifier // for syntactic qualifying
67605-	opts     *completionOptions
67606-
67607-	// completionContext contains information about the trigger for this
67608-	// completion request.
67609-	completionContext completionContext
67610-
67611-	// fh is a handle to the file associated with this completion request.
67612-	fh source.FileHandle
67613-
67614-	// filename is the name of the file associated with this completion request.
67615-	filename string
67616-
67617-	// file is the AST of the file associated with this completion request.
67618-	file *ast.File
67619-
67620-	// (tokFile, pos) is the position at which the request was triggered.
67621-	tokFile *token.File
67622-	pos     token.Pos
67623-
67624-	// path is the path of AST nodes enclosing the position.
67625-	path []ast.Node
67626-
67627-	// seen is the map that ensures we do not return duplicate results.
67628-	seen map[types.Object]bool
67629-
67630-	// items is the list of completion items returned.
67631-	items []CompletionItem
67632-
67633-	// completionCallbacks is a list of callbacks to collect completions that
67634-	// require expensive operations. This includes operations where we search
67635-	// through the entire module cache.
67636-	completionCallbacks []func(opts *imports.Options) error
67637-
67638-	// surrounding describes the identifier surrounding the position.
67639-	surrounding *Selection
67640-
67641-	// inference contains information we've inferred about ideal
67642-	// candidates such as the candidate's type.
67643-	inference candidateInference
67644-
67645-	// enclosingFunc contains information about the function enclosing
67646-	// the position.
67647-	enclosingFunc *funcInfo
67648-
67649-	// enclosingCompositeLiteral contains information about the composite literal
67650-	// enclosing the position.
67651-	enclosingCompositeLiteral *compLitInfo
67652-
67653-	// deepState contains the current state of our deep completion search.
67654-	deepState deepCompletionState
67655-
67656-	// matcher matches the candidates against the surrounding prefix.
67657-	matcher matcher
67658-
67659-	// methodSetCache caches the types.NewMethodSet call, which is relatively
67660-	// expensive and can be called many times for the same type while searching
67661-	// for deep completions.
67662-	methodSetCache map[methodSetKey]*types.MethodSet
67663-
67664-	// mapper converts the positions in the file from which the completion originated.
67665-	mapper *protocol.Mapper
67666-
67667-	// startTime is when we started processing this completion request. It does
67668-	// not include any time the request spent in the queue.
67669-	startTime time.Time
67670-
67671-	// scopes contains all scopes defined by nodes in our path,
67672-	// including nil values for nodes that don't defined a scope. It
67673-	// also includes our package scope and the universal scope at the
67674-	// end.
67675-	scopes []*types.Scope
67676-}
67677-
67678-// funcInfo holds info about a function object.
67679-type funcInfo struct {
67680-	// sig is the function declaration enclosing the position.
67681-	sig *types.Signature
67682-
67683-	// body is the function's body.
67684-	body *ast.BlockStmt
67685-}
67686-
67687-type compLitInfo struct {
67688-	// cl is the *ast.CompositeLit enclosing the position.
67689-	cl *ast.CompositeLit
67690-
67691-	// clType is the type of cl.
67692-	clType types.Type
67693-
67694-	// kv is the *ast.KeyValueExpr enclosing the position, if any.
67695-	kv *ast.KeyValueExpr
67696-
67697-	// inKey is true if we are certain the position is in the key side
67698-	// of a key-value pair.
67699-	inKey bool
67700-
67701-	// maybeInFieldName is true if inKey is false and it is possible
67702-	// we are completing a struct field name. For example,
67703-	// "SomeStruct{<>}" will be inKey=false, but maybeInFieldName=true
67704-	// because we _could_ be completing a field name.
67705-	maybeInFieldName bool
67706-}
67707-
67708-type importInfo struct {
67709-	importPath string
67710-	name       string
67711-}
67712-
67713-type methodSetKey struct {
67714-	typ         types.Type
67715-	addressable bool
67716-}
67717-
67718-type completionContext struct {
67719-	// triggerCharacter is the character used to trigger completion at current
67720-	// position, if any.
67721-	triggerCharacter string
67722-
67723-	// triggerKind is information about how a completion was triggered.
67724-	triggerKind protocol.CompletionTriggerKind
67725-
67726-	// commentCompletion is true if we are completing a comment.
67727-	commentCompletion bool
67728-
67729-	// packageCompletion is true if we are completing a package name.
67730-	packageCompletion bool
67731-}
67732-
67733-// A Selection represents the cursor position and surrounding identifier.
67734-type Selection struct {
67735-	content            string
67736-	tokFile            *token.File
67737-	start, end, cursor token.Pos // relative to rng.TokFile
67738-	mapper             *protocol.Mapper
67739-}
67740-
67741-func (p Selection) Content() string {
67742-	return p.content
67743-}
67744-
67745-func (p Selection) Range() (protocol.Range, error) {
67746-	return p.mapper.PosRange(p.tokFile, p.start, p.end)
67747-}
67748-
67749-func (p Selection) Prefix() string {
67750-	return p.content[:p.cursor-p.start]
67751-}
67752-
67753-func (p Selection) Suffix() string {
67754-	return p.content[p.cursor-p.start:]
67755-}
67756-
67757-func (c *completer) setSurrounding(ident *ast.Ident) {
67758-	if c.surrounding != nil {
67759-		return
67760-	}
67761-	if !(ident.Pos() <= c.pos && c.pos <= ident.End()) {
67762-		return
67763-	}
67764-
67765-	c.surrounding = &Selection{
67766-		content: ident.Name,
67767-		cursor:  c.pos,
67768-		// Overwrite the prefix only.
67769-		tokFile: c.tokFile,
67770-		start:   ident.Pos(),
67771-		end:     ident.End(),
67772-		mapper:  c.mapper,
67773-	}
67774-
67775-	c.setMatcherFromPrefix(c.surrounding.Prefix())
67776-}
67777-
67778-func (c *completer) setMatcherFromPrefix(prefix string) {
67779-	switch c.opts.matcher {
67780-	case source.Fuzzy:
67781-		c.matcher = fuzzy.NewMatcher(prefix)
67782-	case source.CaseSensitive:
67783-		c.matcher = prefixMatcher(prefix)
67784-	default:
67785-		c.matcher = insensitivePrefixMatcher(strings.ToLower(prefix))
67786-	}
67787-}
67788-
67789-func (c *completer) getSurrounding() *Selection {
67790-	if c.surrounding == nil {
67791-		c.surrounding = &Selection{
67792-			content: "",
67793-			cursor:  c.pos,
67794-			tokFile: c.tokFile,
67795-			start:   c.pos,
67796-			end:     c.pos,
67797-			mapper:  c.mapper,
67798-		}
67799-	}
67800-	return c.surrounding
67801-}
67802-
67803-// candidate represents a completion candidate.
67804-type candidate struct {
67805-	// obj is the types.Object to complete to.
67806-	// TODO(adonovan): eliminate dependence on go/types throughout this struct.
67807-	obj types.Object
67808-
67809-	// score is used to rank candidates.
67810-	score float64
67811-
67812-	// name is the deep object name path, e.g. "foo.bar"
67813-	name string
67814-
67815-	// detail is additional information about this item. If not specified,
67816-	// defaults to type string for the object.
67817-	detail string
67818-
67819-	// path holds the path from the search root (excluding the candidate
67820-	// itself) for a deep candidate.
67821-	path []types.Object
67822-
67823-	// pathInvokeMask is a bit mask tracking whether each entry in path
67824-	// should be formatted with "()" (i.e. whether it is a function
67825-	// invocation).
67826-	pathInvokeMask uint16
67827-
67828-	// mods contains modifications that should be applied to the
67829-	// candidate when inserted. For example, "foo" may be inserted as
67830-	// "*foo" or "foo()".
67831-	mods []typeModKind
67832-
67833-	// addressable is true if a pointer can be taken to the candidate.
67834-	addressable bool
67835-
67836-	// convertTo is a type that this candidate should be cast to. For
67837-	// example, if convertTo is float64, "foo" should be formatted as
67838-	// "float64(foo)".
67839-	convertTo types.Type
67840-
67841-	// imp is the import that needs to be added to this package in order
67842-	// for this candidate to be valid. nil if no import needed.
67843-	imp *importInfo
67844-}
67845-
67846-func (c candidate) hasMod(mod typeModKind) bool {
67847-	for _, m := range c.mods {
67848-		if m == mod {
67849-			return true
67850-		}
67851-	}
67852-	return false
67853-}
67854-
67855-// ErrIsDefinition is an error that informs the user they got no
67856-// completions because they tried to complete the name of a new object
67857-// being defined.
67858-type ErrIsDefinition struct {
67859-	objStr string
67860-}
67861-
67862-func (e ErrIsDefinition) Error() string {
67863-	msg := "this is a definition"
67864-	if e.objStr != "" {
67865-		msg += " of " + e.objStr
67866-	}
67867-	return msg
67868-}
67869-
67870-// Completion returns a list of possible candidates for completion, given a
67871-// a file and a position.
67872-//
67873-// The selection is computed based on the preceding identifier and can be used by
67874-// the client to score the quality of the completion. For instance, some clients
67875-// may tolerate imperfect matches as valid completion results, since users may make typos.
67876-func Completion(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle, protoPos protocol.Position, protoContext protocol.CompletionContext) ([]CompletionItem, *Selection, error) {
67877-	ctx, done := event.Start(ctx, "completion.Completion")
67878-	defer done()
67879-
67880-	startTime := time.Now()
67881-
67882-	pkg, pgf, err := source.PackageForFile(ctx, snapshot, fh.URI(), source.NarrowestPackage)
67883-	if err != nil || pgf.File.Package == token.NoPos {
67884-		// If we can't parse this file or find position for the package
67885-		// keyword, it may be missing a package declaration. Try offering
67886-		// suggestions for the package declaration.
67887-		// Note that this would be the case even if the keyword 'package' is
67888-		// present but no package name exists.
67889-		items, surrounding, innerErr := packageClauseCompletions(ctx, snapshot, fh, protoPos)
67890-		if innerErr != nil {
67891-			// return the error for GetParsedFile since it's more relevant in this situation.
67892-			return nil, nil, fmt.Errorf("getting file %s for Completion: %w (package completions: %v)", fh.URI(), err, innerErr)
67893-		}
67894-		return items, surrounding, nil
67895-	}
67896-	pos, err := pgf.PositionPos(protoPos)
67897-	if err != nil {
67898-		return nil, nil, err
67899-	}
67900-	// Completion is based on what precedes the cursor.
67901-	// Find the path to the position before pos.
67902-	path, _ := astutil.PathEnclosingInterval(pgf.File, pos-1, pos-1)
67903-	if path == nil {
67904-		return nil, nil, fmt.Errorf("cannot find node enclosing position")
67905-	}
67906-
67907-	// Check if completion at this position is valid. If not, return early.
67908-	switch n := path[0].(type) {
67909-	case *ast.BasicLit:
67910-		// Skip completion inside literals except for ImportSpec
67911-		if len(path) > 1 {
67912-			if _, ok := path[1].(*ast.ImportSpec); ok {
67913-				break
67914-			}
67915-		}
67916-		return nil, nil, nil
67917-	case *ast.CallExpr:
67918-		if n.Ellipsis.IsValid() && pos > n.Ellipsis && pos <= n.Ellipsis+token.Pos(len("...")) {
67919-			// Don't offer completions inside or directly after "...". For
67920-			// example, don't offer completions at "<>" in "foo(bar...<>").
67921-			return nil, nil, nil
67922-		}
67923-	case *ast.Ident:
67924-		// reject defining identifiers
67925-		if obj, ok := pkg.GetTypesInfo().Defs[n]; ok {
67926-			if v, ok := obj.(*types.Var); ok && v.IsField() && v.Embedded() {
67927-				// An anonymous field is also a reference to a type.
67928-			} else if pgf.File.Name == n {
67929-				// Don't skip completions if Ident is for package name.
67930-				break
67931-			} else {
67932-				objStr := ""
67933-				if obj != nil {
67934-					qual := types.RelativeTo(pkg.GetTypes())
67935-					objStr = types.ObjectString(obj, qual)
67936-				}
67937-				ans, sel := definition(path, obj, pgf)
67938-				if ans != nil {
67939-					sort.Slice(ans, func(i, j int) bool {
67940-						return ans[i].Score > ans[j].Score
67941-					})
67942-					return ans, sel, nil
67943-				}
67944-				return nil, nil, ErrIsDefinition{objStr: objStr}
67945-			}
67946-		}
67947-	}
67948-
67949-	// Collect all surrounding scopes, innermost first.
67950-	scopes := source.CollectScopes(pkg.GetTypesInfo(), path, pos)
67951-	scopes = append(scopes, pkg.GetTypes().Scope(), types.Universe)
67952-
67953-	opts := snapshot.View().Options()
67954-	c := &completer{
67955-		pkg:      pkg,
67956-		snapshot: snapshot,
67957-		qf:       source.Qualifier(pgf.File, pkg.GetTypes(), pkg.GetTypesInfo()),
67958-		mq:       source.MetadataQualifierForFile(snapshot, pgf.File, pkg.Metadata()),
67959-		completionContext: completionContext{
67960-			triggerCharacter: protoContext.TriggerCharacter,
67961-			triggerKind:      protoContext.TriggerKind,
67962-		},
67963-		fh:                        fh,
67964-		filename:                  fh.URI().Filename(),
67965-		tokFile:                   pgf.Tok,
67966-		file:                      pgf.File,
67967-		path:                      path,
67968-		pos:                       pos,
67969-		seen:                      make(map[types.Object]bool),
67970-		enclosingFunc:             enclosingFunction(path, pkg.GetTypesInfo()),
67971-		enclosingCompositeLiteral: enclosingCompositeLiteral(path, pos, pkg.GetTypesInfo()),
67972-		deepState: deepCompletionState{
67973-			enabled: opts.DeepCompletion,
67974-		},
67975-		opts: &completionOptions{
67976-			matcher:           opts.Matcher,
67977-			unimported:        opts.CompleteUnimported,
67978-			documentation:     opts.CompletionDocumentation && opts.HoverKind != source.NoDocumentation,
67979-			fullDocumentation: opts.HoverKind == source.FullDocumentation,
67980-			placeholders:      opts.UsePlaceholders,
67981-			literal:           opts.LiteralCompletions && opts.InsertTextFormat == protocol.SnippetTextFormat,
67982-			budget:            opts.CompletionBudget,
67983-			snippets:          opts.InsertTextFormat == protocol.SnippetTextFormat,
67984-			postfix:           opts.ExperimentalPostfixCompletions,
67985-		},
67986-		// default to a matcher that always matches
67987-		matcher:        prefixMatcher(""),
67988-		methodSetCache: make(map[methodSetKey]*types.MethodSet),
67989-		mapper:         pgf.Mapper,
67990-		startTime:      startTime,
67991-		scopes:         scopes,
67992-	}
67993-
67994-	var cancel context.CancelFunc
67995-	if c.opts.budget == 0 {
67996-		ctx, cancel = context.WithCancel(ctx)
67997-	} else {
67998-		// timeoutDuration is the completion budget remaining. If less than
67999-		// 10ms, set to 10ms
68000-		timeoutDuration := time.Until(c.startTime.Add(c.opts.budget))
68001-		if timeoutDuration < 10*time.Millisecond {
68002-			timeoutDuration = 10 * time.Millisecond
68003-		}
68004-		ctx, cancel = context.WithTimeout(ctx, timeoutDuration)
68005-	}
68006-	defer cancel()
68007-
68008-	if surrounding := c.containingIdent(pgf.Src); surrounding != nil {
68009-		c.setSurrounding(surrounding)
68010-	}
68011-
68012-	c.inference = expectedCandidate(ctx, c)
68013-
68014-	err = c.collectCompletions(ctx)
68015-	if err != nil {
68016-		return nil, nil, err
68017-	}
68018-
68019-	// Deep search collected candidates and their members for more candidates.
68020-	c.deepSearch(ctx)
68021-
68022-	for _, callback := range c.completionCallbacks {
68023-		if err := c.snapshot.RunProcessEnvFunc(ctx, callback); err != nil {
68024-			return nil, nil, err
68025-		}
68026-	}
68027-
68028-	// Search candidates populated by expensive operations like
68029-	// unimportedMembers etc. for more completion items.
68030-	c.deepSearch(ctx)
68031-
68032-	// Statement candidates offer an entire statement in certain contexts, as
68033-	// opposed to a single object. Add statement candidates last because they
68034-	// depend on other candidates having already been collected.
68035-	c.addStatementCandidates()
68036-
68037-	c.sortItems()
68038-	return c.items, c.getSurrounding(), nil
68039-}
68040-
68041-// collectCompletions adds possible completion candidates to either the deep
68042-// search queue or completion items directly for different completion contexts.
68043-func (c *completer) collectCompletions(ctx context.Context) error {
68044-	// Inside import blocks, return completions for unimported packages.
68045-	for _, importSpec := range c.file.Imports {
68046-		if !(importSpec.Path.Pos() <= c.pos && c.pos <= importSpec.Path.End()) {
68047-			continue
68048-		}
68049-		return c.populateImportCompletions(ctx, importSpec)
68050-	}
68051-
68052-	// Inside comments, offer completions for the name of the relevant symbol.
68053-	for _, comment := range c.file.Comments {
68054-		if comment.Pos() < c.pos && c.pos <= comment.End() {
68055-			c.populateCommentCompletions(ctx, comment)
68056-			return nil
68057-		}
68058-	}
68059-
68060-	// Struct literals are handled entirely separately.
68061-	if c.wantStructFieldCompletions() {
68062-		// If we are definitely completing a struct field name, deep completions
68063-		// don't make sense.
68064-		if c.enclosingCompositeLiteral.inKey {
68065-			c.deepState.enabled = false
68066-		}
68067-		return c.structLiteralFieldName(ctx)
68068-	}
68069-
68070-	if lt := c.wantLabelCompletion(); lt != labelNone {
68071-		c.labels(lt)
68072-		return nil
68073-	}
68074-
68075-	if c.emptySwitchStmt() {
68076-		// Empty switch statements only admit "default" and "case" keywords.
68077-		c.addKeywordItems(map[string]bool{}, highScore, CASE, DEFAULT)
68078-		return nil
68079-	}
68080-
68081-	switch n := c.path[0].(type) {
68082-	case *ast.Ident:
68083-		if c.file.Name == n {
68084-			return c.packageNameCompletions(ctx, c.fh.URI(), n)
68085-		} else if sel, ok := c.path[1].(*ast.SelectorExpr); ok && sel.Sel == n {
68086-			// Is this the Sel part of a selector?
68087-			return c.selector(ctx, sel)
68088-		}
68089-		return c.lexical(ctx)
68090-	// The function name hasn't been typed yet, but the parens are there:
68091-	//   recv.‸(arg)
68092-	case *ast.TypeAssertExpr:
68093-		// Create a fake selector expression.
68094-		return c.selector(ctx, &ast.SelectorExpr{X: n.X})
68095-	case *ast.SelectorExpr:
68096-		return c.selector(ctx, n)
68097-	// At the file scope, only keywords are allowed.
68098-	case *ast.BadDecl, *ast.File:
68099-		c.addKeywordCompletions()
68100-	default:
68101-		// fallback to lexical completions
68102-		return c.lexical(ctx)
68103-	}
68104-
68105-	return nil
68106-}
68107-
68108-// containingIdent returns the *ast.Ident containing pos, if any. It
68109-// synthesizes an *ast.Ident to allow completion in the face of
68110-// certain syntax errors.
68111-func (c *completer) containingIdent(src []byte) *ast.Ident {
68112-	// In the normal case, our leaf AST node is the identifier being completed.
68113-	if ident, ok := c.path[0].(*ast.Ident); ok {
68114-		return ident
68115-	}
68116-
68117-	pos, tkn, lit := c.scanToken(src)
68118-	if !pos.IsValid() {
68119-		return nil
68120-	}
68121-
68122-	fakeIdent := &ast.Ident{Name: lit, NamePos: pos}
68123-
68124-	if _, isBadDecl := c.path[0].(*ast.BadDecl); isBadDecl {
68125-		// You don't get *ast.Idents at the file level, so look for bad
68126-		// decls and use the manually extracted token.
68127-		return fakeIdent
68128-	} else if c.emptySwitchStmt() {
68129-		// Only keywords are allowed in empty switch statements.
68130-		// *ast.Idents are not parsed, so we must use the manually
68131-		// extracted token.
68132-		return fakeIdent
68133-	} else if tkn.IsKeyword() {
68134-		// Otherwise, manually extract the prefix if our containing token
68135-		// is a keyword. This improves completion after an "accidental
68136-		// keyword", e.g. completing to "variance" in "someFunc(var<>)".
68137-		return fakeIdent
68138-	}
68139-
68140-	return nil
68141-}
68142-
68143-// scanToken scans pgh's contents for the token containing pos.
68144-func (c *completer) scanToken(contents []byte) (token.Pos, token.Token, string) {
68145-	tok := c.pkg.FileSet().File(c.pos)
68146-
68147-	var s scanner.Scanner
68148-	s.Init(tok, contents, nil, 0)
68149-	for {
68150-		tknPos, tkn, lit := s.Scan()
68151-		if tkn == token.EOF || tknPos >= c.pos {
68152-			return token.NoPos, token.ILLEGAL, ""
68153-		}
68154-
68155-		if len(lit) > 0 && tknPos <= c.pos && c.pos <= tknPos+token.Pos(len(lit)) {
68156-			return tknPos, tkn, lit
68157-		}
68158-	}
68159-}
68160-
68161-func (c *completer) sortItems() {
68162-	sort.SliceStable(c.items, func(i, j int) bool {
68163-		// Sort by score first.
68164-		if c.items[i].Score != c.items[j].Score {
68165-			return c.items[i].Score > c.items[j].Score
68166-		}
68167-
68168-		// Then sort by label so order stays consistent. This also has the
68169-		// effect of preferring shorter candidates.
68170-		return c.items[i].Label < c.items[j].Label
68171-	})
68172-}
68173-
68174-// emptySwitchStmt reports whether pos is in an empty switch or select
68175-// statement.
68176-func (c *completer) emptySwitchStmt() bool {
68177-	block, ok := c.path[0].(*ast.BlockStmt)
68178-	if !ok || len(block.List) > 0 || len(c.path) == 1 {
68179-		return false
68180-	}
68181-
68182-	switch c.path[1].(type) {
68183-	case *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt:
68184-		return true
68185-	default:
68186-		return false
68187-	}
68188-}
68189-
68190-// populateImportCompletions yields completions for an import path around the cursor.
68191-//
68192-// Completions are suggested at the directory depth of the given import path so
68193-// that we don't overwhelm the user with a large list of possibilities. As an
68194-// example, a completion for the prefix "golang" results in "golang.org/".
68195-// Completions for "golang.org/" yield its subdirectories
68196-// (i.e. "golang.org/x/"). The user is meant to accept completion suggestions
68197-// until they reach a complete import path.
68198-func (c *completer) populateImportCompletions(ctx context.Context, searchImport *ast.ImportSpec) error {
68199-	if !strings.HasPrefix(searchImport.Path.Value, `"`) {
68200-		return nil
68201-	}
68202-
68203-	// deepSearch is not valuable for import completions.
68204-	c.deepState.enabled = false
68205-
68206-	importPath := searchImport.Path.Value
68207-
68208-	// Extract the text between the quotes (if any) in an import spec.
68209-	// prefix is the part of import path before the cursor.
68210-	prefixEnd := c.pos - searchImport.Path.Pos()
68211-	prefix := strings.Trim(importPath[:prefixEnd], `"`)
68212-
68213-	// The number of directories in the import path gives us the depth at
68214-	// which to search.
68215-	depth := len(strings.Split(prefix, "/")) - 1
68216-
68217-	content := importPath
68218-	start, end := searchImport.Path.Pos(), searchImport.Path.End()
68219-	namePrefix, nameSuffix := `"`, `"`
68220-	// If a starting quote is present, adjust surrounding to either after the
68221-	// cursor or after the first slash (/), except if cursor is at the starting
68222-	// quote. Otherwise we provide a completion including the starting quote.
68223-	if strings.HasPrefix(importPath, `"`) && c.pos > searchImport.Path.Pos() {
68224-		content = content[1:]
68225-		start++
68226-		if depth > 0 {
68227-			// Adjust textEdit start to replacement range. For ex: if current
68228-			// path was "golang.or/x/to<>ols/internal/", where <> is the cursor
68229-			// position, start of the replacement range would be after
68230-			// "golang.org/x/".
68231-			path := strings.SplitAfter(prefix, "/")
68232-			numChars := len(strings.Join(path[:len(path)-1], ""))
68233-			content = content[numChars:]
68234-			start += token.Pos(numChars)
68235-		}
68236-		namePrefix = ""
68237-	}
68238-
68239-	// We won't provide an ending quote if one is already present, except if
68240-	// cursor is after the ending quote but still in import spec. This is
68241-	// because cursor has to be in our textEdit range.
68242-	if strings.HasSuffix(importPath, `"`) && c.pos < searchImport.Path.End() {
68243-		end--
68244-		content = content[:len(content)-1]
68245-		nameSuffix = ""
68246-	}
68247-
68248-	c.surrounding = &Selection{
68249-		content: content,
68250-		cursor:  c.pos,
68251-		tokFile: c.tokFile,
68252-		start:   start,
68253-		end:     end,
68254-		mapper:  c.mapper,
68255-	}
68256-
68257-	seenImports := make(map[string]struct{})
68258-	for _, importSpec := range c.file.Imports {
68259-		if importSpec.Path.Value == importPath {
68260-			continue
68261-		}
68262-		seenImportPath, err := strconv.Unquote(importSpec.Path.Value)
68263-		if err != nil {
68264-			return err
68265-		}
68266-		seenImports[seenImportPath] = struct{}{}
68267-	}
68268-
68269-	var mu sync.Mutex // guard c.items locally, since searchImports is called in parallel
68270-	seen := make(map[string]struct{})
68271-	searchImports := func(pkg imports.ImportFix) {
68272-		path := pkg.StmtInfo.ImportPath
68273-		if _, ok := seenImports[path]; ok {
68274-			return
68275-		}
68276-
68277-		// Any package path containing fewer directories than the search
68278-		// prefix is not a match.
68279-		pkgDirList := strings.Split(path, "/")
68280-		if len(pkgDirList) < depth+1 {
68281-			return
68282-		}
68283-		pkgToConsider := strings.Join(pkgDirList[:depth+1], "/")
68284-
68285-		name := pkgDirList[depth]
68286-		// if we're adding an opening quote to completion too, set name to full
68287-		// package path since we'll need to overwrite that range.
68288-		if namePrefix == `"` {
68289-			name = pkgToConsider
68290-		}
68291-
68292-		score := pkg.Relevance
68293-		if len(pkgDirList)-1 == depth {
68294-			score *= highScore
68295-		} else {
68296-			// For incomplete package paths, add a terminal slash to indicate that the
68297-			// user should keep triggering completions.
68298-			name += "/"
68299-			pkgToConsider += "/"
68300-		}
68301-
68302-		if _, ok := seen[pkgToConsider]; ok {
68303-			return
68304-		}
68305-		seen[pkgToConsider] = struct{}{}
68306-
68307-		mu.Lock()
68308-		defer mu.Unlock()
68309-
68310-		name = namePrefix + name + nameSuffix
68311-		obj := types.NewPkgName(0, nil, name, types.NewPackage(pkgToConsider, name))
68312-		c.deepState.enqueue(candidate{
68313-			obj:    obj,
68314-			detail: fmt.Sprintf("%q", pkgToConsider),
68315-			score:  score,
68316-		})
68317-	}
68318-
68319-	c.completionCallbacks = append(c.completionCallbacks, func(opts *imports.Options) error {
68320-		return imports.GetImportPaths(ctx, searchImports, prefix, c.filename, c.pkg.GetTypes().Name(), opts.Env)
68321-	})
68322-	return nil
68323-}
68324-
68325-// populateCommentCompletions yields completions for comments preceding or in declarations.
68326-func (c *completer) populateCommentCompletions(ctx context.Context, comment *ast.CommentGroup) {
68327-	// If the completion was triggered by a period, ignore it. These types of
68328-	// completions will not be useful in comments.
68329-	if c.completionContext.triggerCharacter == "." {
68330-		return
68331-	}
68332-
68333-	// Using the comment position find the line after
68334-	file := c.pkg.FileSet().File(comment.End())
68335-	if file == nil {
68336-		return
68337-	}
68338-
68339-	// Deep completion doesn't work properly in comments since we don't
68340-	// have a type object to complete further.
68341-	c.deepState.enabled = false
68342-	c.completionContext.commentCompletion = true
68343-
68344-	// Documentation isn't useful in comments, since it might end up being the
68345-	// comment itself.
68346-	c.opts.documentation = false
68347-
68348-	commentLine := file.Line(comment.End())
68349-
68350-	// comment is valid, set surrounding as word boundaries around cursor
68351-	c.setSurroundingForComment(comment)
68352-
68353-	// Using the next line pos, grab and parse the exported symbol on that line
68354-	for _, n := range c.file.Decls {
68355-		declLine := file.Line(n.Pos())
68356-		// if the comment is not in, directly above or on the same line as a declaration
68357-		if declLine != commentLine && declLine != commentLine+1 &&
68358-			!(n.Pos() <= comment.Pos() && comment.End() <= n.End()) {
68359-			continue
68360-		}
68361-		switch node := n.(type) {
68362-		// handle const, vars, and types
68363-		case *ast.GenDecl:
68364-			for _, spec := range node.Specs {
68365-				switch spec := spec.(type) {
68366-				case *ast.ValueSpec:
68367-					for _, name := range spec.Names {
68368-						if name.String() == "_" {
68369-							continue
68370-						}
68371-						obj := c.pkg.GetTypesInfo().ObjectOf(name)
68372-						c.deepState.enqueue(candidate{obj: obj, score: stdScore})
68373-					}
68374-				case *ast.TypeSpec:
68375-					// add TypeSpec fields to completion
68376-					switch typeNode := spec.Type.(type) {
68377-					case *ast.StructType:
68378-						c.addFieldItems(ctx, typeNode.Fields)
68379-					case *ast.FuncType:
68380-						c.addFieldItems(ctx, typeNode.Params)
68381-						c.addFieldItems(ctx, typeNode.Results)
68382-					case *ast.InterfaceType:
68383-						c.addFieldItems(ctx, typeNode.Methods)
68384-					}
68385-
68386-					if spec.Name.String() == "_" {
68387-						continue
68388-					}
68389-
68390-					obj := c.pkg.GetTypesInfo().ObjectOf(spec.Name)
68391-					// Type name should get a higher score than fields but not highScore by default
68392-					// since field near a comment cursor gets a highScore
68393-					score := stdScore * 1.1
68394-					// If type declaration is on the line after comment, give it a highScore.
68395-					if declLine == commentLine+1 {
68396-						score = highScore
68397-					}
68398-
68399-					c.deepState.enqueue(candidate{obj: obj, score: score})
68400-				}
68401-			}
68402-		// handle functions
68403-		case *ast.FuncDecl:
68404-			c.addFieldItems(ctx, node.Recv)
68405-			c.addFieldItems(ctx, node.Type.Params)
68406-			c.addFieldItems(ctx, node.Type.Results)
68407-
68408-			// collect receiver struct fields
68409-			if node.Recv != nil {
68410-				for _, fields := range node.Recv.List {
68411-					for _, name := range fields.Names {
68412-						obj := c.pkg.GetTypesInfo().ObjectOf(name)
68413-						if obj == nil {
68414-							continue
68415-						}
68416-
68417-						recvType := obj.Type().Underlying()
68418-						if ptr, ok := recvType.(*types.Pointer); ok {
68419-							recvType = ptr.Elem()
68420-						}
68421-						recvStruct, ok := recvType.Underlying().(*types.Struct)
68422-						if !ok {
68423-							continue
68424-						}
68425-						for i := 0; i < recvStruct.NumFields(); i++ {
68426-							field := recvStruct.Field(i)
68427-							c.deepState.enqueue(candidate{obj: field, score: lowScore})
68428-						}
68429-					}
68430-				}
68431-			}
68432-
68433-			if node.Name.String() == "_" {
68434-				continue
68435-			}
68436-
68437-			obj := c.pkg.GetTypesInfo().ObjectOf(node.Name)
68438-			if obj == nil || obj.Pkg() != nil && obj.Pkg() != c.pkg.GetTypes() {
68439-				continue
68440-			}
68441-
68442-			c.deepState.enqueue(candidate{obj: obj, score: highScore})
68443-		}
68444-	}
68445-}
68446-
68447-// sets word boundaries surrounding a cursor for a comment
68448-func (c *completer) setSurroundingForComment(comments *ast.CommentGroup) {
68449-	var cursorComment *ast.Comment
68450-	for _, comment := range comments.List {
68451-		if c.pos >= comment.Pos() && c.pos <= comment.End() {
68452-			cursorComment = comment
68453-			break
68454-		}
68455-	}
68456-	// if cursor isn't in the comment
68457-	if cursorComment == nil {
68458-		return
68459-	}
68460-
68461-	// index of cursor in comment text
68462-	cursorOffset := int(c.pos - cursorComment.Pos())
68463-	start, end := cursorOffset, cursorOffset
68464-	for start > 0 && isValidIdentifierChar(cursorComment.Text[start-1]) {
68465-		start--
68466-	}
68467-	for end < len(cursorComment.Text) && isValidIdentifierChar(cursorComment.Text[end]) {
68468-		end++
68469-	}
68470-
68471-	c.surrounding = &Selection{
68472-		content: cursorComment.Text[start:end],
68473-		cursor:  c.pos,
68474-		tokFile: c.tokFile,
68475-		start:   token.Pos(int(cursorComment.Slash) + start),
68476-		end:     token.Pos(int(cursorComment.Slash) + end),
68477-		mapper:  c.mapper,
68478-	}
68479-	c.setMatcherFromPrefix(c.surrounding.Prefix())
68480-}
68481-
68482-// isValidIdentifierChar returns true if a byte is a valid go identifier
68483-// character, i.e. unicode letter or digit or underscore.
68484-func isValidIdentifierChar(char byte) bool {
68485-	charRune := rune(char)
68486-	return unicode.In(charRune, unicode.Letter, unicode.Digit) || char == '_'
68487-}
68488-
68489-// adds struct fields, interface methods, function declaration fields to completion
68490-func (c *completer) addFieldItems(ctx context.Context, fields *ast.FieldList) {
68491-	if fields == nil {
68492-		return
68493-	}
68494-
68495-	cursor := c.surrounding.cursor
68496-	for _, field := range fields.List {
68497-		for _, name := range field.Names {
68498-			if name.String() == "_" {
68499-				continue
68500-			}
68501-			obj := c.pkg.GetTypesInfo().ObjectOf(name)
68502-			if obj == nil {
68503-				continue
68504-			}
68505-
68506-			// if we're in a field comment/doc, score that field as more relevant
68507-			score := stdScore
68508-			if field.Comment != nil && field.Comment.Pos() <= cursor && cursor <= field.Comment.End() {
68509-				score = highScore
68510-			} else if field.Doc != nil && field.Doc.Pos() <= cursor && cursor <= field.Doc.End() {
68511-				score = highScore
68512-			}
68513-
68514-			c.deepState.enqueue(candidate{obj: obj, score: score})
68515-		}
68516-	}
68517-}
68518-
68519-func (c *completer) wantStructFieldCompletions() bool {
68520-	clInfo := c.enclosingCompositeLiteral
68521-	if clInfo == nil {
68522-		return false
68523-	}
68524-
68525-	return clInfo.isStruct() && (clInfo.inKey || clInfo.maybeInFieldName)
68526-}
68527-
68528-func (c *completer) wantTypeName() bool {
68529-	return !c.completionContext.commentCompletion && c.inference.typeName.wantTypeName
68530-}
68531-
68532-// See https://golang.org/issue/36001. Unimported completions are expensive.
68533-const (
68534-	maxUnimportedPackageNames = 5
68535-	unimportedMemberTarget    = 100
68536-)
68537-
68538-// selector finds completions for the specified selector expression.
68539-func (c *completer) selector(ctx context.Context, sel *ast.SelectorExpr) error {
68540-	c.inference.objChain = objChain(c.pkg.GetTypesInfo(), sel.X)
68541-
68542-	// True selector?
68543-	if tv, ok := c.pkg.GetTypesInfo().Types[sel.X]; ok {
68544-		c.methodsAndFields(tv.Type, tv.Addressable(), nil, c.deepState.enqueue)
68545-		c.addPostfixSnippetCandidates(ctx, sel)
68546-		return nil
68547-	}
68548-
68549-	id, ok := sel.X.(*ast.Ident)
68550-	if !ok {
68551-		return nil
68552-	}
68553-
68554-	// Treat sel as a qualified identifier.
68555-	var filter func(*source.Metadata) bool
68556-	needImport := false
68557-	if pkgName, ok := c.pkg.GetTypesInfo().Uses[id].(*types.PkgName); ok {
68558-		// Qualified identifier with import declaration.
68559-		imp := pkgName.Imported()
68560-
68561-		// Known direct dependency? Expand using type information.
68562-		if _, ok := c.pkg.Metadata().DepsByPkgPath[source.PackagePath(imp.Path())]; ok {
68563-			c.packageMembers(imp, stdScore, nil, c.deepState.enqueue)
68564-			return nil
68565-		}
68566-
68567-		// Imported declaration with missing type information.
68568-		// Fall through to shallow completion of unimported package members.
68569-		// Match candidate packages by path.
68570-		// TODO(adonovan): simplify by merging with else case and matching on name only?
68571-		filter = func(m *source.Metadata) bool {
68572-			return strings.TrimPrefix(string(m.PkgPath), "vendor/") == imp.Path()
68573-		}
68574-	} else {
68575-		// Qualified identifier without import declaration.
68576-		// Match candidate packages by name.
68577-		filter = func(m *source.Metadata) bool {
68578-			return string(m.Name) == id.Name
68579-		}
68580-		needImport = true
68581-	}
68582-
68583-	// Search unimported packages.
68584-	if !c.opts.unimported {
68585-		return nil // feature disabled
68586-	}
68587-
68588-	// The deep completion algorithm is exceedingly complex and
68589-	// deeply coupled to the now obsolete notions that all
68590-	// token.Pos values can be interpreted by as a single FileSet
68591-	// belonging to the Snapshot and that all types.Object values
68592-	// are canonicalized by a single types.Importer mapping.
68593-	// These invariants are no longer true now that gopls uses
68594-	// an incremental approach, parsing and type-checking each
68595-	// package separately.
68596-	//
68597-	// Consequently, completion of symbols defined in packages that
68598-	// are not currently imported by the query file cannot use the
68599-	// deep completion machinery which is based on type information.
68600-	// Instead it must use only syntax information from a quick
68601-	// parse of top-level declarations (but not function bodies).
68602-	//
68603-	// TODO(adonovan): rewrite the deep completion machinery to
68604-	// not assume global Pos/Object realms and then use export
68605-	// data instead of the quick parse approach taken here.
68606-
68607-	// First, we search among packages in the workspace.
68608-	// We'll use a fast parse to extract package members
68609-	// from those that match the name/path criterion.
68610-	all, err := c.snapshot.AllMetadata(ctx)
68611-	if err != nil {
68612-		return err
68613-	}
68614-	var paths []string
68615-	known := make(map[source.PackagePath][]*source.Metadata) // may include test variant
68616-	for _, m := range all {
68617-		if m.IsIntermediateTestVariant() || m.Name == "main" || !filter(m) {
68618-			continue
68619-		}
68620-		known[m.PkgPath] = append(known[m.PkgPath], m)
68621-		paths = append(paths, string(m.PkgPath))
68622-	}
68623-
68624-	// Rank import paths as goimports would.
68625-	var relevances map[string]float64
68626-	if len(paths) > 0 {
68627-		if err := c.snapshot.RunProcessEnvFunc(ctx, func(opts *imports.Options) error {
68628-			var err error
68629-			relevances, err = imports.ScoreImportPaths(ctx, opts.Env, paths)
68630-			return err
68631-		}); err != nil {
68632-			return err
68633-		}
68634-		sort.Slice(paths, func(i, j int) bool {
68635-			return relevances[paths[i]] > relevances[paths[j]]
68636-		})
68637-	}
68638-
68639-	// quickParse does a quick parse of a single file of package m,
68640-	// extracts exported package members and adds candidates to c.items.
68641-	var itemsMu sync.Mutex // guards c.items
68642-	var enough int32       // atomic bool
68643-	quickParse := func(uri span.URI, m *source.Metadata) error {
68644-		if atomic.LoadInt32(&enough) != 0 {
68645-			return nil
68646-		}
68647-
68648-		fh, err := c.snapshot.GetFile(ctx, uri)
68649-		if err != nil {
68650-			return err
68651-		}
68652-		content, err := fh.Read()
68653-		if err != nil {
68654-			return err
68655-		}
68656-		path := string(m.PkgPath)
68657-		forEachPackageMember(content, func(tok token.Token, id *ast.Ident, fn *ast.FuncDecl) {
68658-			if atomic.LoadInt32(&enough) != 0 {
68659-				return
68660-			}
68661-
68662-			if !id.IsExported() ||
68663-				sel.Sel.Name != "_" && !strings.HasPrefix(id.Name, sel.Sel.Name) {
68664-				return // not a match
68665-			}
68666-
68667-			// The only detail is the kind and package: `var (from "example.com/foo")`
68668-			// TODO(adonovan): pretty-print FuncDecl.FuncType or TypeSpec.Type?
68669-			item := CompletionItem{
68670-				Label:      id.Name,
68671-				Detail:     fmt.Sprintf("%s (from %q)", strings.ToLower(tok.String()), m.PkgPath),
68672-				InsertText: id.Name,
68673-				Score:      unimportedScore(relevances[path]),
68674-			}
68675-			switch tok {
68676-			case token.FUNC:
68677-				item.Kind = protocol.FunctionCompletion
68678-			case token.VAR:
68679-				item.Kind = protocol.VariableCompletion
68680-			case token.CONST:
68681-				item.Kind = protocol.ConstantCompletion
68682-			case token.TYPE:
68683-				// Without types, we can't distinguish Class from Interface.
68684-				item.Kind = protocol.ClassCompletion
68685-			}
68686-
68687-			if needImport {
68688-				imp := &importInfo{importPath: path}
68689-				if imports.ImportPathToAssumedName(path) != string(m.Name) {
68690-					imp.name = string(m.Name)
68691-				}
68692-				item.AdditionalTextEdits, _ = c.importEdits(imp)
68693-			}
68694-
68695-			// For functions, add a parameter snippet.
68696-			if fn != nil {
68697-				var sn snippet.Builder
68698-				sn.WriteText(id.Name)
68699-				sn.WriteText("(")
68700-				var nparams int
68701-				for _, field := range fn.Type.Params.List {
68702-					if field.Names != nil {
68703-						nparams += len(field.Names)
68704-					} else {
68705-						nparams++
68706-					}
68707-				}
68708-				for i := 0; i < nparams; i++ {
68709-					if i > 0 {
68710-						sn.WriteText(", ")
68711-					}
68712-					sn.WritePlaceholder(nil)
68713-				}
68714-				sn.WriteText(")")
68715-				item.snippet = &sn
68716-			}
68717-
68718-			itemsMu.Lock()
68719-			c.items = append(c.items, item)
68720-			if len(c.items) >= unimportedMemberTarget {
68721-				atomic.StoreInt32(&enough, 1)
68722-			}
68723-			itemsMu.Unlock()
68724-		})
68725-		return nil
68726-	}
68727-
68728-	// Extract the package-level candidates using a quick parse.
68729-	var g errgroup.Group
68730-	for _, path := range paths {
68731-		for _, m := range known[source.PackagePath(path)] {
68732-			m := m
68733-			for _, uri := range m.CompiledGoFiles {
68734-				uri := uri
68735-				g.Go(func() error {
68736-					return quickParse(uri, m)
68737-				})
68738-			}
68739-		}
68740-	}
68741-	if err := g.Wait(); err != nil {
68742-		return err
68743-	}
68744-
68745-	// In addition, we search in the module cache using goimports.
68746-	ctx, cancel := context.WithCancel(ctx)
68747-	var mu sync.Mutex
68748-	add := func(pkgExport imports.PackageExport) {
68749-		mu.Lock()
68750-		defer mu.Unlock()
68751-		// TODO(adonovan): what if the actual package has a vendor/ prefix?
68752-		if _, ok := known[source.PackagePath(pkgExport.Fix.StmtInfo.ImportPath)]; ok {
68753-			return // We got this one above.
68754-		}
68755-
68756-		// Continue with untyped proposals.
68757-		pkg := types.NewPackage(pkgExport.Fix.StmtInfo.ImportPath, pkgExport.Fix.IdentName)
68758-		for _, export := range pkgExport.Exports {
68759-			score := unimportedScore(pkgExport.Fix.Relevance)
68760-			c.deepState.enqueue(candidate{
68761-				obj:   types.NewVar(0, pkg, export, nil),
68762-				score: score,
68763-				imp: &importInfo{
68764-					importPath: pkgExport.Fix.StmtInfo.ImportPath,
68765-					name:       pkgExport.Fix.StmtInfo.Name,
68766-				},
68767-			})
68768-		}
68769-		if len(c.items) >= unimportedMemberTarget {
68770-			cancel()
68771-		}
68772-	}
68773-
68774-	c.completionCallbacks = append(c.completionCallbacks, func(opts *imports.Options) error {
68775-		defer cancel()
68776-		return imports.GetPackageExports(ctx, add, id.Name, c.filename, c.pkg.GetTypes().Name(), opts.Env)
68777-	})
68778-	return nil
68779-}
68780-
68781-// unimportedScore returns a score for an unimported package that is generally
68782-// lower than other candidates.
68783-func unimportedScore(relevance float64) float64 {
68784-	return (stdScore + .1*relevance) / 2
68785-}
68786-
68787-func (c *completer) packageMembers(pkg *types.Package, score float64, imp *importInfo, cb func(candidate)) {
68788-	scope := pkg.Scope()
68789-	for _, name := range scope.Names() {
68790-		obj := scope.Lookup(name)
68791-		cb(candidate{
68792-			obj:         obj,
68793-			score:       score,
68794-			imp:         imp,
68795-			addressable: isVar(obj),
68796-		})
68797-	}
68798-}
68799-
68800-func (c *completer) methodsAndFields(typ types.Type, addressable bool, imp *importInfo, cb func(candidate)) {
68801-	mset := c.methodSetCache[methodSetKey{typ, addressable}]
68802-	if mset == nil {
68803-		if addressable && !types.IsInterface(typ) && !isPointer(typ) {
68804-			// Add methods of *T, which includes methods with receiver T.
68805-			mset = types.NewMethodSet(types.NewPointer(typ))
68806-		} else {
68807-			// Add methods of T.
68808-			mset = types.NewMethodSet(typ)
68809-		}
68810-		c.methodSetCache[methodSetKey{typ, addressable}] = mset
68811-	}
68812-
68813-	if isStarTestingDotF(typ) && addressable {
68814-		// is that a sufficient test? (or is more care needed?)
68815-		if c.fuzz(typ, mset, imp, cb, c.pkg.FileSet()) {
68816-			return
68817-		}
68818-	}
68819-
68820-	for i := 0; i < mset.Len(); i++ {
68821-		cb(candidate{
68822-			obj:         mset.At(i).Obj(),
68823-			score:       stdScore,
68824-			imp:         imp,
68825-			addressable: addressable || isPointer(typ),
68826-		})
68827-	}
68828-
68829-	// Add fields of T.
68830-	eachField(typ, func(v *types.Var) {
68831-		cb(candidate{
68832-			obj:         v,
68833-			score:       stdScore - 0.01,
68834-			imp:         imp,
68835-			addressable: addressable || isPointer(typ),
68836-		})
68837-	})
68838-}
68839-
68840-// isStarTestingDotF reports whether typ is *testing.F.
68841-func isStarTestingDotF(typ types.Type) bool {
68842-	ptr, _ := typ.(*types.Pointer)
68843-	if ptr == nil {
68844-		return false
68845-	}
68846-	named, _ := ptr.Elem().(*types.Named)
68847-	if named == nil {
68848-		return false
68849-	}
68850-	obj := named.Obj()
68851-	// obj.Pkg is nil for the error type.
68852-	return obj != nil && obj.Pkg() != nil && obj.Pkg().Path() == "testing" && obj.Name() == "F"
68853-}
68854-
68855-// lexical finds completions in the lexical environment.
68856-func (c *completer) lexical(ctx context.Context) error {
68857-	var (
68858-		builtinIota = types.Universe.Lookup("iota")
68859-		builtinNil  = types.Universe.Lookup("nil")
68860-
68861-		// TODO(rfindley): only allow "comparable" where it is valid (in constraint
68862-		// position or embedded in interface declarations).
68863-		// builtinComparable = types.Universe.Lookup("comparable")
68864-	)
68865-
68866-	// Track seen variables to avoid showing completions for shadowed variables.
68867-	// This works since we look at scopes from innermost to outermost.
68868-	seen := make(map[string]struct{})
68869-
68870-	// Process scopes innermost first.
68871-	for i, scope := range c.scopes {
68872-		if scope == nil {
68873-			continue
68874-		}
68875-
68876-	Names:
68877-		for _, name := range scope.Names() {
68878-			declScope, obj := scope.LookupParent(name, c.pos)
68879-			if declScope != scope {
68880-				continue // Name was declared in some enclosing scope, or not at all.
68881-			}
68882-
68883-			// If obj's type is invalid, find the AST node that defines the lexical block
68884-			// containing the declaration of obj. Don't resolve types for packages.
68885-			if !isPkgName(obj) && !typeIsValid(obj.Type()) {
68886-				// Match the scope to its ast.Node. If the scope is the package scope,
68887-				// use the *ast.File as the starting node.
68888-				var node ast.Node
68889-				if i < len(c.path) {
68890-					node = c.path[i]
68891-				} else if i == len(c.path) { // use the *ast.File for package scope
68892-					node = c.path[i-1]
68893-				}
68894-				if node != nil {
68895-					if resolved := resolveInvalid(c.pkg.FileSet(), obj, node, c.pkg.GetTypesInfo()); resolved != nil {
68896-						obj = resolved
68897-					}
68898-				}
68899-			}
68900-
68901-			// Don't use LHS of decl in RHS.
68902-			for _, ident := range enclosingDeclLHS(c.path) {
68903-				if obj.Pos() == ident.Pos() {
68904-					continue Names
68905-				}
68906-			}
68907-
68908-			// Don't suggest "iota" outside of const decls.
68909-			if obj == builtinIota && !c.inConstDecl() {
68910-				continue
68911-			}
68912-
68913-			// Rank outer scopes lower than inner.
68914-			score := stdScore * math.Pow(.99, float64(i))
68915-
68916-			// Dowrank "nil" a bit so it is ranked below more interesting candidates.
68917-			if obj == builtinNil {
68918-				score /= 2
68919-			}
68920-
68921-			// If we haven't already added a candidate for an object with this name.
68922-			if _, ok := seen[obj.Name()]; !ok {
68923-				seen[obj.Name()] = struct{}{}
68924-				c.deepState.enqueue(candidate{
68925-					obj:         obj,
68926-					score:       score,
68927-					addressable: isVar(obj),
68928-				})
68929-			}
68930-		}
68931-	}
68932-
68933-	if c.inference.objType != nil {
68934-		if named, _ := source.Deref(c.inference.objType).(*types.Named); named != nil {
68935-			// If we expected a named type, check the type's package for
68936-			// completion items. This is useful when the current file hasn't
68937-			// imported the type's package yet.
68938-
68939-			if named.Obj() != nil && named.Obj().Pkg() != nil {
68940-				pkg := named.Obj().Pkg()
68941-
68942-				// Make sure the package name isn't already in use by another
68943-				// object, and that this file doesn't import the package yet.
68944-				// TODO(adonovan): what if pkg.Path has vendor/ prefix?
68945-				if _, ok := seen[pkg.Name()]; !ok && pkg != c.pkg.GetTypes() && !alreadyImports(c.file, source.ImportPath(pkg.Path())) {
68946-					seen[pkg.Name()] = struct{}{}
68947-					obj := types.NewPkgName(0, nil, pkg.Name(), pkg)
68948-					imp := &importInfo{
68949-						importPath: pkg.Path(),
68950-					}
68951-					if imports.ImportPathToAssumedName(pkg.Path()) != pkg.Name() {
68952-						imp.name = pkg.Name()
68953-					}
68954-					c.deepState.enqueue(candidate{
68955-						obj:   obj,
68956-						score: stdScore,
68957-						imp:   imp,
68958-					})
68959-				}
68960-			}
68961-		}
68962-	}
68963-
68964-	if c.opts.unimported {
68965-		if err := c.unimportedPackages(ctx, seen); err != nil {
68966-			return err
68967-		}
68968-	}
68969-
68970-	if c.inference.typeName.isTypeParam {
68971-		// If we are completing a type param, offer each structural type.
68972-		// This ensures we suggest "[]int" and "[]float64" for a constraint
68973-		// with type union "[]int | []float64".
68974-		if t, _ := c.inference.objType.(*types.Interface); t != nil {
68975-			terms, _ := typeparams.InterfaceTermSet(t)
68976-			for _, term := range terms {
68977-				c.injectType(ctx, term.Type())
68978-			}
68979-		}
68980-	} else {
68981-		c.injectType(ctx, c.inference.objType)
68982-	}
68983-
68984-	// Add keyword completion items appropriate in the current context.
68985-	c.addKeywordCompletions()
68986-
68987-	return nil
68988-}
68989-
68990-// injectType manufactures candidates based on the given type. This is
68991-// intended for types not discoverable via lexical search, such as
68992-// composite and/or generic types. For example, if the type is "[]int",
68993-// this method makes sure you get candidates "[]int{}" and "[]int"
68994-// (the latter applies when completing a type name).
68995-func (c *completer) injectType(ctx context.Context, t types.Type) {
68996-	if t == nil {
68997-		return
68998-	}
68999-
69000-	t = source.Deref(t)
69001-
69002-	// If we have an expected type and it is _not_ a named type, handle
69003-	// it specially. Non-named types like "[]int" will never be
69004-	// considered via a lexical search, so we need to directly inject
69005-	// them. Also allow generic types since lexical search does not
69006-	// infer instantiated versions of them.
69007-	if named, _ := t.(*types.Named); named == nil || typeparams.ForNamed(named).Len() > 0 {
69008-		// If our expected type is "[]int", this will add a literal
69009-		// candidate of "[]int{}".
69010-		c.literal(ctx, t, nil)
69011-
69012-		if _, isBasic := t.(*types.Basic); !isBasic {
69013-			// If we expect a non-basic type name (e.g. "[]int"), hack up
69014-			// a named type whose name is literally "[]int". This allows
69015-			// us to reuse our object based completion machinery.
69016-			fakeNamedType := candidate{
69017-				obj:   types.NewTypeName(token.NoPos, nil, types.TypeString(t, c.qf), t),
69018-				score: stdScore,
69019-			}
69020-			// Make sure the type name matches before considering
69021-			// candidate. This cuts down on useless candidates.
69022-			if c.matchingTypeName(&fakeNamedType) {
69023-				c.deepState.enqueue(fakeNamedType)
69024-			}
69025-		}
69026-	}
69027-}
69028-
69029-func (c *completer) unimportedPackages(ctx context.Context, seen map[string]struct{}) error {
69030-	var prefix string
69031-	if c.surrounding != nil {
69032-		prefix = c.surrounding.Prefix()
69033-	}
69034-
69035-	// Don't suggest unimported packages if we have absolutely nothing
69036-	// to go on.
69037-	if prefix == "" {
69038-		return nil
69039-	}
69040-
69041-	count := 0
69042-
69043-	// Search packages across the entire workspace.
69044-	all, err := c.snapshot.AllMetadata(ctx)
69045-	if err != nil {
69046-		return err
69047-	}
69048-	pkgNameByPath := make(map[source.PackagePath]string)
69049-	var paths []string // actually PackagePaths
69050-	for _, m := range all {
69051-		if m.ForTest != "" {
69052-			continue // skip all test variants
69053-		}
69054-		if m.Name == "main" {
69055-			continue // main is non-importable
69056-		}
69057-		if !strings.HasPrefix(string(m.Name), prefix) {
69058-			continue // not a match
69059-		}
69060-		paths = append(paths, string(m.PkgPath))
69061-		pkgNameByPath[m.PkgPath] = string(m.Name)
69062-	}
69063-
69064-	// Rank candidates using goimports' algorithm.
69065-	var relevances map[string]float64
69066-	if len(paths) != 0 {
69067-		if err := c.snapshot.RunProcessEnvFunc(ctx, func(opts *imports.Options) error {
69068-			var err error
69069-			relevances, err = imports.ScoreImportPaths(ctx, opts.Env, paths)
69070-			return err
69071-		}); err != nil {
69072-			return err
69073-		}
69074-	}
69075-	sort.Slice(paths, func(i, j int) bool {
69076-		if relevances[paths[i]] != relevances[paths[j]] {
69077-			return relevances[paths[i]] > relevances[paths[j]]
69078-		}
69079-
69080-		// Fall back to lexical sort to keep truncated set of candidates
69081-		// in a consistent order.
69082-		return paths[i] < paths[j]
69083-	})
69084-
69085-	for _, path := range paths {
69086-		name := pkgNameByPath[source.PackagePath(path)]
69087-		if _, ok := seen[name]; ok {
69088-			continue
69089-		}
69090-		imp := &importInfo{
69091-			importPath: path,
69092-		}
69093-		if imports.ImportPathToAssumedName(path) != name {
69094-			imp.name = name
69095-		}
69096-		if count >= maxUnimportedPackageNames {
69097-			return nil
69098-		}
69099-		c.deepState.enqueue(candidate{
69100-			// Pass an empty *types.Package to disable deep completions.
69101-			obj:   types.NewPkgName(0, nil, name, types.NewPackage(path, name)),
69102-			score: unimportedScore(relevances[path]),
69103-			imp:   imp,
69104-		})
69105-		count++
69106-	}
69107-
69108-	ctx, cancel := context.WithCancel(ctx)
69109-
69110-	var mu sync.Mutex
69111-	add := func(pkg imports.ImportFix) {
69112-		mu.Lock()
69113-		defer mu.Unlock()
69114-		if _, ok := seen[pkg.IdentName]; ok {
69115-			return
69116-		}
69117-		if _, ok := relevances[pkg.StmtInfo.ImportPath]; ok {
69118-			return
69119-		}
69120-
69121-		if count >= maxUnimportedPackageNames {
69122-			cancel()
69123-			return
69124-		}
69125-
69126-		// Do not add the unimported packages to seen, since we can have
69127-		// multiple packages of the same name as completion suggestions, since
69128-		// only one will be chosen.
69129-		obj := types.NewPkgName(0, nil, pkg.IdentName, types.NewPackage(pkg.StmtInfo.ImportPath, pkg.IdentName))
69130-		c.deepState.enqueue(candidate{
69131-			obj:   obj,
69132-			score: unimportedScore(pkg.Relevance),
69133-			imp: &importInfo{
69134-				importPath: pkg.StmtInfo.ImportPath,
69135-				name:       pkg.StmtInfo.Name,
69136-			},
69137-		})
69138-		count++
69139-	}
69140-	c.completionCallbacks = append(c.completionCallbacks, func(opts *imports.Options) error {
69141-		defer cancel()
69142-		return imports.GetAllCandidates(ctx, add, prefix, c.filename, c.pkg.GetTypes().Name(), opts.Env)
69143-	})
69144-	return nil
69145-}
69146-
69147-// alreadyImports reports whether f has an import with the specified path.
69148-func alreadyImports(f *ast.File, path source.ImportPath) bool {
69149-	for _, s := range f.Imports {
69150-		if source.UnquoteImportPath(s) == path {
69151-			return true
69152-		}
69153-	}
69154-	return false
69155-}
69156-
69157-func (c *completer) inConstDecl() bool {
69158-	for _, n := range c.path {
69159-		if decl, ok := n.(*ast.GenDecl); ok && decl.Tok == token.CONST {
69160-			return true
69161-		}
69162-	}
69163-	return false
69164-}
69165-
69166-// structLiteralFieldName finds completions for struct field names inside a struct literal.
69167-func (c *completer) structLiteralFieldName(ctx context.Context) error {
69168-	clInfo := c.enclosingCompositeLiteral
69169-
69170-	// Mark fields of the composite literal that have already been set,
69171-	// except for the current field.
69172-	addedFields := make(map[*types.Var]bool)
69173-	for _, el := range clInfo.cl.Elts {
69174-		if kvExpr, ok := el.(*ast.KeyValueExpr); ok {
69175-			if clInfo.kv == kvExpr {
69176-				continue
69177-			}
69178-
69179-			if key, ok := kvExpr.Key.(*ast.Ident); ok {
69180-				if used, ok := c.pkg.GetTypesInfo().Uses[key]; ok {
69181-					if usedVar, ok := used.(*types.Var); ok {
69182-						addedFields[usedVar] = true
69183-					}
69184-				}
69185-			}
69186-		}
69187-	}
69188-
69189-	deltaScore := 0.0001
69190-	switch t := clInfo.clType.(type) {
69191-	case *types.Struct:
69192-		for i := 0; i < t.NumFields(); i++ {
69193-			field := t.Field(i)
69194-			if !addedFields[field] {
69195-				c.deepState.enqueue(candidate{
69196-					obj:   field,
69197-					score: highScore - float64(i)*deltaScore,
69198-				})
69199-			}
69200-		}
69201-
69202-		// Add lexical completions if we aren't certain we are in the key part of a
69203-		// key-value pair.
69204-		if clInfo.maybeInFieldName {
69205-			return c.lexical(ctx)
69206-		}
69207-	default:
69208-		return c.lexical(ctx)
69209-	}
69210-
69211-	return nil
69212-}
69213-
69214-func (cl *compLitInfo) isStruct() bool {
69215-	_, ok := cl.clType.(*types.Struct)
69216-	return ok
69217-}
69218-
69219-// enclosingCompositeLiteral returns information about the composite literal enclosing the
69220-// position.
69221-func enclosingCompositeLiteral(path []ast.Node, pos token.Pos, info *types.Info) *compLitInfo {
69222-	for _, n := range path {
69223-		switch n := n.(type) {
69224-		case *ast.CompositeLit:
69225-			// The enclosing node will be a composite literal if the user has just
69226-			// opened the curly brace (e.g. &x{<>) or the completion request is triggered
69227-			// from an already completed composite literal expression (e.g. &x{foo: 1, <>})
69228-			//
69229-			// The position is not part of the composite literal unless it falls within the
69230-			// curly braces (e.g. "foo.Foo<>Struct{}").
69231-			if !(n.Lbrace < pos && pos <= n.Rbrace) {
69232-				// Keep searching since we may yet be inside a composite literal.
69233-				// For example "Foo{B: Ba<>{}}".
69234-				break
69235-			}
69236-
69237-			tv, ok := info.Types[n]
69238-			if !ok {
69239-				return nil
69240-			}
69241-
69242-			clInfo := compLitInfo{
69243-				cl:     n,
69244-				clType: source.Deref(tv.Type).Underlying(),
69245-			}
69246-
69247-			var (
69248-				expr    ast.Expr
69249-				hasKeys bool
69250-			)
69251-			for _, el := range n.Elts {
69252-				// Remember the expression that the position falls in, if any.
69253-				if el.Pos() <= pos && pos <= el.End() {
69254-					expr = el
69255-				}
69256-
69257-				if kv, ok := el.(*ast.KeyValueExpr); ok {
69258-					hasKeys = true
69259-					// If expr == el then we know the position falls in this expression,
69260-					// so also record kv as the enclosing *ast.KeyValueExpr.
69261-					if expr == el {
69262-						clInfo.kv = kv
69263-						break
69264-					}
69265-				}
69266-			}
69267-
69268-			if clInfo.kv != nil {
69269-				// If in a *ast.KeyValueExpr, we know we are in the key if the position
69270-				// is to the left of the colon (e.g. "Foo{F<>: V}".
69271-				clInfo.inKey = pos <= clInfo.kv.Colon
69272-			} else if hasKeys {
69273-				// If we aren't in a *ast.KeyValueExpr but the composite literal has
69274-				// other *ast.KeyValueExprs, we must be on the key side of a new
69275-				// *ast.KeyValueExpr (e.g. "Foo{F: V, <>}").
69276-				clInfo.inKey = true
69277-			} else {
69278-				switch clInfo.clType.(type) {
69279-				case *types.Struct:
69280-					if len(n.Elts) == 0 {
69281-						// If the struct literal is empty, next could be a struct field
69282-						// name or an expression (e.g. "Foo{<>}" could become "Foo{F:}"
69283-						// or "Foo{someVar}").
69284-						clInfo.maybeInFieldName = true
69285-					} else if len(n.Elts) == 1 {
69286-						// If there is one expression and the position is in that expression
69287-						// and the expression is an identifier, we may be writing a field
69288-						// name or an expression (e.g. "Foo{F<>}").
69289-						_, clInfo.maybeInFieldName = expr.(*ast.Ident)
69290-					}
69291-				case *types.Map:
69292-					// If we aren't in a *ast.KeyValueExpr we must be adding a new key
69293-					// to the map.
69294-					clInfo.inKey = true
69295-				}
69296-			}
69297-
69298-			return &clInfo
69299-		default:
69300-			if breaksExpectedTypeInference(n, pos) {
69301-				return nil
69302-			}
69303-		}
69304-	}
69305-
69306-	return nil
69307-}
69308-
69309-// enclosingFunction returns the signature and body of the function
69310-// enclosing the given position.
69311-func enclosingFunction(path []ast.Node, info *types.Info) *funcInfo {
69312-	for _, node := range path {
69313-		switch t := node.(type) {
69314-		case *ast.FuncDecl:
69315-			if obj, ok := info.Defs[t.Name]; ok {
69316-				return &funcInfo{
69317-					sig:  obj.Type().(*types.Signature),
69318-					body: t.Body,
69319-				}
69320-			}
69321-		case *ast.FuncLit:
69322-			if typ, ok := info.Types[t]; ok {
69323-				if sig, _ := typ.Type.(*types.Signature); sig == nil {
69324-					// golang/go#49397: it should not be possible, but we somehow arrived
69325-					// here with a non-signature type, most likely due to AST mangling
69326-					// such that node.Type is not a FuncType.
69327-					return nil
69328-				}
69329-				return &funcInfo{
69330-					sig:  typ.Type.(*types.Signature),
69331-					body: t.Body,
69332-				}
69333-			}
69334-		}
69335-	}
69336-	return nil
69337-}
69338-
69339-func (c *completer) expectedCompositeLiteralType() types.Type {
69340-	clInfo := c.enclosingCompositeLiteral
69341-	switch t := clInfo.clType.(type) {
69342-	case *types.Slice:
69343-		if clInfo.inKey {
69344-			return types.Typ[types.UntypedInt]
69345-		}
69346-		return t.Elem()
69347-	case *types.Array:
69348-		if clInfo.inKey {
69349-			return types.Typ[types.UntypedInt]
69350-		}
69351-		return t.Elem()
69352-	case *types.Map:
69353-		if clInfo.inKey {
69354-			return t.Key()
69355-		}
69356-		return t.Elem()
69357-	case *types.Struct:
69358-		// If we are completing a key (i.e. field name), there is no expected type.
69359-		if clInfo.inKey {
69360-			return nil
69361-		}
69362-
69363-		// If we are in a key-value pair, but not in the key, then we must be on the
69364-		// value side. The expected type of the value will be determined from the key.
69365-		if clInfo.kv != nil {
69366-			if key, ok := clInfo.kv.Key.(*ast.Ident); ok {
69367-				for i := 0; i < t.NumFields(); i++ {
69368-					if field := t.Field(i); field.Name() == key.Name {
69369-						return field.Type()
69370-					}
69371-				}
69372-			}
69373-		} else {
69374-			// If we aren't in a key-value pair and aren't in the key, we must be using
69375-			// implicit field names.
69376-
69377-			// The order of the literal fields must match the order in the struct definition.
69378-			// Find the element that the position belongs to and suggest that field's type.
69379-			if i := exprAtPos(c.pos, clInfo.cl.Elts); i < t.NumFields() {
69380-				return t.Field(i).Type()
69381-			}
69382-		}
69383-	}
69384-	return nil
69385-}
69386-
69387-// typeMod represents an operator that changes the expected type.
69388-type typeMod struct {
69389-	mod      typeModKind
69390-	arrayLen int64
69391-}
69392-
69393-type typeModKind int
69394-
69395-const (
69396-	dereference   typeModKind = iota // pointer indirection: "*"
69397-	reference                        // adds level of pointer: "&" for values, "*" for type names
69398-	chanRead                         // channel read operator: "<-"
69399-	sliceType                        // make a slice type: "[]" in "[]int"
69400-	arrayType                        // make an array type: "[2]" in "[2]int"
69401-	invoke                           // make a function call: "()" in "foo()"
69402-	takeSlice                        // take slice of array: "[:]" in "foo[:]"
69403-	takeDotDotDot                    // turn slice into variadic args: "..." in "foo..."
69404-	index                            // index into slice/array: "[0]" in "foo[0]"
69405-)
69406-
69407-type objKind int
69408-
69409-const (
69410-	kindAny   objKind = 0
69411-	kindArray objKind = 1 << iota
69412-	kindSlice
69413-	kindChan
69414-	kindMap
69415-	kindStruct
69416-	kindString
69417-	kindInt
69418-	kindBool
69419-	kindBytes
69420-	kindPtr
69421-	kindFloat
69422-	kindComplex
69423-	kindError
69424-	kindStringer
69425-	kindFunc
69426-)
69427-
69428-// penalizedObj represents an object that should be disfavored as a
69429-// completion candidate.
69430-type penalizedObj struct {
69431-	// objChain is the full "chain", e.g. "foo.bar().baz" becomes
69432-	// []types.Object{foo, bar, baz}.
69433-	objChain []types.Object
69434-	// penalty is score penalty in the range (0, 1).
69435-	penalty float64
69436-}
69437-
69438-// candidateInference holds information we have inferred about a type that can be
69439-// used at the current position.
69440-type candidateInference struct {
69441-	// objType is the desired type of an object used at the query position.
69442-	objType types.Type
69443-
69444-	// objKind is a mask of expected kinds of types such as "map", "slice", etc.
69445-	objKind objKind
69446-
69447-	// variadic is true if we are completing the initial variadic
69448-	// parameter. For example:
69449-	//   append([]T{}, <>)      // objType=T variadic=true
69450-	//   append([]T{}, T{}, <>) // objType=T variadic=false
69451-	variadic bool
69452-
69453-	// modifiers are prefixes such as "*", "&" or "<-" that influence how
69454-	// a candidate type relates to the expected type.
69455-	modifiers []typeMod
69456-
69457-	// convertibleTo is a type our candidate type must be convertible to.
69458-	convertibleTo types.Type
69459-
69460-	// typeName holds information about the expected type name at
69461-	// position, if any.
69462-	typeName typeNameInference
69463-
69464-	// assignees are the types that would receive a function call's
69465-	// results at the position. For example:
69466-	//
69467-	// foo := 123
69468-	// foo, bar := <>
69469-	//
69470-	// at "<>", the assignees are [int, <invalid>].
69471-	assignees []types.Type
69472-
69473-	// variadicAssignees is true if we could be completing an inner
69474-	// function call that fills out an outer function call's variadic
69475-	// params. For example:
69476-	//
69477-	// func foo(int, ...string) {}
69478-	//
69479-	// foo(<>)         // variadicAssignees=true
69480-	// foo(bar<>)      // variadicAssignees=true
69481-	// foo(bar, baz<>) // variadicAssignees=false
69482-	variadicAssignees bool
69483-
69484-	// penalized holds expressions that should be disfavored as
69485-	// candidates. For example, it tracks expressions already used in a
69486-	// switch statement's other cases. Each expression is tracked using
69487-	// its entire object "chain" allowing differentiation between
69488-	// "a.foo" and "b.foo" when "a" and "b" are the same type.
69489-	penalized []penalizedObj
69490-
69491-	// objChain contains the chain of objects representing the
69492-	// surrounding *ast.SelectorExpr. For example, if we are completing
69493-	// "foo.bar.ba<>", objChain will contain []types.Object{foo, bar}.
69494-	objChain []types.Object
69495-}
69496-
69497-// typeNameInference holds information about the expected type name at
69498-// position.
69499-type typeNameInference struct {
69500-	// wantTypeName is true if we expect the name of a type.
69501-	wantTypeName bool
69502-
69503-	// modifiers are prefixes such as "*", "&" or "<-" that influence how
69504-	// a candidate type relates to the expected type.
69505-	modifiers []typeMod
69506-
69507-	// assertableFrom is a type that must be assertable to our candidate type.
69508-	assertableFrom types.Type
69509-
69510-	// wantComparable is true if we want a comparable type.
69511-	wantComparable bool
69512-
69513-	// seenTypeSwitchCases tracks types that have already been used by
69514-	// the containing type switch.
69515-	seenTypeSwitchCases []types.Type
69516-
69517-	// compLitType is true if we are completing a composite literal type
69518-	// name, e.g "foo<>{}".
69519-	compLitType bool
69520-
69521-	// isTypeParam is true if we are completing a type instantiation parameter
69522-	isTypeParam bool
69523-}
69524-
69525-// expectedCandidate returns information about the expected candidate
69526-// for an expression at the query position.
69527-func expectedCandidate(ctx context.Context, c *completer) (inf candidateInference) {
69528-	inf.typeName = expectTypeName(c)
69529-
69530-	if c.enclosingCompositeLiteral != nil {
69531-		inf.objType = c.expectedCompositeLiteralType()
69532-	}
69533-
69534-Nodes:
69535-	for i, node := range c.path {
69536-		switch node := node.(type) {
69537-		case *ast.BinaryExpr:
69538-			// Determine if query position comes from left or right of op.
69539-			e := node.X
69540-			if c.pos < node.OpPos {
69541-				e = node.Y
69542-			}
69543-			if tv, ok := c.pkg.GetTypesInfo().Types[e]; ok {
69544-				switch node.Op {
69545-				case token.LAND, token.LOR:
69546-					// Don't infer "bool" type for "&&" or "||". Often you want
69547-					// to compose a boolean expression from non-boolean
69548-					// candidates.
69549-				default:
69550-					inf.objType = tv.Type
69551-				}
69552-				break Nodes
69553-			}
69554-		case *ast.AssignStmt:
69555-			// Only rank completions if you are on the right side of the token.
69556-			if c.pos > node.TokPos {
69557-				i := exprAtPos(c.pos, node.Rhs)
69558-				if i >= len(node.Lhs) {
69559-					i = len(node.Lhs) - 1
69560-				}
69561-				if tv, ok := c.pkg.GetTypesInfo().Types[node.Lhs[i]]; ok {
69562-					inf.objType = tv.Type
69563-				}
69564-
69565-				// If we have a single expression on the RHS, record the LHS
69566-				// assignees so we can favor multi-return function calls with
69567-				// matching result values.
69568-				if len(node.Rhs) <= 1 {
69569-					for _, lhs := range node.Lhs {
69570-						inf.assignees = append(inf.assignees, c.pkg.GetTypesInfo().TypeOf(lhs))
69571-					}
69572-				} else {
69573-					// Otherwise, record our single assignee, even if its type is
69574-					// not available. We use this info to downrank functions
69575-					// with the wrong number of result values.
69576-					inf.assignees = append(inf.assignees, c.pkg.GetTypesInfo().TypeOf(node.Lhs[i]))
69577-				}
69578-			}
69579-			return inf
69580-		case *ast.ValueSpec:
69581-			if node.Type != nil && c.pos > node.Type.End() {
69582-				inf.objType = c.pkg.GetTypesInfo().TypeOf(node.Type)
69583-			}
69584-			return inf
69585-		case *ast.CallExpr:
69586-			// Only consider CallExpr args if position falls between parens.
69587-			if node.Lparen < c.pos && c.pos <= node.Rparen {
69588-				// For type conversions like "int64(foo)" we can only infer our
69589-				// desired type is convertible to int64.
69590-				if typ := typeConversion(node, c.pkg.GetTypesInfo()); typ != nil {
69591-					inf.convertibleTo = typ
69592-					break Nodes
69593-				}
69594-
69595-				sig, _ := c.pkg.GetTypesInfo().Types[node.Fun].Type.(*types.Signature)
69596-
69597-				if sig != nil && typeparams.ForSignature(sig).Len() > 0 {
69598-					// If we are completing a generic func call, re-check the call expression.
69599-					// This allows type param inference to work in cases like:
69600-					//
69601-					// func foo[T any](T) {}
69602-					// foo[int](<>) // <- get "int" completions instead of "T"
69603-					//
69604-					// TODO: remove this after https://go.dev/issue/52503
69605-					info := &types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
69606-					types.CheckExpr(c.pkg.FileSet(), c.pkg.GetTypes(), node.Fun.Pos(), node.Fun, info)
69607-					sig, _ = info.Types[node.Fun].Type.(*types.Signature)
69608-				}
69609-
69610-				if sig != nil {
69611-					inf = c.expectedCallParamType(inf, node, sig)
69612-				}
69613-
69614-				if funIdent, ok := node.Fun.(*ast.Ident); ok {
69615-					obj := c.pkg.GetTypesInfo().ObjectOf(funIdent)
69616-
69617-					if obj != nil && obj.Parent() == types.Universe {
69618-						// Defer call to builtinArgType so we can provide it the
69619-						// inferred type from its parent node.
69620-						defer func() {
69621-							inf = c.builtinArgType(obj, node, inf)
69622-							inf.objKind = c.builtinArgKind(ctx, obj, node)
69623-						}()
69624-
69625-						// The expected type of builtin arguments like append() is
69626-						// the expected type of the builtin call itself. For
69627-						// example:
69628-						//
69629-						// var foo []int = append(<>)
69630-						//
69631-						// To find the expected type at <> we "skip" the append()
69632-						// node and get the expected type one level up, which is
69633-						// []int.
69634-						continue Nodes
69635-					}
69636-				}
69637-
69638-				return inf
69639-			}
69640-		case *ast.ReturnStmt:
69641-			if c.enclosingFunc != nil {
69642-				sig := c.enclosingFunc.sig
69643-				// Find signature result that corresponds to our return statement.
69644-				if resultIdx := exprAtPos(c.pos, node.Results); resultIdx < len(node.Results) {
69645-					if resultIdx < sig.Results().Len() {
69646-						inf.objType = sig.Results().At(resultIdx).Type()
69647-					}
69648-				}
69649-			}
69650-			return inf
69651-		case *ast.CaseClause:
69652-			if swtch, ok := findSwitchStmt(c.path[i+1:], c.pos, node).(*ast.SwitchStmt); ok {
69653-				if tv, ok := c.pkg.GetTypesInfo().Types[swtch.Tag]; ok {
69654-					inf.objType = tv.Type
69655-
69656-					// Record which objects have already been used in the case
69657-					// statements so we don't suggest them again.
69658-					for _, cc := range swtch.Body.List {
69659-						for _, caseExpr := range cc.(*ast.CaseClause).List {
69660-							// Don't record the expression we are currently completing.
69661-							if caseExpr.Pos() < c.pos && c.pos <= caseExpr.End() {
69662-								continue
69663-							}
69664-
69665-							if objs := objChain(c.pkg.GetTypesInfo(), caseExpr); len(objs) > 0 {
69666-								inf.penalized = append(inf.penalized, penalizedObj{objChain: objs, penalty: 0.1})
69667-							}
69668-						}
69669-					}
69670-				}
69671-			}
69672-			return inf
69673-		case *ast.SliceExpr:
69674-			// Make sure position falls within the brackets (e.g. "foo[a:<>]").
69675-			if node.Lbrack < c.pos && c.pos <= node.Rbrack {
69676-				inf.objType = types.Typ[types.UntypedInt]
69677-			}
69678-			return inf
69679-		case *ast.IndexExpr:
69680-			// Make sure position falls within the brackets (e.g. "foo[<>]").
69681-			if node.Lbrack < c.pos && c.pos <= node.Rbrack {
69682-				if tv, ok := c.pkg.GetTypesInfo().Types[node.X]; ok {
69683-					switch t := tv.Type.Underlying().(type) {
69684-					case *types.Map:
69685-						inf.objType = t.Key()
69686-					case *types.Slice, *types.Array:
69687-						inf.objType = types.Typ[types.UntypedInt]
69688-					}
69689-
69690-					if ct := expectedConstraint(tv.Type, 0); ct != nil {
69691-						inf.objType = ct
69692-						inf.typeName.wantTypeName = true
69693-						inf.typeName.isTypeParam = true
69694-					}
69695-				}
69696-			}
69697-			return inf
69698-		case *typeparams.IndexListExpr:
69699-			if node.Lbrack < c.pos && c.pos <= node.Rbrack {
69700-				if tv, ok := c.pkg.GetTypesInfo().Types[node.X]; ok {
69701-					if ct := expectedConstraint(tv.Type, exprAtPos(c.pos, node.Indices)); ct != nil {
69702-						inf.objType = ct
69703-						inf.typeName.wantTypeName = true
69704-						inf.typeName.isTypeParam = true
69705-					}
69706-				}
69707-			}
69708-			return inf
69709-		case *ast.SendStmt:
69710-			// Make sure we are on right side of arrow (e.g. "foo <- <>").
69711-			if c.pos > node.Arrow+1 {
69712-				if tv, ok := c.pkg.GetTypesInfo().Types[node.Chan]; ok {
69713-					if ch, ok := tv.Type.Underlying().(*types.Chan); ok {
69714-						inf.objType = ch.Elem()
69715-					}
69716-				}
69717-			}
69718-			return inf
69719-		case *ast.RangeStmt:
69720-			if source.NodeContains(node.X, c.pos) {
69721-				inf.objKind |= kindSlice | kindArray | kindMap | kindString
69722-				if node.Value == nil {
69723-					inf.objKind |= kindChan
69724-				}
69725-			}
69726-			return inf
69727-		case *ast.StarExpr:
69728-			inf.modifiers = append(inf.modifiers, typeMod{mod: dereference})
69729-		case *ast.UnaryExpr:
69730-			switch node.Op {
69731-			case token.AND:
69732-				inf.modifiers = append(inf.modifiers, typeMod{mod: reference})
69733-			case token.ARROW:
69734-				inf.modifiers = append(inf.modifiers, typeMod{mod: chanRead})
69735-			}
69736-		case *ast.DeferStmt, *ast.GoStmt:
69737-			inf.objKind |= kindFunc
69738-			return inf
69739-		default:
69740-			if breaksExpectedTypeInference(node, c.pos) {
69741-				return inf
69742-			}
69743-		}
69744-	}
69745-
69746-	return inf
69747-}
69748-
69749-func (c *completer) expectedCallParamType(inf candidateInference, node *ast.CallExpr, sig *types.Signature) candidateInference {
69750-	numParams := sig.Params().Len()
69751-	if numParams == 0 {
69752-		return inf
69753-	}
69754-
69755-	exprIdx := exprAtPos(c.pos, node.Args)
69756-
69757-	// If we have one or zero arg expressions, we may be
69758-	// completing to a function call that returns multiple
69759-	// values, in turn getting passed in to the surrounding
69760-	// call. Record the assignees so we can favor function
69761-	// calls that return matching values.
69762-	if len(node.Args) <= 1 && exprIdx == 0 {
69763-		for i := 0; i < sig.Params().Len(); i++ {
69764-			inf.assignees = append(inf.assignees, sig.Params().At(i).Type())
69765-		}
69766-
69767-		// Record that we may be completing into variadic parameters.
69768-		inf.variadicAssignees = sig.Variadic()
69769-	}
69770-
69771-	// Make sure not to run past the end of expected parameters.
69772-	if exprIdx >= numParams {
69773-		inf.objType = sig.Params().At(numParams - 1).Type()
69774-	} else {
69775-		inf.objType = sig.Params().At(exprIdx).Type()
69776-	}
69777-
69778-	if sig.Variadic() && exprIdx >= (numParams-1) {
69779-		// If we are completing a variadic param, deslice the variadic type.
69780-		inf.objType = deslice(inf.objType)
69781-		// Record whether we are completing the initial variadic param.
69782-		inf.variadic = exprIdx == numParams-1 && len(node.Args) <= numParams
69783-
69784-		// Check if we can infer object kind from printf verb.
69785-		inf.objKind |= printfArgKind(c.pkg.GetTypesInfo(), node, exprIdx)
69786-	}
69787-
69788-	// If our expected type is an uninstantiated generic type param,
69789-	// swap to the constraint which will do a decent job filtering
69790-	// candidates.
69791-	if tp, _ := inf.objType.(*typeparams.TypeParam); tp != nil {
69792-		inf.objType = tp.Constraint()
69793-	}
69794-
69795-	return inf
69796-}
69797-
69798-func expectedConstraint(t types.Type, idx int) types.Type {
69799-	var tp *typeparams.TypeParamList
69800-	if named, _ := t.(*types.Named); named != nil {
69801-		tp = typeparams.ForNamed(named)
69802-	} else if sig, _ := t.Underlying().(*types.Signature); sig != nil {
69803-		tp = typeparams.ForSignature(sig)
69804-	}
69805-	if tp == nil || idx >= tp.Len() {
69806-		return nil
69807-	}
69808-	return tp.At(idx).Constraint()
69809-}
69810-
69811-// objChain decomposes e into a chain of objects if possible. For
69812-// example, "foo.bar().baz" will yield []types.Object{foo, bar, baz}.
69813-// If any part can't be turned into an object, return nil.
69814-func objChain(info *types.Info, e ast.Expr) []types.Object {
69815-	var objs []types.Object
69816-
69817-	for e != nil {
69818-		switch n := e.(type) {
69819-		case *ast.Ident:
69820-			obj := info.ObjectOf(n)
69821-			if obj == nil {
69822-				return nil
69823-			}
69824-			objs = append(objs, obj)
69825-			e = nil
69826-		case *ast.SelectorExpr:
69827-			obj := info.ObjectOf(n.Sel)
69828-			if obj == nil {
69829-				return nil
69830-			}
69831-			objs = append(objs, obj)
69832-			e = n.X
69833-		case *ast.CallExpr:
69834-			if len(n.Args) > 0 {
69835-				return nil
69836-			}
69837-			e = n.Fun
69838-		default:
69839-			return nil
69840-		}
69841-	}
69842-
69843-	// Reverse order so the layout matches the syntactic order.
69844-	for i := 0; i < len(objs)/2; i++ {
69845-		objs[i], objs[len(objs)-1-i] = objs[len(objs)-1-i], objs[i]
69846-	}
69847-
69848-	return objs
69849-}
69850-
69851-// applyTypeModifiers applies the list of type modifiers to a type.
69852-// It returns nil if the modifiers could not be applied.
69853-func (ci candidateInference) applyTypeModifiers(typ types.Type, addressable bool) types.Type {
69854-	for _, mod := range ci.modifiers {
69855-		switch mod.mod {
69856-		case dereference:
69857-			// For every "*" indirection operator, remove a pointer layer
69858-			// from candidate type.
69859-			if ptr, ok := typ.Underlying().(*types.Pointer); ok {
69860-				typ = ptr.Elem()
69861-			} else {
69862-				return nil
69863-			}
69864-		case reference:
69865-			// For every "&" address operator, add another pointer layer to
69866-			// candidate type, if the candidate is addressable.
69867-			if addressable {
69868-				typ = types.NewPointer(typ)
69869-			} else {
69870-				return nil
69871-			}
69872-		case chanRead:
69873-			// For every "<-" operator, remove a layer of channelness.
69874-			if ch, ok := typ.(*types.Chan); ok {
69875-				typ = ch.Elem()
69876-			} else {
69877-				return nil
69878-			}
69879-		}
69880-	}
69881-
69882-	return typ
69883-}
69884-
69885-// applyTypeNameModifiers applies the list of type modifiers to a type name.
69886-func (ci candidateInference) applyTypeNameModifiers(typ types.Type) types.Type {
69887-	for _, mod := range ci.typeName.modifiers {
69888-		switch mod.mod {
69889-		case reference:
69890-			typ = types.NewPointer(typ)
69891-		case arrayType:
69892-			typ = types.NewArray(typ, mod.arrayLen)
69893-		case sliceType:
69894-			typ = types.NewSlice(typ)
69895-		}
69896-	}
69897-	return typ
69898-}
69899-
69900-// matchesVariadic returns true if we are completing a variadic
69901-// parameter and candType is a compatible slice type.
69902-func (ci candidateInference) matchesVariadic(candType types.Type) bool {
69903-	return ci.variadic && ci.objType != nil && assignableTo(candType, types.NewSlice(ci.objType))
69904-}
69905-
69906-// findSwitchStmt returns an *ast.CaseClause's corresponding *ast.SwitchStmt or
69907-// *ast.TypeSwitchStmt. path should start from the case clause's first ancestor.
69908-func findSwitchStmt(path []ast.Node, pos token.Pos, c *ast.CaseClause) ast.Stmt {
69909-	// Make sure position falls within a "case <>:" clause.
69910-	if exprAtPos(pos, c.List) >= len(c.List) {
69911-		return nil
69912-	}
69913-	// A case clause is always nested within a block statement in a switch statement.
69914-	if len(path) < 2 {
69915-		return nil
69916-	}
69917-	if _, ok := path[0].(*ast.BlockStmt); !ok {
69918-		return nil
69919-	}
69920-	switch s := path[1].(type) {
69921-	case *ast.SwitchStmt:
69922-		return s
69923-	case *ast.TypeSwitchStmt:
69924-		return s
69925-	default:
69926-		return nil
69927-	}
69928-}
69929-
69930-// breaksExpectedTypeInference reports if an expression node's type is unrelated
69931-// to its child expression node types. For example, "Foo{Bar: x.Baz(<>)}" should
69932-// expect a function argument, not a composite literal value.
69933-func breaksExpectedTypeInference(n ast.Node, pos token.Pos) bool {
69934-	switch n := n.(type) {
69935-	case *ast.CompositeLit:
69936-		// Doesn't break inference if pos is in type name.
69937-		// For example: "Foo<>{Bar: 123}"
69938-		return !source.NodeContains(n.Type, pos)
69939-	case *ast.CallExpr:
69940-		// Doesn't break inference if pos is in func name.
69941-		// For example: "Foo<>(123)"
69942-		return !source.NodeContains(n.Fun, pos)
69943-	case *ast.FuncLit, *ast.IndexExpr, *ast.SliceExpr:
69944-		return true
69945-	default:
69946-		return false
69947-	}
69948-}
69949-
69950-// expectTypeName returns information about the expected type name at position.
69951-func expectTypeName(c *completer) typeNameInference {
69952-	var inf typeNameInference
69953-
69954-Nodes:
69955-	for i, p := range c.path {
69956-		switch n := p.(type) {
69957-		case *ast.FieldList:
69958-			// Expect a type name if pos is in a FieldList. This applies to
69959-			// FuncType params/results, FuncDecl receiver, StructType, and
69960-			// InterfaceType. We don't need to worry about the field name
69961-			// because completion bails out early if pos is in an *ast.Ident
69962-			// that defines an object.
69963-			inf.wantTypeName = true
69964-			break Nodes
69965-		case *ast.CaseClause:
69966-			// Expect type names in type switch case clauses.
69967-			if swtch, ok := findSwitchStmt(c.path[i+1:], c.pos, n).(*ast.TypeSwitchStmt); ok {
69968-				// The case clause types must be assertable from the type switch parameter.
69969-				ast.Inspect(swtch.Assign, func(n ast.Node) bool {
69970-					if ta, ok := n.(*ast.TypeAssertExpr); ok {
69971-						inf.assertableFrom = c.pkg.GetTypesInfo().TypeOf(ta.X)
69972-						return false
69973-					}
69974-					return true
69975-				})
69976-				inf.wantTypeName = true
69977-
69978-				// Track the types that have already been used in this
69979-				// switch's case statements so we don't recommend them.
69980-				for _, e := range swtch.Body.List {
69981-					for _, typeExpr := range e.(*ast.CaseClause).List {
69982-						// Skip if type expression contains pos. We don't want to
69983-						// count it as already used if the user is completing it.
69984-						if typeExpr.Pos() < c.pos && c.pos <= typeExpr.End() {
69985-							continue
69986-						}
69987-
69988-						if t := c.pkg.GetTypesInfo().TypeOf(typeExpr); t != nil {
69989-							inf.seenTypeSwitchCases = append(inf.seenTypeSwitchCases, t)
69990-						}
69991-					}
69992-				}
69993-
69994-				break Nodes
69995-			}
69996-			return typeNameInference{}
69997-		case *ast.TypeAssertExpr:
69998-			// Expect type names in type assert expressions.
69999-			if n.Lparen < c.pos && c.pos <= n.Rparen {
70000-				// The type in parens must be assertable from the expression type.
70001-				inf.assertableFrom = c.pkg.GetTypesInfo().TypeOf(n.X)
70002-				inf.wantTypeName = true
70003-				break Nodes
70004-			}
70005-			return typeNameInference{}
70006-		case *ast.StarExpr:
70007-			inf.modifiers = append(inf.modifiers, typeMod{mod: reference})
70008-		case *ast.CompositeLit:
70009-			// We want a type name if position is in the "Type" part of a
70010-			// composite literal (e.g. "Foo<>{}").
70011-			if n.Type != nil && n.Type.Pos() <= c.pos && c.pos <= n.Type.End() {
70012-				inf.wantTypeName = true
70013-				inf.compLitType = true
70014-
70015-				if i < len(c.path)-1 {
70016-					// Track preceding "&" operator. Technically it applies to
70017-					// the composite literal and not the type name, but if
70018-					// affects our type completion nonetheless.
70019-					if u, ok := c.path[i+1].(*ast.UnaryExpr); ok && u.Op == token.AND {
70020-						inf.modifiers = append(inf.modifiers, typeMod{mod: reference})
70021-					}
70022-				}
70023-			}
70024-			break Nodes
70025-		case *ast.ArrayType:
70026-			// If we are inside the "Elt" part of an array type, we want a type name.
70027-			if n.Elt.Pos() <= c.pos && c.pos <= n.Elt.End() {
70028-				inf.wantTypeName = true
70029-				if n.Len == nil {
70030-					// No "Len" expression means a slice type.
70031-					inf.modifiers = append(inf.modifiers, typeMod{mod: sliceType})
70032-				} else {
70033-					// Try to get the array type using the constant value of "Len".
70034-					tv, ok := c.pkg.GetTypesInfo().Types[n.Len]
70035-					if ok && tv.Value != nil && tv.Value.Kind() == constant.Int {
70036-						if arrayLen, ok := constant.Int64Val(tv.Value); ok {
70037-							inf.modifiers = append(inf.modifiers, typeMod{mod: arrayType, arrayLen: arrayLen})
70038-						}
70039-					}
70040-				}
70041-
70042-				// ArrayTypes can be nested, so keep going if our parent is an
70043-				// ArrayType.
70044-				if i < len(c.path)-1 {
70045-					if _, ok := c.path[i+1].(*ast.ArrayType); ok {
70046-						continue Nodes
70047-					}
70048-				}
70049-
70050-				break Nodes
70051-			}
70052-		case *ast.MapType:
70053-			inf.wantTypeName = true
70054-			if n.Key != nil {
70055-				inf.wantComparable = source.NodeContains(n.Key, c.pos)
70056-			} else {
70057-				// If the key is empty, assume we are completing the key if
70058-				// pos is directly after the "map[".
70059-				inf.wantComparable = c.pos == n.Pos()+token.Pos(len("map["))
70060-			}
70061-			break Nodes
70062-		case *ast.ValueSpec:
70063-			inf.wantTypeName = source.NodeContains(n.Type, c.pos)
70064-			break Nodes
70065-		case *ast.TypeSpec:
70066-			inf.wantTypeName = source.NodeContains(n.Type, c.pos)
70067-		default:
70068-			if breaksExpectedTypeInference(p, c.pos) {
70069-				return typeNameInference{}
70070-			}
70071-		}
70072-	}
70073-
70074-	return inf
70075-}
70076-
70077-func (c *completer) fakeObj(T types.Type) *types.Var {
70078-	return types.NewVar(token.NoPos, c.pkg.GetTypes(), "", T)
70079-}
70080-
70081-// derivableTypes iterates types you can derive from t. For example,
70082-// from "foo" we might derive "&foo", and "foo()".
70083-func derivableTypes(t types.Type, addressable bool, f func(t types.Type, addressable bool, mod typeModKind) bool) bool {
70084-	switch t := t.Underlying().(type) {
70085-	case *types.Signature:
70086-		// If t is a func type with a single result, offer the result type.
70087-		if t.Results().Len() == 1 && f(t.Results().At(0).Type(), false, invoke) {
70088-			return true
70089-		}
70090-	case *types.Array:
70091-		if f(t.Elem(), true, index) {
70092-			return true
70093-		}
70094-		// Try converting array to slice.
70095-		if f(types.NewSlice(t.Elem()), false, takeSlice) {
70096-			return true
70097-		}
70098-	case *types.Pointer:
70099-		if f(t.Elem(), false, dereference) {
70100-			return true
70101-		}
70102-	case *types.Slice:
70103-		if f(t.Elem(), true, index) {
70104-			return true
70105-		}
70106-	case *types.Map:
70107-		if f(t.Elem(), false, index) {
70108-			return true
70109-		}
70110-	case *types.Chan:
70111-		if f(t.Elem(), false, chanRead) {
70112-			return true
70113-		}
70114-	}
70115-
70116-	// Check if c is addressable and a pointer to c matches our type inference.
70117-	if addressable && f(types.NewPointer(t), false, reference) {
70118-		return true
70119-	}
70120-
70121-	return false
70122-}
70123-
70124-// anyCandType reports whether f returns true for any candidate type
70125-// derivable from c. It searches up to three levels of type
70126-// modification. For example, given "foo" we could discover "***foo"
70127-// or "*foo()".
70128-func (c *candidate) anyCandType(f func(t types.Type, addressable bool) bool) bool {
70129-	if c.obj == nil || c.obj.Type() == nil {
70130-		return false
70131-	}
70132-
70133-	const maxDepth = 3
70134-
70135-	var searchTypes func(t types.Type, addressable bool, mods []typeModKind) bool
70136-	searchTypes = func(t types.Type, addressable bool, mods []typeModKind) bool {
70137-		if f(t, addressable) {
70138-			if len(mods) > 0 {
70139-				newMods := make([]typeModKind, len(mods)+len(c.mods))
70140-				copy(newMods, mods)
70141-				copy(newMods[len(mods):], c.mods)
70142-				c.mods = newMods
70143-			}
70144-			return true
70145-		}
70146-
70147-		if len(mods) == maxDepth {
70148-			return false
70149-		}
70150-
70151-		return derivableTypes(t, addressable, func(t types.Type, addressable bool, mod typeModKind) bool {
70152-			return searchTypes(t, addressable, append(mods, mod))
70153-		})
70154-	}
70155-
70156-	return searchTypes(c.obj.Type(), c.addressable, make([]typeModKind, 0, maxDepth))
70157-}
70158-
70159-// matchingCandidate reports whether cand matches our type inferences.
70160-// It mutates cand's score in certain cases.
70161-func (c *completer) matchingCandidate(cand *candidate) bool {
70162-	if c.completionContext.commentCompletion {
70163-		return false
70164-	}
70165-
70166-	// Bail out early if we are completing a field name in a composite literal.
70167-	if v, ok := cand.obj.(*types.Var); ok && v.IsField() && c.wantStructFieldCompletions() {
70168-		return true
70169-	}
70170-
70171-	if isTypeName(cand.obj) {
70172-		return c.matchingTypeName(cand)
70173-	} else if c.wantTypeName() {
70174-		// If we want a type, a non-type object never matches.
70175-		return false
70176-	}
70177-
70178-	if c.inference.candTypeMatches(cand) {
70179-		return true
70180-	}
70181-
70182-	candType := cand.obj.Type()
70183-	if candType == nil {
70184-		return false
70185-	}
70186-
70187-	if sig, ok := candType.Underlying().(*types.Signature); ok {
70188-		if c.inference.assigneesMatch(cand, sig) {
70189-			// Invoke the candidate if its results are multi-assignable.
70190-			cand.mods = append(cand.mods, invoke)
70191-			return true
70192-		}
70193-	}
70194-
70195-	// Default to invoking *types.Func candidates. This is so function
70196-	// completions in an empty statement (or other cases with no expected type)
70197-	// are invoked by default.
70198-	if isFunc(cand.obj) {
70199-		cand.mods = append(cand.mods, invoke)
70200-	}
70201-
70202-	return false
70203-}
70204-
70205-// candTypeMatches reports whether cand makes a good completion
70206-// candidate given the candidate inference. cand's score may be
70207-// mutated to downrank the candidate in certain situations.
70208-func (ci *candidateInference) candTypeMatches(cand *candidate) bool {
70209-	var (
70210-		expTypes     = make([]types.Type, 0, 2)
70211-		variadicType types.Type
70212-	)
70213-	if ci.objType != nil {
70214-		expTypes = append(expTypes, ci.objType)
70215-
70216-		if ci.variadic {
70217-			variadicType = types.NewSlice(ci.objType)
70218-			expTypes = append(expTypes, variadicType)
70219-		}
70220-	}
70221-
70222-	return cand.anyCandType(func(candType types.Type, addressable bool) bool {
70223-		// Take into account any type modifiers on the expected type.
70224-		candType = ci.applyTypeModifiers(candType, addressable)
70225-		if candType == nil {
70226-			return false
70227-		}
70228-
70229-		if ci.convertibleTo != nil && convertibleTo(candType, ci.convertibleTo) {
70230-			return true
70231-		}
70232-
70233-		for _, expType := range expTypes {
70234-			if isEmptyInterface(expType) {
70235-				continue
70236-			}
70237-
70238-			matches := ci.typeMatches(expType, candType)
70239-			if !matches {
70240-				// If candType doesn't otherwise match, consider if we can
70241-				// convert candType directly to expType.
70242-				if considerTypeConversion(candType, expType, cand.path) {
70243-					cand.convertTo = expType
70244-					// Give a major score penalty so we always prefer directly
70245-					// assignable candidates, all else equal.
70246-					cand.score *= 0.5
70247-					return true
70248-				}
70249-
70250-				continue
70251-			}
70252-
70253-			if expType == variadicType {
70254-				cand.mods = append(cand.mods, takeDotDotDot)
70255-			}
70256-
70257-			// Lower candidate score for untyped conversions. This avoids
70258-			// ranking untyped constants above candidates with an exact type
70259-			// match. Don't lower score of builtin constants, e.g. "true".
70260-			if isUntyped(candType) && !types.Identical(candType, expType) && cand.obj.Parent() != types.Universe {
70261-				// Bigger penalty for deep completions into other packages to
70262-				// avoid random constants from other packages popping up all
70263-				// the time.
70264-				if len(cand.path) > 0 && isPkgName(cand.path[0]) {
70265-					cand.score *= 0.5
70266-				} else {
70267-					cand.score *= 0.75
70268-				}
70269-			}
70270-
70271-			return true
70272-		}
70273-
70274-		// If we don't have a specific expected type, fall back to coarser
70275-		// object kind checks.
70276-		if ci.objType == nil || isEmptyInterface(ci.objType) {
70277-			// If we were able to apply type modifiers to our candidate type,
70278-			// count that as a match. For example:
70279-			//
70280-			//   var foo chan int
70281-			//   <-fo<>
70282-			//
70283-			// We were able to apply the "<-" type modifier to "foo", so "foo"
70284-			// matches.
70285-			if len(ci.modifiers) > 0 {
70286-				return true
70287-			}
70288-
70289-			// If we didn't have an exact type match, check if our object kind
70290-			// matches.
70291-			if ci.kindMatches(candType) {
70292-				if ci.objKind == kindFunc {
70293-					cand.mods = append(cand.mods, invoke)
70294-				}
70295-				return true
70296-			}
70297-		}
70298-
70299-		return false
70300-	})
70301-}
70302-
70303-// considerTypeConversion returns true if we should offer a completion
70304-// automatically converting "from" to "to".
70305-func considerTypeConversion(from, to types.Type, path []types.Object) bool {
70306-	// Don't offer to convert deep completions from other packages.
70307-	// Otherwise there are many random package level consts/vars that
70308-	// pop up as candidates all the time.
70309-	if len(path) > 0 && isPkgName(path[0]) {
70310-		return false
70311-	}
70312-
70313-	if _, ok := from.(*typeparams.TypeParam); ok {
70314-		return false
70315-	}
70316-
70317-	if !convertibleTo(from, to) {
70318-		return false
70319-	}
70320-
70321-	// Don't offer to convert ints to strings since that probably
70322-	// doesn't do what the user wants.
70323-	if isBasicKind(from, types.IsInteger) && isBasicKind(to, types.IsString) {
70324-		return false
70325-	}
70326-
70327-	return true
70328-}
70329-
70330-// typeMatches reports whether an object of candType makes a good
70331-// completion candidate given the expected type expType.
70332-func (ci *candidateInference) typeMatches(expType, candType types.Type) bool {
70333-	// Handle untyped values specially since AssignableTo gives false negatives
70334-	// for them (see https://golang.org/issue/32146).
70335-	if candBasic, ok := candType.Underlying().(*types.Basic); ok {
70336-		if expBasic, ok := expType.Underlying().(*types.Basic); ok {
70337-			// Note that the candidate and/or the expected can be untyped.
70338-			// In "fo<> == 100" the expected type is untyped, and the
70339-			// candidate could also be an untyped constant.
70340-
70341-			// Sort by is_untyped and then by is_int to simplify below logic.
70342-			a, b := candBasic.Info(), expBasic.Info()
70343-			if a&types.IsUntyped == 0 || (b&types.IsInteger > 0 && b&types.IsUntyped > 0) {
70344-				a, b = b, a
70345-			}
70346-
70347-			// If at least one is untyped...
70348-			if a&types.IsUntyped > 0 {
70349-				switch {
70350-				// Untyped integers are compatible with floats.
70351-				case a&types.IsInteger > 0 && b&types.IsFloat > 0:
70352-					return true
70353-
70354-				// Check if their constant kind (bool|int|float|complex|string) matches.
70355-				// This doesn't take into account the constant value, so there will be some
70356-				// false positives due to integer sign and overflow.
70357-				case a&types.IsConstType == b&types.IsConstType:
70358-					return true
70359-				}
70360-			}
70361-		}
70362-	}
70363-
70364-	// AssignableTo covers the case where the types are equal, but also handles
70365-	// cases like assigning a concrete type to an interface type.
70366-	return assignableTo(candType, expType)
70367-}
70368-
70369-// kindMatches reports whether candType's kind matches our expected
70370-// kind (e.g. slice, map, etc.).
70371-func (ci *candidateInference) kindMatches(candType types.Type) bool {
70372-	return ci.objKind > 0 && ci.objKind&candKind(candType) > 0
70373-}
70374-
70375-// assigneesMatch reports whether an invocation of sig matches the
70376-// number and type of any assignees.
70377-func (ci *candidateInference) assigneesMatch(cand *candidate, sig *types.Signature) bool {
70378-	if len(ci.assignees) == 0 {
70379-		return false
70380-	}
70381-
70382-	// Uniresult functions are always usable and are handled by the
70383-	// normal, non-assignees type matching logic.
70384-	if sig.Results().Len() == 1 {
70385-		return false
70386-	}
70387-
70388-	// Don't prefer completing into func(...interface{}) calls since all
70389-	// functions would match.
70390-	if ci.variadicAssignees && len(ci.assignees) == 1 && isEmptyInterface(deslice(ci.assignees[0])) {
70391-		return false
70392-	}
70393-
70394-	var numberOfResultsCouldMatch bool
70395-	if ci.variadicAssignees {
70396-		numberOfResultsCouldMatch = sig.Results().Len() >= len(ci.assignees)-1
70397-	} else {
70398-		numberOfResultsCouldMatch = sig.Results().Len() == len(ci.assignees)
70399-	}
70400-
70401-	// If our signature doesn't return the right number of values, it's
70402-	// not a match, so downrank it. For example:
70403-	//
70404-	//  var foo func() (int, int)
70405-	//  a, b, c := <> // downrank "foo()" since it only returns two values
70406-	if !numberOfResultsCouldMatch {
70407-		cand.score /= 2
70408-		return false
70409-	}
70410-
70411-	// If at least one assignee has a valid type, and all valid
70412-	// assignees match the corresponding sig result value, the signature
70413-	// is a match.
70414-	allMatch := false
70415-	for i := 0; i < sig.Results().Len(); i++ {
70416-		var assignee types.Type
70417-
70418-		// If we are completing into variadic parameters, deslice the
70419-		// expected variadic type.
70420-		if ci.variadicAssignees && i >= len(ci.assignees)-1 {
70421-			assignee = ci.assignees[len(ci.assignees)-1]
70422-			if elem := deslice(assignee); elem != nil {
70423-				assignee = elem
70424-			}
70425-		} else {
70426-			assignee = ci.assignees[i]
70427-		}
70428-
70429-		if assignee == nil || assignee == types.Typ[types.Invalid] {
70430-			continue
70431-		}
70432-
70433-		allMatch = ci.typeMatches(assignee, sig.Results().At(i).Type())
70434-		if !allMatch {
70435-			break
70436-		}
70437-	}
70438-	return allMatch
70439-}
70440-
70441-func (c *completer) matchingTypeName(cand *candidate) bool {
70442-	if !c.wantTypeName() {
70443-		return false
70444-	}
70445-
70446-	typeMatches := func(candType types.Type) bool {
70447-		// Take into account any type name modifier prefixes.
70448-		candType = c.inference.applyTypeNameModifiers(candType)
70449-
70450-		if from := c.inference.typeName.assertableFrom; from != nil {
70451-			// Don't suggest the starting type in type assertions. For example,
70452-			// if "foo" is an io.Writer, don't suggest "foo.(io.Writer)".
70453-			if types.Identical(from, candType) {
70454-				return false
70455-			}
70456-
70457-			if intf, ok := from.Underlying().(*types.Interface); ok {
70458-				if !types.AssertableTo(intf, candType) {
70459-					return false
70460-				}
70461-			}
70462-		}
70463-
70464-		if c.inference.typeName.wantComparable && !types.Comparable(candType) {
70465-			return false
70466-		}
70467-
70468-		// Skip this type if it has already been used in another type
70469-		// switch case.
70470-		for _, seen := range c.inference.typeName.seenTypeSwitchCases {
70471-			if types.Identical(candType, seen) {
70472-				return false
70473-			}
70474-		}
70475-
70476-		// We can expect a type name and have an expected type in cases like:
70477-		//
70478-		//   var foo []int
70479-		//   foo = []i<>
70480-		//
70481-		// Where our expected type is "[]int", and we expect a type name.
70482-		if c.inference.objType != nil {
70483-			return assignableTo(candType, c.inference.objType)
70484-		}
70485-
70486-		// Default to saying any type name is a match.
70487-		return true
70488-	}
70489-
70490-	t := cand.obj.Type()
70491-
70492-	if typeMatches(t) {
70493-		return true
70494-	}
70495-
70496-	if !types.IsInterface(t) && typeMatches(types.NewPointer(t)) {
70497-		if c.inference.typeName.compLitType {
70498-			// If we are completing a composite literal type as in
70499-			// "foo<>{}", to make a pointer we must prepend "&".
70500-			cand.mods = append(cand.mods, reference)
70501-		} else {
70502-			// If we are completing a normal type name such as "foo<>", to
70503-			// make a pointer we must prepend "*".
70504-			cand.mods = append(cand.mods, dereference)
70505-		}
70506-		return true
70507-	}
70508-
70509-	return false
70510-}
70511-
70512-var (
70513-	// "interface { Error() string }" (i.e. error)
70514-	errorIntf = types.Universe.Lookup("error").Type().Underlying().(*types.Interface)
70515-
70516-	// "interface { String() string }" (i.e. fmt.Stringer)
70517-	stringerIntf = types.NewInterfaceType([]*types.Func{
70518-		types.NewFunc(token.NoPos, nil, "String", types.NewSignature(
70519-			nil,
70520-			nil,
70521-			types.NewTuple(types.NewParam(token.NoPos, nil, "", types.Typ[types.String])),
70522-			false,
70523-		)),
70524-	}, nil).Complete()
70525-
70526-	byteType = types.Universe.Lookup("byte").Type()
70527-)
70528-
70529-// candKind returns the objKind of candType, if any.
70530-func candKind(candType types.Type) objKind {
70531-	var kind objKind
70532-
70533-	switch t := candType.Underlying().(type) {
70534-	case *types.Array:
70535-		kind |= kindArray
70536-		if t.Elem() == byteType {
70537-			kind |= kindBytes
70538-		}
70539-	case *types.Slice:
70540-		kind |= kindSlice
70541-		if t.Elem() == byteType {
70542-			kind |= kindBytes
70543-		}
70544-	case *types.Chan:
70545-		kind |= kindChan
70546-	case *types.Map:
70547-		kind |= kindMap
70548-	case *types.Pointer:
70549-		kind |= kindPtr
70550-
70551-		// Some builtins handle array pointers as arrays, so just report a pointer
70552-		// to an array as an array.
70553-		if _, isArray := t.Elem().Underlying().(*types.Array); isArray {
70554-			kind |= kindArray
70555-		}
70556-	case *types.Basic:
70557-		switch info := t.Info(); {
70558-		case info&types.IsString > 0:
70559-			kind |= kindString
70560-		case info&types.IsInteger > 0:
70561-			kind |= kindInt
70562-		case info&types.IsFloat > 0:
70563-			kind |= kindFloat
70564-		case info&types.IsComplex > 0:
70565-			kind |= kindComplex
70566-		case info&types.IsBoolean > 0:
70567-			kind |= kindBool
70568-		}
70569-	case *types.Signature:
70570-		return kindFunc
70571-	}
70572-
70573-	if types.Implements(candType, errorIntf) {
70574-		kind |= kindError
70575-	}
70576-
70577-	if types.Implements(candType, stringerIntf) {
70578-		kind |= kindStringer
70579-	}
70580-
70581-	return kind
70582-}
70583-
70584-// innermostScope returns the innermost scope for c.pos.
70585-func (c *completer) innermostScope() *types.Scope {
70586-	for _, s := range c.scopes {
70587-		if s != nil {
70588-			return s
70589-		}
70590-	}
70591-	return nil
70592-}
70593-
70594-// isSlice reports whether the object's underlying type is a slice.
70595-func isSlice(obj types.Object) bool {
70596-	if obj != nil && obj.Type() != nil {
70597-		if _, ok := obj.Type().Underlying().(*types.Slice); ok {
70598-			return true
70599-		}
70600-	}
70601-	return false
70602-}
70603-
70604-// forEachPackageMember calls f(tok, id, fn) for each package-level
70605-// TYPE/VAR/CONST/FUNC declaration in the Go source file, based on a
70606-// quick partial parse. fn is non-nil only for function declarations.
70607-// The AST position information is garbage.
70608-func forEachPackageMember(content []byte, f func(tok token.Token, id *ast.Ident, fn *ast.FuncDecl)) {
70609-	purged := purgeFuncBodies(content)
70610-	file, _ := parser.ParseFile(token.NewFileSet(), "", purged, 0)
70611-	for _, decl := range file.Decls {
70612-		switch decl := decl.(type) {
70613-		case *ast.GenDecl:
70614-			for _, spec := range decl.Specs {
70615-				switch spec := spec.(type) {
70616-				case *ast.ValueSpec: // var/const
70617-					for _, id := range spec.Names {
70618-						f(decl.Tok, id, nil)
70619-					}
70620-				case *ast.TypeSpec:
70621-					f(decl.Tok, spec.Name, nil)
70622-				}
70623-			}
70624-		case *ast.FuncDecl:
70625-			if decl.Recv == nil {
70626-				f(token.FUNC, decl.Name, decl)
70627-			}
70628-		}
70629-	}
70630-}
70631-
70632-// purgeFuncBodies returns a copy of src in which the contents of each
70633-// outermost {...} region except struct and interface types have been
70634-// deleted. It does not preserve newlines. This reduces the amount of
70635-// work required to parse the top-level declarations.
70636-func purgeFuncBodies(src []byte) []byte {
70637-	// Destroy the content of any {...}-bracketed regions that are
70638-	// not immediately preceded by a "struct" or "interface"
70639-	// token.  That includes function bodies, composite literals,
70640-	// switch/select bodies, and all blocks of statements.
70641-	// This will lead to non-void functions that don't have return
70642-	// statements, which of course is a type error, but that's ok.
70643-
70644-	var out bytes.Buffer
70645-	file := token.NewFileSet().AddFile("", -1, len(src))
70646-	var sc scanner.Scanner
70647-	sc.Init(file, src, nil, 0)
70648-	var prev token.Token
70649-	var cursor int         // last consumed src offset
70650-	var braces []token.Pos // stack of unclosed braces or -1 for struct/interface type
70651-	for {
70652-		pos, tok, _ := sc.Scan()
70653-		if tok == token.EOF {
70654-			break
70655-		}
70656-		switch tok {
70657-		case token.COMMENT:
70658-			// TODO(adonovan): opt: skip, to save an estimated 20% of time.
70659-
70660-		case token.LBRACE:
70661-			if prev == token.STRUCT || prev == token.INTERFACE {
70662-				pos = -1
70663-			}
70664-			braces = append(braces, pos)
70665-
70666-		case token.RBRACE:
70667-			if last := len(braces) - 1; last >= 0 {
70668-				top := braces[last]
70669-				braces = braces[:last]
70670-				if top < 0 {
70671-					// struct/interface type: leave alone
70672-				} else if len(braces) == 0 { // toplevel only
70673-					// Delete {...} body.
70674-					start, _ := safetoken.Offset(file, top)
70675-					end, _ := safetoken.Offset(file, pos)
70676-					out.Write(src[cursor : start+len("{")])
70677-					cursor = end
70678-				}
70679-			}
70680-		}
70681-		prev = tok
70682-	}
70683-	out.Write(src[cursor:])
70684-	return out.Bytes()
70685-}
70686diff -urN a/gopls/internal/lsp/source/completion/deep_completion.go b/gopls/internal/lsp/source/completion/deep_completion.go
70687--- a/gopls/internal/lsp/source/completion/deep_completion.go	2000-01-01 00:00:00.000000000 -0000
70688+++ b/gopls/internal/lsp/source/completion/deep_completion.go	1970-01-01 00:00:00.000000000 +0000
70689@@ -1,362 +0,0 @@
70690-// Copyright 2019 The Go Authors. All rights reserved.
70691-// Use of this source code is governed by a BSD-style
70692-// license that can be found in the LICENSE file.
70693-
70694-package completion
70695-
70696-import (
70697-	"context"
70698-	"go/types"
70699-	"strings"
70700-	"time"
70701-)
70702-
70703-// MaxDeepCompletions limits deep completion results because in most cases
70704-// there are too many to be useful.
70705-const MaxDeepCompletions = 3
70706-
70707-// deepCompletionState stores our state as we search for deep completions.
70708-// "deep completion" refers to searching into objects' fields and methods to
70709-// find more completion candidates.
70710-type deepCompletionState struct {
70711-	// enabled indicates whether deep completion is permitted.
70712-	enabled bool
70713-
70714-	// queueClosed is used to disable adding new sub-fields to search queue
70715-	// once we're running out of our time budget.
70716-	queueClosed bool
70717-
70718-	// thisQueue holds the current breadth first search queue.
70719-	thisQueue []candidate
70720-
70721-	// nextQueue holds the next breadth first search iteration's queue.
70722-	nextQueue []candidate
70723-
70724-	// highScores tracks the highest deep candidate scores we have found
70725-	// so far. This is used to avoid work for low scoring deep candidates.
70726-	highScores [MaxDeepCompletions]float64
70727-
70728-	// candidateCount is the count of unique deep candidates encountered
70729-	// so far.
70730-	candidateCount int
70731-}
70732-
70733-// enqueue adds a candidate to the search queue.
70734-func (s *deepCompletionState) enqueue(cand candidate) {
70735-	s.nextQueue = append(s.nextQueue, cand)
70736-}
70737-
70738-// dequeue removes and returns the leftmost element from the search queue.
70739-func (s *deepCompletionState) dequeue() *candidate {
70740-	var cand *candidate
70741-	cand, s.thisQueue = &s.thisQueue[len(s.thisQueue)-1], s.thisQueue[:len(s.thisQueue)-1]
70742-	return cand
70743-}
70744-
70745-// scorePenalty computes a deep candidate score penalty. A candidate is
70746-// penalized based on depth to favor shallower candidates. We also give a
70747-// slight bonus to unexported objects and a slight additional penalty to
70748-// function objects.
70749-func (s *deepCompletionState) scorePenalty(cand *candidate) float64 {
70750-	var deepPenalty float64
70751-	for _, dc := range cand.path {
70752-		deepPenalty++
70753-
70754-		if !dc.Exported() {
70755-			deepPenalty -= 0.1
70756-		}
70757-
70758-		if _, isSig := dc.Type().Underlying().(*types.Signature); isSig {
70759-			deepPenalty += 0.1
70760-		}
70761-	}
70762-
70763-	// Normalize penalty to a max depth of 10.
70764-	return deepPenalty / 10
70765-}
70766-
70767-// isHighScore returns whether score is among the top MaxDeepCompletions deep
70768-// candidate scores encountered so far. If so, it adds score to highScores,
70769-// possibly displacing an existing high score.
70770-func (s *deepCompletionState) isHighScore(score float64) bool {
70771-	// Invariant: s.highScores is sorted with highest score first. Unclaimed
70772-	// positions are trailing zeros.
70773-
70774-	// If we beat an existing score then take its spot.
70775-	for i, deepScore := range s.highScores {
70776-		if score <= deepScore {
70777-			continue
70778-		}
70779-
70780-		if deepScore != 0 && i != len(s.highScores)-1 {
70781-			// If this wasn't an empty slot then we need to scooch everyone
70782-			// down one spot.
70783-			copy(s.highScores[i+1:], s.highScores[i:])
70784-		}
70785-		s.highScores[i] = score
70786-		return true
70787-	}
70788-
70789-	return false
70790-}
70791-
70792-// newPath returns path from search root for an object following a given
70793-// candidate.
70794-func (s *deepCompletionState) newPath(cand candidate, obj types.Object) []types.Object {
70795-	path := make([]types.Object, len(cand.path)+1)
70796-	copy(path, cand.path)
70797-	path[len(path)-1] = obj
70798-
70799-	return path
70800-}
70801-
70802-// deepSearch searches a candidate and its subordinate objects for completion
70803-// items if deep completion is enabled and adds the valid candidates to
70804-// completion items.
70805-func (c *completer) deepSearch(ctx context.Context) {
70806-	defer func() {
70807-		// We can return early before completing the search, so be sure to
70808-		// clear out our queues to not impact any further invocations.
70809-		c.deepState.thisQueue = c.deepState.thisQueue[:0]
70810-		c.deepState.nextQueue = c.deepState.nextQueue[:0]
70811-	}()
70812-
70813-	for len(c.deepState.nextQueue) > 0 {
70814-		c.deepState.thisQueue, c.deepState.nextQueue = c.deepState.nextQueue, c.deepState.thisQueue[:0]
70815-
70816-	outer:
70817-		for _, cand := range c.deepState.thisQueue {
70818-			obj := cand.obj
70819-
70820-			if obj == nil {
70821-				continue
70822-			}
70823-
70824-			// At the top level, dedupe by object.
70825-			if len(cand.path) == 0 {
70826-				if c.seen[obj] {
70827-					continue
70828-				}
70829-				c.seen[obj] = true
70830-			}
70831-
70832-			// If obj is not accessible because it lives in another package and is
70833-			// not exported, don't treat it as a completion candidate unless it's
70834-			// a package completion candidate.
70835-			if !c.completionContext.packageCompletion &&
70836-				obj.Pkg() != nil && obj.Pkg() != c.pkg.GetTypes() && !obj.Exported() {
70837-				continue
70838-			}
70839-
70840-			// If we want a type name, don't offer non-type name candidates.
70841-			// However, do offer package names since they can contain type names,
70842-			// and do offer any candidate without a type since we aren't sure if it
70843-			// is a type name or not (i.e. unimported candidate).
70844-			if c.wantTypeName() && obj.Type() != nil && !isTypeName(obj) && !isPkgName(obj) {
70845-				continue
70846-			}
70847-
70848-			// When searching deep, make sure we don't have a cycle in our chain.
70849-			// We don't dedupe by object because we want to allow both "foo.Baz"
70850-			// and "bar.Baz" even though "Baz" is represented the same types.Object
70851-			// in both.
70852-			for _, seenObj := range cand.path {
70853-				if seenObj == obj {
70854-					continue outer
70855-				}
70856-			}
70857-
70858-			c.addCandidate(ctx, &cand)
70859-
70860-			c.deepState.candidateCount++
70861-			if c.opts.budget > 0 && c.deepState.candidateCount%100 == 0 {
70862-				spent := float64(time.Since(c.startTime)) / float64(c.opts.budget)
70863-				select {
70864-				case <-ctx.Done():
70865-					return
70866-				default:
70867-					// If we are almost out of budgeted time, no further elements
70868-					// should be added to the queue. This ensures remaining time is
70869-					// used for processing current queue.
70870-					if !c.deepState.queueClosed && spent >= 0.85 {
70871-						c.deepState.queueClosed = true
70872-					}
70873-				}
70874-			}
70875-
70876-			// if deep search is disabled, don't add any more candidates.
70877-			if !c.deepState.enabled || c.deepState.queueClosed {
70878-				continue
70879-			}
70880-
70881-			// Searching members for a type name doesn't make sense.
70882-			if isTypeName(obj) {
70883-				continue
70884-			}
70885-			if obj.Type() == nil {
70886-				continue
70887-			}
70888-
70889-			// Don't search embedded fields because they were already included in their
70890-			// parent's fields.
70891-			if v, ok := obj.(*types.Var); ok && v.Embedded() {
70892-				continue
70893-			}
70894-
70895-			if sig, ok := obj.Type().Underlying().(*types.Signature); ok {
70896-				// If obj is a function that takes no arguments and returns one
70897-				// value, keep searching across the function call.
70898-				if sig.Params().Len() == 0 && sig.Results().Len() == 1 {
70899-					path := c.deepState.newPath(cand, obj)
70900-					// The result of a function call is not addressable.
70901-					c.methodsAndFields(sig.Results().At(0).Type(), false, cand.imp, func(newCand candidate) {
70902-						newCand.pathInvokeMask = cand.pathInvokeMask | (1 << uint64(len(cand.path)))
70903-						newCand.path = path
70904-						c.deepState.enqueue(newCand)
70905-					})
70906-				}
70907-			}
70908-
70909-			path := c.deepState.newPath(cand, obj)
70910-			switch obj := obj.(type) {
70911-			case *types.PkgName:
70912-				c.packageMembers(obj.Imported(), stdScore, cand.imp, func(newCand candidate) {
70913-					newCand.pathInvokeMask = cand.pathInvokeMask
70914-					newCand.path = path
70915-					c.deepState.enqueue(newCand)
70916-				})
70917-			default:
70918-				c.methodsAndFields(obj.Type(), cand.addressable, cand.imp, func(newCand candidate) {
70919-					newCand.pathInvokeMask = cand.pathInvokeMask
70920-					newCand.path = path
70921-					c.deepState.enqueue(newCand)
70922-				})
70923-			}
70924-		}
70925-	}
70926-}
70927-
70928-// addCandidate adds a completion candidate to suggestions, without searching
70929-// its members for more candidates.
70930-func (c *completer) addCandidate(ctx context.Context, cand *candidate) {
70931-	obj := cand.obj
70932-	if c.matchingCandidate(cand) {
70933-		cand.score *= highScore
70934-
70935-		if p := c.penalty(cand); p > 0 {
70936-			cand.score *= (1 - p)
70937-		}
70938-	} else if isTypeName(obj) {
70939-		// If obj is a *types.TypeName that didn't otherwise match, check
70940-		// if a literal object of this type makes a good candidate.
70941-
70942-		// We only care about named types (i.e. don't want builtin types).
70943-		if _, isNamed := obj.Type().(*types.Named); isNamed {
70944-			c.literal(ctx, obj.Type(), cand.imp)
70945-		}
70946-	}
70947-
70948-	// Lower score of method calls so we prefer fields and vars over calls.
70949-	if cand.hasMod(invoke) {
70950-		if sig, ok := obj.Type().Underlying().(*types.Signature); ok && sig.Recv() != nil {
70951-			cand.score *= 0.9
70952-		}
70953-	}
70954-
70955-	// Prefer private objects over public ones.
70956-	if !obj.Exported() && obj.Parent() != types.Universe {
70957-		cand.score *= 1.1
70958-	}
70959-
70960-	// Slight penalty for index modifier (e.g. changing "foo" to
70961-	// "foo[]") to curb false positives.
70962-	if cand.hasMod(index) {
70963-		cand.score *= 0.9
70964-	}
70965-
70966-	// Favor shallow matches by lowering score according to depth.
70967-	cand.score -= cand.score * c.deepState.scorePenalty(cand)
70968-
70969-	if cand.score < 0 {
70970-		cand.score = 0
70971-	}
70972-
70973-	cand.name = deepCandName(cand)
70974-	if item, err := c.item(ctx, *cand); err == nil {
70975-		c.items = append(c.items, item)
70976-	}
70977-}
70978-
70979-// deepCandName produces the full candidate name including any
70980-// ancestor objects. For example, "foo.bar().baz" for candidate "baz".
70981-func deepCandName(cand *candidate) string {
70982-	totalLen := len(cand.obj.Name())
70983-	for i, obj := range cand.path {
70984-		totalLen += len(obj.Name()) + 1
70985-		if cand.pathInvokeMask&(1<<uint16(i)) > 0 {
70986-			totalLen += 2
70987-		}
70988-	}
70989-
70990-	var buf strings.Builder
70991-	buf.Grow(totalLen)
70992-
70993-	for i, obj := range cand.path {
70994-		buf.WriteString(obj.Name())
70995-		if cand.pathInvokeMask&(1<<uint16(i)) > 0 {
70996-			buf.WriteByte('(')
70997-			buf.WriteByte(')')
70998-		}
70999-		buf.WriteByte('.')
71000-	}
71001-
71002-	buf.WriteString(cand.obj.Name())
71003-
71004-	return buf.String()
71005-}
71006-
71007-// penalty reports a score penalty for cand in the range (0, 1).
71008-// For example, a candidate is penalized if it has already been used
71009-// in another switch case statement.
71010-func (c *completer) penalty(cand *candidate) float64 {
71011-	for _, p := range c.inference.penalized {
71012-		if c.objChainMatches(cand, p.objChain) {
71013-			return p.penalty
71014-		}
71015-	}
71016-
71017-	return 0
71018-}
71019-
71020-// objChainMatches reports whether cand combined with the surrounding
71021-// object prefix matches chain.
71022-func (c *completer) objChainMatches(cand *candidate, chain []types.Object) bool {
71023-	// For example, when completing:
71024-	//
71025-	//   foo.ba<>
71026-	//
71027-	// If we are considering the deep candidate "bar.baz", cand is baz,
71028-	// objChain is [foo] and deepChain is [bar]. We would match the
71029-	// chain [foo, bar, baz].
71030-	if len(chain) != len(c.inference.objChain)+len(cand.path)+1 {
71031-		return false
71032-	}
71033-
71034-	if chain[len(chain)-1] != cand.obj {
71035-		return false
71036-	}
71037-
71038-	for i, o := range c.inference.objChain {
71039-		if chain[i] != o {
71040-			return false
71041-		}
71042-	}
71043-
71044-	for i, o := range cand.path {
71045-		if chain[i+len(c.inference.objChain)] != o {
71046-			return false
71047-		}
71048-	}
71049-
71050-	return true
71051-}
71052diff -urN a/gopls/internal/lsp/source/completion/deep_completion_test.go b/gopls/internal/lsp/source/completion/deep_completion_test.go
71053--- a/gopls/internal/lsp/source/completion/deep_completion_test.go	2000-01-01 00:00:00.000000000 -0000
71054+++ b/gopls/internal/lsp/source/completion/deep_completion_test.go	1970-01-01 00:00:00.000000000 +0000
71055@@ -1,33 +0,0 @@
71056-// Copyright 2020 The Go Authors. All rights reserved.
71057-// Use of this source code is governed by a BSD-style
71058-// license that can be found in the LICENSE file.
71059-
71060-package completion
71061-
71062-import (
71063-	"testing"
71064-)
71065-
71066-func TestDeepCompletionIsHighScore(t *testing.T) {
71067-	// Test that deepCompletionState.isHighScore properly tracks the top
71068-	// N=MaxDeepCompletions scores.
71069-
71070-	var s deepCompletionState
71071-
71072-	if !s.isHighScore(1) {
71073-		// No other scores yet, anything is a winner.
71074-		t.Error("1 should be high score")
71075-	}
71076-
71077-	// Fill up with higher scores.
71078-	for i := 0; i < MaxDeepCompletions; i++ {
71079-		if !s.isHighScore(10) {
71080-			t.Error("10 should be high score")
71081-		}
71082-	}
71083-
71084-	// High scores should be filled with 10s so 2 is not a high score.
71085-	if s.isHighScore(2) {
71086-		t.Error("2 shouldn't be high score")
71087-	}
71088-}
71089diff -urN a/gopls/internal/lsp/source/completion/definition.go b/gopls/internal/lsp/source/completion/definition.go
71090--- a/gopls/internal/lsp/source/completion/definition.go	2000-01-01 00:00:00.000000000 -0000
71091+++ b/gopls/internal/lsp/source/completion/definition.go	1970-01-01 00:00:00.000000000 +0000
71092@@ -1,160 +0,0 @@
71093-// Copyright 2022 The Go Authors. All rights reserved.
71094-// Use of this source code is governed by a BSD-style
71095-// license that can be found in the LICENSE file.
71096-
71097-package completion
71098-
71099-import (
71100-	"go/ast"
71101-	"go/types"
71102-	"strings"
71103-	"unicode"
71104-	"unicode/utf8"
71105-
71106-	"golang.org/x/tools/gopls/internal/lsp/protocol"
71107-	"golang.org/x/tools/gopls/internal/lsp/snippet"
71108-	"golang.org/x/tools/gopls/internal/lsp/source"
71109-)
71110-
71111-// some function definitions in test files can be completed
71112-// So far, TestFoo(t *testing.T), TestMain(m *testing.M)
71113-// BenchmarkFoo(b *testing.B), FuzzFoo(f *testing.F)
71114-
71115-// path[0] is known to be *ast.Ident
71116-func definition(path []ast.Node, obj types.Object, pgf *source.ParsedGoFile) ([]CompletionItem, *Selection) {
71117-	if _, ok := obj.(*types.Func); !ok {
71118-		return nil, nil // not a function at all
71119-	}
71120-	if !strings.HasSuffix(pgf.URI.Filename(), "_test.go") {
71121-		return nil, nil // not a test file
71122-	}
71123-
71124-	name := path[0].(*ast.Ident).Name
71125-	if len(name) == 0 {
71126-		// can't happen
71127-		return nil, nil
71128-	}
71129-	start := path[0].Pos()
71130-	end := path[0].End()
71131-	sel := &Selection{
71132-		content: "",
71133-		cursor:  start,
71134-		tokFile: pgf.Tok,
71135-		start:   start,
71136-		end:     end,
71137-		mapper:  pgf.Mapper,
71138-	}
71139-	var ans []CompletionItem
71140-	var hasParens bool
71141-	n, ok := path[1].(*ast.FuncDecl)
71142-	if !ok {
71143-		return nil, nil // can't happen
71144-	}
71145-	if n.Recv != nil {
71146-		return nil, nil // a method, not a function
71147-	}
71148-	t := n.Type.Params
71149-	if t.Closing != t.Opening {
71150-		hasParens = true
71151-	}
71152-
71153-	// Always suggest TestMain, if possible
71154-	if strings.HasPrefix("TestMain", name) {
71155-		if hasParens {
71156-			ans = append(ans, defItem("TestMain", obj))
71157-		} else {
71158-			ans = append(ans, defItem("TestMain(m *testing.M)", obj))
71159-		}
71160-	}
71161-
71162-	// If a snippet is possible, suggest it
71163-	if strings.HasPrefix("Test", name) {
71164-		if hasParens {
71165-			ans = append(ans, defItem("Test", obj))
71166-		} else {
71167-			ans = append(ans, defSnippet("Test", "(t *testing.T)", obj))
71168-		}
71169-		return ans, sel
71170-	} else if strings.HasPrefix("Benchmark", name) {
71171-		if hasParens {
71172-			ans = append(ans, defItem("Benchmark", obj))
71173-		} else {
71174-			ans = append(ans, defSnippet("Benchmark", "(b *testing.B)", obj))
71175-		}
71176-		return ans, sel
71177-	} else if strings.HasPrefix("Fuzz", name) {
71178-		if hasParens {
71179-			ans = append(ans, defItem("Fuzz", obj))
71180-		} else {
71181-			ans = append(ans, defSnippet("Fuzz", "(f *testing.F)", obj))
71182-		}
71183-		return ans, sel
71184-	}
71185-
71186-	// Fill in the argument for what the user has already typed
71187-	if got := defMatches(name, "Test", path, "(t *testing.T)"); got != "" {
71188-		ans = append(ans, defItem(got, obj))
71189-	} else if got := defMatches(name, "Benchmark", path, "(b *testing.B)"); got != "" {
71190-		ans = append(ans, defItem(got, obj))
71191-	} else if got := defMatches(name, "Fuzz", path, "(f *testing.F)"); got != "" {
71192-		ans = append(ans, defItem(got, obj))
71193-	}
71194-	return ans, sel
71195-}
71196-
71197-// defMatches returns text for defItem, never for defSnippet
71198-func defMatches(name, pat string, path []ast.Node, arg string) string {
71199-	if !strings.HasPrefix(name, pat) {
71200-		return ""
71201-	}
71202-	c, _ := utf8.DecodeRuneInString(name[len(pat):])
71203-	if unicode.IsLower(c) {
71204-		return ""
71205-	}
71206-	fd, ok := path[1].(*ast.FuncDecl)
71207-	if !ok {
71208-		// we don't know what's going on
71209-		return ""
71210-	}
71211-	fp := fd.Type.Params
71212-	if len(fp.List) > 0 {
71213-		// signature already there, nothing to suggest
71214-		return ""
71215-	}
71216-	if fp.Opening != fp.Closing {
71217-		// nothing: completion works on words, not easy to insert arg
71218-		return ""
71219-	}
71220-	// suggesting signature too
71221-	return name + arg
71222-}
71223-
71224-func defSnippet(prefix, suffix string, obj types.Object) CompletionItem {
71225-	var sn snippet.Builder
71226-	sn.WriteText(prefix)
71227-	sn.WritePlaceholder(func(b *snippet.Builder) { b.WriteText("Xxx") })
71228-	sn.WriteText(suffix + " {\n\t")
71229-	sn.WriteFinalTabstop()
71230-	sn.WriteText("\n}")
71231-	return CompletionItem{
71232-		Label:         prefix + "Xxx" + suffix,
71233-		Detail:        "tab, type the rest of the name, then tab",
71234-		Kind:          protocol.FunctionCompletion,
71235-		Depth:         0,
71236-		Score:         10,
71237-		snippet:       &sn,
71238-		Documentation: prefix + " test function",
71239-		isSlice:       isSlice(obj),
71240-	}
71241-}
71242-func defItem(val string, obj types.Object) CompletionItem {
71243-	return CompletionItem{
71244-		Label:         val,
71245-		InsertText:    val,
71246-		Kind:          protocol.FunctionCompletion,
71247-		Depth:         0,
71248-		Score:         9, // prefer the snippets when available
71249-		Documentation: "complete the function name",
71250-		isSlice:       isSlice(obj),
71251-	}
71252-}
71253diff -urN a/gopls/internal/lsp/source/completion/format.go b/gopls/internal/lsp/source/completion/format.go
71254--- a/gopls/internal/lsp/source/completion/format.go	2000-01-01 00:00:00.000000000 -0000
71255+++ b/gopls/internal/lsp/source/completion/format.go	1970-01-01 00:00:00.000000000 +0000
71256@@ -1,338 +0,0 @@
71257-// Copyright 2019 The Go Authors. All rights reserved.
71258-// Use of this source code is governed by a BSD-style
71259-// license that can be found in the LICENSE file.
71260-
71261-package completion
71262-
71263-import (
71264-	"context"
71265-	"errors"
71266-	"fmt"
71267-	"go/ast"
71268-	"go/doc"
71269-	"go/types"
71270-	"strings"
71271-
71272-	"golang.org/x/tools/gopls/internal/lsp/protocol"
71273-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
71274-	"golang.org/x/tools/gopls/internal/lsp/snippet"
71275-	"golang.org/x/tools/gopls/internal/lsp/source"
71276-	"golang.org/x/tools/gopls/internal/span"
71277-	"golang.org/x/tools/internal/event"
71278-	"golang.org/x/tools/internal/imports"
71279-	"golang.org/x/tools/internal/typeparams"
71280-)
71281-
71282-var (
71283-	errNoMatch  = errors.New("not a surrounding match")
71284-	errLowScore = errors.New("not a high scoring candidate")
71285-)
71286-
71287-// item formats a candidate to a CompletionItem.
71288-func (c *completer) item(ctx context.Context, cand candidate) (CompletionItem, error) {
71289-	obj := cand.obj
71290-
71291-	// if the object isn't a valid match against the surrounding, return early.
71292-	matchScore := c.matcher.Score(cand.name)
71293-	if matchScore <= 0 {
71294-		return CompletionItem{}, errNoMatch
71295-	}
71296-	cand.score *= float64(matchScore)
71297-
71298-	// Ignore deep candidates that won't be in the MaxDeepCompletions anyway.
71299-	if len(cand.path) != 0 && !c.deepState.isHighScore(cand.score) {
71300-		return CompletionItem{}, errLowScore
71301-	}
71302-
71303-	// Handle builtin types separately.
71304-	if obj.Parent() == types.Universe {
71305-		return c.formatBuiltin(ctx, cand)
71306-	}
71307-
71308-	var (
71309-		label         = cand.name
71310-		detail        = types.TypeString(obj.Type(), c.qf)
71311-		insert        = label
71312-		kind          = protocol.TextCompletion
71313-		snip          snippet.Builder
71314-		protocolEdits []protocol.TextEdit
71315-	)
71316-	if obj.Type() == nil {
71317-		detail = ""
71318-	}
71319-	if isTypeName(obj) && c.wantTypeParams() {
71320-		x := cand.obj.(*types.TypeName)
71321-		if named, ok := x.Type().(*types.Named); ok {
71322-			tp := typeparams.ForNamed(named)
71323-			label += source.FormatTypeParams(tp)
71324-			insert = label // maintain invariant above (label == insert)
71325-		}
71326-	}
71327-
71328-	snip.WriteText(insert)
71329-
71330-	switch obj := obj.(type) {
71331-	case *types.TypeName:
71332-		detail, kind = source.FormatType(obj.Type(), c.qf)
71333-	case *types.Const:
71334-		kind = protocol.ConstantCompletion
71335-	case *types.Var:
71336-		if _, ok := obj.Type().(*types.Struct); ok {
71337-			detail = "struct{...}" // for anonymous structs
71338-		} else if obj.IsField() {
71339-			var err error
71340-			detail, err = source.FormatVarType(ctx, c.snapshot, c.pkg, obj, c.qf, c.mq)
71341-			if err != nil {
71342-				return CompletionItem{}, err
71343-			}
71344-		}
71345-		if obj.IsField() {
71346-			kind = protocol.FieldCompletion
71347-			c.structFieldSnippet(cand, detail, &snip)
71348-		} else {
71349-			kind = protocol.VariableCompletion
71350-		}
71351-		if obj.Type() == nil {
71352-			break
71353-		}
71354-	case *types.Func:
71355-		sig, ok := obj.Type().Underlying().(*types.Signature)
71356-		if !ok {
71357-			break
71358-		}
71359-		kind = protocol.FunctionCompletion
71360-		if sig != nil && sig.Recv() != nil {
71361-			kind = protocol.MethodCompletion
71362-		}
71363-	case *types.PkgName:
71364-		kind = protocol.ModuleCompletion
71365-		detail = fmt.Sprintf("%q", obj.Imported().Path())
71366-	case *types.Label:
71367-		kind = protocol.ConstantCompletion
71368-		detail = "label"
71369-	}
71370-
71371-	var prefix string
71372-	for _, mod := range cand.mods {
71373-		switch mod {
71374-		case reference:
71375-			prefix = "&" + prefix
71376-		case dereference:
71377-			prefix = "*" + prefix
71378-		case chanRead:
71379-			prefix = "<-" + prefix
71380-		}
71381-	}
71382-
71383-	var (
71384-		suffix   string
71385-		funcType = obj.Type()
71386-	)
71387-Suffixes:
71388-	for _, mod := range cand.mods {
71389-		switch mod {
71390-		case invoke:
71391-			if sig, ok := funcType.Underlying().(*types.Signature); ok {
71392-				s, err := source.NewSignature(ctx, c.snapshot, c.pkg, sig, nil, c.qf, c.mq)
71393-				if err != nil {
71394-					return CompletionItem{}, err
71395-				}
71396-				c.functionCallSnippet("", s.TypeParams(), s.Params(), &snip)
71397-				if sig.Results().Len() == 1 {
71398-					funcType = sig.Results().At(0).Type()
71399-				}
71400-				detail = "func" + s.Format()
71401-			}
71402-
71403-			if !c.opts.snippets {
71404-				// Without snippets the candidate will not include "()". Don't
71405-				// add further suffixes since they will be invalid. For
71406-				// example, with snippets "foo()..." would become "foo..."
71407-				// without snippets if we added the dotDotDot.
71408-				break Suffixes
71409-			}
71410-		case takeSlice:
71411-			suffix += "[:]"
71412-		case takeDotDotDot:
71413-			suffix += "..."
71414-		case index:
71415-			snip.WriteText("[")
71416-			snip.WritePlaceholder(nil)
71417-			snip.WriteText("]")
71418-		}
71419-	}
71420-
71421-	// If this candidate needs an additional import statement,
71422-	// add the additional text edits needed.
71423-	if cand.imp != nil {
71424-		addlEdits, err := c.importEdits(cand.imp)
71425-
71426-		if err != nil {
71427-			return CompletionItem{}, err
71428-		}
71429-
71430-		protocolEdits = append(protocolEdits, addlEdits...)
71431-		if kind != protocol.ModuleCompletion {
71432-			if detail != "" {
71433-				detail += " "
71434-			}
71435-			detail += fmt.Sprintf("(from %q)", cand.imp.importPath)
71436-		}
71437-	}
71438-
71439-	if cand.convertTo != nil {
71440-		typeName := types.TypeString(cand.convertTo, c.qf)
71441-
71442-		switch cand.convertTo.(type) {
71443-		// We need extra parens when casting to these types. For example,
71444-		// we need "(*int)(foo)", not "*int(foo)".
71445-		case *types.Pointer, *types.Signature:
71446-			typeName = "(" + typeName + ")"
71447-		}
71448-
71449-		prefix = typeName + "(" + prefix
71450-		suffix = ")"
71451-	}
71452-
71453-	if prefix != "" {
71454-		// If we are in a selector, add an edit to place prefix before selector.
71455-		if sel := enclosingSelector(c.path, c.pos); sel != nil {
71456-			edits, err := c.editText(sel.Pos(), sel.Pos(), prefix)
71457-			if err != nil {
71458-				return CompletionItem{}, err
71459-			}
71460-			protocolEdits = append(protocolEdits, edits...)
71461-		} else {
71462-			// If there is no selector, just stick the prefix at the start.
71463-			insert = prefix + insert
71464-			snip.PrependText(prefix)
71465-		}
71466-	}
71467-
71468-	if suffix != "" {
71469-		insert += suffix
71470-		snip.WriteText(suffix)
71471-	}
71472-
71473-	detail = strings.TrimPrefix(detail, "untyped ")
71474-	// override computed detail with provided detail, if something is provided.
71475-	if cand.detail != "" {
71476-		detail = cand.detail
71477-	}
71478-	item := CompletionItem{
71479-		Label:               label,
71480-		InsertText:          insert,
71481-		AdditionalTextEdits: protocolEdits,
71482-		Detail:              detail,
71483-		Kind:                kind,
71484-		Score:               cand.score,
71485-		Depth:               len(cand.path),
71486-		snippet:             &snip,
71487-		isSlice:             isSlice(obj),
71488-	}
71489-	// If the user doesn't want documentation for completion items.
71490-	if !c.opts.documentation {
71491-		return item, nil
71492-	}
71493-	pos := safetoken.StartPosition(c.pkg.FileSet(), obj.Pos())
71494-
71495-	// We ignore errors here, because some types, like "unsafe" or "error",
71496-	// may not have valid positions that we can use to get documentation.
71497-	if !pos.IsValid() {
71498-		return item, nil
71499-	}
71500-
71501-	comment, err := source.HoverDocForObject(ctx, c.snapshot, c.pkg.FileSet(), obj)
71502-	if err != nil {
71503-		event.Error(ctx, fmt.Sprintf("failed to find Hover for %q", obj.Name()), err)
71504-		return item, nil
71505-	}
71506-	if c.opts.fullDocumentation {
71507-		item.Documentation = comment.Text()
71508-	} else {
71509-		item.Documentation = doc.Synopsis(comment.Text())
71510-	}
71511-	// The desired pattern is `^// Deprecated`, but the prefix has been removed
71512-	// TODO(rfindley): It doesn't look like this does the right thing for
71513-	// multi-line comments.
71514-	if strings.HasPrefix(comment.Text(), "Deprecated") {
71515-		if c.snapshot.View().Options().CompletionTags {
71516-			item.Tags = []protocol.CompletionItemTag{protocol.ComplDeprecated}
71517-		} else if c.snapshot.View().Options().CompletionDeprecated {
71518-			item.Deprecated = true
71519-		}
71520-	}
71521-
71522-	return item, nil
71523-}
71524-
71525-// importEdits produces the text edits necessary to add the given import to the current file.
71526-func (c *completer) importEdits(imp *importInfo) ([]protocol.TextEdit, error) {
71527-	if imp == nil {
71528-		return nil, nil
71529-	}
71530-
71531-	pgf, err := c.pkg.File(span.URIFromPath(c.filename))
71532-	if err != nil {
71533-		return nil, err
71534-	}
71535-
71536-	return source.ComputeOneImportFixEdits(c.snapshot, pgf, &imports.ImportFix{
71537-		StmtInfo: imports.ImportInfo{
71538-			ImportPath: imp.importPath,
71539-			Name:       imp.name,
71540-		},
71541-		// IdentName is unused on this path and is difficult to get.
71542-		FixType: imports.AddImport,
71543-	})
71544-}
71545-
71546-func (c *completer) formatBuiltin(ctx context.Context, cand candidate) (CompletionItem, error) {
71547-	obj := cand.obj
71548-	item := CompletionItem{
71549-		Label:      obj.Name(),
71550-		InsertText: obj.Name(),
71551-		Score:      cand.score,
71552-	}
71553-	switch obj.(type) {
71554-	case *types.Const:
71555-		item.Kind = protocol.ConstantCompletion
71556-	case *types.Builtin:
71557-		item.Kind = protocol.FunctionCompletion
71558-		sig, err := source.NewBuiltinSignature(ctx, c.snapshot, obj.Name())
71559-		if err != nil {
71560-			return CompletionItem{}, err
71561-		}
71562-		item.Detail = "func" + sig.Format()
71563-		item.snippet = &snippet.Builder{}
71564-		c.functionCallSnippet(obj.Name(), sig.TypeParams(), sig.Params(), item.snippet)
71565-	case *types.TypeName:
71566-		if types.IsInterface(obj.Type()) {
71567-			item.Kind = protocol.InterfaceCompletion
71568-		} else {
71569-			item.Kind = protocol.ClassCompletion
71570-		}
71571-	case *types.Nil:
71572-		item.Kind = protocol.VariableCompletion
71573-	}
71574-	return item, nil
71575-}
71576-
71577-// decide if the type params (if any) should be part of the completion
71578-// which only possible for types.Named and types.Signature
71579-// (so far, only in receivers, e.g.; func (s *GENERIC[K, V])..., which is a types.Named)
71580-func (c *completer) wantTypeParams() bool {
71581-	// Need to be lexically in a receiver, and a child of an IndexListExpr
71582-	// (but IndexListExpr only exists with go1.18)
71583-	start := c.path[0].Pos()
71584-	for i, nd := range c.path {
71585-		if fd, ok := nd.(*ast.FuncDecl); ok {
71586-			if i > 0 && fd.Recv != nil && start < fd.Recv.End() {
71587-				return true
71588-			} else {
71589-				return false
71590-			}
71591-		}
71592-	}
71593-	return false
71594-}
71595diff -urN a/gopls/internal/lsp/source/completion/fuzz.go b/gopls/internal/lsp/source/completion/fuzz.go
71596--- a/gopls/internal/lsp/source/completion/fuzz.go	2000-01-01 00:00:00.000000000 -0000
71597+++ b/gopls/internal/lsp/source/completion/fuzz.go	1970-01-01 00:00:00.000000000 +0000
71598@@ -1,142 +0,0 @@
71599-// Copyright 2022 The Go Authors. All rights reserved.
71600-// Use of this source code is governed by a BSD-style
71601-// license that can be found in the LICENSE file.
71602-
71603-package completion
71604-
71605-import (
71606-	"fmt"
71607-	"go/ast"
71608-	"go/token"
71609-	"go/types"
71610-	"strings"
71611-
71612-	"golang.org/x/tools/gopls/internal/lsp/protocol"
71613-)
71614-
71615-// golang/go#51089
71616-// *testing.F deserves special treatment as member use is constrained:
71617-// The arguments to f.Fuzz are determined by the arguments to a previous f.Add
71618-// Inside f.Fuzz only f.Failed and f.Name are allowed.
71619-// PJW: are there other packages where we can deduce usage constraints?
71620-
71621-// if we find fuzz completions, then return true, as those are the only completions to offer
71622-func (c *completer) fuzz(typ types.Type, mset *types.MethodSet, imp *importInfo, cb func(candidate), fset *token.FileSet) bool {
71623-	// 1. inside f.Fuzz? (only f.Failed and f.Name)
71624-	// 2. possible completing f.Fuzz?
71625-	//    [Ident,SelectorExpr,Callexpr,ExprStmt,BlockiStmt,FuncDecl(Fuzz...)]
71626-	// 3. before f.Fuzz, same (for 2., offer choice when looking at an F)
71627-
71628-	// does the path contain FuncLit as arg to f.Fuzz CallExpr?
71629-	inside := false
71630-Loop:
71631-	for i, n := range c.path {
71632-		switch v := n.(type) {
71633-		case *ast.CallExpr:
71634-			if len(v.Args) != 1 {
71635-				continue Loop
71636-			}
71637-			if _, ok := v.Args[0].(*ast.FuncLit); !ok {
71638-				continue
71639-			}
71640-			if s, ok := v.Fun.(*ast.SelectorExpr); !ok || s.Sel.Name != "Fuzz" {
71641-				continue
71642-			}
71643-			if i > 2 { // avoid t.Fuzz itself in tests
71644-				inside = true
71645-				break Loop
71646-			}
71647-		}
71648-	}
71649-	if inside {
71650-		for i := 0; i < mset.Len(); i++ {
71651-			o := mset.At(i).Obj()
71652-			if o.Name() == "Failed" || o.Name() == "Name" {
71653-				cb(candidate{
71654-					obj:         o,
71655-					score:       stdScore,
71656-					imp:         imp,
71657-					addressable: true,
71658-				})
71659-			}
71660-		}
71661-		return true
71662-	}
71663-	// if it could be t.Fuzz, look for the preceding t.Add
71664-	id, ok := c.path[0].(*ast.Ident)
71665-	if ok && strings.HasPrefix("Fuzz", id.Name) {
71666-		var add *ast.CallExpr
71667-		f := func(n ast.Node) bool {
71668-			if n == nil {
71669-				return true
71670-			}
71671-			call, ok := n.(*ast.CallExpr)
71672-			if !ok {
71673-				return true
71674-			}
71675-			s, ok := call.Fun.(*ast.SelectorExpr)
71676-			if !ok {
71677-				return true
71678-			}
71679-			if s.Sel.Name != "Add" {
71680-				return true
71681-			}
71682-			// Sel.X should be of type *testing.F
71683-			got := c.pkg.GetTypesInfo().Types[s.X]
71684-			if got.Type.String() == "*testing.F" {
71685-				add = call
71686-			}
71687-			return false // because we're done...
71688-		}
71689-		// look at the enclosing FuzzFoo functions
71690-		if len(c.path) < 2 {
71691-			return false
71692-		}
71693-		n := c.path[len(c.path)-2]
71694-		if _, ok := n.(*ast.FuncDecl); !ok {
71695-			// the path should start with ast.File, ast.FuncDecl, ...
71696-			// but it didn't, so give up
71697-			return false
71698-		}
71699-		ast.Inspect(n, f)
71700-		if add == nil {
71701-			// looks like f.Fuzz without a preceding f.Add.
71702-			// let the regular completion handle it.
71703-			return false
71704-		}
71705-
71706-		lbl := "Fuzz(func(t *testing.T"
71707-		for i, a := range add.Args {
71708-			info := c.pkg.GetTypesInfo().TypeOf(a)
71709-			if info == nil {
71710-				return false // How could this happen, but better safe than panic.
71711-			}
71712-			lbl += fmt.Sprintf(", %c %s", 'a'+i, info)
71713-		}
71714-		lbl += ")"
71715-		xx := CompletionItem{
71716-			Label:         lbl,
71717-			InsertText:    lbl,
71718-			Kind:          protocol.FunctionCompletion,
71719-			Depth:         0,
71720-			Score:         10, // pretty confident the user should see this
71721-			Documentation: "argument types from f.Add",
71722-			isSlice:       false,
71723-		}
71724-		c.items = append(c.items, xx)
71725-		for i := 0; i < mset.Len(); i++ {
71726-			o := mset.At(i).Obj()
71727-			if o.Name() != "Fuzz" {
71728-				cb(candidate{
71729-					obj:         o,
71730-					score:       stdScore,
71731-					imp:         imp,
71732-					addressable: true,
71733-				})
71734-			}
71735-		}
71736-		return true // done
71737-	}
71738-	// let the standard processing take care of it instead
71739-	return false
71740-}
71741diff -urN a/gopls/internal/lsp/source/completion/keywords.go b/gopls/internal/lsp/source/completion/keywords.go
71742--- a/gopls/internal/lsp/source/completion/keywords.go	2000-01-01 00:00:00.000000000 -0000
71743+++ b/gopls/internal/lsp/source/completion/keywords.go	1970-01-01 00:00:00.000000000 +0000
71744@@ -1,154 +0,0 @@
71745-// Copyright 2020 The Go Authors. All rights reserved.
71746-// Use of this source code is governed by a BSD-style
71747-// license that can be found in the LICENSE file.
71748-
71749-package completion
71750-
71751-import (
71752-	"go/ast"
71753-
71754-	"golang.org/x/tools/gopls/internal/lsp/protocol"
71755-	"golang.org/x/tools/gopls/internal/lsp/source"
71756-)
71757-
71758-const (
71759-	BREAK       = "break"
71760-	CASE        = "case"
71761-	CHAN        = "chan"
71762-	CONST       = "const"
71763-	CONTINUE    = "continue"
71764-	DEFAULT     = "default"
71765-	DEFER       = "defer"
71766-	ELSE        = "else"
71767-	FALLTHROUGH = "fallthrough"
71768-	FOR         = "for"
71769-	FUNC        = "func"
71770-	GO          = "go"
71771-	GOTO        = "goto"
71772-	IF          = "if"
71773-	IMPORT      = "import"
71774-	INTERFACE   = "interface"
71775-	MAP         = "map"
71776-	PACKAGE     = "package"
71777-	RANGE       = "range"
71778-	RETURN      = "return"
71779-	SELECT      = "select"
71780-	STRUCT      = "struct"
71781-	SWITCH      = "switch"
71782-	TYPE        = "type"
71783-	VAR         = "var"
71784-)
71785-
71786-// addKeywordCompletions offers keyword candidates appropriate at the position.
71787-func (c *completer) addKeywordCompletions() {
71788-	seen := make(map[string]bool)
71789-
71790-	if c.wantTypeName() && c.inference.objType == nil {
71791-		// If we want a type name but don't have an expected obj type,
71792-		// include "interface", "struct", "func", "chan", and "map".
71793-
71794-		// "interface" and "struct" are more common declaring named types.
71795-		// Give them a higher score if we are in a type declaration.
71796-		structIntf, funcChanMap := stdScore, highScore
71797-		if len(c.path) > 1 {
71798-			if _, namedDecl := c.path[1].(*ast.TypeSpec); namedDecl {
71799-				structIntf, funcChanMap = highScore, stdScore
71800-			}
71801-		}
71802-
71803-		c.addKeywordItems(seen, structIntf, STRUCT, INTERFACE)
71804-		c.addKeywordItems(seen, funcChanMap, FUNC, CHAN, MAP)
71805-	}
71806-
71807-	// If we are at the file scope, only offer decl keywords. We don't
71808-	// get *ast.Idents at the file scope because non-keyword identifiers
71809-	// turn into *ast.BadDecl, not *ast.Ident.
71810-	if len(c.path) == 1 || isASTFile(c.path[1]) {
71811-		c.addKeywordItems(seen, stdScore, TYPE, CONST, VAR, FUNC, IMPORT)
71812-		return
71813-	} else if _, ok := c.path[0].(*ast.Ident); !ok {
71814-		// Otherwise only offer keywords if the client is completing an identifier.
71815-		return
71816-	}
71817-
71818-	if len(c.path) > 2 {
71819-		// Offer "range" if we are in ast.ForStmt.Init. This is what the
71820-		// AST looks like before "range" is typed, e.g. "for i := r<>".
71821-		if loop, ok := c.path[2].(*ast.ForStmt); ok && source.NodeContains(loop.Init, c.pos) {
71822-			c.addKeywordItems(seen, stdScore, RANGE)
71823-		}
71824-	}
71825-
71826-	// Only suggest keywords if we are beginning a statement.
71827-	switch n := c.path[1].(type) {
71828-	case *ast.BlockStmt, *ast.ExprStmt:
71829-		// OK - our ident must be at beginning of statement.
71830-	case *ast.CommClause:
71831-		// Make sure we aren't in the Comm statement.
71832-		if !n.Colon.IsValid() || c.pos <= n.Colon {
71833-			return
71834-		}
71835-	case *ast.CaseClause:
71836-		// Make sure we aren't in the case List.
71837-		if !n.Colon.IsValid() || c.pos <= n.Colon {
71838-			return
71839-		}
71840-	default:
71841-		return
71842-	}
71843-
71844-	// Filter out keywords depending on scope
71845-	// Skip the first one because we want to look at the enclosing scopes
71846-	path := c.path[1:]
71847-	for i, n := range path {
71848-		switch node := n.(type) {
71849-		case *ast.CaseClause:
71850-			// only recommend "fallthrough" and "break" within the bodies of a case clause
71851-			if c.pos > node.Colon {
71852-				c.addKeywordItems(seen, stdScore, BREAK)
71853-				// "fallthrough" is only valid in switch statements.
71854-				// A case clause is always nested within a block statement in a switch statement,
71855-				// that block statement is nested within either a TypeSwitchStmt or a SwitchStmt.
71856-				if i+2 >= len(path) {
71857-					continue
71858-				}
71859-				if _, ok := path[i+2].(*ast.SwitchStmt); ok {
71860-					c.addKeywordItems(seen, stdScore, FALLTHROUGH)
71861-				}
71862-			}
71863-		case *ast.CommClause:
71864-			if c.pos > node.Colon {
71865-				c.addKeywordItems(seen, stdScore, BREAK)
71866-			}
71867-		case *ast.TypeSwitchStmt, *ast.SelectStmt, *ast.SwitchStmt:
71868-			c.addKeywordItems(seen, stdScore, CASE, DEFAULT)
71869-		case *ast.ForStmt, *ast.RangeStmt:
71870-			c.addKeywordItems(seen, stdScore, BREAK, CONTINUE)
71871-		// This is a bit weak, functions allow for many keywords
71872-		case *ast.FuncDecl:
71873-			if node.Body != nil && c.pos > node.Body.Lbrace {
71874-				c.addKeywordItems(seen, stdScore, DEFER, RETURN, FOR, GO, SWITCH, SELECT, IF, ELSE, VAR, CONST, GOTO, TYPE)
71875-			}
71876-		}
71877-	}
71878-}
71879-
71880-// addKeywordItems dedupes and adds completion items for the specified
71881-// keywords with the specified score.
71882-func (c *completer) addKeywordItems(seen map[string]bool, score float64, kws ...string) {
71883-	for _, kw := range kws {
71884-		if seen[kw] {
71885-			continue
71886-		}
71887-		seen[kw] = true
71888-
71889-		if matchScore := c.matcher.Score(kw); matchScore > 0 {
71890-			c.items = append(c.items, CompletionItem{
71891-				Label:      kw,
71892-				Kind:       protocol.KeywordCompletion,
71893-				InsertText: kw,
71894-				Score:      score * float64(matchScore),
71895-			})
71896-		}
71897-	}
71898-}
71899diff -urN a/gopls/internal/lsp/source/completion/labels.go b/gopls/internal/lsp/source/completion/labels.go
71900--- a/gopls/internal/lsp/source/completion/labels.go	2000-01-01 00:00:00.000000000 -0000
71901+++ b/gopls/internal/lsp/source/completion/labels.go	1970-01-01 00:00:00.000000000 +0000
71902@@ -1,112 +0,0 @@
71903-// Copyright 2019 The Go Authors. All rights reserved.
71904-// Use of this source code is governed by a BSD-style
71905-// license that can be found in the LICENSE file.
71906-
71907-package completion
71908-
71909-import (
71910-	"go/ast"
71911-	"go/token"
71912-	"math"
71913-)
71914-
71915-type labelType int
71916-
71917-const (
71918-	labelNone labelType = iota
71919-	labelBreak
71920-	labelContinue
71921-	labelGoto
71922-)
71923-
71924-// wantLabelCompletion returns true if we want (only) label
71925-// completions at the position.
71926-func (c *completer) wantLabelCompletion() labelType {
71927-	if _, ok := c.path[0].(*ast.Ident); ok && len(c.path) > 1 {
71928-		// We want a label if we are an *ast.Ident child of a statement
71929-		// that accepts a label, e.g. "break Lo<>".
71930-		return takesLabel(c.path[1])
71931-	}
71932-
71933-	return labelNone
71934-}
71935-
71936-// takesLabel returns the corresponding labelType if n is a statement
71937-// that accepts a label, otherwise labelNone.
71938-func takesLabel(n ast.Node) labelType {
71939-	if bs, ok := n.(*ast.BranchStmt); ok {
71940-		switch bs.Tok {
71941-		case token.BREAK:
71942-			return labelBreak
71943-		case token.CONTINUE:
71944-			return labelContinue
71945-		case token.GOTO:
71946-			return labelGoto
71947-		}
71948-	}
71949-	return labelNone
71950-}
71951-
71952-// labels adds completion items for labels defined in the enclosing
71953-// function.
71954-func (c *completer) labels(lt labelType) {
71955-	if c.enclosingFunc == nil {
71956-		return
71957-	}
71958-
71959-	addLabel := func(score float64, l *ast.LabeledStmt) {
71960-		labelObj := c.pkg.GetTypesInfo().ObjectOf(l.Label)
71961-		if labelObj != nil {
71962-			c.deepState.enqueue(candidate{obj: labelObj, score: score})
71963-		}
71964-	}
71965-
71966-	switch lt {
71967-	case labelBreak, labelContinue:
71968-		// "break" and "continue" only accept labels from enclosing statements.
71969-
71970-		for i, p := range c.path {
71971-			switch p := p.(type) {
71972-			case *ast.FuncLit:
71973-				// Labels are function scoped, so don't continue out of functions.
71974-				return
71975-			case *ast.LabeledStmt:
71976-				switch p.Stmt.(type) {
71977-				case *ast.ForStmt, *ast.RangeStmt:
71978-					// Loop labels can be used for "break" or "continue".
71979-					addLabel(highScore*math.Pow(.99, float64(i)), p)
71980-				case *ast.SwitchStmt, *ast.SelectStmt, *ast.TypeSwitchStmt:
71981-					// Switch and select labels can be used only for "break".
71982-					if lt == labelBreak {
71983-						addLabel(highScore*math.Pow(.99, float64(i)), p)
71984-					}
71985-				}
71986-			}
71987-		}
71988-	case labelGoto:
71989-		// Goto accepts any label in the same function not in a nested
71990-		// block. It also doesn't take labels that would jump across
71991-		// variable definitions, but ignore that case for now.
71992-		ast.Inspect(c.enclosingFunc.body, func(n ast.Node) bool {
71993-			if n == nil {
71994-				return false
71995-			}
71996-
71997-			switch n := n.(type) {
71998-			// Only search into block-like nodes enclosing our "goto".
71999-			// This prevents us from finding labels in nested blocks.
72000-			case *ast.BlockStmt, *ast.CommClause, *ast.CaseClause:
72001-				for _, p := range c.path {
72002-					if n == p {
72003-						return true
72004-					}
72005-				}
72006-				return false
72007-			case *ast.LabeledStmt:
72008-				addLabel(highScore, n)
72009-			}
72010-
72011-			return true
72012-		})
72013-	}
72014-}
72015diff -urN a/gopls/internal/lsp/source/completion/literal.go b/gopls/internal/lsp/source/completion/literal.go
72016--- a/gopls/internal/lsp/source/completion/literal.go	2000-01-01 00:00:00.000000000 -0000
72017+++ b/gopls/internal/lsp/source/completion/literal.go	1970-01-01 00:00:00.000000000 +0000
72018@@ -1,592 +0,0 @@
72019-// Copyright 2019 The Go Authors. All rights reserved.
72020-// Use of this source code is governed by a BSD-style
72021-// license that can be found in the LICENSE file.
72022-
72023-package completion
72024-
72025-import (
72026-	"context"
72027-	"fmt"
72028-	"go/types"
72029-	"strings"
72030-	"unicode"
72031-
72032-	"golang.org/x/tools/gopls/internal/lsp/protocol"
72033-	"golang.org/x/tools/gopls/internal/lsp/snippet"
72034-	"golang.org/x/tools/gopls/internal/lsp/source"
72035-	"golang.org/x/tools/internal/event"
72036-	"golang.org/x/tools/internal/typeparams"
72037-)
72038-
72039-// literal generates composite literal, function literal, and make()
72040-// completion items.
72041-func (c *completer) literal(ctx context.Context, literalType types.Type, imp *importInfo) {
72042-	if !c.opts.literal {
72043-		return
72044-	}
72045-
72046-	expType := c.inference.objType
72047-
72048-	if c.inference.matchesVariadic(literalType) {
72049-		// Don't offer literal slice candidates for variadic arguments.
72050-		// For example, don't offer "[]interface{}{}" in "fmt.Print(<>)".
72051-		return
72052-	}
72053-
72054-	// Avoid literal candidates if the expected type is an empty
72055-	// interface. It isn't very useful to suggest a literal candidate of
72056-	// every possible type.
72057-	if expType != nil && isEmptyInterface(expType) {
72058-		return
72059-	}
72060-
72061-	// We handle unnamed literal completions explicitly before searching
72062-	// for candidates. Avoid named-type literal completions for
72063-	// unnamed-type expected type since that results in duplicate
72064-	// candidates. For example, in
72065-	//
72066-	// type mySlice []int
72067-	// var []int = <>
72068-	//
72069-	// don't offer "mySlice{}" since we have already added a candidate
72070-	// of "[]int{}".
72071-	if _, named := literalType.(*types.Named); named && expType != nil {
72072-		if _, named := source.Deref(expType).(*types.Named); !named {
72073-			return
72074-		}
72075-	}
72076-
72077-	// Check if an object of type literalType would match our expected type.
72078-	cand := candidate{
72079-		obj: c.fakeObj(literalType),
72080-	}
72081-
72082-	switch literalType.Underlying().(type) {
72083-	// These literal types are addressable (e.g. "&[]int{}"), others are
72084-	// not (e.g. can't do "&(func(){})").
72085-	case *types.Struct, *types.Array, *types.Slice, *types.Map:
72086-		cand.addressable = true
72087-	}
72088-
72089-	if !c.matchingCandidate(&cand) || cand.convertTo != nil {
72090-		return
72091-	}
72092-
72093-	var (
72094-		qf  = c.qf
72095-		sel = enclosingSelector(c.path, c.pos)
72096-	)
72097-
72098-	// Don't qualify the type name if we are in a selector expression
72099-	// since the package name is already present.
72100-	if sel != nil {
72101-		qf = func(_ *types.Package) string { return "" }
72102-	}
72103-
72104-	snip, typeName := c.typeNameSnippet(literalType, qf)
72105-
72106-	// A type name of "[]int" doesn't work very will with the matcher
72107-	// since "[" isn't a valid identifier prefix. Here we strip off the
72108-	// slice (and array) prefix yielding just "int".
72109-	matchName := typeName
72110-	switch t := literalType.(type) {
72111-	case *types.Slice:
72112-		matchName = types.TypeString(t.Elem(), qf)
72113-	case *types.Array:
72114-		matchName = types.TypeString(t.Elem(), qf)
72115-	}
72116-
72117-	addlEdits, err := c.importEdits(imp)
72118-	if err != nil {
72119-		event.Error(ctx, "error adding import for literal candidate", err)
72120-		return
72121-	}
72122-
72123-	// If prefix matches the type name, client may want a composite literal.
72124-	if score := c.matcher.Score(matchName); score > 0 {
72125-		if cand.hasMod(reference) {
72126-			if sel != nil {
72127-				// If we are in a selector we must place the "&" before the selector.
72128-				// For example, "foo.B<>" must complete to "&foo.Bar{}", not
72129-				// "foo.&Bar{}".
72130-				edits, err := c.editText(sel.Pos(), sel.Pos(), "&")
72131-				if err != nil {
72132-					event.Error(ctx, "error making edit for literal pointer completion", err)
72133-					return
72134-				}
72135-				addlEdits = append(addlEdits, edits...)
72136-			} else {
72137-				// Otherwise we can stick the "&" directly before the type name.
72138-				typeName = "&" + typeName
72139-				snip.PrependText("&")
72140-			}
72141-		}
72142-
72143-		switch t := literalType.Underlying().(type) {
72144-		case *types.Struct, *types.Array, *types.Slice, *types.Map:
72145-			c.compositeLiteral(t, snip.Clone(), typeName, float64(score), addlEdits)
72146-		case *types.Signature:
72147-			// Add a literal completion for a signature type that implements
72148-			// an interface. For example, offer "http.HandlerFunc()" when
72149-			// expected type is "http.Handler".
72150-			if expType != nil && types.IsInterface(expType) {
72151-				c.basicLiteral(t, snip.Clone(), typeName, float64(score), addlEdits)
72152-			}
72153-		case *types.Basic:
72154-			// Add a literal completion for basic types that implement our
72155-			// expected interface (e.g. named string type http.Dir
72156-			// implements http.FileSystem), or are identical to our expected
72157-			// type (i.e. yielding a type conversion such as "float64()").
72158-			if expType != nil && (types.IsInterface(expType) || types.Identical(expType, literalType)) {
72159-				c.basicLiteral(t, snip.Clone(), typeName, float64(score), addlEdits)
72160-			}
72161-		}
72162-	}
72163-
72164-	// If prefix matches "make", client may want a "make()"
72165-	// invocation. We also include the type name to allow for more
72166-	// flexible fuzzy matching.
72167-	if score := c.matcher.Score("make." + matchName); !cand.hasMod(reference) && score > 0 {
72168-		switch literalType.Underlying().(type) {
72169-		case *types.Slice:
72170-			// The second argument to "make()" for slices is required, so default to "0".
72171-			c.makeCall(snip.Clone(), typeName, "0", float64(score), addlEdits)
72172-		case *types.Map, *types.Chan:
72173-			// Maps and channels don't require the second argument, so omit
72174-			// to keep things simple for now.
72175-			c.makeCall(snip.Clone(), typeName, "", float64(score), addlEdits)
72176-		}
72177-	}
72178-
72179-	// If prefix matches "func", client may want a function literal.
72180-	if score := c.matcher.Score("func"); !cand.hasMod(reference) && score > 0 && (expType == nil || !types.IsInterface(expType)) {
72181-		switch t := literalType.Underlying().(type) {
72182-		case *types.Signature:
72183-			c.functionLiteral(ctx, t, float64(score))
72184-		}
72185-	}
72186-}
72187-
72188-// literalCandidateScore is the base score for literal candidates.
72189-// Literal candidates match the expected type so they should be high
72190-// scoring, but we want them ranked below lexical objects of the
72191-// correct type, so scale down highScore.
72192-const literalCandidateScore = highScore / 2
72193-
72194-// functionLiteral adds a function literal completion item for the
72195-// given signature.
72196-func (c *completer) functionLiteral(ctx context.Context, sig *types.Signature, matchScore float64) {
72197-	snip := &snippet.Builder{}
72198-	snip.WriteText("func(")
72199-
72200-	// First we generate names for each param and keep a seen count so
72201-	// we know if we need to uniquify param names. For example,
72202-	// "func(int)" will become "func(i int)", but "func(int, int64)"
72203-	// will become "func(i1 int, i2 int64)".
72204-	var (
72205-		paramNames     = make([]string, sig.Params().Len())
72206-		paramNameCount = make(map[string]int)
72207-		hasTypeParams  bool
72208-	)
72209-	for i := 0; i < sig.Params().Len(); i++ {
72210-		var (
72211-			p    = sig.Params().At(i)
72212-			name = p.Name()
72213-		)
72214-
72215-		if tp, _ := p.Type().(*typeparams.TypeParam); tp != nil && !c.typeParamInScope(tp) {
72216-			hasTypeParams = true
72217-		}
72218-
72219-		if name == "" {
72220-			// If the param has no name in the signature, guess a name based
72221-			// on the type. Use an empty qualifier to ignore the package.
72222-			// For example, we want to name "http.Request" "r", not "hr".
72223-			typeName, err := source.FormatVarType(ctx, c.snapshot, c.pkg, p,
72224-				func(p *types.Package) string { return "" },
72225-				func(source.PackageName, source.ImportPath, source.PackagePath) string { return "" })
72226-			if err != nil {
72227-				// In general, the only error we should encounter while formatting is
72228-				// context cancellation.
72229-				if ctx.Err() == nil {
72230-					event.Error(ctx, "formatting var type", err)
72231-				}
72232-				return
72233-			}
72234-			name = abbreviateTypeName(typeName)
72235-		}
72236-		paramNames[i] = name
72237-		if name != "_" {
72238-			paramNameCount[name]++
72239-		}
72240-	}
72241-
72242-	for n, c := range paramNameCount {
72243-		// Any names we saw more than once will need a unique suffix added
72244-		// on. Reset the count to 1 to act as the suffix for the first
72245-		// name.
72246-		if c >= 2 {
72247-			paramNameCount[n] = 1
72248-		} else {
72249-			delete(paramNameCount, n)
72250-		}
72251-	}
72252-
72253-	for i := 0; i < sig.Params().Len(); i++ {
72254-		if hasTypeParams && !c.opts.placeholders {
72255-			// If there are type params in the args then the user must
72256-			// choose the concrete types. If placeholders are disabled just
72257-			// drop them between the parens and let them fill things in.
72258-			snip.WritePlaceholder(nil)
72259-			break
72260-		}
72261-
72262-		if i > 0 {
72263-			snip.WriteText(", ")
72264-		}
72265-
72266-		var (
72267-			p    = sig.Params().At(i)
72268-			name = paramNames[i]
72269-		)
72270-
72271-		// Uniquify names by adding on an incrementing numeric suffix.
72272-		if idx, found := paramNameCount[name]; found {
72273-			paramNameCount[name]++
72274-			name = fmt.Sprintf("%s%d", name, idx)
72275-		}
72276-
72277-		if name != p.Name() && c.opts.placeholders {
72278-			// If we didn't use the signature's param name verbatim then we
72279-			// may have chosen a poor name. Give the user a placeholder so
72280-			// they can easily fix the name.
72281-			snip.WritePlaceholder(func(b *snippet.Builder) {
72282-				b.WriteText(name)
72283-			})
72284-		} else {
72285-			snip.WriteText(name)
72286-		}
72287-
72288-		// If the following param's type is identical to this one, omit
72289-		// this param's type string. For example, emit "i, j int" instead
72290-		// of "i int, j int".
72291-		if i == sig.Params().Len()-1 || !types.Identical(p.Type(), sig.Params().At(i+1).Type()) {
72292-			snip.WriteText(" ")
72293-			typeStr, err := source.FormatVarType(ctx, c.snapshot, c.pkg, p, c.qf, c.mq)
72294-			if err != nil {
72295-				// In general, the only error we should encounter while formatting is
72296-				// context cancellation.
72297-				if ctx.Err() == nil {
72298-					event.Error(ctx, "formatting var type", err)
72299-				}
72300-				return
72301-			}
72302-			if sig.Variadic() && i == sig.Params().Len()-1 {
72303-				typeStr = strings.Replace(typeStr, "[]", "...", 1)
72304-			}
72305-
72306-			if tp, _ := p.Type().(*typeparams.TypeParam); tp != nil && !c.typeParamInScope(tp) {
72307-				snip.WritePlaceholder(func(snip *snippet.Builder) {
72308-					snip.WriteText(typeStr)
72309-				})
72310-			} else {
72311-				snip.WriteText(typeStr)
72312-			}
72313-		}
72314-	}
72315-	snip.WriteText(")")
72316-
72317-	results := sig.Results()
72318-	if results.Len() > 0 {
72319-		snip.WriteText(" ")
72320-	}
72321-
72322-	resultsNeedParens := results.Len() > 1 ||
72323-		results.Len() == 1 && results.At(0).Name() != ""
72324-
72325-	var resultHasTypeParams bool
72326-	for i := 0; i < results.Len(); i++ {
72327-		if tp, _ := results.At(i).Type().(*typeparams.TypeParam); tp != nil && !c.typeParamInScope(tp) {
72328-			resultHasTypeParams = true
72329-		}
72330-	}
72331-
72332-	if resultsNeedParens {
72333-		snip.WriteText("(")
72334-	}
72335-	for i := 0; i < results.Len(); i++ {
72336-		if resultHasTypeParams && !c.opts.placeholders {
72337-			// Leave an empty tabstop if placeholders are disabled and there
72338-			// are type args that need specificying.
72339-			snip.WritePlaceholder(nil)
72340-			break
72341-		}
72342-
72343-		if i > 0 {
72344-			snip.WriteText(", ")
72345-		}
72346-		r := results.At(i)
72347-		if name := r.Name(); name != "" {
72348-			snip.WriteText(name + " ")
72349-		}
72350-
72351-		text, err := source.FormatVarType(ctx, c.snapshot, c.pkg, r, c.qf, c.mq)
72352-		if err != nil {
72353-			// In general, the only error we should encounter while formatting is
72354-			// context cancellation.
72355-			if ctx.Err() == nil {
72356-				event.Error(ctx, "formatting var type", err)
72357-			}
72358-			return
72359-		}
72360-		if tp, _ := r.Type().(*typeparams.TypeParam); tp != nil && !c.typeParamInScope(tp) {
72361-			snip.WritePlaceholder(func(snip *snippet.Builder) {
72362-				snip.WriteText(text)
72363-			})
72364-		} else {
72365-			snip.WriteText(text)
72366-		}
72367-	}
72368-	if resultsNeedParens {
72369-		snip.WriteText(")")
72370-	}
72371-
72372-	snip.WriteText(" {")
72373-	snip.WriteFinalTabstop()
72374-	snip.WriteText("}")
72375-
72376-	c.items = append(c.items, CompletionItem{
72377-		Label:   "func(...) {}",
72378-		Score:   matchScore * literalCandidateScore,
72379-		Kind:    protocol.VariableCompletion,
72380-		snippet: snip,
72381-	})
72382-}
72383-
72384-// conventionalAcronyms contains conventional acronyms for type names
72385-// in lower case. For example, "ctx" for "context" and "err" for "error".
72386-var conventionalAcronyms = map[string]string{
72387-	"context":        "ctx",
72388-	"error":          "err",
72389-	"tx":             "tx",
72390-	"responsewriter": "w",
72391-}
72392-
72393-// abbreviateTypeName abbreviates type names into acronyms. For
72394-// example, "fooBar" is abbreviated "fb". Care is taken to ignore
72395-// non-identifier runes. For example, "[]int" becomes "i", and
72396-// "struct { i int }" becomes "s".
72397-func abbreviateTypeName(s string) string {
72398-	var (
72399-		b            strings.Builder
72400-		useNextUpper bool
72401-	)
72402-
72403-	// Trim off leading non-letters. We trim everything between "[" and
72404-	// "]" to handle array types like "[someConst]int".
72405-	var inBracket bool
72406-	s = strings.TrimFunc(s, func(r rune) bool {
72407-		if inBracket {
72408-			inBracket = r != ']'
72409-			return true
72410-		}
72411-
72412-		if r == '[' {
72413-			inBracket = true
72414-		}
72415-
72416-		return !unicode.IsLetter(r)
72417-	})
72418-
72419-	if acr, ok := conventionalAcronyms[strings.ToLower(s)]; ok {
72420-		return acr
72421-	}
72422-
72423-	for i, r := range s {
72424-		// Stop if we encounter a non-identifier rune.
72425-		if !unicode.IsLetter(r) && !unicode.IsNumber(r) {
72426-			break
72427-		}
72428-
72429-		if i == 0 {
72430-			b.WriteRune(unicode.ToLower(r))
72431-		}
72432-
72433-		if unicode.IsUpper(r) {
72434-			if useNextUpper {
72435-				b.WriteRune(unicode.ToLower(r))
72436-				useNextUpper = false
72437-			}
72438-		} else {
72439-			useNextUpper = true
72440-		}
72441-	}
72442-
72443-	return b.String()
72444-}
72445-
72446-// compositeLiteral adds a composite literal completion item for the given typeName.
72447-func (c *completer) compositeLiteral(T types.Type, snip *snippet.Builder, typeName string, matchScore float64, edits []protocol.TextEdit) {
72448-	snip.WriteText("{")
72449-	// Don't put the tab stop inside the composite literal curlies "{}"
72450-	// for structs that have no accessible fields.
72451-	if strct, ok := T.(*types.Struct); !ok || fieldsAccessible(strct, c.pkg.GetTypes()) {
72452-		snip.WriteFinalTabstop()
72453-	}
72454-	snip.WriteText("}")
72455-
72456-	nonSnippet := typeName + "{}"
72457-
72458-	c.items = append(c.items, CompletionItem{
72459-		Label:               nonSnippet,
72460-		InsertText:          nonSnippet,
72461-		Score:               matchScore * literalCandidateScore,
72462-		Kind:                protocol.VariableCompletion,
72463-		AdditionalTextEdits: edits,
72464-		snippet:             snip,
72465-	})
72466-}
72467-
72468-// basicLiteral adds a literal completion item for the given basic
72469-// type name typeName.
72470-func (c *completer) basicLiteral(T types.Type, snip *snippet.Builder, typeName string, matchScore float64, edits []protocol.TextEdit) {
72471-	// Never give type conversions like "untyped int()".
72472-	if isUntyped(T) {
72473-		return
72474-	}
72475-
72476-	snip.WriteText("(")
72477-	snip.WriteFinalTabstop()
72478-	snip.WriteText(")")
72479-
72480-	nonSnippet := typeName + "()"
72481-
72482-	c.items = append(c.items, CompletionItem{
72483-		Label:               nonSnippet,
72484-		InsertText:          nonSnippet,
72485-		Detail:              T.String(),
72486-		Score:               matchScore * literalCandidateScore,
72487-		Kind:                protocol.VariableCompletion,
72488-		AdditionalTextEdits: edits,
72489-		snippet:             snip,
72490-	})
72491-}
72492-
72493-// makeCall adds a completion item for a "make()" call given a specific type.
72494-func (c *completer) makeCall(snip *snippet.Builder, typeName string, secondArg string, matchScore float64, edits []protocol.TextEdit) {
72495-	// Keep it simple and don't add any placeholders for optional "make()" arguments.
72496-
72497-	snip.PrependText("make(")
72498-	if secondArg != "" {
72499-		snip.WriteText(", ")
72500-		snip.WritePlaceholder(func(b *snippet.Builder) {
72501-			if c.opts.placeholders {
72502-				b.WriteText(secondArg)
72503-			}
72504-		})
72505-	}
72506-	snip.WriteText(")")
72507-
72508-	var nonSnippet strings.Builder
72509-	nonSnippet.WriteString("make(" + typeName)
72510-	if secondArg != "" {
72511-		nonSnippet.WriteString(", ")
72512-		nonSnippet.WriteString(secondArg)
72513-	}
72514-	nonSnippet.WriteByte(')')
72515-
72516-	c.items = append(c.items, CompletionItem{
72517-		Label:               nonSnippet.String(),
72518-		InsertText:          nonSnippet.String(),
72519-		Score:               matchScore * literalCandidateScore,
72520-		Kind:                protocol.FunctionCompletion,
72521-		AdditionalTextEdits: edits,
72522-		snippet:             snip,
72523-	})
72524-}
72525-
72526-// Create a snippet for a type name where type params become placeholders.
72527-func (c *completer) typeNameSnippet(literalType types.Type, qf types.Qualifier) (*snippet.Builder, string) {
72528-	var (
72529-		snip     snippet.Builder
72530-		typeName string
72531-		named, _ = literalType.(*types.Named)
72532-	)
72533-
72534-	if named != nil && named.Obj() != nil && typeparams.ForNamed(named).Len() > 0 && !c.fullyInstantiated(named) {
72535-		// We are not "fully instantiated" meaning we have type params that must be specified.
72536-		if pkg := qf(named.Obj().Pkg()); pkg != "" {
72537-			typeName = pkg + "."
72538-		}
72539-
72540-		// We do this to get "someType" instead of "someType[T]".
72541-		typeName += named.Obj().Name()
72542-		snip.WriteText(typeName + "[")
72543-
72544-		if c.opts.placeholders {
72545-			for i := 0; i < typeparams.ForNamed(named).Len(); i++ {
72546-				if i > 0 {
72547-					snip.WriteText(", ")
72548-				}
72549-				snip.WritePlaceholder(func(snip *snippet.Builder) {
72550-					snip.WriteText(types.TypeString(typeparams.ForNamed(named).At(i), qf))
72551-				})
72552-			}
72553-		} else {
72554-			snip.WritePlaceholder(nil)
72555-		}
72556-		snip.WriteText("]")
72557-		typeName += "[...]"
72558-	} else {
72559-		// We don't have unspecified type params so use default type formatting.
72560-		typeName = types.TypeString(literalType, qf)
72561-		snip.WriteText(typeName)
72562-	}
72563-
72564-	return &snip, typeName
72565-}
72566-
72567-// fullyInstantiated reports whether all of t's type params have
72568-// specified type args.
72569-func (c *completer) fullyInstantiated(t *types.Named) bool {
72570-	tps := typeparams.ForNamed(t)
72571-	tas := typeparams.NamedTypeArgs(t)
72572-
72573-	if tps.Len() != tas.Len() {
72574-		return false
72575-	}
72576-
72577-	for i := 0; i < tas.Len(); i++ {
72578-		switch ta := tas.At(i).(type) {
72579-		case *typeparams.TypeParam:
72580-			// A *TypeParam only counts as specified if it is currently in
72581-			// scope (i.e. we are in a generic definition).
72582-			if !c.typeParamInScope(ta) {
72583-				return false
72584-			}
72585-		case *types.Named:
72586-			if !c.fullyInstantiated(ta) {
72587-				return false
72588-			}
72589-		}
72590-	}
72591-	return true
72592-}
72593-
72594-// typeParamInScope returns whether tp's object is in scope at c.pos.
72595-// This tells you whether you are in a generic definition and can
72596-// assume tp has been specified.
72597-func (c *completer) typeParamInScope(tp *typeparams.TypeParam) bool {
72598-	obj := tp.Obj()
72599-	if obj == nil {
72600-		return false
72601-	}
72602-
72603-	scope := c.innermostScope()
72604-	if scope == nil {
72605-		return false
72606-	}
72607-
72608-	_, foundObj := scope.LookupParent(obj.Name(), c.pos)
72609-	return obj == foundObj
72610-}
72611diff -urN a/gopls/internal/lsp/source/completion/package.go b/gopls/internal/lsp/source/completion/package.go
72612--- a/gopls/internal/lsp/source/completion/package.go	2000-01-01 00:00:00.000000000 -0000
72613+++ b/gopls/internal/lsp/source/completion/package.go	1970-01-01 00:00:00.000000000 +0000
72614@@ -1,351 +0,0 @@
72615-// Copyright 2020 The Go Authors. All rights reserved.
72616-// Use of this source code is governed by a BSD-style
72617-// license that can be found in the LICENSE file.
72618-
72619-package completion
72620-
72621-import (
72622-	"bytes"
72623-	"context"
72624-	"errors"
72625-	"fmt"
72626-	"go/ast"
72627-	"go/parser"
72628-	"go/scanner"
72629-	"go/token"
72630-	"go/types"
72631-	"path/filepath"
72632-	"strings"
72633-	"unicode"
72634-
72635-	"golang.org/x/tools/gopls/internal/lsp/protocol"
72636-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
72637-	"golang.org/x/tools/gopls/internal/lsp/source"
72638-	"golang.org/x/tools/gopls/internal/span"
72639-	"golang.org/x/tools/internal/fuzzy"
72640-)
72641-
72642-// packageClauseCompletions offers completions for a package declaration when
72643-// one is not present in the given file.
72644-func packageClauseCompletions(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle, position protocol.Position) ([]CompletionItem, *Selection, error) {
72645-	// We know that the AST for this file will be empty due to the missing
72646-	// package declaration, but parse it anyway to get a mapper.
72647-	// TODO(adonovan): opt: there's no need to parse just to get a mapper.
72648-	pgf, err := snapshot.ParseGo(ctx, fh, source.ParseFull)
72649-	if err != nil {
72650-		return nil, nil, err
72651-	}
72652-
72653-	offset, err := pgf.Mapper.PositionOffset(position)
72654-	if err != nil {
72655-		return nil, nil, err
72656-	}
72657-	surrounding, err := packageCompletionSurrounding(pgf, offset)
72658-	if err != nil {
72659-		return nil, nil, fmt.Errorf("invalid position for package completion: %w", err)
72660-	}
72661-
72662-	packageSuggestions, err := packageSuggestions(ctx, snapshot, fh.URI(), "")
72663-	if err != nil {
72664-		return nil, nil, err
72665-	}
72666-
72667-	var items []CompletionItem
72668-	for _, pkg := range packageSuggestions {
72669-		insertText := fmt.Sprintf("package %s", pkg.name)
72670-		items = append(items, CompletionItem{
72671-			Label:      insertText,
72672-			Kind:       protocol.ModuleCompletion,
72673-			InsertText: insertText,
72674-			Score:      pkg.score,
72675-		})
72676-	}
72677-
72678-	return items, surrounding, nil
72679-}
72680-
72681-// packageCompletionSurrounding returns surrounding for package completion if a
72682-// package completions can be suggested at a given cursor offset. A valid location
72683-// for package completion is above any declarations or import statements.
72684-func packageCompletionSurrounding(pgf *source.ParsedGoFile, offset int) (*Selection, error) {
72685-	m := pgf.Mapper
72686-	// If the file lacks a package declaration, the parser will return an empty
72687-	// AST. As a work-around, try to parse an expression from the file contents.
72688-	fset := token.NewFileSet()
72689-	expr, _ := parser.ParseExprFrom(fset, m.URI.Filename(), pgf.Src, parser.Mode(0))
72690-	if expr == nil {
72691-		return nil, fmt.Errorf("unparseable file (%s)", m.URI)
72692-	}
72693-	tok := fset.File(expr.Pos())
72694-	cursor := tok.Pos(offset)
72695-
72696-	// If we were able to parse out an identifier as the first expression from
72697-	// the file, it may be the beginning of a package declaration ("pack ").
72698-	// We can offer package completions if the cursor is in the identifier.
72699-	if name, ok := expr.(*ast.Ident); ok {
72700-		if cursor >= name.Pos() && cursor <= name.End() {
72701-			if !strings.HasPrefix(PACKAGE, name.Name) {
72702-				return nil, fmt.Errorf("cursor in non-matching ident")
72703-			}
72704-			return &Selection{
72705-				content: name.Name,
72706-				cursor:  cursor,
72707-				tokFile: tok,
72708-				start:   name.Pos(),
72709-				end:     name.End(),
72710-				mapper:  m,
72711-			}, nil
72712-		}
72713-	}
72714-
72715-	// The file is invalid, but it contains an expression that we were able to
72716-	// parse. We will use this expression to construct the cursor's
72717-	// "surrounding".
72718-
72719-	// First, consider the possibility that we have a valid "package" keyword
72720-	// with an empty package name ("package "). "package" is parsed as an
72721-	// *ast.BadDecl since it is a keyword. This logic would allow "package" to
72722-	// appear on any line of the file as long as it's the first code expression
72723-	// in the file.
72724-	lines := strings.Split(string(pgf.Src), "\n")
72725-	cursorLine := tok.Line(cursor)
72726-	if cursorLine <= 0 || cursorLine > len(lines) {
72727-		return nil, fmt.Errorf("invalid line number")
72728-	}
72729-	if safetoken.StartPosition(fset, expr.Pos()).Line == cursorLine {
72730-		words := strings.Fields(lines[cursorLine-1])
72731-		if len(words) > 0 && words[0] == PACKAGE {
72732-			content := PACKAGE
72733-			// Account for spaces if there are any.
72734-			if len(words) > 1 {
72735-				content += " "
72736-			}
72737-
72738-			start := expr.Pos()
72739-			end := token.Pos(int(expr.Pos()) + len(content) + 1)
72740-			// We have verified that we have a valid 'package' keyword as our
72741-			// first expression. Ensure that cursor is in this keyword or
72742-			// otherwise fallback to the general case.
72743-			if cursor >= start && cursor <= end {
72744-				return &Selection{
72745-					content: content,
72746-					cursor:  cursor,
72747-					tokFile: tok,
72748-					start:   start,
72749-					end:     end,
72750-					mapper:  m,
72751-				}, nil
72752-			}
72753-		}
72754-	}
72755-
72756-	// If the cursor is after the start of the expression, no package
72757-	// declaration will be valid.
72758-	if cursor > expr.Pos() {
72759-		return nil, fmt.Errorf("cursor after expression")
72760-	}
72761-
72762-	// If the cursor is in a comment, don't offer any completions.
72763-	if cursorInComment(tok, cursor, m.Content) {
72764-		return nil, fmt.Errorf("cursor in comment")
72765-	}
72766-
72767-	// The surrounding range in this case is the cursor.
72768-	return &Selection{
72769-		content: "",
72770-		tokFile: tok,
72771-		start:   cursor,
72772-		end:     cursor,
72773-		cursor:  cursor,
72774-		mapper:  m,
72775-	}, nil
72776-}
72777-
72778-func cursorInComment(file *token.File, cursor token.Pos, src []byte) bool {
72779-	var s scanner.Scanner
72780-	s.Init(file, src, func(_ token.Position, _ string) {}, scanner.ScanComments)
72781-	for {
72782-		pos, tok, lit := s.Scan()
72783-		if pos <= cursor && cursor <= token.Pos(int(pos)+len(lit)) {
72784-			return tok == token.COMMENT
72785-		}
72786-		if tok == token.EOF {
72787-			break
72788-		}
72789-	}
72790-	return false
72791-}
72792-
72793-// packageNameCompletions returns name completions for a package clause using
72794-// the current name as prefix.
72795-func (c *completer) packageNameCompletions(ctx context.Context, fileURI span.URI, name *ast.Ident) error {
72796-	cursor := int(c.pos - name.NamePos)
72797-	if cursor < 0 || cursor > len(name.Name) {
72798-		return errors.New("cursor is not in package name identifier")
72799-	}
72800-
72801-	c.completionContext.packageCompletion = true
72802-
72803-	prefix := name.Name[:cursor]
72804-	packageSuggestions, err := packageSuggestions(ctx, c.snapshot, fileURI, prefix)
72805-	if err != nil {
72806-		return err
72807-	}
72808-
72809-	for _, pkg := range packageSuggestions {
72810-		c.deepState.enqueue(pkg)
72811-	}
72812-	return nil
72813-}
72814-
72815-// packageSuggestions returns a list of packages from workspace packages that
72816-// have the given prefix and are used in the same directory as the given
72817-// file. This also includes test packages for these packages (<pkg>_test) and
72818-// the directory name itself.
72819-func packageSuggestions(ctx context.Context, snapshot source.Snapshot, fileURI span.URI, prefix string) (packages []candidate, err error) {
72820-	active, err := snapshot.ActiveMetadata(ctx)
72821-	if err != nil {
72822-		return nil, err
72823-	}
72824-
72825-	toCandidate := func(name string, score float64) candidate {
72826-		obj := types.NewPkgName(0, nil, name, types.NewPackage("", name))
72827-		return candidate{obj: obj, name: name, detail: name, score: score}
72828-	}
72829-
72830-	matcher := fuzzy.NewMatcher(prefix)
72831-
72832-	// Always try to suggest a main package
72833-	defer func() {
72834-		if score := float64(matcher.Score("main")); score > 0 {
72835-			packages = append(packages, toCandidate("main", score*lowScore))
72836-		}
72837-	}()
72838-
72839-	dirPath := filepath.Dir(fileURI.Filename())
72840-	dirName := filepath.Base(dirPath)
72841-	if !isValidDirName(dirName) {
72842-		return packages, nil
72843-	}
72844-	pkgName := convertDirNameToPkgName(dirName)
72845-
72846-	seenPkgs := make(map[source.PackageName]struct{})
72847-
72848-	// The `go` command by default only allows one package per directory but we
72849-	// support multiple package suggestions since gopls is build system agnostic.
72850-	for _, m := range active {
72851-		if m.Name == "main" || m.Name == "" {
72852-			continue
72853-		}
72854-		if _, ok := seenPkgs[m.Name]; ok {
72855-			continue
72856-		}
72857-
72858-		// Only add packages that are previously used in the current directory.
72859-		var relevantPkg bool
72860-		for _, uri := range m.CompiledGoFiles {
72861-			if filepath.Dir(uri.Filename()) == dirPath {
72862-				relevantPkg = true
72863-				break
72864-			}
72865-		}
72866-		if !relevantPkg {
72867-			continue
72868-		}
72869-
72870-		// Add a found package used in current directory as a high relevance
72871-		// suggestion and the test package for it as a medium relevance
72872-		// suggestion.
72873-		if score := float64(matcher.Score(string(m.Name))); score > 0 {
72874-			packages = append(packages, toCandidate(string(m.Name), score*highScore))
72875-		}
72876-		seenPkgs[m.Name] = struct{}{}
72877-
72878-		testPkgName := m.Name + "_test"
72879-		if _, ok := seenPkgs[testPkgName]; ok || strings.HasSuffix(string(m.Name), "_test") {
72880-			continue
72881-		}
72882-		if score := float64(matcher.Score(string(testPkgName))); score > 0 {
72883-			packages = append(packages, toCandidate(string(testPkgName), score*stdScore))
72884-		}
72885-		seenPkgs[testPkgName] = struct{}{}
72886-	}
72887-
72888-	// Add current directory name as a low relevance suggestion.
72889-	if _, ok := seenPkgs[pkgName]; !ok {
72890-		if score := float64(matcher.Score(string(pkgName))); score > 0 {
72891-			packages = append(packages, toCandidate(string(pkgName), score*lowScore))
72892-		}
72893-
72894-		testPkgName := pkgName + "_test"
72895-		if score := float64(matcher.Score(string(testPkgName))); score > 0 {
72896-			packages = append(packages, toCandidate(string(testPkgName), score*lowScore))
72897-		}
72898-	}
72899-
72900-	return packages, nil
72901-}
72902-
72903-// isValidDirName checks whether the passed directory name can be used in
72904-// a package path. Requirements for a package path can be found here:
72905-// https://golang.org/ref/mod#go-mod-file-ident.
72906-func isValidDirName(dirName string) bool {
72907-	if dirName == "" {
72908-		return false
72909-	}
72910-
72911-	for i, ch := range dirName {
72912-		if isLetter(ch) || isDigit(ch) {
72913-			continue
72914-		}
72915-		if i == 0 {
72916-			// Directory name can start only with '_'. '.' is not allowed in module paths.
72917-			// '-' and '~' are not allowed because elements of package paths must be
72918-			// safe command-line arguments.
72919-			if ch == '_' {
72920-				continue
72921-			}
72922-		} else {
72923-			// Modules path elements can't end with '.'
72924-			if isAllowedPunctuation(ch) && (i != len(dirName)-1 || ch != '.') {
72925-				continue
72926-			}
72927-		}
72928-
72929-		return false
72930-	}
72931-	return true
72932-}
72933-
72934-// convertDirNameToPkgName converts a valid directory name to a valid package name.
72935-// It leaves only letters and digits. All letters are mapped to lower case.
72936-func convertDirNameToPkgName(dirName string) source.PackageName {
72937-	var buf bytes.Buffer
72938-	for _, ch := range dirName {
72939-		switch {
72940-		case isLetter(ch):
72941-			buf.WriteRune(unicode.ToLower(ch))
72942-
72943-		case buf.Len() != 0 && isDigit(ch):
72944-			buf.WriteRune(ch)
72945-		}
72946-	}
72947-	return source.PackageName(buf.String())
72948-}
72949-
72950-// isLetter and isDigit allow only ASCII characters because
72951-// "Each path element is a non-empty string made of up ASCII letters,
72952-// ASCII digits, and limited ASCII punctuation"
72953-// (see https://golang.org/ref/mod#go-mod-file-ident).
72954-
72955-func isLetter(ch rune) bool {
72956-	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z'
72957-}
72958-
72959-func isDigit(ch rune) bool {
72960-	return '0' <= ch && ch <= '9'
72961-}
72962-
72963-func isAllowedPunctuation(ch rune) bool {
72964-	return ch == '_' || ch == '-' || ch == '~' || ch == '.'
72965-}
72966diff -urN a/gopls/internal/lsp/source/completion/package_test.go b/gopls/internal/lsp/source/completion/package_test.go
72967--- a/gopls/internal/lsp/source/completion/package_test.go	2000-01-01 00:00:00.000000000 -0000
72968+++ b/gopls/internal/lsp/source/completion/package_test.go	1970-01-01 00:00:00.000000000 +0000
72969@@ -1,81 +0,0 @@
72970-// Copyright 2021 The Go Authors. All rights reserved.
72971-// Use of this source code is governed by a BSD-style
72972-// license that can be found in the LICENSE file.
72973-
72974-package completion
72975-
72976-import (
72977-	"testing"
72978-
72979-	"golang.org/x/tools/gopls/internal/lsp/source"
72980-)
72981-
72982-func TestIsValidDirName(t *testing.T) {
72983-	tests := []struct {
72984-		dirName string
72985-		valid   bool
72986-	}{
72987-		{dirName: "", valid: false},
72988-		//
72989-		{dirName: "a", valid: true},
72990-		{dirName: "abcdef", valid: true},
72991-		{dirName: "AbCdEf", valid: true},
72992-		//
72993-		{dirName: "1a35", valid: true},
72994-		{dirName: "a16", valid: true},
72995-		//
72996-		{dirName: "_a", valid: true},
72997-		{dirName: "a_", valid: true},
72998-		//
72999-		{dirName: "~a", valid: false},
73000-		{dirName: "a~", valid: true},
73001-		//
73002-		{dirName: "-a", valid: false},
73003-		{dirName: "a-", valid: true},
73004-		//
73005-		{dirName: ".a", valid: false},
73006-		{dirName: "a.", valid: false},
73007-		//
73008-		{dirName: "a~_b--c.-e", valid: true},
73009-		{dirName: "~a~_b--c.-e", valid: false},
73010-		{dirName: "a~_b--c.-e--~", valid: true},
73011-		{dirName: "a~_b--2134dc42.-e6--~", valid: true},
73012-		{dirName: "abc`def", valid: false},
73013-		{dirName: "тест", valid: false},
73014-		{dirName: "你好", valid: false},
73015-	}
73016-	for _, tt := range tests {
73017-		valid := isValidDirName(tt.dirName)
73018-		if tt.valid != valid {
73019-			t.Errorf("%s: expected %v, got %v", tt.dirName, tt.valid, valid)
73020-		}
73021-	}
73022-}
73023-
73024-func TestConvertDirNameToPkgName(t *testing.T) {
73025-	tests := []struct {
73026-		dirName string
73027-		pkgName source.PackageName
73028-	}{
73029-		{dirName: "a", pkgName: "a"},
73030-		{dirName: "abcdef", pkgName: "abcdef"},
73031-		{dirName: "AbCdEf", pkgName: "abcdef"},
73032-		{dirName: "1a35", pkgName: "a35"},
73033-		{dirName: "14a35", pkgName: "a35"},
73034-		{dirName: "a16", pkgName: "a16"},
73035-		{dirName: "_a", pkgName: "a"},
73036-		{dirName: "a_", pkgName: "a"},
73037-		{dirName: "a~", pkgName: "a"},
73038-		{dirName: "a-", pkgName: "a"},
73039-		{dirName: "a~_b--c.-e", pkgName: "abce"},
73040-		{dirName: "a~_b--c.-e--~", pkgName: "abce"},
73041-		{dirName: "a~_b--2134dc42.-e6--~", pkgName: "ab2134dc42e6"},
73042-	}
73043-	for _, tt := range tests {
73044-		pkgName := convertDirNameToPkgName(tt.dirName)
73045-		if tt.pkgName != pkgName {
73046-			t.Errorf("%s: expected %v, got %v", tt.dirName, tt.pkgName, pkgName)
73047-			continue
73048-		}
73049-	}
73050-}
73051diff -urN a/gopls/internal/lsp/source/completion/postfix_snippets.go b/gopls/internal/lsp/source/completion/postfix_snippets.go
73052--- a/gopls/internal/lsp/source/completion/postfix_snippets.go	2000-01-01 00:00:00.000000000 -0000
73053+++ b/gopls/internal/lsp/source/completion/postfix_snippets.go	1970-01-01 00:00:00.000000000 +0000
73054@@ -1,471 +0,0 @@
73055-// Copyright 2020 The Go Authors. All rights reserved.
73056-// Use of this source code is governed by a BSD-style
73057-// license that can be found in the LICENSE file.
73058-
73059-package completion
73060-
73061-import (
73062-	"context"
73063-	"fmt"
73064-	"go/ast"
73065-	"go/token"
73066-	"go/types"
73067-	"log"
73068-	"reflect"
73069-	"strings"
73070-	"sync"
73071-	"text/template"
73072-
73073-	"golang.org/x/tools/gopls/internal/lsp/protocol"
73074-	"golang.org/x/tools/gopls/internal/lsp/snippet"
73075-	"golang.org/x/tools/gopls/internal/lsp/source"
73076-	"golang.org/x/tools/internal/event"
73077-	"golang.org/x/tools/internal/imports"
73078-)
73079-
73080-// Postfix snippets are artificial methods that allow the user to
73081-// compose common operations in an "argument oriented" fashion. For
73082-// example, instead of "sort.Slice(someSlice, ...)" a user can expand
73083-// "someSlice.sort!".
73084-
73085-// postfixTmpl represents a postfix snippet completion candidate.
73086-type postfixTmpl struct {
73087-	// label is the completion candidate's label presented to the user.
73088-	label string
73089-
73090-	// details is passed along to the client as the candidate's details.
73091-	details string
73092-
73093-	// body is the template text. See postfixTmplArgs for details on the
73094-	// facilities available to the template.
73095-	body string
73096-
73097-	tmpl *template.Template
73098-}
73099-
73100-// postfixTmplArgs are the template execution arguments available to
73101-// the postfix snippet templates.
73102-type postfixTmplArgs struct {
73103-	// StmtOK is true if it is valid to replace the selector with a
73104-	// statement. For example:
73105-	//
73106-	//    func foo() {
73107-	//      bar.sort! // statement okay
73108-	//
73109-	//      someMethod(bar.sort!) // statement not okay
73110-	//    }
73111-	StmtOK bool
73112-
73113-	// X is the textual SelectorExpr.X. For example, when completing
73114-	// "foo.bar.print!", "X" is "foo.bar".
73115-	X string
73116-
73117-	// Obj is the types.Object of SelectorExpr.X, if any.
73118-	Obj types.Object
73119-
73120-	// Type is the type of "foo.bar" in "foo.bar.print!".
73121-	Type types.Type
73122-
73123-	scope          *types.Scope
73124-	snip           snippet.Builder
73125-	importIfNeeded func(pkgPath string, scope *types.Scope) (name string, edits []protocol.TextEdit, err error)
73126-	edits          []protocol.TextEdit
73127-	qf             types.Qualifier
73128-	varNames       map[string]bool
73129-}
73130-
73131-var postfixTmpls = []postfixTmpl{{
73132-	label:   "sort",
73133-	details: "sort.Slice()",
73134-	body: `{{if and (eq .Kind "slice") .StmtOK -}}
73135-{{.Import "sort"}}.Slice({{.X}}, func({{.VarName nil "i"}}, {{.VarName nil "j"}} int) bool {
73136-	{{.Cursor}}
73137-})
73138-{{- end}}`,
73139-}, {
73140-	label:   "last",
73141-	details: "s[len(s)-1]",
73142-	body: `{{if and (eq .Kind "slice") .Obj -}}
73143-{{.X}}[len({{.X}})-1]
73144-{{- end}}`,
73145-}, {
73146-	label:   "reverse",
73147-	details: "reverse slice",
73148-	body: `{{if and (eq .Kind "slice") .StmtOK -}}
73149-{{$i := .VarName nil "i"}}{{$j := .VarName nil "j" -}}
73150-for {{$i}}, {{$j}} := 0, len({{.X}})-1; {{$i}} < {{$j}}; {{$i}}, {{$j}} = {{$i}}+1, {{$j}}-1 {
73151-	{{.X}}[{{$i}}], {{.X}}[{{$j}}] = {{.X}}[{{$j}}], {{.X}}[{{$i}}]
73152-}
73153-{{end}}`,
73154-}, {
73155-	label:   "range",
73156-	details: "range over slice",
73157-	body: `{{if and (eq .Kind "slice") .StmtOK -}}
73158-for {{.VarName nil "i"}}, {{.VarName .ElemType "v"}} := range {{.X}} {
73159-	{{.Cursor}}
73160-}
73161-{{- end}}`,
73162-}, {
73163-	label:   "append",
73164-	details: "append and re-assign slice",
73165-	body: `{{if and (eq .Kind "slice") .StmtOK .Obj -}}
73166-{{.X}} = append({{.X}}, {{.Cursor}})
73167-{{- end}}`,
73168-}, {
73169-	label:   "append",
73170-	details: "append to slice",
73171-	body: `{{if and (eq .Kind "slice") (not .StmtOK) -}}
73172-append({{.X}}, {{.Cursor}})
73173-{{- end}}`,
73174-}, {
73175-	label:   "copy",
73176-	details: "duplicate slice",
73177-	body: `{{if and (eq .Kind "slice") .StmtOK .Obj -}}
73178-{{$v := (.VarName nil (printf "%sCopy" .X))}}{{$v}} := make([]{{.TypeName .ElemType}}, len({{.X}}))
73179-copy({{$v}}, {{.X}})
73180-{{end}}`,
73181-}, {
73182-	label:   "range",
73183-	details: "range over map",
73184-	body: `{{if and (eq .Kind "map") .StmtOK -}}
73185-for {{.VarName .KeyType "k"}}, {{.VarName .ElemType "v"}} := range {{.X}} {
73186-	{{.Cursor}}
73187-}
73188-{{- end}}`,
73189-}, {
73190-	label:   "clear",
73191-	details: "clear map contents",
73192-	body: `{{if and (eq .Kind "map") .StmtOK -}}
73193-{{$k := (.VarName .KeyType "k")}}for {{$k}} := range {{.X}} {
73194-	delete({{.X}}, {{$k}})
73195-}
73196-{{end}}`,
73197-}, {
73198-	label:   "keys",
73199-	details: "create slice of keys",
73200-	body: `{{if and (eq .Kind "map") .StmtOK -}}
73201-{{$keysVar := (.VarName nil "keys")}}{{$keysVar}} := make([]{{.TypeName .KeyType}}, 0, len({{.X}}))
73202-{{$k := (.VarName .KeyType "k")}}for {{$k}} := range {{.X}} {
73203-	{{$keysVar}} = append({{$keysVar}}, {{$k}})
73204-}
73205-{{end}}`,
73206-}, {
73207-	label:   "range",
73208-	details: "range over channel",
73209-	body: `{{if and (eq .Kind "chan") .StmtOK -}}
73210-for {{.VarName .ElemType "e"}} := range {{.X}} {
73211-	{{.Cursor}}
73212-}
73213-{{- end}}`,
73214-}, {
73215-	label:   "var",
73216-	details: "assign to variables",
73217-	body: `{{if and (eq .Kind "tuple") .StmtOK -}}
73218-{{$a := .}}{{range $i, $v := .Tuple}}{{if $i}}, {{end}}{{$a.VarName $v.Type $v.Name}}{{end}} := {{.X}}
73219-{{- end}}`,
73220-}, {
73221-	label:   "var",
73222-	details: "assign to variable",
73223-	body: `{{if and (ne .Kind "tuple") .StmtOK -}}
73224-{{.VarName .Type ""}} := {{.X}}
73225-{{- end}}`,
73226-}, {
73227-	label:   "print",
73228-	details: "print to stdout",
73229-	body: `{{if and (ne .Kind "tuple") .StmtOK -}}
73230-{{.Import "fmt"}}.Printf("{{.EscapeQuotes .X}}: %v\n", {{.X}})
73231-{{- end}}`,
73232-}, {
73233-	label:   "print",
73234-	details: "print to stdout",
73235-	body: `{{if and (eq .Kind "tuple") .StmtOK -}}
73236-{{.Import "fmt"}}.Println({{.X}})
73237-{{- end}}`,
73238-}, {
73239-	label:   "split",
73240-	details: "split string",
73241-	body: `{{if (eq (.TypeName .Type) "string") -}}
73242-{{.Import "strings"}}.Split({{.X}}, "{{.Cursor}}")
73243-{{- end}}`,
73244-}, {
73245-	label:   "join",
73246-	details: "join string slice",
73247-	body: `{{if and (eq .Kind "slice") (eq (.TypeName .ElemType) "string") -}}
73248-{{.Import "strings"}}.Join({{.X}}, "{{.Cursor}}")
73249-{{- end}}`,
73250-}}
73251-
73252-// Cursor indicates where the client's cursor should end up after the
73253-// snippet is done.
73254-func (a *postfixTmplArgs) Cursor() string {
73255-	a.snip.WriteFinalTabstop()
73256-	return ""
73257-}
73258-
73259-// Import makes sure the package corresponding to path is imported,
73260-// returning the identifier to use to refer to the package.
73261-func (a *postfixTmplArgs) Import(path string) (string, error) {
73262-	name, edits, err := a.importIfNeeded(path, a.scope)
73263-	if err != nil {
73264-		return "", fmt.Errorf("couldn't import %q: %w", path, err)
73265-	}
73266-	a.edits = append(a.edits, edits...)
73267-	return name, nil
73268-}
73269-
73270-func (a *postfixTmplArgs) EscapeQuotes(v string) string {
73271-	return strings.ReplaceAll(v, `"`, `\\"`)
73272-}
73273-
73274-// ElemType returns the Elem() type of xType, if applicable.
73275-func (a *postfixTmplArgs) ElemType() types.Type {
73276-	if e, _ := a.Type.(interface{ Elem() types.Type }); e != nil {
73277-		return e.Elem()
73278-	}
73279-	return nil
73280-}
73281-
73282-// Kind returns the underlying kind of type, e.g. "slice", "struct",
73283-// etc.
73284-func (a *postfixTmplArgs) Kind() string {
73285-	t := reflect.TypeOf(a.Type.Underlying())
73286-	return strings.ToLower(strings.TrimPrefix(t.String(), "*types."))
73287-}
73288-
73289-// KeyType returns the type of X's key. KeyType panics if X is not a
73290-// map.
73291-func (a *postfixTmplArgs) KeyType() types.Type {
73292-	return a.Type.Underlying().(*types.Map).Key()
73293-}
73294-
73295-// Tuple returns the tuple result vars if X is a call expression.
73296-func (a *postfixTmplArgs) Tuple() []*types.Var {
73297-	tuple, _ := a.Type.(*types.Tuple)
73298-	if tuple == nil {
73299-		return nil
73300-	}
73301-
73302-	typs := make([]*types.Var, 0, tuple.Len())
73303-	for i := 0; i < tuple.Len(); i++ {
73304-		typs = append(typs, tuple.At(i))
73305-	}
73306-	return typs
73307-}
73308-
73309-// TypeName returns the textual representation of type t.
73310-func (a *postfixTmplArgs) TypeName(t types.Type) (string, error) {
73311-	if t == nil || t == types.Typ[types.Invalid] {
73312-		return "", fmt.Errorf("invalid type: %v", t)
73313-	}
73314-	return types.TypeString(t, a.qf), nil
73315-}
73316-
73317-// VarName returns a suitable variable name for the type t. If t
73318-// implements the error interface, "err" is used. If t is not a named
73319-// type then nonNamedDefault is used. Otherwise a name is made by
73320-// abbreviating the type name. If the resultant name is already in
73321-// scope, an integer is appended to make a unique name.
73322-func (a *postfixTmplArgs) VarName(t types.Type, nonNamedDefault string) string {
73323-	if t == nil {
73324-		t = types.Typ[types.Invalid]
73325-	}
73326-
73327-	var name string
73328-	// go/types predicates are undefined on types.Typ[types.Invalid].
73329-	if !types.Identical(t, types.Typ[types.Invalid]) && types.Implements(t, errorIntf) {
73330-		name = "err"
73331-	} else if _, isNamed := source.Deref(t).(*types.Named); !isNamed {
73332-		name = nonNamedDefault
73333-	}
73334-
73335-	if name == "" {
73336-		name = types.TypeString(t, func(p *types.Package) string {
73337-			return ""
73338-		})
73339-		name = abbreviateTypeName(name)
73340-	}
73341-
73342-	if dot := strings.LastIndex(name, "."); dot > -1 {
73343-		name = name[dot+1:]
73344-	}
73345-
73346-	uniqueName := name
73347-	for i := 2; ; i++ {
73348-		if s, _ := a.scope.LookupParent(uniqueName, token.NoPos); s == nil && !a.varNames[uniqueName] {
73349-			break
73350-		}
73351-		uniqueName = fmt.Sprintf("%s%d", name, i)
73352-	}
73353-
73354-	a.varNames[uniqueName] = true
73355-
73356-	return uniqueName
73357-}
73358-
73359-func (c *completer) addPostfixSnippetCandidates(ctx context.Context, sel *ast.SelectorExpr) {
73360-	if !c.opts.postfix {
73361-		return
73362-	}
73363-
73364-	initPostfixRules()
73365-
73366-	if sel == nil || sel.Sel == nil {
73367-		return
73368-	}
73369-
73370-	selType := c.pkg.GetTypesInfo().TypeOf(sel.X)
73371-	if selType == nil {
73372-		return
73373-	}
73374-
73375-	// Skip empty tuples since there is no value to operate on.
73376-	if tuple, ok := selType.Underlying().(*types.Tuple); ok && tuple == nil {
73377-		return
73378-	}
73379-
73380-	tokFile := c.pkg.FileSet().File(c.pos)
73381-
73382-	// Only replace sel with a statement if sel is already a statement.
73383-	var stmtOK bool
73384-	for i, n := range c.path {
73385-		if n == sel && i < len(c.path)-1 {
73386-			switch p := c.path[i+1].(type) {
73387-			case *ast.ExprStmt:
73388-				stmtOK = true
73389-			case *ast.AssignStmt:
73390-				// In cases like:
73391-				//
73392-				//   foo.<>
73393-				//   bar = 123
73394-				//
73395-				// detect that "foo." makes up the entire statement since the
73396-				// apparent selector spans lines.
73397-				stmtOK = tokFile.Line(c.pos) < tokFile.Line(p.TokPos)
73398-			}
73399-			break
73400-		}
73401-	}
73402-
73403-	scope := c.pkg.GetTypes().Scope().Innermost(c.pos)
73404-	if scope == nil {
73405-		return
73406-	}
73407-
73408-	// afterDot is the position after selector dot, e.g. "|" in
73409-	// "foo.|print".
73410-	afterDot := sel.Sel.Pos()
73411-
73412-	// We must detect dangling selectors such as:
73413-	//
73414-	//    foo.<>
73415-	//    bar
73416-	//
73417-	// and adjust afterDot so that we don't mistakenly delete the
73418-	// newline thinking "bar" is part of our selector.
73419-	if startLine := tokFile.Line(sel.Pos()); startLine != tokFile.Line(afterDot) {
73420-		if tokFile.Line(c.pos) != startLine {
73421-			return
73422-		}
73423-		afterDot = c.pos
73424-	}
73425-
73426-	for _, rule := range postfixTmpls {
73427-		// When completing foo.print<>, "print" is naturally overwritten,
73428-		// but we need to also remove "foo." so the snippet has a clean
73429-		// slate.
73430-		edits, err := c.editText(sel.Pos(), afterDot, "")
73431-		if err != nil {
73432-			event.Error(ctx, "error calculating postfix edits", err)
73433-			return
73434-		}
73435-
73436-		tmplArgs := postfixTmplArgs{
73437-			X:              source.FormatNode(c.pkg.FileSet(), sel.X),
73438-			StmtOK:         stmtOK,
73439-			Obj:            exprObj(c.pkg.GetTypesInfo(), sel.X),
73440-			Type:           selType,
73441-			qf:             c.qf,
73442-			importIfNeeded: c.importIfNeeded,
73443-			scope:          scope,
73444-			varNames:       make(map[string]bool),
73445-		}
73446-
73447-		// Feed the template straight into the snippet builder. This
73448-		// allows templates to build snippets as they are executed.
73449-		err = rule.tmpl.Execute(&tmplArgs.snip, &tmplArgs)
73450-		if err != nil {
73451-			event.Error(ctx, "error executing postfix template", err)
73452-			continue
73453-		}
73454-
73455-		if strings.TrimSpace(tmplArgs.snip.String()) == "" {
73456-			continue
73457-		}
73458-
73459-		score := c.matcher.Score(rule.label)
73460-		if score <= 0 {
73461-			continue
73462-		}
73463-
73464-		c.items = append(c.items, CompletionItem{
73465-			Label:               rule.label + "!",
73466-			Detail:              rule.details,
73467-			Score:               float64(score) * 0.01,
73468-			Kind:                protocol.SnippetCompletion,
73469-			snippet:             &tmplArgs.snip,
73470-			AdditionalTextEdits: append(edits, tmplArgs.edits...),
73471-		})
73472-	}
73473-}
73474-
73475-var postfixRulesOnce sync.Once
73476-
73477-func initPostfixRules() {
73478-	postfixRulesOnce.Do(func() {
73479-		var idx int
73480-		for _, rule := range postfixTmpls {
73481-			var err error
73482-			rule.tmpl, err = template.New("postfix_snippet").Parse(rule.body)
73483-			if err != nil {
73484-				log.Panicf("error parsing postfix snippet template: %v", err)
73485-			}
73486-			postfixTmpls[idx] = rule
73487-			idx++
73488-		}
73489-		postfixTmpls = postfixTmpls[:idx]
73490-	})
73491-}
73492-
73493-// importIfNeeded returns the package identifier and any necessary
73494-// edits to import package pkgPath.
73495-func (c *completer) importIfNeeded(pkgPath string, scope *types.Scope) (string, []protocol.TextEdit, error) {
73496-	defaultName := imports.ImportPathToAssumedName(pkgPath)
73497-
73498-	// Check if file already imports pkgPath.
73499-	for _, s := range c.file.Imports {
73500-		// TODO(adonovan): what if pkgPath has a vendor/ suffix?
73501-		// This may be the cause of go.dev/issue/56291.
73502-		if source.UnquoteImportPath(s) == source.ImportPath(pkgPath) {
73503-			if s.Name == nil {
73504-				return defaultName, nil, nil
73505-			}
73506-			if s.Name.Name != "_" {
73507-				return s.Name.Name, nil, nil
73508-			}
73509-		}
73510-	}
73511-
73512-	// Give up if the package's name is already in use by another object.
73513-	if _, obj := scope.LookupParent(defaultName, token.NoPos); obj != nil {
73514-		return "", nil, fmt.Errorf("import name %q of %q already in use", defaultName, pkgPath)
73515-	}
73516-
73517-	edits, err := c.importEdits(&importInfo{
73518-		importPath: pkgPath,
73519-	})
73520-	if err != nil {
73521-		return "", nil, err
73522-	}
73523-
73524-	return defaultName, edits, nil
73525-}
73526diff -urN a/gopls/internal/lsp/source/completion/printf.go b/gopls/internal/lsp/source/completion/printf.go
73527--- a/gopls/internal/lsp/source/completion/printf.go	2000-01-01 00:00:00.000000000 -0000
73528+++ b/gopls/internal/lsp/source/completion/printf.go	1970-01-01 00:00:00.000000000 +0000
73529@@ -1,172 +0,0 @@
73530-// Copyright 2020 The Go Authors. All rights reserved.
73531-// Use of this source code is governed by a BSD-style
73532-// license that can be found in the LICENSE file.
73533-
73534-package completion
73535-
73536-import (
73537-	"go/ast"
73538-	"go/constant"
73539-	"go/types"
73540-	"strconv"
73541-	"strings"
73542-	"unicode/utf8"
73543-)
73544-
73545-// printfArgKind returns the expected objKind when completing a
73546-// printf-like operand. call is the printf-like function call, and
73547-// argIdx is the index of call.Args being completed.
73548-func printfArgKind(info *types.Info, call *ast.CallExpr, argIdx int) objKind {
73549-	// Printf-like function name must end in "f".
73550-	fn := exprObj(info, call.Fun)
73551-	if fn == nil || !strings.HasSuffix(fn.Name(), "f") {
73552-		return kindAny
73553-	}
73554-
73555-	sig, _ := fn.Type().(*types.Signature)
73556-	if sig == nil {
73557-		return kindAny
73558-	}
73559-
73560-	// Must be variadic and take at least two params.
73561-	numParams := sig.Params().Len()
73562-	if !sig.Variadic() || numParams < 2 || argIdx < numParams-1 {
73563-		return kindAny
73564-	}
73565-
73566-	// Param preceding variadic args must be a (format) string.
73567-	if !types.Identical(sig.Params().At(numParams-2).Type(), types.Typ[types.String]) {
73568-		return kindAny
73569-	}
73570-
73571-	// Format string must be a constant.
73572-	strArg := info.Types[call.Args[numParams-2]].Value
73573-	if strArg == nil || strArg.Kind() != constant.String {
73574-		return kindAny
73575-	}
73576-
73577-	return formatOperandKind(constant.StringVal(strArg), argIdx-(numParams-1)+1)
73578-}
73579-
73580-// formatOperandKind returns the objKind corresponding to format's
73581-// operandIdx'th operand.
73582-func formatOperandKind(format string, operandIdx int) objKind {
73583-	var (
73584-		prevOperandIdx int
73585-		kind           = kindAny
73586-	)
73587-	for {
73588-		i := strings.Index(format, "%")
73589-		if i == -1 {
73590-			break
73591-		}
73592-
73593-		var operands []formatOperand
73594-		format, operands = parsePrintfVerb(format[i+1:], prevOperandIdx)
73595-
73596-		// Check if any this verb's operands correspond to our target
73597-		// operandIdx.
73598-		for _, v := range operands {
73599-			if v.idx == operandIdx {
73600-				if kind == kindAny {
73601-					kind = v.kind
73602-				} else if v.kind != kindAny {
73603-					// If multiple verbs refer to the same operand, take the
73604-					// intersection of their kinds.
73605-					kind &= v.kind
73606-				}
73607-			}
73608-
73609-			prevOperandIdx = v.idx
73610-		}
73611-	}
73612-	return kind
73613-}
73614-
73615-type formatOperand struct {
73616-	// idx is the one-based printf operand index.
73617-	idx int
73618-	// kind is a mask of expected kinds of objects for this operand.
73619-	kind objKind
73620-}
73621-
73622-// parsePrintfVerb parses the leading printf verb in f. The opening
73623-// "%" must already be trimmed from f. prevIdx is the previous
73624-// operand's index, or zero if this is the first verb. The format
73625-// string is returned with the leading verb removed. Multiple operands
73626-// can be returned in the case of dynamic widths such as "%*.*f".
73627-func parsePrintfVerb(f string, prevIdx int) (string, []formatOperand) {
73628-	var verbs []formatOperand
73629-
73630-	addVerb := func(k objKind) {
73631-		verbs = append(verbs, formatOperand{
73632-			idx:  prevIdx + 1,
73633-			kind: k,
73634-		})
73635-		prevIdx++
73636-	}
73637-
73638-	for len(f) > 0 {
73639-		// Trim first rune off of f so we are guaranteed to make progress.
73640-		r, l := utf8.DecodeRuneInString(f)
73641-		f = f[l:]
73642-
73643-		// We care about three things:
73644-		// 1. The verb, which maps directly to object kind.
73645-		// 2. Explicit operand indices like "%[2]s".
73646-		// 3. Dynamic widths using "*".
73647-		switch r {
73648-		case '%':
73649-			return f, nil
73650-		case '*':
73651-			addVerb(kindInt)
73652-			continue
73653-		case '[':
73654-			// Parse operand index as in "%[2]s".
73655-			i := strings.Index(f, "]")
73656-			if i == -1 {
73657-				return f, nil
73658-			}
73659-
73660-			idx, err := strconv.Atoi(f[:i])
73661-			f = f[i+1:]
73662-			if err != nil {
73663-				return f, nil
73664-			}
73665-
73666-			prevIdx = idx - 1
73667-			continue
73668-		case 'v', 'T':
73669-			addVerb(kindAny)
73670-		case 't':
73671-			addVerb(kindBool)
73672-		case 'c', 'd', 'o', 'O', 'U':
73673-			addVerb(kindInt)
73674-		case 'e', 'E', 'f', 'F', 'g', 'G':
73675-			addVerb(kindFloat | kindComplex)
73676-		case 'b':
73677-			addVerb(kindInt | kindFloat | kindComplex | kindBytes)
73678-		case 'q', 's':
73679-			addVerb(kindString | kindBytes | kindStringer | kindError)
73680-		case 'x', 'X':
73681-			// Omit kindStringer and kindError though technically allowed.
73682-			addVerb(kindString | kindBytes | kindInt | kindFloat | kindComplex)
73683-		case 'p':
73684-			addVerb(kindPtr | kindSlice)
73685-		case 'w':
73686-			addVerb(kindError)
73687-		case '+', '-', '#', ' ', '.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
73688-			// Flag or numeric width/precision value.
73689-			continue
73690-		default:
73691-			// Assume unrecognized rune is a custom fmt.Formatter verb.
73692-			addVerb(kindAny)
73693-		}
73694-
73695-		if len(verbs) > 0 {
73696-			break
73697-		}
73698-	}
73699-
73700-	return f, verbs
73701-}
73702diff -urN a/gopls/internal/lsp/source/completion/printf_test.go b/gopls/internal/lsp/source/completion/printf_test.go
73703--- a/gopls/internal/lsp/source/completion/printf_test.go	2000-01-01 00:00:00.000000000 -0000
73704+++ b/gopls/internal/lsp/source/completion/printf_test.go	1970-01-01 00:00:00.000000000 +0000
73705@@ -1,72 +0,0 @@
73706-// Copyright 2020 The Go Authors. All rights reserved.
73707-// Use of this source code is governed by a BSD-style
73708-// license that can be found in the LICENSE file.
73709-
73710-package completion
73711-
73712-import (
73713-	"fmt"
73714-	"testing"
73715-)
73716-
73717-func TestFormatOperandKind(t *testing.T) {
73718-	cases := []struct {
73719-		f    string
73720-		idx  int
73721-		kind objKind
73722-	}{
73723-		{"", 1, kindAny},
73724-		{"%", 1, kindAny},
73725-		{"%%%", 1, kindAny},
73726-		{"%[1", 1, kindAny},
73727-		{"%[?%s", 2, kindAny},
73728-		{"%[abc]v", 1, kindAny},
73729-
73730-		{"%v", 1, kindAny},
73731-		{"%T", 1, kindAny},
73732-		{"%t", 1, kindBool},
73733-		{"%d", 1, kindInt},
73734-		{"%c", 1, kindInt},
73735-		{"%o", 1, kindInt},
73736-		{"%O", 1, kindInt},
73737-		{"%U", 1, kindInt},
73738-		{"%e", 1, kindFloat | kindComplex},
73739-		{"%E", 1, kindFloat | kindComplex},
73740-		{"%f", 1, kindFloat | kindComplex},
73741-		{"%F", 1, kindFloat | kindComplex},
73742-		{"%g", 1, kindFloat | kindComplex},
73743-		{"%G", 1, kindFloat | kindComplex},
73744-		{"%b", 1, kindInt | kindFloat | kindComplex | kindBytes},
73745-		{"%q", 1, kindString | kindBytes | kindStringer | kindError},
73746-		{"%s", 1, kindString | kindBytes | kindStringer | kindError},
73747-		{"%x", 1, kindString | kindBytes | kindInt | kindFloat | kindComplex},
73748-		{"%X", 1, kindString | kindBytes | kindInt | kindFloat | kindComplex},
73749-		{"%p", 1, kindPtr | kindSlice},
73750-		{"%w", 1, kindError},
73751-
73752-		{"%1.2f", 1, kindFloat | kindComplex},
73753-		{"%*f", 1, kindInt},
73754-		{"%*f", 2, kindFloat | kindComplex},
73755-		{"%*.*f", 1, kindInt},
73756-		{"%*.*f", 2, kindInt},
73757-		{"%*.*f", 3, kindFloat | kindComplex},
73758-		{"%[3]*.[2]*[1]f", 1, kindFloat | kindComplex},
73759-		{"%[3]*.[2]*[1]f", 2, kindInt},
73760-		{"%[3]*.[2]*[1]f", 3, kindInt},
73761-
73762-		{"foo %% %d", 1, kindInt},
73763-		{"%#-12.34f", 1, kindFloat | kindComplex},
73764-		{"% d", 1, kindInt},
73765-
73766-		{"%s %[1]X %d", 1, kindString | kindBytes},
73767-		{"%s %[1]X %d", 2, kindInt},
73768-	}
73769-
73770-	for _, c := range cases {
73771-		t.Run(fmt.Sprintf("%q#%d", c.f, c.idx), func(t *testing.T) {
73772-			if got := formatOperandKind(c.f, c.idx); got != c.kind {
73773-				t.Errorf("expected %d (%[1]b), got %d (%[2]b)", c.kind, got)
73774-			}
73775-		})
73776-	}
73777-}
73778diff -urN a/gopls/internal/lsp/source/completion/snippet.go b/gopls/internal/lsp/source/completion/snippet.go
73779--- a/gopls/internal/lsp/source/completion/snippet.go	2000-01-01 00:00:00.000000000 -0000
73780+++ b/gopls/internal/lsp/source/completion/snippet.go	1970-01-01 00:00:00.000000000 +0000
73781@@ -1,116 +0,0 @@
73782-// Copyright 2019 The Go Authors. All rights reserved.
73783-// Use of this source code is governed by a BSD-style
73784-// license that can be found in the LICENSE file.
73785-
73786-package completion
73787-
73788-import (
73789-	"go/ast"
73790-
73791-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
73792-	"golang.org/x/tools/gopls/internal/lsp/snippet"
73793-)
73794-
73795-// structFieldSnippet calculates the snippet for struct literal field names.
73796-func (c *completer) structFieldSnippet(cand candidate, detail string, snip *snippet.Builder) {
73797-	if !c.wantStructFieldCompletions() {
73798-		return
73799-	}
73800-
73801-	// If we are in a deep completion then we can't be completing a field
73802-	// name (e.g. "Foo{f<>}" completing to "Foo{f.Bar}" should not generate
73803-	// a snippet).
73804-	if len(cand.path) > 0 {
73805-		return
73806-	}
73807-
73808-	clInfo := c.enclosingCompositeLiteral
73809-
73810-	// If we are already in a key-value expression, we don't want a snippet.
73811-	if clInfo.kv != nil {
73812-		return
73813-	}
73814-
73815-	// A plain snippet turns "Foo{Ba<>" into "Foo{Bar: <>".
73816-	snip.WriteText(": ")
73817-	snip.WritePlaceholder(func(b *snippet.Builder) {
73818-		// A placeholder snippet turns "Foo{Ba<>" into "Foo{Bar: <*int*>".
73819-		if c.opts.placeholders {
73820-			b.WriteText(detail)
73821-		}
73822-	})
73823-
73824-	fset := c.pkg.FileSet()
73825-
73826-	// If the cursor position is on a different line from the literal's opening brace,
73827-	// we are in a multiline literal. Ignore line directives.
73828-	if safetoken.StartPosition(fset, c.pos).Line != safetoken.StartPosition(fset, clInfo.cl.Lbrace).Line {
73829-		snip.WriteText(",")
73830-	}
73831-}
73832-
73833-// functionCallSnippet calculates the snippet for function calls.
73834-func (c *completer) functionCallSnippet(name string, tparams, params []string, snip *snippet.Builder) {
73835-	// If there is no suffix then we need to reuse existing call parens
73836-	// "()" if present. If there is an identifier suffix then we always
73837-	// need to include "()" since we don't overwrite the suffix.
73838-	if c.surrounding != nil && c.surrounding.Suffix() == "" && len(c.path) > 1 {
73839-		// If we are the left side (i.e. "Fun") part of a call expression,
73840-		// we don't want a snippet since there are already parens present.
73841-		switch n := c.path[1].(type) {
73842-		case *ast.CallExpr:
73843-			// The Lparen != Rparen check detects fudged CallExprs we
73844-			// inserted when fixing the AST. In this case, we do still need
73845-			// to insert the calling "()" parens.
73846-			if n.Fun == c.path[0] && n.Lparen != n.Rparen {
73847-				return
73848-			}
73849-		case *ast.SelectorExpr:
73850-			if len(c.path) > 2 {
73851-				if call, ok := c.path[2].(*ast.CallExpr); ok && call.Fun == c.path[1] && call.Lparen != call.Rparen {
73852-					return
73853-				}
73854-			}
73855-		}
73856-	}
73857-
73858-	snip.WriteText(name)
73859-
73860-	if len(tparams) > 0 {
73861-		snip.WriteText("[")
73862-		if c.opts.placeholders {
73863-			for i, tp := range tparams {
73864-				if i > 0 {
73865-					snip.WriteText(", ")
73866-				}
73867-				snip.WritePlaceholder(func(b *snippet.Builder) {
73868-					b.WriteText(tp)
73869-				})
73870-			}
73871-		} else {
73872-			snip.WritePlaceholder(nil)
73873-		}
73874-		snip.WriteText("]")
73875-	}
73876-
73877-	snip.WriteText("(")
73878-
73879-	if c.opts.placeholders {
73880-		// A placeholder snippet turns "someFun<>" into "someFunc(<*i int*>, *s string*)".
73881-		for i, p := range params {
73882-			if i > 0 {
73883-				snip.WriteText(", ")
73884-			}
73885-			snip.WritePlaceholder(func(b *snippet.Builder) {
73886-				b.WriteText(p)
73887-			})
73888-		}
73889-	} else {
73890-		// A plain snippet turns "someFun<>" into "someFunc(<>)".
73891-		if len(params) > 0 {
73892-			snip.WritePlaceholder(nil)
73893-		}
73894-	}
73895-
73896-	snip.WriteText(")")
73897-}
73898diff -urN a/gopls/internal/lsp/source/completion/statements.go b/gopls/internal/lsp/source/completion/statements.go
73899--- a/gopls/internal/lsp/source/completion/statements.go	2000-01-01 00:00:00.000000000 -0000
73900+++ b/gopls/internal/lsp/source/completion/statements.go	1970-01-01 00:00:00.000000000 +0000
73901@@ -1,361 +0,0 @@
73902-// Copyright 2020 The Go Authors. All rights reserved.
73903-// Use of this source code is governed by a BSD-style
73904-// license that can be found in the LICENSE file.
73905-
73906-package completion
73907-
73908-import (
73909-	"fmt"
73910-	"go/ast"
73911-	"go/token"
73912-	"go/types"
73913-
73914-	"golang.org/x/tools/gopls/internal/lsp/protocol"
73915-	"golang.org/x/tools/gopls/internal/lsp/snippet"
73916-	"golang.org/x/tools/gopls/internal/lsp/source"
73917-)
73918-
73919-// addStatementCandidates adds full statement completion candidates
73920-// appropriate for the current context.
73921-func (c *completer) addStatementCandidates() {
73922-	c.addErrCheck()
73923-	c.addAssignAppend()
73924-}
73925-
73926-// addAssignAppend offers a completion candidate of the form:
73927-//
73928-//	someSlice = append(someSlice, )
73929-//
73930-// It will offer the "append" completion in either of two situations:
73931-//
73932-//  1. Position is in RHS of assign, prefix matches "append", and
73933-//     corresponding LHS object is a slice. For example,
73934-//     "foo = ap<>" completes to "foo = append(foo, )".
73935-//
73936-//  2. Prefix is an ident or selector in an *ast.ExprStmt (i.e.
73937-//     beginning of statement), and our best matching candidate is a
73938-//     slice. For example: "foo.ba" completes to "foo.bar = append(foo.bar, )".
73939-func (c *completer) addAssignAppend() {
73940-	if len(c.path) < 3 {
73941-		return
73942-	}
73943-
73944-	ident, _ := c.path[0].(*ast.Ident)
73945-	if ident == nil {
73946-		return
73947-	}
73948-
73949-	var (
73950-		// sliceText is the full name of our slice object, e.g. "s.abc" in
73951-		// "s.abc = app<>".
73952-		sliceText string
73953-		// needsLHS is true if we need to prepend the LHS slice name and
73954-		// "=" to our candidate.
73955-		needsLHS = false
73956-		fset     = c.pkg.FileSet()
73957-	)
73958-
73959-	switch n := c.path[1].(type) {
73960-	case *ast.AssignStmt:
73961-		// We are already in an assignment. Make sure our prefix matches "append".
73962-		if c.matcher.Score("append") <= 0 {
73963-			return
73964-		}
73965-
73966-		exprIdx := exprAtPos(c.pos, n.Rhs)
73967-		if exprIdx == len(n.Rhs) || exprIdx > len(n.Lhs)-1 {
73968-			return
73969-		}
73970-
73971-		lhsType := c.pkg.GetTypesInfo().TypeOf(n.Lhs[exprIdx])
73972-		if lhsType == nil {
73973-			return
73974-		}
73975-
73976-		// Make sure our corresponding LHS object is a slice.
73977-		if _, isSlice := lhsType.Underlying().(*types.Slice); !isSlice {
73978-			return
73979-		}
73980-
73981-		// The name or our slice is whatever's in the LHS expression.
73982-		sliceText = source.FormatNode(fset, n.Lhs[exprIdx])
73983-	case *ast.SelectorExpr:
73984-		// Make sure we are a selector at the beginning of a statement.
73985-		if _, parentIsExprtStmt := c.path[2].(*ast.ExprStmt); !parentIsExprtStmt {
73986-			return
73987-		}
73988-
73989-		// So far we only know the first part of our slice name. For
73990-		// example in "s.a<>" we only know our slice begins with "s."
73991-		// since the user could still be typing.
73992-		sliceText = source.FormatNode(fset, n.X) + "."
73993-		needsLHS = true
73994-	case *ast.ExprStmt:
73995-		needsLHS = true
73996-	default:
73997-		return
73998-	}
73999-
74000-	var (
74001-		label string
74002-		snip  snippet.Builder
74003-		score = highScore
74004-	)
74005-
74006-	if needsLHS {
74007-		// Offer the long form assign + append candidate if our best
74008-		// candidate is a slice.
74009-		bestItem := c.topCandidate()
74010-		if bestItem == nil || !bestItem.isSlice {
74011-			return
74012-		}
74013-
74014-		// Don't rank the full form assign + append candidate above the
74015-		// slice itself.
74016-		score = bestItem.Score - 0.01
74017-
74018-		// Fill in rest of sliceText now that we have the object name.
74019-		sliceText += bestItem.Label
74020-
74021-		// Fill in the candidate's LHS bits.
74022-		label = fmt.Sprintf("%s = ", bestItem.Label)
74023-		snip.WriteText(label)
74024-	}
74025-
74026-	snip.WriteText(fmt.Sprintf("append(%s, ", sliceText))
74027-	snip.WritePlaceholder(nil)
74028-	snip.WriteText(")")
74029-
74030-	c.items = append(c.items, CompletionItem{
74031-		Label:   label + fmt.Sprintf("append(%s, )", sliceText),
74032-		Kind:    protocol.FunctionCompletion,
74033-		Score:   score,
74034-		snippet: &snip,
74035-	})
74036-}
74037-
74038-// topCandidate returns the strictly highest scoring candidate
74039-// collected so far. If the top two candidates have the same score,
74040-// nil is returned.
74041-func (c *completer) topCandidate() *CompletionItem {
74042-	var bestItem, secondBestItem *CompletionItem
74043-	for i := range c.items {
74044-		if bestItem == nil || c.items[i].Score > bestItem.Score {
74045-			bestItem = &c.items[i]
74046-		} else if secondBestItem == nil || c.items[i].Score > secondBestItem.Score {
74047-			secondBestItem = &c.items[i]
74048-		}
74049-	}
74050-
74051-	// If secondBestItem has the same score, bestItem isn't
74052-	// the strict best.
74053-	if secondBestItem != nil && secondBestItem.Score == bestItem.Score {
74054-		return nil
74055-	}
74056-
74057-	return bestItem
74058-}
74059-
74060-// addErrCheck offers a completion candidate of the form:
74061-//
74062-//	if err != nil {
74063-//	  return nil, err
74064-//	}
74065-//
74066-// In the case of test functions, it offers a completion candidate of the form:
74067-//
74068-//	if err != nil {
74069-//	  t.Fatal(err)
74070-//	}
74071-//
74072-// The position must be in a function that returns an error, and the
74073-// statement preceding the position must be an assignment where the
74074-// final LHS object is an error. addErrCheck will synthesize
74075-// zero values as necessary to make the return statement valid.
74076-func (c *completer) addErrCheck() {
74077-	if len(c.path) < 2 || c.enclosingFunc == nil || !c.opts.placeholders {
74078-		return
74079-	}
74080-
74081-	var (
74082-		errorType        = types.Universe.Lookup("error").Type()
74083-		result           = c.enclosingFunc.sig.Results()
74084-		testVar          = getTestVar(c.enclosingFunc, c.pkg)
74085-		isTest           = testVar != ""
74086-		doesNotReturnErr = result.Len() == 0 || !types.Identical(result.At(result.Len()-1).Type(), errorType)
74087-	)
74088-	// Make sure our enclosing function is a Test func or returns an error.
74089-	if !isTest && doesNotReturnErr {
74090-		return
74091-	}
74092-
74093-	prevLine := prevStmt(c.pos, c.path)
74094-	if prevLine == nil {
74095-		return
74096-	}
74097-
74098-	// Make sure our preceding statement was as assignment.
74099-	assign, _ := prevLine.(*ast.AssignStmt)
74100-	if assign == nil || len(assign.Lhs) == 0 {
74101-		return
74102-	}
74103-
74104-	lastAssignee := assign.Lhs[len(assign.Lhs)-1]
74105-
74106-	// Make sure the final assignee is an error.
74107-	if !types.Identical(c.pkg.GetTypesInfo().TypeOf(lastAssignee), errorType) {
74108-		return
74109-	}
74110-
74111-	var (
74112-		// errVar is e.g. "err" in "foo, err := bar()".
74113-		errVar = source.FormatNode(c.pkg.FileSet(), lastAssignee)
74114-
74115-		// Whether we need to include the "if" keyword in our candidate.
74116-		needsIf = true
74117-	)
74118-
74119-	// If the returned error from the previous statement is "_", it is not a real object.
74120-	// If we don't have an error, and the function signature takes a testing.TB that is either ignored
74121-	// or an "_", then we also can't call t.Fatal(err).
74122-	if errVar == "_" {
74123-		return
74124-	}
74125-
74126-	// Below we try to detect if the user has already started typing "if
74127-	// err" so we can replace what they've typed with our complete
74128-	// statement.
74129-	switch n := c.path[0].(type) {
74130-	case *ast.Ident:
74131-		switch c.path[1].(type) {
74132-		case *ast.ExprStmt:
74133-			// This handles:
74134-			//
74135-			//     f, err := os.Open("foo")
74136-			//     i<>
74137-
74138-			// Make sure they are typing "if".
74139-			if c.matcher.Score("if") <= 0 {
74140-				return
74141-			}
74142-		case *ast.IfStmt:
74143-			// This handles:
74144-			//
74145-			//     f, err := os.Open("foo")
74146-			//     if er<>
74147-
74148-			// Make sure they are typing the error's name.
74149-			if c.matcher.Score(errVar) <= 0 {
74150-				return
74151-			}
74152-
74153-			needsIf = false
74154-		default:
74155-			return
74156-		}
74157-	case *ast.IfStmt:
74158-		// This handles:
74159-		//
74160-		//     f, err := os.Open("foo")
74161-		//     if <>
74162-
74163-		// Avoid false positives by ensuring the if's cond is a bad
74164-		// expression. For example, don't offer the completion in cases
74165-		// like "if <> somethingElse".
74166-		if _, bad := n.Cond.(*ast.BadExpr); !bad {
74167-			return
74168-		}
74169-
74170-		// If "if" is our direct prefix, we need to include it in our
74171-		// candidate since the existing "if" will be overwritten.
74172-		needsIf = c.pos == n.Pos()+token.Pos(len("if"))
74173-	}
74174-
74175-	// Build up a snippet that looks like:
74176-	//
74177-	//     if err != nil {
74178-	//       return <zero value>, ..., ${1:err}
74179-	//     }
74180-	//
74181-	// We make the error a placeholder so it is easy to alter the error.
74182-	var snip snippet.Builder
74183-	if needsIf {
74184-		snip.WriteText("if ")
74185-	}
74186-	snip.WriteText(fmt.Sprintf("%s != nil {\n\t", errVar))
74187-
74188-	var label string
74189-	if isTest {
74190-		snip.WriteText(fmt.Sprintf("%s.Fatal(%s)", testVar, errVar))
74191-		label = fmt.Sprintf("%[1]s != nil { %[2]s.Fatal(%[1]s) }", errVar, testVar)
74192-	} else {
74193-		snip.WriteText("return ")
74194-		for i := 0; i < result.Len()-1; i++ {
74195-			snip.WriteText(formatZeroValue(result.At(i).Type(), c.qf))
74196-			snip.WriteText(", ")
74197-		}
74198-		snip.WritePlaceholder(func(b *snippet.Builder) {
74199-			b.WriteText(errVar)
74200-		})
74201-		label = fmt.Sprintf("%[1]s != nil { return %[1]s }", errVar)
74202-	}
74203-
74204-	snip.WriteText("\n}")
74205-
74206-	if needsIf {
74207-		label = "if " + label
74208-	}
74209-
74210-	c.items = append(c.items, CompletionItem{
74211-		Label: label,
74212-		// There doesn't seem to be a more appropriate kind.
74213-		Kind:    protocol.KeywordCompletion,
74214-		Score:   highScore,
74215-		snippet: &snip,
74216-	})
74217-}
74218-
74219-// getTestVar checks the function signature's input parameters and returns
74220-// the name of the first parameter that implements "testing.TB". For example,
74221-// func someFunc(t *testing.T) returns the string "t", func someFunc(b *testing.B)
74222-// returns "b" etc. An empty string indicates that the function signature
74223-// does not take a testing.TB parameter or does so but is ignored such
74224-// as func someFunc(*testing.T).
74225-func getTestVar(enclosingFunc *funcInfo, pkg source.Package) string {
74226-	if enclosingFunc == nil || enclosingFunc.sig == nil {
74227-		return ""
74228-	}
74229-
74230-	var testingPkg *types.Package
74231-	for _, p := range pkg.GetTypes().Imports() {
74232-		if p.Path() == "testing" {
74233-			testingPkg = p
74234-			break
74235-		}
74236-	}
74237-	if testingPkg == nil {
74238-		return ""
74239-	}
74240-	tbObj := testingPkg.Scope().Lookup("TB")
74241-	if tbObj == nil {
74242-		return ""
74243-	}
74244-	iface, ok := tbObj.Type().Underlying().(*types.Interface)
74245-	if !ok {
74246-		return ""
74247-	}
74248-
74249-	sig := enclosingFunc.sig
74250-	for i := 0; i < sig.Params().Len(); i++ {
74251-		param := sig.Params().At(i)
74252-		if param.Name() == "_" {
74253-			continue
74254-		}
74255-		if !types.Implements(param.Type(), iface) {
74256-			continue
74257-		}
74258-		return param.Name()
74259-	}
74260-
74261-	return ""
74262-}
74263diff -urN a/gopls/internal/lsp/source/completion/util.go b/gopls/internal/lsp/source/completion/util.go
74264--- a/gopls/internal/lsp/source/completion/util.go	2000-01-01 00:00:00.000000000 -0000
74265+++ b/gopls/internal/lsp/source/completion/util.go	1970-01-01 00:00:00.000000000 +0000
74266@@ -1,344 +0,0 @@
74267-// Copyright 2020 The Go Authors. All rights reserved.
74268-// Use of this source code is governed by a BSD-style
74269-// license that can be found in the LICENSE file.
74270-
74271-package completion
74272-
74273-import (
74274-	"go/ast"
74275-	"go/token"
74276-	"go/types"
74277-
74278-	"golang.org/x/tools/go/types/typeutil"
74279-	"golang.org/x/tools/gopls/internal/lsp/protocol"
74280-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
74281-	"golang.org/x/tools/gopls/internal/lsp/source"
74282-	"golang.org/x/tools/internal/diff"
74283-	"golang.org/x/tools/internal/typeparams"
74284-)
74285-
74286-// exprAtPos returns the index of the expression containing pos.
74287-func exprAtPos(pos token.Pos, args []ast.Expr) int {
74288-	for i, expr := range args {
74289-		if expr.Pos() <= pos && pos <= expr.End() {
74290-			return i
74291-		}
74292-	}
74293-	return len(args)
74294-}
74295-
74296-// eachField invokes fn for each field that can be selected from a
74297-// value of type T.
74298-func eachField(T types.Type, fn func(*types.Var)) {
74299-	// TODO(adonovan): this algorithm doesn't exclude ambiguous
74300-	// selections that match more than one field/method.
74301-	// types.NewSelectionSet should do that for us.
74302-
74303-	// for termination on recursive types
74304-	var seen typeutil.Map
74305-
74306-	var visit func(T types.Type)
74307-	visit = func(T types.Type) {
74308-		if T, ok := source.Deref(T).Underlying().(*types.Struct); ok {
74309-			if seen.At(T) != nil {
74310-				return
74311-			}
74312-
74313-			for i := 0; i < T.NumFields(); i++ {
74314-				f := T.Field(i)
74315-				fn(f)
74316-				if f.Anonymous() {
74317-					seen.Set(T, true)
74318-					visit(f.Type())
74319-				}
74320-			}
74321-		}
74322-	}
74323-	visit(T)
74324-}
74325-
74326-// typeIsValid reports whether typ doesn't contain any Invalid types.
74327-func typeIsValid(typ types.Type) bool {
74328-	// Check named types separately, because we don't want
74329-	// to call Underlying() on them to avoid problems with recursive types.
74330-	if _, ok := typ.(*types.Named); ok {
74331-		return true
74332-	}
74333-
74334-	switch typ := typ.Underlying().(type) {
74335-	case *types.Basic:
74336-		return typ.Kind() != types.Invalid
74337-	case *types.Array:
74338-		return typeIsValid(typ.Elem())
74339-	case *types.Slice:
74340-		return typeIsValid(typ.Elem())
74341-	case *types.Pointer:
74342-		return typeIsValid(typ.Elem())
74343-	case *types.Map:
74344-		return typeIsValid(typ.Key()) && typeIsValid(typ.Elem())
74345-	case *types.Chan:
74346-		return typeIsValid(typ.Elem())
74347-	case *types.Signature:
74348-		return typeIsValid(typ.Params()) && typeIsValid(typ.Results())
74349-	case *types.Tuple:
74350-		for i := 0; i < typ.Len(); i++ {
74351-			if !typeIsValid(typ.At(i).Type()) {
74352-				return false
74353-			}
74354-		}
74355-		return true
74356-	case *types.Struct, *types.Interface:
74357-		// Don't bother checking structs, interfaces for validity.
74358-		return true
74359-	default:
74360-		return false
74361-	}
74362-}
74363-
74364-// resolveInvalid traverses the node of the AST that defines the scope
74365-// containing the declaration of obj, and attempts to find a user-friendly
74366-// name for its invalid type. The resulting Object and its Type are fake.
74367-func resolveInvalid(fset *token.FileSet, obj types.Object, node ast.Node, info *types.Info) types.Object {
74368-	var resultExpr ast.Expr
74369-	ast.Inspect(node, func(node ast.Node) bool {
74370-		switch n := node.(type) {
74371-		case *ast.ValueSpec:
74372-			for _, name := range n.Names {
74373-				if info.Defs[name] == obj {
74374-					resultExpr = n.Type
74375-				}
74376-			}
74377-			return false
74378-		case *ast.Field: // This case handles parameters and results of a FuncDecl or FuncLit.
74379-			for _, name := range n.Names {
74380-				if info.Defs[name] == obj {
74381-					resultExpr = n.Type
74382-				}
74383-			}
74384-			return false
74385-		default:
74386-			return true
74387-		}
74388-	})
74389-	// Construct a fake type for the object and return a fake object with this type.
74390-	typename := source.FormatNode(fset, resultExpr)
74391-	typ := types.NewNamed(types.NewTypeName(token.NoPos, obj.Pkg(), typename, nil), types.Typ[types.Invalid], nil)
74392-	return types.NewVar(obj.Pos(), obj.Pkg(), obj.Name(), typ)
74393-}
74394-
74395-func isPointer(T types.Type) bool {
74396-	_, ok := T.(*types.Pointer)
74397-	return ok
74398-}
74399-
74400-func isVar(obj types.Object) bool {
74401-	_, ok := obj.(*types.Var)
74402-	return ok
74403-}
74404-
74405-func isTypeName(obj types.Object) bool {
74406-	_, ok := obj.(*types.TypeName)
74407-	return ok
74408-}
74409-
74410-func isFunc(obj types.Object) bool {
74411-	_, ok := obj.(*types.Func)
74412-	return ok
74413-}
74414-
74415-func isEmptyInterface(T types.Type) bool {
74416-	intf, _ := T.(*types.Interface)
74417-	return intf != nil && intf.NumMethods() == 0 && typeparams.IsMethodSet(intf)
74418-}
74419-
74420-func isUntyped(T types.Type) bool {
74421-	if basic, ok := T.(*types.Basic); ok {
74422-		return basic.Info()&types.IsUntyped > 0
74423-	}
74424-	return false
74425-}
74426-
74427-func isPkgName(obj types.Object) bool {
74428-	_, ok := obj.(*types.PkgName)
74429-	return ok
74430-}
74431-
74432-func isASTFile(n ast.Node) bool {
74433-	_, ok := n.(*ast.File)
74434-	return ok
74435-}
74436-
74437-func deslice(T types.Type) types.Type {
74438-	if slice, ok := T.Underlying().(*types.Slice); ok {
74439-		return slice.Elem()
74440-	}
74441-	return nil
74442-}
74443-
74444-// isSelector returns the enclosing *ast.SelectorExpr when pos is in the
74445-// selector.
74446-func enclosingSelector(path []ast.Node, pos token.Pos) *ast.SelectorExpr {
74447-	if len(path) == 0 {
74448-		return nil
74449-	}
74450-
74451-	if sel, ok := path[0].(*ast.SelectorExpr); ok {
74452-		return sel
74453-	}
74454-
74455-	if _, ok := path[0].(*ast.Ident); ok && len(path) > 1 {
74456-		if sel, ok := path[1].(*ast.SelectorExpr); ok && pos >= sel.Sel.Pos() {
74457-			return sel
74458-		}
74459-	}
74460-
74461-	return nil
74462-}
74463-
74464-// enclosingDeclLHS returns LHS idents from containing value spec or
74465-// assign statement.
74466-func enclosingDeclLHS(path []ast.Node) []*ast.Ident {
74467-	for _, n := range path {
74468-		switch n := n.(type) {
74469-		case *ast.ValueSpec:
74470-			return n.Names
74471-		case *ast.AssignStmt:
74472-			ids := make([]*ast.Ident, 0, len(n.Lhs))
74473-			for _, e := range n.Lhs {
74474-				if id, ok := e.(*ast.Ident); ok {
74475-					ids = append(ids, id)
74476-				}
74477-			}
74478-			return ids
74479-		}
74480-	}
74481-
74482-	return nil
74483-}
74484-
74485-// exprObj returns the types.Object associated with the *ast.Ident or
74486-// *ast.SelectorExpr e.
74487-func exprObj(info *types.Info, e ast.Expr) types.Object {
74488-	var ident *ast.Ident
74489-	switch expr := e.(type) {
74490-	case *ast.Ident:
74491-		ident = expr
74492-	case *ast.SelectorExpr:
74493-		ident = expr.Sel
74494-	default:
74495-		return nil
74496-	}
74497-
74498-	return info.ObjectOf(ident)
74499-}
74500-
74501-// typeConversion returns the type being converted to if call is a type
74502-// conversion expression.
74503-func typeConversion(call *ast.CallExpr, info *types.Info) types.Type {
74504-	// Type conversion (e.g. "float64(foo)").
74505-	if fun, _ := exprObj(info, call.Fun).(*types.TypeName); fun != nil {
74506-		return fun.Type()
74507-	}
74508-
74509-	return nil
74510-}
74511-
74512-// fieldsAccessible returns whether s has at least one field accessible by p.
74513-func fieldsAccessible(s *types.Struct, p *types.Package) bool {
74514-	for i := 0; i < s.NumFields(); i++ {
74515-		f := s.Field(i)
74516-		if f.Exported() || f.Pkg() == p {
74517-			return true
74518-		}
74519-	}
74520-	return false
74521-}
74522-
74523-// prevStmt returns the statement that precedes the statement containing pos.
74524-// For example:
74525-//
74526-//	foo := 1
74527-//	bar(1 + 2<>)
74528-//
74529-// If "<>" is pos, prevStmt returns "foo := 1"
74530-func prevStmt(pos token.Pos, path []ast.Node) ast.Stmt {
74531-	var blockLines []ast.Stmt
74532-	for i := 0; i < len(path) && blockLines == nil; i++ {
74533-		switch n := path[i].(type) {
74534-		case *ast.BlockStmt:
74535-			blockLines = n.List
74536-		case *ast.CommClause:
74537-			blockLines = n.Body
74538-		case *ast.CaseClause:
74539-			blockLines = n.Body
74540-		}
74541-	}
74542-
74543-	for i := len(blockLines) - 1; i >= 0; i-- {
74544-		if blockLines[i].End() < pos {
74545-			return blockLines[i]
74546-		}
74547-	}
74548-
74549-	return nil
74550-}
74551-
74552-// formatZeroValue produces Go code representing the zero value of T. It
74553-// returns the empty string if T is invalid.
74554-func formatZeroValue(T types.Type, qf types.Qualifier) string {
74555-	switch u := T.Underlying().(type) {
74556-	case *types.Basic:
74557-		switch {
74558-		case u.Info()&types.IsNumeric > 0:
74559-			return "0"
74560-		case u.Info()&types.IsString > 0:
74561-			return `""`
74562-		case u.Info()&types.IsBoolean > 0:
74563-			return "false"
74564-		default:
74565-			return ""
74566-		}
74567-	case *types.Pointer, *types.Interface, *types.Chan, *types.Map, *types.Slice, *types.Signature:
74568-		return "nil"
74569-	default:
74570-		return types.TypeString(T, qf) + "{}"
74571-	}
74572-}
74573-
74574-// isBasicKind returns whether t is a basic type of kind k.
74575-func isBasicKind(t types.Type, k types.BasicInfo) bool {
74576-	b, _ := t.Underlying().(*types.Basic)
74577-	return b != nil && b.Info()&k > 0
74578-}
74579-
74580-func (c *completer) editText(from, to token.Pos, newText string) ([]protocol.TextEdit, error) {
74581-	start, end, err := safetoken.Offsets(c.tokFile, from, to)
74582-	if err != nil {
74583-		return nil, err // can't happen: from/to came from c
74584-	}
74585-	return source.ToProtocolEdits(c.mapper, []diff.Edit{{
74586-		Start: start,
74587-		End:   end,
74588-		New:   newText,
74589-	}})
74590-}
74591-
74592-// assignableTo is like types.AssignableTo, but returns false if
74593-// either type is invalid.
74594-func assignableTo(x, to types.Type) bool {
74595-	if x == types.Typ[types.Invalid] || to == types.Typ[types.Invalid] {
74596-		return false
74597-	}
74598-
74599-	return types.AssignableTo(x, to)
74600-}
74601-
74602-// convertibleTo is like types.ConvertibleTo, but returns false if
74603-// either type is invalid.
74604-func convertibleTo(x, to types.Type) bool {
74605-	if x == types.Typ[types.Invalid] || to == types.Typ[types.Invalid] {
74606-		return false
74607-	}
74608-
74609-	return types.ConvertibleTo(x, to)
74610-}
74611diff -urN a/gopls/internal/lsp/source/completion/util_test.go b/gopls/internal/lsp/source/completion/util_test.go
74612--- a/gopls/internal/lsp/source/completion/util_test.go	2000-01-01 00:00:00.000000000 -0000
74613+++ b/gopls/internal/lsp/source/completion/util_test.go	1970-01-01 00:00:00.000000000 +0000
74614@@ -1,28 +0,0 @@
74615-// Copyright 2020 The Go Authors. All rights reserved.
74616-// Use of this source code is governed by a BSD-style
74617-// license that can be found in the LICENSE file.
74618-
74619-package completion
74620-
74621-import (
74622-	"go/types"
74623-	"testing"
74624-)
74625-
74626-func TestFormatZeroValue(t *testing.T) {
74627-	tests := []struct {
74628-		typ  types.Type
74629-		want string
74630-	}{
74631-		{types.Typ[types.String], `""`},
74632-		{types.Typ[types.Byte], "0"},
74633-		{types.Typ[types.Invalid], ""},
74634-		{types.Universe.Lookup("error").Type(), "nil"},
74635-	}
74636-
74637-	for _, test := range tests {
74638-		if got := formatZeroValue(test.typ, nil); got != test.want {
74639-			t.Errorf("formatZeroValue(%v) = %q, want %q", test.typ, got, test.want)
74640-		}
74641-	}
74642-}
74643diff -urN a/gopls/internal/lsp/source/definition.go b/gopls/internal/lsp/source/definition.go
74644--- a/gopls/internal/lsp/source/definition.go	2000-01-01 00:00:00.000000000 -0000
74645+++ b/gopls/internal/lsp/source/definition.go	1970-01-01 00:00:00.000000000 +0000
74646@@ -1,229 +0,0 @@
74647-// Copyright 2023 The Go Authors. All rights reserved.
74648-// Use of this source code is governed by a BSD-style
74649-// license that can be found in the LICENSE file.
74650-
74651-package source
74652-
74653-import (
74654-	"context"
74655-	"fmt"
74656-	"go/ast"
74657-	"go/token"
74658-	"go/types"
74659-
74660-	"golang.org/x/tools/gopls/internal/lsp/protocol"
74661-	"golang.org/x/tools/gopls/internal/span"
74662-	"golang.org/x/tools/internal/bug"
74663-	"golang.org/x/tools/internal/event"
74664-)
74665-
74666-// Definition handles the textDocument/definition request for Go files.
74667-func Definition(ctx context.Context, snapshot Snapshot, fh FileHandle, position protocol.Position) ([]protocol.Location, error) {
74668-	ctx, done := event.Start(ctx, "source.Definition")
74669-	defer done()
74670-
74671-	pkg, pgf, err := PackageForFile(ctx, snapshot, fh.URI(), NarrowestPackage)
74672-	if err != nil {
74673-		return nil, err
74674-	}
74675-	pos, err := pgf.PositionPos(position)
74676-	if err != nil {
74677-		return nil, err
74678-	}
74679-
74680-	// Handle the case where the cursor is in an import.
74681-	importLocations, err := importDefinition(ctx, snapshot, pkg, pgf, pos)
74682-	if err != nil {
74683-		return nil, err
74684-	}
74685-	if len(importLocations) > 0 {
74686-		return importLocations, nil
74687-	}
74688-
74689-	// Handle the case where the cursor is in the package name.
74690-	// We use "<= End" to accept a query immediately after the package name.
74691-	if pgf.File != nil && pgf.File.Name.Pos() <= pos && pos <= pgf.File.Name.End() {
74692-		// If there's no package documentation, just use current file.
74693-		declFile := pgf
74694-		for _, pgf := range pkg.CompiledGoFiles() {
74695-			if pgf.File.Name != nil && pgf.File.Doc != nil {
74696-				declFile = pgf
74697-				break
74698-			}
74699-		}
74700-		loc, err := declFile.NodeLocation(declFile.File.Name)
74701-		if err != nil {
74702-			return nil, err
74703-		}
74704-		return []protocol.Location{loc}, nil
74705-	}
74706-
74707-	// The general case: the cursor is on an identifier.
74708-	_, obj, _ := referencedObject(pkg, pgf, pos)
74709-	if obj == nil {
74710-		return nil, nil
74711-	}
74712-
74713-	// Handle built-in identifiers.
74714-	if obj.Parent() == types.Universe {
74715-		builtin, err := snapshot.BuiltinFile(ctx)
74716-		if err != nil {
74717-			return nil, err
74718-		}
74719-		// Note that builtinObj is an ast.Object, not types.Object :)
74720-		builtinObj := builtin.File.Scope.Lookup(obj.Name())
74721-		if builtinObj == nil {
74722-			// Every builtin should have documentation.
74723-			return nil, bug.Errorf("internal error: no builtin object for %s", obj.Name())
74724-		}
74725-		decl, ok := builtinObj.Decl.(ast.Node)
74726-		if !ok {
74727-			return nil, bug.Errorf("internal error: no declaration for %s", obj.Name())
74728-		}
74729-		// The builtin package isn't in the dependency graph, so the usual
74730-		// utilities won't work here.
74731-		loc, err := builtin.PosLocation(decl.Pos(), decl.Pos()+token.Pos(len(obj.Name())))
74732-		if err != nil {
74733-			return nil, err
74734-		}
74735-		return []protocol.Location{loc}, nil
74736-	}
74737-
74738-	// Finally, map the object position.
74739-	var locs []protocol.Location
74740-	if !obj.Pos().IsValid() {
74741-		return nil, bug.Errorf("internal error: no position for %v", obj.Name())
74742-	}
74743-	loc, err := mapPosition(ctx, pkg.FileSet(), snapshot, obj.Pos(), adjustedObjEnd(obj))
74744-	if err != nil {
74745-		return nil, err
74746-	}
74747-	locs = append(locs, loc)
74748-	return locs, nil
74749-}
74750-
74751-// referencedObject returns the identifier and object referenced at the
74752-// specified position, which must be within the file pgf, for the purposes of
74753-// definition/hover/call hierarchy operations. It returns a nil object if no
74754-// object was found at the given position.
74755-//
74756-// If the returned identifier is a type-switch implicit (i.e. the x in x :=
74757-// e.(type)), the third result will be the type of the expression being
74758-// switched on (the type of e in the example). This facilitates workarounds for
74759-// limitations of the go/types API, which does not report an object for the
74760-// identifier x.
74761-//
74762-// For embedded fields, referencedObject returns the type name object rather
74763-// than the var (field) object.
74764-//
74765-// TODO(rfindley): this function exists to preserve the pre-existing behavior
74766-// of source.Identifier. Eliminate this helper in favor of sharing
74767-// functionality with objectsAt, after choosing suitable primitives.
74768-func referencedObject(pkg Package, pgf *ParsedGoFile, pos token.Pos) (*ast.Ident, types.Object, types.Type) {
74769-	path := pathEnclosingObjNode(pgf.File, pos)
74770-	if len(path) == 0 {
74771-		return nil, nil, nil
74772-	}
74773-	var obj types.Object
74774-	info := pkg.GetTypesInfo()
74775-	switch n := path[0].(type) {
74776-	case *ast.Ident:
74777-		obj = info.ObjectOf(n)
74778-		// If n is the var's declaring ident in a type switch
74779-		// [i.e. the x in x := foo.(type)], it will not have an object. In this
74780-		// case, set obj to the first implicit object (if any), and return the type
74781-		// of the expression being switched on.
74782-		//
74783-		// The type switch may have no case clauses and thus no
74784-		// implicit objects; this is a type error ("unused x"),
74785-		if obj == nil {
74786-			if implicits, typ := typeSwitchImplicits(info, path); len(implicits) > 0 {
74787-				return n, implicits[0], typ
74788-			}
74789-		}
74790-
74791-		// If the original position was an embedded field, we want to jump
74792-		// to the field's type definition, not the field's definition.
74793-		if v, ok := obj.(*types.Var); ok && v.Embedded() {
74794-			// types.Info.Uses contains the embedded field's *types.TypeName.
74795-			if typeName := info.Uses[n]; typeName != nil {
74796-				obj = typeName
74797-			}
74798-		}
74799-		return n, obj, nil
74800-	}
74801-	return nil, nil, nil
74802-}
74803-
74804-// importDefinition returns locations defining a package referenced by the
74805-// import spec containing pos.
74806-//
74807-// If pos is not inside an import spec, it returns nil, nil.
74808-func importDefinition(ctx context.Context, s Snapshot, pkg Package, pgf *ParsedGoFile, pos token.Pos) ([]protocol.Location, error) {
74809-	var imp *ast.ImportSpec
74810-	for _, spec := range pgf.File.Imports {
74811-		// We use "<= End" to accept a query immediately after an ImportSpec.
74812-		if spec.Path.Pos() <= pos && pos <= spec.Path.End() {
74813-			imp = spec
74814-		}
74815-	}
74816-	if imp == nil {
74817-		return nil, nil
74818-	}
74819-
74820-	importPath := UnquoteImportPath(imp)
74821-	impID := pkg.Metadata().DepsByImpPath[importPath]
74822-	if impID == "" {
74823-		return nil, fmt.Errorf("failed to resolve import %q", importPath)
74824-	}
74825-	impMetadata := s.Metadata(impID)
74826-	if impMetadata == nil {
74827-		return nil, fmt.Errorf("missing information for package %q", impID)
74828-	}
74829-
74830-	var locs []protocol.Location
74831-	for _, f := range impMetadata.CompiledGoFiles {
74832-		fh, err := s.GetFile(ctx, f)
74833-		if err != nil {
74834-			if ctx.Err() != nil {
74835-				return nil, ctx.Err()
74836-			}
74837-			continue
74838-		}
74839-		pgf, err := s.ParseGo(ctx, fh, ParseHeader)
74840-		if err != nil {
74841-			if ctx.Err() != nil {
74842-				return nil, ctx.Err()
74843-			}
74844-			continue
74845-		}
74846-		loc, err := pgf.NodeLocation(pgf.File)
74847-		if err != nil {
74848-			return nil, err
74849-		}
74850-		locs = append(locs, loc)
74851-	}
74852-
74853-	if len(locs) == 0 {
74854-		return nil, fmt.Errorf("package %q has no readable files", impID) // incl. unsafe
74855-	}
74856-
74857-	return locs, nil
74858-}
74859-
74860-// TODO(rfindley): avoid the duplicate column mapping here, by associating a
74861-// column mapper with each file handle.
74862-func mapPosition(ctx context.Context, fset *token.FileSet, s FileSource, start, end token.Pos) (protocol.Location, error) {
74863-	file := fset.File(start)
74864-	uri := span.URIFromPath(file.Name())
74865-	fh, err := s.GetFile(ctx, uri)
74866-	if err != nil {
74867-		return protocol.Location{}, err
74868-	}
74869-	content, err := fh.Read()
74870-	if err != nil {
74871-		return protocol.Location{}, err
74872-	}
74873-	m := protocol.NewMapper(fh.URI(), content)
74874-	return m.PosLocation(file, start, end)
74875-}
74876diff -urN a/gopls/internal/lsp/source/diagnostics.go b/gopls/internal/lsp/source/diagnostics.go
74877--- a/gopls/internal/lsp/source/diagnostics.go	2000-01-01 00:00:00.000000000 -0000
74878+++ b/gopls/internal/lsp/source/diagnostics.go	1970-01-01 00:00:00.000000000 +0000
74879@@ -1,138 +0,0 @@
74880-// Copyright 2018 The Go Authors. All rights reserved.
74881-// Use of this source code is governed by a BSD-style
74882-// license that can be found in the LICENSE file.
74883-
74884-package source
74885-
74886-import (
74887-	"context"
74888-
74889-	"golang.org/x/tools/gopls/internal/lsp/protocol"
74890-	"golang.org/x/tools/gopls/internal/span"
74891-)
74892-
74893-type SuggestedFix struct {
74894-	Title      string
74895-	Edits      map[span.URI][]protocol.TextEdit
74896-	Command    *protocol.Command
74897-	ActionKind protocol.CodeActionKind
74898-}
74899-
74900-// Analyze reports go/analysis-framework diagnostics in the specified package.
74901-func Analyze(ctx context.Context, snapshot Snapshot, pkgid PackageID, includeConvenience bool) (map[span.URI][]*Diagnostic, error) {
74902-	// Exit early if the context has been canceled. This also protects us
74903-	// from a race on Options, see golang/go#36699.
74904-	if ctx.Err() != nil {
74905-		return nil, ctx.Err()
74906-	}
74907-
74908-	options := snapshot.View().Options()
74909-	categories := []map[string]*Analyzer{
74910-		options.DefaultAnalyzers,
74911-		options.StaticcheckAnalyzers,
74912-		options.TypeErrorAnalyzers,
74913-	}
74914-	if includeConvenience { // e.g. for codeAction
74915-		categories = append(categories, options.ConvenienceAnalyzers) // e.g. fillstruct
74916-	}
74917-
74918-	var analyzers []*Analyzer
74919-	for _, cat := range categories {
74920-		for _, a := range cat {
74921-			analyzers = append(analyzers, a)
74922-		}
74923-	}
74924-
74925-	analysisDiagnostics, err := snapshot.Analyze(ctx, pkgid, analyzers)
74926-	if err != nil {
74927-		return nil, err
74928-	}
74929-
74930-	// Report diagnostics and errors from root analyzers.
74931-	reports := make(map[span.URI][]*Diagnostic)
74932-	for _, diag := range analysisDiagnostics {
74933-		reports[diag.URI] = append(reports[diag.URI], diag)
74934-	}
74935-	return reports, nil
74936-}
74937-
74938-// FileDiagnostics reports diagnostics in the specified file,
74939-// as used by the "gopls check" command.
74940-//
74941-// TODO(adonovan): factor in common with (*Server).codeAction, which
74942-// executes { PackageForFile; Analyze } too?
74943-//
74944-// TODO(adonovan): opt: this function is called in a loop from the
74945-// "gopls/diagnoseFiles" nonstandard request handler. It would be more
74946-// efficient to compute the set of packages and TypeCheck and
74947-// Analyze them all at once.
74948-func FileDiagnostics(ctx context.Context, snapshot Snapshot, uri span.URI) (FileHandle, []*Diagnostic, error) {
74949-	fh, err := snapshot.GetFile(ctx, uri)
74950-	if err != nil {
74951-		return nil, nil, err
74952-	}
74953-	pkg, _, err := PackageForFile(ctx, snapshot, uri, NarrowestPackage)
74954-	if err != nil {
74955-		return nil, nil, err
74956-	}
74957-	pkgDiags, err := pkg.DiagnosticsForFile(ctx, snapshot, uri)
74958-	if err != nil {
74959-		return nil, nil, err
74960-	}
74961-	adiags, err := Analyze(ctx, snapshot, pkg.Metadata().ID, false)
74962-	if err != nil {
74963-		return nil, nil, err
74964-	}
74965-	var fileDiags []*Diagnostic // combine load/parse/type + analysis diagnostics
74966-	CombineDiagnostics(pkgDiags, adiags[uri], &fileDiags, &fileDiags)
74967-	return fh, fileDiags, nil
74968-}
74969-
74970-// CombineDiagnostics combines and filters list/parse/type diagnostics from
74971-// tdiags with adiags, and appends the two lists to *outT and *outA,
74972-// respectively.
74973-//
74974-// Type-error analyzers produce diagnostics that are redundant
74975-// with type checker diagnostics, but more detailed (e.g. fixes).
74976-// Rather than report two diagnostics for the same problem,
74977-// we combine them by augmenting the type-checker diagnostic
74978-// and discarding the analyzer diagnostic.
74979-//
74980-// If an analysis diagnostic has the same range and message as
74981-// a list/parse/type diagnostic, the suggested fix information
74982-// (et al) of the latter is merged into a copy of the former.
74983-// This handles the case where a type-error analyzer suggests
74984-// a fix to a type error, and avoids duplication.
74985-//
74986-// The use of out-slices, though irregular, allows the caller to
74987-// easily choose whether to keep the results separate or combined.
74988-//
74989-// The arguments are not modified.
74990-func CombineDiagnostics(tdiags []*Diagnostic, adiags []*Diagnostic, outT, outA *[]*Diagnostic) {
74991-
74992-	// Build index of (list+parse+)type errors.
74993-	type key struct {
74994-		Range   protocol.Range
74995-		message string
74996-	}
74997-	index := make(map[key]int) // maps (Range,Message) to index in tdiags slice
74998-	for i, diag := range tdiags {
74999-		index[key{diag.Range, diag.Message}] = i
75000-	}
75001-
75002-	// Filter out analysis diagnostics that match type errors,
75003-	// retaining their suggested fix (etc) fields.
75004-	for _, diag := range adiags {
75005-		if i, ok := index[key{diag.Range, diag.Message}]; ok {
75006-			copy := *tdiags[i]
75007-			copy.SuggestedFixes = diag.SuggestedFixes
75008-			copy.Tags = diag.Tags
75009-			tdiags[i] = &copy
75010-			continue
75011-		}
75012-
75013-		*outA = append(*outA, diag)
75014-	}
75015-
75016-	*outT = append(*outT, tdiags...)
75017-}
75018diff -urN a/gopls/internal/lsp/source/extract.go b/gopls/internal/lsp/source/extract.go
75019--- a/gopls/internal/lsp/source/extract.go	2000-01-01 00:00:00.000000000 -0000
75020+++ b/gopls/internal/lsp/source/extract.go	1970-01-01 00:00:00.000000000 +0000
75021@@ -1,1331 +0,0 @@
75022-// Copyright 2020 The Go Authors. All rights reserved.
75023-// Use of this source code is governed by a BSD-style
75024-// license that can be found in the LICENSE file.
75025-
75026-package source
75027-
75028-import (
75029-	"bytes"
75030-	"fmt"
75031-	"go/ast"
75032-	"go/format"
75033-	"go/parser"
75034-	"go/token"
75035-	"go/types"
75036-	"sort"
75037-	"strings"
75038-	"text/scanner"
75039-
75040-	"golang.org/x/tools/go/analysis"
75041-	"golang.org/x/tools/go/ast/astutil"
75042-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
75043-	"golang.org/x/tools/internal/analysisinternal"
75044-	"golang.org/x/tools/internal/bug"
75045-)
75046-
75047-func extractVariable(fset *token.FileSet, start, end token.Pos, src []byte, file *ast.File, _ *types.Package, info *types.Info) (*analysis.SuggestedFix, error) {
75048-	tokFile := fset.File(file.Pos())
75049-	expr, path, ok, err := CanExtractVariable(start, end, file)
75050-	if !ok {
75051-		return nil, fmt.Errorf("extractVariable: cannot extract %s: %v", safetoken.StartPosition(fset, start), err)
75052-	}
75053-
75054-	// Create new AST node for extracted code.
75055-	var lhsNames []string
75056-	switch expr := expr.(type) {
75057-	// TODO: stricter rules for selectorExpr.
75058-	case *ast.BasicLit, *ast.CompositeLit, *ast.IndexExpr, *ast.SliceExpr,
75059-		*ast.UnaryExpr, *ast.BinaryExpr, *ast.SelectorExpr:
75060-		lhsName, _ := generateAvailableIdentifier(expr.Pos(), file, path, info, "x", 0)
75061-		lhsNames = append(lhsNames, lhsName)
75062-	case *ast.CallExpr:
75063-		tup, ok := info.TypeOf(expr).(*types.Tuple)
75064-		if !ok {
75065-			// If the call expression only has one return value, we can treat it the
75066-			// same as our standard extract variable case.
75067-			lhsName, _ := generateAvailableIdentifier(expr.Pos(), file, path, info, "x", 0)
75068-			lhsNames = append(lhsNames, lhsName)
75069-			break
75070-		}
75071-		idx := 0
75072-		for i := 0; i < tup.Len(); i++ {
75073-			// Generate a unique variable for each return value.
75074-			var lhsName string
75075-			lhsName, idx = generateAvailableIdentifier(expr.Pos(), file, path, info, "x", idx)
75076-			lhsNames = append(lhsNames, lhsName)
75077-		}
75078-	default:
75079-		return nil, fmt.Errorf("cannot extract %T", expr)
75080-	}
75081-
75082-	insertBeforeStmt := analysisinternal.StmtToInsertVarBefore(path)
75083-	if insertBeforeStmt == nil {
75084-		return nil, fmt.Errorf("cannot find location to insert extraction")
75085-	}
75086-	indent, err := calculateIndentation(src, tokFile, insertBeforeStmt)
75087-	if err != nil {
75088-		return nil, err
75089-	}
75090-	newLineIndent := "\n" + indent
75091-
75092-	lhs := strings.Join(lhsNames, ", ")
75093-	assignStmt := &ast.AssignStmt{
75094-		Lhs: []ast.Expr{ast.NewIdent(lhs)},
75095-		Tok: token.DEFINE,
75096-		Rhs: []ast.Expr{expr},
75097-	}
75098-	var buf bytes.Buffer
75099-	if err := format.Node(&buf, fset, assignStmt); err != nil {
75100-		return nil, err
75101-	}
75102-	assignment := strings.ReplaceAll(buf.String(), "\n", newLineIndent) + newLineIndent
75103-
75104-	return &analysis.SuggestedFix{
75105-		TextEdits: []analysis.TextEdit{
75106-			{
75107-				Pos:     insertBeforeStmt.Pos(),
75108-				End:     insertBeforeStmt.Pos(),
75109-				NewText: []byte(assignment),
75110-			},
75111-			{
75112-				Pos:     start,
75113-				End:     end,
75114-				NewText: []byte(lhs),
75115-			},
75116-		},
75117-	}, nil
75118-}
75119-
75120-// CanExtractVariable reports whether the code in the given range can be
75121-// extracted to a variable.
75122-func CanExtractVariable(start, end token.Pos, file *ast.File) (ast.Expr, []ast.Node, bool, error) {
75123-	if start == end {
75124-		return nil, nil, false, fmt.Errorf("start and end are equal")
75125-	}
75126-	path, _ := astutil.PathEnclosingInterval(file, start, end)
75127-	if len(path) == 0 {
75128-		return nil, nil, false, fmt.Errorf("no path enclosing interval")
75129-	}
75130-	for _, n := range path {
75131-		if _, ok := n.(*ast.ImportSpec); ok {
75132-			return nil, nil, false, fmt.Errorf("cannot extract variable in an import block")
75133-		}
75134-	}
75135-	node := path[0]
75136-	if start != node.Pos() || end != node.End() {
75137-		return nil, nil, false, fmt.Errorf("range does not map to an AST node")
75138-	}
75139-	expr, ok := node.(ast.Expr)
75140-	if !ok {
75141-		return nil, nil, false, fmt.Errorf("node is not an expression")
75142-	}
75143-	switch expr.(type) {
75144-	case *ast.BasicLit, *ast.CompositeLit, *ast.IndexExpr, *ast.CallExpr,
75145-		*ast.SliceExpr, *ast.UnaryExpr, *ast.BinaryExpr, *ast.SelectorExpr:
75146-		return expr, path, true, nil
75147-	}
75148-	return nil, nil, false, fmt.Errorf("cannot extract an %T to a variable", expr)
75149-}
75150-
75151-// Calculate indentation for insertion.
75152-// When inserting lines of code, we must ensure that the lines have consistent
75153-// formatting (i.e. the proper indentation). To do so, we observe the indentation on the
75154-// line of code on which the insertion occurs.
75155-func calculateIndentation(content []byte, tok *token.File, insertBeforeStmt ast.Node) (string, error) {
75156-	line := tok.Line(insertBeforeStmt.Pos())
75157-	lineOffset, stmtOffset, err := safetoken.Offsets(tok, tok.LineStart(line), insertBeforeStmt.Pos())
75158-	if err != nil {
75159-		return "", err
75160-	}
75161-	return string(content[lineOffset:stmtOffset]), nil
75162-}
75163-
75164-// generateAvailableIdentifier adjusts the new function name until there are no collisions in scope.
75165-// Possible collisions include other function and variable names. Returns the next index to check for prefix.
75166-func generateAvailableIdentifier(pos token.Pos, file *ast.File, path []ast.Node, info *types.Info, prefix string, idx int) (string, int) {
75167-	scopes := CollectScopes(info, path, pos)
75168-	return generateIdentifier(idx, prefix, func(name string) bool {
75169-		return file.Scope.Lookup(name) != nil || !isValidName(name, scopes)
75170-	})
75171-}
75172-
75173-func generateIdentifier(idx int, prefix string, hasCollision func(string) bool) (string, int) {
75174-	name := prefix
75175-	if idx != 0 {
75176-		name += fmt.Sprintf("%d", idx)
75177-	}
75178-	for hasCollision(name) {
75179-		idx++
75180-		name = fmt.Sprintf("%v%d", prefix, idx)
75181-	}
75182-	return name, idx + 1
75183-}
75184-
75185-// isValidName checks for variable collision in scope.
75186-func isValidName(name string, scopes []*types.Scope) bool {
75187-	for _, scope := range scopes {
75188-		if scope == nil {
75189-			continue
75190-		}
75191-		if scope.Lookup(name) != nil {
75192-			return false
75193-		}
75194-	}
75195-	return true
75196-}
75197-
75198-// returnVariable keeps track of the information we need to properly introduce a new variable
75199-// that we will return in the extracted function.
75200-type returnVariable struct {
75201-	// name is the identifier that is used on the left-hand side of the call to
75202-	// the extracted function.
75203-	name ast.Expr
75204-	// decl is the declaration of the variable. It is used in the type signature of the
75205-	// extracted function and for variable declarations.
75206-	decl *ast.Field
75207-	// zeroVal is the "zero value" of the type of the variable. It is used in a return
75208-	// statement in the extracted function.
75209-	zeroVal ast.Expr
75210-}
75211-
75212-// extractMethod refactors the selected block of code into a new method.
75213-func extractMethod(fset *token.FileSet, start, end token.Pos, src []byte, file *ast.File, pkg *types.Package, info *types.Info) (*analysis.SuggestedFix, error) {
75214-	return extractFunctionMethod(fset, start, end, src, file, pkg, info, true)
75215-}
75216-
75217-// extractFunction refactors the selected block of code into a new function.
75218-func extractFunction(fset *token.FileSet, start, end token.Pos, src []byte, file *ast.File, pkg *types.Package, info *types.Info) (*analysis.SuggestedFix, error) {
75219-	return extractFunctionMethod(fset, start, end, src, file, pkg, info, false)
75220-}
75221-
75222-// extractFunctionMethod refactors the selected block of code into a new function/method.
75223-// It also replaces the selected block of code with a call to the extracted
75224-// function. First, we manually adjust the selection range. We remove trailing
75225-// and leading whitespace characters to ensure the range is precisely bounded
75226-// by AST nodes. Next, we determine the variables that will be the parameters
75227-// and return values of the extracted function/method. Lastly, we construct the call
75228-// of the function/method and insert this call as well as the extracted function/method into
75229-// their proper locations.
75230-func extractFunctionMethod(fset *token.FileSet, start, end token.Pos, src []byte, file *ast.File, pkg *types.Package, info *types.Info, isMethod bool) (*analysis.SuggestedFix, error) {
75231-	errorPrefix := "extractFunction"
75232-	if isMethod {
75233-		errorPrefix = "extractMethod"
75234-	}
75235-
75236-	tok := fset.File(file.Pos())
75237-	if tok == nil {
75238-		return nil, bug.Errorf("no file for position")
75239-	}
75240-	p, ok, methodOk, err := CanExtractFunction(tok, start, end, src, file)
75241-	if (!ok && !isMethod) || (!methodOk && isMethod) {
75242-		return nil, fmt.Errorf("%s: cannot extract %s: %v", errorPrefix,
75243-			safetoken.StartPosition(fset, start), err)
75244-	}
75245-	tok, path, start, end, outer, node := p.tok, p.path, p.start, p.end, p.outer, p.node
75246-	fileScope := info.Scopes[file]
75247-	if fileScope == nil {
75248-		return nil, fmt.Errorf("%s: file scope is empty", errorPrefix)
75249-	}
75250-	pkgScope := fileScope.Parent()
75251-	if pkgScope == nil {
75252-		return nil, fmt.Errorf("%s: package scope is empty", errorPrefix)
75253-	}
75254-
75255-	// A return statement is non-nested if its parent node is equal to the parent node
75256-	// of the first node in the selection. These cases must be handled separately because
75257-	// non-nested return statements are guaranteed to execute.
75258-	var retStmts []*ast.ReturnStmt
75259-	var hasNonNestedReturn bool
75260-	startParent := findParent(outer, node)
75261-	ast.Inspect(outer, func(n ast.Node) bool {
75262-		if n == nil {
75263-			return false
75264-		}
75265-		if n.Pos() < start || n.End() > end {
75266-			return n.Pos() <= end
75267-		}
75268-		ret, ok := n.(*ast.ReturnStmt)
75269-		if !ok {
75270-			return true
75271-		}
75272-		if findParent(outer, n) == startParent {
75273-			hasNonNestedReturn = true
75274-		}
75275-		retStmts = append(retStmts, ret)
75276-		return false
75277-	})
75278-	containsReturnStatement := len(retStmts) > 0
75279-
75280-	// Now that we have determined the correct range for the selection block,
75281-	// we must determine the signature of the extracted function. We will then replace
75282-	// the block with an assignment statement that calls the extracted function with
75283-	// the appropriate parameters and return values.
75284-	variables, err := collectFreeVars(info, file, fileScope, pkgScope, start, end, path[0])
75285-	if err != nil {
75286-		return nil, err
75287-	}
75288-
75289-	var (
75290-		receiverUsed bool
75291-		receiver     *ast.Field
75292-		receiverName string
75293-		receiverObj  types.Object
75294-	)
75295-	if isMethod {
75296-		if outer == nil || outer.Recv == nil || len(outer.Recv.List) == 0 {
75297-			return nil, fmt.Errorf("%s: cannot extract need method receiver", errorPrefix)
75298-		}
75299-		receiver = outer.Recv.List[0]
75300-		if len(receiver.Names) == 0 || receiver.Names[0] == nil {
75301-			return nil, fmt.Errorf("%s: cannot extract need method receiver name", errorPrefix)
75302-		}
75303-		recvName := receiver.Names[0]
75304-		receiverName = recvName.Name
75305-		receiverObj = info.ObjectOf(recvName)
75306-	}
75307-
75308-	var (
75309-		params, returns         []ast.Expr     // used when calling the extracted function
75310-		paramTypes, returnTypes []*ast.Field   // used in the signature of the extracted function
75311-		uninitialized           []types.Object // vars we will need to initialize before the call
75312-	)
75313-
75314-	// Avoid duplicates while traversing vars and uninitialized.
75315-	seenVars := make(map[types.Object]ast.Expr)
75316-	seenUninitialized := make(map[types.Object]struct{})
75317-
75318-	// Some variables on the left-hand side of our assignment statement may be free. If our
75319-	// selection begins in the same scope in which the free variable is defined, we can
75320-	// redefine it in our assignment statement. See the following example, where 'b' and
75321-	// 'err' (both free variables) can be redefined in the second funcCall() while maintaining
75322-	// correctness.
75323-	//
75324-	//
75325-	// Not Redefined:
75326-	//
75327-	// a, err := funcCall()
75328-	// var b int
75329-	// b, err = funcCall()
75330-	//
75331-	// Redefined:
75332-	//
75333-	// a, err := funcCall()
75334-	// b, err := funcCall()
75335-	//
75336-	// We track the number of free variables that can be redefined to maintain our preference
75337-	// of using "x, y, z := fn()" style assignment statements.
75338-	var canRedefineCount int
75339-
75340-	// Each identifier in the selected block must become (1) a parameter to the
75341-	// extracted function, (2) a return value of the extracted function, or (3) a local
75342-	// variable in the extracted function. Determine the outcome(s) for each variable
75343-	// based on whether it is free, altered within the selected block, and used outside
75344-	// of the selected block.
75345-	for _, v := range variables {
75346-		if _, ok := seenVars[v.obj]; ok {
75347-			continue
75348-		}
75349-		if v.obj.Name() == "_" {
75350-			// The blank identifier is always a local variable
75351-			continue
75352-		}
75353-		typ := analysisinternal.TypeExpr(file, pkg, v.obj.Type())
75354-		if typ == nil {
75355-			return nil, fmt.Errorf("nil AST expression for type: %v", v.obj.Name())
75356-		}
75357-		seenVars[v.obj] = typ
75358-		identifier := ast.NewIdent(v.obj.Name())
75359-		// An identifier must meet three conditions to become a return value of the
75360-		// extracted function. (1) its value must be defined or reassigned within
75361-		// the selection (isAssigned), (2) it must be used at least once after the
75362-		// selection (isUsed), and (3) its first use after the selection
75363-		// cannot be its own reassignment or redefinition (objOverriden).
75364-		if v.obj.Parent() == nil {
75365-			return nil, fmt.Errorf("parent nil")
75366-		}
75367-		isUsed, firstUseAfter := objUsed(info, end, v.obj.Parent().End(), v.obj)
75368-		if v.assigned && isUsed && !varOverridden(info, firstUseAfter, v.obj, v.free, outer) {
75369-			returnTypes = append(returnTypes, &ast.Field{Type: typ})
75370-			returns = append(returns, identifier)
75371-			if !v.free {
75372-				uninitialized = append(uninitialized, v.obj)
75373-			} else if v.obj.Parent().Pos() == startParent.Pos() {
75374-				canRedefineCount++
75375-			}
75376-		}
75377-		// An identifier must meet two conditions to become a parameter of the
75378-		// extracted function. (1) it must be free (isFree), and (2) its first
75379-		// use within the selection cannot be its own definition (isDefined).
75380-		if v.free && !v.defined {
75381-			// Skip the selector for a method.
75382-			if isMethod && v.obj == receiverObj {
75383-				receiverUsed = true
75384-				continue
75385-			}
75386-			params = append(params, identifier)
75387-			paramTypes = append(paramTypes, &ast.Field{
75388-				Names: []*ast.Ident{identifier},
75389-				Type:  typ,
75390-			})
75391-		}
75392-	}
75393-
75394-	// Find the function literal that encloses the selection. The enclosing function literal
75395-	// may not be the enclosing function declaration (i.e. 'outer'). For example, in the
75396-	// following block:
75397-	//
75398-	// func main() {
75399-	//     ast.Inspect(node, func(n ast.Node) bool {
75400-	//         v := 1 // this line extracted
75401-	//         return true
75402-	//     })
75403-	// }
75404-	//
75405-	// 'outer' is main(). However, the extracted selection most directly belongs to
75406-	// the anonymous function literal, the second argument of ast.Inspect(). We use the
75407-	// enclosing function literal to determine the proper return types for return statements
75408-	// within the selection. We still need the enclosing function declaration because this is
75409-	// the top-level declaration. We inspect the top-level declaration to look for variables
75410-	// as well as for code replacement.
75411-	enclosing := outer.Type
75412-	for _, p := range path {
75413-		if p == enclosing {
75414-			break
75415-		}
75416-		if fl, ok := p.(*ast.FuncLit); ok {
75417-			enclosing = fl.Type
75418-			break
75419-		}
75420-	}
75421-
75422-	// We put the selection in a constructed file. We can then traverse and edit
75423-	// the extracted selection without modifying the original AST.
75424-	startOffset, endOffset, err := safetoken.Offsets(tok, start, end)
75425-	if err != nil {
75426-		return nil, err
75427-	}
75428-	selection := src[startOffset:endOffset]
75429-	extractedBlock, err := parseBlockStmt(fset, selection)
75430-	if err != nil {
75431-		return nil, err
75432-	}
75433-
75434-	// We need to account for return statements in the selected block, as they will complicate
75435-	// the logical flow of the extracted function. See the following example, where ** denotes
75436-	// the range to be extracted.
75437-	//
75438-	// Before:
75439-	//
75440-	// func _() int {
75441-	//     a := 1
75442-	//     b := 2
75443-	//     **if a == b {
75444-	//         return a
75445-	//     }**
75446-	//     ...
75447-	// }
75448-	//
75449-	// After:
75450-	//
75451-	// func _() int {
75452-	//     a := 1
75453-	//     b := 2
75454-	//     cond0, ret0 := x0(a, b)
75455-	//     if cond0 {
75456-	//         return ret0
75457-	//     }
75458-	//     ...
75459-	// }
75460-	//
75461-	// func x0(a int, b int) (bool, int) {
75462-	//     if a == b {
75463-	//         return true, a
75464-	//     }
75465-	//     return false, 0
75466-	// }
75467-	//
75468-	// We handle returns by adding an additional boolean return value to the extracted function.
75469-	// This bool reports whether the original function would have returned. Because the
75470-	// extracted selection contains a return statement, we must also add the types in the
75471-	// return signature of the enclosing function to the return signature of the
75472-	// extracted function. We then add an extra if statement checking this boolean value
75473-	// in the original function. If the condition is met, the original function should
75474-	// return a value, mimicking the functionality of the original return statement(s)
75475-	// in the selection.
75476-	//
75477-	// If there is a return that is guaranteed to execute (hasNonNestedReturns=true), then
75478-	// we don't need to include this additional condition check and can simply return.
75479-	//
75480-	// Before:
75481-	//
75482-	// func _() int {
75483-	//     a := 1
75484-	//     b := 2
75485-	//     **if a == b {
75486-	//         return a
75487-	//     }
75488-	//	   return b**
75489-	// }
75490-	//
75491-	// After:
75492-	//
75493-	// func _() int {
75494-	//     a := 1
75495-	//     b := 2
75496-	//     return x0(a, b)
75497-	// }
75498-	//
75499-	// func x0(a int, b int) int {
75500-	//     if a == b {
75501-	//         return a
75502-	//     }
75503-	//     return b
75504-	// }
75505-
75506-	var retVars []*returnVariable
75507-	var ifReturn *ast.IfStmt
75508-	if containsReturnStatement {
75509-		if !hasNonNestedReturn {
75510-			// The selected block contained return statements, so we have to modify the
75511-			// signature of the extracted function as described above. Adjust all of
75512-			// the return statements in the extracted function to reflect this change in
75513-			// signature.
75514-			if err := adjustReturnStatements(returnTypes, seenVars, fset, file,
75515-				pkg, extractedBlock); err != nil {
75516-				return nil, err
75517-			}
75518-		}
75519-		// Collect the additional return values and types needed to accommodate return
75520-		// statements in the selection. Update the type signature of the extracted
75521-		// function and construct the if statement that will be inserted in the enclosing
75522-		// function.
75523-		retVars, ifReturn, err = generateReturnInfo(enclosing, pkg, path, file, info, fset, start, hasNonNestedReturn)
75524-		if err != nil {
75525-			return nil, err
75526-		}
75527-	}
75528-
75529-	// Add a return statement to the end of the new function. This return statement must include
75530-	// the values for the types of the original extracted function signature and (if a return
75531-	// statement is present in the selection) enclosing function signature.
75532-	// This only needs to be done if the selections does not have a non-nested return, otherwise
75533-	// it already terminates with a return statement.
75534-	hasReturnValues := len(returns)+len(retVars) > 0
75535-	if hasReturnValues && !hasNonNestedReturn {
75536-		extractedBlock.List = append(extractedBlock.List, &ast.ReturnStmt{
75537-			Results: append(returns, getZeroVals(retVars)...),
75538-		})
75539-	}
75540-
75541-	// Construct the appropriate call to the extracted function.
75542-	// We must meet two conditions to use ":=" instead of '='. (1) there must be at least
75543-	// one variable on the lhs that is uninitialized (non-free) prior to the assignment.
75544-	// (2) all of the initialized (free) variables on the lhs must be able to be redefined.
75545-	sym := token.ASSIGN
75546-	canDefineCount := len(uninitialized) + canRedefineCount
75547-	canDefine := len(uninitialized)+len(retVars) > 0 && canDefineCount == len(returns)
75548-	if canDefine {
75549-		sym = token.DEFINE
75550-	}
75551-	var name, funName string
75552-	if isMethod {
75553-		name = "newMethod"
75554-		// TODO(suzmue): generate a name that does not conflict for "newMethod".
75555-		funName = name
75556-	} else {
75557-		name = "newFunction"
75558-		funName, _ = generateAvailableIdentifier(start, file, path, info, name, 0)
75559-	}
75560-	extractedFunCall := generateFuncCall(hasNonNestedReturn, hasReturnValues, params,
75561-		append(returns, getNames(retVars)...), funName, sym, receiverName)
75562-
75563-	// Build the extracted function.
75564-	newFunc := &ast.FuncDecl{
75565-		Name: ast.NewIdent(funName),
75566-		Type: &ast.FuncType{
75567-			Params:  &ast.FieldList{List: paramTypes},
75568-			Results: &ast.FieldList{List: append(returnTypes, getDecls(retVars)...)},
75569-		},
75570-		Body: extractedBlock,
75571-	}
75572-	if isMethod {
75573-		var names []*ast.Ident
75574-		if receiverUsed {
75575-			names = append(names, ast.NewIdent(receiverName))
75576-		}
75577-		newFunc.Recv = &ast.FieldList{
75578-			List: []*ast.Field{{
75579-				Names: names,
75580-				Type:  receiver.Type,
75581-			}},
75582-		}
75583-	}
75584-
75585-	// Create variable declarations for any identifiers that need to be initialized prior to
75586-	// calling the extracted function. We do not manually initialize variables if every return
75587-	// value is uninitialized. We can use := to initialize the variables in this situation.
75588-	var declarations []ast.Stmt
75589-	if canDefineCount != len(returns) {
75590-		declarations = initializeVars(uninitialized, retVars, seenUninitialized, seenVars)
75591-	}
75592-
75593-	var declBuf, replaceBuf, newFuncBuf, ifBuf, commentBuf bytes.Buffer
75594-	if err := format.Node(&declBuf, fset, declarations); err != nil {
75595-		return nil, err
75596-	}
75597-	if err := format.Node(&replaceBuf, fset, extractedFunCall); err != nil {
75598-		return nil, err
75599-	}
75600-	if ifReturn != nil {
75601-		if err := format.Node(&ifBuf, fset, ifReturn); err != nil {
75602-			return nil, err
75603-		}
75604-	}
75605-	if err := format.Node(&newFuncBuf, fset, newFunc); err != nil {
75606-		return nil, err
75607-	}
75608-	// Find all the comments within the range and print them to be put somewhere.
75609-	// TODO(suzmue): print these in the extracted function at the correct place.
75610-	for _, cg := range file.Comments {
75611-		if cg.Pos().IsValid() && cg.Pos() < end && cg.Pos() >= start {
75612-			for _, c := range cg.List {
75613-				fmt.Fprintln(&commentBuf, c.Text)
75614-			}
75615-		}
75616-	}
75617-
75618-	// We're going to replace the whole enclosing function,
75619-	// so preserve the text before and after the selected block.
75620-	outerStart, outerEnd, err := safetoken.Offsets(tok, outer.Pos(), outer.End())
75621-	if err != nil {
75622-		return nil, err
75623-	}
75624-	before := src[outerStart:startOffset]
75625-	after := src[endOffset:outerEnd]
75626-	indent, err := calculateIndentation(src, tok, node)
75627-	if err != nil {
75628-		return nil, err
75629-	}
75630-	newLineIndent := "\n" + indent
75631-
75632-	var fullReplacement strings.Builder
75633-	fullReplacement.Write(before)
75634-	if commentBuf.Len() > 0 {
75635-		comments := strings.ReplaceAll(commentBuf.String(), "\n", newLineIndent)
75636-		fullReplacement.WriteString(comments)
75637-	}
75638-	if declBuf.Len() > 0 { // add any initializations, if needed
75639-		initializations := strings.ReplaceAll(declBuf.String(), "\n", newLineIndent) +
75640-			newLineIndent
75641-		fullReplacement.WriteString(initializations)
75642-	}
75643-	fullReplacement.Write(replaceBuf.Bytes()) // call the extracted function
75644-	if ifBuf.Len() > 0 {                      // add the if statement below the function call, if needed
75645-		ifstatement := newLineIndent +
75646-			strings.ReplaceAll(ifBuf.String(), "\n", newLineIndent)
75647-		fullReplacement.WriteString(ifstatement)
75648-	}
75649-	fullReplacement.Write(after)
75650-	fullReplacement.WriteString("\n\n")       // add newlines after the enclosing function
75651-	fullReplacement.Write(newFuncBuf.Bytes()) // insert the extracted function
75652-
75653-	return &analysis.SuggestedFix{
75654-		TextEdits: []analysis.TextEdit{{
75655-			Pos:     outer.Pos(),
75656-			End:     outer.End(),
75657-			NewText: []byte(fullReplacement.String()),
75658-		}},
75659-	}, nil
75660-}
75661-
75662-// adjustRangeForCommentsAndWhiteSpace adjusts the given range to exclude unnecessary leading or
75663-// trailing whitespace characters from selection as well as leading or trailing comments.
75664-// In the following example, each line of the if statement is indented once. There are also two
75665-// extra spaces after the sclosing bracket before the line break and a comment.
75666-//
75667-// \tif (true) {
75668-// \t    _ = 1
75669-// \t} // hello \n
75670-//
75671-// By default, a valid range begins at 'if' and ends at the first whitespace character
75672-// after the '}'. But, users are likely to highlight full lines rather than adjusting
75673-// their cursors for whitespace. To support this use case, we must manually adjust the
75674-// ranges to match the correct AST node. In this particular example, we would adjust
75675-// rng.Start forward to the start of 'if' and rng.End backward to after '}'.
75676-func adjustRangeForCommentsAndWhiteSpace(tok *token.File, start, end token.Pos, content []byte, file *ast.File) (token.Pos, token.Pos, error) {
75677-	// Adjust the end of the range to after leading whitespace and comments.
75678-	prevStart := token.NoPos
75679-	startComment := sort.Search(len(file.Comments), func(i int) bool {
75680-		// Find the index for the first comment that ends after range start.
75681-		return file.Comments[i].End() > start
75682-	})
75683-	for prevStart != start {
75684-		prevStart = start
75685-		// If start is within a comment, move start to the end
75686-		// of the comment group.
75687-		if startComment < len(file.Comments) && file.Comments[startComment].Pos() <= start && start < file.Comments[startComment].End() {
75688-			start = file.Comments[startComment].End()
75689-			startComment++
75690-		}
75691-		// Move forwards to find a non-whitespace character.
75692-		offset, err := safetoken.Offset(tok, start)
75693-		if err != nil {
75694-			return 0, 0, err
75695-		}
75696-		for offset < len(content) && isGoWhiteSpace(content[offset]) {
75697-			offset++
75698-		}
75699-		start = tok.Pos(offset)
75700-	}
75701-
75702-	// Adjust the end of the range to before trailing whitespace and comments.
75703-	prevEnd := token.NoPos
75704-	endComment := sort.Search(len(file.Comments), func(i int) bool {
75705-		// Find the index for the first comment that ends after the range end.
75706-		return file.Comments[i].End() >= end
75707-	})
75708-	// Search will return n if not found, so we need to adjust if there are no
75709-	// comments that would match.
75710-	if endComment == len(file.Comments) {
75711-		endComment = -1
75712-	}
75713-	for prevEnd != end {
75714-		prevEnd = end
75715-		// If end is within a comment, move end to the start
75716-		// of the comment group.
75717-		if endComment >= 0 && file.Comments[endComment].Pos() < end && end <= file.Comments[endComment].End() {
75718-			end = file.Comments[endComment].Pos()
75719-			endComment--
75720-		}
75721-		// Move backwards to find a non-whitespace character.
75722-		offset, err := safetoken.Offset(tok, end)
75723-		if err != nil {
75724-			return 0, 0, err
75725-		}
75726-		for offset > 0 && isGoWhiteSpace(content[offset-1]) {
75727-			offset--
75728-		}
75729-		end = tok.Pos(offset)
75730-	}
75731-
75732-	return start, end, nil
75733-}
75734-
75735-// isGoWhiteSpace returns true if b is a considered white space in
75736-// Go as defined by scanner.GoWhitespace.
75737-func isGoWhiteSpace(b byte) bool {
75738-	return uint64(scanner.GoWhitespace)&(1<<uint(b)) != 0
75739-}
75740-
75741-// findParent finds the parent AST node of the given target node, if the target is a
75742-// descendant of the starting node.
75743-func findParent(start ast.Node, target ast.Node) ast.Node {
75744-	var parent ast.Node
75745-	analysisinternal.WalkASTWithParent(start, func(n, p ast.Node) bool {
75746-		if n == target {
75747-			parent = p
75748-			return false
75749-		}
75750-		return true
75751-	})
75752-	return parent
75753-}
75754-
75755-// variable describes the status of a variable within a selection.
75756-type variable struct {
75757-	obj types.Object
75758-
75759-	// free reports whether the variable is a free variable, meaning it should
75760-	// be a parameter to the extracted function.
75761-	free bool
75762-
75763-	// assigned reports whether the variable is assigned to in the selection.
75764-	assigned bool
75765-
75766-	// defined reports whether the variable is defined in the selection.
75767-	defined bool
75768-}
75769-
75770-// collectFreeVars maps each identifier in the given range to whether it is "free."
75771-// Given a range, a variable in that range is defined as "free" if it is declared
75772-// outside of the range and neither at the file scope nor package scope. These free
75773-// variables will be used as arguments in the extracted function. It also returns a
75774-// list of identifiers that may need to be returned by the extracted function.
75775-// Some of the code in this function has been adapted from tools/cmd/guru/freevars.go.
75776-func collectFreeVars(info *types.Info, file *ast.File, fileScope, pkgScope *types.Scope, start, end token.Pos, node ast.Node) ([]*variable, error) {
75777-	// id returns non-nil if n denotes an object that is referenced by the span
75778-	// and defined either within the span or in the lexical environment. The bool
75779-	// return value acts as an indicator for where it was defined.
75780-	id := func(n *ast.Ident) (types.Object, bool) {
75781-		obj := info.Uses[n]
75782-		if obj == nil {
75783-			return info.Defs[n], false
75784-		}
75785-		if obj.Name() == "_" {
75786-			return nil, false // exclude objects denoting '_'
75787-		}
75788-		if _, ok := obj.(*types.PkgName); ok {
75789-			return nil, false // imported package
75790-		}
75791-		if !(file.Pos() <= obj.Pos() && obj.Pos() <= file.End()) {
75792-			return nil, false // not defined in this file
75793-		}
75794-		scope := obj.Parent()
75795-		if scope == nil {
75796-			return nil, false // e.g. interface method, struct field
75797-		}
75798-		if scope == fileScope || scope == pkgScope {
75799-			return nil, false // defined at file or package scope
75800-		}
75801-		if start <= obj.Pos() && obj.Pos() <= end {
75802-			return obj, false // defined within selection => not free
75803-		}
75804-		return obj, true
75805-	}
75806-	// sel returns non-nil if n denotes a selection o.x.y that is referenced by the
75807-	// span and defined either within the span or in the lexical environment. The bool
75808-	// return value acts as an indicator for where it was defined.
75809-	var sel func(n *ast.SelectorExpr) (types.Object, bool)
75810-	sel = func(n *ast.SelectorExpr) (types.Object, bool) {
75811-		switch x := astutil.Unparen(n.X).(type) {
75812-		case *ast.SelectorExpr:
75813-			return sel(x)
75814-		case *ast.Ident:
75815-			return id(x)
75816-		}
75817-		return nil, false
75818-	}
75819-	seen := make(map[types.Object]*variable)
75820-	firstUseIn := make(map[types.Object]token.Pos)
75821-	var vars []types.Object
75822-	ast.Inspect(node, func(n ast.Node) bool {
75823-		if n == nil {
75824-			return false
75825-		}
75826-		if start <= n.Pos() && n.End() <= end {
75827-			var obj types.Object
75828-			var isFree, prune bool
75829-			switch n := n.(type) {
75830-			case *ast.Ident:
75831-				obj, isFree = id(n)
75832-			case *ast.SelectorExpr:
75833-				obj, isFree = sel(n)
75834-				prune = true
75835-			}
75836-			if obj != nil {
75837-				seen[obj] = &variable{
75838-					obj:  obj,
75839-					free: isFree,
75840-				}
75841-				vars = append(vars, obj)
75842-				// Find the first time that the object is used in the selection.
75843-				first, ok := firstUseIn[obj]
75844-				if !ok || n.Pos() < first {
75845-					firstUseIn[obj] = n.Pos()
75846-				}
75847-				if prune {
75848-					return false
75849-				}
75850-			}
75851-		}
75852-		return n.Pos() <= end
75853-	})
75854-
75855-	// Find identifiers that are initialized or whose values are altered at some
75856-	// point in the selected block. For example, in a selected block from lines 2-4,
75857-	// variables x, y, and z are included in assigned. However, in a selected block
75858-	// from lines 3-4, only variables y and z are included in assigned.
75859-	//
75860-	// 1: var a int
75861-	// 2: var x int
75862-	// 3: y := 3
75863-	// 4: z := x + a
75864-	//
75865-	ast.Inspect(node, func(n ast.Node) bool {
75866-		if n == nil {
75867-			return false
75868-		}
75869-		if n.Pos() < start || n.End() > end {
75870-			return n.Pos() <= end
75871-		}
75872-		switch n := n.(type) {
75873-		case *ast.AssignStmt:
75874-			for _, assignment := range n.Lhs {
75875-				lhs, ok := assignment.(*ast.Ident)
75876-				if !ok {
75877-					continue
75878-				}
75879-				obj, _ := id(lhs)
75880-				if obj == nil {
75881-					continue
75882-				}
75883-				if _, ok := seen[obj]; !ok {
75884-					continue
75885-				}
75886-				seen[obj].assigned = true
75887-				if n.Tok != token.DEFINE {
75888-					continue
75889-				}
75890-				// Find identifiers that are defined prior to being used
75891-				// elsewhere in the selection.
75892-				// TODO: Include identifiers that are assigned prior to being
75893-				// used elsewhere in the selection. Then, change the assignment
75894-				// to a definition in the extracted function.
75895-				if firstUseIn[obj] != lhs.Pos() {
75896-					continue
75897-				}
75898-				// Ensure that the object is not used in its own re-definition.
75899-				// For example:
75900-				// var f float64
75901-				// f, e := math.Frexp(f)
75902-				for _, expr := range n.Rhs {
75903-					if referencesObj(info, expr, obj) {
75904-						continue
75905-					}
75906-					if _, ok := seen[obj]; !ok {
75907-						continue
75908-					}
75909-					seen[obj].defined = true
75910-					break
75911-				}
75912-			}
75913-			return false
75914-		case *ast.DeclStmt:
75915-			gen, ok := n.Decl.(*ast.GenDecl)
75916-			if !ok {
75917-				return false
75918-			}
75919-			for _, spec := range gen.Specs {
75920-				vSpecs, ok := spec.(*ast.ValueSpec)
75921-				if !ok {
75922-					continue
75923-				}
75924-				for _, vSpec := range vSpecs.Names {
75925-					obj, _ := id(vSpec)
75926-					if obj == nil {
75927-						continue
75928-					}
75929-					if _, ok := seen[obj]; !ok {
75930-						continue
75931-					}
75932-					seen[obj].assigned = true
75933-				}
75934-			}
75935-			return false
75936-		case *ast.IncDecStmt:
75937-			if ident, ok := n.X.(*ast.Ident); !ok {
75938-				return false
75939-			} else if obj, _ := id(ident); obj == nil {
75940-				return false
75941-			} else {
75942-				if _, ok := seen[obj]; !ok {
75943-					return false
75944-				}
75945-				seen[obj].assigned = true
75946-			}
75947-		}
75948-		return true
75949-	})
75950-	var variables []*variable
75951-	for _, obj := range vars {
75952-		v, ok := seen[obj]
75953-		if !ok {
75954-			return nil, fmt.Errorf("no seen types.Object for %v", obj)
75955-		}
75956-		variables = append(variables, v)
75957-	}
75958-	return variables, nil
75959-}
75960-
75961-// referencesObj checks whether the given object appears in the given expression.
75962-func referencesObj(info *types.Info, expr ast.Expr, obj types.Object) bool {
75963-	var hasObj bool
75964-	ast.Inspect(expr, func(n ast.Node) bool {
75965-		if n == nil {
75966-			return false
75967-		}
75968-		ident, ok := n.(*ast.Ident)
75969-		if !ok {
75970-			return true
75971-		}
75972-		objUse := info.Uses[ident]
75973-		if obj == objUse {
75974-			hasObj = true
75975-			return false
75976-		}
75977-		return false
75978-	})
75979-	return hasObj
75980-}
75981-
75982-type fnExtractParams struct {
75983-	tok        *token.File
75984-	start, end token.Pos
75985-	path       []ast.Node
75986-	outer      *ast.FuncDecl
75987-	node       ast.Node
75988-}
75989-
75990-// CanExtractFunction reports whether the code in the given range can be
75991-// extracted to a function.
75992-func CanExtractFunction(tok *token.File, start, end token.Pos, src []byte, file *ast.File) (*fnExtractParams, bool, bool, error) {
75993-	if start == end {
75994-		return nil, false, false, fmt.Errorf("start and end are equal")
75995-	}
75996-	var err error
75997-	start, end, err = adjustRangeForCommentsAndWhiteSpace(tok, start, end, src, file)
75998-	if err != nil {
75999-		return nil, false, false, err
76000-	}
76001-	path, _ := astutil.PathEnclosingInterval(file, start, end)
76002-	if len(path) == 0 {
76003-		return nil, false, false, fmt.Errorf("no path enclosing interval")
76004-	}
76005-	// Node that encloses the selection must be a statement.
76006-	// TODO: Support function extraction for an expression.
76007-	_, ok := path[0].(ast.Stmt)
76008-	if !ok {
76009-		return nil, false, false, fmt.Errorf("node is not a statement")
76010-	}
76011-
76012-	// Find the function declaration that encloses the selection.
76013-	var outer *ast.FuncDecl
76014-	for _, p := range path {
76015-		if p, ok := p.(*ast.FuncDecl); ok {
76016-			outer = p
76017-			break
76018-		}
76019-	}
76020-	if outer == nil {
76021-		return nil, false, false, fmt.Errorf("no enclosing function")
76022-	}
76023-
76024-	// Find the nodes at the start and end of the selection.
76025-	var startNode, endNode ast.Node
76026-	ast.Inspect(outer, func(n ast.Node) bool {
76027-		if n == nil {
76028-			return false
76029-		}
76030-		// Do not override 'start' with a node that begins at the same location
76031-		// but is nested further from 'outer'.
76032-		if startNode == nil && n.Pos() == start && n.End() <= end {
76033-			startNode = n
76034-		}
76035-		if endNode == nil && n.End() == end && n.Pos() >= start {
76036-			endNode = n
76037-		}
76038-		return n.Pos() <= end
76039-	})
76040-	if startNode == nil || endNode == nil {
76041-		return nil, false, false, fmt.Errorf("range does not map to AST nodes")
76042-	}
76043-	// If the region is a blockStmt, use the first and last nodes in the block
76044-	// statement.
76045-	// <rng.start>{ ... }<rng.end> => { <rng.start>...<rng.end> }
76046-	if blockStmt, ok := startNode.(*ast.BlockStmt); ok {
76047-		if len(blockStmt.List) == 0 {
76048-			return nil, false, false, fmt.Errorf("range maps to empty block statement")
76049-		}
76050-		startNode, endNode = blockStmt.List[0], blockStmt.List[len(blockStmt.List)-1]
76051-		start, end = startNode.Pos(), endNode.End()
76052-	}
76053-	return &fnExtractParams{
76054-		tok:   tok,
76055-		start: start,
76056-		end:   end,
76057-		path:  path,
76058-		outer: outer,
76059-		node:  startNode,
76060-	}, true, outer.Recv != nil, nil
76061-}
76062-
76063-// objUsed checks if the object is used within the range. It returns the first
76064-// occurrence of the object in the range, if it exists.
76065-func objUsed(info *types.Info, start, end token.Pos, obj types.Object) (bool, *ast.Ident) {
76066-	var firstUse *ast.Ident
76067-	for id, objUse := range info.Uses {
76068-		if obj != objUse {
76069-			continue
76070-		}
76071-		if id.Pos() < start || id.End() > end {
76072-			continue
76073-		}
76074-		if firstUse == nil || id.Pos() < firstUse.Pos() {
76075-			firstUse = id
76076-		}
76077-	}
76078-	return firstUse != nil, firstUse
76079-}
76080-
76081-// varOverridden traverses the given AST node until we find the given identifier. Then, we
76082-// examine the occurrence of the given identifier and check for (1) whether the identifier
76083-// is being redefined. If the identifier is free, we also check for (2) whether the identifier
76084-// is being reassigned. We will not include an identifier in the return statement of the
76085-// extracted function if it meets one of the above conditions.
76086-func varOverridden(info *types.Info, firstUse *ast.Ident, obj types.Object, isFree bool, node ast.Node) bool {
76087-	var isOverriden bool
76088-	ast.Inspect(node, func(n ast.Node) bool {
76089-		if n == nil {
76090-			return false
76091-		}
76092-		assignment, ok := n.(*ast.AssignStmt)
76093-		if !ok {
76094-			return true
76095-		}
76096-		// A free variable is initialized prior to the selection. We can always reassign
76097-		// this variable after the selection because it has already been defined.
76098-		// Conversely, a non-free variable is initialized within the selection. Thus, we
76099-		// cannot reassign this variable after the selection unless it is initialized and
76100-		// returned by the extracted function.
76101-		if !isFree && assignment.Tok == token.ASSIGN {
76102-			return false
76103-		}
76104-		for _, assigned := range assignment.Lhs {
76105-			ident, ok := assigned.(*ast.Ident)
76106-			// Check if we found the first use of the identifier.
76107-			if !ok || ident != firstUse {
76108-				continue
76109-			}
76110-			objUse := info.Uses[ident]
76111-			if objUse == nil || objUse != obj {
76112-				continue
76113-			}
76114-			// Ensure that the object is not used in its own definition.
76115-			// For example:
76116-			// var f float64
76117-			// f, e := math.Frexp(f)
76118-			for _, expr := range assignment.Rhs {
76119-				if referencesObj(info, expr, obj) {
76120-					return false
76121-				}
76122-			}
76123-			isOverriden = true
76124-			return false
76125-		}
76126-		return false
76127-	})
76128-	return isOverriden
76129-}
76130-
76131-// parseBlockStmt generates an AST file from the given text. We then return the portion of the
76132-// file that represents the text.
76133-func parseBlockStmt(fset *token.FileSet, src []byte) (*ast.BlockStmt, error) {
76134-	text := "package main\nfunc _() { " + string(src) + " }"
76135-	extract, err := parser.ParseFile(fset, "", text, 0)
76136-	if err != nil {
76137-		return nil, err
76138-	}
76139-	if len(extract.Decls) == 0 {
76140-		return nil, fmt.Errorf("parsed file does not contain any declarations")
76141-	}
76142-	decl, ok := extract.Decls[0].(*ast.FuncDecl)
76143-	if !ok {
76144-		return nil, fmt.Errorf("parsed file does not contain expected function declaration")
76145-	}
76146-	if decl.Body == nil {
76147-		return nil, fmt.Errorf("extracted function has no body")
76148-	}
76149-	return decl.Body, nil
76150-}
76151-
76152-// generateReturnInfo generates the information we need to adjust the return statements and
76153-// signature of the extracted function. We prepare names, signatures, and "zero values" that
76154-// represent the new variables. We also use this information to construct the if statement that
76155-// is inserted below the call to the extracted function.
76156-func generateReturnInfo(enclosing *ast.FuncType, pkg *types.Package, path []ast.Node, file *ast.File, info *types.Info, fset *token.FileSet, pos token.Pos, hasNonNestedReturns bool) ([]*returnVariable, *ast.IfStmt, error) {
76157-	var retVars []*returnVariable
76158-	var cond *ast.Ident
76159-	if !hasNonNestedReturns {
76160-		// Generate information for the added bool value.
76161-		name, _ := generateAvailableIdentifier(pos, file, path, info, "shouldReturn", 0)
76162-		cond = &ast.Ident{Name: name}
76163-		retVars = append(retVars, &returnVariable{
76164-			name:    cond,
76165-			decl:    &ast.Field{Type: ast.NewIdent("bool")},
76166-			zeroVal: ast.NewIdent("false"),
76167-		})
76168-	}
76169-	// Generate information for the values in the return signature of the enclosing function.
76170-	if enclosing.Results != nil {
76171-		idx := 0
76172-		for _, field := range enclosing.Results.List {
76173-			typ := info.TypeOf(field.Type)
76174-			if typ == nil {
76175-				return nil, nil, fmt.Errorf(
76176-					"failed type conversion, AST expression: %T", field.Type)
76177-			}
76178-			expr := analysisinternal.TypeExpr(file, pkg, typ)
76179-			if expr == nil {
76180-				return nil, nil, fmt.Errorf("nil AST expression")
76181-			}
76182-			var name string
76183-			name, idx = generateAvailableIdentifier(pos, file,
76184-				path, info, "returnValue", idx)
76185-			retVars = append(retVars, &returnVariable{
76186-				name:    ast.NewIdent(name),
76187-				decl:    &ast.Field{Type: expr},
76188-				zeroVal: analysisinternal.ZeroValue(file, pkg, typ),
76189-			})
76190-		}
76191-	}
76192-	var ifReturn *ast.IfStmt
76193-	if !hasNonNestedReturns {
76194-		// Create the return statement for the enclosing function. We must exclude the variable
76195-		// for the condition of the if statement (cond) from the return statement.
76196-		ifReturn = &ast.IfStmt{
76197-			Cond: cond,
76198-			Body: &ast.BlockStmt{
76199-				List: []ast.Stmt{&ast.ReturnStmt{Results: getNames(retVars)[1:]}},
76200-			},
76201-		}
76202-	}
76203-	return retVars, ifReturn, nil
76204-}
76205-
76206-// adjustReturnStatements adds "zero values" of the given types to each return statement
76207-// in the given AST node.
76208-func adjustReturnStatements(returnTypes []*ast.Field, seenVars map[types.Object]ast.Expr, fset *token.FileSet, file *ast.File, pkg *types.Package, extractedBlock *ast.BlockStmt) error {
76209-	var zeroVals []ast.Expr
76210-	// Create "zero values" for each type.
76211-	for _, returnType := range returnTypes {
76212-		var val ast.Expr
76213-		for obj, typ := range seenVars {
76214-			if typ != returnType.Type {
76215-				continue
76216-			}
76217-			val = analysisinternal.ZeroValue(file, pkg, obj.Type())
76218-			break
76219-		}
76220-		if val == nil {
76221-			return fmt.Errorf(
76222-				"could not find matching AST expression for %T", returnType.Type)
76223-		}
76224-		zeroVals = append(zeroVals, val)
76225-	}
76226-	// Add "zero values" to each return statement.
76227-	// The bool reports whether the enclosing function should return after calling the
76228-	// extracted function. We set the bool to 'true' because, if these return statements
76229-	// execute, the extracted function terminates early, and the enclosing function must
76230-	// return as well.
76231-	zeroVals = append(zeroVals, ast.NewIdent("true"))
76232-	ast.Inspect(extractedBlock, func(n ast.Node) bool {
76233-		if n == nil {
76234-			return false
76235-		}
76236-		if n, ok := n.(*ast.ReturnStmt); ok {
76237-			n.Results = append(zeroVals, n.Results...)
76238-			return false
76239-		}
76240-		return true
76241-	})
76242-	return nil
76243-}
76244-
76245-// generateFuncCall constructs a call expression for the extracted function, described by the
76246-// given parameters and return variables.
76247-func generateFuncCall(hasNonNestedReturn, hasReturnVals bool, params, returns []ast.Expr, name string, token token.Token, selector string) ast.Node {
76248-	var replace ast.Node
76249-	callExpr := &ast.CallExpr{
76250-		Fun:  ast.NewIdent(name),
76251-		Args: params,
76252-	}
76253-	if selector != "" {
76254-		callExpr = &ast.CallExpr{
76255-			Fun: &ast.SelectorExpr{
76256-				X:   ast.NewIdent(selector),
76257-				Sel: ast.NewIdent(name),
76258-			},
76259-			Args: params,
76260-		}
76261-	}
76262-	if hasReturnVals {
76263-		if hasNonNestedReturn {
76264-			// Create a return statement that returns the result of the function call.
76265-			replace = &ast.ReturnStmt{
76266-				Return:  0,
76267-				Results: []ast.Expr{callExpr},
76268-			}
76269-		} else {
76270-			// Assign the result of the function call.
76271-			replace = &ast.AssignStmt{
76272-				Lhs: returns,
76273-				Tok: token,
76274-				Rhs: []ast.Expr{callExpr},
76275-			}
76276-		}
76277-	} else {
76278-		replace = callExpr
76279-	}
76280-	return replace
76281-}
76282-
76283-// initializeVars creates variable declarations, if needed.
76284-// Our preference is to replace the selected block with an "x, y, z := fn()" style
76285-// assignment statement. We can use this style when all of the variables in the
76286-// extracted function's return statement are either not defined prior to the extracted block
76287-// or can be safely redefined. However, for example, if z is already defined
76288-// in a different scope, we replace the selected block with:
76289-//
76290-// var x int
76291-// var y string
76292-// x, y, z = fn()
76293-func initializeVars(uninitialized []types.Object, retVars []*returnVariable, seenUninitialized map[types.Object]struct{}, seenVars map[types.Object]ast.Expr) []ast.Stmt {
76294-	var declarations []ast.Stmt
76295-	for _, obj := range uninitialized {
76296-		if _, ok := seenUninitialized[obj]; ok {
76297-			continue
76298-		}
76299-		seenUninitialized[obj] = struct{}{}
76300-		valSpec := &ast.ValueSpec{
76301-			Names: []*ast.Ident{ast.NewIdent(obj.Name())},
76302-			Type:  seenVars[obj],
76303-		}
76304-		genDecl := &ast.GenDecl{
76305-			Tok:   token.VAR,
76306-			Specs: []ast.Spec{valSpec},
76307-		}
76308-		declarations = append(declarations, &ast.DeclStmt{Decl: genDecl})
76309-	}
76310-	// Each variable added from a return statement in the selection
76311-	// must be initialized.
76312-	for i, retVar := range retVars {
76313-		n := retVar.name.(*ast.Ident)
76314-		valSpec := &ast.ValueSpec{
76315-			Names: []*ast.Ident{n},
76316-			Type:  retVars[i].decl.Type,
76317-		}
76318-		genDecl := &ast.GenDecl{
76319-			Tok:   token.VAR,
76320-			Specs: []ast.Spec{valSpec},
76321-		}
76322-		declarations = append(declarations, &ast.DeclStmt{Decl: genDecl})
76323-	}
76324-	return declarations
76325-}
76326-
76327-// getNames returns the names from the given list of returnVariable.
76328-func getNames(retVars []*returnVariable) []ast.Expr {
76329-	var names []ast.Expr
76330-	for _, retVar := range retVars {
76331-		names = append(names, retVar.name)
76332-	}
76333-	return names
76334-}
76335-
76336-// getZeroVals returns the "zero values" from the given list of returnVariable.
76337-func getZeroVals(retVars []*returnVariable) []ast.Expr {
76338-	var zvs []ast.Expr
76339-	for _, retVar := range retVars {
76340-		zvs = append(zvs, retVar.zeroVal)
76341-	}
76342-	return zvs
76343-}
76344-
76345-// getDecls returns the declarations from the given list of returnVariable.
76346-func getDecls(retVars []*returnVariable) []*ast.Field {
76347-	var decls []*ast.Field
76348-	for _, retVar := range retVars {
76349-		decls = append(decls, retVar.decl)
76350-	}
76351-	return decls
76352-}
76353diff -urN a/gopls/internal/lsp/source/fix.go b/gopls/internal/lsp/source/fix.go
76354--- a/gopls/internal/lsp/source/fix.go	2000-01-01 00:00:00.000000000 -0000
76355+++ b/gopls/internal/lsp/source/fix.go	1970-01-01 00:00:00.000000000 +0000
76356@@ -1,138 +0,0 @@
76357-// Copyright 2020 The Go Authors. All rights reserved.
76358-// Use of this source code is governed by a BSD-style
76359-// license that can be found in the LICENSE file.
76360-
76361-package source
76362-
76363-import (
76364-	"context"
76365-	"fmt"
76366-	"go/ast"
76367-	"go/token"
76368-	"go/types"
76369-
76370-	"golang.org/x/tools/go/analysis"
76371-	"golang.org/x/tools/gopls/internal/lsp/analysis/fillstruct"
76372-	"golang.org/x/tools/gopls/internal/lsp/analysis/undeclaredname"
76373-	"golang.org/x/tools/gopls/internal/lsp/protocol"
76374-	"golang.org/x/tools/gopls/internal/span"
76375-	"golang.org/x/tools/internal/bug"
76376-)
76377-
76378-type (
76379-	// SuggestedFixFunc is a function used to get the suggested fixes for a given
76380-	// gopls command, some of which are provided by go/analysis.Analyzers. Some of
76381-	// the analyzers in internal/lsp/analysis are not efficient enough to include
76382-	// suggested fixes with their diagnostics, so we have to compute them
76383-	// separately. Such analyzers should provide a function with a signature of
76384-	// SuggestedFixFunc.
76385-	//
76386-	// The returned FileSet must map all token.Pos found in the suggested text
76387-	// edits.
76388-	SuggestedFixFunc  func(ctx context.Context, snapshot Snapshot, fh FileHandle, pRng protocol.Range) (*token.FileSet, *analysis.SuggestedFix, error)
76389-	singleFileFixFunc func(fset *token.FileSet, start, end token.Pos, src []byte, file *ast.File, pkg *types.Package, info *types.Info) (*analysis.SuggestedFix, error)
76390-)
76391-
76392-const (
76393-	FillStruct      = "fill_struct"
76394-	StubMethods     = "stub_methods"
76395-	UndeclaredName  = "undeclared_name"
76396-	ExtractVariable = "extract_variable"
76397-	ExtractFunction = "extract_function"
76398-	ExtractMethod   = "extract_method"
76399-)
76400-
76401-// suggestedFixes maps a suggested fix command id to its handler.
76402-var suggestedFixes = map[string]SuggestedFixFunc{
76403-	FillStruct:      singleFile(fillstruct.SuggestedFix),
76404-	UndeclaredName:  singleFile(undeclaredname.SuggestedFix),
76405-	ExtractVariable: singleFile(extractVariable),
76406-	ExtractFunction: singleFile(extractFunction),
76407-	ExtractMethod:   singleFile(extractMethod),
76408-	StubMethods:     stubSuggestedFixFunc,
76409-}
76410-
76411-// singleFile calls analyzers that expect inputs for a single file
76412-func singleFile(sf singleFileFixFunc) SuggestedFixFunc {
76413-	return func(ctx context.Context, snapshot Snapshot, fh FileHandle, pRng protocol.Range) (*token.FileSet, *analysis.SuggestedFix, error) {
76414-		pkg, pgf, err := PackageForFile(ctx, snapshot, fh.URI(), NarrowestPackage)
76415-		if err != nil {
76416-			return nil, nil, err
76417-		}
76418-		start, end, err := pgf.RangePos(pRng)
76419-		if err != nil {
76420-			return nil, nil, err
76421-		}
76422-		fix, err := sf(pkg.FileSet(), start, end, pgf.Src, pgf.File, pkg.GetTypes(), pkg.GetTypesInfo())
76423-		return pkg.FileSet(), fix, err
76424-	}
76425-}
76426-
76427-func SuggestedFixFromCommand(cmd protocol.Command, kind protocol.CodeActionKind) SuggestedFix {
76428-	return SuggestedFix{
76429-		Title:      cmd.Title,
76430-		Command:    &cmd,
76431-		ActionKind: kind,
76432-	}
76433-}
76434-
76435-// ApplyFix applies the command's suggested fix to the given file and
76436-// range, returning the resulting edits.
76437-func ApplyFix(ctx context.Context, fix string, snapshot Snapshot, fh FileHandle, pRng protocol.Range) ([]protocol.TextDocumentEdit, error) {
76438-	handler, ok := suggestedFixes[fix]
76439-	if !ok {
76440-		return nil, fmt.Errorf("no suggested fix function for %s", fix)
76441-	}
76442-	fset, suggestion, err := handler(ctx, snapshot, fh, pRng)
76443-	if err != nil {
76444-		return nil, err
76445-	}
76446-	if suggestion == nil {
76447-		return nil, nil
76448-	}
76449-	editsPerFile := map[span.URI]*protocol.TextDocumentEdit{}
76450-	for _, edit := range suggestion.TextEdits {
76451-		tokFile := fset.File(edit.Pos)
76452-		if tokFile == nil {
76453-			return nil, bug.Errorf("no file for edit position")
76454-		}
76455-		end := edit.End
76456-		if !end.IsValid() {
76457-			end = edit.Pos
76458-		}
76459-		fh, err := snapshot.GetFile(ctx, span.URIFromPath(tokFile.Name()))
76460-		if err != nil {
76461-			return nil, err
76462-		}
76463-		te, ok := editsPerFile[fh.URI()]
76464-		if !ok {
76465-			te = &protocol.TextDocumentEdit{
76466-				TextDocument: protocol.OptionalVersionedTextDocumentIdentifier{
76467-					Version: fh.Version(),
76468-					TextDocumentIdentifier: protocol.TextDocumentIdentifier{
76469-						URI: protocol.URIFromSpanURI(fh.URI()),
76470-					},
76471-				},
76472-			}
76473-			editsPerFile[fh.URI()] = te
76474-		}
76475-		content, err := fh.Read()
76476-		if err != nil {
76477-			return nil, err
76478-		}
76479-		m := protocol.NewMapper(fh.URI(), content)
76480-		rng, err := m.PosRange(tokFile, edit.Pos, end)
76481-		if err != nil {
76482-			return nil, err
76483-		}
76484-		te.Edits = append(te.Edits, protocol.TextEdit{
76485-			Range:   rng,
76486-			NewText: string(edit.NewText),
76487-		})
76488-	}
76489-	var edits []protocol.TextDocumentEdit
76490-	for _, edit := range editsPerFile {
76491-		edits = append(edits, *edit)
76492-	}
76493-	return edits, nil
76494-}
76495diff -urN a/gopls/internal/lsp/source/folding_range.go b/gopls/internal/lsp/source/folding_range.go
76496--- a/gopls/internal/lsp/source/folding_range.go	2000-01-01 00:00:00.000000000 -0000
76497+++ b/gopls/internal/lsp/source/folding_range.go	1970-01-01 00:00:00.000000000 +0000
76498@@ -1,193 +0,0 @@
76499-// Copyright 2019 The Go Authors. All rights reserved.
76500-// Use of this source code is governed by a BSD-style
76501-// license that can be found in the LICENSE file.
76502-
76503-package source
76504-
76505-import (
76506-	"context"
76507-	"go/ast"
76508-	"go/token"
76509-	"sort"
76510-	"strings"
76511-
76512-	"golang.org/x/tools/gopls/internal/lsp/protocol"
76513-	"golang.org/x/tools/internal/bug"
76514-)
76515-
76516-// FoldingRangeInfo holds range and kind info of folding for an ast.Node
76517-type FoldingRangeInfo struct {
76518-	MappedRange protocol.MappedRange
76519-	Kind        protocol.FoldingRangeKind
76520-}
76521-
76522-// FoldingRange gets all of the folding range for f.
76523-func FoldingRange(ctx context.Context, snapshot Snapshot, fh FileHandle, lineFoldingOnly bool) (ranges []*FoldingRangeInfo, err error) {
76524-	// TODO(suzmue): consider limiting the number of folding ranges returned, and
76525-	// implement a way to prioritize folding ranges in that case.
76526-	pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
76527-	if err != nil {
76528-		return nil, err
76529-	}
76530-
76531-	// With parse errors, we wouldn't be able to produce accurate folding info.
76532-	// LSP protocol (3.16) currently does not have a way to handle this case
76533-	// (https://github.com/microsoft/language-server-protocol/issues/1200).
76534-	// We cannot return an error either because we are afraid some editors
76535-	// may not handle errors nicely. As a workaround, we now return an empty
76536-	// result and let the client handle this case by double check the file
76537-	// contents (i.e. if the file is not empty and the folding range result
76538-	// is empty, raise an internal error).
76539-	if pgf.ParseErr != nil {
76540-		return nil, nil
76541-	}
76542-
76543-	// Get folding ranges for comments separately as they are not walked by ast.Inspect.
76544-	ranges = append(ranges, commentsFoldingRange(pgf)...)
76545-
76546-	visit := func(n ast.Node) bool {
76547-		rng := foldingRangeFunc(pgf, n, lineFoldingOnly)
76548-		if rng != nil {
76549-			ranges = append(ranges, rng)
76550-		}
76551-		return true
76552-	}
76553-	// Walk the ast and collect folding ranges.
76554-	ast.Inspect(pgf.File, visit)
76555-
76556-	sort.Slice(ranges, func(i, j int) bool {
76557-		irng := ranges[i].MappedRange.Range()
76558-		jrng := ranges[j].MappedRange.Range()
76559-		return protocol.CompareRange(irng, jrng) < 0
76560-	})
76561-
76562-	return ranges, nil
76563-}
76564-
76565-// foldingRangeFunc calculates the line folding range for ast.Node n
76566-func foldingRangeFunc(pgf *ParsedGoFile, n ast.Node, lineFoldingOnly bool) *FoldingRangeInfo {
76567-	// TODO(suzmue): include trailing empty lines before the closing
76568-	// parenthesis/brace.
76569-	var kind protocol.FoldingRangeKind
76570-	var start, end token.Pos
76571-	switch n := n.(type) {
76572-	case *ast.BlockStmt:
76573-		// Fold between positions of or lines between "{" and "}".
76574-		var startList, endList token.Pos
76575-		if num := len(n.List); num != 0 {
76576-			startList, endList = n.List[0].Pos(), n.List[num-1].End()
76577-		}
76578-		start, end = validLineFoldingRange(pgf.Tok, n.Lbrace, n.Rbrace, startList, endList, lineFoldingOnly)
76579-	case *ast.CaseClause:
76580-		// Fold from position of ":" to end.
76581-		start, end = n.Colon+1, n.End()
76582-	case *ast.CommClause:
76583-		// Fold from position of ":" to end.
76584-		start, end = n.Colon+1, n.End()
76585-	case *ast.CallExpr:
76586-		// Fold from position of "(" to position of ")".
76587-		start, end = n.Lparen+1, n.Rparen
76588-	case *ast.FieldList:
76589-		// Fold between positions of or lines between opening parenthesis/brace and closing parenthesis/brace.
76590-		var startList, endList token.Pos
76591-		if num := len(n.List); num != 0 {
76592-			startList, endList = n.List[0].Pos(), n.List[num-1].End()
76593-		}
76594-		start, end = validLineFoldingRange(pgf.Tok, n.Opening, n.Closing, startList, endList, lineFoldingOnly)
76595-	case *ast.GenDecl:
76596-		// If this is an import declaration, set the kind to be protocol.Imports.
76597-		if n.Tok == token.IMPORT {
76598-			kind = protocol.Imports
76599-		}
76600-		// Fold between positions of or lines between "(" and ")".
76601-		var startSpecs, endSpecs token.Pos
76602-		if num := len(n.Specs); num != 0 {
76603-			startSpecs, endSpecs = n.Specs[0].Pos(), n.Specs[num-1].End()
76604-		}
76605-		start, end = validLineFoldingRange(pgf.Tok, n.Lparen, n.Rparen, startSpecs, endSpecs, lineFoldingOnly)
76606-	case *ast.BasicLit:
76607-		// Fold raw string literals from position of "`" to position of "`".
76608-		if n.Kind == token.STRING && len(n.Value) >= 2 && n.Value[0] == '`' && n.Value[len(n.Value)-1] == '`' {
76609-			start, end = n.Pos(), n.End()
76610-		}
76611-	case *ast.CompositeLit:
76612-		// Fold between positions of or lines between "{" and "}".
76613-		var startElts, endElts token.Pos
76614-		if num := len(n.Elts); num != 0 {
76615-			startElts, endElts = n.Elts[0].Pos(), n.Elts[num-1].End()
76616-		}
76617-		start, end = validLineFoldingRange(pgf.Tok, n.Lbrace, n.Rbrace, startElts, endElts, lineFoldingOnly)
76618-	}
76619-
76620-	// Check that folding positions are valid.
76621-	if !start.IsValid() || !end.IsValid() {
76622-		return nil
76623-	}
76624-	// in line folding mode, do not fold if the start and end lines are the same.
76625-	if lineFoldingOnly && pgf.Tok.Line(start) == pgf.Tok.Line(end) {
76626-		return nil
76627-	}
76628-	mrng, err := pgf.PosMappedRange(start, end)
76629-	if err != nil {
76630-		bug.Errorf("%w", err) // can't happen
76631-	}
76632-	return &FoldingRangeInfo{
76633-		MappedRange: mrng,
76634-		Kind:        kind,
76635-	}
76636-}
76637-
76638-// validLineFoldingRange returns start and end token.Pos for folding range if the range is valid.
76639-// returns token.NoPos otherwise, which fails token.IsValid check
76640-func validLineFoldingRange(tokFile *token.File, open, close, start, end token.Pos, lineFoldingOnly bool) (token.Pos, token.Pos) {
76641-	if lineFoldingOnly {
76642-		if !open.IsValid() || !close.IsValid() {
76643-			return token.NoPos, token.NoPos
76644-		}
76645-
76646-		// Don't want to fold if the start/end is on the same line as the open/close
76647-		// as an example, the example below should *not* fold:
76648-		// var x = [2]string{"d",
76649-		// "e" }
76650-		if tokFile.Line(open) == tokFile.Line(start) ||
76651-			tokFile.Line(close) == tokFile.Line(end) {
76652-			return token.NoPos, token.NoPos
76653-		}
76654-
76655-		return open + 1, end
76656-	}
76657-	return open + 1, close
76658-}
76659-
76660-// commentsFoldingRange returns the folding ranges for all comment blocks in file.
76661-// The folding range starts at the end of the first line of the comment block, and ends at the end of the
76662-// comment block and has kind protocol.Comment.
76663-func commentsFoldingRange(pgf *ParsedGoFile) (comments []*FoldingRangeInfo) {
76664-	tokFile := pgf.Tok
76665-	for _, commentGrp := range pgf.File.Comments {
76666-		startGrpLine, endGrpLine := tokFile.Line(commentGrp.Pos()), tokFile.Line(commentGrp.End())
76667-		if startGrpLine == endGrpLine {
76668-			// Don't fold single line comments.
76669-			continue
76670-		}
76671-
76672-		firstComment := commentGrp.List[0]
76673-		startPos, endLinePos := firstComment.Pos(), firstComment.End()
76674-		startCmmntLine, endCmmntLine := tokFile.Line(startPos), tokFile.Line(endLinePos)
76675-		if startCmmntLine != endCmmntLine {
76676-			// If the first comment spans multiple lines, then we want to have the
76677-			// folding range start at the end of the first line.
76678-			endLinePos = token.Pos(int(startPos) + len(strings.Split(firstComment.Text, "\n")[0]))
76679-		}
76680-		mrng, err := pgf.PosMappedRange(endLinePos, commentGrp.End())
76681-		if err != nil {
76682-			bug.Errorf("%w", err) // can't happen
76683-		}
76684-		comments = append(comments, &FoldingRangeInfo{
76685-			// Fold from the end of the first line comment to the end of the comment block.
76686-			MappedRange: mrng,
76687-			Kind:        protocol.Comment,
76688-		})
76689-	}
76690-	return comments
76691-}
76692diff -urN a/gopls/internal/lsp/source/format.go b/gopls/internal/lsp/source/format.go
76693--- a/gopls/internal/lsp/source/format.go	2000-01-01 00:00:00.000000000 -0000
76694+++ b/gopls/internal/lsp/source/format.go	1970-01-01 00:00:00.000000000 +0000
76695@@ -1,391 +0,0 @@
76696-// Copyright 2018 The Go Authors. All rights reserved.
76697-// Use of this source code is governed by a BSD-style
76698-// license that can be found in the LICENSE file.
76699-
76700-// Package source provides core features for use by Go editors and tools.
76701-package source
76702-
76703-import (
76704-	"bytes"
76705-	"context"
76706-	"fmt"
76707-	"go/ast"
76708-	"go/format"
76709-	"go/parser"
76710-	"go/token"
76711-	"strings"
76712-	"text/scanner"
76713-
76714-	"golang.org/x/tools/gopls/internal/lsp/protocol"
76715-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
76716-	"golang.org/x/tools/internal/diff"
76717-	"golang.org/x/tools/internal/event"
76718-	"golang.org/x/tools/internal/imports"
76719-)
76720-
76721-// Format formats a file with a given range.
76722-func Format(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]protocol.TextEdit, error) {
76723-	ctx, done := event.Start(ctx, "source.Format")
76724-	defer done()
76725-
76726-	// Generated files shouldn't be edited. So, don't format them
76727-	if IsGenerated(ctx, snapshot, fh.URI()) {
76728-		return nil, fmt.Errorf("can't format %q: file is generated", fh.URI().Filename())
76729-	}
76730-
76731-	pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
76732-	if err != nil {
76733-		return nil, err
76734-	}
76735-	// Even if this file has parse errors, it might still be possible to format it.
76736-	// Using format.Node on an AST with errors may result in code being modified.
76737-	// Attempt to format the source of this file instead.
76738-	if pgf.ParseErr != nil {
76739-		formatted, err := formatSource(ctx, fh)
76740-		if err != nil {
76741-			return nil, err
76742-		}
76743-		return computeTextEdits(ctx, snapshot, pgf, string(formatted))
76744-	}
76745-
76746-	// format.Node changes slightly from one release to another, so the version
76747-	// of Go used to build the LSP server will determine how it formats code.
76748-	// This should be acceptable for all users, who likely be prompted to rebuild
76749-	// the LSP server on each Go release.
76750-	buf := &bytes.Buffer{}
76751-	fset := FileSetFor(pgf.Tok)
76752-	if err := format.Node(buf, fset, pgf.File); err != nil {
76753-		return nil, err
76754-	}
76755-	formatted := buf.String()
76756-
76757-	// Apply additional formatting, if any is supported. Currently, the only
76758-	// supported additional formatter is gofumpt.
76759-	if format := snapshot.View().Options().GofumptFormat; snapshot.View().Options().Gofumpt && format != nil {
76760-		// gofumpt can customize formatting based on language version and module
76761-		// path, if available.
76762-		//
76763-		// Try to derive this information, but fall-back on the default behavior.
76764-		//
76765-		// TODO: under which circumstances can we fail to find module information?
76766-		// Can this, for example, result in inconsistent formatting across saves,
76767-		// due to pending calls to packages.Load?
76768-		var langVersion, modulePath string
76769-		mds, err := snapshot.MetadataForFile(ctx, fh.URI())
76770-		if err == nil && len(mds) > 0 {
76771-			if mi := mds[0].Module; mi != nil {
76772-				langVersion = mi.GoVersion
76773-				modulePath = mi.Path
76774-			}
76775-		}
76776-		b, err := format(ctx, langVersion, modulePath, buf.Bytes())
76777-		if err != nil {
76778-			return nil, err
76779-		}
76780-		formatted = string(b)
76781-	}
76782-	return computeTextEdits(ctx, snapshot, pgf, formatted)
76783-}
76784-
76785-func formatSource(ctx context.Context, fh FileHandle) ([]byte, error) {
76786-	_, done := event.Start(ctx, "source.formatSource")
76787-	defer done()
76788-
76789-	data, err := fh.Read()
76790-	if err != nil {
76791-		return nil, err
76792-	}
76793-	return format.Source(data)
76794-}
76795-
76796-type ImportFix struct {
76797-	Fix   *imports.ImportFix
76798-	Edits []protocol.TextEdit
76799-}
76800-
76801-// AllImportsFixes formats f for each possible fix to the imports.
76802-// In addition to returning the result of applying all edits,
76803-// it returns a list of fixes that could be applied to the file, with the
76804-// corresponding TextEdits that would be needed to apply that fix.
76805-func AllImportsFixes(ctx context.Context, snapshot Snapshot, fh FileHandle) (allFixEdits []protocol.TextEdit, editsPerFix []*ImportFix, err error) {
76806-	ctx, done := event.Start(ctx, "source.AllImportsFixes")
76807-	defer done()
76808-
76809-	pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
76810-	if err != nil {
76811-		return nil, nil, err
76812-	}
76813-	if err := snapshot.RunProcessEnvFunc(ctx, func(opts *imports.Options) error {
76814-		allFixEdits, editsPerFix, err = computeImportEdits(snapshot, pgf, opts)
76815-		return err
76816-	}); err != nil {
76817-		return nil, nil, fmt.Errorf("AllImportsFixes: %v", err)
76818-	}
76819-	return allFixEdits, editsPerFix, nil
76820-}
76821-
76822-// computeImportEdits computes a set of edits that perform one or all of the
76823-// necessary import fixes.
76824-func computeImportEdits(snapshot Snapshot, pgf *ParsedGoFile, options *imports.Options) (allFixEdits []protocol.TextEdit, editsPerFix []*ImportFix, err error) {
76825-	filename := pgf.URI.Filename()
76826-
76827-	// Build up basic information about the original file.
76828-	allFixes, err := imports.FixImports(filename, pgf.Src, options)
76829-	if err != nil {
76830-		return nil, nil, err
76831-	}
76832-
76833-	allFixEdits, err = computeFixEdits(snapshot, pgf, options, allFixes)
76834-	if err != nil {
76835-		return nil, nil, err
76836-	}
76837-
76838-	// Apply all of the import fixes to the file.
76839-	// Add the edits for each fix to the result.
76840-	for _, fix := range allFixes {
76841-		edits, err := computeFixEdits(snapshot, pgf, options, []*imports.ImportFix{fix})
76842-		if err != nil {
76843-			return nil, nil, err
76844-		}
76845-		editsPerFix = append(editsPerFix, &ImportFix{
76846-			Fix:   fix,
76847-			Edits: edits,
76848-		})
76849-	}
76850-	return allFixEdits, editsPerFix, nil
76851-}
76852-
76853-// ComputeOneImportFixEdits returns text edits for a single import fix.
76854-func ComputeOneImportFixEdits(snapshot Snapshot, pgf *ParsedGoFile, fix *imports.ImportFix) ([]protocol.TextEdit, error) {
76855-	options := &imports.Options{
76856-		LocalPrefix: snapshot.View().Options().Local,
76857-		// Defaults.
76858-		AllErrors:  true,
76859-		Comments:   true,
76860-		Fragment:   true,
76861-		FormatOnly: false,
76862-		TabIndent:  true,
76863-		TabWidth:   8,
76864-	}
76865-	return computeFixEdits(snapshot, pgf, options, []*imports.ImportFix{fix})
76866-}
76867-
76868-func computeFixEdits(snapshot Snapshot, pgf *ParsedGoFile, options *imports.Options, fixes []*imports.ImportFix) ([]protocol.TextEdit, error) {
76869-	// trim the original data to match fixedData
76870-	left, err := importPrefix(pgf.Src)
76871-	if err != nil {
76872-		return nil, err
76873-	}
76874-	extra := !strings.Contains(left, "\n") // one line may have more than imports
76875-	if extra {
76876-		left = string(pgf.Src)
76877-	}
76878-	if len(left) > 0 && left[len(left)-1] != '\n' {
76879-		left += "\n"
76880-	}
76881-	// Apply the fixes and re-parse the file so that we can locate the
76882-	// new imports.
76883-	flags := parser.ImportsOnly
76884-	if extra {
76885-		// used all of origData above, use all of it here too
76886-		flags = 0
76887-	}
76888-	fixedData, err := imports.ApplyFixes(fixes, "", pgf.Src, options, flags)
76889-	if err != nil {
76890-		return nil, err
76891-	}
76892-	if fixedData == nil || fixedData[len(fixedData)-1] != '\n' {
76893-		fixedData = append(fixedData, '\n') // ApplyFixes may miss the newline, go figure.
76894-	}
76895-	edits := snapshot.View().Options().ComputeEdits(left, string(fixedData))
76896-	return protocolEditsFromSource([]byte(left), edits)
76897-}
76898-
76899-// importPrefix returns the prefix of the given file content through the final
76900-// import statement. If there are no imports, the prefix is the package
76901-// statement and any comment groups below it.
76902-func importPrefix(src []byte) (string, error) {
76903-	fset := token.NewFileSet()
76904-	// do as little parsing as possible
76905-	f, err := parser.ParseFile(fset, "", src, parser.ImportsOnly|parser.ParseComments)
76906-	if err != nil { // This can happen if 'package' is misspelled
76907-		return "", fmt.Errorf("importPrefix: failed to parse: %s", err)
76908-	}
76909-	tok := fset.File(f.Pos())
76910-	var importEnd int
76911-	for _, d := range f.Decls {
76912-		if x, ok := d.(*ast.GenDecl); ok && x.Tok == token.IMPORT {
76913-			if e, err := safetoken.Offset(tok, d.End()); err != nil {
76914-				return "", fmt.Errorf("importPrefix: %s", err)
76915-			} else if e > importEnd {
76916-				importEnd = e
76917-			}
76918-		}
76919-	}
76920-
76921-	maybeAdjustToLineEnd := func(pos token.Pos, isCommentNode bool) int {
76922-		offset, err := safetoken.Offset(tok, pos)
76923-		if err != nil {
76924-			return -1
76925-		}
76926-
76927-		// Don't go past the end of the file.
76928-		if offset > len(src) {
76929-			offset = len(src)
76930-		}
76931-		// The go/ast package does not account for different line endings, and
76932-		// specifically, in the text of a comment, it will strip out \r\n line
76933-		// endings in favor of \n. To account for these differences, we try to
76934-		// return a position on the next line whenever possible.
76935-		switch line := tok.Line(tok.Pos(offset)); {
76936-		case line < tok.LineCount():
76937-			nextLineOffset, err := safetoken.Offset(tok, tok.LineStart(line+1))
76938-			if err != nil {
76939-				return -1
76940-			}
76941-			// If we found a position that is at the end of a line, move the
76942-			// offset to the start of the next line.
76943-			if offset+1 == nextLineOffset {
76944-				offset = nextLineOffset
76945-			}
76946-		case isCommentNode, offset+1 == tok.Size():
76947-			// If the last line of the file is a comment, or we are at the end
76948-			// of the file, the prefix is the entire file.
76949-			offset = len(src)
76950-		}
76951-		return offset
76952-	}
76953-	if importEnd == 0 {
76954-		pkgEnd := f.Name.End()
76955-		importEnd = maybeAdjustToLineEnd(pkgEnd, false)
76956-	}
76957-	for _, cgroup := range f.Comments {
76958-		for _, c := range cgroup.List {
76959-			if end, err := safetoken.Offset(tok, c.End()); err != nil {
76960-				return "", err
76961-			} else if end > importEnd {
76962-				startLine := safetoken.Position(tok, c.Pos()).Line
76963-				endLine := safetoken.Position(tok, c.End()).Line
76964-
76965-				// Work around golang/go#41197 by checking if the comment might
76966-				// contain "\r", and if so, find the actual end position of the
76967-				// comment by scanning the content of the file.
76968-				startOffset, err := safetoken.Offset(tok, c.Pos())
76969-				if err != nil {
76970-					return "", err
76971-				}
76972-				if startLine != endLine && bytes.Contains(src[startOffset:], []byte("\r")) {
76973-					if commentEnd := scanForCommentEnd(src[startOffset:]); commentEnd > 0 {
76974-						end = startOffset + commentEnd
76975-					}
76976-				}
76977-				importEnd = maybeAdjustToLineEnd(tok.Pos(end), true)
76978-			}
76979-		}
76980-	}
76981-	if importEnd > len(src) {
76982-		importEnd = len(src)
76983-	}
76984-	return string(src[:importEnd]), nil
76985-}
76986-
76987-// scanForCommentEnd returns the offset of the end of the multi-line comment
76988-// at the start of the given byte slice.
76989-func scanForCommentEnd(src []byte) int {
76990-	var s scanner.Scanner
76991-	s.Init(bytes.NewReader(src))
76992-	s.Mode ^= scanner.SkipComments
76993-
76994-	t := s.Scan()
76995-	if t == scanner.Comment {
76996-		return s.Pos().Offset
76997-	}
76998-	return 0
76999-}
77000-
77001-func computeTextEdits(ctx context.Context, snapshot Snapshot, pgf *ParsedGoFile, formatted string) ([]protocol.TextEdit, error) {
77002-	_, done := event.Start(ctx, "source.computeTextEdits")
77003-	defer done()
77004-
77005-	edits := snapshot.View().Options().ComputeEdits(string(pgf.Src), formatted)
77006-	return ToProtocolEdits(pgf.Mapper, edits)
77007-}
77008-
77009-// protocolEditsFromSource converts text edits to LSP edits using the original
77010-// source.
77011-func protocolEditsFromSource(src []byte, edits []diff.Edit) ([]protocol.TextEdit, error) {
77012-	m := protocol.NewMapper("", src)
77013-	var result []protocol.TextEdit
77014-	for _, edit := range edits {
77015-		rng, err := m.OffsetRange(edit.Start, edit.End)
77016-		if err != nil {
77017-			return nil, err
77018-		}
77019-
77020-		if rng.Start == rng.End && edit.New == "" {
77021-			// Degenerate case, which may result from a diff tool wanting to delete
77022-			// '\r' in line endings. Filter it out.
77023-			continue
77024-		}
77025-		result = append(result, protocol.TextEdit{
77026-			Range:   rng,
77027-			NewText: edit.New,
77028-		})
77029-	}
77030-	return result, nil
77031-}
77032-
77033-// ToProtocolEdits converts diff.Edits to LSP TextEdits.
77034-// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textEditArray
77035-func ToProtocolEdits(m *protocol.Mapper, edits []diff.Edit) ([]protocol.TextEdit, error) {
77036-	// LSP doesn't require TextEditArray to be sorted:
77037-	// this is the receiver's concern. But govim, and perhaps
77038-	// other clients have historically relied on the order.
77039-	edits = append([]diff.Edit(nil), edits...)
77040-	diff.SortEdits(edits)
77041-
77042-	result := make([]protocol.TextEdit, len(edits))
77043-	for i, edit := range edits {
77044-		rng, err := m.OffsetRange(edit.Start, edit.End)
77045-		if err != nil {
77046-			return nil, err
77047-		}
77048-		result[i] = protocol.TextEdit{
77049-			Range:   rng,
77050-			NewText: edit.New,
77051-		}
77052-	}
77053-	return result, nil
77054-}
77055-
77056-// FromProtocolEdits converts LSP TextEdits to diff.Edits.
77057-// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textEditArray
77058-func FromProtocolEdits(m *protocol.Mapper, edits []protocol.TextEdit) ([]diff.Edit, error) {
77059-	if edits == nil {
77060-		return nil, nil
77061-	}
77062-	result := make([]diff.Edit, len(edits))
77063-	for i, edit := range edits {
77064-		start, end, err := m.RangeOffsets(edit.Range)
77065-		if err != nil {
77066-			return nil, err
77067-		}
77068-		result[i] = diff.Edit{
77069-			Start: start,
77070-			End:   end,
77071-			New:   edit.NewText,
77072-		}
77073-	}
77074-	return result, nil
77075-}
77076-
77077-// ApplyProtocolEdits applies the patch (edits) to m.Content and returns the result.
77078-// It also returns the edits converted to diff-package form.
77079-func ApplyProtocolEdits(m *protocol.Mapper, edits []protocol.TextEdit) ([]byte, []diff.Edit, error) {
77080-	diffEdits, err := FromProtocolEdits(m, edits)
77081-	if err != nil {
77082-		return nil, nil, err
77083-	}
77084-	out, err := diff.ApplyBytes(m.Content, diffEdits)
77085-	return out, diffEdits, err
77086-}
77087diff -urN a/gopls/internal/lsp/source/format_test.go b/gopls/internal/lsp/source/format_test.go
77088--- a/gopls/internal/lsp/source/format_test.go	2000-01-01 00:00:00.000000000 -0000
77089+++ b/gopls/internal/lsp/source/format_test.go	1970-01-01 00:00:00.000000000 +0000
77090@@ -1,75 +0,0 @@
77091-// Copyright 2020 The Go Authors. All rights reserved.
77092-// Use of this source code is governed by a BSD-style
77093-// license that can be found in the LICENSE file.
77094-
77095-package source
77096-
77097-import (
77098-	"strings"
77099-	"testing"
77100-
77101-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
77102-)
77103-
77104-func TestImportPrefix(t *testing.T) {
77105-	for i, tt := range []struct {
77106-		input, want string
77107-	}{
77108-		{"package foo", "package foo"},
77109-		{"package foo\n", "package foo\n"},
77110-		{"package foo\n\nfunc f(){}\n", "package foo\n"},
77111-		{"package foo\n\nimport \"fmt\"\n", "package foo\n\nimport \"fmt\""},
77112-		{"package foo\nimport (\n\"fmt\"\n)\n", "package foo\nimport (\n\"fmt\"\n)"},
77113-		{"\n\n\npackage foo\n", "\n\n\npackage foo\n"},
77114-		{"// hi \n\npackage foo //xx\nfunc _(){}\n", "// hi \n\npackage foo //xx\n"},
77115-		{"package foo //hi\n", "package foo //hi\n"},
77116-		{"//hi\npackage foo\n//a\n\n//b\n", "//hi\npackage foo\n//a\n\n//b\n"},
77117-		{
77118-			"package a\n\nimport (\n  \"fmt\"\n)\n//hi\n",
77119-			"package a\n\nimport (\n  \"fmt\"\n)\n//hi\n",
77120-		},
77121-		{`package a /*hi*/`, `package a /*hi*/`},
77122-		{"package main\r\n\r\nimport \"go/types\"\r\n\r\n/*\r\n\r\n */\r\n", "package main\r\n\r\nimport \"go/types\"\r\n\r\n/*\r\n\r\n */\r\n"},
77123-		{"package x; import \"os\"; func f() {}\n\n", "package x; import \"os\""},
77124-		{"package x; func f() {fmt.Println()}\n\n", "package x"},
77125-	} {
77126-		got, err := importPrefix([]byte(tt.input))
77127-		if err != nil {
77128-			t.Fatal(err)
77129-		}
77130-		if d := compare.Text(tt.want, got); d != "" {
77131-			t.Errorf("%d: failed for %q:\n%s", i, tt.input, d)
77132-		}
77133-	}
77134-}
77135-
77136-func TestCRLFFile(t *testing.T) {
77137-	for i, tt := range []struct {
77138-		input, want string
77139-	}{
77140-		{
77141-			input: `package main
77142-
77143-/*
77144-Hi description
77145-*/
77146-func Hi() {
77147-}
77148-`,
77149-			want: `package main
77150-
77151-/*
77152-Hi description
77153-*/`,
77154-		},
77155-	} {
77156-		got, err := importPrefix([]byte(strings.ReplaceAll(tt.input, "\n", "\r\n")))
77157-		if err != nil {
77158-			t.Fatal(err)
77159-		}
77160-		want := strings.ReplaceAll(tt.want, "\n", "\r\n")
77161-		if d := compare.Text(want, got); d != "" {
77162-			t.Errorf("%d: failed for %q:\n%s", i, tt.input, d)
77163-		}
77164-	}
77165-}
77166diff -urN a/gopls/internal/lsp/source/gc_annotations.go b/gopls/internal/lsp/source/gc_annotations.go
77167--- a/gopls/internal/lsp/source/gc_annotations.go	2000-01-01 00:00:00.000000000 -0000
77168+++ b/gopls/internal/lsp/source/gc_annotations.go	1970-01-01 00:00:00.000000000 +0000
77169@@ -1,221 +0,0 @@
77170-// Copyright 2020 The Go Authors. All rights reserved.
77171-// Use of this source code is governed by a BSD-style
77172-// license that can be found in the LICENSE file.
77173-
77174-package source
77175-
77176-import (
77177-	"bytes"
77178-	"context"
77179-	"encoding/json"
77180-	"fmt"
77181-	"io/ioutil"
77182-	"os"
77183-	"path/filepath"
77184-	"strings"
77185-
77186-	"golang.org/x/tools/gopls/internal/lsp/protocol"
77187-	"golang.org/x/tools/gopls/internal/span"
77188-	"golang.org/x/tools/internal/gocommand"
77189-)
77190-
77191-type Annotation string
77192-
77193-const (
77194-	// Nil controls nil checks.
77195-	Nil Annotation = "nil"
77196-
77197-	// Escape controls diagnostics about escape choices.
77198-	Escape Annotation = "escape"
77199-
77200-	// Inline controls diagnostics about inlining choices.
77201-	Inline Annotation = "inline"
77202-
77203-	// Bounds controls bounds checking diagnostics.
77204-	Bounds Annotation = "bounds"
77205-)
77206-
77207-func GCOptimizationDetails(ctx context.Context, snapshot Snapshot, m *Metadata) (map[span.URI][]*Diagnostic, error) {
77208-	if len(m.CompiledGoFiles) == 0 {
77209-		return nil, nil
77210-	}
77211-	pkgDir := filepath.Dir(m.CompiledGoFiles[0].Filename())
77212-	outDir := filepath.Join(os.TempDir(), fmt.Sprintf("gopls-%d.details", os.Getpid()))
77213-
77214-	if err := os.MkdirAll(outDir, 0700); err != nil {
77215-		return nil, err
77216-	}
77217-	tmpFile, err := ioutil.TempFile(os.TempDir(), "gopls-x")
77218-	if err != nil {
77219-		return nil, err
77220-	}
77221-	defer os.Remove(tmpFile.Name())
77222-
77223-	outDirURI := span.URIFromPath(outDir)
77224-	// GC details doesn't handle Windows URIs in the form of "file:///C:/...",
77225-	// so rewrite them to "file://C:/...". See golang/go#41614.
77226-	if !strings.HasPrefix(outDir, "/") {
77227-		outDirURI = span.URI(strings.Replace(string(outDirURI), "file:///", "file://", 1))
77228-	}
77229-	inv := &gocommand.Invocation{
77230-		Verb: "build",
77231-		Args: []string{
77232-			fmt.Sprintf("-gcflags=-json=0,%s", outDirURI),
77233-			fmt.Sprintf("-o=%s", tmpFile.Name()),
77234-			".",
77235-		},
77236-		WorkingDir: pkgDir,
77237-	}
77238-	_, err = snapshot.RunGoCommandDirect(ctx, Normal, inv)
77239-	if err != nil {
77240-		return nil, err
77241-	}
77242-	files, err := findJSONFiles(outDir)
77243-	if err != nil {
77244-		return nil, err
77245-	}
77246-	reports := make(map[span.URI][]*Diagnostic)
77247-	opts := snapshot.View().Options()
77248-	var parseError error
77249-	for _, fn := range files {
77250-		uri, diagnostics, err := parseDetailsFile(fn, opts)
77251-		if err != nil {
77252-			// expect errors for all the files, save 1
77253-			parseError = err
77254-		}
77255-		fh := snapshot.FindFile(uri)
77256-		if fh == nil {
77257-			continue
77258-		}
77259-		if pkgDir != filepath.Dir(fh.URI().Filename()) {
77260-			// https://github.com/golang/go/issues/42198
77261-			// sometimes the detail diagnostics generated for files
77262-			// outside the package can never be taken back.
77263-			continue
77264-		}
77265-		reports[fh.URI()] = diagnostics
77266-	}
77267-	return reports, parseError
77268-}
77269-
77270-func parseDetailsFile(filename string, options *Options) (span.URI, []*Diagnostic, error) {
77271-	buf, err := ioutil.ReadFile(filename)
77272-	if err != nil {
77273-		return "", nil, err
77274-	}
77275-	var (
77276-		uri         span.URI
77277-		i           int
77278-		diagnostics []*Diagnostic
77279-	)
77280-	type metadata struct {
77281-		File string `json:"file,omitempty"`
77282-	}
77283-	for dec := json.NewDecoder(bytes.NewReader(buf)); dec.More(); {
77284-		// The first element always contains metadata.
77285-		if i == 0 {
77286-			i++
77287-			m := new(metadata)
77288-			if err := dec.Decode(m); err != nil {
77289-				return "", nil, err
77290-			}
77291-			if !strings.HasSuffix(m.File, ".go") {
77292-				continue // <autogenerated>
77293-			}
77294-			uri = span.URIFromPath(m.File)
77295-			continue
77296-		}
77297-		d := new(protocol.Diagnostic)
77298-		if err := dec.Decode(d); err != nil {
77299-			return "", nil, err
77300-		}
77301-		msg := d.Code.(string)
77302-		if msg != "" {
77303-			msg = fmt.Sprintf("%s(%s)", msg, d.Message)
77304-		}
77305-		if !showDiagnostic(msg, d.Source, options) {
77306-			continue
77307-		}
77308-		var related []protocol.DiagnosticRelatedInformation
77309-		for _, ri := range d.RelatedInformation {
77310-			// TODO(rfindley): The compiler uses LSP-like JSON to encode gc details,
77311-			// however the positions it uses are 1-based UTF-8:
77312-			// https://github.com/golang/go/blob/master/src/cmd/compile/internal/logopt/log_opts.go
77313-			//
77314-			// Here, we adjust for 0-based positions, but do not translate UTF-8 to UTF-16.
77315-			related = append(related, protocol.DiagnosticRelatedInformation{
77316-				Location: protocol.Location{
77317-					URI:   ri.Location.URI,
77318-					Range: zeroIndexedRange(ri.Location.Range),
77319-				},
77320-				Message: ri.Message,
77321-			})
77322-		}
77323-		diagnostic := &Diagnostic{
77324-			URI:      uri,
77325-			Range:    zeroIndexedRange(d.Range),
77326-			Message:  msg,
77327-			Severity: d.Severity,
77328-			Source:   OptimizationDetailsError, // d.Source is always "go compiler" as of 1.16, use our own
77329-			Tags:     d.Tags,
77330-			Related:  related,
77331-		}
77332-		diagnostics = append(diagnostics, diagnostic)
77333-		i++
77334-	}
77335-	return uri, diagnostics, nil
77336-}
77337-
77338-// showDiagnostic reports whether a given diagnostic should be shown to the end
77339-// user, given the current options.
77340-func showDiagnostic(msg, source string, o *Options) bool {
77341-	if source != "go compiler" {
77342-		return false
77343-	}
77344-	if o.Annotations == nil {
77345-		return true
77346-	}
77347-	switch {
77348-	case strings.HasPrefix(msg, "canInline") ||
77349-		strings.HasPrefix(msg, "cannotInline") ||
77350-		strings.HasPrefix(msg, "inlineCall"):
77351-		return o.Annotations[Inline]
77352-	case strings.HasPrefix(msg, "escape") || msg == "leak":
77353-		return o.Annotations[Escape]
77354-	case strings.HasPrefix(msg, "nilcheck"):
77355-		return o.Annotations[Nil]
77356-	case strings.HasPrefix(msg, "isInBounds") ||
77357-		strings.HasPrefix(msg, "isSliceInBounds"):
77358-		return o.Annotations[Bounds]
77359-	}
77360-	return false
77361-}
77362-
77363-// The range produced by the compiler is 1-indexed, so subtract range by 1.
77364-func zeroIndexedRange(rng protocol.Range) protocol.Range {
77365-	return protocol.Range{
77366-		Start: protocol.Position{
77367-			Line:      rng.Start.Line - 1,
77368-			Character: rng.Start.Character - 1,
77369-		},
77370-		End: protocol.Position{
77371-			Line:      rng.End.Line - 1,
77372-			Character: rng.End.Character - 1,
77373-		},
77374-	}
77375-}
77376-
77377-func findJSONFiles(dir string) ([]string, error) {
77378-	ans := []string{}
77379-	f := func(path string, fi os.FileInfo, _ error) error {
77380-		if fi.IsDir() {
77381-			return nil
77382-		}
77383-		if strings.HasSuffix(path, ".json") {
77384-			ans = append(ans, path)
77385-		}
77386-		return nil
77387-	}
77388-	err := filepath.Walk(dir, f)
77389-	return ans, err
77390-}
77391diff -urN a/gopls/internal/lsp/source/highlight.go b/gopls/internal/lsp/source/highlight.go
77392--- a/gopls/internal/lsp/source/highlight.go	2000-01-01 00:00:00.000000000 -0000
77393+++ b/gopls/internal/lsp/source/highlight.go	1970-01-01 00:00:00.000000000 +0000
77394@@ -1,484 +0,0 @@
77395-// Copyright 2019 The Go Authors. All rights reserved.
77396-// Use of this source code is governed by a BSD-style
77397-// license that can be found in the LICENSE file.
77398-
77399-package source
77400-
77401-import (
77402-	"context"
77403-	"fmt"
77404-	"go/ast"
77405-	"go/token"
77406-	"go/types"
77407-	"strings"
77408-
77409-	"golang.org/x/tools/go/ast/astutil"
77410-	"golang.org/x/tools/gopls/internal/lsp/protocol"
77411-	"golang.org/x/tools/internal/event"
77412-)
77413-
77414-func Highlight(ctx context.Context, snapshot Snapshot, fh FileHandle, position protocol.Position) ([]protocol.Range, error) {
77415-	ctx, done := event.Start(ctx, "source.Highlight")
77416-	defer done()
77417-
77418-	// We always want fully parsed files for highlight, regardless
77419-	// of whether the file belongs to a workspace package.
77420-	pkg, pgf, err := PackageForFile(ctx, snapshot, fh.URI(), NarrowestPackage)
77421-	if err != nil {
77422-		return nil, fmt.Errorf("getting package for Highlight: %w", err)
77423-	}
77424-
77425-	pos, err := pgf.PositionPos(position)
77426-	if err != nil {
77427-		return nil, err
77428-	}
77429-	path, _ := astutil.PathEnclosingInterval(pgf.File, pos, pos)
77430-	if len(path) == 0 {
77431-		return nil, fmt.Errorf("no enclosing position found for %v:%v", position.Line, position.Character)
77432-	}
77433-	// If start == end for astutil.PathEnclosingInterval, the 1-char interval
77434-	// following start is used instead. As a result, we might not get an exact
77435-	// match so we should check the 1-char interval to the left of the passed
77436-	// in position to see if that is an exact match.
77437-	if _, ok := path[0].(*ast.Ident); !ok {
77438-		if p, _ := astutil.PathEnclosingInterval(pgf.File, pos-1, pos-1); p != nil {
77439-			switch p[0].(type) {
77440-			case *ast.Ident, *ast.SelectorExpr:
77441-				path = p // use preceding ident/selector
77442-			}
77443-		}
77444-	}
77445-	result, err := highlightPath(path, pgf.File, pkg.GetTypesInfo())
77446-	if err != nil {
77447-		return nil, err
77448-	}
77449-	var ranges []protocol.Range
77450-	for rng := range result {
77451-		rng, err := pgf.PosRange(rng.start, rng.end)
77452-		if err != nil {
77453-			return nil, err
77454-		}
77455-		ranges = append(ranges, rng)
77456-	}
77457-	return ranges, nil
77458-}
77459-
77460-func highlightPath(path []ast.Node, file *ast.File, info *types.Info) (map[posRange]struct{}, error) {
77461-	result := make(map[posRange]struct{})
77462-	switch node := path[0].(type) {
77463-	case *ast.BasicLit:
77464-		if len(path) > 1 {
77465-			if _, ok := path[1].(*ast.ImportSpec); ok {
77466-				err := highlightImportUses(path, info, result)
77467-				return result, err
77468-			}
77469-		}
77470-		highlightFuncControlFlow(path, result)
77471-	case *ast.ReturnStmt, *ast.FuncDecl, *ast.FuncType:
77472-		highlightFuncControlFlow(path, result)
77473-	case *ast.Ident:
77474-		// Check if ident is inside return or func decl.
77475-		highlightFuncControlFlow(path, result)
77476-		highlightIdentifier(node, file, info, result)
77477-	case *ast.ForStmt, *ast.RangeStmt:
77478-		highlightLoopControlFlow(path, info, result)
77479-	case *ast.SwitchStmt:
77480-		highlightSwitchFlow(path, info, result)
77481-	case *ast.BranchStmt:
77482-		// BREAK can exit a loop, switch or select, while CONTINUE exit a loop so
77483-		// these need to be handled separately. They can also be embedded in any
77484-		// other loop/switch/select if they have a label. TODO: add support for
77485-		// GOTO and FALLTHROUGH as well.
77486-		switch node.Tok {
77487-		case token.BREAK:
77488-			if node.Label != nil {
77489-				highlightLabeledFlow(path, info, node, result)
77490-			} else {
77491-				highlightUnlabeledBreakFlow(path, info, result)
77492-			}
77493-		case token.CONTINUE:
77494-			if node.Label != nil {
77495-				highlightLabeledFlow(path, info, node, result)
77496-			} else {
77497-				highlightLoopControlFlow(path, info, result)
77498-			}
77499-		}
77500-	default:
77501-		// If the cursor is in an unidentified area, return empty results.
77502-		return nil, nil
77503-	}
77504-	return result, nil
77505-}
77506-
77507-type posRange struct {
77508-	start, end token.Pos
77509-}
77510-
77511-func highlightFuncControlFlow(path []ast.Node, result map[posRange]struct{}) {
77512-	var enclosingFunc ast.Node
77513-	var returnStmt *ast.ReturnStmt
77514-	var resultsList *ast.FieldList
77515-	inReturnList := false
77516-
77517-Outer:
77518-	// Reverse walk the path till we get to the func block.
77519-	for i, n := range path {
77520-		switch node := n.(type) {
77521-		case *ast.KeyValueExpr:
77522-			// If cursor is in a key: value expr, we don't want control flow highlighting
77523-			return
77524-		case *ast.CallExpr:
77525-			// If cursor is an arg in a callExpr, we don't want control flow highlighting.
77526-			if i > 0 {
77527-				for _, arg := range node.Args {
77528-					if arg == path[i-1] {
77529-						return
77530-					}
77531-				}
77532-			}
77533-		case *ast.Field:
77534-			inReturnList = true
77535-		case *ast.FuncLit:
77536-			enclosingFunc = n
77537-			resultsList = node.Type.Results
77538-			break Outer
77539-		case *ast.FuncDecl:
77540-			enclosingFunc = n
77541-			resultsList = node.Type.Results
77542-			break Outer
77543-		case *ast.ReturnStmt:
77544-			returnStmt = node
77545-			// If the cursor is not directly in a *ast.ReturnStmt, then
77546-			// we need to know if it is within one of the values that is being returned.
77547-			inReturnList = inReturnList || path[0] != returnStmt
77548-		}
77549-	}
77550-	// Cursor is not in a function.
77551-	if enclosingFunc == nil {
77552-		return
77553-	}
77554-	// If the cursor is on a "return" or "func" keyword, we should highlight all of the exit
77555-	// points of the function, including the "return" and "func" keywords.
77556-	highlightAllReturnsAndFunc := path[0] == returnStmt || path[0] == enclosingFunc
77557-	switch path[0].(type) {
77558-	case *ast.Ident, *ast.BasicLit:
77559-		// Cursor is in an identifier and not in a return statement or in the results list.
77560-		if returnStmt == nil && !inReturnList {
77561-			return
77562-		}
77563-	case *ast.FuncType:
77564-		highlightAllReturnsAndFunc = true
77565-	}
77566-	// The user's cursor may be within the return statement of a function,
77567-	// or within the result section of a function's signature.
77568-	// index := -1
77569-	var nodes []ast.Node
77570-	if returnStmt != nil {
77571-		for _, n := range returnStmt.Results {
77572-			nodes = append(nodes, n)
77573-		}
77574-	} else if resultsList != nil {
77575-		for _, n := range resultsList.List {
77576-			nodes = append(nodes, n)
77577-		}
77578-	}
77579-	_, index := nodeAtPos(nodes, path[0].Pos())
77580-
77581-	// Highlight the correct argument in the function declaration return types.
77582-	if resultsList != nil && -1 < index && index < len(resultsList.List) {
77583-		rng := posRange{
77584-			start: resultsList.List[index].Pos(),
77585-			end:   resultsList.List[index].End(),
77586-		}
77587-		result[rng] = struct{}{}
77588-	}
77589-	// Add the "func" part of the func declaration.
77590-	if highlightAllReturnsAndFunc {
77591-		r := posRange{
77592-			start: enclosingFunc.Pos(),
77593-			end:   enclosingFunc.Pos() + token.Pos(len("func")),
77594-		}
77595-		result[r] = struct{}{}
77596-	}
77597-	ast.Inspect(enclosingFunc, func(n ast.Node) bool {
77598-		// Don't traverse any other functions.
77599-		switch n.(type) {
77600-		case *ast.FuncDecl, *ast.FuncLit:
77601-			return enclosingFunc == n
77602-		}
77603-		ret, ok := n.(*ast.ReturnStmt)
77604-		if !ok {
77605-			return true
77606-		}
77607-		var toAdd ast.Node
77608-		// Add the entire return statement, applies when highlight the word "return" or "func".
77609-		if highlightAllReturnsAndFunc {
77610-			toAdd = n
77611-		}
77612-		// Add the relevant field within the entire return statement.
77613-		if -1 < index && index < len(ret.Results) {
77614-			toAdd = ret.Results[index]
77615-		}
77616-		if toAdd != nil {
77617-			result[posRange{start: toAdd.Pos(), end: toAdd.End()}] = struct{}{}
77618-		}
77619-		return false
77620-	})
77621-}
77622-
77623-// highlightUnlabeledBreakFlow highlights the innermost enclosing for/range/switch or swlect
77624-func highlightUnlabeledBreakFlow(path []ast.Node, info *types.Info, result map[posRange]struct{}) {
77625-	// Reverse walk the path until we find closest loop, select, or switch.
77626-	for _, n := range path {
77627-		switch n.(type) {
77628-		case *ast.ForStmt, *ast.RangeStmt:
77629-			highlightLoopControlFlow(path, info, result)
77630-			return // only highlight the innermost statement
77631-		case *ast.SwitchStmt:
77632-			highlightSwitchFlow(path, info, result)
77633-			return
77634-		case *ast.SelectStmt:
77635-			// TODO: add highlight when breaking a select.
77636-			return
77637-		}
77638-	}
77639-}
77640-
77641-// highlightLabeledFlow highlights the enclosing labeled for, range,
77642-// or switch statement denoted by a labeled break or continue stmt.
77643-func highlightLabeledFlow(path []ast.Node, info *types.Info, stmt *ast.BranchStmt, result map[posRange]struct{}) {
77644-	use := info.Uses[stmt.Label]
77645-	if use == nil {
77646-		return
77647-	}
77648-	for _, n := range path {
77649-		if label, ok := n.(*ast.LabeledStmt); ok && info.Defs[label.Label] == use {
77650-			switch label.Stmt.(type) {
77651-			case *ast.ForStmt, *ast.RangeStmt:
77652-				highlightLoopControlFlow([]ast.Node{label.Stmt, label}, info, result)
77653-			case *ast.SwitchStmt:
77654-				highlightSwitchFlow([]ast.Node{label.Stmt, label}, info, result)
77655-			}
77656-			return
77657-		}
77658-	}
77659-}
77660-
77661-func labelFor(path []ast.Node) *ast.Ident {
77662-	if len(path) > 1 {
77663-		if n, ok := path[1].(*ast.LabeledStmt); ok {
77664-			return n.Label
77665-		}
77666-	}
77667-	return nil
77668-}
77669-
77670-func highlightLoopControlFlow(path []ast.Node, info *types.Info, result map[posRange]struct{}) {
77671-	var loop ast.Node
77672-	var loopLabel *ast.Ident
77673-	stmtLabel := labelFor(path)
77674-Outer:
77675-	// Reverse walk the path till we get to the for loop.
77676-	for i := range path {
77677-		switch n := path[i].(type) {
77678-		case *ast.ForStmt, *ast.RangeStmt:
77679-			loopLabel = labelFor(path[i:])
77680-
77681-			if stmtLabel == nil || loopLabel == stmtLabel {
77682-				loop = n
77683-				break Outer
77684-			}
77685-		}
77686-	}
77687-	if loop == nil {
77688-		return
77689-	}
77690-
77691-	// Add the for statement.
77692-	rng := posRange{
77693-		start: loop.Pos(),
77694-		end:   loop.Pos() + token.Pos(len("for")),
77695-	}
77696-	result[rng] = struct{}{}
77697-
77698-	// Traverse AST to find branch statements within the same for-loop.
77699-	ast.Inspect(loop, func(n ast.Node) bool {
77700-		switch n.(type) {
77701-		case *ast.ForStmt, *ast.RangeStmt:
77702-			return loop == n
77703-		case *ast.SwitchStmt, *ast.SelectStmt:
77704-			return false
77705-		}
77706-		b, ok := n.(*ast.BranchStmt)
77707-		if !ok {
77708-			return true
77709-		}
77710-		if b.Label == nil || info.Uses[b.Label] == info.Defs[loopLabel] {
77711-			result[posRange{start: b.Pos(), end: b.End()}] = struct{}{}
77712-		}
77713-		return true
77714-	})
77715-
77716-	// Find continue statements in the same loop or switches/selects.
77717-	ast.Inspect(loop, func(n ast.Node) bool {
77718-		switch n.(type) {
77719-		case *ast.ForStmt, *ast.RangeStmt:
77720-			return loop == n
77721-		}
77722-
77723-		if n, ok := n.(*ast.BranchStmt); ok && n.Tok == token.CONTINUE {
77724-			result[posRange{start: n.Pos(), end: n.End()}] = struct{}{}
77725-		}
77726-		return true
77727-	})
77728-
77729-	// We don't need to check other for loops if we aren't looking for labeled statements.
77730-	if loopLabel == nil {
77731-		return
77732-	}
77733-
77734-	// Find labeled branch statements in any loop.
77735-	ast.Inspect(loop, func(n ast.Node) bool {
77736-		b, ok := n.(*ast.BranchStmt)
77737-		if !ok {
77738-			return true
77739-		}
77740-		// statement with labels that matches the loop
77741-		if b.Label != nil && info.Uses[b.Label] == info.Defs[loopLabel] {
77742-			result[posRange{start: b.Pos(), end: b.End()}] = struct{}{}
77743-		}
77744-		return true
77745-	})
77746-}
77747-
77748-func highlightSwitchFlow(path []ast.Node, info *types.Info, result map[posRange]struct{}) {
77749-	var switchNode ast.Node
77750-	var switchNodeLabel *ast.Ident
77751-	stmtLabel := labelFor(path)
77752-Outer:
77753-	// Reverse walk the path till we get to the switch statement.
77754-	for i := range path {
77755-		switch n := path[i].(type) {
77756-		case *ast.SwitchStmt:
77757-			switchNodeLabel = labelFor(path[i:])
77758-			if stmtLabel == nil || switchNodeLabel == stmtLabel {
77759-				switchNode = n
77760-				break Outer
77761-			}
77762-		}
77763-	}
77764-	// Cursor is not in a switch statement
77765-	if switchNode == nil {
77766-		return
77767-	}
77768-
77769-	// Add the switch statement.
77770-	rng := posRange{
77771-		start: switchNode.Pos(),
77772-		end:   switchNode.Pos() + token.Pos(len("switch")),
77773-	}
77774-	result[rng] = struct{}{}
77775-
77776-	// Traverse AST to find break statements within the same switch.
77777-	ast.Inspect(switchNode, func(n ast.Node) bool {
77778-		switch n.(type) {
77779-		case *ast.SwitchStmt:
77780-			return switchNode == n
77781-		case *ast.ForStmt, *ast.RangeStmt, *ast.SelectStmt:
77782-			return false
77783-		}
77784-
77785-		b, ok := n.(*ast.BranchStmt)
77786-		if !ok || b.Tok != token.BREAK {
77787-			return true
77788-		}
77789-
77790-		if b.Label == nil || info.Uses[b.Label] == info.Defs[switchNodeLabel] {
77791-			result[posRange{start: b.Pos(), end: b.End()}] = struct{}{}
77792-		}
77793-		return true
77794-	})
77795-
77796-	// We don't need to check other switches if we aren't looking for labeled statements.
77797-	if switchNodeLabel == nil {
77798-		return
77799-	}
77800-
77801-	// Find labeled break statements in any switch
77802-	ast.Inspect(switchNode, func(n ast.Node) bool {
77803-		b, ok := n.(*ast.BranchStmt)
77804-		if !ok || b.Tok != token.BREAK {
77805-			return true
77806-		}
77807-
77808-		if b.Label != nil && info.Uses[b.Label] == info.Defs[switchNodeLabel] {
77809-			result[posRange{start: b.Pos(), end: b.End()}] = struct{}{}
77810-		}
77811-
77812-		return true
77813-	})
77814-}
77815-
77816-func highlightImportUses(path []ast.Node, info *types.Info, result map[posRange]struct{}) error {
77817-	basicLit, ok := path[0].(*ast.BasicLit)
77818-	if !ok {
77819-		return fmt.Errorf("highlightImportUses called with an ast.Node of type %T", basicLit)
77820-	}
77821-	ast.Inspect(path[len(path)-1], func(node ast.Node) bool {
77822-		if imp, ok := node.(*ast.ImportSpec); ok && imp.Path == basicLit {
77823-			result[posRange{start: node.Pos(), end: node.End()}] = struct{}{}
77824-			return false
77825-		}
77826-		n, ok := node.(*ast.Ident)
77827-		if !ok {
77828-			return true
77829-		}
77830-		obj, ok := info.ObjectOf(n).(*types.PkgName)
77831-		if !ok {
77832-			return true
77833-		}
77834-		if !strings.Contains(basicLit.Value, obj.Name()) {
77835-			return true
77836-		}
77837-		result[posRange{start: n.Pos(), end: n.End()}] = struct{}{}
77838-		return false
77839-	})
77840-	return nil
77841-}
77842-
77843-func highlightIdentifier(id *ast.Ident, file *ast.File, info *types.Info, result map[posRange]struct{}) {
77844-	// TODO(rfindley): idObj may be nil. Note that returning early in this case
77845-	// causes tests to fail (because the nObj == idObj check below was succeeded
77846-	// for nil == nil!)
77847-	//
77848-	// Revisit this. If ObjectOf is nil, there are type errors, and it seems
77849-	// reasonable for identifier highlighting not to work.
77850-	idObj := info.ObjectOf(id)
77851-	pkgObj, isImported := idObj.(*types.PkgName)
77852-	ast.Inspect(file, func(node ast.Node) bool {
77853-		if imp, ok := node.(*ast.ImportSpec); ok && isImported {
77854-			highlightImport(pkgObj, imp, result)
77855-		}
77856-		n, ok := node.(*ast.Ident)
77857-		if !ok {
77858-			return true
77859-		}
77860-		if n.Name != id.Name {
77861-			return false
77862-		}
77863-		if nObj := info.ObjectOf(n); nObj == idObj {
77864-			result[posRange{start: n.Pos(), end: n.End()}] = struct{}{}
77865-		}
77866-		return false
77867-	})
77868-}
77869-
77870-func highlightImport(obj *types.PkgName, imp *ast.ImportSpec, result map[posRange]struct{}) {
77871-	if imp.Name != nil || imp.Path == nil {
77872-		return
77873-	}
77874-	if !strings.Contains(imp.Path.Value, obj.Name()) {
77875-		return
77876-	}
77877-	result[posRange{start: imp.Path.Pos(), end: imp.Path.End()}] = struct{}{}
77878-}
77879diff -urN a/gopls/internal/lsp/source/hover.go b/gopls/internal/lsp/source/hover.go
77880--- a/gopls/internal/lsp/source/hover.go	2000-01-01 00:00:00.000000000 -0000
77881+++ b/gopls/internal/lsp/source/hover.go	1970-01-01 00:00:00.000000000 +0000
77882@@ -1,951 +0,0 @@
77883-// Copyright 2019 The Go Authors. All rights reserved.
77884-// Use of this source code is governed by a BSD-style
77885-// license that can be found in the LICENSE file.
77886-
77887-package source
77888-
77889-import (
77890-	"context"
77891-	"encoding/json"
77892-	"fmt"
77893-	"go/ast"
77894-	"go/constant"
77895-	"go/doc"
77896-	"go/format"
77897-	"go/token"
77898-	"go/types"
77899-	"strconv"
77900-	"strings"
77901-	"time"
77902-	"unicode/utf8"
77903-
77904-	"golang.org/x/text/unicode/runenames"
77905-	"golang.org/x/tools/go/ast/astutil"
77906-	"golang.org/x/tools/go/types/typeutil"
77907-	"golang.org/x/tools/gopls/internal/lsp/protocol"
77908-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
77909-	"golang.org/x/tools/gopls/internal/span"
77910-	"golang.org/x/tools/internal/bug"
77911-	"golang.org/x/tools/internal/event"
77912-	"golang.org/x/tools/internal/typeparams"
77913-)
77914-
77915-// HoverJSON contains information used by hover. It is also the JSON returned
77916-// for the "structured" hover format
77917-type HoverJSON struct {
77918-	// Synopsis is a single sentence synopsis of the symbol's documentation.
77919-	Synopsis string `json:"synopsis"`
77920-
77921-	// FullDocumentation is the symbol's full documentation.
77922-	FullDocumentation string `json:"fullDocumentation"`
77923-
77924-	// Signature is the symbol's signature.
77925-	Signature string `json:"signature"`
77926-
77927-	// SingleLine is a single line describing the symbol.
77928-	// This is recommended only for use in clients that show a single line for hover.
77929-	SingleLine string `json:"singleLine"`
77930-
77931-	// SymbolName is the human-readable name to use for the symbol in links.
77932-	SymbolName string `json:"symbolName"`
77933-
77934-	// LinkPath is the pkg.go.dev link for the given symbol.
77935-	// For example, the "go/ast" part of "pkg.go.dev/go/ast#Node".
77936-	LinkPath string `json:"linkPath"`
77937-
77938-	// LinkAnchor is the pkg.go.dev link anchor for the given symbol.
77939-	// For example, the "Node" part of "pkg.go.dev/go/ast#Node".
77940-	LinkAnchor string `json:"linkAnchor"`
77941-}
77942-
77943-// Hover implements the "textDocument/hover" RPC for Go files.
77944-func Hover(ctx context.Context, snapshot Snapshot, fh FileHandle, position protocol.Position) (*protocol.Hover, error) {
77945-	ctx, done := event.Start(ctx, "source.Hover")
77946-	defer done()
77947-
77948-	rng, h, err := hover(ctx, snapshot, fh, position)
77949-	if err != nil {
77950-		return nil, err
77951-	}
77952-	if h == nil {
77953-		return nil, nil
77954-	}
77955-	hover, err := formatHover(h, snapshot.View().Options())
77956-	if err != nil {
77957-		return nil, err
77958-	}
77959-	return &protocol.Hover{
77960-		Contents: protocol.MarkupContent{
77961-			Kind:  snapshot.View().Options().PreferredContentFormat,
77962-			Value: hover,
77963-		},
77964-		Range: rng,
77965-	}, nil
77966-}
77967-
77968-// hover computes hover information at the given position. If we do not support
77969-// hovering at the position, it returns _, nil, nil: an error is only returned
77970-// if the position is valid but we fail to compute hover information.
77971-func hover(ctx context.Context, snapshot Snapshot, fh FileHandle, pp protocol.Position) (protocol.Range, *HoverJSON, error) {
77972-	pkg, pgf, err := PackageForFile(ctx, snapshot, fh.URI(), NarrowestPackage)
77973-	if err != nil {
77974-		return protocol.Range{}, nil, err
77975-	}
77976-	pos, err := pgf.PositionPos(pp)
77977-	if err != nil {
77978-		return protocol.Range{}, nil, err
77979-	}
77980-
77981-	// Handle hovering over import paths, which do not have an associated
77982-	// identifier.
77983-	for _, spec := range pgf.File.Imports {
77984-		// We are inclusive of the end point here to allow hovering when the cursor
77985-		// is just after the import path.
77986-		if spec.Path.Pos() <= pos && pos <= spec.Path.End() {
77987-			return hoverImport(ctx, snapshot, pkg, pgf, spec)
77988-		}
77989-	}
77990-
77991-	// Handle hovering over the package name, which does not have an associated
77992-	// object.
77993-	// As with import paths, we allow hovering just after the package name.
77994-	if pgf.File.Name != nil && pgf.File.Name.Pos() <= pos && pos <= pgf.File.Name.Pos() {
77995-		return hoverPackageName(pkg, pgf)
77996-	}
77997-
77998-	// Handle hovering over (non-import-path) literals.
77999-	if path, _ := astutil.PathEnclosingInterval(pgf.File, pos, pos); len(path) > 0 {
78000-		if lit, _ := path[0].(*ast.BasicLit); lit != nil {
78001-			return hoverLit(pgf, lit, pos)
78002-		}
78003-	}
78004-
78005-	// The general case: compute hover information for the object referenced by
78006-	// the identifier at pos.
78007-	ident, obj, selectedType := referencedObject(pkg, pgf, pos)
78008-	if obj == nil || ident == nil {
78009-		return protocol.Range{}, nil, nil // no object to hover
78010-	}
78011-
78012-	rng, err := pgf.NodeRange(ident)
78013-	if err != nil {
78014-		return protocol.Range{}, nil, err
78015-	}
78016-
78017-	// By convention, we qualify hover information relative to the package
78018-	// from which the request originated.
78019-	qf := Qualifier(pgf.File, pkg.GetTypes(), pkg.GetTypesInfo())
78020-
78021-	// Handle type switch identifiers as a special case, since they don't have an
78022-	// object.
78023-	//
78024-	// There's not much useful information to provide.
78025-	if selectedType != nil {
78026-		fakeObj := types.NewVar(obj.Pos(), obj.Pkg(), obj.Name(), selectedType)
78027-		signature := objectString(fakeObj, qf, nil)
78028-		return rng, &HoverJSON{
78029-			Signature:  signature,
78030-			SingleLine: signature,
78031-			SymbolName: fakeObj.Name(),
78032-		}, nil
78033-	}
78034-
78035-	// Handle builtins, which don't have a package or position.
78036-	if obj.Pkg() == nil {
78037-		h, err := hoverBuiltin(ctx, snapshot, obj)
78038-		return rng, h, err
78039-	}
78040-
78041-	// For all other objects, consider the full syntax of their declaration in
78042-	// order to correctly compute their documentation, signature, and link.
78043-	declPGF, declPos, err := parseFull(ctx, snapshot, pkg.FileSet(), obj.Pos())
78044-	if err != nil {
78045-		return protocol.Range{}, nil, fmt.Errorf("re-parsing declaration of %s: %v", obj.Name(), err)
78046-	}
78047-	decl, spec, field := findDeclInfo([]*ast.File{declPGF.File}, declPos)
78048-	comment := chooseDocComment(decl, spec, field)
78049-	docText := comment.Text()
78050-
78051-	// By default, types.ObjectString provides a reasonable signature.
78052-	signature := objectString(obj, qf, nil)
78053-	// TODO(rfindley): we could do much better for inferred signatures.
78054-	if inferred := inferredSignature(pkg.GetTypesInfo(), ident); inferred != nil {
78055-		signature = objectString(obj, qf, inferred)
78056-	}
78057-
78058-	// For "objects defined by a type spec", the signature produced by
78059-	// objectString is insufficient:
78060-	//  (1) large structs are formatted poorly, with no newlines
78061-	//  (2) we lose inline comments
78062-	//
78063-	// Furthermore, we include a summary of their method set.
78064-	//
78065-	// TODO(rfindley): this should use FormatVarType to get proper qualification
78066-	// of identifiers, and we should revisit the formatting of method set.
78067-	_, isTypeName := obj.(*types.TypeName)
78068-	_, isTypeParam := obj.Type().(*typeparams.TypeParam)
78069-	if isTypeName && !isTypeParam {
78070-		spec, ok := spec.(*ast.TypeSpec)
78071-		if !ok {
78072-			return protocol.Range{}, nil, bug.Errorf("type name %q without type spec", obj.Name())
78073-		}
78074-		spec2 := *spec
78075-		// Don't duplicate comments when formatting type specs.
78076-		spec2.Doc = nil
78077-		spec2.Comment = nil
78078-		var b strings.Builder
78079-		b.WriteString("type ")
78080-		fset := FileSetFor(declPGF.Tok)
78081-		if err := format.Node(&b, fset, &spec2); err != nil {
78082-			return protocol.Range{}, nil, err
78083-		}
78084-
78085-		// Display the declared methods accessible from the identifier.
78086-		//
78087-		// (The format.Node call above displays any struct fields, public
78088-		// or private, in syntactic form. We choose not to recursively
78089-		// enumerate any fields and methods promoted from them.)
78090-		if !types.IsInterface(obj.Type()) {
78091-			sep := "\n\n"
78092-			for _, m := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
78093-				// Show direct methods that are either exported, or defined in the
78094-				// current package.
78095-				if (m.Obj().Exported() || m.Obj().Pkg() == pkg.GetTypes()) && len(m.Index()) == 1 {
78096-					b.WriteString(sep)
78097-					sep = "\n"
78098-					b.WriteString(objectString(m.Obj(), qf, nil))
78099-				}
78100-			}
78101-		}
78102-		signature = b.String()
78103-	}
78104-
78105-	// Compute link data (on pkg.go.dev or other documentation host).
78106-	//
78107-	// If linkPath is empty, the symbol is not linkable.
78108-	var (
78109-		linkName string    // => link title, always non-empty
78110-		linkPath string    // => link path
78111-		anchor   string    // link anchor
78112-		linkMeta *Metadata // metadata for the linked package
78113-	)
78114-	{
78115-		linkMeta = findFileInDeps(snapshot, pkg.Metadata(), declPGF.URI)
78116-		if linkMeta == nil {
78117-			return protocol.Range{}, nil, bug.Errorf("no metadata for %s", declPGF.URI)
78118-		}
78119-
78120-		// For package names, we simply link to their imported package.
78121-		if pkgName, ok := obj.(*types.PkgName); ok {
78122-			linkName = pkgName.Name()
78123-			linkPath = pkgName.Imported().Path()
78124-			impID := linkMeta.DepsByPkgPath[PackagePath(pkgName.Imported().Path())]
78125-			linkMeta = snapshot.Metadata(impID)
78126-			if linkMeta == nil {
78127-				return protocol.Range{}, nil, bug.Errorf("no metadata for %s", declPGF.URI)
78128-			}
78129-		} else {
78130-			// For all others, check whether the object is in the package scope, or
78131-			// an exported field or method of an object in the package scope.
78132-			//
78133-			// We try to match pkgsite's heuristics for what is linkable, and what is
78134-			// not.
78135-			var recv types.Object
78136-			switch obj := obj.(type) {
78137-			case *types.Func:
78138-				sig := obj.Type().(*types.Signature)
78139-				if sig.Recv() != nil {
78140-					tname := typeToObject(sig.Recv().Type())
78141-					if tname != nil { // beware typed nil
78142-						recv = tname
78143-					}
78144-				}
78145-			case *types.Var:
78146-				if obj.IsField() {
78147-					if spec, ok := spec.(*ast.TypeSpec); ok {
78148-						typeName := spec.Name
78149-						scopeObj, _ := obj.Pkg().Scope().Lookup(typeName.Name).(*types.TypeName)
78150-						if scopeObj != nil {
78151-							if st, _ := scopeObj.Type().Underlying().(*types.Struct); st != nil {
78152-								for i := 0; i < st.NumFields(); i++ {
78153-									if obj == st.Field(i) {
78154-										recv = scopeObj
78155-									}
78156-								}
78157-							}
78158-						}
78159-					}
78160-				}
78161-			}
78162-
78163-			// Even if the object is not available in package documentation, it may
78164-			// be embedded in a documented receiver. Detect this by searching
78165-			// enclosing selector expressions.
78166-			//
78167-			// TODO(rfindley): pkgsite doesn't document fields from embedding, just
78168-			// methods.
78169-			if recv == nil || !recv.Exported() {
78170-				path := pathEnclosingObjNode(pgf.File, pos)
78171-				if enclosing := searchForEnclosing(pkg.GetTypesInfo(), path); enclosing != nil {
78172-					recv = enclosing
78173-				} else {
78174-					recv = nil // note: just recv = ... could result in a typed nil.
78175-				}
78176-			}
78177-
78178-			pkg := obj.Pkg()
78179-			if recv != nil {
78180-				linkName = fmt.Sprintf("(%s.%s).%s", pkg.Name(), recv.Name(), obj.Name())
78181-				if obj.Exported() && recv.Exported() && pkg.Scope().Lookup(recv.Name()) == recv {
78182-					linkPath = pkg.Path()
78183-					anchor = fmt.Sprintf("%s.%s", recv.Name(), obj.Name())
78184-				}
78185-			} else {
78186-				linkName = fmt.Sprintf("%s.%s", pkg.Name(), obj.Name())
78187-				if obj.Exported() && pkg.Scope().Lookup(obj.Name()) == obj {
78188-					linkPath = pkg.Path()
78189-					anchor = obj.Name()
78190-				}
78191-			}
78192-		}
78193-	}
78194-
78195-	if snapshot.View().IsGoPrivatePath(linkPath) || linkMeta.ForTest != "" {
78196-		linkPath = ""
78197-	} else if linkMeta.Module != nil && linkMeta.Module.Version != "" {
78198-		mod := linkMeta.Module
78199-		linkPath = strings.Replace(linkPath, mod.Path, mod.Path+"@"+mod.Version, 1)
78200-	}
78201-
78202-	return rng, &HoverJSON{
78203-		Synopsis:          doc.Synopsis(docText),
78204-		FullDocumentation: docText,
78205-		SingleLine:        objectString(obj, qf, nil),
78206-		SymbolName:        linkName,
78207-		Signature:         signature,
78208-		LinkPath:          linkPath,
78209-		LinkAnchor:        anchor,
78210-	}, nil
78211-}
78212-
78213-// hoverBuiltin computes hover information when hovering over a builtin
78214-// identifier.
78215-func hoverBuiltin(ctx context.Context, snapshot Snapshot, obj types.Object) (*HoverJSON, error) {
78216-	// TODO(rfindley): link to the correct version of Go documentation.
78217-	builtin, err := snapshot.BuiltinFile(ctx)
78218-	if err != nil {
78219-		return nil, err
78220-	}
78221-
78222-	// TODO(rfindley): add a test for jump to definition of error.Error (which is
78223-	// probably failing, considering it lacks special handling).
78224-	if obj.Name() == "Error" {
78225-		signature := obj.String()
78226-		return &HoverJSON{
78227-			Signature:  signature,
78228-			SingleLine: signature,
78229-			// TODO(rfindley): these are better than the current behavior.
78230-			// SymbolName: "(error).Error",
78231-			// LinkPath:   "builtin",
78232-			// LinkAnchor: "error.Error",
78233-		}, nil
78234-	}
78235-
78236-	builtinObj := builtin.File.Scope.Lookup(obj.Name())
78237-	if builtinObj == nil {
78238-		// All builtins should have a declaration in the builtin file.
78239-		return nil, bug.Errorf("no builtin object for %s", obj.Name())
78240-	}
78241-	node, _ := builtinObj.Decl.(ast.Node)
78242-	if node == nil {
78243-		return nil, bug.Errorf("no declaration for %s", obj.Name())
78244-	}
78245-
78246-	var comment *ast.CommentGroup
78247-	path, _ := astutil.PathEnclosingInterval(builtin.File, node.Pos(), node.End())
78248-	for _, n := range path {
78249-		switch n := n.(type) {
78250-		case *ast.GenDecl:
78251-			// Separate documentation and signature.
78252-			comment = n.Doc
78253-			node2 := *n
78254-			node2.Doc = nil
78255-			node = &node2
78256-		case *ast.FuncDecl:
78257-			// Ditto.
78258-			comment = n.Doc
78259-			node2 := *n
78260-			node2.Doc = nil
78261-			node = &node2
78262-		}
78263-	}
78264-
78265-	signature := FormatNodeFile(builtin.Tok, node)
78266-	// Replace fake types with their common equivalent.
78267-	// TODO(rfindley): we should instead use obj.Type(), which would have the
78268-	// *actual* types of the builtin call.
78269-	signature = replacer.Replace(signature)
78270-
78271-	docText := comment.Text()
78272-	return &HoverJSON{
78273-		Synopsis:          doc.Synopsis(docText),
78274-		FullDocumentation: docText,
78275-		Signature:         signature,
78276-		SingleLine:        obj.String(),
78277-		SymbolName:        obj.Name(),
78278-		LinkPath:          "builtin",
78279-		LinkAnchor:        obj.Name(),
78280-	}, nil
78281-}
78282-
78283-// hoverImport computes hover information when hovering over the import path of
78284-// imp in the file pgf of pkg.
78285-//
78286-// If we do not have metadata for the hovered import, it returns _
78287-func hoverImport(ctx context.Context, snapshot Snapshot, pkg Package, pgf *ParsedGoFile, imp *ast.ImportSpec) (protocol.Range, *HoverJSON, error) {
78288-	rng, err := pgf.NodeRange(imp.Path)
78289-	if err != nil {
78290-		return protocol.Range{}, nil, err
78291-	}
78292-
78293-	importPath := UnquoteImportPath(imp)
78294-	if importPath == "" {
78295-		return protocol.Range{}, nil, fmt.Errorf("invalid import path")
78296-	}
78297-	impID := pkg.Metadata().DepsByImpPath[importPath]
78298-	if impID == "" {
78299-		return protocol.Range{}, nil, fmt.Errorf("no package data for import %q", importPath)
78300-	}
78301-	impMetadata := snapshot.Metadata(impID)
78302-	if impMetadata == nil {
78303-		return protocol.Range{}, nil, bug.Errorf("failed to resolve import ID %q", impID)
78304-	}
78305-
78306-	// Find the first file with a package doc comment.
78307-	var comment *ast.CommentGroup
78308-	for _, f := range impMetadata.CompiledGoFiles {
78309-		fh, err := snapshot.GetFile(ctx, f)
78310-		if err != nil {
78311-			if ctx.Err() != nil {
78312-				return protocol.Range{}, nil, ctx.Err()
78313-			}
78314-			continue
78315-		}
78316-		pgf, err := snapshot.ParseGo(ctx, fh, ParseHeader)
78317-		if err != nil {
78318-			if ctx.Err() != nil {
78319-				return protocol.Range{}, nil, ctx.Err()
78320-			}
78321-			continue
78322-		}
78323-		if pgf.File.Doc != nil {
78324-			comment = pgf.File.Doc
78325-			break
78326-		}
78327-	}
78328-
78329-	docText := comment.Text()
78330-	return rng, &HoverJSON{
78331-		Synopsis:          doc.Synopsis(docText),
78332-		FullDocumentation: docText,
78333-	}, nil
78334-}
78335-
78336-// hoverPackageName computes hover information for the package name of the file
78337-// pgf in pkg.
78338-func hoverPackageName(pkg Package, pgf *ParsedGoFile) (protocol.Range, *HoverJSON, error) {
78339-	var comment *ast.CommentGroup
78340-	for _, pgf := range pkg.CompiledGoFiles() {
78341-		if pgf.File.Doc != nil {
78342-			comment = pgf.File.Doc
78343-			break
78344-		}
78345-	}
78346-	rng, err := pgf.NodeRange(pgf.File.Name)
78347-	if err != nil {
78348-		return protocol.Range{}, nil, err
78349-	}
78350-	docText := comment.Text()
78351-	return rng, &HoverJSON{
78352-		Synopsis:          doc.Synopsis(docText),
78353-		FullDocumentation: docText,
78354-		// Note: including a signature is redundant, since the cursor is already on the
78355-		// package name.
78356-	}, nil
78357-}
78358-
78359-// hoverLit computes hover information when hovering over the basic literal lit
78360-// in the file pgf. The provided pos must be the exact position of the cursor,
78361-// as it is used to extract the hovered rune in strings.
78362-//
78363-// For example, hovering over "\u2211" in "foo \u2211 bar" yields:
78364-//
78365-//	'∑', U+2211, N-ARY SUMMATION
78366-func hoverLit(pgf *ParsedGoFile, lit *ast.BasicLit, pos token.Pos) (protocol.Range, *HoverJSON, error) {
78367-	var r rune
78368-	var start, end token.Pos
78369-	// Extract a rune from the current position.
78370-	// 'Ω', "...Ω...", or 0x03A9 => 'Ω', U+03A9, GREEK CAPITAL LETTER OMEGA
78371-	switch lit.Kind {
78372-	case token.CHAR:
78373-		s, err := strconv.Unquote(lit.Value)
78374-		if err != nil {
78375-			// If the conversion fails, it's because of an invalid syntax, therefore
78376-			// there is no rune to be found.
78377-			return protocol.Range{}, nil, nil
78378-		}
78379-		r, _ = utf8.DecodeRuneInString(s)
78380-		if r == utf8.RuneError {
78381-			return protocol.Range{}, nil, fmt.Errorf("rune error")
78382-		}
78383-		start, end = lit.Pos(), lit.End()
78384-	case token.INT:
78385-		// TODO(rfindley): add support for hex/octal/binary->int conversion here.
78386-
78387-		// It's an integer, scan only if it is a hex literal whose bitsize in
78388-		// ranging from 8 to 32.
78389-		if !(strings.HasPrefix(lit.Value, "0x") && len(lit.Value[2:]) >= 2 && len(lit.Value[2:]) <= 8) {
78390-			return protocol.Range{}, nil, nil
78391-		}
78392-		v, err := strconv.ParseUint(lit.Value[2:], 16, 32)
78393-		if err != nil {
78394-			return protocol.Range{}, nil, fmt.Errorf("parsing int: %v", err)
78395-		}
78396-		r = rune(v)
78397-		if r == utf8.RuneError {
78398-			return protocol.Range{}, nil, fmt.Errorf("rune error")
78399-		}
78400-		start, end = lit.Pos(), lit.End()
78401-	case token.STRING:
78402-		// It's a string, scan only if it contains a unicode escape sequence under or before the
78403-		// current cursor position.
78404-		litOffset, err := safetoken.Offset(pgf.Tok, lit.Pos())
78405-		if err != nil {
78406-			return protocol.Range{}, nil, err
78407-		}
78408-		offset, err := safetoken.Offset(pgf.Tok, pos)
78409-		if err != nil {
78410-			return protocol.Range{}, nil, err
78411-		}
78412-		for i := offset - litOffset; i > 0; i-- {
78413-			// Start at the cursor position and search backward for the beginning of a rune escape sequence.
78414-			rr, _ := utf8.DecodeRuneInString(lit.Value[i:])
78415-			if rr == utf8.RuneError {
78416-				return protocol.Range{}, nil, fmt.Errorf("rune error")
78417-			}
78418-			if rr == '\\' {
78419-				// Got the beginning, decode it.
78420-				var tail string
78421-				r, _, tail, err = strconv.UnquoteChar(lit.Value[i:], '"')
78422-				if err != nil {
78423-					// If the conversion fails, it's because of an invalid syntax,
78424-					// therefore is no rune to be found.
78425-					return protocol.Range{}, nil, nil
78426-				}
78427-				// Only the rune escape sequence part of the string has to be highlighted, recompute the range.
78428-				runeLen := len(lit.Value) - (int(i) + len(tail))
78429-				start = token.Pos(int(lit.Pos()) + int(i))
78430-				end = token.Pos(int(start) + runeLen)
78431-				break
78432-			}
78433-		}
78434-	}
78435-	if r == 0 {
78436-		return protocol.Range{}, nil, nil
78437-	}
78438-	rng, err := pgf.PosRange(start, end)
78439-	if err != nil {
78440-		return protocol.Range{}, nil, err
78441-	}
78442-
78443-	var desc string
78444-	runeName := runenames.Name(r)
78445-	if len(runeName) > 0 && runeName[0] == '<' {
78446-		// Check if the rune looks like an HTML tag. If so, trim the surrounding <>
78447-		// characters to work around https://github.com/microsoft/vscode/issues/124042.
78448-		runeName = strings.TrimRight(runeName[1:], ">")
78449-	}
78450-	if strconv.IsPrint(r) {
78451-		desc = fmt.Sprintf("'%s', U+%04X, %s", string(r), uint32(r), runeName)
78452-	} else {
78453-		desc = fmt.Sprintf("U+%04X, %s", uint32(r), runeName)
78454-	}
78455-	return rng, &HoverJSON{
78456-		Synopsis:          desc,
78457-		FullDocumentation: desc,
78458-	}, nil
78459-}
78460-
78461-// objectString is a wrapper around the types.ObjectString function.
78462-// It handles adding more information to the object string.
78463-//
78464-// TODO(rfindley): this function does too much. We should lift the special
78465-// handling to callsites.
78466-func objectString(obj types.Object, qf types.Qualifier, inferred *types.Signature) string {
78467-	// If the signature type was inferred, prefer the inferred signature with a
78468-	// comment showing the generic signature.
78469-	if sig, _ := obj.Type().(*types.Signature); sig != nil && typeparams.ForSignature(sig).Len() > 0 && inferred != nil {
78470-		obj2 := types.NewFunc(obj.Pos(), obj.Pkg(), obj.Name(), inferred)
78471-		str := types.ObjectString(obj2, qf)
78472-		// Try to avoid overly long lines.
78473-		if len(str) > 60 {
78474-			str += "\n"
78475-		} else {
78476-			str += " "
78477-		}
78478-		str += "// " + types.TypeString(sig, qf)
78479-		return str
78480-	}
78481-	str := types.ObjectString(obj, qf)
78482-	switch obj := obj.(type) {
78483-	case *types.Const:
78484-		str = fmt.Sprintf("%s = %s", str, obj.Val())
78485-
78486-		// Try to add a formatted duration as an inline comment
78487-		typ, ok := obj.Type().(*types.Named)
78488-		if !ok {
78489-			break
78490-		}
78491-		pkg := typ.Obj().Pkg()
78492-		if pkg.Path() == "time" && typ.Obj().Name() == "Duration" {
78493-			if d, ok := constant.Int64Val(obj.Val()); ok {
78494-				str += " // " + time.Duration(d).String()
78495-			}
78496-		}
78497-	}
78498-	return str
78499-}
78500-
78501-// HoverDocForObject returns the best doc comment for obj (for which
78502-// fset provides file/line information).
78503-//
78504-// TODO(rfindley): there appears to be zero(!) tests for this functionality.
78505-func HoverDocForObject(ctx context.Context, snapshot Snapshot, fset *token.FileSet, obj types.Object) (*ast.CommentGroup, error) {
78506-	if _, isTypeName := obj.(*types.TypeName); isTypeName {
78507-		if _, isTypeParam := obj.Type().(*typeparams.TypeParam); isTypeParam {
78508-			return nil, nil
78509-		}
78510-	}
78511-
78512-	pgf, pos, err := parseFull(ctx, snapshot, fset, obj.Pos())
78513-	if err != nil {
78514-		return nil, fmt.Errorf("re-parsing: %v", err)
78515-	}
78516-
78517-	decl, spec, field := findDeclInfo([]*ast.File{pgf.File}, pos)
78518-	return chooseDocComment(decl, spec, field), nil
78519-}
78520-
78521-func chooseDocComment(decl ast.Decl, spec ast.Spec, field *ast.Field) *ast.CommentGroup {
78522-	if field != nil {
78523-		if field.Doc != nil {
78524-			return field.Doc
78525-		}
78526-		if field.Comment != nil {
78527-			return field.Comment
78528-		}
78529-		return nil
78530-	}
78531-	switch decl := decl.(type) {
78532-	case *ast.FuncDecl:
78533-		return decl.Doc
78534-	case *ast.GenDecl:
78535-		switch spec := spec.(type) {
78536-		case *ast.ValueSpec:
78537-			if spec.Doc != nil {
78538-				return spec.Doc
78539-			}
78540-			if decl.Doc != nil {
78541-				return decl.Doc
78542-			}
78543-			return spec.Comment
78544-		case *ast.TypeSpec:
78545-			if spec.Doc != nil {
78546-				return spec.Doc
78547-			}
78548-			if decl.Doc != nil {
78549-				return decl.Doc
78550-			}
78551-			return spec.Comment
78552-		}
78553-	}
78554-	return nil
78555-}
78556-
78557-// parseFull fully parses the file corresponding to position pos (for
78558-// which fset provides file/line information).
78559-//
78560-// It returns the resulting ParsedGoFile as well as new pos contained in the
78561-// parsed file.
78562-func parseFull(ctx context.Context, snapshot Snapshot, fset *token.FileSet, pos token.Pos) (*ParsedGoFile, token.Pos, error) {
78563-	f := fset.File(pos)
78564-	if f == nil {
78565-		return nil, 0, bug.Errorf("internal error: no file for position %d", pos)
78566-	}
78567-
78568-	uri := span.URIFromPath(f.Name())
78569-	fh, err := snapshot.GetFile(ctx, uri)
78570-	if err != nil {
78571-		return nil, 0, err
78572-	}
78573-
78574-	pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
78575-	if err != nil {
78576-		return nil, 0, err
78577-	}
78578-
78579-	offset, err := safetoken.Offset(f, pos)
78580-	if err != nil {
78581-		return nil, 0, bug.Errorf("offset out of bounds in %q", uri)
78582-	}
78583-
78584-	fullPos, err := safetoken.Pos(pgf.Tok, offset)
78585-	if err != nil {
78586-		return nil, 0, err
78587-	}
78588-
78589-	return pgf, fullPos, nil
78590-}
78591-
78592-// extractFieldList recursively tries to extract a field list.
78593-// If it is not found, nil is returned.
78594-func extractFieldList(specType ast.Expr) *ast.FieldList {
78595-	switch t := specType.(type) {
78596-	case *ast.StructType:
78597-		return t.Fields
78598-	case *ast.InterfaceType:
78599-		return t.Methods
78600-	case *ast.ArrayType:
78601-		return extractFieldList(t.Elt)
78602-	case *ast.MapType:
78603-		// Map value has a greater chance to be a struct
78604-		if fields := extractFieldList(t.Value); fields != nil {
78605-			return fields
78606-		}
78607-		return extractFieldList(t.Key)
78608-	case *ast.ChanType:
78609-		return extractFieldList(t.Value)
78610-	}
78611-	return nil
78612-}
78613-
78614-func formatHover(h *HoverJSON, options *Options) (string, error) {
78615-	signature := formatSignature(h, options)
78616-
78617-	switch options.HoverKind {
78618-	case SingleLine:
78619-		return h.SingleLine, nil
78620-	case NoDocumentation:
78621-		return signature, nil
78622-	case Structured:
78623-		b, err := json.Marshal(h)
78624-		if err != nil {
78625-			return "", err
78626-		}
78627-		return string(b), nil
78628-	}
78629-
78630-	link := formatLink(h, options)
78631-	doc := formatDoc(h, options)
78632-
78633-	var b strings.Builder
78634-	parts := []string{signature, doc, link}
78635-	for i, el := range parts {
78636-		if el != "" {
78637-			b.WriteString(el)
78638-
78639-			// If any elements of the remainder of the list are non-empty,
78640-			// write an extra newline.
78641-			if anyNonEmpty(parts[i+1:]) {
78642-				if options.PreferredContentFormat == protocol.Markdown {
78643-					b.WriteString("\n\n")
78644-				} else {
78645-					b.WriteRune('\n')
78646-				}
78647-			}
78648-		}
78649-	}
78650-	return b.String(), nil
78651-}
78652-
78653-func formatSignature(h *HoverJSON, options *Options) string {
78654-	signature := h.Signature
78655-	if signature != "" && options.PreferredContentFormat == protocol.Markdown {
78656-		signature = fmt.Sprintf("```go\n%s\n```", signature)
78657-	}
78658-	return signature
78659-}
78660-
78661-func formatLink(h *HoverJSON, options *Options) string {
78662-	if !options.LinksInHover || options.LinkTarget == "" || h.LinkPath == "" {
78663-		return ""
78664-	}
78665-	plainLink := BuildLink(options.LinkTarget, h.LinkPath, h.LinkAnchor)
78666-	switch options.PreferredContentFormat {
78667-	case protocol.Markdown:
78668-		return fmt.Sprintf("[`%s` on %s](%s)", h.SymbolName, options.LinkTarget, plainLink)
78669-	case protocol.PlainText:
78670-		return ""
78671-	default:
78672-		return plainLink
78673-	}
78674-}
78675-
78676-// BuildLink constructs a URL with the given target, path, and anchor.
78677-func BuildLink(target, path, anchor string) string {
78678-	link := fmt.Sprintf("https://%s/%s", target, path)
78679-	if anchor == "" {
78680-		return link
78681-	}
78682-	return link + "#" + anchor
78683-}
78684-
78685-func formatDoc(h *HoverJSON, options *Options) string {
78686-	var doc string
78687-	switch options.HoverKind {
78688-	case SynopsisDocumentation:
78689-		doc = h.Synopsis
78690-	case FullDocumentation:
78691-		doc = h.FullDocumentation
78692-	}
78693-	if options.PreferredContentFormat == protocol.Markdown {
78694-		return CommentToMarkdown(doc, options)
78695-	}
78696-	return doc
78697-}
78698-
78699-func anyNonEmpty(x []string) bool {
78700-	for _, el := range x {
78701-		if el != "" {
78702-			return true
78703-		}
78704-	}
78705-	return false
78706-}
78707-
78708-// findDeclInfo returns the syntax nodes involved in the declaration of the
78709-// types.Object with position pos, searching the given list of file syntax
78710-// trees.
78711-//
78712-// Pos may be the position of the name-defining identifier in a FuncDecl,
78713-// ValueSpec, TypeSpec, Field, or as a special case the position of
78714-// Ellipsis.Elt in an ellipsis field.
78715-//
78716-// If found, the resulting decl, spec, and field will be the inner-most
78717-// instance of each node type surrounding pos.
78718-//
78719-// If field is non-nil, pos is the position of a field Var. If field is nil and
78720-// spec is non-nil, pos is the position of a Var, Const, or TypeName object. If
78721-// both field and spec are nil and decl is non-nil, pos is the position of a
78722-// Func object.
78723-//
78724-// It returns a nil decl if no object-defining node is found at pos.
78725-//
78726-// TODO(rfindley): this function has tricky semantics, and may be worth unit
78727-// testing and/or refactoring.
78728-func findDeclInfo(files []*ast.File, pos token.Pos) (decl ast.Decl, spec ast.Spec, field *ast.Field) {
78729-	// panic(found{}) breaks off the traversal and
78730-	// causes the function to return normally.
78731-	type found struct{}
78732-	defer func() {
78733-		switch x := recover().(type) {
78734-		case nil:
78735-		case found:
78736-		default:
78737-			panic(x)
78738-		}
78739-	}()
78740-
78741-	// Visit the files in search of the node at pos.
78742-	stack := make([]ast.Node, 0, 20)
78743-	// Allocate the closure once, outside the loop.
78744-	f := func(n ast.Node) bool {
78745-		if n != nil {
78746-			stack = append(stack, n) // push
78747-		} else {
78748-			stack = stack[:len(stack)-1] // pop
78749-			return false
78750-		}
78751-
78752-		// Skip subtrees (incl. files) that don't contain the search point.
78753-		if !(n.Pos() <= pos && pos < n.End()) {
78754-			return false
78755-		}
78756-
78757-		switch n := n.(type) {
78758-		case *ast.Field:
78759-			findEnclosingDeclAndSpec := func() {
78760-				for i := len(stack) - 1; i >= 0; i-- {
78761-					switch n := stack[i].(type) {
78762-					case ast.Spec:
78763-						spec = n
78764-					case ast.Decl:
78765-						decl = n
78766-						return
78767-					}
78768-				}
78769-			}
78770-
78771-			// Check each field name since you can have
78772-			// multiple names for the same type expression.
78773-			for _, id := range n.Names {
78774-				if id.Pos() == pos {
78775-					field = n
78776-					findEnclosingDeclAndSpec()
78777-					panic(found{})
78778-				}
78779-			}
78780-
78781-			// Check *ast.Field itself. This handles embedded
78782-			// fields which have no associated *ast.Ident name.
78783-			if n.Pos() == pos {
78784-				field = n
78785-				findEnclosingDeclAndSpec()
78786-				panic(found{})
78787-			}
78788-
78789-			// Also check "X" in "...X". This makes it easy to format variadic
78790-			// signature params properly.
78791-			//
78792-			// TODO(rfindley): I don't understand this comment. How does finding the
78793-			// field in this case make it easier to format variadic signature params?
78794-			if ell, ok := n.Type.(*ast.Ellipsis); ok && ell.Elt != nil && ell.Elt.Pos() == pos {
78795-				field = n
78796-				findEnclosingDeclAndSpec()
78797-				panic(found{})
78798-			}
78799-
78800-		case *ast.FuncDecl:
78801-			if n.Name.Pos() == pos {
78802-				decl = n
78803-				panic(found{})
78804-			}
78805-
78806-		case *ast.GenDecl:
78807-			for _, s := range n.Specs {
78808-				switch s := s.(type) {
78809-				case *ast.TypeSpec:
78810-					if s.Name.Pos() == pos {
78811-						decl = n
78812-						spec = s
78813-						panic(found{})
78814-					}
78815-				case *ast.ValueSpec:
78816-					for _, id := range s.Names {
78817-						if id.Pos() == pos {
78818-							decl = n
78819-							spec = s
78820-							panic(found{})
78821-						}
78822-					}
78823-				}
78824-			}
78825-		}
78826-		return true
78827-	}
78828-	for _, file := range files {
78829-		ast.Inspect(file, f)
78830-	}
78831-
78832-	return nil, nil, nil
78833-}
78834diff -urN a/gopls/internal/lsp/source/identifier.go b/gopls/internal/lsp/source/identifier.go
78835--- a/gopls/internal/lsp/source/identifier.go	2000-01-01 00:00:00.000000000 -0000
78836+++ b/gopls/internal/lsp/source/identifier.go	1970-01-01 00:00:00.000000000 +0000
78837@@ -1,174 +0,0 @@
78838-// Copyright 2018 The Go Authors. All rights reserved.
78839-// Use of this source code is governed by a BSD-style
78840-// license that can be found in the LICENSE file.
78841-
78842-package source
78843-
78844-import (
78845-	"errors"
78846-	"go/ast"
78847-	"go/types"
78848-
78849-	"golang.org/x/tools/internal/typeparams"
78850-)
78851-
78852-// ErrNoIdentFound is error returned when no identifier is found at a particular position
78853-var ErrNoIdentFound = errors.New("no identifier found")
78854-
78855-// inferredSignature determines the resolved non-generic signature for an
78856-// identifier in an instantiation expression.
78857-//
78858-// If no such signature exists, it returns nil.
78859-func inferredSignature(info *types.Info, id *ast.Ident) *types.Signature {
78860-	inst := typeparams.GetInstances(info)[id]
78861-	sig, _ := inst.Type.(*types.Signature)
78862-	return sig
78863-}
78864-
78865-func searchForEnclosing(info *types.Info, path []ast.Node) *types.TypeName {
78866-	for _, n := range path {
78867-		switch n := n.(type) {
78868-		case *ast.SelectorExpr:
78869-			if sel, ok := info.Selections[n]; ok {
78870-				recv := Deref(sel.Recv())
78871-
78872-				// Keep track of the last exported type seen.
78873-				var exported *types.TypeName
78874-				if named, ok := recv.(*types.Named); ok && named.Obj().Exported() {
78875-					exported = named.Obj()
78876-				}
78877-				// We don't want the last element, as that's the field or
78878-				// method itself.
78879-				for _, index := range sel.Index()[:len(sel.Index())-1] {
78880-					if r, ok := recv.Underlying().(*types.Struct); ok {
78881-						recv = Deref(r.Field(index).Type())
78882-						if named, ok := recv.(*types.Named); ok && named.Obj().Exported() {
78883-							exported = named.Obj()
78884-						}
78885-					}
78886-				}
78887-				return exported
78888-			}
78889-		}
78890-	}
78891-	return nil
78892-}
78893-
78894-// typeToObject returns the relevant type name for the given type, after
78895-// unwrapping pointers, arrays, slices, channels, and function signatures with
78896-// a single non-error result.
78897-func typeToObject(typ types.Type) *types.TypeName {
78898-	switch typ := typ.(type) {
78899-	case *types.Named:
78900-		// TODO(rfindley): this should use typeparams.NamedTypeOrigin.
78901-		return typ.Obj()
78902-	case *types.Pointer:
78903-		return typeToObject(typ.Elem())
78904-	case *types.Array:
78905-		return typeToObject(typ.Elem())
78906-	case *types.Slice:
78907-		return typeToObject(typ.Elem())
78908-	case *types.Chan:
78909-		return typeToObject(typ.Elem())
78910-	case *types.Signature:
78911-		// Try to find a return value of a named type. If there's only one
78912-		// such value, jump to its type definition.
78913-		var res *types.TypeName
78914-
78915-		results := typ.Results()
78916-		for i := 0; i < results.Len(); i++ {
78917-			obj := typeToObject(results.At(i).Type())
78918-			if obj == nil || hasErrorType(obj) {
78919-				// Skip builtins.
78920-				continue
78921-			}
78922-			if res != nil {
78923-				// The function/method must have only one return value of a named type.
78924-				return nil
78925-			}
78926-
78927-			res = obj
78928-		}
78929-		return res
78930-	default:
78931-		return nil
78932-	}
78933-}
78934-
78935-func hasErrorType(obj types.Object) bool {
78936-	return types.IsInterface(obj.Type()) && obj.Pkg() == nil && obj.Name() == "error"
78937-}
78938-
78939-// typeSwitchImplicits returns all the implicit type switch objects that
78940-// correspond to the leaf *ast.Ident. It also returns the original type
78941-// associated with the identifier (outside of a case clause).
78942-func typeSwitchImplicits(info *types.Info, path []ast.Node) ([]types.Object, types.Type) {
78943-	ident, _ := path[0].(*ast.Ident)
78944-	if ident == nil {
78945-		return nil, nil
78946-	}
78947-
78948-	var (
78949-		ts     *ast.TypeSwitchStmt
78950-		assign *ast.AssignStmt
78951-		cc     *ast.CaseClause
78952-		obj    = info.ObjectOf(ident)
78953-	)
78954-
78955-	// Walk our ancestors to determine if our leaf ident refers to a
78956-	// type switch variable, e.g. the "a" from "switch a := b.(type)".
78957-Outer:
78958-	for i := 1; i < len(path); i++ {
78959-		switch n := path[i].(type) {
78960-		case *ast.AssignStmt:
78961-			// Check if ident is the "a" in "a := foo.(type)". The "a" in
78962-			// this case has no types.Object, so check for ident equality.
78963-			if len(n.Lhs) == 1 && n.Lhs[0] == ident {
78964-				assign = n
78965-			}
78966-		case *ast.CaseClause:
78967-			// Check if ident is a use of "a" within a case clause. Each
78968-			// case clause implicitly maps "a" to a different types.Object,
78969-			// so check if ident's object is the case clause's implicit
78970-			// object.
78971-			if obj != nil && info.Implicits[n] == obj {
78972-				cc = n
78973-			}
78974-		case *ast.TypeSwitchStmt:
78975-			// Look for the type switch that owns our previously found
78976-			// *ast.AssignStmt or *ast.CaseClause.
78977-			if n.Assign == assign {
78978-				ts = n
78979-				break Outer
78980-			}
78981-
78982-			for _, stmt := range n.Body.List {
78983-				if stmt == cc {
78984-					ts = n
78985-					break Outer
78986-				}
78987-			}
78988-		}
78989-	}
78990-	if ts == nil {
78991-		return nil, nil
78992-	}
78993-	// Our leaf ident refers to a type switch variable. Fan out to the
78994-	// type switch's implicit case clause objects.
78995-	var objs []types.Object
78996-	for _, cc := range ts.Body.List {
78997-		if ccObj := info.Implicits[cc]; ccObj != nil {
78998-			objs = append(objs, ccObj)
78999-		}
79000-	}
79001-	// The right-hand side of a type switch should only have one
79002-	// element, and we need to track its type in order to generate
79003-	// hover information for implicit type switch variables.
79004-	var typ types.Type
79005-	if assign, ok := ts.Assign.(*ast.AssignStmt); ok && len(assign.Rhs) == 1 {
79006-		if rhs := assign.Rhs[0].(*ast.TypeAssertExpr); ok {
79007-			typ = info.TypeOf(rhs.X)
79008-		}
79009-	}
79010-	return objs, typ
79011-}
79012diff -urN a/gopls/internal/lsp/source/identifier_test.go b/gopls/internal/lsp/source/identifier_test.go
79013--- a/gopls/internal/lsp/source/identifier_test.go	2000-01-01 00:00:00.000000000 -0000
79014+++ b/gopls/internal/lsp/source/identifier_test.go	1970-01-01 00:00:00.000000000 +0000
79015@@ -1,103 +0,0 @@
79016-// Copyright 2020 The Go Authors. All rights reserved.
79017-// Use of this source code is governed by a BSD-style
79018-// license that can be found in the LICENSE file.
79019-
79020-package source
79021-
79022-import (
79023-	"bytes"
79024-	"go/ast"
79025-	"go/parser"
79026-	"go/token"
79027-	"go/types"
79028-	"testing"
79029-)
79030-
79031-func TestSearchForEnclosing(t *testing.T) {
79032-	tests := []struct {
79033-		desc string
79034-		// For convenience, consider the first occurrence of the identifier "X" in
79035-		// src.
79036-		src string
79037-		// By convention, "" means no type found.
79038-		wantTypeName string
79039-	}{
79040-		{
79041-			// TODO(rFindley): is this correct, or do we want to resolve I2 here?
79042-			desc:         "embedded interface in interface",
79043-			src:          `package a; var y = i1.X; type i1 interface {I2}; type I2 interface{X()}`,
79044-			wantTypeName: "",
79045-		},
79046-		{
79047-			desc:         "embedded interface in struct",
79048-			src:          `package a; var y = t.X; type t struct {I}; type I interface{X()}`,
79049-			wantTypeName: "I",
79050-		},
79051-		{
79052-			desc:         "double embedding",
79053-			src:          `package a; var y = t1.X; type t1 struct {t2}; type t2 struct {I}; type I interface{X()}`,
79054-			wantTypeName: "I",
79055-		},
79056-	}
79057-
79058-	for _, test := range tests {
79059-		test := test
79060-		t.Run(test.desc, func(t *testing.T) {
79061-			fset := token.NewFileSet()
79062-			file, err := parser.ParseFile(fset, "a.go", test.src, parser.AllErrors)
79063-			if err != nil {
79064-				t.Fatal(err)
79065-			}
79066-			column := 1 + bytes.IndexRune([]byte(test.src), 'X')
79067-			pos := posAt(1, column, fset, "a.go")
79068-			path := pathEnclosingObjNode(file, pos)
79069-			if path == nil {
79070-				t.Fatalf("no ident found at (1, %d)", column)
79071-			}
79072-			info := newInfo()
79073-			if _, err = (*types.Config)(nil).Check("p", fset, []*ast.File{file}, info); err != nil {
79074-				t.Fatal(err)
79075-			}
79076-			obj := searchForEnclosing(info, path)
79077-			if obj == nil {
79078-				if test.wantTypeName != "" {
79079-					t.Errorf("searchForEnclosing(...) = <nil>, want %q", test.wantTypeName)
79080-				}
79081-				return
79082-			}
79083-			if got := obj.Name(); got != test.wantTypeName {
79084-				t.Errorf("searchForEnclosing(...) = %q, want %q", got, test.wantTypeName)
79085-			}
79086-		})
79087-	}
79088-}
79089-
79090-// posAt returns the token.Pos corresponding to the 1-based (line, column)
79091-// coordinates in the file fname of fset.
79092-func posAt(line, column int, fset *token.FileSet, fname string) token.Pos {
79093-	var tok *token.File
79094-	fset.Iterate(func(tf *token.File) bool {
79095-		if tf.Name() == fname {
79096-			tok = tf
79097-			return false
79098-		}
79099-		return true
79100-	})
79101-	if tok == nil {
79102-		return token.NoPos
79103-	}
79104-	start := tok.LineStart(line)
79105-	return start + token.Pos(column-1)
79106-}
79107-
79108-// newInfo returns a types.Info with all maps populated.
79109-func newInfo() *types.Info {
79110-	return &types.Info{
79111-		Types:      make(map[ast.Expr]types.TypeAndValue),
79112-		Defs:       make(map[*ast.Ident]types.Object),
79113-		Uses:       make(map[*ast.Ident]types.Object),
79114-		Implicits:  make(map[ast.Node]types.Object),
79115-		Selections: make(map[*ast.SelectorExpr]*types.Selection),
79116-		Scopes:     make(map[ast.Node]*types.Scope),
79117-	}
79118-}
79119diff -urN a/gopls/internal/lsp/source/implementation.go b/gopls/internal/lsp/source/implementation.go
79120--- a/gopls/internal/lsp/source/implementation.go	2000-01-01 00:00:00.000000000 -0000
79121+++ b/gopls/internal/lsp/source/implementation.go	1970-01-01 00:00:00.000000000 +0000
79122@@ -1,482 +0,0 @@
79123-// Copyright 2019 The Go Authors. All rights reserved.
79124-// Use of this source code is governed by a BSD-style
79125-// license that can be found in the LICENSE file.
79126-
79127-package source
79128-
79129-import (
79130-	"context"
79131-	"errors"
79132-	"fmt"
79133-	"go/ast"
79134-	"go/token"
79135-	"go/types"
79136-	"reflect"
79137-	"sort"
79138-	"strings"
79139-	"sync"
79140-
79141-	"golang.org/x/sync/errgroup"
79142-	"golang.org/x/tools/gopls/internal/lsp/protocol"
79143-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
79144-	"golang.org/x/tools/gopls/internal/lsp/source/methodsets"
79145-	"golang.org/x/tools/gopls/internal/span"
79146-	"golang.org/x/tools/internal/event"
79147-)
79148-
79149-// This file defines the new implementation of the 'implementation'
79150-// operator that does not require type-checker data structures for an
79151-// unbounded number of packages.
79152-//
79153-// TODO(adonovan):
79154-// - Audit to ensure robustness in face of type errors.
79155-// - Support 'error' and 'error.Error', which were also lacking from the old implementation.
79156-// - Eliminate false positives due to 'tricky' cases of the global algorithm.
79157-// - Ensure we have test coverage of:
79158-//      type aliases
79159-//      nil, PkgName, Builtin (all errors)
79160-//      any (empty result)
79161-//      method of unnamed interface type (e.g. var x interface { f() })
79162-//        (the global algorithm may find implementations of this type
79163-//         but will not include it in the index.)
79164-
79165-// Implementation returns a new sorted array of locations of
79166-// declarations of types that implement (or are implemented by) the
79167-// type referred to at the given position.
79168-//
79169-// If the position denotes a method, the computation is applied to its
79170-// receiver type and then its corresponding methods are returned.
79171-func Implementation(ctx context.Context, snapshot Snapshot, f FileHandle, pp protocol.Position) ([]protocol.Location, error) {
79172-	ctx, done := event.Start(ctx, "source.Implementation")
79173-	defer done()
79174-
79175-	locs, err := implementations2(ctx, snapshot, f, pp)
79176-	if err != nil {
79177-		return nil, err
79178-	}
79179-
79180-	// Sort and de-duplicate locations.
79181-	sort.Slice(locs, func(i, j int) bool {
79182-		return protocol.CompareLocation(locs[i], locs[j]) < 0
79183-	})
79184-	out := locs[:0]
79185-	for _, loc := range locs {
79186-		if len(out) == 0 || out[len(out)-1] != loc {
79187-			out = append(out, loc)
79188-		}
79189-	}
79190-	locs = out
79191-
79192-	return locs, nil
79193-}
79194-
79195-func implementations2(ctx context.Context, snapshot Snapshot, fh FileHandle, pp protocol.Position) ([]protocol.Location, error) {
79196-
79197-	// Type-check the query package, find the query identifier,
79198-	// and locate the type or method declaration it refers to.
79199-	declPosn, err := typeDeclPosition(ctx, snapshot, fh.URI(), pp)
79200-	if err != nil {
79201-		return nil, err
79202-	}
79203-
79204-	// Type-check the declaring package (incl. variants) for use
79205-	// by the "local" search, which uses type information to
79206-	// enumerate all types within the package that satisfy the
79207-	// query type, even those defined local to a function.
79208-	declURI := span.URIFromPath(declPosn.Filename)
79209-	declMetas, err := snapshot.MetadataForFile(ctx, declURI)
79210-	if err != nil {
79211-		return nil, err
79212-	}
79213-	if len(declMetas) == 0 {
79214-		return nil, fmt.Errorf("no packages for file %s", declURI)
79215-	}
79216-	ids := make([]PackageID, len(declMetas))
79217-	for i, m := range declMetas {
79218-		ids[i] = m.ID
79219-	}
79220-	localPkgs, err := snapshot.TypeCheck(ctx, ids...)
79221-	if err != nil {
79222-		return nil, err
79223-	}
79224-	// The narrowest package will do, since the local search is based
79225-	// on position and the global search is based on fingerprint.
79226-	// (Neither is based on object identity.)
79227-	declPkg := localPkgs[0]
79228-	declFile, err := declPkg.File(declURI)
79229-	if err != nil {
79230-		return nil, err // "can't happen"
79231-	}
79232-
79233-	// Find declaration of corresponding object
79234-	// in this package based on (URI, offset).
79235-	pos, err := safetoken.Pos(declFile.Tok, declPosn.Offset)
79236-	if err != nil {
79237-		return nil, err
79238-	}
79239-	// TODO(adonovan): simplify: use objectsAt?
79240-	path := pathEnclosingObjNode(declFile.File, pos)
79241-	if path == nil {
79242-		return nil, ErrNoIdentFound // checked earlier
79243-	}
79244-	id, ok := path[0].(*ast.Ident)
79245-	if !ok {
79246-		return nil, ErrNoIdentFound // checked earlier
79247-	}
79248-	obj := declPkg.GetTypesInfo().ObjectOf(id) // may be nil
79249-
79250-	// Is the selected identifier a type name or method?
79251-	// (For methods, report the corresponding method names.)
79252-	var queryType types.Type
79253-	var queryMethodID string
79254-	switch obj := obj.(type) {
79255-	case *types.TypeName:
79256-		queryType = obj.Type()
79257-	case *types.Func:
79258-		// For methods, use the receiver type, which may be anonymous.
79259-		if recv := obj.Type().(*types.Signature).Recv(); recv != nil {
79260-			queryType = recv.Type()
79261-			queryMethodID = obj.Id()
79262-		}
79263-	}
79264-	if queryType == nil {
79265-		return nil, fmt.Errorf("%s is not a type or method", id.Name)
79266-	}
79267-
79268-	// Compute the method-set fingerprint used as a key to the global search.
79269-	key, hasMethods := methodsets.KeyOf(queryType)
79270-	if !hasMethods {
79271-		// A type with no methods yields an empty result.
79272-		// (No point reporting that every type satisfies 'any'.)
79273-		return nil, nil
79274-	}
79275-
79276-	// The global search needs to look at every package in the workspace;
79277-	// see package ./methodsets.
79278-	//
79279-	// For now we do all the type checking before beginning the search.
79280-	// TODO(adonovan): opt: search in parallel topological order
79281-	// so that we can overlap index lookup with typechecking.
79282-	// I suspect a number of algorithms on the result of TypeCheck could
79283-	// be optimized by being applied as soon as each package is available.
79284-	globalMetas, err := snapshot.AllMetadata(ctx)
79285-	if err != nil {
79286-		return nil, err
79287-	}
79288-	globalIDs := make([]PackageID, 0, len(globalMetas))
79289-	for _, m := range globalMetas {
79290-		if m.PkgPath == declPkg.Metadata().PkgPath {
79291-			continue // declaring package is handled by local implementation
79292-		}
79293-		globalIDs = append(globalIDs, m.ID)
79294-	}
79295-	indexes, err := snapshot.MethodSets(ctx, globalIDs...)
79296-	if err != nil {
79297-		return nil, err
79298-	}
79299-
79300-	// Search local and global packages in parallel.
79301-	var (
79302-		group  errgroup.Group
79303-		locsMu sync.Mutex
79304-		locs   []protocol.Location
79305-	)
79306-	// local search
79307-	for _, localPkg := range localPkgs {
79308-		localPkg := localPkg
79309-		group.Go(func() error {
79310-			localLocs, err := localImplementations(ctx, snapshot, localPkg, queryType, queryMethodID)
79311-			if err != nil {
79312-				return err
79313-			}
79314-			locsMu.Lock()
79315-			locs = append(locs, localLocs...)
79316-			locsMu.Unlock()
79317-			return nil
79318-		})
79319-	}
79320-	// global search
79321-	for _, index := range indexes {
79322-		index := index
79323-		group.Go(func() error {
79324-			for _, res := range index.Search(key, queryMethodID) {
79325-				loc := res.Location
79326-				// Map offsets to protocol.Locations in parallel (may involve I/O).
79327-				group.Go(func() error {
79328-					ploc, err := offsetToLocation(ctx, snapshot, loc.Filename, loc.Start, loc.End)
79329-					if err != nil {
79330-						return err
79331-					}
79332-					locsMu.Lock()
79333-					locs = append(locs, ploc)
79334-					locsMu.Unlock()
79335-					return nil
79336-				})
79337-			}
79338-			return nil
79339-		})
79340-	}
79341-	if err := group.Wait(); err != nil {
79342-		return nil, err
79343-	}
79344-
79345-	return locs, nil
79346-}
79347-
79348-// offsetToLocation converts an offset-based position to a protocol.Location,
79349-// which requires reading the file.
79350-func offsetToLocation(ctx context.Context, snapshot Snapshot, filename string, start, end int) (protocol.Location, error) {
79351-	uri := span.URIFromPath(filename)
79352-	fh, err := snapshot.GetFile(ctx, uri)
79353-	if err != nil {
79354-		return protocol.Location{}, err // cancelled, perhaps
79355-	}
79356-	content, err := fh.Read()
79357-	if err != nil {
79358-		return protocol.Location{}, err // nonexistent or deleted ("can't happen")
79359-	}
79360-	m := protocol.NewMapper(uri, content)
79361-	return m.OffsetLocation(start, end)
79362-}
79363-
79364-// typeDeclPosition returns the position of the declaration of the
79365-// type (or one of its methods) referred to at (uri, ppos).
79366-func typeDeclPosition(ctx context.Context, snapshot Snapshot, uri span.URI, ppos protocol.Position) (token.Position, error) {
79367-	var noPosn token.Position
79368-
79369-	pkg, pgf, err := PackageForFile(ctx, snapshot, uri, WidestPackage)
79370-	if err != nil {
79371-		return noPosn, err
79372-	}
79373-	pos, err := pgf.PositionPos(ppos)
79374-	if err != nil {
79375-		return noPosn, err
79376-	}
79377-
79378-	// This function inherits the limitation of its predecessor in
79379-	// requiring the selection to be an identifier (of a type or
79380-	// method). But there's no fundamental reason why one could
79381-	// not pose this query about any selected piece of syntax that
79382-	// has a type and thus a method set.
79383-	// (If LSP was more thorough about passing text selections as
79384-	// intervals to queries, you could ask about the method set of a
79385-	// subexpression such as x.f().)
79386-
79387-	// TODO(adonovan): simplify: use objectsAt?
79388-	path := pathEnclosingObjNode(pgf.File, pos)
79389-	if path == nil {
79390-		return noPosn, ErrNoIdentFound
79391-	}
79392-	id, ok := path[0].(*ast.Ident)
79393-	if !ok {
79394-		return noPosn, ErrNoIdentFound
79395-	}
79396-
79397-	// Is the object a type or method? Reject other kinds.
79398-	obj := pkg.GetTypesInfo().Uses[id]
79399-	if obj == nil {
79400-		// Check uses first (unlike ObjectOf) so that T in
79401-		// struct{T} is treated as a reference to a type,
79402-		// not a declaration of a field.
79403-		obj = pkg.GetTypesInfo().Defs[id]
79404-	}
79405-	switch obj := obj.(type) {
79406-	case *types.TypeName:
79407-		// ok
79408-	case *types.Func:
79409-		if obj.Type().(*types.Signature).Recv() == nil {
79410-			return noPosn, fmt.Errorf("%s is a function, not a method", id.Name)
79411-		}
79412-	case nil:
79413-		return noPosn, fmt.Errorf("%s denotes unknown object", id.Name)
79414-	default:
79415-		// e.g. *types.Var -> "var".
79416-		kind := strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types."))
79417-		return noPosn, fmt.Errorf("%s is a %s, not a type", id.Name, kind)
79418-	}
79419-
79420-	declPosn := safetoken.StartPosition(pkg.FileSet(), obj.Pos())
79421-	return declPosn, nil
79422-}
79423-
79424-// localImplementations searches within pkg for declarations of all
79425-// types that are assignable to/from the query type, and returns a new
79426-// unordered array of their locations.
79427-//
79428-// If methodID is non-empty, the function instead returns the location
79429-// of each type's method (if any) of that ID.
79430-//
79431-// ("Local" refers to the search within the same package, but this
79432-// function's results may include type declarations that are local to
79433-// a function body. The global search index excludes such types
79434-// because reliably naming such types is hard.)
79435-func localImplementations(ctx context.Context, snapshot Snapshot, pkg Package, queryType types.Type, methodID string) ([]protocol.Location, error) {
79436-	queryType = methodsets.EnsurePointer(queryType)
79437-
79438-	// Scan through all type declarations in the syntax.
79439-	var locs []protocol.Location
79440-	var methodLocs []methodsets.Location
79441-	for _, pgf := range pkg.CompiledGoFiles() {
79442-		ast.Inspect(pgf.File, func(n ast.Node) bool {
79443-			spec, ok := n.(*ast.TypeSpec)
79444-			if !ok {
79445-				return true // not a type declaration
79446-			}
79447-			def := pkg.GetTypesInfo().Defs[spec.Name]
79448-			if def == nil {
79449-				return true // "can't happen" for types
79450-			}
79451-			if def.(*types.TypeName).IsAlias() {
79452-				return true // skip type aliases to avoid duplicate reporting
79453-			}
79454-			candidateType := methodsets.EnsurePointer(def.Type())
79455-
79456-			// The historical behavior enshrined by this
79457-			// function rejects cases where both are
79458-			// (nontrivial) interface types?
79459-			// That seems like useful information.
79460-			// TODO(adonovan): UX: report I/I pairs too?
79461-			// The same question appears in the global algorithm (methodsets).
79462-			if !concreteImplementsIntf(candidateType, queryType) {
79463-				return true // not assignable
79464-			}
79465-
79466-			// Ignore types with empty method sets.
79467-			// (No point reporting that every type satisfies 'any'.)
79468-			mset := types.NewMethodSet(candidateType)
79469-			if mset.Len() == 0 {
79470-				return true
79471-			}
79472-
79473-			if methodID == "" {
79474-				// Found matching type.
79475-				locs = append(locs, mustLocation(pgf, spec.Name))
79476-				return true
79477-			}
79478-
79479-			// Find corresponding method.
79480-			//
79481-			// We can't use LookupFieldOrMethod because it requires
79482-			// the methodID's types.Package, which we don't know.
79483-			// We could recursively search pkg.Imports for it,
79484-			// but it's easier to walk the method set.
79485-			for i := 0; i < mset.Len(); i++ {
79486-				method := mset.At(i).Obj()
79487-				if method.Id() == methodID {
79488-					posn := safetoken.StartPosition(pkg.FileSet(), method.Pos())
79489-					methodLocs = append(methodLocs, methodsets.Location{
79490-						Filename: posn.Filename,
79491-						Start:    posn.Offset,
79492-						End:      posn.Offset + len(method.Name()),
79493-					})
79494-					break
79495-				}
79496-			}
79497-			return true
79498-		})
79499-	}
79500-
79501-	// Finally convert method positions to protocol form by reading the files.
79502-	for _, mloc := range methodLocs {
79503-		loc, err := offsetToLocation(ctx, snapshot, mloc.Filename, mloc.Start, mloc.End)
79504-		if err != nil {
79505-			return nil, err
79506-		}
79507-		locs = append(locs, loc)
79508-	}
79509-
79510-	return locs, nil
79511-}
79512-
79513-// concreteImplementsIntf returns true if a is an interface type implemented by
79514-// concrete type b, or vice versa.
79515-func concreteImplementsIntf(a, b types.Type) bool {
79516-	aIsIntf, bIsIntf := types.IsInterface(a), types.IsInterface(b)
79517-
79518-	// Make sure exactly one is an interface type.
79519-	if aIsIntf == bIsIntf {
79520-		return false
79521-	}
79522-
79523-	// Rearrange if needed so "a" is the concrete type.
79524-	if aIsIntf {
79525-		a, b = b, a
79526-	}
79527-
79528-	// TODO(adonovan): this should really use GenericAssignableTo
79529-	// to report (e.g.) "ArrayList[T] implements List[T]", but
79530-	// GenericAssignableTo doesn't work correctly on pointers to
79531-	// generic named types. Thus the legacy implementation and the
79532-	// "local" part of implementation2 fail to report generics.
79533-	// The global algorithm based on subsets does the right thing.
79534-	return types.AssignableTo(a, b)
79535-}
79536-
79537-var (
79538-	// TODO(adonovan): why do various RPC handlers related to
79539-	// IncomingCalls return (nil, nil) on the protocol in response
79540-	// to this error? That seems like a violation of the protocol.
79541-	// Is it perhaps a workaround for VSCode behavior?
79542-	errNoObjectFound = errors.New("no object found")
79543-)
79544-
79545-// pathEnclosingObjNode returns the AST path to the object-defining
79546-// node associated with pos. "Object-defining" means either an
79547-// *ast.Ident mapped directly to a types.Object or an ast.Node mapped
79548-// implicitly to a types.Object.
79549-func pathEnclosingObjNode(f *ast.File, pos token.Pos) []ast.Node {
79550-	var (
79551-		path  []ast.Node
79552-		found bool
79553-	)
79554-
79555-	ast.Inspect(f, func(n ast.Node) bool {
79556-		if found {
79557-			return false
79558-		}
79559-
79560-		if n == nil {
79561-			path = path[:len(path)-1]
79562-			return false
79563-		}
79564-
79565-		path = append(path, n)
79566-
79567-		switch n := n.(type) {
79568-		case *ast.Ident:
79569-			// Include the position directly after identifier. This handles
79570-			// the common case where the cursor is right after the
79571-			// identifier the user is currently typing. Previously we
79572-			// handled this by calling astutil.PathEnclosingInterval twice,
79573-			// once for "pos" and once for "pos-1".
79574-			found = n.Pos() <= pos && pos <= n.End()
79575-		case *ast.ImportSpec:
79576-			if n.Path.Pos() <= pos && pos < n.Path.End() {
79577-				found = true
79578-				// If import spec has a name, add name to path even though
79579-				// position isn't in the name.
79580-				if n.Name != nil {
79581-					path = append(path, n.Name)
79582-				}
79583-			}
79584-		case *ast.StarExpr:
79585-			// Follow star expressions to the inner identifier.
79586-			if pos == n.Star {
79587-				pos = n.X.Pos()
79588-			}
79589-		}
79590-
79591-		return !found
79592-	})
79593-
79594-	if len(path) == 0 {
79595-		return nil
79596-	}
79597-
79598-	// Reverse path so leaf is first element.
79599-	for i := 0; i < len(path)/2; i++ {
79600-		path[i], path[len(path)-1-i] = path[len(path)-1-i], path[i]
79601-	}
79602-
79603-	return path
79604-}
79605diff -urN a/gopls/internal/lsp/source/inlay_hint.go b/gopls/internal/lsp/source/inlay_hint.go
79606--- a/gopls/internal/lsp/source/inlay_hint.go	2000-01-01 00:00:00.000000000 -0000
79607+++ b/gopls/internal/lsp/source/inlay_hint.go	1970-01-01 00:00:00.000000000 +0000
79608@@ -1,394 +0,0 @@
79609-// Copyright 2022 The Go Authors. All rights reserved.
79610-// Use of this source code is governed by a BSD-style
79611-// license that can be found in the LICENSE file.
79612-
79613-package source
79614-
79615-import (
79616-	"context"
79617-	"fmt"
79618-	"go/ast"
79619-	"go/constant"
79620-	"go/token"
79621-	"go/types"
79622-	"strings"
79623-
79624-	"golang.org/x/tools/gopls/internal/lsp/protocol"
79625-	"golang.org/x/tools/internal/event"
79626-	"golang.org/x/tools/internal/typeparams"
79627-)
79628-
79629-const (
79630-	maxLabelLength = 28
79631-)
79632-
79633-type InlayHintFunc func(node ast.Node, m *protocol.Mapper, tf *token.File, info *types.Info, q *types.Qualifier) []protocol.InlayHint
79634-
79635-type Hint struct {
79636-	Name string
79637-	Doc  string
79638-	Run  InlayHintFunc
79639-}
79640-
79641-const (
79642-	ParameterNames             = "parameterNames"
79643-	AssignVariableTypes        = "assignVariableTypes"
79644-	ConstantValues             = "constantValues"
79645-	RangeVariableTypes         = "rangeVariableTypes"
79646-	CompositeLiteralTypes      = "compositeLiteralTypes"
79647-	CompositeLiteralFieldNames = "compositeLiteralFields"
79648-	FunctionTypeParameters     = "functionTypeParameters"
79649-)
79650-
79651-var AllInlayHints = map[string]*Hint{
79652-	AssignVariableTypes: {
79653-		Name: AssignVariableTypes,
79654-		Doc:  "Enable/disable inlay hints for variable types in assign statements:\n```go\n\ti/* int*/, j/* int*/ := 0, len(r)-1\n```",
79655-		Run:  assignVariableTypes,
79656-	},
79657-	ParameterNames: {
79658-		Name: ParameterNames,
79659-		Doc:  "Enable/disable inlay hints for parameter names:\n```go\n\tparseInt(/* str: */ \"123\", /* radix: */ 8)\n```",
79660-		Run:  parameterNames,
79661-	},
79662-	ConstantValues: {
79663-		Name: ConstantValues,
79664-		Doc:  "Enable/disable inlay hints for constant values:\n```go\n\tconst (\n\t\tKindNone   Kind = iota/* = 0*/\n\t\tKindPrint/*  = 1*/\n\t\tKindPrintf/* = 2*/\n\t\tKindErrorf/* = 3*/\n\t)\n```",
79665-		Run:  constantValues,
79666-	},
79667-	RangeVariableTypes: {
79668-		Name: RangeVariableTypes,
79669-		Doc:  "Enable/disable inlay hints for variable types in range statements:\n```go\n\tfor k/* int*/, v/* string*/ := range []string{} {\n\t\tfmt.Println(k, v)\n\t}\n```",
79670-		Run:  rangeVariableTypes,
79671-	},
79672-	CompositeLiteralTypes: {
79673-		Name: CompositeLiteralTypes,
79674-		Doc:  "Enable/disable inlay hints for composite literal types:\n```go\n\tfor _, c := range []struct {\n\t\tin, want string\n\t}{\n\t\t/*struct{ in string; want string }*/{\"Hello, world\", \"dlrow ,olleH\"},\n\t}\n```",
79675-		Run:  compositeLiteralTypes,
79676-	},
79677-	CompositeLiteralFieldNames: {
79678-		Name: CompositeLiteralFieldNames,
79679-		Doc:  "Enable/disable inlay hints for composite literal field names:\n```go\n\t{/*in: */\"Hello, world\", /*want: */\"dlrow ,olleH\"}\n```",
79680-		Run:  compositeLiteralFields,
79681-	},
79682-	FunctionTypeParameters: {
79683-		Name: FunctionTypeParameters,
79684-		Doc:  "Enable/disable inlay hints for implicit type parameters on generic functions:\n```go\n\tmyFoo/*[int, string]*/(1, \"hello\")\n```",
79685-		Run:  funcTypeParams,
79686-	},
79687-}
79688-
79689-func InlayHint(ctx context.Context, snapshot Snapshot, fh FileHandle, pRng protocol.Range) ([]protocol.InlayHint, error) {
79690-	ctx, done := event.Start(ctx, "source.InlayHint")
79691-	defer done()
79692-
79693-	pkg, pgf, err := PackageForFile(ctx, snapshot, fh.URI(), NarrowestPackage)
79694-	if err != nil {
79695-		return nil, fmt.Errorf("getting file for InlayHint: %w", err)
79696-	}
79697-
79698-	// Collect a list of the inlay hints that are enabled.
79699-	inlayHintOptions := snapshot.View().Options().InlayHintOptions
79700-	var enabledHints []InlayHintFunc
79701-	for hint, enabled := range inlayHintOptions.Hints {
79702-		if !enabled {
79703-			continue
79704-		}
79705-		if h, ok := AllInlayHints[hint]; ok {
79706-			enabledHints = append(enabledHints, h.Run)
79707-		}
79708-	}
79709-	if len(enabledHints) == 0 {
79710-		return nil, nil
79711-	}
79712-
79713-	info := pkg.GetTypesInfo()
79714-	q := Qualifier(pgf.File, pkg.GetTypes(), info)
79715-
79716-	// Set the range to the full file if the range is not valid.
79717-	start, end := pgf.File.Pos(), pgf.File.End()
79718-	if pRng.Start.Line < pRng.End.Line || pRng.Start.Character < pRng.End.Character {
79719-		// Adjust start and end for the specified range.
79720-		var err error
79721-		start, end, err = pgf.RangePos(pRng)
79722-		if err != nil {
79723-			return nil, err
79724-		}
79725-	}
79726-
79727-	var hints []protocol.InlayHint
79728-	ast.Inspect(pgf.File, func(node ast.Node) bool {
79729-		// If not in range, we can stop looking.
79730-		if node == nil || node.End() < start || node.Pos() > end {
79731-			return false
79732-		}
79733-		for _, fn := range enabledHints {
79734-			hints = append(hints, fn(node, pgf.Mapper, pgf.Tok, info, &q)...)
79735-		}
79736-		return true
79737-	})
79738-	return hints, nil
79739-}
79740-
79741-func parameterNames(node ast.Node, m *protocol.Mapper, tf *token.File, info *types.Info, _ *types.Qualifier) []protocol.InlayHint {
79742-	callExpr, ok := node.(*ast.CallExpr)
79743-	if !ok {
79744-		return nil
79745-	}
79746-	signature, ok := info.TypeOf(callExpr.Fun).(*types.Signature)
79747-	if !ok {
79748-		return nil
79749-	}
79750-
79751-	var hints []protocol.InlayHint
79752-	for i, v := range callExpr.Args {
79753-		start, err := m.PosPosition(tf, v.Pos())
79754-		if err != nil {
79755-			continue
79756-		}
79757-		params := signature.Params()
79758-		// When a function has variadic params, we skip args after
79759-		// params.Len().
79760-		if i > params.Len()-1 {
79761-			break
79762-		}
79763-		param := params.At(i)
79764-		// param.Name is empty for built-ins like append
79765-		if param.Name() == "" {
79766-			continue
79767-		}
79768-		// Skip the parameter name hint if the arg matches the
79769-		// the parameter name.
79770-		if i, ok := v.(*ast.Ident); ok && i.Name == param.Name() {
79771-			continue
79772-		}
79773-
79774-		label := param.Name()
79775-		if signature.Variadic() && i == params.Len()-1 {
79776-			label = label + "..."
79777-		}
79778-		hints = append(hints, protocol.InlayHint{
79779-			Position:     start,
79780-			Label:        buildLabel(label + ":"),
79781-			Kind:         protocol.Parameter,
79782-			PaddingRight: true,
79783-		})
79784-	}
79785-	return hints
79786-}
79787-
79788-func funcTypeParams(node ast.Node, m *protocol.Mapper, tf *token.File, info *types.Info, _ *types.Qualifier) []protocol.InlayHint {
79789-	ce, ok := node.(*ast.CallExpr)
79790-	if !ok {
79791-		return nil
79792-	}
79793-	id, ok := ce.Fun.(*ast.Ident)
79794-	if !ok {
79795-		return nil
79796-	}
79797-	inst := typeparams.GetInstances(info)[id]
79798-	if inst.TypeArgs == nil {
79799-		return nil
79800-	}
79801-	start, err := m.PosPosition(tf, id.End())
79802-	if err != nil {
79803-		return nil
79804-	}
79805-	var args []string
79806-	for i := 0; i < inst.TypeArgs.Len(); i++ {
79807-		args = append(args, inst.TypeArgs.At(i).String())
79808-	}
79809-	if len(args) == 0 {
79810-		return nil
79811-	}
79812-	return []protocol.InlayHint{{
79813-		Position: start,
79814-		Label:    buildLabel("[" + strings.Join(args, ", ") + "]"),
79815-		Kind:     protocol.Type,
79816-	}}
79817-}
79818-
79819-func assignVariableTypes(node ast.Node, m *protocol.Mapper, tf *token.File, info *types.Info, q *types.Qualifier) []protocol.InlayHint {
79820-	stmt, ok := node.(*ast.AssignStmt)
79821-	if !ok || stmt.Tok != token.DEFINE {
79822-		return nil
79823-	}
79824-
79825-	var hints []protocol.InlayHint
79826-	for _, v := range stmt.Lhs {
79827-		if h := variableType(v, m, tf, info, q); h != nil {
79828-			hints = append(hints, *h)
79829-		}
79830-	}
79831-	return hints
79832-}
79833-
79834-func rangeVariableTypes(node ast.Node, m *protocol.Mapper, tf *token.File, info *types.Info, q *types.Qualifier) []protocol.InlayHint {
79835-	rStmt, ok := node.(*ast.RangeStmt)
79836-	if !ok {
79837-		return nil
79838-	}
79839-	var hints []protocol.InlayHint
79840-	if h := variableType(rStmt.Key, m, tf, info, q); h != nil {
79841-		hints = append(hints, *h)
79842-	}
79843-	if h := variableType(rStmt.Value, m, tf, info, q); h != nil {
79844-		hints = append(hints, *h)
79845-	}
79846-	return hints
79847-}
79848-
79849-func variableType(e ast.Expr, m *protocol.Mapper, tf *token.File, info *types.Info, q *types.Qualifier) *protocol.InlayHint {
79850-	typ := info.TypeOf(e)
79851-	if typ == nil {
79852-		return nil
79853-	}
79854-	end, err := m.PosPosition(tf, e.End())
79855-	if err != nil {
79856-		return nil
79857-	}
79858-	return &protocol.InlayHint{
79859-		Position:    end,
79860-		Label:       buildLabel(types.TypeString(typ, *q)),
79861-		Kind:        protocol.Type,
79862-		PaddingLeft: true,
79863-	}
79864-}
79865-
79866-func constantValues(node ast.Node, m *protocol.Mapper, tf *token.File, info *types.Info, _ *types.Qualifier) []protocol.InlayHint {
79867-	genDecl, ok := node.(*ast.GenDecl)
79868-	if !ok || genDecl.Tok != token.CONST {
79869-		return nil
79870-	}
79871-
79872-	var hints []protocol.InlayHint
79873-	for _, v := range genDecl.Specs {
79874-		spec, ok := v.(*ast.ValueSpec)
79875-		if !ok {
79876-			continue
79877-		}
79878-		end, err := m.PosPosition(tf, v.End())
79879-		if err != nil {
79880-			continue
79881-		}
79882-		// Show hints when values are missing or at least one value is not
79883-		// a basic literal.
79884-		showHints := len(spec.Values) == 0
79885-		checkValues := len(spec.Names) == len(spec.Values)
79886-		var values []string
79887-		for i, w := range spec.Names {
79888-			obj, ok := info.ObjectOf(w).(*types.Const)
79889-			if !ok || obj.Val().Kind() == constant.Unknown {
79890-				return nil
79891-			}
79892-			if checkValues {
79893-				switch spec.Values[i].(type) {
79894-				case *ast.BadExpr:
79895-					return nil
79896-				case *ast.BasicLit:
79897-				default:
79898-					if obj.Val().Kind() != constant.Bool {
79899-						showHints = true
79900-					}
79901-				}
79902-			}
79903-			values = append(values, fmt.Sprintf("%v", obj.Val()))
79904-		}
79905-		if !showHints || len(values) == 0 {
79906-			continue
79907-		}
79908-		hints = append(hints, protocol.InlayHint{
79909-			Position:    end,
79910-			Label:       buildLabel("= " + strings.Join(values, ", ")),
79911-			PaddingLeft: true,
79912-		})
79913-	}
79914-	return hints
79915-}
79916-
79917-func compositeLiteralFields(node ast.Node, m *protocol.Mapper, tf *token.File, info *types.Info, q *types.Qualifier) []protocol.InlayHint {
79918-	compLit, ok := node.(*ast.CompositeLit)
79919-	if !ok {
79920-		return nil
79921-	}
79922-	typ := info.TypeOf(compLit)
79923-	if typ == nil {
79924-		return nil
79925-	}
79926-	if t, ok := typ.(*types.Pointer); ok {
79927-		typ = t.Elem()
79928-	}
79929-	strct, ok := typ.Underlying().(*types.Struct)
79930-	if !ok {
79931-		return nil
79932-	}
79933-
79934-	var hints []protocol.InlayHint
79935-	var allEdits []protocol.TextEdit
79936-	for i, v := range compLit.Elts {
79937-		if _, ok := v.(*ast.KeyValueExpr); !ok {
79938-			start, err := m.PosPosition(tf, v.Pos())
79939-			if err != nil {
79940-				continue
79941-			}
79942-			if i > strct.NumFields()-1 {
79943-				break
79944-			}
79945-			hints = append(hints, protocol.InlayHint{
79946-				Position:     start,
79947-				Label:        buildLabel(strct.Field(i).Name() + ":"),
79948-				Kind:         protocol.Parameter,
79949-				PaddingRight: true,
79950-			})
79951-			allEdits = append(allEdits, protocol.TextEdit{
79952-				Range:   protocol.Range{Start: start, End: start},
79953-				NewText: strct.Field(i).Name() + ": ",
79954-			})
79955-		}
79956-	}
79957-	// It is not allowed to have a mix of keyed and unkeyed fields, so
79958-	// have the text edits add keys to all fields.
79959-	for i := range hints {
79960-		hints[i].TextEdits = allEdits
79961-	}
79962-	return hints
79963-}
79964-
79965-func compositeLiteralTypes(node ast.Node, m *protocol.Mapper, tf *token.File, info *types.Info, q *types.Qualifier) []protocol.InlayHint {
79966-	compLit, ok := node.(*ast.CompositeLit)
79967-	if !ok {
79968-		return nil
79969-	}
79970-	typ := info.TypeOf(compLit)
79971-	if typ == nil {
79972-		return nil
79973-	}
79974-	if compLit.Type != nil {
79975-		return nil
79976-	}
79977-	prefix := ""
79978-	if t, ok := typ.(*types.Pointer); ok {
79979-		typ = t.Elem()
79980-		prefix = "&"
79981-	}
79982-	// The type for this composite literal is implicit, add an inlay hint.
79983-	start, err := m.PosPosition(tf, compLit.Lbrace)
79984-	if err != nil {
79985-		return nil
79986-	}
79987-	return []protocol.InlayHint{{
79988-		Position: start,
79989-		Label:    buildLabel(fmt.Sprintf("%s%s", prefix, types.TypeString(typ, *q))),
79990-		Kind:     protocol.Type,
79991-	}}
79992-}
79993-
79994-func buildLabel(s string) []protocol.InlayHintLabelPart {
79995-	label := protocol.InlayHintLabelPart{
79996-		Value: s,
79997-	}
79998-	if len(s) > maxLabelLength+len("...") {
79999-		label.Value = s[:maxLabelLength] + "..."
80000-	}
80001-	return []protocol.InlayHintLabelPart{label}
80002-}
80003diff -urN a/gopls/internal/lsp/source/known_packages.go b/gopls/internal/lsp/source/known_packages.go
80004--- a/gopls/internal/lsp/source/known_packages.go	2000-01-01 00:00:00.000000000 -0000
80005+++ b/gopls/internal/lsp/source/known_packages.go	1970-01-01 00:00:00.000000000 +0000
80006@@ -1,140 +0,0 @@
80007-// Copyright 2020 The Go Authors. All rights reserved.
80008-// Use of this source code is governed by a BSD-style
80009-// license that can be found in the LICENSE file.
80010-
80011-package source
80012-
80013-import (
80014-	"context"
80015-	"fmt"
80016-	"go/parser"
80017-	"go/token"
80018-	"sort"
80019-	"strings"
80020-	"sync"
80021-	"time"
80022-
80023-	"golang.org/x/tools/internal/event"
80024-	"golang.org/x/tools/internal/imports"
80025-)
80026-
80027-// KnownPackagePaths returns a new list of package paths of all known
80028-// packages in the package graph that could potentially be imported by
80029-// the given file. The list is ordered lexicographically, except that
80030-// all dot-free paths (standard packages) appear before dotful ones.
80031-//
80032-// It is part of the gopls.list_known_packages command.
80033-func KnownPackagePaths(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]PackagePath, error) {
80034-	// This algorithm is expressed in terms of Metadata, not Packages,
80035-	// so it doesn't cause or wait for type checking.
80036-
80037-	// Find a Metadata containing the file.
80038-	metas, err := snapshot.MetadataForFile(ctx, fh.URI())
80039-	if err != nil {
80040-		return nil, err // e.g. context cancelled
80041-	}
80042-	if len(metas) == 0 {
80043-		return nil, fmt.Errorf("no loaded package contain file %s", fh.URI())
80044-	}
80045-	current := metas[0] // pick one arbitrarily (they should all have the same package path)
80046-
80047-	// Parse the file's imports so we can compute which
80048-	// PackagePaths are imported by this specific file.
80049-	src, err := fh.Read()
80050-	if err != nil {
80051-		return nil, err
80052-	}
80053-	file, err := parser.ParseFile(token.NewFileSet(), fh.URI().Filename(), src, parser.ImportsOnly)
80054-	if err != nil {
80055-		return nil, err
80056-	}
80057-	imported := make(map[PackagePath]bool)
80058-	for _, imp := range file.Imports {
80059-		if id := current.DepsByImpPath[UnquoteImportPath(imp)]; id != "" {
80060-			if m := snapshot.Metadata(id); m != nil {
80061-				imported[m.PkgPath] = true
80062-			}
80063-		}
80064-	}
80065-
80066-	// Now find candidates among known packages.
80067-	knownPkgs, err := snapshot.AllMetadata(ctx)
80068-	if err != nil {
80069-		return nil, err
80070-	}
80071-	seen := make(map[PackagePath]bool)
80072-	for _, knownPkg := range knownPkgs {
80073-		// package main cannot be imported
80074-		if knownPkg.Name == "main" {
80075-			continue
80076-		}
80077-		// test packages cannot be imported
80078-		if knownPkg.ForTest != "" {
80079-			continue
80080-		}
80081-		// No need to import what the file already imports.
80082-		// This check is based on PackagePath, not PackageID,
80083-		// so that all test variants are filtered out too.
80084-		if imported[knownPkg.PkgPath] {
80085-			continue
80086-		}
80087-		// make sure internal packages are importable by the file
80088-		if !IsValidImport(current.PkgPath, knownPkg.PkgPath) {
80089-			continue
80090-		}
80091-		// naive check on cyclical imports
80092-		if isDirectlyCyclical(current, knownPkg) {
80093-			continue
80094-		}
80095-		// AllMetadata may have multiple variants of a pkg.
80096-		seen[knownPkg.PkgPath] = true
80097-	}
80098-
80099-	// Augment the set by invoking the goimports algorithm.
80100-	if err := snapshot.RunProcessEnvFunc(ctx, func(o *imports.Options) error {
80101-		ctx, cancel := context.WithTimeout(ctx, time.Millisecond*80)
80102-		defer cancel()
80103-		var seenMu sync.Mutex
80104-		wrapped := func(ifix imports.ImportFix) {
80105-			seenMu.Lock()
80106-			defer seenMu.Unlock()
80107-			// TODO(adonovan): what if the actual package path has a vendor/ prefix?
80108-			seen[PackagePath(ifix.StmtInfo.ImportPath)] = true
80109-		}
80110-		return imports.GetAllCandidates(ctx, wrapped, "", fh.URI().Filename(), string(current.Name), o.Env)
80111-	}); err != nil {
80112-		// If goimports failed, proceed with just the candidates from the metadata.
80113-		event.Error(ctx, "imports.GetAllCandidates", err)
80114-	}
80115-
80116-	// Sort lexicographically, but with std before non-std packages.
80117-	paths := make([]PackagePath, 0, len(seen))
80118-	for path := range seen {
80119-		paths = append(paths, path)
80120-	}
80121-	sort.Slice(paths, func(i, j int) bool {
80122-		importI, importJ := paths[i], paths[j]
80123-		iHasDot := strings.Contains(string(importI), ".")
80124-		jHasDot := strings.Contains(string(importJ), ".")
80125-		if iHasDot != jHasDot {
80126-			return jHasDot // dot-free paths (standard packages) compare less
80127-		}
80128-		return importI < importJ
80129-	})
80130-
80131-	return paths, nil
80132-}
80133-
80134-// isDirectlyCyclical checks if imported directly imports pkg.
80135-// It does not (yet) offer a full cyclical check because showing a user
80136-// a list of importable packages already generates a very large list
80137-// and having a few false positives in there could be worth the
80138-// performance snappiness.
80139-//
80140-// TODO(adonovan): ensure that metadata graph is always cyclic!
80141-// Many algorithms will get confused or even stuck in the
80142-// presence of cycles. Then replace this function by 'false'.
80143-func isDirectlyCyclical(pkg, imported *Metadata) bool {
80144-	_, ok := imported.DepsByPkgPath[pkg.PkgPath]
80145-	return ok
80146-}
80147diff -urN a/gopls/internal/lsp/source/linkname.go b/gopls/internal/lsp/source/linkname.go
80148--- a/gopls/internal/lsp/source/linkname.go	2000-01-01 00:00:00.000000000 -0000
80149+++ b/gopls/internal/lsp/source/linkname.go	1970-01-01 00:00:00.000000000 +0000
80150@@ -1,136 +0,0 @@
80151-// Copyright 2023 The Go Authors. All rights reserved.
80152-// Use of this source code is governed by a BSD-style
80153-// license that can be found in the LICENSE file.
80154-
80155-package source
80156-
80157-import (
80158-	"context"
80159-	"errors"
80160-	"fmt"
80161-	"go/token"
80162-	"strings"
80163-
80164-	"golang.org/x/tools/gopls/internal/lsp/protocol"
80165-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
80166-	"golang.org/x/tools/gopls/internal/span"
80167-)
80168-
80169-// ErrNoLinkname is returned by LinknameDefinition when no linkname
80170-// directive is found at a particular position.
80171-// As such it indicates that other definitions could be worth checking.
80172-var ErrNoLinkname = errors.New("no linkname directive found")
80173-
80174-// LinknameDefinition finds the definition of the linkname directive in fh at pos.
80175-// If there is no linkname directive at pos, returns ErrNoLinkname.
80176-func LinknameDefinition(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protocol.Position) ([]protocol.Location, error) {
80177-	pkgPath, name := parseLinkname(ctx, snapshot, fh, pos)
80178-	if pkgPath == "" {
80179-		return nil, ErrNoLinkname
80180-	}
80181-	return findLinkname(ctx, snapshot, fh, pos, PackagePath(pkgPath), name)
80182-}
80183-
80184-// parseLinkname attempts to parse a go:linkname declaration at the given pos.
80185-// If successful, it returns the package path and object name referenced by the second
80186-// argument of the linkname directive.
80187-//
80188-// If the position is not in the second argument of a go:linkname directive, or parsing fails, it returns "", "".
80189-func parseLinkname(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protocol.Position) (pkgPath, name string) {
80190-	pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
80191-	if err != nil {
80192-		return "", ""
80193-	}
80194-
80195-	span, err := pgf.Mapper.PositionPoint(pos)
80196-	if err != nil {
80197-		return "", ""
80198-	}
80199-	atLine := span.Line()
80200-	atColumn := span.Column()
80201-
80202-	// Looking for pkgpath in '//go:linkname f pkgpath.g'.
80203-	// (We ignore 1-arg linkname directives.)
80204-	directive, column := findLinknameOnLine(pgf, atLine)
80205-	parts := strings.Fields(directive)
80206-	if len(parts) != 3 {
80207-		return "", ""
80208-	}
80209-
80210-	// Inside 2nd arg [start, end]?
80211-	end := column + len(directive)
80212-	start := end - len(parts[2])
80213-	if !(start <= atColumn && atColumn <= end) {
80214-		return "", ""
80215-	}
80216-	linkname := parts[2]
80217-
80218-	// Split the pkg path from the name.
80219-	dot := strings.LastIndexByte(linkname, '.')
80220-	if dot < 0 {
80221-		return "", ""
80222-	}
80223-	return linkname[:dot], linkname[dot+1:]
80224-}
80225-
80226-// findLinknameOnLine returns the first linkname directive on line and the column it starts at.
80227-// Returns "", 0 if no linkname directive is found on the line.
80228-func findLinknameOnLine(pgf *ParsedGoFile, line int) (string, int) {
80229-	for _, grp := range pgf.File.Comments {
80230-		for _, com := range grp.List {
80231-			if strings.HasPrefix(com.Text, "//go:linkname") {
80232-				p := safetoken.Position(pgf.Tok, com.Pos())
80233-				if p.Line == line {
80234-					return com.Text, p.Column
80235-				}
80236-			}
80237-		}
80238-	}
80239-	return "", 0
80240-}
80241-
80242-// findLinkname searches dependencies of packages containing fh for an object
80243-// with linker name matching the given package path and name.
80244-func findLinkname(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protocol.Position, pkgPath PackagePath, name string) ([]protocol.Location, error) {
80245-	// Typically the linkname refers to a forward dependency
80246-	// or a reverse dependency, but in general it may refer
80247-	// to any package in the workspace.
80248-	var pkgMeta *Metadata
80249-	metas, err := snapshot.AllMetadata(ctx)
80250-	if err != nil {
80251-		return nil, err
80252-	}
80253-	metas = RemoveIntermediateTestVariants(metas)
80254-	for _, meta := range metas {
80255-		if meta.PkgPath == pkgPath {
80256-			pkgMeta = meta
80257-			break
80258-		}
80259-	}
80260-	if pkgMeta == nil {
80261-		return nil, fmt.Errorf("cannot find package %q", pkgPath)
80262-	}
80263-
80264-	// When found, type check the desired package (snapshot.TypeCheck in TypecheckFull mode),
80265-	pkgs, err := snapshot.TypeCheck(ctx, pkgMeta.ID)
80266-	if err != nil {
80267-		return nil, err
80268-	}
80269-	pkg := pkgs[0]
80270-
80271-	obj := pkg.GetTypes().Scope().Lookup(name)
80272-	if obj == nil {
80273-		return nil, fmt.Errorf("package %q does not define %s", pkgPath, name)
80274-	}
80275-
80276-	objURI := safetoken.StartPosition(pkg.FileSet(), obj.Pos())
80277-	pgf, err := pkg.File(span.URIFromPath(objURI.Filename))
80278-	if err != nil {
80279-		return nil, err
80280-	}
80281-	loc, err := pgf.PosLocation(obj.Pos(), obj.Pos()+token.Pos(len(name)))
80282-	if err != nil {
80283-		return nil, err
80284-	}
80285-	return []protocol.Location{loc}, nil
80286-}
80287diff -urN a/gopls/internal/lsp/source/methodsets/methodsets.go b/gopls/internal/lsp/source/methodsets/methodsets.go
80288--- a/gopls/internal/lsp/source/methodsets/methodsets.go	2000-01-01 00:00:00.000000000 -0000
80289+++ b/gopls/internal/lsp/source/methodsets/methodsets.go	1970-01-01 00:00:00.000000000 +0000
80290@@ -1,508 +0,0 @@
80291-// Copyright 2023 The Go Authors. All rights reserved.
80292-// Use of this source code is governed by a BSD-style
80293-// license that can be found in the LICENSE file.
80294-
80295-// Package methodsets defines an incremental, serializable index of
80296-// method-set information that allows efficient 'implements' queries
80297-// across packages of the workspace without using the type checker.
80298-//
80299-// This package provides only the "global" (all workspace) search; the
80300-// "local" search within a given package uses a different
80301-// implementation based on type-checker data structures for a single
80302-// package plus variants; see ../implementation2.go.
80303-// The local algorithm is more precise as it tests function-local types too.
80304-//
80305-// A global index of function-local types is challenging since they
80306-// may reference other local types, for which we would need to invent
80307-// stable names, an unsolved problem described in passing in Go issue
80308-// 57497. The global algorithm also does not index anonymous interface
80309-// types, even outside function bodies.
80310-//
80311-// Consequently, global results are not symmetric: applying the
80312-// operation twice may not get you back where you started.
80313-package methodsets
80314-
80315-// DESIGN
80316-//
80317-// See https://go.dev/cl/452060 for a minimal exposition of the algorithm.
80318-//
80319-// For each method, we compute a fingerprint: a string representing
80320-// the method name and type such that equal fingerprint strings mean
80321-// identical method types.
80322-//
80323-// For efficiency, the fingerprint is reduced to a single bit
80324-// of a uint64, so that the method set can be represented as
80325-// the union of those method bits (a uint64 bitmask).
80326-// Assignability thus reduces to a subset check on bitmasks
80327-// followed by equality checks on fingerprints.
80328-//
80329-// In earlier experiments, using 128-bit masks instead of 64 reduced
80330-// the number of candidates by about 2x. Using (like a Bloom filter) a
80331-// different hash function to compute a second 64-bit mask and
80332-// performing a second mask test reduced it by about 4x.
80333-// Neither had much effect on the running time, presumably because a
80334-// single 64-bit mask is quite effective. See CL 452060 for details.
80335-
80336-import (
80337-	"bytes"
80338-	"encoding/gob"
80339-	"fmt"
80340-	"go/token"
80341-	"go/types"
80342-	"hash/crc32"
80343-	"log"
80344-	"strconv"
80345-	"strings"
80346-
80347-	"golang.org/x/tools/go/types/objectpath"
80348-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
80349-	"golang.org/x/tools/internal/typeparams"
80350-	"golang.org/x/tools/internal/typesinternal"
80351-)
80352-
80353-// An Index records the non-empty method sets of all package-level
80354-// types in a package in a form that permits assignability queries
80355-// without the type checker.
80356-type Index struct {
80357-	pkg gobPackage
80358-}
80359-
80360-// Decode decodes the given gob-encoded data as an Index.
80361-func Decode(data []byte) *Index {
80362-	var pkg gobPackage
80363-	mustDecode(data, &pkg)
80364-	return &Index{pkg}
80365-}
80366-
80367-// Encode encodes the receiver as gob-encoded data.
80368-func (index *Index) Encode() []byte {
80369-	return mustEncode(index.pkg)
80370-}
80371-
80372-func mustEncode(x interface{}) []byte {
80373-	var buf bytes.Buffer
80374-	if err := gob.NewEncoder(&buf).Encode(x); err != nil {
80375-		log.Fatalf("internal error encoding %T: %v", x, err)
80376-	}
80377-	return buf.Bytes()
80378-}
80379-
80380-func mustDecode(data []byte, ptr interface{}) {
80381-	if err := gob.NewDecoder(bytes.NewReader(data)).Decode(ptr); err != nil {
80382-		log.Fatalf("internal error decoding %T: %v", ptr, err)
80383-	}
80384-}
80385-
80386-// NewIndex returns a new index of method-set information for all
80387-// package-level types in the specified package.
80388-func NewIndex(fset *token.FileSet, pkg *types.Package) *Index {
80389-	return new(indexBuilder).build(fset, pkg)
80390-}
80391-
80392-// A Location records the extent of an identifier in byte-offset form.
80393-//
80394-// Conversion to protocol (UTF-16) form is done by the caller after a
80395-// search, not during index construction.
80396-type Location struct {
80397-	Filename   string
80398-	Start, End int // byte offsets
80399-}
80400-
80401-// A Key represents the method set of a given type in a form suitable
80402-// to pass to the (*Index).Search method of many different Indexes.
80403-type Key struct {
80404-	mset gobMethodSet // note: lacks position information
80405-}
80406-
80407-// KeyOf returns the search key for the method sets of a given type.
80408-// It returns false if the type has no methods.
80409-func KeyOf(t types.Type) (Key, bool) {
80410-	mset := methodSetInfo(t, nil)
80411-	if mset.Mask == 0 {
80412-		return Key{}, false // no methods
80413-	}
80414-	return Key{mset}, true
80415-}
80416-
80417-// A Result reports a matching type or method in a method-set search.
80418-type Result struct {
80419-	Location Location // location of the type or method
80420-
80421-	// methods only:
80422-	PkgPath    string          // path of declaring package (may differ due to embedding)
80423-	ObjectPath objectpath.Path // path of method within declaring package
80424-}
80425-
80426-// Search reports each type that implements (or is implemented by) the
80427-// type that produced the search key. If methodID is nonempty, only
80428-// that method of each type is reported.
80429-//
80430-// The result does not include the error.Error method.
80431-// TODO(adonovan): give this special case a more systematic treatment.
80432-func (index *Index) Search(key Key, methodID string) []Result {
80433-	var results []Result
80434-	for _, candidate := range index.pkg.MethodSets {
80435-		// Traditionally this feature doesn't report
80436-		// interface/interface elements of the relation.
80437-		// I think that's a mistake.
80438-		// TODO(adonovan): UX: change it, here and in the local implementation.
80439-		if candidate.IsInterface && key.mset.IsInterface {
80440-			continue
80441-		}
80442-		if !satisfies(candidate, key.mset) && !satisfies(key.mset, candidate) {
80443-			continue
80444-		}
80445-
80446-		if candidate.Tricky {
80447-			// If any interface method is tricky then extra
80448-			// checking may be needed to eliminate a false positive.
80449-			// TODO(adonovan): implement it.
80450-		}
80451-
80452-		if methodID == "" {
80453-			results = append(results, Result{Location: index.location(candidate.Posn)})
80454-		} else {
80455-			for _, m := range candidate.Methods {
80456-				// Here we exploit knowledge of the shape of the fingerprint string.
80457-				if strings.HasPrefix(m.Fingerprint, methodID) &&
80458-					m.Fingerprint[len(methodID)] == '(' {
80459-
80460-					// Don't report error.Error among the results:
80461-					// it has no true source location, no package,
80462-					// and is excluded from the xrefs index.
80463-					if m.PkgPath == 0 || m.ObjectPath == 0 {
80464-						if methodID != "Error" {
80465-							panic("missing info for" + methodID)
80466-						}
80467-						continue
80468-					}
80469-
80470-					results = append(results, Result{
80471-						Location:   index.location(m.Posn),
80472-						PkgPath:    index.pkg.Strings[m.PkgPath],
80473-						ObjectPath: objectpath.Path(index.pkg.Strings[m.ObjectPath]),
80474-					})
80475-					break
80476-				}
80477-			}
80478-		}
80479-	}
80480-	return results
80481-}
80482-
80483-// satisfies does a fast check for whether x satisfies y.
80484-func satisfies(x, y gobMethodSet) bool {
80485-	return y.IsInterface && x.Mask&y.Mask == y.Mask && subset(y, x)
80486-}
80487-
80488-// subset reports whether method set x is a subset of y.
80489-func subset(x, y gobMethodSet) bool {
80490-outer:
80491-	for _, mx := range x.Methods {
80492-		for _, my := range y.Methods {
80493-			if mx.Sum == my.Sum && mx.Fingerprint == my.Fingerprint {
80494-				continue outer // found; try next x method
80495-			}
80496-		}
80497-		return false // method of x not found in y
80498-	}
80499-	return true // all methods of x found in y
80500-}
80501-
80502-func (index *Index) location(posn gobPosition) Location {
80503-	return Location{
80504-		Filename: index.pkg.Strings[posn.File],
80505-		Start:    posn.Offset,
80506-		End:      posn.Offset + posn.Len,
80507-	}
80508-}
80509-
80510-// An indexBuilder builds an index for a single package.
80511-type indexBuilder struct {
80512-	gobPackage
80513-	stringIndex map[string]int
80514-}
80515-
80516-// build adds to the index all package-level named types of the specified package.
80517-func (b *indexBuilder) build(fset *token.FileSet, pkg *types.Package) *Index {
80518-	_ = b.string("") // 0 => ""
80519-
80520-	objectPos := func(obj types.Object) gobPosition {
80521-		posn := safetoken.StartPosition(fset, obj.Pos())
80522-		return gobPosition{b.string(posn.Filename), posn.Offset, len(obj.Name())}
80523-	}
80524-
80525-	objectpathFor := typesinternal.NewObjectpathFunc()
80526-
80527-	// setindexInfo sets the (Posn, PkgPath, ObjectPath) fields for each method declaration.
80528-	setIndexInfo := func(m *gobMethod, method *types.Func) {
80529-		// error.Error has empty Position, PkgPath, and ObjectPath.
80530-		if method.Pkg() == nil {
80531-			return
80532-		}
80533-
80534-		m.Posn = objectPos(method)
80535-		m.PkgPath = b.string(method.Pkg().Path())
80536-
80537-		// Instantiations of generic methods don't have an
80538-		// object path, so we use the generic.
80539-		if p, err := objectpathFor(typeparams.OriginMethod(method)); err != nil {
80540-			panic(err) // can't happen for a method of a package-level type
80541-		} else {
80542-			m.ObjectPath = b.string(string(p))
80543-		}
80544-	}
80545-
80546-	// We ignore aliases, though in principle they could define a
80547-	// struct{...}  or interface{...} type, or an instantiation of
80548-	// a generic, that has a novel method set.
80549-	scope := pkg.Scope()
80550-	for _, name := range scope.Names() {
80551-		if tname, ok := scope.Lookup(name).(*types.TypeName); ok && !tname.IsAlias() {
80552-			if mset := methodSetInfo(tname.Type(), setIndexInfo); mset.Mask != 0 {
80553-				mset.Posn = objectPos(tname)
80554-				// Only record types with non-trivial method sets.
80555-				b.MethodSets = append(b.MethodSets, mset)
80556-			}
80557-		}
80558-	}
80559-
80560-	return &Index{pkg: b.gobPackage}
80561-}
80562-
80563-// string returns a small integer that encodes the string.
80564-func (b *indexBuilder) string(s string) int {
80565-	i, ok := b.stringIndex[s]
80566-	if !ok {
80567-		i = len(b.Strings)
80568-		if b.stringIndex == nil {
80569-			b.stringIndex = make(map[string]int)
80570-		}
80571-		b.stringIndex[s] = i
80572-		b.Strings = append(b.Strings, s)
80573-	}
80574-	return i
80575-}
80576-
80577-// methodSetInfo returns the method-set fingerprint of a type.
80578-// It calls the optional setIndexInfo function for each gobMethod.
80579-// This is used during index construction, but not search (KeyOf),
80580-// to store extra information.
80581-func methodSetInfo(t types.Type, setIndexInfo func(*gobMethod, *types.Func)) gobMethodSet {
80582-	// For non-interface types, use *T
80583-	// (if T is not already a pointer)
80584-	// since it may have more methods.
80585-	mset := types.NewMethodSet(EnsurePointer(t))
80586-
80587-	// Convert the method set into a compact summary.
80588-	var mask uint64
80589-	tricky := false
80590-	methods := make([]gobMethod, mset.Len())
80591-	for i := 0; i < mset.Len(); i++ {
80592-		m := mset.At(i).Obj().(*types.Func)
80593-		fp, isTricky := fingerprint(m)
80594-		if isTricky {
80595-			tricky = true
80596-		}
80597-		sum := crc32.ChecksumIEEE([]byte(fp))
80598-		methods[i] = gobMethod{Fingerprint: fp, Sum: sum}
80599-		if setIndexInfo != nil {
80600-			setIndexInfo(&methods[i], m) // set Position, PkgPath, ObjectPath
80601-		}
80602-		mask |= 1 << uint64(((sum>>24)^(sum>>16)^(sum>>8)^sum)&0x3f)
80603-	}
80604-	return gobMethodSet{
80605-		IsInterface: types.IsInterface(t),
80606-		Tricky:      tricky,
80607-		Mask:        mask,
80608-		Methods:     methods,
80609-	}
80610-}
80611-
80612-// EnsurePointer wraps T in a types.Pointer if T is a named, non-interface type.
80613-// This is useful to make sure you consider a named type's full method set.
80614-func EnsurePointer(T types.Type) types.Type {
80615-	if _, ok := T.(*types.Named); ok && !types.IsInterface(T) {
80616-		return types.NewPointer(T)
80617-	}
80618-
80619-	return T
80620-}
80621-
80622-// fingerprint returns an encoding of a method signature such that two
80623-// methods with equal encodings have identical types, except for a few
80624-// tricky types whose encodings may spuriously match and whose exact
80625-// identity computation requires the type checker to eliminate false
80626-// positives (which are rare). The boolean result indicates whether
80627-// the result was one of these tricky types.
80628-//
80629-// In the standard library, 99.8% of package-level types have a
80630-// non-tricky method-set.  The most common exceptions are due to type
80631-// parameters.
80632-//
80633-// The fingerprint string starts with method.Id() + "(".
80634-func fingerprint(method *types.Func) (string, bool) {
80635-	var buf strings.Builder
80636-	tricky := false
80637-	var fprint func(t types.Type)
80638-	fprint = func(t types.Type) {
80639-		switch t := t.(type) {
80640-		case *types.Named:
80641-			tname := t.Obj()
80642-			if tname.Pkg() != nil {
80643-				buf.WriteString(strconv.Quote(tname.Pkg().Path()))
80644-				buf.WriteByte('.')
80645-			} else if tname.Name() != "error" {
80646-				panic(tname) // error is the only named type with no package
80647-			}
80648-			buf.WriteString(tname.Name())
80649-
80650-		case *types.Array:
80651-			fmt.Fprintf(&buf, "[%d]", t.Len())
80652-			fprint(t.Elem())
80653-
80654-		case *types.Slice:
80655-			buf.WriteString("[]")
80656-			fprint(t.Elem())
80657-
80658-		case *types.Pointer:
80659-			buf.WriteByte('*')
80660-			fprint(t.Elem())
80661-
80662-		case *types.Map:
80663-			buf.WriteString("map[")
80664-			fprint(t.Key())
80665-			buf.WriteByte(']')
80666-			fprint(t.Elem())
80667-
80668-		case *types.Chan:
80669-			switch t.Dir() {
80670-			case types.SendRecv:
80671-				buf.WriteString("chan ")
80672-			case types.SendOnly:
80673-				buf.WriteString("<-chan ")
80674-			case types.RecvOnly:
80675-				buf.WriteString("chan<- ")
80676-			}
80677-			fprint(t.Elem())
80678-
80679-		case *types.Tuple:
80680-			buf.WriteByte('(')
80681-			for i := 0; i < t.Len(); i++ {
80682-				if i > 0 {
80683-					buf.WriteByte(',')
80684-				}
80685-				fprint(t.At(i).Type())
80686-			}
80687-			buf.WriteByte(')')
80688-
80689-		case *types.Basic:
80690-			// Use canonical names for uint8 and int32 aliases.
80691-			switch t.Kind() {
80692-			case types.Byte:
80693-				buf.WriteString("byte")
80694-			case types.Rune:
80695-				buf.WriteString("rune")
80696-			default:
80697-				buf.WriteString(t.String())
80698-			}
80699-
80700-		case *types.Signature:
80701-			buf.WriteString("func")
80702-			fprint(t.Params())
80703-			if t.Variadic() {
80704-				buf.WriteString("...") // not quite Go syntax
80705-			}
80706-			fprint(t.Results())
80707-
80708-		case *types.Struct:
80709-			// Non-empty unnamed struct types in method
80710-			// signatures are vanishingly rare.
80711-			buf.WriteString("struct{")
80712-			for i := 0; i < t.NumFields(); i++ {
80713-				if i > 0 {
80714-					buf.WriteByte(';')
80715-				}
80716-				f := t.Field(i)
80717-				// This isn't quite right for embedded type aliases.
80718-				// (See types.TypeString(StructType) and #44410 for context.)
80719-				// But this is vanishingly rare.
80720-				if !f.Embedded() {
80721-					buf.WriteString(f.Id())
80722-					buf.WriteByte(' ')
80723-				}
80724-				fprint(f.Type())
80725-				if tag := t.Tag(i); tag != "" {
80726-					buf.WriteByte(' ')
80727-					buf.WriteString(strconv.Quote(tag))
80728-				}
80729-			}
80730-			buf.WriteString("}")
80731-
80732-		case *types.Interface:
80733-			if t.NumMethods() == 0 {
80734-				buf.WriteString("any") // common case
80735-			} else {
80736-				// Interface assignability is particularly
80737-				// tricky due to the possibility of recursion.
80738-				tricky = true
80739-				// We could still give more disambiguating precision
80740-				// than "..." if we wanted to.
80741-				buf.WriteString("interface{...}")
80742-			}
80743-
80744-		case *typeparams.TypeParam:
80745-			tricky = true
80746-			// TODO(adonovan): refine this by adding a numeric suffix
80747-			// indicating the index among the receiver type's parameters.
80748-			buf.WriteByte('?')
80749-
80750-		default: // incl. *types.Union
80751-			panic(t)
80752-		}
80753-	}
80754-
80755-	buf.WriteString(method.Id()) // e.g. "pkg.Type"
80756-	sig := method.Type().(*types.Signature)
80757-	fprint(sig.Params())
80758-	fprint(sig.Results())
80759-	return buf.String(), tricky
80760-}
80761-
80762-// -- serial format of index --
80763-
80764-// The cost of gob encoding and decoding for most packages in x/tools
80765-// is under 50us, with occasional peaks of around 1-3ms.
80766-// The encoded indexes are around 1KB-50KB.
80767-
80768-// A gobPackage records the method set of each package-level type for a single package.
80769-type gobPackage struct {
80770-	Strings    []string // index of strings used by gobPosition.File, gobMethod.{Pkg,Object}Path
80771-	MethodSets []gobMethodSet
80772-}
80773-
80774-// A gobMethodSet records the method set of a single type.
80775-type gobMethodSet struct {
80776-	Posn        gobPosition
80777-	IsInterface bool
80778-	Tricky      bool   // at least one method is tricky; assignability requires go/types
80779-	Mask        uint64 // mask with 1 bit from each of methods[*].sum
80780-	Methods     []gobMethod
80781-}
80782-
80783-// A gobMethod records the name, type, and position of a single method.
80784-type gobMethod struct {
80785-	Fingerprint string // string of form "methodID(params...)(results)"
80786-	Sum         uint32 // checksum of fingerprint
80787-
80788-	// index records only (zero in KeyOf; also for index of error.Error).
80789-	Posn       gobPosition // location of method declaration
80790-	PkgPath    int         // path of package containing method declaration
80791-	ObjectPath int         // object path of method relative to PkgPath
80792-}
80793-
80794-// A gobPosition records the file, offset, and length of an identifier.
80795-type gobPosition struct {
80796-	File        int // index into gobPackage.Strings
80797-	Offset, Len int // in bytes
80798-}
80799diff -urN a/gopls/internal/lsp/source/options.go b/gopls/internal/lsp/source/options.go
80800--- a/gopls/internal/lsp/source/options.go	2000-01-01 00:00:00.000000000 -0000
80801+++ b/gopls/internal/lsp/source/options.go	1970-01-01 00:00:00.000000000 +0000
80802@@ -1,1631 +0,0 @@
80803-// Copyright 2019 The Go Authors. All rights reserved.
80804-// Use of this source code is governed by a BSD-style
80805-// license that can be found in the LICENSE file.
80806-
80807-package source
80808-
80809-import (
80810-	"context"
80811-	"fmt"
80812-	"io"
80813-	"path/filepath"
80814-	"regexp"
80815-	"runtime"
80816-	"strings"
80817-	"sync"
80818-	"time"
80819-
80820-	"golang.org/x/tools/go/analysis"
80821-	"golang.org/x/tools/go/analysis/passes/asmdecl"
80822-	"golang.org/x/tools/go/analysis/passes/assign"
80823-	"golang.org/x/tools/go/analysis/passes/atomic"
80824-	"golang.org/x/tools/go/analysis/passes/atomicalign"
80825-	"golang.org/x/tools/go/analysis/passes/bools"
80826-	"golang.org/x/tools/go/analysis/passes/buildtag"
80827-	"golang.org/x/tools/go/analysis/passes/cgocall"
80828-	"golang.org/x/tools/go/analysis/passes/composite"
80829-	"golang.org/x/tools/go/analysis/passes/copylock"
80830-	"golang.org/x/tools/go/analysis/passes/deepequalerrors"
80831-	"golang.org/x/tools/go/analysis/passes/directive"
80832-	"golang.org/x/tools/go/analysis/passes/errorsas"
80833-	"golang.org/x/tools/go/analysis/passes/fieldalignment"
80834-	"golang.org/x/tools/go/analysis/passes/httpresponse"
80835-	"golang.org/x/tools/go/analysis/passes/ifaceassert"
80836-	"golang.org/x/tools/go/analysis/passes/loopclosure"
80837-	"golang.org/x/tools/go/analysis/passes/lostcancel"
80838-	"golang.org/x/tools/go/analysis/passes/nilfunc"
80839-	"golang.org/x/tools/go/analysis/passes/nilness"
80840-	"golang.org/x/tools/go/analysis/passes/printf"
80841-	"golang.org/x/tools/go/analysis/passes/shadow"
80842-	"golang.org/x/tools/go/analysis/passes/shift"
80843-	"golang.org/x/tools/go/analysis/passes/sortslice"
80844-	"golang.org/x/tools/go/analysis/passes/stdmethods"
80845-	"golang.org/x/tools/go/analysis/passes/stringintconv"
80846-	"golang.org/x/tools/go/analysis/passes/structtag"
80847-	"golang.org/x/tools/go/analysis/passes/testinggoroutine"
80848-	"golang.org/x/tools/go/analysis/passes/tests"
80849-	"golang.org/x/tools/go/analysis/passes/timeformat"
80850-	"golang.org/x/tools/go/analysis/passes/unmarshal"
80851-	"golang.org/x/tools/go/analysis/passes/unreachable"
80852-	"golang.org/x/tools/go/analysis/passes/unsafeptr"
80853-	"golang.org/x/tools/go/analysis/passes/unusedresult"
80854-	"golang.org/x/tools/go/analysis/passes/unusedwrite"
80855-	"golang.org/x/tools/gopls/internal/lsp/analysis/embeddirective"
80856-	"golang.org/x/tools/gopls/internal/lsp/analysis/fillreturns"
80857-	"golang.org/x/tools/gopls/internal/lsp/analysis/fillstruct"
80858-	"golang.org/x/tools/gopls/internal/lsp/analysis/infertypeargs"
80859-	"golang.org/x/tools/gopls/internal/lsp/analysis/nonewvars"
80860-	"golang.org/x/tools/gopls/internal/lsp/analysis/noresultvalues"
80861-	"golang.org/x/tools/gopls/internal/lsp/analysis/simplifycompositelit"
80862-	"golang.org/x/tools/gopls/internal/lsp/analysis/simplifyrange"
80863-	"golang.org/x/tools/gopls/internal/lsp/analysis/simplifyslice"
80864-	"golang.org/x/tools/gopls/internal/lsp/analysis/stubmethods"
80865-	"golang.org/x/tools/gopls/internal/lsp/analysis/undeclaredname"
80866-	"golang.org/x/tools/gopls/internal/lsp/analysis/unusedparams"
80867-	"golang.org/x/tools/gopls/internal/lsp/analysis/unusedvariable"
80868-	"golang.org/x/tools/gopls/internal/lsp/analysis/useany"
80869-	"golang.org/x/tools/gopls/internal/lsp/command"
80870-	"golang.org/x/tools/gopls/internal/lsp/protocol"
80871-	"golang.org/x/tools/internal/diff"
80872-	"golang.org/x/tools/internal/diff/myers"
80873-)
80874-
80875-var (
80876-	optionsOnce    sync.Once
80877-	defaultOptions *Options
80878-)
80879-
80880-// DefaultOptions is the options that are used for Gopls execution independent
80881-// of any externally provided configuration (LSP initialization, command
80882-// invocation, etc.).
80883-func DefaultOptions() *Options {
80884-	optionsOnce.Do(func() {
80885-		var commands []string
80886-		for _, c := range command.Commands {
80887-			commands = append(commands, c.ID())
80888-		}
80889-		defaultOptions = &Options{
80890-			ClientOptions: ClientOptions{
80891-				InsertTextFormat:                           protocol.PlainTextTextFormat,
80892-				PreferredContentFormat:                     protocol.Markdown,
80893-				ConfigurationSupported:                     true,
80894-				DynamicConfigurationSupported:              true,
80895-				DynamicRegistrationSemanticTokensSupported: true,
80896-				DynamicWatchedFilesSupported:               true,
80897-				LineFoldingOnly:                            false,
80898-				HierarchicalDocumentSymbolSupport:          true,
80899-			},
80900-			ServerOptions: ServerOptions{
80901-				SupportedCodeActions: map[FileKind]map[protocol.CodeActionKind]bool{
80902-					Go: {
80903-						protocol.SourceFixAll:          true,
80904-						protocol.SourceOrganizeImports: true,
80905-						protocol.QuickFix:              true,
80906-						protocol.RefactorRewrite:       true,
80907-						protocol.RefactorExtract:       true,
80908-					},
80909-					Mod: {
80910-						protocol.SourceOrganizeImports: true,
80911-						protocol.QuickFix:              true,
80912-					},
80913-					Work: {},
80914-					Sum:  {},
80915-					Tmpl: {},
80916-				},
80917-				SupportedCommands: commands,
80918-			},
80919-			UserOptions: UserOptions{
80920-				BuildOptions: BuildOptions{
80921-					ExpandWorkspaceToModule: true,
80922-					MemoryMode:              ModeNormal,
80923-					DirectoryFilters:        []string{"-**/node_modules"},
80924-					TemplateExtensions:      []string{},
80925-					StandaloneTags:          []string{"ignore"},
80926-				},
80927-				UIOptions: UIOptions{
80928-					DiagnosticOptions: DiagnosticOptions{
80929-						DiagnosticsDelay: 250 * time.Millisecond,
80930-						Annotations: map[Annotation]bool{
80931-							Bounds: true,
80932-							Escape: true,
80933-							Inline: true,
80934-							Nil:    true,
80935-						},
80936-						Vulncheck: ModeVulncheckOff,
80937-					},
80938-					InlayHintOptions: InlayHintOptions{},
80939-					DocumentationOptions: DocumentationOptions{
80940-						HoverKind:    FullDocumentation,
80941-						LinkTarget:   "pkg.go.dev",
80942-						LinksInHover: true,
80943-					},
80944-					NavigationOptions: NavigationOptions{
80945-						ImportShortcut: BothShortcuts,
80946-						SymbolMatcher:  SymbolFastFuzzy,
80947-						SymbolStyle:    DynamicSymbols,
80948-					},
80949-					CompletionOptions: CompletionOptions{
80950-						Matcher:                        Fuzzy,
80951-						CompletionBudget:               100 * time.Millisecond,
80952-						ExperimentalPostfixCompletions: true,
80953-					},
80954-					Codelenses: map[string]bool{
80955-						string(command.Generate):          true,
80956-						string(command.RegenerateCgo):     true,
80957-						string(command.Tidy):              true,
80958-						string(command.GCDetails):         false,
80959-						string(command.UpgradeDependency): true,
80960-						string(command.Vendor):            true,
80961-						// TODO(hyangah): enable command.RunGovulncheck.
80962-					},
80963-				},
80964-			},
80965-			InternalOptions: InternalOptions{
80966-				LiteralCompletions:      true,
80967-				TempModfile:             true,
80968-				CompleteUnimported:      true,
80969-				CompletionDocumentation: true,
80970-				DeepCompletion:          true,
80971-				ChattyDiagnostics:       true,
80972-				NewDiff:                 "both",
80973-			},
80974-			Hooks: Hooks{
80975-				// TODO(adonovan): switch to new diff.Strings implementation.
80976-				ComputeEdits:         myers.ComputeEdits,
80977-				URLRegexp:            urlRegexp(),
80978-				DefaultAnalyzers:     defaultAnalyzers(),
80979-				TypeErrorAnalyzers:   typeErrorAnalyzers(),
80980-				ConvenienceAnalyzers: convenienceAnalyzers(),
80981-				StaticcheckAnalyzers: map[string]*Analyzer{},
80982-				GoDiff:               true,
80983-			},
80984-		}
80985-	})
80986-	return defaultOptions
80987-}
80988-
80989-// Options holds various configuration that affects Gopls execution, organized
80990-// by the nature or origin of the settings.
80991-type Options struct {
80992-	ClientOptions
80993-	ServerOptions
80994-	UserOptions
80995-	InternalOptions
80996-	Hooks
80997-}
80998-
80999-// ClientOptions holds LSP-specific configuration that is provided by the
81000-// client.
81001-type ClientOptions struct {
81002-	InsertTextFormat                           protocol.InsertTextFormat
81003-	ConfigurationSupported                     bool
81004-	DynamicConfigurationSupported              bool
81005-	DynamicRegistrationSemanticTokensSupported bool
81006-	DynamicWatchedFilesSupported               bool
81007-	PreferredContentFormat                     protocol.MarkupKind
81008-	LineFoldingOnly                            bool
81009-	HierarchicalDocumentSymbolSupport          bool
81010-	SemanticTypes                              []string
81011-	SemanticMods                               []string
81012-	RelatedInformationSupported                bool
81013-	CompletionTags                             bool
81014-	CompletionDeprecated                       bool
81015-	SupportedResourceOperations                []protocol.ResourceOperationKind
81016-}
81017-
81018-// ServerOptions holds LSP-specific configuration that is provided by the
81019-// server.
81020-type ServerOptions struct {
81021-	SupportedCodeActions map[FileKind]map[protocol.CodeActionKind]bool
81022-	SupportedCommands    []string
81023-}
81024-
81025-type BuildOptions struct {
81026-	// BuildFlags is the set of flags passed on to the build system when invoked.
81027-	// It is applied to queries like `go list`, which is used when discovering files.
81028-	// The most common use is to set `-tags`.
81029-	BuildFlags []string
81030-
81031-	// Env adds environment variables to external commands run by `gopls`, most notably `go list`.
81032-	Env map[string]string
81033-
81034-	// DirectoryFilters can be used to exclude unwanted directories from the
81035-	// workspace. By default, all directories are included. Filters are an
81036-	// operator, `+` to include and `-` to exclude, followed by a path prefix
81037-	// relative to the workspace folder. They are evaluated in order, and
81038-	// the last filter that applies to a path controls whether it is included.
81039-	// The path prefix can be empty, so an initial `-` excludes everything.
81040-	//
81041-	// DirectoryFilters also supports the `**` operator to match 0 or more directories.
81042-	//
81043-	// Examples:
81044-	//
81045-	// Exclude node_modules at current depth: `-node_modules`
81046-	//
81047-	// Exclude node_modules at any depth: `-**/node_modules`
81048-	//
81049-	// Include only project_a: `-` (exclude everything), `+project_a`
81050-	//
81051-	// Include only project_a, but not node_modules inside it: `-`, `+project_a`, `-project_a/node_modules`
81052-	DirectoryFilters []string
81053-
81054-	// TemplateExtensions gives the extensions of file names that are treateed
81055-	// as template files. (The extension
81056-	// is the part of the file name after the final dot.)
81057-	TemplateExtensions []string
81058-
81059-	// MemoryMode controls the tradeoff `gopls` makes between memory usage and
81060-	// correctness.
81061-	//
81062-	// Values other than `Normal` are untested and may break in surprising ways.
81063-	MemoryMode MemoryMode `status:"experimental"`
81064-
81065-	// ExpandWorkspaceToModule instructs `gopls` to adjust the scope of the
81066-	// workspace to find the best available module root. `gopls` first looks for
81067-	// a go.mod file in any parent directory of the workspace folder, expanding
81068-	// the scope to that directory if it exists. If no viable parent directory is
81069-	// found, gopls will check if there is exactly one child directory containing
81070-	// a go.mod file, narrowing the scope to that directory if it exists.
81071-	ExpandWorkspaceToModule bool `status:"experimental"`
81072-
81073-	// AllowModfileModifications disables -mod=readonly, allowing imports from
81074-	// out-of-scope modules. This option will eventually be removed.
81075-	AllowModfileModifications bool `status:"experimental"`
81076-
81077-	// AllowImplicitNetworkAccess disables GOPROXY=off, allowing implicit module
81078-	// downloads rather than requiring user action. This option will eventually
81079-	// be removed.
81080-	AllowImplicitNetworkAccess bool `status:"experimental"`
81081-
81082-	// StandaloneTags specifies a set of build constraints that identify
81083-	// individual Go source files that make up the entire main package of an
81084-	// executable.
81085-	//
81086-	// A common example of standalone main files is the convention of using the
81087-	// directive `//go:build ignore` to denote files that are not intended to be
81088-	// included in any package, for example because they are invoked directly by
81089-	// the developer using `go run`.
81090-	//
81091-	// Gopls considers a file to be a standalone main file if and only if it has
81092-	// package name "main" and has a build directive of the exact form
81093-	// "//go:build tag" or "// +build tag", where tag is among the list of tags
81094-	// configured by this setting. Notably, if the build constraint is more
81095-	// complicated than a simple tag (such as the composite constraint
81096-	// `//go:build tag && go1.18`), the file is not considered to be a standalone
81097-	// main file.
81098-	//
81099-	// This setting is only supported when gopls is built with Go 1.16 or later.
81100-	StandaloneTags []string
81101-}
81102-
81103-type UIOptions struct {
81104-	DocumentationOptions
81105-	CompletionOptions
81106-	NavigationOptions
81107-	DiagnosticOptions
81108-	InlayHintOptions
81109-
81110-	// Codelenses overrides the enabled/disabled state of code lenses. See the
81111-	// "Code Lenses" section of the
81112-	// [Settings page](https://github.com/golang/tools/blob/master/gopls/doc/settings.md#code-lenses)
81113-	// for the list of supported lenses.
81114-	//
81115-	// Example Usage:
81116-	//
81117-	// ```json5
81118-	// "gopls": {
81119-	// ...
81120-	//   "codelenses": {
81121-	//     "generate": false,  // Don't show the `go generate` lens.
81122-	//     "gc_details": true  // Show a code lens toggling the display of gc's choices.
81123-	//   }
81124-	// ...
81125-	// }
81126-	// ```
81127-	Codelenses map[string]bool
81128-
81129-	// SemanticTokens controls whether the LSP server will send
81130-	// semantic tokens to the client.
81131-	SemanticTokens bool `status:"experimental"`
81132-
81133-	// NoSemanticString turns off the sending of the semantic token 'string'
81134-	NoSemanticString bool `status:"experimental"`
81135-
81136-	// NoSemanticNumber  turns off the sending of the semantic token 'number'
81137-	NoSemanticNumber bool `status:"experimental"`
81138-}
81139-
81140-type CompletionOptions struct {
81141-	// Placeholders enables placeholders for function parameters or struct
81142-	// fields in completion responses.
81143-	UsePlaceholders bool
81144-
81145-	// CompletionBudget is the soft latency goal for completion requests. Most
81146-	// requests finish in a couple milliseconds, but in some cases deep
81147-	// completions can take much longer. As we use up our budget we
81148-	// dynamically reduce the search scope to ensure we return timely
81149-	// results. Zero means unlimited.
81150-	CompletionBudget time.Duration `status:"debug"`
81151-
81152-	// Matcher sets the algorithm that is used when calculating completion
81153-	// candidates.
81154-	Matcher Matcher `status:"advanced"`
81155-
81156-	// ExperimentalPostfixCompletions enables artificial method snippets
81157-	// such as "someSlice.sort!".
81158-	ExperimentalPostfixCompletions bool `status:"experimental"`
81159-}
81160-
81161-type DocumentationOptions struct {
81162-	// HoverKind controls the information that appears in the hover text.
81163-	// SingleLine and Structured are intended for use only by authors of editor plugins.
81164-	HoverKind HoverKind
81165-
81166-	// LinkTarget controls where documentation links go.
81167-	// It might be one of:
81168-	//
81169-	// * `"godoc.org"`
81170-	// * `"pkg.go.dev"`
81171-	//
81172-	// If company chooses to use its own `godoc.org`, its address can be used as well.
81173-	//
81174-	// Modules matching the GOPRIVATE environment variable will not have
81175-	// documentation links in hover.
81176-	LinkTarget string
81177-
81178-	// LinksInHover toggles the presence of links to documentation in hover.
81179-	LinksInHover bool
81180-}
81181-
81182-type FormattingOptions struct {
81183-	// Local is the equivalent of the `goimports -local` flag, which puts
81184-	// imports beginning with this string after third-party packages. It should
81185-	// be the prefix of the import path whose imports should be grouped
81186-	// separately.
81187-	Local string
81188-
81189-	// Gofumpt indicates if we should run gofumpt formatting.
81190-	Gofumpt bool
81191-}
81192-
81193-type DiagnosticOptions struct {
81194-	// Analyses specify analyses that the user would like to enable or disable.
81195-	// A map of the names of analysis passes that should be enabled/disabled.
81196-	// A full list of analyzers that gopls uses can be found in
81197-	// [analyzers.md](https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md).
81198-	//
81199-	// Example Usage:
81200-	//
81201-	// ```json5
81202-	// ...
81203-	// "analyses": {
81204-	//   "unreachable": false, // Disable the unreachable analyzer.
81205-	//   "unusedparams": true  // Enable the unusedparams analyzer.
81206-	// }
81207-	// ...
81208-	// ```
81209-	Analyses map[string]bool
81210-
81211-	// Staticcheck enables additional analyses from staticcheck.io.
81212-	// These analyses are documented on
81213-	// [Staticcheck's website](https://staticcheck.io/docs/checks/).
81214-	Staticcheck bool `status:"experimental"`
81215-
81216-	// Annotations specifies the various kinds of optimization diagnostics
81217-	// that should be reported by the gc_details command.
81218-	Annotations map[Annotation]bool `status:"experimental"`
81219-
81220-	// Vulncheck enables vulnerability scanning.
81221-	Vulncheck VulncheckMode `status:"experimental"`
81222-
81223-	// DiagnosticsDelay controls the amount of time that gopls waits
81224-	// after the most recent file modification before computing deep diagnostics.
81225-	// Simple diagnostics (parsing and type-checking) are always run immediately
81226-	// on recently modified packages.
81227-	//
81228-	// This option must be set to a valid duration string, for example `"250ms"`.
81229-	DiagnosticsDelay time.Duration `status:"advanced"`
81230-}
81231-
81232-type InlayHintOptions struct {
81233-	// Hints specify inlay hints that users want to see. A full list of hints
81234-	// that gopls uses can be found in
81235-	// [inlayHints.md](https://github.com/golang/tools/blob/master/gopls/doc/inlayHints.md).
81236-	Hints map[string]bool `status:"experimental"`
81237-}
81238-
81239-type NavigationOptions struct {
81240-	// ImportShortcut specifies whether import statements should link to
81241-	// documentation or go to definitions.
81242-	ImportShortcut ImportShortcut
81243-
81244-	// SymbolMatcher sets the algorithm that is used when finding workspace symbols.
81245-	SymbolMatcher SymbolMatcher `status:"advanced"`
81246-
81247-	// SymbolStyle controls how symbols are qualified in symbol responses.
81248-	//
81249-	// Example Usage:
81250-	//
81251-	// ```json5
81252-	// "gopls": {
81253-	// ...
81254-	//   "symbolStyle": "Dynamic",
81255-	// ...
81256-	// }
81257-	// ```
81258-	SymbolStyle SymbolStyle `status:"advanced"`
81259-}
81260-
81261-// UserOptions holds custom Gopls configuration (not part of the LSP) that is
81262-// modified by the client.
81263-type UserOptions struct {
81264-	BuildOptions
81265-	UIOptions
81266-	FormattingOptions
81267-
81268-	// VerboseOutput enables additional debug logging.
81269-	VerboseOutput bool `status:"debug"`
81270-}
81271-
81272-// EnvSlice returns Env as a slice of k=v strings.
81273-func (u *UserOptions) EnvSlice() []string {
81274-	var result []string
81275-	for k, v := range u.Env {
81276-		result = append(result, fmt.Sprintf("%v=%v", k, v))
81277-	}
81278-	return result
81279-}
81280-
81281-// SetEnvSlice sets Env from a slice of k=v strings.
81282-func (u *UserOptions) SetEnvSlice(env []string) {
81283-	u.Env = map[string]string{}
81284-	for _, kv := range env {
81285-		split := strings.SplitN(kv, "=", 2)
81286-		if len(split) != 2 {
81287-			continue
81288-		}
81289-		u.Env[split[0]] = split[1]
81290-	}
81291-}
81292-
81293-// DiffFunction is the type for a function that produces a set of edits that
81294-// convert from the before content to the after content.
81295-type DiffFunction func(before, after string) []diff.Edit
81296-
81297-// Hooks contains configuration that is provided to the Gopls command by the
81298-// main package.
81299-type Hooks struct {
81300-	// LicensesText holds third party licenses for software used by gopls.
81301-	LicensesText string
81302-
81303-	// GoDiff is used in gopls/hooks to get Myers' diff
81304-	GoDiff bool
81305-
81306-	// Whether staticcheck is supported.
81307-	StaticcheckSupported bool
81308-
81309-	// ComputeEdits is used to compute edits between file versions.
81310-	ComputeEdits DiffFunction
81311-
81312-	// URLRegexp is used to find potential URLs in comments/strings.
81313-	//
81314-	// Not all matches are shown to the user: if the matched URL is not detected
81315-	// as valid, it will be skipped.
81316-	URLRegexp *regexp.Regexp
81317-
81318-	// GofumptFormat allows the gopls module to wire-in a call to
81319-	// gofumpt/format.Source. langVersion and modulePath are used for some
81320-	// Gofumpt formatting rules -- see the Gofumpt documentation for details.
81321-	GofumptFormat func(ctx context.Context, langVersion, modulePath string, src []byte) ([]byte, error)
81322-
81323-	DefaultAnalyzers     map[string]*Analyzer
81324-	TypeErrorAnalyzers   map[string]*Analyzer
81325-	ConvenienceAnalyzers map[string]*Analyzer
81326-	StaticcheckAnalyzers map[string]*Analyzer
81327-}
81328-
81329-// InternalOptions contains settings that are not intended for use by the
81330-// average user. These may be settings used by tests or outdated settings that
81331-// will soon be deprecated. Some of these settings may not even be configurable
81332-// by the user.
81333-type InternalOptions struct {
81334-	// LiteralCompletions controls whether literal candidates such as
81335-	// "&someStruct{}" are offered. Tests disable this flag to simplify
81336-	// their expected values.
81337-	LiteralCompletions bool
81338-
81339-	// VerboseWorkDoneProgress controls whether the LSP server should send
81340-	// progress reports for all work done outside the scope of an RPC.
81341-	// Used by the regression tests.
81342-	VerboseWorkDoneProgress bool
81343-
81344-	// The following options were previously available to users, but they
81345-	// really shouldn't be configured by anyone other than "power users".
81346-
81347-	// CompletionDocumentation enables documentation with completion results.
81348-	CompletionDocumentation bool
81349-
81350-	// CompleteUnimported enables completion for packages that you do not
81351-	// currently import.
81352-	CompleteUnimported bool
81353-
81354-	// DeepCompletion enables the ability to return completions from deep
81355-	// inside relevant entities, rather than just the locally accessible ones.
81356-	//
81357-	// Consider this example:
81358-	//
81359-	// ```go
81360-	// package main
81361-	//
81362-	// import "fmt"
81363-	//
81364-	// type wrapString struct {
81365-	//     str string
81366-	// }
81367-	//
81368-	// func main() {
81369-	//     x := wrapString{"hello world"}
81370-	//     fmt.Printf(<>)
81371-	// }
81372-	// ```
81373-	//
81374-	// At the location of the `<>` in this program, deep completion would suggest
81375-	// the result `x.str`.
81376-	DeepCompletion bool
81377-
81378-	// TempModfile controls the use of the -modfile flag in Go 1.14.
81379-	TempModfile bool
81380-
81381-	// ShowBugReports causes a message to be shown when the first bug is reported
81382-	// on the server.
81383-	// This option applies only during initialization.
81384-	ShowBugReports bool
81385-
81386-	// NewDiff controls the choice of the new diff implementation. It can be
81387-	// 'new', 'old', or 'both', which is the default. 'both' computes diffs with
81388-	// both algorithms, checks that the new algorithm has worked, and write some
81389-	// summary statistics to a file in os.TmpDir().
81390-	NewDiff string
81391-
81392-	// ChattyDiagnostics controls whether to report file diagnostics for each
81393-	// file change. If unset, gopls only reports diagnostics when they change, or
81394-	// when a file is opened or closed.
81395-	ChattyDiagnostics bool
81396-}
81397-
81398-type ImportShortcut string
81399-
81400-const (
81401-	BothShortcuts      ImportShortcut = "Both"
81402-	LinkShortcut       ImportShortcut = "Link"
81403-	DefinitionShortcut ImportShortcut = "Definition"
81404-)
81405-
81406-func (s ImportShortcut) ShowLinks() bool {
81407-	return s == BothShortcuts || s == LinkShortcut
81408-}
81409-
81410-func (s ImportShortcut) ShowDefinition() bool {
81411-	return s == BothShortcuts || s == DefinitionShortcut
81412-}
81413-
81414-type Matcher string
81415-
81416-const (
81417-	Fuzzy           Matcher = "Fuzzy"
81418-	CaseInsensitive Matcher = "CaseInsensitive"
81419-	CaseSensitive   Matcher = "CaseSensitive"
81420-)
81421-
81422-type SymbolMatcher string
81423-
81424-const (
81425-	SymbolFuzzy           SymbolMatcher = "Fuzzy"
81426-	SymbolFastFuzzy       SymbolMatcher = "FastFuzzy"
81427-	SymbolCaseInsensitive SymbolMatcher = "CaseInsensitive"
81428-	SymbolCaseSensitive   SymbolMatcher = "CaseSensitive"
81429-)
81430-
81431-type SymbolStyle string
81432-
81433-const (
81434-	// PackageQualifiedSymbols is package qualified symbols i.e.
81435-	// "pkg.Foo.Field".
81436-	PackageQualifiedSymbols SymbolStyle = "Package"
81437-	// FullyQualifiedSymbols is fully qualified symbols, i.e.
81438-	// "path/to/pkg.Foo.Field".
81439-	FullyQualifiedSymbols SymbolStyle = "Full"
81440-	// DynamicSymbols uses whichever qualifier results in the highest scoring
81441-	// match for the given symbol query. Here a "qualifier" is any "/" or "."
81442-	// delimited suffix of the fully qualified symbol. i.e. "to/pkg.Foo.Field" or
81443-	// just "Foo.Field".
81444-	DynamicSymbols SymbolStyle = "Dynamic"
81445-)
81446-
81447-type HoverKind string
81448-
81449-const (
81450-	SingleLine            HoverKind = "SingleLine"
81451-	NoDocumentation       HoverKind = "NoDocumentation"
81452-	SynopsisDocumentation HoverKind = "SynopsisDocumentation"
81453-	FullDocumentation     HoverKind = "FullDocumentation"
81454-
81455-	// Structured is an experimental setting that returns a structured hover format.
81456-	// This format separates the signature from the documentation, so that the client
81457-	// can do more manipulation of these fields.
81458-	//
81459-	// This should only be used by clients that support this behavior.
81460-	Structured HoverKind = "Structured"
81461-)
81462-
81463-type MemoryMode string
81464-
81465-const (
81466-	ModeNormal MemoryMode = "Normal"
81467-	// In DegradeClosed mode, `gopls` will collect less information about
81468-	// packages without open files. As a result, features like Find
81469-	// References and Rename will miss results in such packages.
81470-	ModeDegradeClosed MemoryMode = "DegradeClosed"
81471-)
81472-
81473-type VulncheckMode string
81474-
81475-const (
81476-	// Disable vulnerability analysis.
81477-	ModeVulncheckOff VulncheckMode = "Off"
81478-	// In Imports mode, `gopls` will report vulnerabilities that affect packages
81479-	// directly and indirectly used by the analyzed main module.
81480-	ModeVulncheckImports VulncheckMode = "Imports"
81481-
81482-	// TODO: VulncheckRequire, VulncheckCallgraph
81483-)
81484-
81485-type OptionResults []OptionResult
81486-
81487-type OptionResult struct {
81488-	Name  string
81489-	Value interface{}
81490-	Error error
81491-}
81492-
81493-func SetOptions(options *Options, opts interface{}) OptionResults {
81494-	var results OptionResults
81495-	switch opts := opts.(type) {
81496-	case nil:
81497-	case map[string]interface{}:
81498-		// If the user's settings contains "allExperiments", set that first,
81499-		// and then let them override individual settings independently.
81500-		var enableExperiments bool
81501-		for name, value := range opts {
81502-			if b, ok := value.(bool); name == "allExperiments" && ok && b {
81503-				enableExperiments = true
81504-				options.EnableAllExperiments()
81505-			}
81506-		}
81507-		seen := map[string]struct{}{}
81508-		for name, value := range opts {
81509-			results = append(results, options.set(name, value, seen))
81510-		}
81511-		// Finally, enable any experimental features that are specified in
81512-		// maps, which allows users to individually toggle them on or off.
81513-		if enableExperiments {
81514-			options.enableAllExperimentMaps()
81515-		}
81516-	default:
81517-		results = append(results, OptionResult{
81518-			Value: opts,
81519-			Error: fmt.Errorf("Invalid options type %T", opts),
81520-		})
81521-	}
81522-	return results
81523-}
81524-
81525-func (o *Options) ForClientCapabilities(caps protocol.ClientCapabilities) {
81526-	// Check if the client supports snippets in completion items.
81527-	if caps.Workspace.WorkspaceEdit != nil {
81528-		o.SupportedResourceOperations = caps.Workspace.WorkspaceEdit.ResourceOperations
81529-	}
81530-	if c := caps.TextDocument.Completion; c.CompletionItem.SnippetSupport {
81531-		o.InsertTextFormat = protocol.SnippetTextFormat
81532-	}
81533-	// Check if the client supports configuration messages.
81534-	o.ConfigurationSupported = caps.Workspace.Configuration
81535-	o.DynamicConfigurationSupported = caps.Workspace.DidChangeConfiguration.DynamicRegistration
81536-	o.DynamicRegistrationSemanticTokensSupported = caps.TextDocument.SemanticTokens.DynamicRegistration
81537-	o.DynamicWatchedFilesSupported = caps.Workspace.DidChangeWatchedFiles.DynamicRegistration
81538-
81539-	// Check which types of content format are supported by this client.
81540-	if hover := caps.TextDocument.Hover; hover != nil && len(hover.ContentFormat) > 0 {
81541-		o.PreferredContentFormat = hover.ContentFormat[0]
81542-	}
81543-	// Check if the client supports only line folding.
81544-
81545-	if fr := caps.TextDocument.FoldingRange; fr != nil {
81546-		o.LineFoldingOnly = fr.LineFoldingOnly
81547-	}
81548-	// Check if the client supports hierarchical document symbols.
81549-	o.HierarchicalDocumentSymbolSupport = caps.TextDocument.DocumentSymbol.HierarchicalDocumentSymbolSupport
81550-
81551-	// Client's semantic tokens
81552-	o.SemanticTypes = caps.TextDocument.SemanticTokens.TokenTypes
81553-	o.SemanticMods = caps.TextDocument.SemanticTokens.TokenModifiers
81554-	// we don't need Requests, as we support full functionality
81555-	// we don't need Formats, as there is only one, for now
81556-
81557-	// Check if the client supports diagnostic related information.
81558-	o.RelatedInformationSupported = caps.TextDocument.PublishDiagnostics.RelatedInformation
81559-	// Check if the client completion support includes tags (preferred) or deprecation
81560-	if caps.TextDocument.Completion.CompletionItem.TagSupport.ValueSet != nil {
81561-		o.CompletionTags = true
81562-	} else if caps.TextDocument.Completion.CompletionItem.DeprecatedSupport {
81563-		o.CompletionDeprecated = true
81564-	}
81565-}
81566-
81567-func (o *Options) Clone() *Options {
81568-	// TODO(rfindley): has this function gone stale? It appears that there are
81569-	// settings that are incorrectly cloned here (such as TemplateExtensions).
81570-	result := &Options{
81571-		ClientOptions:   o.ClientOptions,
81572-		InternalOptions: o.InternalOptions,
81573-		Hooks: Hooks{
81574-			GoDiff:               o.GoDiff,
81575-			StaticcheckSupported: o.StaticcheckSupported,
81576-			ComputeEdits:         o.ComputeEdits,
81577-			GofumptFormat:        o.GofumptFormat,
81578-			URLRegexp:            o.URLRegexp,
81579-		},
81580-		ServerOptions: o.ServerOptions,
81581-		UserOptions:   o.UserOptions,
81582-	}
81583-	// Fully clone any slice or map fields. Only Hooks, ExperimentalOptions,
81584-	// and UserOptions can be modified.
81585-	copyStringMap := func(src map[string]bool) map[string]bool {
81586-		dst := make(map[string]bool)
81587-		for k, v := range src {
81588-			dst[k] = v
81589-		}
81590-		return dst
81591-	}
81592-	result.Analyses = copyStringMap(o.Analyses)
81593-	result.Codelenses = copyStringMap(o.Codelenses)
81594-
81595-	copySlice := func(src []string) []string {
81596-		dst := make([]string, len(src))
81597-		copy(dst, src)
81598-		return dst
81599-	}
81600-	result.SetEnvSlice(o.EnvSlice())
81601-	result.BuildFlags = copySlice(o.BuildFlags)
81602-	result.DirectoryFilters = copySlice(o.DirectoryFilters)
81603-	result.StandaloneTags = copySlice(o.StandaloneTags)
81604-
81605-	copyAnalyzerMap := func(src map[string]*Analyzer) map[string]*Analyzer {
81606-		dst := make(map[string]*Analyzer)
81607-		for k, v := range src {
81608-			dst[k] = v
81609-		}
81610-		return dst
81611-	}
81612-	result.DefaultAnalyzers = copyAnalyzerMap(o.DefaultAnalyzers)
81613-	result.TypeErrorAnalyzers = copyAnalyzerMap(o.TypeErrorAnalyzers)
81614-	result.ConvenienceAnalyzers = copyAnalyzerMap(o.ConvenienceAnalyzers)
81615-	result.StaticcheckAnalyzers = copyAnalyzerMap(o.StaticcheckAnalyzers)
81616-	return result
81617-}
81618-
81619-func (o *Options) AddStaticcheckAnalyzer(a *analysis.Analyzer, enabled bool, severity protocol.DiagnosticSeverity) {
81620-	o.StaticcheckAnalyzers[a.Name] = &Analyzer{
81621-		Analyzer: a,
81622-		Enabled:  enabled,
81623-		Severity: severity,
81624-	}
81625-}
81626-
81627-// EnableAllExperiments turns on all of the experimental "off-by-default"
81628-// features offered by gopls. Any experimental features specified in maps
81629-// should be enabled in enableAllExperimentMaps.
81630-func (o *Options) EnableAllExperiments() {
81631-	o.SemanticTokens = true
81632-}
81633-
81634-func (o *Options) enableAllExperimentMaps() {
81635-	if _, ok := o.Codelenses[string(command.GCDetails)]; !ok {
81636-		o.Codelenses[string(command.GCDetails)] = true
81637-	}
81638-	if _, ok := o.Codelenses[string(command.RunGovulncheck)]; !ok {
81639-		o.Codelenses[string(command.RunGovulncheck)] = true
81640-	}
81641-	if _, ok := o.Analyses[unusedparams.Analyzer.Name]; !ok {
81642-		o.Analyses[unusedparams.Analyzer.Name] = true
81643-	}
81644-	if _, ok := o.Analyses[unusedvariable.Analyzer.Name]; !ok {
81645-		o.Analyses[unusedvariable.Analyzer.Name] = true
81646-	}
81647-}
81648-
81649-// validateDirectoryFilter validates if the filter string
81650-// - is not empty
81651-// - start with either + or -
81652-// - doesn't contain currently unsupported glob operators: *, ?
81653-func validateDirectoryFilter(ifilter string) (string, error) {
81654-	filter := fmt.Sprint(ifilter)
81655-	if filter == "" || (filter[0] != '+' && filter[0] != '-') {
81656-		return "", fmt.Errorf("invalid filter %v, must start with + or -", filter)
81657-	}
81658-	segs := strings.Split(filter[1:], "/")
81659-	unsupportedOps := [...]string{"?", "*"}
81660-	for _, seg := range segs {
81661-		if seg != "**" {
81662-			for _, op := range unsupportedOps {
81663-				if strings.Contains(seg, op) {
81664-					return "", fmt.Errorf("invalid filter %v, operator %v not supported. If you want to have this operator supported, consider filing an issue.", filter, op)
81665-				}
81666-			}
81667-		}
81668-	}
81669-
81670-	return strings.TrimRight(filepath.FromSlash(filter), "/"), nil
81671-}
81672-
81673-func (o *Options) set(name string, value interface{}, seen map[string]struct{}) OptionResult {
81674-	// Flatten the name in case we get options with a hierarchy.
81675-	split := strings.Split(name, ".")
81676-	name = split[len(split)-1]
81677-
81678-	result := OptionResult{Name: name, Value: value}
81679-	if _, ok := seen[name]; ok {
81680-		result.parseErrorf("duplicate configuration for %s", name)
81681-	}
81682-	seen[name] = struct{}{}
81683-
81684-	switch name {
81685-	case "env":
81686-		menv, ok := value.(map[string]interface{})
81687-		if !ok {
81688-			result.parseErrorf("invalid type %T, expect map", value)
81689-			break
81690-		}
81691-		if o.Env == nil {
81692-			o.Env = make(map[string]string)
81693-		}
81694-		for k, v := range menv {
81695-			o.Env[k] = fmt.Sprint(v)
81696-		}
81697-
81698-	case "buildFlags":
81699-		// TODO(rfindley): use asStringSlice.
81700-		iflags, ok := value.([]interface{})
81701-		if !ok {
81702-			result.parseErrorf("invalid type %T, expect list", value)
81703-			break
81704-		}
81705-		flags := make([]string, 0, len(iflags))
81706-		for _, flag := range iflags {
81707-			flags = append(flags, fmt.Sprintf("%s", flag))
81708-		}
81709-		o.BuildFlags = flags
81710-
81711-	case "directoryFilters":
81712-		// TODO(rfindley): use asStringSlice.
81713-		ifilters, ok := value.([]interface{})
81714-		if !ok {
81715-			result.parseErrorf("invalid type %T, expect list", value)
81716-			break
81717-		}
81718-		var filters []string
81719-		for _, ifilter := range ifilters {
81720-			filter, err := validateDirectoryFilter(fmt.Sprintf("%v", ifilter))
81721-			if err != nil {
81722-				result.parseErrorf("%v", err)
81723-				return result
81724-			}
81725-			filters = append(filters, strings.TrimRight(filepath.FromSlash(filter), "/"))
81726-		}
81727-		o.DirectoryFilters = filters
81728-
81729-	case "memoryMode":
81730-		if s, ok := result.asOneOf(
81731-			string(ModeNormal),
81732-			string(ModeDegradeClosed),
81733-		); ok {
81734-			o.MemoryMode = MemoryMode(s)
81735-		}
81736-	case "completionDocumentation":
81737-		result.setBool(&o.CompletionDocumentation)
81738-	case "usePlaceholders":
81739-		result.setBool(&o.UsePlaceholders)
81740-	case "deepCompletion":
81741-		result.setBool(&o.DeepCompletion)
81742-	case "completeUnimported":
81743-		result.setBool(&o.CompleteUnimported)
81744-	case "completionBudget":
81745-		result.setDuration(&o.CompletionBudget)
81746-	case "matcher":
81747-		if s, ok := result.asOneOf(
81748-			string(Fuzzy),
81749-			string(CaseSensitive),
81750-			string(CaseInsensitive),
81751-		); ok {
81752-			o.Matcher = Matcher(s)
81753-		}
81754-
81755-	case "symbolMatcher":
81756-		if s, ok := result.asOneOf(
81757-			string(SymbolFuzzy),
81758-			string(SymbolFastFuzzy),
81759-			string(SymbolCaseInsensitive),
81760-			string(SymbolCaseSensitive),
81761-		); ok {
81762-			o.SymbolMatcher = SymbolMatcher(s)
81763-		}
81764-
81765-	case "symbolStyle":
81766-		if s, ok := result.asOneOf(
81767-			string(FullyQualifiedSymbols),
81768-			string(PackageQualifiedSymbols),
81769-			string(DynamicSymbols),
81770-		); ok {
81771-			o.SymbolStyle = SymbolStyle(s)
81772-		}
81773-
81774-	case "hoverKind":
81775-		if s, ok := result.asOneOf(
81776-			string(NoDocumentation),
81777-			string(SingleLine),
81778-			string(SynopsisDocumentation),
81779-			string(FullDocumentation),
81780-			string(Structured),
81781-		); ok {
81782-			o.HoverKind = HoverKind(s)
81783-		}
81784-
81785-	case "linkTarget":
81786-		result.setString(&o.LinkTarget)
81787-
81788-	case "linksInHover":
81789-		result.setBool(&o.LinksInHover)
81790-
81791-	case "importShortcut":
81792-		if s, ok := result.asOneOf(string(BothShortcuts), string(LinkShortcut), string(DefinitionShortcut)); ok {
81793-			o.ImportShortcut = ImportShortcut(s)
81794-		}
81795-
81796-	case "analyses":
81797-		result.setBoolMap(&o.Analyses)
81798-
81799-	case "hints":
81800-		result.setBoolMap(&o.Hints)
81801-
81802-	case "annotations":
81803-		result.setAnnotationMap(&o.Annotations)
81804-
81805-	case "vulncheck":
81806-		if s, ok := result.asOneOf(
81807-			string(ModeVulncheckOff),
81808-			string(ModeVulncheckImports),
81809-		); ok {
81810-			o.Vulncheck = VulncheckMode(s)
81811-		}
81812-
81813-	case "codelenses", "codelens":
81814-		var lensOverrides map[string]bool
81815-		result.setBoolMap(&lensOverrides)
81816-		if result.Error == nil {
81817-			if o.Codelenses == nil {
81818-				o.Codelenses = make(map[string]bool)
81819-			}
81820-			for lens, enabled := range lensOverrides {
81821-				o.Codelenses[lens] = enabled
81822-			}
81823-		}
81824-
81825-		// codelens is deprecated, but still works for now.
81826-		// TODO(rstambler): Remove this for the gopls/v0.7.0 release.
81827-		if name == "codelens" {
81828-			result.deprecated("codelenses")
81829-		}
81830-
81831-	case "staticcheck":
81832-		if v, ok := result.asBool(); ok {
81833-			o.Staticcheck = v
81834-			if v && !o.StaticcheckSupported {
81835-				result.Error = fmt.Errorf("applying setting %q: staticcheck is not supported at %s;"+
81836-					" rebuild gopls with a more recent version of Go", result.Name, runtime.Version())
81837-			}
81838-		}
81839-
81840-	case "local":
81841-		result.setString(&o.Local)
81842-
81843-	case "verboseOutput":
81844-		result.setBool(&o.VerboseOutput)
81845-
81846-	case "verboseWorkDoneProgress":
81847-		result.setBool(&o.VerboseWorkDoneProgress)
81848-
81849-	case "tempModfile":
81850-		result.setBool(&o.TempModfile)
81851-
81852-	case "showBugReports":
81853-		result.setBool(&o.ShowBugReports)
81854-
81855-	case "gofumpt":
81856-		if v, ok := result.asBool(); ok {
81857-			o.Gofumpt = v
81858-			if v && o.GofumptFormat == nil {
81859-				result.Error = fmt.Errorf("applying setting %q: gofumpt is not supported at %s;"+
81860-					" rebuild gopls with a more recent version of Go", result.Name, runtime.Version())
81861-			}
81862-		}
81863-
81864-	case "semanticTokens":
81865-		result.setBool(&o.SemanticTokens)
81866-
81867-	case "noSemanticString":
81868-		result.setBool(&o.NoSemanticString)
81869-
81870-	case "noSemanticNumber":
81871-		result.setBool(&o.NoSemanticNumber)
81872-
81873-	case "expandWorkspaceToModule":
81874-		result.setBool(&o.ExpandWorkspaceToModule)
81875-
81876-	case "experimentalPostfixCompletions":
81877-		result.setBool(&o.ExperimentalPostfixCompletions)
81878-
81879-	case "experimentalWorkspaceModule":
81880-		result.deprecated("")
81881-
81882-	case "experimentalTemplateSupport": // TODO(pjw): remove after June 2022
81883-		result.deprecated("")
81884-
81885-	case "templateExtensions":
81886-		if iexts, ok := value.([]interface{}); ok {
81887-			ans := []string{}
81888-			for _, x := range iexts {
81889-				ans = append(ans, fmt.Sprint(x))
81890-			}
81891-			o.TemplateExtensions = ans
81892-			break
81893-		}
81894-		if value == nil {
81895-			o.TemplateExtensions = nil
81896-			break
81897-		}
81898-		result.parseErrorf("unexpected type %T not []string", value)
81899-
81900-	case "experimentalDiagnosticsDelay":
81901-		result.deprecated("diagnosticsDelay")
81902-
81903-	case "diagnosticsDelay":
81904-		result.setDuration(&o.DiagnosticsDelay)
81905-
81906-	case "experimentalWatchedFileDelay":
81907-		result.deprecated("")
81908-
81909-	case "experimentalPackageCacheKey":
81910-		result.deprecated("")
81911-
81912-	case "allowModfileModifications":
81913-		result.setBool(&o.AllowModfileModifications)
81914-
81915-	case "allowImplicitNetworkAccess":
81916-		result.setBool(&o.AllowImplicitNetworkAccess)
81917-
81918-	case "experimentalUseInvalidMetadata":
81919-		result.deprecated("")
81920-
81921-	case "standaloneTags":
81922-		result.setStringSlice(&o.StandaloneTags)
81923-
81924-	case "allExperiments":
81925-		// This setting should be handled before all of the other options are
81926-		// processed, so do nothing here.
81927-
81928-	case "newDiff":
81929-		result.setString(&o.NewDiff)
81930-
81931-	case "chattyDiagnostics":
81932-		result.setBool(&o.ChattyDiagnostics)
81933-
81934-	// Replaced settings.
81935-	case "experimentalDisabledAnalyses":
81936-		result.deprecated("analyses")
81937-
81938-	case "disableDeepCompletion":
81939-		result.deprecated("deepCompletion")
81940-
81941-	case "disableFuzzyMatching":
81942-		result.deprecated("fuzzyMatching")
81943-
81944-	case "wantCompletionDocumentation":
81945-		result.deprecated("completionDocumentation")
81946-
81947-	case "wantUnimportedCompletions":
81948-		result.deprecated("completeUnimported")
81949-
81950-	case "fuzzyMatching":
81951-		result.deprecated("matcher")
81952-
81953-	case "caseSensitiveCompletion":
81954-		result.deprecated("matcher")
81955-
81956-	// Deprecated settings.
81957-	case "wantSuggestedFixes":
81958-		result.deprecated("")
81959-
81960-	case "noIncrementalSync":
81961-		result.deprecated("")
81962-
81963-	case "watchFileChanges":
81964-		result.deprecated("")
81965-
81966-	case "go-diff":
81967-		result.deprecated("")
81968-
81969-	default:
81970-		result.unexpected()
81971-	}
81972-	return result
81973-}
81974-
81975-// parseErrorf reports an error parsing the current configuration value.
81976-func (r *OptionResult) parseErrorf(msg string, values ...interface{}) {
81977-	if false {
81978-		_ = fmt.Sprintf(msg, values...) // this causes vet to check this like printf
81979-	}
81980-	prefix := fmt.Sprintf("parsing setting %q: ", r.Name)
81981-	r.Error = fmt.Errorf(prefix+msg, values...)
81982-}
81983-
81984-// A SoftError is an error that does not affect the functionality of gopls.
81985-type SoftError struct {
81986-	msg string
81987-}
81988-
81989-func (e *SoftError) Error() string {
81990-	return e.msg
81991-}
81992-
81993-// softErrorf reports an error that does not affect the functionality of gopls
81994-// (a warning in the UI).
81995-// The formatted message will be shown to the user unmodified.
81996-func (r *OptionResult) softErrorf(format string, values ...interface{}) {
81997-	msg := fmt.Sprintf(format, values...)
81998-	r.Error = &SoftError{msg}
81999-}
82000-
82001-// deprecated reports the current setting as deprecated. If 'replacement' is
82002-// non-nil, it is suggested to the user.
82003-func (r *OptionResult) deprecated(replacement string) {
82004-	msg := fmt.Sprintf("gopls setting %q is deprecated", r.Name)
82005-	if replacement != "" {
82006-		msg = fmt.Sprintf("%s, use %q instead", msg, replacement)
82007-	}
82008-	r.Error = &SoftError{msg}
82009-}
82010-
82011-// unexpected reports that the current setting is not known to gopls.
82012-func (r *OptionResult) unexpected() {
82013-	r.Error = fmt.Errorf("unexpected gopls setting %q", r.Name)
82014-}
82015-
82016-func (r *OptionResult) asBool() (bool, bool) {
82017-	b, ok := r.Value.(bool)
82018-	if !ok {
82019-		r.parseErrorf("invalid type %T, expect bool", r.Value)
82020-		return false, false
82021-	}
82022-	return b, true
82023-}
82024-
82025-func (r *OptionResult) setBool(b *bool) {
82026-	if v, ok := r.asBool(); ok {
82027-		*b = v
82028-	}
82029-}
82030-
82031-func (r *OptionResult) setDuration(d *time.Duration) {
82032-	if v, ok := r.asString(); ok {
82033-		parsed, err := time.ParseDuration(v)
82034-		if err != nil {
82035-			r.parseErrorf("failed to parse duration %q: %v", v, err)
82036-			return
82037-		}
82038-		*d = parsed
82039-	}
82040-}
82041-
82042-func (r *OptionResult) setBoolMap(bm *map[string]bool) {
82043-	m := r.asBoolMap()
82044-	*bm = m
82045-}
82046-
82047-func (r *OptionResult) setAnnotationMap(bm *map[Annotation]bool) {
82048-	all := r.asBoolMap()
82049-	if all == nil {
82050-		return
82051-	}
82052-	// Default to everything enabled by default.
82053-	m := make(map[Annotation]bool)
82054-	for k, enabled := range all {
82055-		a, err := asOneOf(
82056-			k,
82057-			string(Nil),
82058-			string(Escape),
82059-			string(Inline),
82060-			string(Bounds),
82061-		)
82062-		if err != nil {
82063-			// In case of an error, process any legacy values.
82064-			switch k {
82065-			case "noEscape":
82066-				m[Escape] = false
82067-				r.parseErrorf(`"noEscape" is deprecated, set "Escape: false" instead`)
82068-			case "noNilcheck":
82069-				m[Nil] = false
82070-				r.parseErrorf(`"noNilcheck" is deprecated, set "Nil: false" instead`)
82071-			case "noInline":
82072-				m[Inline] = false
82073-				r.parseErrorf(`"noInline" is deprecated, set "Inline: false" instead`)
82074-			case "noBounds":
82075-				m[Bounds] = false
82076-				r.parseErrorf(`"noBounds" is deprecated, set "Bounds: false" instead`)
82077-			default:
82078-				r.parseErrorf("%v", err)
82079-			}
82080-			continue
82081-		}
82082-		m[Annotation(a)] = enabled
82083-	}
82084-	*bm = m
82085-}
82086-
82087-func (r *OptionResult) asBoolMap() map[string]bool {
82088-	all, ok := r.Value.(map[string]interface{})
82089-	if !ok {
82090-		r.parseErrorf("invalid type %T for map[string]bool option", r.Value)
82091-		return nil
82092-	}
82093-	m := make(map[string]bool)
82094-	for a, enabled := range all {
82095-		if e, ok := enabled.(bool); ok {
82096-			m[a] = e
82097-		} else {
82098-			r.parseErrorf("invalid type %T for map key %q", enabled, a)
82099-			return m
82100-		}
82101-	}
82102-	return m
82103-}
82104-
82105-func (r *OptionResult) asString() (string, bool) {
82106-	b, ok := r.Value.(string)
82107-	if !ok {
82108-		r.parseErrorf("invalid type %T, expect string", r.Value)
82109-		return "", false
82110-	}
82111-	return b, true
82112-}
82113-
82114-func (r *OptionResult) asStringSlice() ([]string, bool) {
82115-	iList, ok := r.Value.([]interface{})
82116-	if !ok {
82117-		r.parseErrorf("invalid type %T, expect list", r.Value)
82118-		return nil, false
82119-	}
82120-	var list []string
82121-	for _, elem := range iList {
82122-		s, ok := elem.(string)
82123-		if !ok {
82124-			r.parseErrorf("invalid element type %T, expect string", elem)
82125-			return nil, false
82126-		}
82127-		list = append(list, s)
82128-	}
82129-	return list, true
82130-}
82131-
82132-func (r *OptionResult) asOneOf(options ...string) (string, bool) {
82133-	s, ok := r.asString()
82134-	if !ok {
82135-		return "", false
82136-	}
82137-	s, err := asOneOf(s, options...)
82138-	if err != nil {
82139-		r.parseErrorf("%v", err)
82140-	}
82141-	return s, err == nil
82142-}
82143-
82144-func asOneOf(str string, options ...string) (string, error) {
82145-	lower := strings.ToLower(str)
82146-	for _, opt := range options {
82147-		if strings.ToLower(opt) == lower {
82148-			return opt, nil
82149-		}
82150-	}
82151-	return "", fmt.Errorf("invalid option %q for enum", str)
82152-}
82153-
82154-func (r *OptionResult) setString(s *string) {
82155-	if v, ok := r.asString(); ok {
82156-		*s = v
82157-	}
82158-}
82159-
82160-func (r *OptionResult) setStringSlice(s *[]string) {
82161-	if v, ok := r.asStringSlice(); ok {
82162-		*s = v
82163-	}
82164-}
82165-
82166-func typeErrorAnalyzers() map[string]*Analyzer {
82167-	return map[string]*Analyzer{
82168-		fillreturns.Analyzer.Name: {
82169-			Analyzer:   fillreturns.Analyzer,
82170-			ActionKind: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},
82171-			Enabled:    true,
82172-		},
82173-		nonewvars.Analyzer.Name: {
82174-			Analyzer: nonewvars.Analyzer,
82175-			Enabled:  true,
82176-		},
82177-		noresultvalues.Analyzer.Name: {
82178-			Analyzer: noresultvalues.Analyzer,
82179-			Enabled:  true,
82180-		},
82181-		undeclaredname.Analyzer.Name: {
82182-			Analyzer: undeclaredname.Analyzer,
82183-			Fix:      UndeclaredName,
82184-			Enabled:  true,
82185-		},
82186-		unusedvariable.Analyzer.Name: {
82187-			Analyzer: unusedvariable.Analyzer,
82188-			Enabled:  false,
82189-		},
82190-	}
82191-}
82192-
82193-func convenienceAnalyzers() map[string]*Analyzer {
82194-	return map[string]*Analyzer{
82195-		fillstruct.Analyzer.Name: {
82196-			Analyzer:   fillstruct.Analyzer,
82197-			Fix:        FillStruct,
82198-			Enabled:    true,
82199-			ActionKind: []protocol.CodeActionKind{protocol.RefactorRewrite},
82200-		},
82201-		stubmethods.Analyzer.Name: {
82202-			Analyzer:   stubmethods.Analyzer,
82203-			ActionKind: []protocol.CodeActionKind{protocol.RefactorRewrite},
82204-			Fix:        StubMethods,
82205-			Enabled:    true,
82206-		},
82207-	}
82208-}
82209-
82210-func defaultAnalyzers() map[string]*Analyzer {
82211-	return map[string]*Analyzer{
82212-		// The traditional vet suite:
82213-		asmdecl.Analyzer.Name:       {Analyzer: asmdecl.Analyzer, Enabled: true},
82214-		assign.Analyzer.Name:        {Analyzer: assign.Analyzer, Enabled: true},
82215-		atomic.Analyzer.Name:        {Analyzer: atomic.Analyzer, Enabled: true},
82216-		bools.Analyzer.Name:         {Analyzer: bools.Analyzer, Enabled: true},
82217-		buildtag.Analyzer.Name:      {Analyzer: buildtag.Analyzer, Enabled: true},
82218-		cgocall.Analyzer.Name:       {Analyzer: cgocall.Analyzer, Enabled: true},
82219-		composite.Analyzer.Name:     {Analyzer: composite.Analyzer, Enabled: true},
82220-		copylock.Analyzer.Name:      {Analyzer: copylock.Analyzer, Enabled: true},
82221-		directive.Analyzer.Name:     {Analyzer: directive.Analyzer, Enabled: true},
82222-		errorsas.Analyzer.Name:      {Analyzer: errorsas.Analyzer, Enabled: true},
82223-		httpresponse.Analyzer.Name:  {Analyzer: httpresponse.Analyzer, Enabled: true},
82224-		ifaceassert.Analyzer.Name:   {Analyzer: ifaceassert.Analyzer, Enabled: true},
82225-		loopclosure.Analyzer.Name:   {Analyzer: loopclosure.Analyzer, Enabled: true},
82226-		lostcancel.Analyzer.Name:    {Analyzer: lostcancel.Analyzer, Enabled: true},
82227-		nilfunc.Analyzer.Name:       {Analyzer: nilfunc.Analyzer, Enabled: true},
82228-		printf.Analyzer.Name:        {Analyzer: printf.Analyzer, Enabled: true},
82229-		shift.Analyzer.Name:         {Analyzer: shift.Analyzer, Enabled: true},
82230-		stdmethods.Analyzer.Name:    {Analyzer: stdmethods.Analyzer, Enabled: true},
82231-		stringintconv.Analyzer.Name: {Analyzer: stringintconv.Analyzer, Enabled: true},
82232-		structtag.Analyzer.Name:     {Analyzer: structtag.Analyzer, Enabled: true},
82233-		tests.Analyzer.Name:         {Analyzer: tests.Analyzer, Enabled: true},
82234-		unmarshal.Analyzer.Name:     {Analyzer: unmarshal.Analyzer, Enabled: true},
82235-		unreachable.Analyzer.Name:   {Analyzer: unreachable.Analyzer, Enabled: true},
82236-		unsafeptr.Analyzer.Name:     {Analyzer: unsafeptr.Analyzer, Enabled: true},
82237-		unusedresult.Analyzer.Name:  {Analyzer: unusedresult.Analyzer, Enabled: true},
82238-
82239-		// Non-vet analyzers:
82240-		atomicalign.Analyzer.Name:      {Analyzer: atomicalign.Analyzer, Enabled: true},
82241-		deepequalerrors.Analyzer.Name:  {Analyzer: deepequalerrors.Analyzer, Enabled: true},
82242-		fieldalignment.Analyzer.Name:   {Analyzer: fieldalignment.Analyzer, Enabled: false},
82243-		nilness.Analyzer.Name:          {Analyzer: nilness.Analyzer, Enabled: false},
82244-		shadow.Analyzer.Name:           {Analyzer: shadow.Analyzer, Enabled: false},
82245-		sortslice.Analyzer.Name:        {Analyzer: sortslice.Analyzer, Enabled: true},
82246-		testinggoroutine.Analyzer.Name: {Analyzer: testinggoroutine.Analyzer, Enabled: true},
82247-		unusedparams.Analyzer.Name:     {Analyzer: unusedparams.Analyzer, Enabled: false},
82248-		unusedwrite.Analyzer.Name:      {Analyzer: unusedwrite.Analyzer, Enabled: false},
82249-		useany.Analyzer.Name:           {Analyzer: useany.Analyzer, Enabled: false},
82250-		infertypeargs.Analyzer.Name:    {Analyzer: infertypeargs.Analyzer, Enabled: true},
82251-		embeddirective.Analyzer.Name:   {Analyzer: embeddirective.Analyzer, Enabled: true},
82252-		timeformat.Analyzer.Name:       {Analyzer: timeformat.Analyzer, Enabled: true},
82253-
82254-		// gofmt -s suite:
82255-		simplifycompositelit.Analyzer.Name: {
82256-			Analyzer:   simplifycompositelit.Analyzer,
82257-			Enabled:    true,
82258-			ActionKind: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},
82259-		},
82260-		simplifyrange.Analyzer.Name: {
82261-			Analyzer:   simplifyrange.Analyzer,
82262-			Enabled:    true,
82263-			ActionKind: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},
82264-		},
82265-		simplifyslice.Analyzer.Name: {
82266-			Analyzer:   simplifyslice.Analyzer,
82267-			Enabled:    true,
82268-			ActionKind: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},
82269-		},
82270-	}
82271-}
82272-
82273-func urlRegexp() *regexp.Regexp {
82274-	// Ensure links are matched as full words, not anywhere.
82275-	re := regexp.MustCompile(`\b(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?\b`)
82276-	re.Longest()
82277-	return re
82278-}
82279-
82280-type APIJSON struct {
82281-	Options   map[string][]*OptionJSON
82282-	Commands  []*CommandJSON
82283-	Lenses    []*LensJSON
82284-	Analyzers []*AnalyzerJSON
82285-	Hints     []*HintJSON
82286-}
82287-
82288-type OptionJSON struct {
82289-	Name       string
82290-	Type       string
82291-	Doc        string
82292-	EnumKeys   EnumKeys
82293-	EnumValues []EnumValue
82294-	Default    string
82295-	Status     string
82296-	Hierarchy  string
82297-}
82298-
82299-func (o *OptionJSON) String() string {
82300-	return o.Name
82301-}
82302-
82303-func (o *OptionJSON) Write(w io.Writer) {
82304-	fmt.Fprintf(w, "**%v** *%v*\n\n", o.Name, o.Type)
82305-	writeStatus(w, o.Status)
82306-	enumValues := collectEnums(o)
82307-	fmt.Fprintf(w, "%v%v\nDefault: `%v`.\n\n", o.Doc, enumValues, o.Default)
82308-}
82309-
82310-func writeStatus(section io.Writer, status string) {
82311-	switch status {
82312-	case "":
82313-	case "advanced":
82314-		fmt.Fprint(section, "**This is an advanced setting and should not be configured by most `gopls` users.**\n\n")
82315-	case "debug":
82316-		fmt.Fprint(section, "**This setting is for debugging purposes only.**\n\n")
82317-	case "experimental":
82318-		fmt.Fprint(section, "**This setting is experimental and may be deleted.**\n\n")
82319-	default:
82320-		fmt.Fprintf(section, "**Status: %s.**\n\n", status)
82321-	}
82322-}
82323-
82324-var parBreakRE = regexp.MustCompile("\n{2,}")
82325-
82326-func collectEnums(opt *OptionJSON) string {
82327-	var b strings.Builder
82328-	write := func(name, doc string, index, len int) {
82329-		if doc != "" {
82330-			unbroken := parBreakRE.ReplaceAllString(doc, "\\\n")
82331-			fmt.Fprintf(&b, "* %s\n", strings.TrimSpace(unbroken))
82332-		} else {
82333-			fmt.Fprintf(&b, "* `%s`\n", name)
82334-		}
82335-	}
82336-	if len(opt.EnumValues) > 0 && opt.Type == "enum" {
82337-		b.WriteString("\nMust be one of:\n\n")
82338-		for i, val := range opt.EnumValues {
82339-			write(val.Value, val.Doc, i, len(opt.EnumValues))
82340-		}
82341-	} else if len(opt.EnumKeys.Keys) > 0 && shouldShowEnumKeysInSettings(opt.Name) {
82342-		b.WriteString("\nCan contain any of:\n\n")
82343-		for i, val := range opt.EnumKeys.Keys {
82344-			write(val.Name, val.Doc, i, len(opt.EnumKeys.Keys))
82345-		}
82346-	}
82347-	return b.String()
82348-}
82349-
82350-func shouldShowEnumKeysInSettings(name string) bool {
82351-	// These fields have too many possible options to print.
82352-	return !(name == "analyses" || name == "codelenses" || name == "hints")
82353-}
82354-
82355-type EnumKeys struct {
82356-	ValueType string
82357-	Keys      []EnumKey
82358-}
82359-
82360-type EnumKey struct {
82361-	Name    string
82362-	Doc     string
82363-	Default string
82364-}
82365-
82366-type EnumValue struct {
82367-	Value string
82368-	Doc   string
82369-}
82370-
82371-type CommandJSON struct {
82372-	Command   string
82373-	Title     string
82374-	Doc       string
82375-	ArgDoc    string
82376-	ResultDoc string
82377-}
82378-
82379-func (c *CommandJSON) String() string {
82380-	return c.Command
82381-}
82382-
82383-func (c *CommandJSON) Write(w io.Writer) {
82384-	fmt.Fprintf(w, "### **%v**\nIdentifier: `%v`\n\n%v\n\n", c.Title, c.Command, c.Doc)
82385-	if c.ArgDoc != "" {
82386-		fmt.Fprintf(w, "Args:\n\n```\n%s\n```\n\n", c.ArgDoc)
82387-	}
82388-	if c.ResultDoc != "" {
82389-		fmt.Fprintf(w, "Result:\n\n```\n%s\n```\n\n", c.ResultDoc)
82390-	}
82391-}
82392-
82393-type LensJSON struct {
82394-	Lens  string
82395-	Title string
82396-	Doc   string
82397-}
82398-
82399-func (l *LensJSON) String() string {
82400-	return l.Title
82401-}
82402-
82403-func (l *LensJSON) Write(w io.Writer) {
82404-	fmt.Fprintf(w, "%s (%s): %s", l.Title, l.Lens, l.Doc)
82405-}
82406-
82407-type AnalyzerJSON struct {
82408-	Name    string
82409-	Doc     string
82410-	Default bool
82411-}
82412-
82413-func (a *AnalyzerJSON) String() string {
82414-	return a.Name
82415-}
82416-
82417-func (a *AnalyzerJSON) Write(w io.Writer) {
82418-	fmt.Fprintf(w, "%s (%s): %v", a.Name, a.Doc, a.Default)
82419-}
82420-
82421-type HintJSON struct {
82422-	Name    string
82423-	Doc     string
82424-	Default bool
82425-}
82426-
82427-func (h *HintJSON) String() string {
82428-	return h.Name
82429-}
82430-
82431-func (h *HintJSON) Write(w io.Writer) {
82432-	fmt.Fprintf(w, "%s (%s): %v", h.Name, h.Doc, h.Default)
82433-}
82434diff -urN a/gopls/internal/lsp/source/options_test.go b/gopls/internal/lsp/source/options_test.go
82435--- a/gopls/internal/lsp/source/options_test.go	2000-01-01 00:00:00.000000000 -0000
82436+++ b/gopls/internal/lsp/source/options_test.go	1970-01-01 00:00:00.000000000 +0000
82437@@ -1,206 +0,0 @@
82438-// Copyright 2020 The Go Authors. All rights reserved.
82439-// Use of this source code is governed by a BSD-style
82440-// license that can be found in the LICENSE file.
82441-
82442-package source
82443-
82444-import (
82445-	"testing"
82446-	"time"
82447-)
82448-
82449-func TestSetOption(t *testing.T) {
82450-	tests := []struct {
82451-		name      string
82452-		value     interface{}
82453-		wantError bool
82454-		check     func(Options) bool
82455-	}{
82456-		{
82457-			name:  "symbolStyle",
82458-			value: "Dynamic",
82459-			check: func(o Options) bool { return o.SymbolStyle == DynamicSymbols },
82460-		},
82461-		{
82462-			name:      "symbolStyle",
82463-			value:     "",
82464-			wantError: true,
82465-			check:     func(o Options) bool { return o.SymbolStyle == "" },
82466-		},
82467-		{
82468-			name:      "symbolStyle",
82469-			value:     false,
82470-			wantError: true,
82471-			check:     func(o Options) bool { return o.SymbolStyle == "" },
82472-		},
82473-		{
82474-			name:  "symbolMatcher",
82475-			value: "caseInsensitive",
82476-			check: func(o Options) bool { return o.SymbolMatcher == SymbolCaseInsensitive },
82477-		},
82478-		{
82479-			name:  "completionBudget",
82480-			value: "2s",
82481-			check: func(o Options) bool { return o.CompletionBudget == 2*time.Second },
82482-		},
82483-		{
82484-			name:      "staticcheck",
82485-			value:     true,
82486-			check:     func(o Options) bool { return o.Staticcheck == true },
82487-			wantError: true, // o.StaticcheckSupported is unset
82488-		},
82489-		{
82490-			name:  "codelenses",
82491-			value: map[string]interface{}{"generate": true},
82492-			check: func(o Options) bool { return o.Codelenses["generate"] },
82493-		},
82494-		{
82495-			name:  "allExperiments",
82496-			value: true,
82497-			check: func(o Options) bool {
82498-				return true // just confirm that we handle this setting
82499-			},
82500-		},
82501-		{
82502-			name:  "hoverKind",
82503-			value: "FullDocumentation",
82504-			check: func(o Options) bool {
82505-				return o.HoverKind == FullDocumentation
82506-			},
82507-		},
82508-		{
82509-			name:  "hoverKind",
82510-			value: "NoDocumentation",
82511-			check: func(o Options) bool {
82512-				return o.HoverKind == NoDocumentation
82513-			},
82514-		},
82515-		{
82516-			name:  "hoverKind",
82517-			value: "SingleLine",
82518-			check: func(o Options) bool {
82519-				return o.HoverKind == SingleLine
82520-			},
82521-		},
82522-		{
82523-			name:  "hoverKind",
82524-			value: "Structured",
82525-			check: func(o Options) bool {
82526-				return o.HoverKind == Structured
82527-			},
82528-		},
82529-		{
82530-			name:  "ui.documentation.hoverKind",
82531-			value: "Structured",
82532-			check: func(o Options) bool {
82533-				return o.HoverKind == Structured
82534-			},
82535-		},
82536-		{
82537-			name:  "matcher",
82538-			value: "Fuzzy",
82539-			check: func(o Options) bool {
82540-				return o.Matcher == Fuzzy
82541-			},
82542-		},
82543-		{
82544-			name:  "matcher",
82545-			value: "CaseSensitive",
82546-			check: func(o Options) bool {
82547-				return o.Matcher == CaseSensitive
82548-			},
82549-		},
82550-		{
82551-			name:  "matcher",
82552-			value: "CaseInsensitive",
82553-			check: func(o Options) bool {
82554-				return o.Matcher == CaseInsensitive
82555-			},
82556-		},
82557-		{
82558-			name:  "env",
82559-			value: map[string]interface{}{"testing": "true"},
82560-			check: func(o Options) bool {
82561-				v, found := o.Env["testing"]
82562-				return found && v == "true"
82563-			},
82564-		},
82565-		{
82566-			name:      "env",
82567-			value:     []string{"invalid", "input"},
82568-			wantError: true,
82569-			check: func(o Options) bool {
82570-				return o.Env == nil
82571-			},
82572-		},
82573-		{
82574-			name:  "directoryFilters",
82575-			value: []interface{}{"-node_modules", "+project_a"},
82576-			check: func(o Options) bool {
82577-				return len(o.DirectoryFilters) == 2
82578-			},
82579-		},
82580-		{
82581-			name:      "directoryFilters",
82582-			value:     []interface{}{"invalid"},
82583-			wantError: true,
82584-			check: func(o Options) bool {
82585-				return len(o.DirectoryFilters) == 0
82586-			},
82587-		},
82588-		{
82589-			name:      "directoryFilters",
82590-			value:     []string{"-invalid", "+type"},
82591-			wantError: true,
82592-			check: func(o Options) bool {
82593-				return len(o.DirectoryFilters) == 0
82594-			},
82595-		},
82596-		{
82597-			name: "annotations",
82598-			value: map[string]interface{}{
82599-				"Nil":      false,
82600-				"noBounds": true,
82601-			},
82602-			wantError: true,
82603-			check: func(o Options) bool {
82604-				return !o.Annotations[Nil] && !o.Annotations[Bounds]
82605-			},
82606-		},
82607-		{
82608-			name:      "vulncheck",
82609-			value:     []interface{}{"invalid"},
82610-			wantError: true,
82611-			check: func(o Options) bool {
82612-				return o.Vulncheck == "" // For invalid value, default to 'off'.
82613-			},
82614-		},
82615-		{
82616-			name:  "vulncheck",
82617-			value: "Imports",
82618-			check: func(o Options) bool {
82619-				return o.Vulncheck == ModeVulncheckImports // For invalid value, default to 'off'.
82620-			},
82621-		},
82622-		{
82623-			name:  "vulncheck",
82624-			value: "imports",
82625-			check: func(o Options) bool {
82626-				return o.Vulncheck == ModeVulncheckImports
82627-			},
82628-		},
82629-	}
82630-
82631-	for _, test := range tests {
82632-		var opts Options
82633-		result := opts.set(test.name, test.value, map[string]struct{}{})
82634-		if (result.Error != nil) != test.wantError {
82635-			t.Fatalf("Options.set(%q, %v): result.Error = %v, want error: %t", test.name, test.value, result.Error, test.wantError)
82636-		}
82637-		// TODO: this could be made much better using cmp.Diff, if that becomes
82638-		// available in this module.
82639-		if !test.check(opts) {
82640-			t.Errorf("Options.set(%q, %v): unexpected result %+v", test.name, test.value, opts)
82641-		}
82642-	}
82643-}
82644diff -urN a/gopls/internal/lsp/source/references.go b/gopls/internal/lsp/source/references.go
82645--- a/gopls/internal/lsp/source/references.go	2000-01-01 00:00:00.000000000 -0000
82646+++ b/gopls/internal/lsp/source/references.go	1970-01-01 00:00:00.000000000 +0000
82647@@ -1,582 +0,0 @@
82648-// Copyright 2019 The Go Authors. All rights reserved.
82649-// Use of this source code is governed by a BSD-style
82650-// license that can be found in the LICENSE file.
82651-
82652-package source
82653-
82654-// This file defines the 'references' query based on a serializable
82655-// index constructed during type checking, thus avoiding the need to
82656-// type-check packages at search time.
82657-//
82658-// See the ./xrefs/ subpackage for the index construction and lookup.
82659-//
82660-// This implementation does not intermingle objects from distinct
82661-// calls to TypeCheck.
82662-
82663-import (
82664-	"context"
82665-	"fmt"
82666-	"go/ast"
82667-	"go/token"
82668-	"go/types"
82669-	"sort"
82670-	"strings"
82671-	"sync"
82672-
82673-	"golang.org/x/sync/errgroup"
82674-	"golang.org/x/tools/go/types/objectpath"
82675-	"golang.org/x/tools/gopls/internal/lsp/protocol"
82676-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
82677-	"golang.org/x/tools/gopls/internal/lsp/source/methodsets"
82678-	"golang.org/x/tools/gopls/internal/span"
82679-	"golang.org/x/tools/internal/bug"
82680-	"golang.org/x/tools/internal/event"
82681-)
82682-
82683-// References returns a list of all references (sorted with
82684-// definitions before uses) to the object denoted by the identifier at
82685-// the given file/position, searching the entire workspace.
82686-func References(ctx context.Context, snapshot Snapshot, fh FileHandle, pp protocol.Position, includeDeclaration bool) ([]protocol.Location, error) {
82687-	references, err := references(ctx, snapshot, fh, pp, includeDeclaration)
82688-	if err != nil {
82689-		return nil, err
82690-	}
82691-	locations := make([]protocol.Location, len(references))
82692-	for i, ref := range references {
82693-		locations[i] = ref.location
82694-	}
82695-	return locations, nil
82696-}
82697-
82698-// A reference describes an identifier that refers to the same
82699-// object as the subject of a References query.
82700-type reference struct {
82701-	isDeclaration bool
82702-	location      protocol.Location
82703-	pkgPath       PackagePath // of declaring package (same for all elements of the slice)
82704-}
82705-
82706-// references returns a list of all references (sorted with
82707-// definitions before uses) to the object denoted by the identifier at
82708-// the given file/position, searching the entire workspace.
82709-func references(ctx context.Context, snapshot Snapshot, f FileHandle, pp protocol.Position, includeDeclaration bool) ([]reference, error) {
82710-	ctx, done := event.Start(ctx, "source.References2")
82711-	defer done()
82712-
82713-	// Is the cursor within the package name declaration?
82714-	_, inPackageName, err := parsePackageNameDecl(ctx, snapshot, f, pp)
82715-	if err != nil {
82716-		return nil, err
82717-	}
82718-
82719-	var refs []reference
82720-	if inPackageName {
82721-		refs, err = packageReferences(ctx, snapshot, f.URI())
82722-	} else {
82723-		refs, err = ordinaryReferences(ctx, snapshot, f.URI(), pp)
82724-	}
82725-	if err != nil {
82726-		return nil, err
82727-	}
82728-
82729-	sort.Slice(refs, func(i, j int) bool {
82730-		x, y := refs[i], refs[j]
82731-		if x.isDeclaration != y.isDeclaration {
82732-			return x.isDeclaration // decls < refs
82733-		}
82734-		return protocol.CompareLocation(x.location, y.location) < 0
82735-	})
82736-
82737-	// De-duplicate by location, and optionally remove declarations.
82738-	out := refs[:0]
82739-	for _, ref := range refs {
82740-		if !includeDeclaration && ref.isDeclaration {
82741-			continue
82742-		}
82743-		if len(out) == 0 || out[len(out)-1].location != ref.location {
82744-			out = append(out, ref)
82745-		}
82746-	}
82747-	refs = out
82748-
82749-	return refs, nil
82750-}
82751-
82752-// packageReferences returns a list of references to the package
82753-// declaration of the specified name and uri by searching among the
82754-// import declarations of all packages that directly import the target
82755-// package.
82756-func packageReferences(ctx context.Context, snapshot Snapshot, uri span.URI) ([]reference, error) {
82757-	metas, err := snapshot.MetadataForFile(ctx, uri)
82758-	if err != nil {
82759-		return nil, err
82760-	}
82761-	if len(metas) == 0 {
82762-		return nil, fmt.Errorf("found no package containing %s", uri)
82763-	}
82764-
82765-	var refs []reference
82766-
82767-	// Find external references to the package declaration
82768-	// from each direct import of the package.
82769-	//
82770-	// The narrowest package is the most broadly imported,
82771-	// so we choose it for the external references.
82772-	//
82773-	// But if the file ends with _test.go then we need to
82774-	// find the package it is testing; there's no direct way
82775-	// to do that, so pick a file from the same package that
82776-	// doesn't end in _test.go and start over.
82777-	narrowest := metas[0]
82778-	if narrowest.ForTest != "" && strings.HasSuffix(string(uri), "_test.go") {
82779-		for _, f := range narrowest.CompiledGoFiles {
82780-			if !strings.HasSuffix(string(f), "_test.go") {
82781-				return packageReferences(ctx, snapshot, f)
82782-			}
82783-		}
82784-		// This package has no non-test files.
82785-		// Skip the search for external references.
82786-		// (Conceivably one could blank-import an empty package, but why?)
82787-	} else {
82788-		rdeps, err := snapshot.ReverseDependencies(ctx, narrowest.ID, false) // direct
82789-		if err != nil {
82790-			return nil, err
82791-		}
82792-		for _, rdep := range rdeps {
82793-			for _, uri := range rdep.CompiledGoFiles {
82794-				fh, err := snapshot.GetFile(ctx, uri)
82795-				if err != nil {
82796-					return nil, err
82797-				}
82798-				f, err := snapshot.ParseGo(ctx, fh, ParseHeader)
82799-				if err != nil {
82800-					return nil, err
82801-				}
82802-				for _, imp := range f.File.Imports {
82803-					if rdep.DepsByImpPath[UnquoteImportPath(imp)] == narrowest.ID {
82804-						refs = append(refs, reference{
82805-							isDeclaration: false,
82806-							location:      mustLocation(f, imp),
82807-							pkgPath:       narrowest.PkgPath,
82808-						})
82809-					}
82810-				}
82811-			}
82812-		}
82813-	}
82814-
82815-	// Find internal "references" to the package from
82816-	// of each package declaration in the target package itself.
82817-	//
82818-	// The widest package (possibly a test variant) has the
82819-	// greatest number of files and thus we choose it for the
82820-	// "internal" references.
82821-	widest := metas[len(metas)-1]
82822-	for _, uri := range widest.CompiledGoFiles {
82823-		fh, err := snapshot.GetFile(ctx, uri)
82824-		if err != nil {
82825-			return nil, err
82826-		}
82827-		f, err := snapshot.ParseGo(ctx, fh, ParseHeader)
82828-		if err != nil {
82829-			return nil, err
82830-		}
82831-		refs = append(refs, reference{
82832-			isDeclaration: true, // (one of many)
82833-			location:      mustLocation(f, f.File.Name),
82834-			pkgPath:       widest.PkgPath,
82835-		})
82836-	}
82837-
82838-	return refs, nil
82839-}
82840-
82841-// ordinaryReferences computes references for all ordinary objects (not package declarations).
82842-func ordinaryReferences(ctx context.Context, snapshot Snapshot, uri span.URI, pp protocol.Position) ([]reference, error) {
82843-	// Strategy: use the reference information computed by the
82844-	// type checker to find the declaration. First type-check this
82845-	// package to find the declaration, then type check the
82846-	// declaring package (which may be different), plus variants,
82847-	// to find local (in-package) references.
82848-	// Global references are satisfied by the index.
82849-
82850-	// Strictly speaking, a wider package could provide a different
82851-	// declaration (e.g. because the _test.go files can change the
82852-	// meaning of a field or method selection), but the narrower
82853-	// package reports the more broadly referenced object.
82854-	pkg, pgf, err := PackageForFile(ctx, snapshot, uri, NarrowestPackage)
82855-	if err != nil {
82856-		return nil, err
82857-	}
82858-
82859-	// Find the selected object (declaration or reference).
82860-	pos, err := pgf.PositionPos(pp)
82861-	if err != nil {
82862-		return nil, err
82863-	}
82864-	candidates, _, err := objectsAt(pkg.GetTypesInfo(), pgf.File, pos)
82865-	if err != nil {
82866-		return nil, err
82867-	}
82868-
82869-	// Pick first object arbitrarily.
82870-	// The case variables of a type switch have different
82871-	// types but that difference is immaterial here.
82872-	var obj types.Object
82873-	for obj = range candidates {
82874-		break
82875-	}
82876-	if obj == nil {
82877-		return nil, ErrNoIdentFound // can't happen
82878-	}
82879-
82880-	// nil, error, error.Error, iota, or other built-in?
82881-	if obj.Pkg() == nil {
82882-		// For some reason, existing tests require that iota has no references,
82883-		// nor an error. TODO(adonovan): do something more principled.
82884-		if obj.Name() == "iota" {
82885-			return nil, nil
82886-		}
82887-
82888-		return nil, fmt.Errorf("references to builtin %q are not supported", obj.Name())
82889-	}
82890-
82891-	// Find metadata of all packages containing the object's defining file.
82892-	// This may include the query pkg, and possibly other variants.
82893-	declPosn := safetoken.StartPosition(pkg.FileSet(), obj.Pos())
82894-	declURI := span.URIFromPath(declPosn.Filename)
82895-	variants, err := snapshot.MetadataForFile(ctx, declURI)
82896-	if err != nil {
82897-		return nil, err
82898-	}
82899-	if len(variants) == 0 {
82900-		return nil, fmt.Errorf("no packages for file %q", declURI) // can't happen
82901-	}
82902-
82903-	// Is object exported?
82904-	// If so, compute scope and targets of the global search.
82905-	var (
82906-		globalScope   = make(map[PackageID]*Metadata)
82907-		globalTargets map[PackagePath]map[objectpath.Path]unit
82908-	)
82909-	// TODO(adonovan): what about generic functions. Need to consider both
82910-	// uninstantiated and instantiated. The latter have no objectpath. Use Origin?
82911-	if path, err := objectpath.For(obj); err == nil && obj.Exported() {
82912-		pkgPath := variants[0].PkgPath // (all variants have same package path)
82913-		globalTargets = map[PackagePath]map[objectpath.Path]unit{
82914-			pkgPath: {path: {}}, // primary target
82915-		}
82916-
82917-		// How far need we search?
82918-		// For package-level objects, we need only search the direct importers.
82919-		// For fields and methods, we must search transitively.
82920-		transitive := obj.Pkg().Scope().Lookup(obj.Name()) != obj
82921-
82922-		// The scope is the union of rdeps of each variant.
82923-		// (Each set is disjoint so there's no benefit to
82924-		// to combining the metadata graph traversals.)
82925-		for _, m := range variants {
82926-			rdeps, err := snapshot.ReverseDependencies(ctx, m.ID, transitive)
82927-			if err != nil {
82928-				return nil, err
82929-			}
82930-			for id, rdep := range rdeps {
82931-				globalScope[id] = rdep
82932-			}
82933-		}
82934-
82935-		// Is object a method?
82936-		//
82937-		// If so, expand the search so that the targets include
82938-		// all methods that correspond to it through interface
82939-		// satisfaction, and the scope includes the rdeps of
82940-		// the package that declares each corresponding type.
82941-		if recv := effectiveReceiver(obj); recv != nil {
82942-			if err := expandMethodSearch(ctx, snapshot, obj.(*types.Func), recv, globalScope, globalTargets); err != nil {
82943-				return nil, err
82944-			}
82945-		}
82946-	}
82947-
82948-	// The search functions will call report(loc) for each hit.
82949-	var (
82950-		refsMu sync.Mutex
82951-		refs   []reference
82952-	)
82953-	report := func(loc protocol.Location, isDecl bool) {
82954-		ref := reference{
82955-			isDeclaration: isDecl,
82956-			location:      loc,
82957-			pkgPath:       pkg.Metadata().PkgPath,
82958-		}
82959-		refsMu.Lock()
82960-		refs = append(refs, ref)
82961-		refsMu.Unlock()
82962-	}
82963-
82964-	// Loop over the variants of the declaring package,
82965-	// and perform both the local (in-package) and global
82966-	// (cross-package) searches, in parallel.
82967-	//
82968-	// TODO(adonovan): opt: support LSP reference streaming. See:
82969-	// - https://github.com/microsoft/vscode-languageserver-node/pull/164
82970-	// - https://github.com/microsoft/language-server-protocol/pull/182
82971-	//
82972-	// Careful: this goroutine must not return before group.Wait.
82973-	var group errgroup.Group
82974-
82975-	// Compute local references for each variant.
82976-	for _, m := range variants {
82977-		// We want the ordinary importable package,
82978-		// plus any test-augmented variants, since
82979-		// declarations in _test.go files may change
82980-		// the reference of a selection, or even a
82981-		// field into a method or vice versa.
82982-		//
82983-		// But we don't need intermediate test variants,
82984-		// as their local references will be covered
82985-		// already by other variants.
82986-		if m.IsIntermediateTestVariant() {
82987-			continue
82988-		}
82989-		m := m
82990-		group.Go(func() error {
82991-			return localReferences(ctx, snapshot, declURI, declPosn.Offset, m, report)
82992-		})
82993-	}
82994-
82995-	// Compute global references for selected reverse dependencies.
82996-	group.Go(func() error {
82997-		var globalIDs []PackageID
82998-		for id := range globalScope {
82999-			globalIDs = append(globalIDs, id)
83000-		}
83001-		indexes, err := snapshot.References(ctx, globalIDs...)
83002-		if err != nil {
83003-			return err
83004-		}
83005-		for _, index := range indexes {
83006-			for _, loc := range index.Lookup(globalTargets) {
83007-				report(loc, false)
83008-			}
83009-		}
83010-		return nil
83011-	})
83012-
83013-	if err := group.Wait(); err != nil {
83014-		return nil, err
83015-	}
83016-	return refs, nil
83017-}
83018-
83019-// expandMethodSearch expands the scope and targets of a global search
83020-// for an exported method to include all methods that correspond to
83021-// it through interface satisfaction.
83022-//
83023-// recv is the method's effective receiver type, for method-set computations.
83024-func expandMethodSearch(ctx context.Context, snapshot Snapshot, method *types.Func, recv types.Type, scope map[PackageID]*Metadata, targets map[PackagePath]map[objectpath.Path]unit) error {
83025-	// Compute the method-set fingerprint used as a key to the global search.
83026-	key, hasMethods := methodsets.KeyOf(recv)
83027-	if !hasMethods {
83028-		return bug.Errorf("KeyOf(%s)={} yet %s is a method", recv, method)
83029-	}
83030-	metas, err := snapshot.AllMetadata(ctx)
83031-	if err != nil {
83032-		return err
83033-	}
83034-	allIDs := make([]PackageID, 0, len(metas))
83035-	for _, m := range metas {
83036-		allIDs = append(allIDs, m.ID)
83037-	}
83038-	// Search the methodset index of each package in the workspace.
83039-	indexes, err := snapshot.MethodSets(ctx, allIDs...)
83040-	if err != nil {
83041-		return err
83042-	}
83043-	var mu sync.Mutex // guards scope and targets
83044-	var group errgroup.Group
83045-	for i, index := range indexes {
83046-		i := i
83047-		index := index
83048-		group.Go(func() error {
83049-			// Consult index for matching methods.
83050-			results := index.Search(key, method.Name())
83051-			if len(results) == 0 {
83052-				return nil
83053-			}
83054-
83055-			// Expand global search scope to include rdeps of this pkg.
83056-			rdeps, err := snapshot.ReverseDependencies(ctx, allIDs[i], true)
83057-			if err != nil {
83058-				return err
83059-			}
83060-			mu.Lock()
83061-			defer mu.Unlock()
83062-			for _, rdep := range rdeps {
83063-				scope[rdep.ID] = rdep
83064-			}
83065-
83066-			// Add each corresponding method the to set of global search targets.
83067-			for _, res := range results {
83068-				methodPkg := PackagePath(res.PkgPath)
83069-				opaths, ok := targets[methodPkg]
83070-				if !ok {
83071-					opaths = make(map[objectpath.Path]unit)
83072-					targets[methodPkg] = opaths
83073-				}
83074-				opaths[res.ObjectPath] = unit{}
83075-			}
83076-			return nil
83077-		})
83078-	}
83079-	return group.Wait()
83080-}
83081-
83082-// localReferences reports each reference to the object
83083-// declared at the specified URI/offset within its enclosing package m.
83084-func localReferences(ctx context.Context, snapshot Snapshot, declURI span.URI, declOffset int, m *Metadata, report func(loc protocol.Location, isDecl bool)) error {
83085-	pkgs, err := snapshot.TypeCheck(ctx, m.ID)
83086-	if err != nil {
83087-		return err
83088-	}
83089-	pkg := pkgs[0] // narrowest
83090-
83091-	// Find declaration of corresponding object
83092-	// in this package based on (URI, offset).
83093-	pgf, err := pkg.File(declURI)
83094-	if err != nil {
83095-		return err
83096-	}
83097-	pos, err := safetoken.Pos(pgf.Tok, declOffset)
83098-	if err != nil {
83099-		return err
83100-	}
83101-	targets, _, err := objectsAt(pkg.GetTypesInfo(), pgf.File, pos)
83102-	if err != nil {
83103-		return err // unreachable? (probably caught earlier)
83104-	}
83105-
83106-	// Report the locations of the declaration(s).
83107-	// TODO(adonovan): what about for corresponding methods? Add tests.
83108-	for _, node := range targets {
83109-		report(mustLocation(pgf, node), true)
83110-	}
83111-
83112-	// If we're searching for references to a method, broaden the
83113-	// search to include references to corresponding methods of
83114-	// mutually assignable receiver types.
83115-	// (We use a slice, but objectsAt never returns >1 methods.)
83116-	var methodRecvs []types.Type
83117-	var methodName string // name of an arbitrary target, iff a method
83118-	for obj := range targets {
83119-		if t := effectiveReceiver(obj); t != nil {
83120-			methodRecvs = append(methodRecvs, t)
83121-			methodName = obj.Name()
83122-		}
83123-	}
83124-
83125-	// matches reports whether obj either is or corresponds to a target.
83126-	// (Correspondence is defined as usual for interface methods.)
83127-	matches := func(obj types.Object) bool {
83128-		if targets[obj] != nil {
83129-			return true
83130-		} else if methodRecvs != nil && obj.Name() == methodName {
83131-			if orecv := effectiveReceiver(obj); orecv != nil {
83132-				for _, mrecv := range methodRecvs {
83133-					if concreteImplementsIntf(orecv, mrecv) {
83134-						return true
83135-					}
83136-				}
83137-			}
83138-		}
83139-		return false
83140-	}
83141-
83142-	// Scan through syntax looking for uses of one of the target objects.
83143-	for _, pgf := range pkg.CompiledGoFiles() {
83144-		ast.Inspect(pgf.File, func(n ast.Node) bool {
83145-			if id, ok := n.(*ast.Ident); ok {
83146-				if obj, ok := pkg.GetTypesInfo().Uses[id]; ok && matches(obj) {
83147-					report(mustLocation(pgf, id), false)
83148-				}
83149-			}
83150-			return true
83151-		})
83152-	}
83153-	return nil
83154-}
83155-
83156-// effectiveReceiver returns the effective receiver type for method-set
83157-// comparisons for obj, if it is a method, or nil otherwise.
83158-func effectiveReceiver(obj types.Object) types.Type {
83159-	if fn, ok := obj.(*types.Func); ok {
83160-		if recv := fn.Type().(*types.Signature).Recv(); recv != nil {
83161-			return methodsets.EnsurePointer(recv.Type())
83162-		}
83163-	}
83164-	return nil
83165-}
83166-
83167-// objectsAt returns the non-empty set of objects denoted (def or use)
83168-// by the specified position within a file syntax tree, or an error if
83169-// none were found.
83170-//
83171-// The result may contain more than one element because all case
83172-// variables of a type switch appear to be declared at the same
83173-// position.
83174-//
83175-// Each object is mapped to the syntax node that was treated as an
83176-// identifier, which is not always an ast.Ident. The second component
83177-// of the result is the innermost node enclosing pos.
83178-//
83179-// TODO(adonovan): factor in common with referencedObject.
83180-func objectsAt(info *types.Info, file *ast.File, pos token.Pos) (map[types.Object]ast.Node, ast.Node, error) {
83181-	path := pathEnclosingObjNode(file, pos)
83182-	if path == nil {
83183-		return nil, nil, ErrNoIdentFound
83184-	}
83185-
83186-	targets := make(map[types.Object]ast.Node)
83187-
83188-	switch leaf := path[0].(type) {
83189-	case *ast.Ident:
83190-		// If leaf represents an implicit type switch object or the type
83191-		// switch "assign" variable, expand to all of the type switch's
83192-		// implicit objects.
83193-		if implicits, _ := typeSwitchImplicits(info, path); len(implicits) > 0 {
83194-			for _, obj := range implicits {
83195-				targets[obj] = leaf
83196-			}
83197-		} else {
83198-			obj := info.ObjectOf(leaf)
83199-			if obj == nil {
83200-				return nil, nil, fmt.Errorf("%w for %q", errNoObjectFound, leaf.Name)
83201-			}
83202-			targets[obj] = leaf
83203-		}
83204-	case *ast.ImportSpec:
83205-		// Look up the implicit *types.PkgName.
83206-		obj := info.Implicits[leaf]
83207-		if obj == nil {
83208-			return nil, nil, fmt.Errorf("%w for import %s", errNoObjectFound, UnquoteImportPath(leaf))
83209-		}
83210-		targets[obj] = leaf
83211-	}
83212-
83213-	if len(targets) == 0 {
83214-		return nil, nil, fmt.Errorf("objectAt: internal error: no targets") // can't happen
83215-	}
83216-	return targets, path[0], nil
83217-}
83218-
83219-// mustLocation reports the location interval a syntax node,
83220-// which must belong to m.File.
83221-//
83222-// Safe for use only by references2 and implementations2.
83223-func mustLocation(pgf *ParsedGoFile, n ast.Node) protocol.Location {
83224-	loc, err := pgf.NodeLocation(n)
83225-	if err != nil {
83226-		panic(err) // can't happen in references2 or implementations2
83227-	}
83228-	return loc
83229-}
83230diff -urN a/gopls/internal/lsp/source/rename_check.go b/gopls/internal/lsp/source/rename_check.go
83231--- a/gopls/internal/lsp/source/rename_check.go	2000-01-01 00:00:00.000000000 -0000
83232+++ b/gopls/internal/lsp/source/rename_check.go	1970-01-01 00:00:00.000000000 +0000
83233@@ -1,921 +0,0 @@
83234-// Copyright 2019 The Go Authors. All rights reserved.
83235-// Use of this source code is governed by a BSD-style
83236-// license that can be found in the LICENSE file.
83237-//
83238-// Taken from golang.org/x/tools/refactor/rename.
83239-
83240-package source
83241-
83242-// This file defines the conflict-checking portion of the rename operation.
83243-//
83244-// The renamer works on a single package of type-checked syntax, and
83245-// is called in parallel for all necessary packages in the workspace,
83246-// possibly up to the transitive reverse dependencies of the
83247-// declaration. Finally the union of all edits and errors is computed.
83248-//
83249-// Renaming one object may entail renaming of others. For example:
83250-//
83251-// - An embedded field couples a Var (field) and a TypeName.
83252-//   So, renaming either one requires renaming the other.
83253-//   If the initial object is an embedded field, we must add its
83254-//   TypeName (and its enclosing package) to the renaming set;
83255-//   this is easily discovered at the outset.
83256-//
83257-//   Conversely, if the initial object is a TypeName, we must observe
83258-//   whether any of its references (from directly importing packages)
83259-//   is coincident with an embedded field Var and, if so, initiate a
83260-//   renaming of it.
83261-//
83262-// - A method of an interface type is coupled to all corresponding
83263-//   methods of types that are assigned to the interface (as
83264-//   discovered by the 'satisfy' pass). As a matter of usability, we
83265-//   require that such renamings be initiated from the interface
83266-//   method, not the concrete method.
83267-
83268-import (
83269-	"fmt"
83270-	"go/ast"
83271-	"go/token"
83272-	"go/types"
83273-	"path/filepath"
83274-	"reflect"
83275-	"strings"
83276-	"unicode"
83277-
83278-	"golang.org/x/tools/go/ast/astutil"
83279-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
83280-	"golang.org/x/tools/refactor/satisfy"
83281-)
83282-
83283-// errorf reports an error (e.g. conflict) and prevents file modification.
83284-func (r *renamer) errorf(pos token.Pos, format string, args ...interface{}) {
83285-	// Conflict error messages in the old gorename tool (whence this
83286-	// logic originated) contain rich information associated with
83287-	// multiple source lines, such as:
83288-	//
83289-	//   p/a.go:1:2: renaming "x" to "y" here
83290-	//   p/b.go:3:4: \t would cause this reference to "y"
83291-	//   p/c.go:5:5: \t to become shadowed by this intervening declaration.
83292-	//
83293-	// Unfortunately LSP provides no means to transmit the
83294-	// structure of this error, so we format the positions briefly
83295-	// using dir/file.go where dir is the base name of the parent
83296-	// directory.
83297-
83298-	var conflict strings.Builder
83299-
83300-	// Add prefix of (truncated) position.
83301-	if pos != token.NoPos {
83302-		// TODO(adonovan): skip position of first error if it is
83303-		// on the same line as the renaming itself.
83304-		posn := safetoken.StartPosition(r.pkg.FileSet(), pos).String()
83305-		segments := strings.Split(filepath.ToSlash(posn), "/")
83306-		if n := len(segments); n > 2 {
83307-			segments = segments[n-2:]
83308-		}
83309-		posn = strings.Join(segments, "/")
83310-		fmt.Fprintf(&conflict, "%s:", posn)
83311-
83312-		if !strings.HasPrefix(format, "\t") {
83313-			conflict.WriteByte(' ')
83314-		}
83315-	}
83316-
83317-	fmt.Fprintf(&conflict, format, args...)
83318-	r.conflicts = append(r.conflicts, conflict.String())
83319-}
83320-
83321-// check performs safety checks of the renaming of the 'from' object to r.to.
83322-func (r *renamer) check(from types.Object) {
83323-	if r.objsToUpdate[from] {
83324-		return
83325-	}
83326-	r.objsToUpdate[from] = true
83327-
83328-	// NB: order of conditions is important.
83329-	if from_, ok := from.(*types.PkgName); ok {
83330-		r.checkInFileBlock(from_)
83331-	} else if from_, ok := from.(*types.Label); ok {
83332-		r.checkLabel(from_)
83333-	} else if isPackageLevel(from) {
83334-		r.checkInPackageBlock(from)
83335-	} else if v, ok := from.(*types.Var); ok && v.IsField() {
83336-		r.checkStructField(v)
83337-	} else if f, ok := from.(*types.Func); ok && recv(f) != nil {
83338-		r.checkMethod(f)
83339-	} else if isLocal(from) {
83340-		r.checkInLexicalScope(from)
83341-	} else {
83342-		r.errorf(from.Pos(), "unexpected %s object %q (please report a bug)\n",
83343-			objectKind(from), from)
83344-	}
83345-}
83346-
83347-// checkInFileBlock performs safety checks for renames of objects in the file block,
83348-// i.e. imported package names.
83349-func (r *renamer) checkInFileBlock(from *types.PkgName) {
83350-	// Check import name is not "init".
83351-	if r.to == "init" {
83352-		r.errorf(from.Pos(), "%q is not a valid imported package name", r.to)
83353-	}
83354-
83355-	// Check for conflicts between file and package block.
83356-	if prev := from.Pkg().Scope().Lookup(r.to); prev != nil {
83357-		r.errorf(from.Pos(), "renaming this %s %q to %q would conflict",
83358-			objectKind(from), from.Name(), r.to)
83359-		r.errorf(prev.Pos(), "\twith this package member %s",
83360-			objectKind(prev))
83361-		return // since checkInPackageBlock would report redundant errors
83362-	}
83363-
83364-	// Check for conflicts in lexical scope.
83365-	r.checkInLexicalScope(from)
83366-}
83367-
83368-// checkInPackageBlock performs safety checks for renames of
83369-// func/var/const/type objects in the package block.
83370-func (r *renamer) checkInPackageBlock(from types.Object) {
83371-	// Check that there are no references to the name from another
83372-	// package if the renaming would make it unexported.
83373-	if typ := r.pkg.GetTypes(); typ != from.Pkg() && ast.IsExported(r.from) && !ast.IsExported(r.to) {
83374-		if id := someUse(r.pkg.GetTypesInfo(), from); id != nil {
83375-			r.checkExport(id, typ, from)
83376-		}
83377-	}
83378-
83379-	// Check that in the package block, "init" is a function, and never referenced.
83380-	if r.to == "init" {
83381-		kind := objectKind(from)
83382-		if kind == "func" {
83383-			// Reject if intra-package references to it exist.
83384-			for id, obj := range r.pkg.GetTypesInfo().Uses {
83385-				if obj == from {
83386-					r.errorf(from.Pos(),
83387-						"renaming this func %q to %q would make it a package initializer",
83388-						from.Name(), r.to)
83389-					r.errorf(id.Pos(), "\tbut references to it exist")
83390-					break
83391-				}
83392-			}
83393-		} else {
83394-			r.errorf(from.Pos(), "you cannot have a %s at package level named %q",
83395-				kind, r.to)
83396-		}
83397-	}
83398-
83399-	// Check for conflicts between package block and all file blocks.
83400-	for _, f := range r.pkg.GetSyntax() {
83401-		fileScope := r.pkg.GetTypesInfo().Scopes[f]
83402-		b, prev := fileScope.LookupParent(r.to, token.NoPos)
83403-		if b == fileScope {
83404-			r.errorf(from.Pos(), "renaming this %s %q to %q would conflict", objectKind(from), from.Name(), r.to)
83405-			var prevPos token.Pos
83406-			if prev != nil {
83407-				prevPos = prev.Pos()
83408-			}
83409-			r.errorf(prevPos, "\twith this %s", objectKind(prev))
83410-			return // since checkInPackageBlock would report redundant errors
83411-		}
83412-	}
83413-
83414-	// Check for conflicts in lexical scope.
83415-	r.checkInLexicalScope(from)
83416-}
83417-
83418-// checkInLexicalScope performs safety checks that a renaming does not
83419-// change the lexical reference structure of the specified package.
83420-//
83421-// For objects in lexical scope, there are three kinds of conflicts:
83422-// same-, sub-, and super-block conflicts.  We will illustrate all three
83423-// using this example:
83424-//
83425-//	var x int
83426-//	var z int
83427-//
83428-//	func f(y int) {
83429-//		print(x)
83430-//		print(y)
83431-//	}
83432-//
83433-// Renaming x to z encounters a "same-block conflict", because an object
83434-// with the new name already exists, defined in the same lexical block
83435-// as the old object.
83436-//
83437-// Renaming x to y encounters a "sub-block conflict", because there exists
83438-// a reference to x from within (what would become) a hole in its scope.
83439-// The definition of y in an (inner) sub-block would cast a shadow in
83440-// the scope of the renamed variable.
83441-//
83442-// Renaming y to x encounters a "super-block conflict".  This is the
83443-// converse situation: there is an existing definition of the new name
83444-// (x) in an (enclosing) super-block, and the renaming would create a
83445-// hole in its scope, within which there exist references to it.  The
83446-// new name shadows the existing definition of x in the super-block.
83447-//
83448-// Removing the old name (and all references to it) is always safe, and
83449-// requires no checks.
83450-func (r *renamer) checkInLexicalScope(from types.Object) {
83451-	b := from.Parent() // the block defining the 'from' object
83452-	if b != nil {
83453-		toBlock, to := b.LookupParent(r.to, from.Parent().End())
83454-		if toBlock == b {
83455-			// same-block conflict
83456-			r.errorf(from.Pos(), "renaming this %s %q to %q",
83457-				objectKind(from), from.Name(), r.to)
83458-			r.errorf(to.Pos(), "\tconflicts with %s in same block",
83459-				objectKind(to))
83460-			return
83461-		} else if toBlock != nil {
83462-			// Check for super-block conflict.
83463-			// The name r.to is defined in a superblock.
83464-			// Is that name referenced from within this block?
83465-			forEachLexicalRef(r.pkg, to, func(id *ast.Ident, block *types.Scope) bool {
83466-				_, obj := block.LookupParent(from.Name(), id.Pos())
83467-				if obj == from {
83468-					// super-block conflict
83469-					r.errorf(from.Pos(), "renaming this %s %q to %q",
83470-						objectKind(from), from.Name(), r.to)
83471-					r.errorf(id.Pos(), "\twould shadow this reference")
83472-					r.errorf(to.Pos(), "\tto the %s declared here",
83473-						objectKind(to))
83474-					return false // stop
83475-				}
83476-				return true
83477-			})
83478-		}
83479-	}
83480-	// Check for sub-block conflict.
83481-	// Is there an intervening definition of r.to between
83482-	// the block defining 'from' and some reference to it?
83483-	forEachLexicalRef(r.pkg, from, func(id *ast.Ident, block *types.Scope) bool {
83484-		// Find the block that defines the found reference.
83485-		// It may be an ancestor.
83486-		fromBlock, _ := block.LookupParent(from.Name(), id.Pos())
83487-		// See what r.to would resolve to in the same scope.
83488-		toBlock, to := block.LookupParent(r.to, id.Pos())
83489-		if to != nil {
83490-			// sub-block conflict
83491-			if deeper(toBlock, fromBlock) {
83492-				r.errorf(from.Pos(), "renaming this %s %q to %q",
83493-					objectKind(from), from.Name(), r.to)
83494-				r.errorf(id.Pos(), "\twould cause this reference to become shadowed")
83495-				r.errorf(to.Pos(), "\tby this intervening %s definition",
83496-					objectKind(to))
83497-				return false // stop
83498-			}
83499-		}
83500-		return true
83501-	})
83502-
83503-	// Renaming a type that is used as an embedded field
83504-	// requires renaming the field too. e.g.
83505-	// 	type T int // if we rename this to U..
83506-	// 	var s struct {T}
83507-	// 	print(s.T) // ...this must change too
83508-	if _, ok := from.(*types.TypeName); ok {
83509-		for id, obj := range r.pkg.GetTypesInfo().Uses {
83510-			if obj == from {
83511-				if field := r.pkg.GetTypesInfo().Defs[id]; field != nil {
83512-					r.check(field)
83513-				}
83514-			}
83515-		}
83516-	}
83517-}
83518-
83519-// deeper reports whether block x is lexically deeper than y.
83520-func deeper(x, y *types.Scope) bool {
83521-	if x == y || x == nil {
83522-		return false
83523-	} else if y == nil {
83524-		return true
83525-	} else {
83526-		return deeper(x.Parent(), y.Parent())
83527-	}
83528-}
83529-
83530-// forEachLexicalRef calls fn(id, block) for each identifier id in package
83531-// pkg that is a reference to obj in lexical scope.  block is the
83532-// lexical block enclosing the reference.  If fn returns false the
83533-// iteration is terminated and findLexicalRefs returns false.
83534-func forEachLexicalRef(pkg Package, obj types.Object, fn func(id *ast.Ident, block *types.Scope) bool) bool {
83535-	ok := true
83536-	var stack []ast.Node
83537-
83538-	var visit func(n ast.Node) bool
83539-	visit = func(n ast.Node) bool {
83540-		if n == nil {
83541-			stack = stack[:len(stack)-1] // pop
83542-			return false
83543-		}
83544-		if !ok {
83545-			return false // bail out
83546-		}
83547-
83548-		stack = append(stack, n) // push
83549-		switch n := n.(type) {
83550-		case *ast.Ident:
83551-			if pkg.GetTypesInfo().Uses[n] == obj {
83552-				block := enclosingBlock(pkg.GetTypesInfo(), stack)
83553-				if !fn(n, block) {
83554-					ok = false
83555-				}
83556-			}
83557-			return visit(nil) // pop stack
83558-
83559-		case *ast.SelectorExpr:
83560-			// don't visit n.Sel
83561-			ast.Inspect(n.X, visit)
83562-			return visit(nil) // pop stack, don't descend
83563-
83564-		case *ast.CompositeLit:
83565-			// Handle recursion ourselves for struct literals
83566-			// so we don't visit field identifiers.
83567-			tv, ok := pkg.GetTypesInfo().Types[n]
83568-			if !ok {
83569-				return visit(nil) // pop stack, don't descend
83570-			}
83571-			if _, ok := Deref(tv.Type).Underlying().(*types.Struct); ok {
83572-				if n.Type != nil {
83573-					ast.Inspect(n.Type, visit)
83574-				}
83575-				for _, elt := range n.Elts {
83576-					if kv, ok := elt.(*ast.KeyValueExpr); ok {
83577-						ast.Inspect(kv.Value, visit)
83578-					} else {
83579-						ast.Inspect(elt, visit)
83580-					}
83581-				}
83582-				return visit(nil) // pop stack, don't descend
83583-			}
83584-		}
83585-		return true
83586-	}
83587-
83588-	for _, f := range pkg.GetSyntax() {
83589-		ast.Inspect(f, visit)
83590-		if len(stack) != 0 {
83591-			panic(stack)
83592-		}
83593-		if !ok {
83594-			break
83595-		}
83596-	}
83597-	return ok
83598-}
83599-
83600-// enclosingBlock returns the innermost block enclosing the specified
83601-// AST node, specified in the form of a path from the root of the file,
83602-// [file...n].
83603-func enclosingBlock(info *types.Info, stack []ast.Node) *types.Scope {
83604-	for i := range stack {
83605-		n := stack[len(stack)-1-i]
83606-		// For some reason, go/types always associates a
83607-		// function's scope with its FuncType.
83608-		// TODO(adonovan): feature or a bug?
83609-		switch f := n.(type) {
83610-		case *ast.FuncDecl:
83611-			n = f.Type
83612-		case *ast.FuncLit:
83613-			n = f.Type
83614-		}
83615-		if b := info.Scopes[n]; b != nil {
83616-			return b
83617-		}
83618-	}
83619-	panic("no Scope for *ast.File")
83620-}
83621-
83622-func (r *renamer) checkLabel(label *types.Label) {
83623-	// Check there are no identical labels in the function's label block.
83624-	// (Label blocks don't nest, so this is easy.)
83625-	if prev := label.Parent().Lookup(r.to); prev != nil {
83626-		r.errorf(label.Pos(), "renaming this label %q to %q", label.Name(), prev.Name())
83627-		r.errorf(prev.Pos(), "\twould conflict with this one")
83628-	}
83629-}
83630-
83631-// checkStructField checks that the field renaming will not cause
83632-// conflicts at its declaration, or ambiguity or changes to any selection.
83633-func (r *renamer) checkStructField(from *types.Var) {
83634-	// Check that the struct declaration is free of field conflicts,
83635-	// and field/method conflicts.
83636-
83637-	// go/types offers no easy way to get from a field (or interface
83638-	// method) to its declaring struct (or interface), so we must
83639-	// ascend the AST.
83640-	pgf, ok := enclosingFile(r.pkg, from.Pos())
83641-	if !ok {
83642-		return // not declared by syntax of this package
83643-	}
83644-	path, _ := astutil.PathEnclosingInterval(pgf.File, from.Pos(), from.Pos())
83645-	// path matches this pattern:
83646-	// [Ident SelectorExpr? StarExpr? Field FieldList StructType ParenExpr* ... File]
83647-
83648-	// Ascend to FieldList.
83649-	var i int
83650-	for {
83651-		if _, ok := path[i].(*ast.FieldList); ok {
83652-			break
83653-		}
83654-		i++
83655-	}
83656-	i++
83657-	tStruct := path[i].(*ast.StructType)
83658-	i++
83659-	// Ascend past parens (unlikely).
83660-	for {
83661-		_, ok := path[i].(*ast.ParenExpr)
83662-		if !ok {
83663-			break
83664-		}
83665-		i++
83666-	}
83667-	if spec, ok := path[i].(*ast.TypeSpec); ok {
83668-		// This struct is also a named type.
83669-		// We must check for direct (non-promoted) field/field
83670-		// and method/field conflicts.
83671-		named := r.pkg.GetTypesInfo().Defs[spec.Name].Type()
83672-		prev, indices, _ := types.LookupFieldOrMethod(named, true, r.pkg.GetTypes(), r.to)
83673-		if len(indices) == 1 {
83674-			r.errorf(from.Pos(), "renaming this field %q to %q",
83675-				from.Name(), r.to)
83676-			r.errorf(prev.Pos(), "\twould conflict with this %s",
83677-				objectKind(prev))
83678-			return // skip checkSelections to avoid redundant errors
83679-		}
83680-	} else {
83681-		// This struct is not a named type.
83682-		// We need only check for direct (non-promoted) field/field conflicts.
83683-		T := r.pkg.GetTypesInfo().Types[tStruct].Type.Underlying().(*types.Struct)
83684-		for i := 0; i < T.NumFields(); i++ {
83685-			if prev := T.Field(i); prev.Name() == r.to {
83686-				r.errorf(from.Pos(), "renaming this field %q to %q",
83687-					from.Name(), r.to)
83688-				r.errorf(prev.Pos(), "\twould conflict with this field")
83689-				return // skip checkSelections to avoid redundant errors
83690-			}
83691-		}
83692-	}
83693-
83694-	// Renaming an anonymous field requires renaming the type too. e.g.
83695-	// 	print(s.T)       // if we rename T to U,
83696-	// 	type T int       // this and
83697-	// 	var s struct {T} // this must change too.
83698-	if from.Anonymous() {
83699-		if named, ok := from.Type().(*types.Named); ok {
83700-			r.check(named.Obj())
83701-		} else if named, ok := Deref(from.Type()).(*types.Named); ok {
83702-			r.check(named.Obj())
83703-		}
83704-	}
83705-
83706-	// Check integrity of existing (field and method) selections.
83707-	r.checkSelections(from)
83708-}
83709-
83710-// checkSelections checks that all uses and selections that resolve to
83711-// the specified object would continue to do so after the renaming.
83712-func (r *renamer) checkSelections(from types.Object) {
83713-	pkg := r.pkg
83714-	typ := pkg.GetTypes()
83715-	{
83716-		if id := someUse(pkg.GetTypesInfo(), from); id != nil {
83717-			if !r.checkExport(id, typ, from) {
83718-				return
83719-			}
83720-		}
83721-
83722-		for syntax, sel := range pkg.GetTypesInfo().Selections {
83723-			// There may be extant selections of only the old
83724-			// name or only the new name, so we must check both.
83725-			// (If neither, the renaming is sound.)
83726-			//
83727-			// In both cases, we wish to compare the lengths
83728-			// of the implicit field path (Selection.Index)
83729-			// to see if the renaming would change it.
83730-			//
83731-			// If a selection that resolves to 'from', when renamed,
83732-			// would yield a path of the same or shorter length,
83733-			// this indicates ambiguity or a changed referent,
83734-			// analogous to same- or sub-block lexical conflict.
83735-			//
83736-			// If a selection using the name 'to' would
83737-			// yield a path of the same or shorter length,
83738-			// this indicates ambiguity or shadowing,
83739-			// analogous to same- or super-block lexical conflict.
83740-
83741-			// TODO(adonovan): fix: derive from Types[syntax.X].Mode
83742-			// TODO(adonovan): test with pointer, value, addressable value.
83743-			isAddressable := true
83744-
83745-			if sel.Obj() == from {
83746-				if obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), r.to); obj != nil {
83747-					// Renaming this existing selection of
83748-					// 'from' may block access to an existing
83749-					// type member named 'to'.
83750-					delta := len(indices) - len(sel.Index())
83751-					if delta > 0 {
83752-						continue // no ambiguity
83753-					}
83754-					r.selectionConflict(from, delta, syntax, obj)
83755-					return
83756-				}
83757-			} else if sel.Obj().Name() == r.to {
83758-				if obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), from.Name()); obj == from {
83759-					// Renaming 'from' may cause this existing
83760-					// selection of the name 'to' to change
83761-					// its meaning.
83762-					delta := len(indices) - len(sel.Index())
83763-					if delta > 0 {
83764-						continue //  no ambiguity
83765-					}
83766-					r.selectionConflict(from, -delta, syntax, sel.Obj())
83767-					return
83768-				}
83769-			}
83770-		}
83771-	}
83772-}
83773-
83774-func (r *renamer) selectionConflict(from types.Object, delta int, syntax *ast.SelectorExpr, obj types.Object) {
83775-	r.errorf(from.Pos(), "renaming this %s %q to %q",
83776-		objectKind(from), from.Name(), r.to)
83777-
83778-	switch {
83779-	case delta < 0:
83780-		// analogous to sub-block conflict
83781-		r.errorf(syntax.Sel.Pos(),
83782-			"\twould change the referent of this selection")
83783-		r.errorf(obj.Pos(), "\tof this %s", objectKind(obj))
83784-	case delta == 0:
83785-		// analogous to same-block conflict
83786-		r.errorf(syntax.Sel.Pos(),
83787-			"\twould make this reference ambiguous")
83788-		r.errorf(obj.Pos(), "\twith this %s", objectKind(obj))
83789-	case delta > 0:
83790-		// analogous to super-block conflict
83791-		r.errorf(syntax.Sel.Pos(),
83792-			"\twould shadow this selection")
83793-		r.errorf(obj.Pos(), "\tof the %s declared here",
83794-			objectKind(obj))
83795-	}
83796-}
83797-
83798-// checkMethod performs safety checks for renaming a method.
83799-// There are three hazards:
83800-// - declaration conflicts
83801-// - selection ambiguity/changes
83802-// - entailed renamings of assignable concrete/interface types.
83803-//
83804-// We reject renamings initiated at concrete methods if it would
83805-// change the assignability relation.  For renamings of abstract
83806-// methods, we rename all methods transitively coupled to it via
83807-// assignability.
83808-func (r *renamer) checkMethod(from *types.Func) {
83809-	// e.g. error.Error
83810-	if from.Pkg() == nil {
83811-		r.errorf(from.Pos(), "you cannot rename built-in method %s", from)
83812-		return
83813-	}
83814-
83815-	// ASSIGNABILITY: We reject renamings of concrete methods that
83816-	// would break a 'satisfy' constraint; but renamings of abstract
83817-	// methods are allowed to proceed, and we rename affected
83818-	// concrete and abstract methods as necessary.  It is the
83819-	// initial method that determines the policy.
83820-
83821-	// Check for conflict at point of declaration.
83822-	// Check to ensure preservation of assignability requirements.
83823-	R := recv(from).Type()
83824-	if types.IsInterface(R) {
83825-		// Abstract method
83826-
83827-		// declaration
83828-		prev, _, _ := types.LookupFieldOrMethod(R, false, from.Pkg(), r.to)
83829-		if prev != nil {
83830-			r.errorf(from.Pos(), "renaming this interface method %q to %q",
83831-				from.Name(), r.to)
83832-			r.errorf(prev.Pos(), "\twould conflict with this method")
83833-			return
83834-		}
83835-
83836-		// Check all interfaces that embed this one for
83837-		// declaration conflicts too.
83838-		{
83839-			// Start with named interface types (better errors)
83840-			for _, obj := range r.pkg.GetTypesInfo().Defs {
83841-				if obj, ok := obj.(*types.TypeName); ok && types.IsInterface(obj.Type()) {
83842-					f, _, _ := types.LookupFieldOrMethod(
83843-						obj.Type(), false, from.Pkg(), from.Name())
83844-					if f == nil {
83845-						continue
83846-					}
83847-					t, _, _ := types.LookupFieldOrMethod(
83848-						obj.Type(), false, from.Pkg(), r.to)
83849-					if t == nil {
83850-						continue
83851-					}
83852-					r.errorf(from.Pos(), "renaming this interface method %q to %q",
83853-						from.Name(), r.to)
83854-					r.errorf(t.Pos(), "\twould conflict with this method")
83855-					r.errorf(obj.Pos(), "\tin named interface type %q", obj.Name())
83856-				}
83857-			}
83858-
83859-			// Now look at all literal interface types (includes named ones again).
83860-			for e, tv := range r.pkg.GetTypesInfo().Types {
83861-				if e, ok := e.(*ast.InterfaceType); ok {
83862-					_ = e
83863-					_ = tv.Type.(*types.Interface)
83864-					// TODO(adonovan): implement same check as above.
83865-				}
83866-			}
83867-		}
83868-
83869-		// assignability
83870-		//
83871-		// Find the set of concrete or abstract methods directly
83872-		// coupled to abstract method 'from' by some
83873-		// satisfy.Constraint, and rename them too.
83874-		for key := range r.satisfy() {
83875-			// key = (lhs, rhs) where lhs is always an interface.
83876-
83877-			lsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())
83878-			if lsel == nil {
83879-				continue
83880-			}
83881-			rmethods := r.msets.MethodSet(key.RHS)
83882-			rsel := rmethods.Lookup(from.Pkg(), from.Name())
83883-			if rsel == nil {
83884-				continue
83885-			}
83886-
83887-			// If both sides have a method of this name,
83888-			// and one of them is m, the other must be coupled.
83889-			var coupled *types.Func
83890-			switch from {
83891-			case lsel.Obj():
83892-				coupled = rsel.Obj().(*types.Func)
83893-			case rsel.Obj():
83894-				coupled = lsel.Obj().(*types.Func)
83895-			default:
83896-				continue
83897-			}
83898-
83899-			// We must treat concrete-to-interface
83900-			// constraints like an implicit selection C.f of
83901-			// each interface method I.f, and check that the
83902-			// renaming leaves the selection unchanged and
83903-			// unambiguous.
83904-			//
83905-			// Fun fact: the implicit selection of C.f
83906-			// 	type I interface{f()}
83907-			// 	type C struct{I}
83908-			// 	func (C) g()
83909-			//      var _ I = C{} // here
83910-			// yields abstract method I.f.  This can make error
83911-			// messages less than obvious.
83912-			//
83913-			if !types.IsInterface(key.RHS) {
83914-				// The logic below was derived from checkSelections.
83915-
83916-				rtosel := rmethods.Lookup(from.Pkg(), r.to)
83917-				if rtosel != nil {
83918-					rto := rtosel.Obj().(*types.Func)
83919-					delta := len(rsel.Index()) - len(rtosel.Index())
83920-					if delta < 0 {
83921-						continue // no ambiguity
83922-					}
83923-
83924-					// TODO(adonovan): record the constraint's position.
83925-					keyPos := token.NoPos
83926-
83927-					r.errorf(from.Pos(), "renaming this method %q to %q",
83928-						from.Name(), r.to)
83929-					if delta == 0 {
83930-						// analogous to same-block conflict
83931-						r.errorf(keyPos, "\twould make the %s method of %s invoked via interface %s ambiguous",
83932-							r.to, key.RHS, key.LHS)
83933-						r.errorf(rto.Pos(), "\twith (%s).%s",
83934-							recv(rto).Type(), r.to)
83935-					} else {
83936-						// analogous to super-block conflict
83937-						r.errorf(keyPos, "\twould change the %s method of %s invoked via interface %s",
83938-							r.to, key.RHS, key.LHS)
83939-						r.errorf(coupled.Pos(), "\tfrom (%s).%s",
83940-							recv(coupled).Type(), r.to)
83941-						r.errorf(rto.Pos(), "\tto (%s).%s",
83942-							recv(rto).Type(), r.to)
83943-					}
83944-					return // one error is enough
83945-				}
83946-			}
83947-
83948-			if !r.changeMethods {
83949-				// This should be unreachable.
83950-				r.errorf(from.Pos(), "internal error: during renaming of abstract method %s", from)
83951-				r.errorf(coupled.Pos(), "\tchangedMethods=false, coupled method=%s", coupled)
83952-				r.errorf(from.Pos(), "\tPlease file a bug report")
83953-				return
83954-			}
83955-
83956-			// Rename the coupled method to preserve assignability.
83957-			r.check(coupled)
83958-		}
83959-	} else {
83960-		// Concrete method
83961-
83962-		// declaration
83963-		prev, indices, _ := types.LookupFieldOrMethod(R, true, from.Pkg(), r.to)
83964-		if prev != nil && len(indices) == 1 {
83965-			r.errorf(from.Pos(), "renaming this method %q to %q",
83966-				from.Name(), r.to)
83967-			r.errorf(prev.Pos(), "\twould conflict with this %s",
83968-				objectKind(prev))
83969-			return
83970-		}
83971-
83972-		// assignability
83973-		//
83974-		// Find the set of abstract methods coupled to concrete
83975-		// method 'from' by some satisfy.Constraint, and rename
83976-		// them too.
83977-		//
83978-		// Coupling may be indirect, e.g. I.f <-> C.f via type D.
83979-		//
83980-		// 	type I interface {f()}
83981-		//	type C int
83982-		//	type (C) f()
83983-		//	type D struct{C}
83984-		//	var _ I = D{}
83985-		//
83986-		for key := range r.satisfy() {
83987-			// key = (lhs, rhs) where lhs is always an interface.
83988-			if types.IsInterface(key.RHS) {
83989-				continue
83990-			}
83991-			rsel := r.msets.MethodSet(key.RHS).Lookup(from.Pkg(), from.Name())
83992-			if rsel == nil || rsel.Obj() != from {
83993-				continue // rhs does not have the method
83994-			}
83995-			lsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())
83996-			if lsel == nil {
83997-				continue
83998-			}
83999-			imeth := lsel.Obj().(*types.Func)
84000-
84001-			// imeth is the abstract method (e.g. I.f)
84002-			// and key.RHS is the concrete coupling type (e.g. D).
84003-			if !r.changeMethods {
84004-				r.errorf(from.Pos(), "renaming this method %q to %q",
84005-					from.Name(), r.to)
84006-				var pos token.Pos
84007-				var iface string
84008-
84009-				I := recv(imeth).Type()
84010-				if named, ok := I.(*types.Named); ok {
84011-					pos = named.Obj().Pos()
84012-					iface = "interface " + named.Obj().Name()
84013-				} else {
84014-					pos = from.Pos()
84015-					iface = I.String()
84016-				}
84017-				r.errorf(pos, "\twould make %s no longer assignable to %s",
84018-					key.RHS, iface)
84019-				r.errorf(imeth.Pos(), "\t(rename %s.%s if you intend to change both types)",
84020-					I, from.Name())
84021-				return // one error is enough
84022-			}
84023-
84024-			// Rename the coupled interface method to preserve assignability.
84025-			r.check(imeth)
84026-		}
84027-	}
84028-
84029-	// Check integrity of existing (field and method) selections.
84030-	// We skip this if there were errors above, to avoid redundant errors.
84031-	r.checkSelections(from)
84032-}
84033-
84034-func (r *renamer) checkExport(id *ast.Ident, pkg *types.Package, from types.Object) bool {
84035-	// Reject cross-package references if r.to is unexported.
84036-	// (Such references may be qualified identifiers or field/method
84037-	// selections.)
84038-	if !ast.IsExported(r.to) && pkg != from.Pkg() {
84039-		r.errorf(from.Pos(),
84040-			"renaming %q to %q would make it unexported",
84041-			from.Name(), r.to)
84042-		r.errorf(id.Pos(), "\tbreaking references from packages such as %q",
84043-			pkg.Path())
84044-		return false
84045-	}
84046-	return true
84047-}
84048-
84049-// satisfy returns the set of interface satisfaction constraints.
84050-func (r *renamer) satisfy() map[satisfy.Constraint]bool {
84051-	if r.satisfyConstraints == nil {
84052-		// Compute on demand: it's expensive.
84053-		var f satisfy.Finder
84054-		pkg := r.pkg
84055-		{
84056-			// From satisfy.Finder documentation:
84057-			//
84058-			// The package must be free of type errors, and
84059-			// info.{Defs,Uses,Selections,Types} must have been populated by the
84060-			// type-checker.
84061-			//
84062-			// Only proceed if all packages have no errors.
84063-			if pkg.HasParseErrors() || pkg.HasTypeErrors() {
84064-				r.errorf(token.NoPos, // we don't have a position for this error.
84065-					"renaming %q to %q not possible because %q has errors",
84066-					r.from, r.to, pkg.Metadata().PkgPath)
84067-				return nil
84068-			}
84069-			f.Find(pkg.GetTypesInfo(), pkg.GetSyntax())
84070-		}
84071-		r.satisfyConstraints = f.Result
84072-	}
84073-	return r.satisfyConstraints
84074-}
84075-
84076-// -- helpers ----------------------------------------------------------
84077-
84078-// recv returns the method's receiver.
84079-func recv(meth *types.Func) *types.Var {
84080-	return meth.Type().(*types.Signature).Recv()
84081-}
84082-
84083-// someUse returns an arbitrary use of obj within info.
84084-func someUse(info *types.Info, obj types.Object) *ast.Ident {
84085-	for id, o := range info.Uses {
84086-		if o == obj {
84087-			return id
84088-		}
84089-	}
84090-	return nil
84091-}
84092-
84093-func objectKind(obj types.Object) string {
84094-	if obj == nil {
84095-		return "nil object"
84096-	}
84097-	switch obj := obj.(type) {
84098-	case *types.PkgName:
84099-		return "imported package name"
84100-	case *types.TypeName:
84101-		return "type"
84102-	case *types.Var:
84103-		if obj.IsField() {
84104-			return "field"
84105-		}
84106-	case *types.Func:
84107-		if obj.Type().(*types.Signature).Recv() != nil {
84108-			return "method"
84109-		}
84110-	}
84111-	// label, func, var, const
84112-	return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types."))
84113-}
84114-
84115-// NB: for renamings, blank is not considered valid.
84116-func isValidIdentifier(id string) bool {
84117-	if id == "" || id == "_" {
84118-		return false
84119-	}
84120-	for i, r := range id {
84121-		if !isLetter(r) && (i == 0 || !isDigit(r)) {
84122-			return false
84123-		}
84124-	}
84125-	return token.Lookup(id) == token.IDENT
84126-}
84127-
84128-// isLocal reports whether obj is local to some function.
84129-// Precondition: not a struct field or interface method.
84130-func isLocal(obj types.Object) bool {
84131-	// [... 5=stmt 4=func 3=file 2=pkg 1=universe]
84132-	var depth int
84133-	for scope := obj.Parent(); scope != nil; scope = scope.Parent() {
84134-		depth++
84135-	}
84136-	return depth >= 4
84137-}
84138-
84139-func isPackageLevel(obj types.Object) bool {
84140-	if obj == nil {
84141-		return false
84142-	}
84143-	return obj.Pkg().Scope().Lookup(obj.Name()) == obj
84144-}
84145-
84146-// -- Plundered from go/scanner: ---------------------------------------
84147-
84148-func isLetter(ch rune) bool {
84149-	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
84150-}
84151-
84152-func isDigit(ch rune) bool {
84153-	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
84154-}
84155diff -urN a/gopls/internal/lsp/source/rename.go b/gopls/internal/lsp/source/rename.go
84156--- a/gopls/internal/lsp/source/rename.go	2000-01-01 00:00:00.000000000 -0000
84157+++ b/gopls/internal/lsp/source/rename.go	1970-01-01 00:00:00.000000000 +0000
84158@@ -1,1244 +0,0 @@
84159-// Copyright 2019 The Go Authors. All rights reserved.
84160-// Use of this source code is governed by a BSD-style
84161-// license that can be found in the LICENSE file.
84162-
84163-package source
84164-
84165-// TODO(adonovan):
84166-//
84167-// - method of generic concrete type -> arbitrary instances of same
84168-//
84169-// - make satisfy work across packages.
84170-//
84171-// - tests, tests, tests:
84172-//   - play with renamings in the k8s tree.
84173-//   - generics
84174-//   - error cases (e.g. conflicts)
84175-//   - renaming a symbol declared in the module cache
84176-//     (currently proceeds with half of the renaming!)
84177-//   - make sure all tests have both a local and a cross-package analogue.
84178-//   - look at coverage
84179-//   - special cases: embedded fields, interfaces, test variants,
84180-//     function-local things with uppercase names;
84181-//     packages with type errors (currently 'satisfy' rejects them),
84182-//     pakage with missing imports;
84183-//
84184-// - measure performance in k8s.
84185-//
84186-// - The original gorename tool assumed well-typedness, but the gopls feature
84187-//   does no such check (which actually makes it much more useful).
84188-//   Audit to ensure it is safe on ill-typed code.
84189-//
84190-// - Generics support was no doubt buggy before but incrementalization
84191-//   may have exacerbated it. If the problem were just about objects,
84192-//   defs and uses it would be fairly simple, but type assignability
84193-//   comes into play in the 'satisfy' check for method renamings.
84194-//   De-instantiating Vector[int] to Vector[T] changes its type.
84195-//   We need to come up with a theory for the satisfy check that
84196-//   works with generics, and across packages. We currently have no
84197-//   simple way to pass types between packages (think: objectpath for
84198-//   types), though presumably exportdata could be pressed into service.
84199-//
84200-// - FileID-based de-duplication of edits to different URIs for the same file.
84201-
84202-import (
84203-	"context"
84204-	"errors"
84205-	"fmt"
84206-	"go/ast"
84207-	"go/token"
84208-	"go/types"
84209-	"path"
84210-	"path/filepath"
84211-	"regexp"
84212-	"sort"
84213-	"strconv"
84214-	"strings"
84215-
84216-	"golang.org/x/mod/modfile"
84217-	"golang.org/x/tools/go/ast/astutil"
84218-	"golang.org/x/tools/go/types/objectpath"
84219-	"golang.org/x/tools/go/types/typeutil"
84220-	"golang.org/x/tools/gopls/internal/lsp/protocol"
84221-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
84222-	"golang.org/x/tools/gopls/internal/span"
84223-	"golang.org/x/tools/internal/bug"
84224-	"golang.org/x/tools/internal/diff"
84225-	"golang.org/x/tools/internal/event"
84226-	"golang.org/x/tools/internal/typeparams"
84227-	"golang.org/x/tools/refactor/satisfy"
84228-)
84229-
84230-// A renamer holds state of a single call to renameObj, which renames
84231-// an object (or several coupled objects) within a single type-checked
84232-// syntax package.
84233-type renamer struct {
84234-	pkg                Package               // the syntax package in which the renaming is applied
84235-	objsToUpdate       map[types.Object]bool // records progress of calls to check
84236-	hadConflicts       bool
84237-	conflicts          []string
84238-	from, to           string
84239-	satisfyConstraints map[satisfy.Constraint]bool
84240-	msets              typeutil.MethodSetCache
84241-	changeMethods      bool
84242-}
84243-
84244-// A PrepareItem holds the result of a "prepare rename" operation:
84245-// the source range and value of a selected identifier.
84246-type PrepareItem struct {
84247-	Range protocol.Range
84248-	Text  string
84249-}
84250-
84251-// PrepareRename searches for a valid renaming at position pp.
84252-//
84253-// The returned usererr is intended to be displayed to the user to explain why
84254-// the prepare fails. Probably we could eliminate the redundancy in returning
84255-// two errors, but for now this is done defensively.
84256-func PrepareRename(ctx context.Context, snapshot Snapshot, f FileHandle, pp protocol.Position) (_ *PrepareItem, usererr, err error) {
84257-	ctx, done := event.Start(ctx, "source.PrepareRename")
84258-	defer done()
84259-
84260-	// Is the cursor within the package name declaration?
84261-	if pgf, inPackageName, err := parsePackageNameDecl(ctx, snapshot, f, pp); err != nil {
84262-		return nil, err, err
84263-	} else if inPackageName {
84264-		item, err := prepareRenamePackageName(ctx, snapshot, pgf)
84265-		return item, err, err
84266-	}
84267-
84268-	// Ordinary (non-package) renaming.
84269-	//
84270-	// Type-check the current package, locate the reference at the position,
84271-	// validate the object, and report its name and range.
84272-	//
84273-	// TODO(adonovan): in all cases below, we return usererr=nil,
84274-	// which means we return (nil, nil) at the protocol
84275-	// layer. This seems like a bug, or at best an exploitation of
84276-	// knowledge of VSCode-specific behavior. Can we avoid that?
84277-	pkg, pgf, err := PackageForFile(ctx, snapshot, f.URI(), NarrowestPackage)
84278-	if err != nil {
84279-		return nil, nil, err
84280-	}
84281-	pos, err := pgf.PositionPos(pp)
84282-	if err != nil {
84283-		return nil, nil, err
84284-	}
84285-	targets, node, err := objectsAt(pkg.GetTypesInfo(), pgf.File, pos)
84286-	if err != nil {
84287-		return nil, nil, err
84288-	}
84289-	var obj types.Object
84290-	for obj = range targets {
84291-		break // pick one arbitrarily
84292-	}
84293-	if err := checkRenamable(obj); err != nil {
84294-		return nil, nil, err
84295-	}
84296-	rng, err := pgf.NodeRange(node)
84297-	if err != nil {
84298-		return nil, nil, err
84299-	}
84300-	if _, isImport := node.(*ast.ImportSpec); isImport {
84301-		// We're not really renaming the import path.
84302-		rng.End = rng.Start
84303-	}
84304-	return &PrepareItem{
84305-		Range: rng,
84306-		Text:  obj.Name(),
84307-	}, nil, nil
84308-}
84309-
84310-func prepareRenamePackageName(ctx context.Context, snapshot Snapshot, pgf *ParsedGoFile) (*PrepareItem, error) {
84311-	// Does the client support file renaming?
84312-	fileRenameSupported := false
84313-	for _, op := range snapshot.View().Options().SupportedResourceOperations {
84314-		if op == protocol.Rename {
84315-			fileRenameSupported = true
84316-			break
84317-		}
84318-	}
84319-	if !fileRenameSupported {
84320-		return nil, errors.New("can't rename package: LSP client does not support file renaming")
84321-	}
84322-
84323-	// Check validity of the metadata for the file's containing package.
84324-	fileMeta, err := snapshot.MetadataForFile(ctx, pgf.URI)
84325-	if err != nil {
84326-		return nil, err
84327-	}
84328-	if len(fileMeta) == 0 {
84329-		return nil, fmt.Errorf("no packages found for file %q", pgf.URI)
84330-	}
84331-	meta := fileMeta[0]
84332-	if meta.Name == "main" {
84333-		return nil, fmt.Errorf("can't rename package \"main\"")
84334-	}
84335-	if strings.HasSuffix(string(meta.Name), "_test") {
84336-		return nil, fmt.Errorf("can't rename x_test packages")
84337-	}
84338-	if meta.Module == nil {
84339-		return nil, fmt.Errorf("can't rename package: missing module information for package %q", meta.PkgPath)
84340-	}
84341-	if meta.Module.Path == string(meta.PkgPath) {
84342-		return nil, fmt.Errorf("can't rename package: package path %q is the same as module path %q", meta.PkgPath, meta.Module.Path)
84343-	}
84344-
84345-	// Return the location of the package declaration.
84346-	rng, err := pgf.NodeRange(pgf.File.Name)
84347-	if err != nil {
84348-		return nil, err
84349-	}
84350-	return &PrepareItem{
84351-		Range: rng,
84352-		Text:  string(meta.Name),
84353-	}, nil
84354-}
84355-
84356-func checkRenamable(obj types.Object) error {
84357-	switch obj := obj.(type) {
84358-	case *types.Var:
84359-		if obj.Embedded() {
84360-			return fmt.Errorf("can't rename embedded fields: rename the type directly or name the field")
84361-		}
84362-	case *types.Builtin, *types.Nil:
84363-		return fmt.Errorf("%s is built in and cannot be renamed", obj.Name())
84364-	}
84365-	if obj.Pkg() == nil || obj.Pkg().Path() == "unsafe" {
84366-		// e.g. error.Error, unsafe.Pointer
84367-		return fmt.Errorf("%s is built in and cannot be renamed", obj.Name())
84368-	}
84369-	if obj.Name() == "_" {
84370-		return errors.New("can't rename \"_\"")
84371-	}
84372-	return nil
84373-}
84374-
84375-// Rename returns a map of TextEdits for each file modified when renaming a
84376-// given identifier within a package and a boolean value of true for renaming
84377-// package and false otherwise.
84378-func Rename(ctx context.Context, snapshot Snapshot, f FileHandle, pp protocol.Position, newName string) (map[span.URI][]protocol.TextEdit, bool, error) {
84379-	ctx, done := event.Start(ctx, "source.Rename")
84380-	defer done()
84381-
84382-	if !isValidIdentifier(newName) {
84383-		return nil, false, fmt.Errorf("invalid identifier to rename: %q", newName)
84384-	}
84385-
84386-	// Cursor within package name declaration?
84387-	_, inPackageName, err := parsePackageNameDecl(ctx, snapshot, f, pp)
84388-	if err != nil {
84389-		return nil, false, err
84390-	}
84391-
84392-	var editMap map[span.URI][]diff.Edit
84393-	if inPackageName {
84394-		editMap, err = renamePackageName(ctx, snapshot, f, PackageName(newName))
84395-	} else {
84396-		editMap, err = renameOrdinary(ctx, snapshot, f, pp, newName)
84397-	}
84398-	if err != nil {
84399-		return nil, false, err
84400-	}
84401-
84402-	// Convert edits to protocol form.
84403-	result := make(map[span.URI][]protocol.TextEdit)
84404-	for uri, edits := range editMap {
84405-		// Sort and de-duplicate edits.
84406-		//
84407-		// Overlapping edits may arise in local renamings (due
84408-		// to type switch implicits) and globals ones (due to
84409-		// processing multiple package variants).
84410-		//
84411-		// We assume renaming produces diffs that are all
84412-		// replacements (no adjacent insertions that might
84413-		// become reordered) and that are either identical or
84414-		// non-overlapping.
84415-		diff.SortEdits(edits)
84416-		filtered := edits[:0]
84417-		for i, edit := range edits {
84418-			if i == 0 || edit != filtered[len(filtered)-1] {
84419-				filtered = append(filtered, edit)
84420-			}
84421-		}
84422-		edits = filtered
84423-
84424-		// TODO(adonovan): the logic above handles repeat edits to the
84425-		// same file URI (e.g. as a member of package p and p_test) but
84426-		// is not sufficient to handle file-system level aliasing arising
84427-		// from symbolic or hard links. For that, we should use a
84428-		// robustio-FileID-keyed map.
84429-		// See https://go.dev/cl/457615 for example.
84430-		// This really occurs in practice, e.g. kubernetes has
84431-		// vendor/k8s.io/kubectl -> ../../staging/src/k8s.io/kubectl.
84432-		fh, err := snapshot.GetFile(ctx, uri)
84433-		if err != nil {
84434-			return nil, false, err
84435-		}
84436-		data, err := fh.Read()
84437-		if err != nil {
84438-			return nil, false, err
84439-		}
84440-		m := protocol.NewMapper(uri, data)
84441-		protocolEdits, err := ToProtocolEdits(m, edits)
84442-		if err != nil {
84443-			return nil, false, err
84444-		}
84445-		result[uri] = protocolEdits
84446-	}
84447-
84448-	return result, inPackageName, nil
84449-}
84450-
84451-// renameOrdinary renames an ordinary (non-package) name throughout the workspace.
84452-func renameOrdinary(ctx context.Context, snapshot Snapshot, f FileHandle, pp protocol.Position, newName string) (map[span.URI][]diff.Edit, error) {
84453-	// Type-check the referring package and locate the object(s).
84454-	// We choose the widest variant as, for non-exported
84455-	// identifiers, it is the only package we need.
84456-	pkg, pgf, err := PackageForFile(ctx, snapshot, f.URI(), WidestPackage)
84457-	if err != nil {
84458-		return nil, err
84459-	}
84460-	pos, err := pgf.PositionPos(pp)
84461-	if err != nil {
84462-		return nil, err
84463-	}
84464-	targets, _, err := objectsAt(pkg.GetTypesInfo(), pgf.File, pos)
84465-	if err != nil {
84466-		return nil, err
84467-	}
84468-
84469-	// Pick a representative object arbitrarily.
84470-	// (All share the same name, pos, and kind.)
84471-	var obj types.Object
84472-	for obj = range targets {
84473-		break
84474-	}
84475-	if obj.Name() == newName {
84476-		return nil, fmt.Errorf("old and new names are the same: %s", newName)
84477-	}
84478-	if err := checkRenamable(obj); err != nil {
84479-		return nil, err
84480-	}
84481-
84482-	// Find objectpath, if object is exported ("" otherwise).
84483-	var declObjPath objectpath.Path
84484-	if obj.Exported() {
84485-		// objectpath.For requires the origin of a generic
84486-		// function or type, not an instantiation (a bug?).
84487-		// Unfortunately we can't call {Func,TypeName}.Origin
84488-		// as these are not available in go/types@go1.18.
84489-		// So we take a scenic route.
84490-		switch obj.(type) { // avoid "obj :=" since cases reassign the var
84491-		case *types.TypeName:
84492-			if named, ok := obj.Type().(*types.Named); ok {
84493-				obj = named.Obj()
84494-			}
84495-		case *types.Func:
84496-			obj = funcOrigin(obj.(*types.Func))
84497-		case *types.Var:
84498-			// TODO(adonovan): do vars need the origin treatment too? (issue #58462)
84499-		}
84500-		if path, err := objectpath.For(obj); err == nil {
84501-			declObjPath = path
84502-		}
84503-	}
84504-
84505-	// Nonexported? Search locally.
84506-	if declObjPath == "" {
84507-		var objects []types.Object
84508-		for obj := range targets {
84509-			objects = append(objects, obj)
84510-		}
84511-		editMap, _, err := renameObjects(ctx, snapshot, newName, pkg, objects...)
84512-		return editMap, err
84513-	}
84514-
84515-	// Exported: search globally.
84516-	//
84517-	// For exported package-level var/const/func/type objects, the
84518-	// search scope is just the direct importers.
84519-	//
84520-	// For exported fields and methods, the scope is the
84521-	// transitive rdeps. (The exportedness of the field's struct
84522-	// or method's receiver is irrelevant.)
84523-	transitive := false
84524-	switch obj.(type) {
84525-	case *types.TypeName:
84526-		// Renaming an exported package-level type
84527-		// requires us to inspect all transitive rdeps
84528-		// in the event that the type is embedded.
84529-		//
84530-		// TODO(adonovan): opt: this is conservative
84531-		// but inefficient. Instead, expand the scope
84532-		// of the search only if we actually encounter
84533-		// an embedding of the type, and only then to
84534-		// the rdeps of the embedding package.
84535-		if obj.Parent() == obj.Pkg().Scope() {
84536-			transitive = true
84537-		}
84538-
84539-	case *types.Var:
84540-		if obj.(*types.Var).IsField() {
84541-			transitive = true // field
84542-		}
84543-
84544-		// TODO(adonovan): opt: process only packages that
84545-		// contain a reference (xrefs) to the target field.
84546-
84547-	case *types.Func:
84548-		if obj.Type().(*types.Signature).Recv() != nil {
84549-			transitive = true // method
84550-		}
84551-
84552-		// It's tempting to optimize by skipping
84553-		// packages that don't contain a reference to
84554-		// the method in the xrefs index, but we still
84555-		// need to apply the satisfy check to those
84556-		// packages to find assignment statements that
84557-		// might expands the scope of the renaming.
84558-	}
84559-
84560-	// Type-check all the packages to inspect.
84561-	declURI := span.URIFromPath(pkg.FileSet().File(obj.Pos()).Name())
84562-	pkgs, err := typeCheckReverseDependencies(ctx, snapshot, declURI, transitive)
84563-	if err != nil {
84564-		return nil, err
84565-	}
84566-
84567-	// Apply the renaming to the (initial) object.
84568-	declPkgPath := PackagePath(obj.Pkg().Path())
84569-	return renameExported(ctx, snapshot, pkgs, declPkgPath, declObjPath, newName)
84570-}
84571-
84572-// funcOrigin is a go1.18-portable implementation of (*types.Func).Origin.
84573-func funcOrigin(fn *types.Func) *types.Func {
84574-	// Method?
84575-	if fn.Type().(*types.Signature).Recv() != nil {
84576-		return typeparams.OriginMethod(fn)
84577-	}
84578-
84579-	// Package-level function?
84580-	// (Assume the origin has the same position.)
84581-	gen := fn.Pkg().Scope().Lookup(fn.Name())
84582-	if gen != nil && gen.Pos() == fn.Pos() {
84583-		return gen.(*types.Func)
84584-	}
84585-
84586-	return fn
84587-}
84588-
84589-// typeCheckReverseDependencies returns the type-checked packages for
84590-// the reverse dependencies of all packages variants containing
84591-// file declURI. The packages are in some topological order.
84592-//
84593-// It includes all variants (even intermediate test variants) for the
84594-// purposes of computing reverse dependencies, but discards ITVs for
84595-// the actual renaming work.
84596-//
84597-// (This neglects obscure edge cases where a _test.go file changes the
84598-// selectors used only in an ITV, but life is short. Also sin must be
84599-// punished.)
84600-func typeCheckReverseDependencies(ctx context.Context, snapshot Snapshot, declURI span.URI, transitive bool) ([]Package, error) {
84601-	variants, err := snapshot.MetadataForFile(ctx, declURI)
84602-	if err != nil {
84603-		return nil, err
84604-	}
84605-	allRdeps := make(map[PackageID]*Metadata)
84606-	for _, variant := range variants {
84607-		rdeps, err := snapshot.ReverseDependencies(ctx, variant.ID, transitive)
84608-		if err != nil {
84609-			return nil, err
84610-		}
84611-		allRdeps[variant.ID] = variant // include self
84612-		for id, meta := range rdeps {
84613-			allRdeps[id] = meta
84614-		}
84615-	}
84616-	var ids []PackageID
84617-	for id, meta := range allRdeps {
84618-		if meta.IsIntermediateTestVariant() {
84619-			continue
84620-		}
84621-		ids = append(ids, id)
84622-	}
84623-
84624-	// Sort the packages into some topological order of the
84625-	// (unfiltered) metadata graph.
84626-	SortPostOrder(snapshot, ids)
84627-
84628-	// Dependencies must be visited first since they can expand
84629-	// the search set. Ideally we would process the (filtered) set
84630-	// of packages in the parallel postorder of the snapshot's
84631-	// (unfiltered) metadata graph, but this is quite tricky
84632-	// without a good graph abstraction.
84633-	//
84634-	// For now, we visit packages sequentially in order of
84635-	// ascending height, like an inverted breadth-first search.
84636-	//
84637-	// Type checking is by far the dominant cost, so
84638-	// overlapping it with renaming may not be worthwhile.
84639-	return snapshot.TypeCheck(ctx, ids...)
84640-}
84641-
84642-// SortPostOrder sorts the IDs so that if x depends on y, then y appears before x.
84643-func SortPostOrder(meta MetadataSource, ids []PackageID) {
84644-	postorder := make(map[PackageID]int)
84645-	order := 0
84646-	var visit func(PackageID)
84647-	visit = func(id PackageID) {
84648-		if _, ok := postorder[id]; !ok {
84649-			postorder[id] = -1 // break recursion
84650-			if m := meta.Metadata(id); m != nil {
84651-				for _, depID := range m.DepsByPkgPath {
84652-					visit(depID)
84653-				}
84654-			}
84655-			order++
84656-			postorder[id] = order
84657-		}
84658-	}
84659-	for _, id := range ids {
84660-		visit(id)
84661-	}
84662-	sort.Slice(ids, func(i, j int) bool {
84663-		return postorder[ids[i]] < postorder[ids[j]]
84664-	})
84665-}
84666-
84667-// renameExported renames the object denoted by (pkgPath, objPath)
84668-// within the specified packages, along with any other objects that
84669-// must be renamed as a consequence. The slice of packages must be
84670-// topologically ordered.
84671-func renameExported(ctx context.Context, snapshot Snapshot, pkgs []Package, declPkgPath PackagePath, declObjPath objectpath.Path, newName string) (map[span.URI][]diff.Edit, error) {
84672-
84673-	// A target is a name for an object that is stable across types.Packages.
84674-	type target struct {
84675-		pkg PackagePath
84676-		obj objectpath.Path
84677-	}
84678-
84679-	// Populate the initial set of target objects.
84680-	// This set may grow as we discover the consequences of each renaming.
84681-	//
84682-	// TODO(adonovan): strictly, each cone of reverse dependencies
84683-	// of a single variant should have its own target map that
84684-	// monotonically expands as we go up the import graph, because
84685-	// declarations in test files can alter the set of
84686-	// package-level names and change the meaning of field and
84687-	// method selectors. So if we parallelize the graph
84688-	// visitation (see above), we should also compute the targets
84689-	// as a union of dependencies.
84690-	//
84691-	// Or we could decide that the logic below is fast enough not
84692-	// to need parallelism. In small measurements so far the
84693-	// type-checking step is about 95% and the renaming only 5%.
84694-	targets := map[target]bool{{declPkgPath, declObjPath}: true}
84695-
84696-	// Apply the renaming operation to each package.
84697-	allEdits := make(map[span.URI][]diff.Edit)
84698-	for _, pkg := range pkgs {
84699-
84700-		// Resolved target objects within package pkg.
84701-		var objects []types.Object
84702-		for t := range targets {
84703-			p := pkg.DependencyTypes(t.pkg)
84704-			if p == nil {
84705-				continue // indirect dependency of no consequence
84706-			}
84707-			obj, err := objectpath.Object(p, t.obj)
84708-			if err != nil {
84709-				// Though this can happen with regular export data
84710-				// due to trimming of inconsequential objects,
84711-				// it can't happen if we load dependencies from full
84712-				// syntax (as today) or shallow export data (soon),
84713-				// as both are complete.
84714-				bug.Reportf("objectpath.Object(%v, %v) failed: %v", p, t.obj, err)
84715-				continue
84716-			}
84717-			objects = append(objects, obj)
84718-		}
84719-		if len(objects) == 0 {
84720-			continue // no targets of consequence to this package
84721-		}
84722-
84723-		// Apply the renaming.
84724-		editMap, moreObjects, err := renameObjects(ctx, snapshot, newName, pkg, objects...)
84725-		if err != nil {
84726-			return nil, err
84727-		}
84728-
84729-		// It is safe to concatenate the edits as they are non-overlapping
84730-		// (or identical, in which case they will be de-duped by Rename).
84731-		for uri, edits := range editMap {
84732-			allEdits[uri] = append(allEdits[uri], edits...)
84733-		}
84734-
84735-		// Expand the search set?
84736-		for obj := range moreObjects {
84737-			objpath, err := objectpath.For(obj)
84738-			if err != nil {
84739-				continue // not exported
84740-			}
84741-			target := target{PackagePath(obj.Pkg().Path()), objpath}
84742-			targets[target] = true
84743-
84744-			// TODO(adonovan): methods requires dynamic
84745-			// programming of the product targets x
84746-			// packages as any package might add a new
84747-			// target (from a foward dep) as a
84748-			// consequence, and any target might imply a
84749-			// new set of rdeps. See golang/go#58461.
84750-		}
84751-	}
84752-
84753-	return allEdits, nil
84754-}
84755-
84756-// renamePackageName renames package declarations, imports, and go.mod files.
84757-func renamePackageName(ctx context.Context, s Snapshot, f FileHandle, newName PackageName) (map[span.URI][]diff.Edit, error) {
84758-	// Rename the package decl and all imports.
84759-	renamingEdits, err := renamePackage(ctx, s, f, newName)
84760-	if err != nil {
84761-		return nil, err
84762-	}
84763-
84764-	// Update the last component of the file's enclosing directory.
84765-	oldBase := filepath.Dir(f.URI().Filename())
84766-	newPkgDir := filepath.Join(filepath.Dir(oldBase), string(newName))
84767-
84768-	// Update any affected replace directives in go.mod files.
84769-	// TODO(adonovan): extract into its own function.
84770-	//
84771-	// TODO: should this operate on all go.mod files, irrespective of whether they are included in the workspace?
84772-	// Get all active mod files in the workspace
84773-	modFiles := s.ModFiles()
84774-	for _, m := range modFiles {
84775-		fh, err := s.GetFile(ctx, m)
84776-		if err != nil {
84777-			return nil, err
84778-		}
84779-		pm, err := s.ParseMod(ctx, fh)
84780-		if err != nil {
84781-			return nil, err
84782-		}
84783-
84784-		modFileDir := filepath.Dir(pm.URI.Filename())
84785-		affectedReplaces := []*modfile.Replace{}
84786-
84787-		// Check if any replace directives need to be fixed
84788-		for _, r := range pm.File.Replace {
84789-			if !strings.HasPrefix(r.New.Path, "/") && !strings.HasPrefix(r.New.Path, "./") && !strings.HasPrefix(r.New.Path, "../") {
84790-				continue
84791-			}
84792-
84793-			replacedPath := r.New.Path
84794-			if strings.HasPrefix(r.New.Path, "./") || strings.HasPrefix(r.New.Path, "../") {
84795-				replacedPath = filepath.Join(modFileDir, r.New.Path)
84796-			}
84797-
84798-			// TODO: Is there a risk of converting a '\' delimited replacement to a '/' delimited replacement?
84799-			if !strings.HasPrefix(filepath.ToSlash(replacedPath)+"/", filepath.ToSlash(oldBase)+"/") {
84800-				continue // not affected by the package renaming
84801-			}
84802-
84803-			affectedReplaces = append(affectedReplaces, r)
84804-		}
84805-
84806-		if len(affectedReplaces) == 0 {
84807-			continue
84808-		}
84809-		copied, err := modfile.Parse("", pm.Mapper.Content, nil)
84810-		if err != nil {
84811-			return nil, err
84812-		}
84813-
84814-		for _, r := range affectedReplaces {
84815-			replacedPath := r.New.Path
84816-			if strings.HasPrefix(r.New.Path, "./") || strings.HasPrefix(r.New.Path, "../") {
84817-				replacedPath = filepath.Join(modFileDir, r.New.Path)
84818-			}
84819-
84820-			suffix := strings.TrimPrefix(replacedPath, string(oldBase))
84821-
84822-			newReplacedPath, err := filepath.Rel(modFileDir, newPkgDir+suffix)
84823-			if err != nil {
84824-				return nil, err
84825-			}
84826-
84827-			newReplacedPath = filepath.ToSlash(newReplacedPath)
84828-
84829-			if !strings.HasPrefix(newReplacedPath, "/") && !strings.HasPrefix(newReplacedPath, "../") {
84830-				newReplacedPath = "./" + newReplacedPath
84831-			}
84832-
84833-			if err := copied.AddReplace(r.Old.Path, "", newReplacedPath, ""); err != nil {
84834-				return nil, err
84835-			}
84836-		}
84837-
84838-		copied.Cleanup()
84839-		newContent, err := copied.Format()
84840-		if err != nil {
84841-			return nil, err
84842-		}
84843-
84844-		// Calculate the edits to be made due to the change.
84845-		edits := s.View().Options().ComputeEdits(string(pm.Mapper.Content), string(newContent))
84846-		renamingEdits[pm.URI] = append(renamingEdits[pm.URI], edits...)
84847-	}
84848-
84849-	return renamingEdits, nil
84850-}
84851-
84852-// renamePackage computes all workspace edits required to rename the package
84853-// described by the given metadata, to newName, by renaming its package
84854-// directory.
84855-//
84856-// It updates package clauses and import paths for the renamed package as well
84857-// as any other packages affected by the directory renaming among packages
84858-// described by allMetadata.
84859-func renamePackage(ctx context.Context, s Snapshot, f FileHandle, newName PackageName) (map[span.URI][]diff.Edit, error) {
84860-	if strings.HasSuffix(string(newName), "_test") {
84861-		return nil, fmt.Errorf("cannot rename to _test package")
84862-	}
84863-
84864-	// We need metadata for the relevant package and module paths.
84865-	// These should be the same for all packages containing the file.
84866-	metas, err := s.MetadataForFile(ctx, f.URI())
84867-	if err != nil {
84868-		return nil, err
84869-	}
84870-	if len(metas) == 0 {
84871-		return nil, fmt.Errorf("no packages found for file %q", f.URI())
84872-	}
84873-	meta := metas[0] // narrowest
84874-
84875-	oldPkgPath := meta.PkgPath
84876-	if meta.Module == nil {
84877-		return nil, fmt.Errorf("cannot rename package: missing module information for package %q", meta.PkgPath)
84878-	}
84879-	modulePath := PackagePath(meta.Module.Path)
84880-	if modulePath == oldPkgPath {
84881-		return nil, fmt.Errorf("cannot rename package: module path %q is the same as the package path, so renaming the package directory would have no effect", modulePath)
84882-	}
84883-
84884-	newPathPrefix := path.Join(path.Dir(string(oldPkgPath)), string(newName))
84885-
84886-	// We must inspect all packages, not just direct importers,
84887-	// because we also rename subpackages, which may be unrelated.
84888-	// (If the renamed package imports a subpackage it may require
84889-	// edits to both its package and import decls.)
84890-	allMetadata, err := s.AllMetadata(ctx)
84891-	if err != nil {
84892-		return nil, err
84893-	}
84894-
84895-	// Rename package and import declarations in all relevant packages.
84896-	edits := make(map[span.URI][]diff.Edit)
84897-	for _, m := range allMetadata {
84898-		// Special case: x_test packages for the renamed package will not have the
84899-		// package path as as a dir prefix, but still need their package clauses
84900-		// renamed.
84901-		if m.PkgPath == oldPkgPath+"_test" {
84902-			if err := renamePackageClause(ctx, m, s, newName+"_test", edits); err != nil {
84903-				return nil, err
84904-			}
84905-			continue
84906-		}
84907-
84908-		// Subtle: check this condition before checking for valid module info
84909-		// below, because we should not fail this operation if unrelated packages
84910-		// lack module info.
84911-		if !strings.HasPrefix(string(m.PkgPath)+"/", string(oldPkgPath)+"/") {
84912-			continue // not affected by the package renaming
84913-		}
84914-
84915-		if m.Module == nil {
84916-			// This check will always fail under Bazel.
84917-			return nil, fmt.Errorf("cannot rename package: missing module information for package %q", m.PkgPath)
84918-		}
84919-
84920-		if modulePath != PackagePath(m.Module.Path) {
84921-			continue // don't edit imports if nested package and renaming package have different module paths
84922-		}
84923-
84924-		// Renaming a package consists of changing its import path and package name.
84925-		suffix := strings.TrimPrefix(string(m.PkgPath), string(oldPkgPath))
84926-		newPath := newPathPrefix + suffix
84927-
84928-		pkgName := m.Name
84929-		if m.PkgPath == oldPkgPath {
84930-			pkgName = PackageName(newName)
84931-
84932-			if err := renamePackageClause(ctx, m, s, newName, edits); err != nil {
84933-				return nil, err
84934-			}
84935-		}
84936-
84937-		imp := ImportPath(newPath) // TODO(adonovan): what if newPath has vendor/ prefix?
84938-		if err := renameImports(ctx, s, m, imp, pkgName, edits); err != nil {
84939-			return nil, err
84940-		}
84941-	}
84942-
84943-	return edits, nil
84944-}
84945-
84946-// renamePackageClause computes edits renaming the package clause of files in
84947-// the package described by the given metadata, to newName.
84948-//
84949-// Edits are written into the edits map.
84950-func renamePackageClause(ctx context.Context, m *Metadata, snapshot Snapshot, newName PackageName, edits map[span.URI][]diff.Edit) error {
84951-	// Rename internal references to the package in the renaming package.
84952-	for _, uri := range m.CompiledGoFiles {
84953-		fh, err := snapshot.GetFile(ctx, uri)
84954-		if err != nil {
84955-			return err
84956-		}
84957-		f, err := snapshot.ParseGo(ctx, fh, ParseHeader)
84958-		if err != nil {
84959-			return err
84960-		}
84961-		if f.File.Name == nil {
84962-			continue // no package declaration
84963-		}
84964-
84965-		edit, err := posEdit(f.Tok, f.File.Name.Pos(), f.File.Name.End(), string(newName))
84966-		if err != nil {
84967-			return err
84968-		}
84969-		edits[f.URI] = append(edits[f.URI], edit)
84970-	}
84971-
84972-	return nil
84973-}
84974-
84975-// renameImports computes the set of edits to imports resulting from renaming
84976-// the package described by the given metadata, to a package with import path
84977-// newPath and name newName.
84978-//
84979-// Edits are written into the edits map.
84980-func renameImports(ctx context.Context, snapshot Snapshot, m *Metadata, newPath ImportPath, newName PackageName, allEdits map[span.URI][]diff.Edit) error {
84981-	rdeps, err := snapshot.ReverseDependencies(ctx, m.ID, false) // find direct importers
84982-	if err != nil {
84983-		return err
84984-	}
84985-
84986-	// Pass 1: rename import paths in import declarations.
84987-	needsTypeCheck := make(map[PackageID][]span.URI)
84988-	for _, rdep := range rdeps {
84989-		if rdep.IsIntermediateTestVariant() {
84990-			continue // for renaming, these variants are redundant
84991-		}
84992-
84993-		for _, uri := range rdep.CompiledGoFiles {
84994-			fh, err := snapshot.GetFile(ctx, uri)
84995-			if err != nil {
84996-				return err
84997-			}
84998-			f, err := snapshot.ParseGo(ctx, fh, ParseHeader)
84999-			if err != nil {
85000-				return err
85001-			}
85002-			if f.File.Name == nil {
85003-				continue // no package declaration
85004-			}
85005-			for _, imp := range f.File.Imports {
85006-				if rdep.DepsByImpPath[UnquoteImportPath(imp)] != m.ID {
85007-					continue // not the import we're looking for
85008-				}
85009-
85010-				// If the import does not explicitly specify
85011-				// a local name, then we need to invoke the
85012-				// type checker to locate references to update.
85013-				//
85014-				// TODO(adonovan): is this actually true?
85015-				// Renaming an import with a local name can still
85016-				// cause conflicts: shadowing of built-ins, or of
85017-				// package-level decls in the same or another file.
85018-				if imp.Name == nil {
85019-					needsTypeCheck[rdep.ID] = append(needsTypeCheck[rdep.ID], uri)
85020-				}
85021-
85022-				// Create text edit for the import path (string literal).
85023-				edit, err := posEdit(f.Tok, imp.Path.Pos(), imp.Path.End(), strconv.Quote(string(newPath)))
85024-				if err != nil {
85025-					return err
85026-				}
85027-				allEdits[uri] = append(allEdits[uri], edit)
85028-			}
85029-		}
85030-	}
85031-
85032-	// If the imported package's name hasn't changed,
85033-	// we don't need to rename references within each file.
85034-	if newName == m.Name {
85035-		return nil
85036-	}
85037-
85038-	// Pass 2: rename local name (types.PkgName) of imported
85039-	// package throughout one or more files of the package.
85040-	ids := make([]PackageID, 0, len(needsTypeCheck))
85041-	for id := range needsTypeCheck {
85042-		ids = append(ids, id)
85043-	}
85044-	pkgs, err := snapshot.TypeCheck(ctx, ids...)
85045-	if err != nil {
85046-		return err
85047-	}
85048-	for i, id := range ids {
85049-		pkg := pkgs[i]
85050-		for _, uri := range needsTypeCheck[id] {
85051-			f, err := pkg.File(uri)
85052-			if err != nil {
85053-				return err
85054-			}
85055-			for _, imp := range f.File.Imports {
85056-				if imp.Name != nil {
85057-					continue // has explicit local name
85058-				}
85059-				if rdeps[id].DepsByImpPath[UnquoteImportPath(imp)] != m.ID {
85060-					continue // not the import we're looking for
85061-				}
85062-
85063-				pkgname := pkg.GetTypesInfo().Implicits[imp].(*types.PkgName)
85064-
85065-				pkgScope := pkg.GetTypes().Scope()
85066-				fileScope := pkg.GetTypesInfo().Scopes[f.File]
85067-
85068-				localName := string(newName)
85069-				try := 0
85070-
85071-				// Keep trying with fresh names until one succeeds.
85072-				//
85073-				// TODO(adonovan): fix: this loop is not sufficient to choose a name
85074-				// that is guaranteed to be conflict-free; renameObj may still fail.
85075-				// So the retry loop should be around renameObj, and we shouldn't
85076-				// bother with scopes here.
85077-				for fileScope.Lookup(localName) != nil || pkgScope.Lookup(localName) != nil {
85078-					try++
85079-					localName = fmt.Sprintf("%s%d", newName, try)
85080-				}
85081-
85082-				// renameObj detects various conflicts, including:
85083-				// - new name conflicts with a package-level decl in this file;
85084-				// - new name hides a package-level decl in another file that
85085-				//   is actually referenced in this file;
85086-				// - new name hides a built-in that is actually referenced
85087-				//   in this file;
85088-				// - a reference in this file to the old package name would
85089-				//   become shadowed by an intervening declaration that
85090-				//   uses the new name.
85091-				// It returns the edits if no conflict was detected.
85092-				editMap, _, err := renameObjects(ctx, snapshot, localName, pkg, pkgname)
85093-				if err != nil {
85094-					return err
85095-				}
85096-
85097-				// If the chosen local package name matches the package's
85098-				// new name, delete the change that would have inserted
85099-				// an explicit local name, which is always the lexically
85100-				// first change.
85101-				if localName == string(newName) {
85102-					edits, ok := editMap[uri]
85103-					if !ok {
85104-						return fmt.Errorf("internal error: no changes for %s", uri)
85105-					}
85106-					diff.SortEdits(edits)
85107-					editMap[uri] = edits[1:]
85108-				}
85109-				for uri, edits := range editMap {
85110-					allEdits[uri] = append(allEdits[uri], edits...)
85111-				}
85112-			}
85113-		}
85114-	}
85115-	return nil
85116-}
85117-
85118-// renameObjects computes the edits to the type-checked syntax package pkg
85119-// required to rename a set of target objects to newName.
85120-//
85121-// It also returns the set of objects that were found (due to
85122-// corresponding methods and embedded fields) to require renaming as a
85123-// consequence of the requested renamings.
85124-//
85125-// It returns an error if the renaming would cause a conflict.
85126-func renameObjects(ctx context.Context, snapshot Snapshot, newName string, pkg Package, targets ...types.Object) (map[span.URI][]diff.Edit, map[types.Object]bool, error) {
85127-	r := renamer{
85128-		pkg:          pkg,
85129-		objsToUpdate: make(map[types.Object]bool),
85130-		from:         targets[0].Name(),
85131-		to:           newName,
85132-	}
85133-
85134-	// A renaming initiated at an interface method indicates the
85135-	// intention to rename abstract and concrete methods as needed
85136-	// to preserve assignability.
85137-	// TODO(adonovan): pull this into the caller.
85138-	for _, obj := range targets {
85139-		if obj, ok := obj.(*types.Func); ok {
85140-			recv := obj.Type().(*types.Signature).Recv()
85141-			if recv != nil && types.IsInterface(recv.Type().Underlying()) {
85142-				r.changeMethods = true
85143-				break
85144-			}
85145-		}
85146-	}
85147-
85148-	// Check that the renaming of the identifier is ok.
85149-	for _, obj := range targets {
85150-		r.check(obj)
85151-		if len(r.conflicts) > 0 {
85152-			// Stop at first error.
85153-			return nil, nil, fmt.Errorf("%s", strings.Join(r.conflicts, "\n"))
85154-		}
85155-	}
85156-
85157-	editMap, err := r.update()
85158-	if err != nil {
85159-		return nil, nil, err
85160-	}
85161-
85162-	// Remove initial targets so that only 'consequences' remain.
85163-	for _, obj := range targets {
85164-		delete(r.objsToUpdate, obj)
85165-	}
85166-	return editMap, r.objsToUpdate, nil
85167-}
85168-
85169-// Rename all references to the target objects.
85170-func (r *renamer) update() (map[span.URI][]diff.Edit, error) {
85171-	result := make(map[span.URI][]diff.Edit)
85172-
85173-	// shouldUpdate reports whether obj is one of (or an
85174-	// instantiation of one of) the target objects.
85175-	shouldUpdate := func(obj types.Object) bool {
85176-		if r.objsToUpdate[obj] {
85177-			return true
85178-		}
85179-		if fn, ok := obj.(*types.Func); ok && r.objsToUpdate[funcOrigin(fn)] {
85180-			return true
85181-		}
85182-		return false
85183-	}
85184-
85185-	// Find all identifiers in the package that define or use a
85186-	// renamed object. We iterate over info as it is more efficent
85187-	// than calling ast.Inspect for each of r.pkg.CompiledGoFiles().
85188-	type item struct {
85189-		node  ast.Node // Ident, ImportSpec (obj=PkgName), or CaseClause (obj=Var)
85190-		obj   types.Object
85191-		isDef bool
85192-	}
85193-	var items []item
85194-	info := r.pkg.GetTypesInfo()
85195-	for id, obj := range info.Uses {
85196-		if shouldUpdate(obj) {
85197-			items = append(items, item{id, obj, false})
85198-		}
85199-	}
85200-	for id, obj := range info.Defs {
85201-		if shouldUpdate(obj) {
85202-			items = append(items, item{id, obj, true})
85203-		}
85204-	}
85205-	for node, obj := range info.Implicits {
85206-		if shouldUpdate(obj) {
85207-			switch node.(type) {
85208-			case *ast.ImportSpec, *ast.CaseClause:
85209-				items = append(items, item{node, obj, true})
85210-			}
85211-		}
85212-	}
85213-	sort.Slice(items, func(i, j int) bool {
85214-		return items[i].node.Pos() < items[j].node.Pos()
85215-	})
85216-
85217-	// Update each identifier.
85218-	for _, item := range items {
85219-		pgf, ok := enclosingFile(r.pkg, item.node.Pos())
85220-		if !ok {
85221-			bug.Reportf("edit does not belong to syntax of package %q", r.pkg)
85222-			continue
85223-		}
85224-
85225-		// Renaming a types.PkgName may result in the addition or removal of an identifier,
85226-		// so we deal with this separately.
85227-		if pkgName, ok := item.obj.(*types.PkgName); ok && item.isDef {
85228-			edit, err := r.updatePkgName(pgf, pkgName)
85229-			if err != nil {
85230-				return nil, err
85231-			}
85232-			result[pgf.URI] = append(result[pgf.URI], edit)
85233-			continue
85234-		}
85235-
85236-		// Workaround the unfortunate lack of a Var object
85237-		// for x in "switch x := expr.(type) {}" by adjusting
85238-		// the case clause to the switch ident.
85239-		// This may result in duplicate edits, but we de-dup later.
85240-		if _, ok := item.node.(*ast.CaseClause); ok {
85241-			path, _ := astutil.PathEnclosingInterval(pgf.File, item.obj.Pos(), item.obj.Pos())
85242-			item.node = path[0].(*ast.Ident)
85243-		}
85244-
85245-		// Replace the identifier with r.to.
85246-		edit, err := posEdit(pgf.Tok, item.node.Pos(), item.node.End(), r.to)
85247-		if err != nil {
85248-			return nil, err
85249-		}
85250-
85251-		result[pgf.URI] = append(result[pgf.URI], edit)
85252-
85253-		if !item.isDef { // uses do not have doc comments to update.
85254-			continue
85255-		}
85256-
85257-		doc := docComment(pgf, item.node.(*ast.Ident))
85258-		if doc == nil {
85259-			continue
85260-		}
85261-
85262-		// Perform the rename in doc comments declared in the original package.
85263-		// go/parser strips out \r\n returns from the comment text, so go
85264-		// line-by-line through the comment text to get the correct positions.
85265-		docRegexp := regexp.MustCompile(`\b` + r.from + `\b`) // valid identifier => valid regexp
85266-		for _, comment := range doc.List {
85267-			if isDirective(comment.Text) {
85268-				continue
85269-			}
85270-			// TODO(adonovan): why are we looping over lines?
85271-			// Just run the loop body once over the entire multiline comment.
85272-			lines := strings.Split(comment.Text, "\n")
85273-			tokFile := pgf.Tok
85274-			commentLine := tokFile.Line(comment.Pos())
85275-			uri := span.URIFromPath(tokFile.Name())
85276-			for i, line := range lines {
85277-				lineStart := comment.Pos()
85278-				if i > 0 {
85279-					lineStart = tokFile.LineStart(commentLine + i)
85280-				}
85281-				for _, locs := range docRegexp.FindAllIndex([]byte(line), -1) {
85282-					edit, err := posEdit(tokFile, lineStart+token.Pos(locs[0]), lineStart+token.Pos(locs[1]), r.to)
85283-					if err != nil {
85284-						return nil, err // can't happen
85285-					}
85286-					result[uri] = append(result[uri], edit)
85287-				}
85288-			}
85289-		}
85290-	}
85291-
85292-	return result, nil
85293-}
85294-
85295-// docComment returns the doc for an identifier within the specified file.
85296-func docComment(pgf *ParsedGoFile, id *ast.Ident) *ast.CommentGroup {
85297-	nodes, _ := astutil.PathEnclosingInterval(pgf.File, id.Pos(), id.End())
85298-	for _, node := range nodes {
85299-		switch decl := node.(type) {
85300-		case *ast.FuncDecl:
85301-			return decl.Doc
85302-		case *ast.Field:
85303-			return decl.Doc
85304-		case *ast.GenDecl:
85305-			return decl.Doc
85306-		// For {Type,Value}Spec, if the doc on the spec is absent,
85307-		// search for the enclosing GenDecl
85308-		case *ast.TypeSpec:
85309-			if decl.Doc != nil {
85310-				return decl.Doc
85311-			}
85312-		case *ast.ValueSpec:
85313-			if decl.Doc != nil {
85314-				return decl.Doc
85315-			}
85316-		case *ast.Ident:
85317-		case *ast.AssignStmt:
85318-			// *ast.AssignStmt doesn't have an associated comment group.
85319-			// So, we try to find a comment just before the identifier.
85320-
85321-			// Try to find a comment group only for short variable declarations (:=).
85322-			if decl.Tok != token.DEFINE {
85323-				return nil
85324-			}
85325-
85326-			identLine := pgf.Tok.Line(id.Pos())
85327-			for _, comment := range nodes[len(nodes)-1].(*ast.File).Comments {
85328-				if comment.Pos() > id.Pos() {
85329-					// Comment is after the identifier.
85330-					continue
85331-				}
85332-
85333-				lastCommentLine := pgf.Tok.Line(comment.End())
85334-				if lastCommentLine+1 == identLine {
85335-					return comment
85336-				}
85337-			}
85338-		default:
85339-			return nil
85340-		}
85341-	}
85342-	return nil
85343-}
85344-
85345-// updatePkgName returns the updates to rename a pkgName in the import spec by
85346-// only modifying the package name portion of the import declaration.
85347-func (r *renamer) updatePkgName(pgf *ParsedGoFile, pkgName *types.PkgName) (diff.Edit, error) {
85348-	// Modify ImportSpec syntax to add or remove the Name as needed.
85349-	path, _ := astutil.PathEnclosingInterval(pgf.File, pkgName.Pos(), pkgName.Pos())
85350-	if len(path) < 2 {
85351-		return diff.Edit{}, fmt.Errorf("no path enclosing interval for %s", pkgName.Name())
85352-	}
85353-	spec, ok := path[1].(*ast.ImportSpec)
85354-	if !ok {
85355-		return diff.Edit{}, fmt.Errorf("failed to update PkgName for %s", pkgName.Name())
85356-	}
85357-
85358-	newText := ""
85359-	if pkgName.Imported().Name() != r.to {
85360-		newText = r.to + " "
85361-	}
85362-
85363-	// Replace the portion (possibly empty) of the spec before the path:
85364-	//     local "path"      or      "path"
85365-	//   ->      <-                -><-
85366-	return posEdit(pgf.Tok, spec.Pos(), spec.Path.Pos(), newText)
85367-}
85368-
85369-// parsePackageNameDecl is a convenience function that parses and
85370-// returns the package name declaration of file fh, and reports
85371-// whether the position ppos lies within it.
85372-//
85373-// Note: also used by references2.
85374-func parsePackageNameDecl(ctx context.Context, snapshot Snapshot, fh FileHandle, ppos protocol.Position) (*ParsedGoFile, bool, error) {
85375-	pgf, err := snapshot.ParseGo(ctx, fh, ParseHeader)
85376-	if err != nil {
85377-		return nil, false, err
85378-	}
85379-	// Careful: because we used ParseHeader,
85380-	// pgf.Pos(ppos) may be beyond EOF => (0, err).
85381-	pos, _ := pgf.PositionPos(ppos)
85382-	return pgf, pgf.File.Name.Pos() <= pos && pos <= pgf.File.Name.End(), nil
85383-}
85384-
85385-// enclosingFile returns the CompiledGoFile of pkg that contains the specified position.
85386-func enclosingFile(pkg Package, pos token.Pos) (*ParsedGoFile, bool) {
85387-	for _, pgf := range pkg.CompiledGoFiles() {
85388-		if pgf.File.Pos() <= pos && pos <= pgf.File.End() {
85389-			return pgf, true
85390-		}
85391-	}
85392-	return nil, false
85393-}
85394-
85395-// posEdit returns an edit to replace the (start, end) range of tf with 'new'.
85396-func posEdit(tf *token.File, start, end token.Pos, new string) (diff.Edit, error) {
85397-	startOffset, endOffset, err := safetoken.Offsets(tf, start, end)
85398-	if err != nil {
85399-		return diff.Edit{}, err
85400-	}
85401-	return diff.Edit{Start: startOffset, End: endOffset, New: new}, nil
85402-}
85403diff -urN a/gopls/internal/lsp/source/signature_help.go b/gopls/internal/lsp/source/signature_help.go
85404--- a/gopls/internal/lsp/source/signature_help.go	2000-01-01 00:00:00.000000000 -0000
85405+++ b/gopls/internal/lsp/source/signature_help.go	1970-01-01 00:00:00.000000000 +0000
85406@@ -1,185 +0,0 @@
85407-// Copyright 2018 The Go Authors. All rights reserved.
85408-// Use of this source code is governed by a BSD-style
85409-// license that can be found in the LICENSE file.
85410-
85411-package source
85412-
85413-import (
85414-	"context"
85415-	"fmt"
85416-	"go/ast"
85417-	"go/token"
85418-	"go/types"
85419-	"strings"
85420-
85421-	"golang.org/x/tools/go/ast/astutil"
85422-	"golang.org/x/tools/gopls/internal/lsp/protocol"
85423-	"golang.org/x/tools/internal/event"
85424-)
85425-
85426-func SignatureHelp(ctx context.Context, snapshot Snapshot, fh FileHandle, position protocol.Position) (*protocol.SignatureInformation, int, error) {
85427-	ctx, done := event.Start(ctx, "source.SignatureHelp")
85428-	defer done()
85429-
85430-	// We need full type-checking here, as we must type-check function bodies in
85431-	// order to provide signature help at the requested position.
85432-	pkg, pgf, err := PackageForFile(ctx, snapshot, fh.URI(), NarrowestPackage)
85433-	if err != nil {
85434-		return nil, 0, fmt.Errorf("getting file for SignatureHelp: %w", err)
85435-	}
85436-	pos, err := pgf.PositionPos(position)
85437-	if err != nil {
85438-		return nil, 0, err
85439-	}
85440-	// Find a call expression surrounding the query position.
85441-	var callExpr *ast.CallExpr
85442-	path, _ := astutil.PathEnclosingInterval(pgf.File, pos, pos)
85443-	if path == nil {
85444-		return nil, 0, fmt.Errorf("cannot find node enclosing position")
85445-	}
85446-FindCall:
85447-	for _, node := range path {
85448-		switch node := node.(type) {
85449-		case *ast.CallExpr:
85450-			if pos >= node.Lparen && pos <= node.Rparen {
85451-				callExpr = node
85452-				break FindCall
85453-			}
85454-		case *ast.FuncLit, *ast.FuncType:
85455-			// The user is within an anonymous function,
85456-			// which may be the parameter to the *ast.CallExpr.
85457-			// Don't show signature help in this case.
85458-			return nil, 0, fmt.Errorf("no signature help within a function declaration")
85459-		case *ast.BasicLit:
85460-			if node.Kind == token.STRING {
85461-				return nil, 0, fmt.Errorf("no signature help within a string literal")
85462-			}
85463-		}
85464-
85465-	}
85466-	if callExpr == nil || callExpr.Fun == nil {
85467-		return nil, 0, fmt.Errorf("cannot find an enclosing function")
85468-	}
85469-
85470-	qf := Qualifier(pgf.File, pkg.GetTypes(), pkg.GetTypesInfo())
85471-
85472-	// Get the object representing the function, if available.
85473-	// There is no object in certain cases such as calling a function returned by
85474-	// a function (e.g. "foo()()").
85475-	var obj types.Object
85476-	switch t := callExpr.Fun.(type) {
85477-	case *ast.Ident:
85478-		obj = pkg.GetTypesInfo().ObjectOf(t)
85479-	case *ast.SelectorExpr:
85480-		obj = pkg.GetTypesInfo().ObjectOf(t.Sel)
85481-	}
85482-
85483-	// Handle builtin functions separately.
85484-	if obj, ok := obj.(*types.Builtin); ok {
85485-		return builtinSignature(ctx, snapshot, callExpr, obj.Name(), pos)
85486-	}
85487-
85488-	// Get the type information for the function being called.
85489-	sigType := pkg.GetTypesInfo().TypeOf(callExpr.Fun)
85490-	if sigType == nil {
85491-		return nil, 0, fmt.Errorf("cannot get type for Fun %[1]T (%[1]v)", callExpr.Fun)
85492-	}
85493-
85494-	sig, _ := sigType.Underlying().(*types.Signature)
85495-	if sig == nil {
85496-		return nil, 0, fmt.Errorf("cannot find signature for Fun %[1]T (%[1]v)", callExpr.Fun)
85497-	}
85498-
85499-	activeParam := activeParameter(callExpr, sig.Params().Len(), sig.Variadic(), pos)
85500-
85501-	var (
85502-		name    string
85503-		comment *ast.CommentGroup
85504-	)
85505-	if obj != nil {
85506-		d, err := HoverDocForObject(ctx, snapshot, pkg.FileSet(), obj)
85507-		if err != nil {
85508-			return nil, 0, err
85509-		}
85510-		name = obj.Name()
85511-		comment = d
85512-	} else {
85513-		name = "func"
85514-	}
85515-	mq := MetadataQualifierForFile(snapshot, pgf.File, pkg.Metadata())
85516-	s, err := NewSignature(ctx, snapshot, pkg, sig, comment, qf, mq)
85517-	if err != nil {
85518-		return nil, 0, err
85519-	}
85520-	paramInfo := make([]protocol.ParameterInformation, 0, len(s.params))
85521-	for _, p := range s.params {
85522-		paramInfo = append(paramInfo, protocol.ParameterInformation{Label: p})
85523-	}
85524-	return &protocol.SignatureInformation{
85525-		Label:         name + s.Format(),
85526-		Documentation: stringToSigInfoDocumentation(s.doc, snapshot.View().Options()),
85527-		Parameters:    paramInfo,
85528-	}, activeParam, nil
85529-}
85530-
85531-func builtinSignature(ctx context.Context, snapshot Snapshot, callExpr *ast.CallExpr, name string, pos token.Pos) (*protocol.SignatureInformation, int, error) {
85532-	sig, err := NewBuiltinSignature(ctx, snapshot, name)
85533-	if err != nil {
85534-		return nil, 0, err
85535-	}
85536-	paramInfo := make([]protocol.ParameterInformation, 0, len(sig.params))
85537-	for _, p := range sig.params {
85538-		paramInfo = append(paramInfo, protocol.ParameterInformation{Label: p})
85539-	}
85540-	activeParam := activeParameter(callExpr, len(sig.params), sig.variadic, pos)
85541-	return &protocol.SignatureInformation{
85542-		Label:         sig.name + sig.Format(),
85543-		Documentation: stringToSigInfoDocumentation(sig.doc, snapshot.View().Options()),
85544-		Parameters:    paramInfo,
85545-	}, activeParam, nil
85546-
85547-}
85548-
85549-func activeParameter(callExpr *ast.CallExpr, numParams int, variadic bool, pos token.Pos) (activeParam int) {
85550-	if len(callExpr.Args) == 0 {
85551-		return 0
85552-	}
85553-	// First, check if the position is even in the range of the arguments.
85554-	start, end := callExpr.Lparen, callExpr.Rparen
85555-	if !(start <= pos && pos <= end) {
85556-		return 0
85557-	}
85558-	for _, expr := range callExpr.Args {
85559-		if start == token.NoPos {
85560-			start = expr.Pos()
85561-		}
85562-		end = expr.End()
85563-		if start <= pos && pos <= end {
85564-			break
85565-		}
85566-		// Don't advance the active parameter for the last parameter of a variadic function.
85567-		if !variadic || activeParam < numParams-1 {
85568-			activeParam++
85569-		}
85570-		start = expr.Pos() + 1 // to account for commas
85571-	}
85572-	return activeParam
85573-}
85574-
85575-func stringToSigInfoDocumentation(s string, options *Options) *protocol.Or_SignatureInformation_documentation {
85576-	v := s
85577-	k := protocol.PlainText
85578-	if options.PreferredContentFormat == protocol.Markdown {
85579-		v = CommentToMarkdown(s, options)
85580-		// whether or not content is newline terminated may not matter for LSP clients,
85581-		// but our tests expect trailing newlines to be stripped.
85582-		v = strings.TrimSuffix(v, "\n") // TODO(pjw): change the golden files
85583-		k = protocol.Markdown
85584-	}
85585-	return &protocol.Or_SignatureInformation_documentation{
85586-		Value: protocol.MarkupContent{
85587-			Kind:  k,
85588-			Value: v,
85589-		},
85590-	}
85591-}
85592diff -urN a/gopls/internal/lsp/source/stub.go b/gopls/internal/lsp/source/stub.go
85593--- a/gopls/internal/lsp/source/stub.go	2000-01-01 00:00:00.000000000 -0000
85594+++ b/gopls/internal/lsp/source/stub.go	1970-01-01 00:00:00.000000000 +0000
85595@@ -1,238 +0,0 @@
85596-// Copyright 2022 The Go Authors. All rights reserved.
85597-// Use of this source code is governed by a BSD-style
85598-// license that can be found in the LICENSE file.
85599-
85600-package source
85601-
85602-import (
85603-	"bytes"
85604-	"context"
85605-	"fmt"
85606-	"go/format"
85607-	"go/parser"
85608-	"go/token"
85609-	"go/types"
85610-	"io"
85611-	"path"
85612-	"strings"
85613-
85614-	"golang.org/x/tools/go/analysis"
85615-	"golang.org/x/tools/go/ast/astutil"
85616-	"golang.org/x/tools/gopls/internal/lsp/analysis/stubmethods"
85617-	"golang.org/x/tools/gopls/internal/lsp/protocol"
85618-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
85619-	"golang.org/x/tools/internal/bug"
85620-	"golang.org/x/tools/internal/typeparams"
85621-)
85622-
85623-// stubSuggestedFixFunc returns a suggested fix to declare the missing
85624-// methods of the concrete type that is assigned to an interface type
85625-// at the cursor position.
85626-func stubSuggestedFixFunc(ctx context.Context, snapshot Snapshot, fh FileHandle, rng protocol.Range) (*token.FileSet, *analysis.SuggestedFix, error) {
85627-	pkg, pgf, err := PackageForFile(ctx, snapshot, fh.URI(), NarrowestPackage)
85628-	if err != nil {
85629-		return nil, nil, fmt.Errorf("GetTypedFile: %w", err)
85630-	}
85631-	start, end, err := pgf.RangePos(rng)
85632-	if err != nil {
85633-		return nil, nil, err
85634-	}
85635-	nodes, _ := astutil.PathEnclosingInterval(pgf.File, start, end)
85636-	si := stubmethods.GetStubInfo(pkg.FileSet(), pkg.GetTypesInfo(), nodes, start)
85637-	if si == nil {
85638-		return nil, nil, fmt.Errorf("nil interface request")
85639-	}
85640-	return stub(ctx, snapshot, si)
85641-}
85642-
85643-// stub returns a suggested fix to declare the missing methods of si.Concrete.
85644-func stub(ctx context.Context, snapshot Snapshot, si *stubmethods.StubInfo) (*token.FileSet, *analysis.SuggestedFix, error) {
85645-	// A function-local type cannot be stubbed
85646-	// since there's nowhere to put the methods.
85647-	conc := si.Concrete.Obj()
85648-	if conc.Parent() != conc.Pkg().Scope() {
85649-		return nil, nil, fmt.Errorf("local type %q cannot be stubbed", conc.Name())
85650-	}
85651-
85652-	// Parse the file declaring the concrete type.
85653-	declPGF, _, err := parseFull(ctx, snapshot, si.Fset, conc.Pos())
85654-	if err != nil {
85655-		return nil, nil, fmt.Errorf("failed to parse file %q declaring implementation type: %w", declPGF.URI, err)
85656-	}
85657-	if declPGF.Fixed {
85658-		return nil, nil, fmt.Errorf("file contains parse errors: %s", declPGF.URI)
85659-	}
85660-
85661-	// Build import environment for the declaring file.
85662-	importEnv := make(map[ImportPath]string) // value is local name
85663-	for _, imp := range declPGF.File.Imports {
85664-		importPath := UnquoteImportPath(imp)
85665-		var name string
85666-		if imp.Name != nil {
85667-			name = imp.Name.Name
85668-			if name == "_" {
85669-				continue
85670-			} else if name == "." {
85671-				name = "" // see types.Qualifier
85672-			}
85673-		} else {
85674-			// TODO(adonovan): may omit a vendor/ prefix; consult the Metadata.
85675-			name = path.Base(string(importPath))
85676-		}
85677-		importEnv[importPath] = name // latest alias wins
85678-	}
85679-
85680-	// Find subset of interface methods that the concrete type lacks.
85681-	var missing []*types.Func
85682-	ifaceType := si.Interface.Type().Underlying().(*types.Interface)
85683-	for i := 0; i < ifaceType.NumMethods(); i++ {
85684-		imethod := ifaceType.Method(i)
85685-		cmethod, _, _ := types.LookupFieldOrMethod(si.Concrete, si.Pointer, imethod.Pkg(), imethod.Name())
85686-		if cmethod == nil {
85687-			missing = append(missing, imethod)
85688-			continue
85689-		}
85690-
85691-		if _, ok := cmethod.(*types.Var); ok {
85692-			// len(LookupFieldOrMethod.index) = 1 => conflict, >1 => shadow.
85693-			return nil, nil, fmt.Errorf("adding method %s.%s would conflict with (or shadow) existing field",
85694-				conc.Name(), imethod.Name())
85695-		}
85696-
85697-		if !types.Identical(cmethod.Type(), imethod.Type()) {
85698-			return nil, nil, fmt.Errorf("method %s.%s already exists but has the wrong type: got %s, want %s",
85699-				conc.Name(), imethod.Name(), cmethod.Type(), imethod.Type())
85700-		}
85701-	}
85702-	if len(missing) == 0 {
85703-		return nil, nil, fmt.Errorf("no missing methods found")
85704-	}
85705-
85706-	// Create a package name qualifier that uses the
85707-	// locally appropriate imported package name.
85708-	// It records any needed new imports.
85709-	// TODO(adonovan): factor with source.FormatVarType, stubmethods.RelativeToFiles?
85710-	//
85711-	// Prior to CL 469155 this logic preserved any renaming
85712-	// imports from the file that declares the interface
85713-	// method--ostensibly the preferred name for imports of
85714-	// frequently renamed packages such as protobufs.
85715-	// Now we use the package's declared name. If this turns out
85716-	// to be a mistake, then use parseHeader(si.iface.Pos()).
85717-	//
85718-	type newImport struct{ name, importPath string }
85719-	var newImports []newImport // for AddNamedImport
85720-	qual := func(pkg *types.Package) string {
85721-		// TODO(adonovan): don't ignore vendor prefix.
85722-		importPath := ImportPath(pkg.Path())
85723-		name, ok := importEnv[importPath]
85724-		if !ok {
85725-			// Insert new import using package's declared name.
85726-			//
85727-			// TODO(adonovan): resolve conflict between declared
85728-			// name and existing file-level (declPGF.File.Imports)
85729-			// or package-level (si.Concrete.Pkg.Scope) decls by
85730-			// generating a fresh name.
85731-			name = pkg.Name()
85732-			importEnv[importPath] = name
85733-			new := newImport{importPath: string(importPath)}
85734-			// For clarity, use a renaming import whenever the
85735-			// local name does not match the path's last segment.
85736-			if name != path.Base(new.importPath) {
85737-				new.name = name
85738-			}
85739-			newImports = append(newImports, new)
85740-		}
85741-		return name
85742-	}
85743-
85744-	// Format interface name (used only in a comment).
85745-	iface := si.Interface.Name()
85746-	if ipkg := si.Interface.Pkg(); ipkg != nil && ipkg != conc.Pkg() {
85747-		iface = ipkg.Name() + "." + iface
85748-	}
85749-
85750-	// Pointer receiver?
85751-	var star string
85752-	if si.Pointer {
85753-		star = "*"
85754-	}
85755-
85756-	// Format the new methods.
85757-	var newMethods bytes.Buffer
85758-	for _, method := range missing {
85759-		fmt.Fprintf(&newMethods, `// %s implements %s
85760-func (%s%s%s) %s%s {
85761-	panic("unimplemented")
85762-}
85763-`,
85764-			method.Name(),
85765-			iface,
85766-			star,
85767-			si.Concrete.Obj().Name(),
85768-			FormatTypeParams(typeparams.ForNamed(si.Concrete)),
85769-			method.Name(),
85770-			strings.TrimPrefix(types.TypeString(method.Type(), qual), "func"))
85771-	}
85772-
85773-	// Compute insertion point for new methods:
85774-	// after the top-level declaration enclosing the (package-level) type.
85775-	insertOffset, err := safetoken.Offset(declPGF.Tok, declPGF.File.End())
85776-	if err != nil {
85777-		return nil, nil, bug.Errorf("internal error: end position outside file bounds: %v", err)
85778-	}
85779-	concOffset, err := safetoken.Offset(si.Fset.File(conc.Pos()), conc.Pos())
85780-	if err != nil {
85781-		return nil, nil, bug.Errorf("internal error: finding type decl offset: %v", err)
85782-	}
85783-	for _, decl := range declPGF.File.Decls {
85784-		declEndOffset, err := safetoken.Offset(declPGF.Tok, decl.End())
85785-		if err != nil {
85786-			return nil, nil, bug.Errorf("internal error: finding decl offset: %v", err)
85787-		}
85788-		if declEndOffset > concOffset {
85789-			insertOffset = declEndOffset
85790-			break
85791-		}
85792-	}
85793-
85794-	// Splice the new methods into the file content.
85795-	var buf bytes.Buffer
85796-	input := declPGF.Mapper.Content // unfixed content of file
85797-	buf.Write(input[:insertOffset])
85798-	buf.WriteByte('\n')
85799-	io.Copy(&buf, &newMethods)
85800-	buf.Write(input[insertOffset:])
85801-
85802-	// Re-parse the file.
85803-	fset := token.NewFileSet()
85804-	newF, err := parser.ParseFile(fset, declPGF.File.Name.Name, buf.Bytes(), parser.ParseComments)
85805-	if err != nil {
85806-		return nil, nil, fmt.Errorf("could not reparse file: %w", err)
85807-	}
85808-
85809-	// Splice the new imports into the syntax tree.
85810-	for _, imp := range newImports {
85811-		astutil.AddNamedImport(fset, newF, imp.name, imp.importPath)
85812-	}
85813-
85814-	// Pretty-print.
85815-	var output strings.Builder
85816-	if err := format.Node(&output, fset, newF); err != nil {
85817-		return nil, nil, fmt.Errorf("format.Node: %w", err)
85818-	}
85819-
85820-	// Report the diff.
85821-	diffs := snapshot.View().Options().ComputeEdits(string(input), output.String())
85822-	var edits []analysis.TextEdit
85823-	for _, edit := range diffs {
85824-		edits = append(edits, analysis.TextEdit{
85825-			Pos:     declPGF.Tok.Pos(edit.Start),
85826-			End:     declPGF.Tok.Pos(edit.End),
85827-			NewText: []byte(edit.New),
85828-		})
85829-	}
85830-	return FileSetFor(declPGF.Tok), // edits use declPGF.Tok
85831-		&analysis.SuggestedFix{TextEdits: edits},
85832-		nil
85833-}
85834diff -urN a/gopls/internal/lsp/source/symbols.go b/gopls/internal/lsp/source/symbols.go
85835--- a/gopls/internal/lsp/source/symbols.go	2000-01-01 00:00:00.000000000 -0000
85836+++ b/gopls/internal/lsp/source/symbols.go	1970-01-01 00:00:00.000000000 +0000
85837@@ -1,227 +0,0 @@
85838-// Copyright 2019 The Go Authors. All rights reserved.
85839-// Use of this source code is governed by a BSD-style
85840-// license that can be found in the LICENSE file.
85841-
85842-package source
85843-
85844-import (
85845-	"context"
85846-	"fmt"
85847-	"go/ast"
85848-	"go/token"
85849-	"go/types"
85850-
85851-	"golang.org/x/tools/gopls/internal/lsp/protocol"
85852-	"golang.org/x/tools/internal/event"
85853-)
85854-
85855-func DocumentSymbols(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]protocol.DocumentSymbol, error) {
85856-	ctx, done := event.Start(ctx, "source.DocumentSymbols")
85857-	defer done()
85858-
85859-	pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
85860-	if err != nil {
85861-		return nil, fmt.Errorf("getting file for DocumentSymbols: %w", err)
85862-	}
85863-
85864-	// Build symbols for file declarations. When encountering a declaration with
85865-	// errors (typically because positions are invalid), we skip the declaration
85866-	// entirely. VS Code fails to show any symbols if one of the top-level
85867-	// symbols is missing position information.
85868-	var symbols []protocol.DocumentSymbol
85869-	for _, decl := range pgf.File.Decls {
85870-		switch decl := decl.(type) {
85871-		case *ast.FuncDecl:
85872-			if decl.Name.Name == "_" {
85873-				continue
85874-			}
85875-			fs, err := funcSymbol(pgf.Mapper, pgf.Tok, decl)
85876-			if err == nil {
85877-				// If function is a method, prepend the type of the method.
85878-				if decl.Recv != nil && len(decl.Recv.List) > 0 {
85879-					fs.Name = fmt.Sprintf("(%s).%s", types.ExprString(decl.Recv.List[0].Type), fs.Name)
85880-				}
85881-				symbols = append(symbols, fs)
85882-			}
85883-		case *ast.GenDecl:
85884-			for _, spec := range decl.Specs {
85885-				switch spec := spec.(type) {
85886-				case *ast.TypeSpec:
85887-					if spec.Name.Name == "_" {
85888-						continue
85889-					}
85890-					ts, err := typeSymbol(pgf.Mapper, pgf.Tok, spec)
85891-					if err == nil {
85892-						symbols = append(symbols, ts)
85893-					}
85894-				case *ast.ValueSpec:
85895-					for _, name := range spec.Names {
85896-						if name.Name == "_" {
85897-							continue
85898-						}
85899-						vs, err := varSymbol(pgf.Mapper, pgf.Tok, spec, name, decl.Tok == token.CONST)
85900-						if err == nil {
85901-							symbols = append(symbols, vs)
85902-						}
85903-					}
85904-				}
85905-			}
85906-		}
85907-	}
85908-	return symbols, nil
85909-}
85910-
85911-func funcSymbol(m *protocol.Mapper, tf *token.File, decl *ast.FuncDecl) (protocol.DocumentSymbol, error) {
85912-	s := protocol.DocumentSymbol{
85913-		Name: decl.Name.Name,
85914-		Kind: protocol.Function,
85915-	}
85916-	if decl.Recv != nil {
85917-		s.Kind = protocol.Method
85918-	}
85919-	var err error
85920-	s.Range, err = m.NodeRange(tf, decl)
85921-	if err != nil {
85922-		return protocol.DocumentSymbol{}, err
85923-	}
85924-	s.SelectionRange, err = m.NodeRange(tf, decl.Name)
85925-	if err != nil {
85926-		return protocol.DocumentSymbol{}, err
85927-	}
85928-	s.Detail = types.ExprString(decl.Type)
85929-	return s, nil
85930-}
85931-
85932-func typeSymbol(m *protocol.Mapper, tf *token.File, spec *ast.TypeSpec) (protocol.DocumentSymbol, error) {
85933-	s := protocol.DocumentSymbol{
85934-		Name: spec.Name.Name,
85935-	}
85936-	var err error
85937-	s.Range, err = m.NodeRange(tf, spec)
85938-	if err != nil {
85939-		return protocol.DocumentSymbol{}, err
85940-	}
85941-	s.SelectionRange, err = m.NodeRange(tf, spec.Name)
85942-	if err != nil {
85943-		return protocol.DocumentSymbol{}, err
85944-	}
85945-	s.Kind, s.Detail, s.Children = typeDetails(m, tf, spec.Type)
85946-	return s, nil
85947-}
85948-
85949-func typeDetails(m *protocol.Mapper, tf *token.File, typExpr ast.Expr) (kind protocol.SymbolKind, detail string, children []protocol.DocumentSymbol) {
85950-	switch typExpr := typExpr.(type) {
85951-	case *ast.StructType:
85952-		kind = protocol.Struct
85953-		children = fieldListSymbols(m, tf, typExpr.Fields, protocol.Field)
85954-		if len(children) > 0 {
85955-			detail = "struct{...}"
85956-		} else {
85957-			detail = "struct{}"
85958-		}
85959-
85960-		// Find interface methods and embedded types.
85961-	case *ast.InterfaceType:
85962-		kind = protocol.Interface
85963-		children = fieldListSymbols(m, tf, typExpr.Methods, protocol.Method)
85964-		if len(children) > 0 {
85965-			detail = "interface{...}"
85966-		} else {
85967-			detail = "interface{}"
85968-		}
85969-
85970-	case *ast.FuncType:
85971-		kind = protocol.Function
85972-		detail = types.ExprString(typExpr)
85973-
85974-	default:
85975-		kind = protocol.Class // catch-all, for cases where we don't know the kind syntactically
85976-		detail = types.ExprString(typExpr)
85977-	}
85978-	return
85979-}
85980-
85981-func fieldListSymbols(m *protocol.Mapper, tf *token.File, fields *ast.FieldList, fieldKind protocol.SymbolKind) []protocol.DocumentSymbol {
85982-	if fields == nil {
85983-		return nil
85984-	}
85985-
85986-	var symbols []protocol.DocumentSymbol
85987-	for _, field := range fields.List {
85988-		detail, children := "", []protocol.DocumentSymbol(nil)
85989-		if field.Type != nil {
85990-			_, detail, children = typeDetails(m, tf, field.Type)
85991-		}
85992-		if len(field.Names) == 0 { // embedded interface or struct field
85993-			// By default, use the formatted type details as the name of this field.
85994-			// This handles potentially invalid syntax, as well as type embeddings in
85995-			// interfaces.
85996-			child := protocol.DocumentSymbol{
85997-				Name:     detail,
85998-				Kind:     protocol.Field, // consider all embeddings to be fields
85999-				Children: children,
86000-			}
86001-
86002-			// If the field is a valid embedding, promote the type name to field
86003-			// name.
86004-			selection := field.Type
86005-			if id := embeddedIdent(field.Type); id != nil {
86006-				child.Name = id.Name
86007-				child.Detail = detail
86008-				selection = id
86009-			}
86010-
86011-			if rng, err := m.NodeRange(tf, field.Type); err == nil {
86012-				child.Range = rng
86013-			}
86014-			if rng, err := m.NodeRange(tf, selection); err == nil {
86015-				child.SelectionRange = rng
86016-			}
86017-
86018-			symbols = append(symbols, child)
86019-		} else {
86020-			for _, name := range field.Names {
86021-				child := protocol.DocumentSymbol{
86022-					Name:     name.Name,
86023-					Kind:     fieldKind,
86024-					Detail:   detail,
86025-					Children: children,
86026-				}
86027-
86028-				if rng, err := m.NodeRange(tf, field); err == nil {
86029-					child.Range = rng
86030-				}
86031-				if rng, err := m.NodeRange(tf, name); err == nil {
86032-					child.SelectionRange = rng
86033-				}
86034-
86035-				symbols = append(symbols, child)
86036-			}
86037-		}
86038-
86039-	}
86040-	return symbols
86041-}
86042-
86043-func varSymbol(m *protocol.Mapper, tf *token.File, spec *ast.ValueSpec, name *ast.Ident, isConst bool) (protocol.DocumentSymbol, error) {
86044-	s := protocol.DocumentSymbol{
86045-		Name: name.Name,
86046-		Kind: protocol.Variable,
86047-	}
86048-	if isConst {
86049-		s.Kind = protocol.Constant
86050-	}
86051-	var err error
86052-	s.Range, err = m.NodeRange(tf, spec)
86053-	if err != nil {
86054-		return protocol.DocumentSymbol{}, err
86055-	}
86056-	s.SelectionRange, err = m.NodeRange(tf, name)
86057-	if err != nil {
86058-		return protocol.DocumentSymbol{}, err
86059-	}
86060-	if spec.Type != nil { // type may be missing from the syntax
86061-		_, s.Detail, s.Children = typeDetails(m, tf, spec.Type)
86062-	}
86063-	return s, nil
86064-}
86065diff -urN a/gopls/internal/lsp/source/type_definition.go b/gopls/internal/lsp/source/type_definition.go
86066--- a/gopls/internal/lsp/source/type_definition.go	2000-01-01 00:00:00.000000000 -0000
86067+++ b/gopls/internal/lsp/source/type_definition.go	1970-01-01 00:00:00.000000000 +0000
86068@@ -1,55 +0,0 @@
86069-// Copyright 2023 The Go Authors. All rights reserved.
86070-// Use of this source code is governed by a BSD-style
86071-// license that can be found in the LICENSE file.
86072-
86073-package source
86074-
86075-import (
86076-	"context"
86077-	"fmt"
86078-	"go/token"
86079-
86080-	"golang.org/x/tools/gopls/internal/lsp/protocol"
86081-	"golang.org/x/tools/internal/event"
86082-)
86083-
86084-// TypeDefinition handles the textDocument/typeDefinition request for Go files.
86085-func TypeDefinition(ctx context.Context, snapshot Snapshot, fh FileHandle, position protocol.Position) ([]protocol.Location, error) {
86086-	ctx, done := event.Start(ctx, "source.TypeDefinition")
86087-	defer done()
86088-
86089-	pkg, pgf, err := PackageForFile(ctx, snapshot, fh.URI(), NarrowestPackage)
86090-	if err != nil {
86091-		return nil, err
86092-	}
86093-	pos, err := pgf.PositionPos(position)
86094-	if err != nil {
86095-		return nil, err
86096-	}
86097-
86098-	// TODO(rfindley): handle type switch implicits correctly here: if the user
86099-	// jumps to the type definition of x in x := y.(type), it makes sense to jump
86100-	// to the type of y.
86101-	_, obj, _ := referencedObject(pkg, pgf, pos)
86102-	if obj == nil {
86103-		return nil, nil
86104-	}
86105-
86106-	typObj := typeToObject(obj.Type())
86107-	if typObj == nil {
86108-		return nil, fmt.Errorf("no type definition for %s", obj.Name())
86109-	}
86110-
86111-	// Identifiers with the type "error" are a special case with no position.
86112-	if hasErrorType(typObj) {
86113-		// TODO(rfindley): we can do better here, returning a link to the builtin
86114-		// file.
86115-		return nil, nil
86116-	}
86117-
86118-	loc, err := mapPosition(ctx, pkg.FileSet(), snapshot, typObj.Pos(), typObj.Pos()+token.Pos(len(typObj.Name())))
86119-	if err != nil {
86120-		return nil, err
86121-	}
86122-	return []protocol.Location{loc}, nil
86123-}
86124diff -urN a/gopls/internal/lsp/source/types_format.go b/gopls/internal/lsp/source/types_format.go
86125--- a/gopls/internal/lsp/source/types_format.go	2000-01-01 00:00:00.000000000 -0000
86126+++ b/gopls/internal/lsp/source/types_format.go	1970-01-01 00:00:00.000000000 +0000
86127@@ -1,517 +0,0 @@
86128-// Copyright 2020 The Go Authors. All rights reserved.
86129-// Use of this source code is governed by a BSD-style
86130-// license that can be found in the LICENSE file.
86131-
86132-package source
86133-
86134-import (
86135-	"bytes"
86136-	"context"
86137-	"fmt"
86138-	"go/ast"
86139-	"go/doc"
86140-	"go/printer"
86141-	"go/token"
86142-	"go/types"
86143-	"strings"
86144-
86145-	"golang.org/x/tools/gopls/internal/lsp/protocol"
86146-	"golang.org/x/tools/internal/bug"
86147-	"golang.org/x/tools/internal/event"
86148-	"golang.org/x/tools/internal/event/tag"
86149-	"golang.org/x/tools/internal/typeparams"
86150-)
86151-
86152-// FormatType returns the detail and kind for a types.Type.
86153-func FormatType(typ types.Type, qf types.Qualifier) (detail string, kind protocol.CompletionItemKind) {
86154-	if types.IsInterface(typ) {
86155-		detail = "interface{...}"
86156-		kind = protocol.InterfaceCompletion
86157-	} else if _, ok := typ.(*types.Struct); ok {
86158-		detail = "struct{...}"
86159-		kind = protocol.StructCompletion
86160-	} else if typ != typ.Underlying() {
86161-		detail, kind = FormatType(typ.Underlying(), qf)
86162-	} else {
86163-		detail = types.TypeString(typ, qf)
86164-		kind = protocol.ClassCompletion
86165-	}
86166-	return detail, kind
86167-}
86168-
86169-type signature struct {
86170-	name, doc                   string
86171-	typeParams, params, results []string
86172-	variadic                    bool
86173-	needResultParens            bool
86174-}
86175-
86176-func (s *signature) Format() string {
86177-	var b strings.Builder
86178-	b.WriteByte('(')
86179-	for i, p := range s.params {
86180-		if i > 0 {
86181-			b.WriteString(", ")
86182-		}
86183-		b.WriteString(p)
86184-	}
86185-	b.WriteByte(')')
86186-
86187-	// Add space between parameters and results.
86188-	if len(s.results) > 0 {
86189-		b.WriteByte(' ')
86190-	}
86191-	if s.needResultParens {
86192-		b.WriteByte('(')
86193-	}
86194-	for i, r := range s.results {
86195-		if i > 0 {
86196-			b.WriteString(", ")
86197-		}
86198-		b.WriteString(r)
86199-	}
86200-	if s.needResultParens {
86201-		b.WriteByte(')')
86202-	}
86203-	return b.String()
86204-}
86205-
86206-func (s *signature) TypeParams() []string {
86207-	return s.typeParams
86208-}
86209-
86210-func (s *signature) Params() []string {
86211-	return s.params
86212-}
86213-
86214-// NewBuiltinSignature returns signature for the builtin object with a given
86215-// name, if a builtin object with the name exists.
86216-func NewBuiltinSignature(ctx context.Context, s Snapshot, name string) (*signature, error) {
86217-	builtin, err := s.BuiltinFile(ctx)
86218-	if err != nil {
86219-		return nil, err
86220-	}
86221-	obj := builtin.File.Scope.Lookup(name)
86222-	if obj == nil {
86223-		return nil, fmt.Errorf("no builtin object for %s", name)
86224-	}
86225-	decl, ok := obj.Decl.(*ast.FuncDecl)
86226-	if !ok {
86227-		return nil, fmt.Errorf("no function declaration for builtin: %s", name)
86228-	}
86229-	if decl.Type == nil {
86230-		return nil, fmt.Errorf("no type for builtin decl %s", decl.Name)
86231-	}
86232-	var variadic bool
86233-	if decl.Type.Params.List != nil {
86234-		numParams := len(decl.Type.Params.List)
86235-		lastParam := decl.Type.Params.List[numParams-1]
86236-		if _, ok := lastParam.Type.(*ast.Ellipsis); ok {
86237-			variadic = true
86238-		}
86239-	}
86240-	fset := FileSetFor(builtin.Tok)
86241-	params, _ := formatFieldList(ctx, fset, decl.Type.Params, variadic)
86242-	results, needResultParens := formatFieldList(ctx, fset, decl.Type.Results, false)
86243-	d := decl.Doc.Text()
86244-	switch s.View().Options().HoverKind {
86245-	case SynopsisDocumentation:
86246-		d = doc.Synopsis(d)
86247-	case NoDocumentation:
86248-		d = ""
86249-	}
86250-	return &signature{
86251-		doc:              d,
86252-		name:             name,
86253-		needResultParens: needResultParens,
86254-		params:           params,
86255-		results:          results,
86256-		variadic:         variadic,
86257-	}, nil
86258-}
86259-
86260-// replacer replaces some synthetic "type classes" used in the builtin file
86261-// with their most common constituent type.
86262-var replacer = strings.NewReplacer(
86263-	`ComplexType`, `complex128`,
86264-	`FloatType`, `float64`,
86265-	`IntegerType`, `int`,
86266-)
86267-
86268-func formatFieldList(ctx context.Context, fset *token.FileSet, list *ast.FieldList, variadic bool) ([]string, bool) {
86269-	if list == nil {
86270-		return nil, false
86271-	}
86272-	var writeResultParens bool
86273-	var result []string
86274-	for i := 0; i < len(list.List); i++ {
86275-		if i >= 1 {
86276-			writeResultParens = true
86277-		}
86278-		p := list.List[i]
86279-		cfg := printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 4}
86280-		b := &bytes.Buffer{}
86281-		if err := cfg.Fprint(b, fset, p.Type); err != nil {
86282-			event.Error(ctx, "unable to print type", nil, tag.Type.Of(p.Type))
86283-			continue
86284-		}
86285-		typ := replacer.Replace(b.String())
86286-		if len(p.Names) == 0 {
86287-			result = append(result, typ)
86288-		}
86289-		for _, name := range p.Names {
86290-			if name.Name != "" {
86291-				if i == 0 {
86292-					writeResultParens = true
86293-				}
86294-				result = append(result, fmt.Sprintf("%s %s", name.Name, typ))
86295-			} else {
86296-				result = append(result, typ)
86297-			}
86298-		}
86299-	}
86300-	if variadic {
86301-		result[len(result)-1] = strings.Replace(result[len(result)-1], "[]", "...", 1)
86302-	}
86303-	return result, writeResultParens
86304-}
86305-
86306-// FormatTypeParams turns TypeParamList into its Go representation, such as:
86307-// [T, Y]. Note that it does not print constraints as this is mainly used for
86308-// formatting type params in method receivers.
86309-func FormatTypeParams(tparams *typeparams.TypeParamList) string {
86310-	if tparams == nil || tparams.Len() == 0 {
86311-		return ""
86312-	}
86313-	var buf bytes.Buffer
86314-	buf.WriteByte('[')
86315-	for i := 0; i < tparams.Len(); i++ {
86316-		if i > 0 {
86317-			buf.WriteString(", ")
86318-		}
86319-		buf.WriteString(tparams.At(i).Obj().Name())
86320-	}
86321-	buf.WriteByte(']')
86322-	return buf.String()
86323-}
86324-
86325-// NewSignature returns formatted signature for a types.Signature struct.
86326-func NewSignature(ctx context.Context, s Snapshot, pkg Package, sig *types.Signature, comment *ast.CommentGroup, qf types.Qualifier, mq MetadataQualifier) (*signature, error) {
86327-	var tparams []string
86328-	tpList := typeparams.ForSignature(sig)
86329-	for i := 0; i < tpList.Len(); i++ {
86330-		tparam := tpList.At(i)
86331-		// TODO: is it possible to reuse the logic from FormatVarType here?
86332-		s := tparam.Obj().Name() + " " + tparam.Constraint().String()
86333-		tparams = append(tparams, s)
86334-	}
86335-
86336-	params := make([]string, 0, sig.Params().Len())
86337-	for i := 0; i < sig.Params().Len(); i++ {
86338-		el := sig.Params().At(i)
86339-		typ, err := FormatVarType(ctx, s, pkg, el, qf, mq)
86340-		if err != nil {
86341-			return nil, err
86342-		}
86343-		p := typ
86344-		if el.Name() != "" {
86345-			p = el.Name() + " " + typ
86346-		}
86347-		params = append(params, p)
86348-	}
86349-
86350-	var needResultParens bool
86351-	results := make([]string, 0, sig.Results().Len())
86352-	for i := 0; i < sig.Results().Len(); i++ {
86353-		if i >= 1 {
86354-			needResultParens = true
86355-		}
86356-		el := sig.Results().At(i)
86357-		typ, err := FormatVarType(ctx, s, pkg, el, qf, mq)
86358-		if err != nil {
86359-			return nil, err
86360-		}
86361-		if el.Name() == "" {
86362-			results = append(results, typ)
86363-		} else {
86364-			if i == 0 {
86365-				needResultParens = true
86366-			}
86367-			results = append(results, el.Name()+" "+typ)
86368-		}
86369-	}
86370-	var d string
86371-	if comment != nil {
86372-		d = comment.Text()
86373-	}
86374-	switch s.View().Options().HoverKind {
86375-	case SynopsisDocumentation:
86376-		d = doc.Synopsis(d)
86377-	case NoDocumentation:
86378-		d = ""
86379-	}
86380-	return &signature{
86381-		doc:              d,
86382-		typeParams:       tparams,
86383-		params:           params,
86384-		results:          results,
86385-		variadic:         sig.Variadic(),
86386-		needResultParens: needResultParens,
86387-	}, nil
86388-}
86389-
86390-// FormatVarType formats a *types.Var, accounting for type aliases.
86391-// To do this, it looks in the AST of the file in which the object is declared.
86392-// On any errors, it always falls back to types.TypeString.
86393-//
86394-// TODO(rfindley): this function could return the actual name used in syntax,
86395-// for better parameter names.
86396-func FormatVarType(ctx context.Context, snapshot Snapshot, srcpkg Package, obj *types.Var, qf types.Qualifier, mq MetadataQualifier) (string, error) {
86397-	// TODO(rfindley): This looks wrong. The previous comment said:
86398-	// "If the given expr refers to a type parameter, then use the
86399-	// object's Type instead of the type parameter declaration. This helps
86400-	// format the instantiated type as opposed to the original undeclared
86401-	// generic type".
86402-	//
86403-	// But of course, if obj is a type param, we are formatting a generic type
86404-	// and not an instantiated type. Handling for instantiated types must be done
86405-	// at a higher level.
86406-	//
86407-	// Left this during refactoring in order to preserve pre-existing logic.
86408-	if typeparams.IsTypeParam(obj.Type()) {
86409-		return types.TypeString(obj.Type(), qf), nil
86410-	}
86411-
86412-	if obj.Pkg() == nil || !obj.Pos().IsValid() {
86413-		// This is defensive, though it is extremely unlikely we'll ever have a
86414-		// builtin var.
86415-		return types.TypeString(obj.Type(), qf), nil
86416-	}
86417-
86418-	targetpgf, pos, err := parseFull(ctx, snapshot, srcpkg.FileSet(), obj.Pos())
86419-	if err != nil {
86420-		return "", err // e.g. ctx cancelled
86421-	}
86422-
86423-	targetMeta := findFileInDeps(snapshot, srcpkg.Metadata(), targetpgf.URI)
86424-	if targetMeta == nil {
86425-		// If we have an object from type-checking, it should exist in a file in
86426-		// the forward transitive closure.
86427-		return "", bug.Errorf("failed to find file %q in deps of %q", targetpgf.URI, srcpkg.Metadata().ID)
86428-	}
86429-
86430-	decl, spec, field := findDeclInfo([]*ast.File{targetpgf.File}, pos)
86431-
86432-	// We can't handle type parameters correctly, so we fall back on TypeString
86433-	// for parameterized decls.
86434-	if decl, _ := decl.(*ast.FuncDecl); decl != nil {
86435-		if typeparams.ForFuncType(decl.Type).NumFields() > 0 {
86436-			return types.TypeString(obj.Type(), qf), nil // in generic function
86437-		}
86438-		if decl.Recv != nil && len(decl.Recv.List) > 0 {
86439-			if x, _, _, _ := typeparams.UnpackIndexExpr(decl.Recv.List[0].Type); x != nil {
86440-				return types.TypeString(obj.Type(), qf), nil // in method of generic type
86441-			}
86442-		}
86443-	}
86444-	if spec, _ := spec.(*ast.TypeSpec); spec != nil && typeparams.ForTypeSpec(spec).NumFields() > 0 {
86445-		return types.TypeString(obj.Type(), qf), nil // in generic type decl
86446-	}
86447-
86448-	if field == nil {
86449-		// TODO(rfindley): we should never reach here from an ordinary var, so
86450-		// should probably return an error here.
86451-		return types.TypeString(obj.Type(), qf), nil
86452-	}
86453-	expr := field.Type
86454-
86455-	rq := requalifier(snapshot, targetpgf.File, targetMeta, mq)
86456-
86457-	// The type names in the AST may not be correctly qualified.
86458-	// Determine the package name to use based on the package that originated
86459-	// the query and the package in which the type is declared.
86460-	// We then qualify the value by cloning the AST node and editing it.
86461-	expr = qualifyTypeExpr(expr, rq)
86462-
86463-	// If the request came from a different package than the one in which the
86464-	// types are defined, we may need to modify the qualifiers.
86465-	return FormatNodeFile(targetpgf.Tok, expr), nil
86466-}
86467-
86468-// qualifyTypeExpr clones the type expression expr after re-qualifying type
86469-// names using the given function, which accepts the current syntactic
86470-// qualifier (possibly "" for unqualified idents), and returns a new qualifier
86471-// (again, possibly "" if the identifier should be unqualified).
86472-//
86473-// The resulting expression may be inaccurate: without type-checking we don't
86474-// properly account for "." imported identifiers or builtins.
86475-//
86476-// TODO(rfindley): add many more tests for this function.
86477-func qualifyTypeExpr(expr ast.Expr, qf func(string) string) ast.Expr {
86478-	switch expr := expr.(type) {
86479-	case *ast.ArrayType:
86480-		return &ast.ArrayType{
86481-			Lbrack: expr.Lbrack,
86482-			Elt:    qualifyTypeExpr(expr.Elt, qf),
86483-			Len:    expr.Len,
86484-		}
86485-
86486-	case *ast.BinaryExpr:
86487-		if expr.Op != token.OR {
86488-			return expr
86489-		}
86490-		return &ast.BinaryExpr{
86491-			X:     qualifyTypeExpr(expr.X, qf),
86492-			OpPos: expr.OpPos,
86493-			Op:    expr.Op,
86494-			Y:     qualifyTypeExpr(expr.Y, qf),
86495-		}
86496-
86497-	case *ast.ChanType:
86498-		return &ast.ChanType{
86499-			Arrow: expr.Arrow,
86500-			Begin: expr.Begin,
86501-			Dir:   expr.Dir,
86502-			Value: qualifyTypeExpr(expr.Value, qf),
86503-		}
86504-
86505-	case *ast.Ellipsis:
86506-		return &ast.Ellipsis{
86507-			Ellipsis: expr.Ellipsis,
86508-			Elt:      qualifyTypeExpr(expr.Elt, qf),
86509-		}
86510-
86511-	case *ast.FuncType:
86512-		return &ast.FuncType{
86513-			Func:    expr.Func,
86514-			Params:  qualifyFieldList(expr.Params, qf),
86515-			Results: qualifyFieldList(expr.Results, qf),
86516-		}
86517-
86518-	case *ast.Ident:
86519-		// Unqualified type (builtin, package local, or dot-imported).
86520-
86521-		// Don't qualify names that look like builtins.
86522-		//
86523-		// Without type-checking this may be inaccurate. It could be made accurate
86524-		// by doing syntactic object resolution for the entire package, but that
86525-		// does not seem worthwhile and we generally want to avoid using
86526-		// ast.Object, which may be inaccurate.
86527-		if obj := types.Universe.Lookup(expr.Name); obj != nil {
86528-			return expr
86529-		}
86530-
86531-		newName := qf("")
86532-		if newName != "" {
86533-			return &ast.SelectorExpr{
86534-				X: &ast.Ident{
86535-					NamePos: expr.Pos(),
86536-					Name:    newName,
86537-				},
86538-				Sel: expr,
86539-			}
86540-		}
86541-		return expr
86542-
86543-	case *ast.IndexExpr:
86544-		return &ast.IndexExpr{
86545-			X:      qualifyTypeExpr(expr.X, qf),
86546-			Lbrack: expr.Lbrack,
86547-			Index:  qualifyTypeExpr(expr.Index, qf),
86548-			Rbrack: expr.Rbrack,
86549-		}
86550-
86551-	case *typeparams.IndexListExpr:
86552-		indices := make([]ast.Expr, len(expr.Indices))
86553-		for i, idx := range expr.Indices {
86554-			indices[i] = qualifyTypeExpr(idx, qf)
86555-		}
86556-		return &typeparams.IndexListExpr{
86557-			X:       qualifyTypeExpr(expr.X, qf),
86558-			Lbrack:  expr.Lbrack,
86559-			Indices: indices,
86560-			Rbrack:  expr.Rbrack,
86561-		}
86562-
86563-	case *ast.InterfaceType:
86564-		return &ast.InterfaceType{
86565-			Interface:  expr.Interface,
86566-			Methods:    qualifyFieldList(expr.Methods, qf),
86567-			Incomplete: expr.Incomplete,
86568-		}
86569-
86570-	case *ast.MapType:
86571-		return &ast.MapType{
86572-			Map:   expr.Map,
86573-			Key:   qualifyTypeExpr(expr.Key, qf),
86574-			Value: qualifyTypeExpr(expr.Value, qf),
86575-		}
86576-
86577-	case *ast.ParenExpr:
86578-		return &ast.ParenExpr{
86579-			Lparen: expr.Lparen,
86580-			Rparen: expr.Rparen,
86581-			X:      qualifyTypeExpr(expr.X, qf),
86582-		}
86583-
86584-	case *ast.SelectorExpr:
86585-		if id, ok := expr.X.(*ast.Ident); ok {
86586-			// qualified type
86587-			newName := qf(id.Name)
86588-			if newName == "" {
86589-				return expr.Sel
86590-			}
86591-			return &ast.SelectorExpr{
86592-				X: &ast.Ident{
86593-					NamePos: id.NamePos,
86594-					Name:    newName,
86595-				},
86596-				Sel: expr.Sel,
86597-			}
86598-		}
86599-		return expr
86600-
86601-	case *ast.StarExpr:
86602-		return &ast.StarExpr{
86603-			Star: expr.Star,
86604-			X:    qualifyTypeExpr(expr.X, qf),
86605-		}
86606-
86607-	case *ast.StructType:
86608-		return &ast.StructType{
86609-			Struct:     expr.Struct,
86610-			Fields:     qualifyFieldList(expr.Fields, qf),
86611-			Incomplete: expr.Incomplete,
86612-		}
86613-
86614-	default:
86615-		return expr
86616-	}
86617-}
86618-
86619-func qualifyFieldList(fl *ast.FieldList, qf func(string) string) *ast.FieldList {
86620-	if fl == nil {
86621-		return nil
86622-	}
86623-	if fl.List == nil {
86624-		return &ast.FieldList{
86625-			Closing: fl.Closing,
86626-			Opening: fl.Opening,
86627-		}
86628-	}
86629-	list := make([]*ast.Field, 0, len(fl.List))
86630-	for _, f := range fl.List {
86631-		list = append(list, &ast.Field{
86632-			Comment: f.Comment,
86633-			Doc:     f.Doc,
86634-			Names:   f.Names,
86635-			Tag:     f.Tag,
86636-			Type:    qualifyTypeExpr(f.Type, qf),
86637-		})
86638-	}
86639-	return &ast.FieldList{
86640-		Closing: fl.Closing,
86641-		Opening: fl.Opening,
86642-		List:    list,
86643-	}
86644-}
86645diff -urN a/gopls/internal/lsp/source/util.go b/gopls/internal/lsp/source/util.go
86646--- a/gopls/internal/lsp/source/util.go	2000-01-01 00:00:00.000000000 -0000
86647+++ b/gopls/internal/lsp/source/util.go	1970-01-01 00:00:00.000000000 +0000
86648@@ -1,555 +0,0 @@
86649-// Copyright 2019 The Go Authors. All rights reserved.
86650-// Use of this source code is governed by a BSD-style
86651-// license that can be found in the LICENSE file.
86652-
86653-package source
86654-
86655-import (
86656-	"context"
86657-	"go/ast"
86658-	"go/printer"
86659-	"go/token"
86660-	"go/types"
86661-	"path/filepath"
86662-	"regexp"
86663-	"sort"
86664-	"strconv"
86665-	"strings"
86666-
86667-	"golang.org/x/tools/gopls/internal/lsp/protocol"
86668-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
86669-	"golang.org/x/tools/gopls/internal/span"
86670-	"golang.org/x/tools/internal/bug"
86671-	"golang.org/x/tools/internal/tokeninternal"
86672-	"golang.org/x/tools/internal/typeparams"
86673-)
86674-
86675-// IsGenerated gets and reads the file denoted by uri and reports
86676-// whether it contains a "generated file" comment as described at
86677-// https://golang.org/s/generatedcode.
86678-//
86679-// TODO(adonovan): opt: this function does too much.
86680-// Move snapshot.GetFile into the caller (most of which have already done it).
86681-func IsGenerated(ctx context.Context, snapshot Snapshot, uri span.URI) bool {
86682-	fh, err := snapshot.GetFile(ctx, uri)
86683-	if err != nil {
86684-		return false
86685-	}
86686-	pgf, err := snapshot.ParseGo(ctx, fh, ParseHeader)
86687-	if err != nil {
86688-		return false
86689-	}
86690-	for _, commentGroup := range pgf.File.Comments {
86691-		for _, comment := range commentGroup.List {
86692-			if matched := generatedRx.MatchString(comment.Text); matched {
86693-				// Check if comment is at the beginning of the line in source.
86694-				if safetoken.Position(pgf.Tok, comment.Slash).Column == 1 {
86695-					return true
86696-				}
86697-			}
86698-		}
86699-	}
86700-	return false
86701-}
86702-
86703-// adjustedObjEnd returns the end position of obj, possibly modified for
86704-// package names.
86705-//
86706-// TODO(rfindley): eliminate this function, by inlining it at callsites where
86707-// it makes sense.
86708-func adjustedObjEnd(obj types.Object) token.Pos {
86709-	nameLen := len(obj.Name())
86710-	if pkgName, ok := obj.(*types.PkgName); ok {
86711-		// An imported Go package has a package-local, unqualified name.
86712-		// When the name matches the imported package name, there is no
86713-		// identifier in the import spec with the local package name.
86714-		//
86715-		// For example:
86716-		// 		import "go/ast" 	// name "ast" matches package name
86717-		// 		import a "go/ast"  	// name "a" does not match package name
86718-		//
86719-		// When the identifier does not appear in the source, have the range
86720-		// of the object be the import path, including quotes.
86721-		if pkgName.Imported().Name() == pkgName.Name() {
86722-			nameLen = len(pkgName.Imported().Path()) + len(`""`)
86723-		}
86724-	}
86725-	return obj.Pos() + token.Pos(nameLen)
86726-}
86727-
86728-// Matches cgo generated comment as well as the proposed standard:
86729-//
86730-//	https://golang.org/s/generatedcode
86731-var generatedRx = regexp.MustCompile(`// .*DO NOT EDIT\.?`)
86732-
86733-// FileKindForLang returns the file kind associated with the given language ID,
86734-// or UnknownKind if the language ID is not recognized.
86735-func FileKindForLang(langID string) FileKind {
86736-	switch langID {
86737-	case "go":
86738-		return Go
86739-	case "go.mod":
86740-		return Mod
86741-	case "go.sum":
86742-		return Sum
86743-	case "tmpl", "gotmpl":
86744-		return Tmpl
86745-	case "go.work":
86746-		return Work
86747-	default:
86748-		return UnknownKind
86749-	}
86750-}
86751-
86752-// nodeAtPos returns the index and the node whose position is contained inside
86753-// the node list.
86754-func nodeAtPos(nodes []ast.Node, pos token.Pos) (ast.Node, int) {
86755-	if nodes == nil {
86756-		return nil, -1
86757-	}
86758-	for i, node := range nodes {
86759-		if node.Pos() <= pos && pos <= node.End() {
86760-			return node, i
86761-		}
86762-	}
86763-	return nil, -1
86764-}
86765-
86766-// FormatNode returns the "pretty-print" output for an ast node.
86767-func FormatNode(fset *token.FileSet, n ast.Node) string {
86768-	var buf strings.Builder
86769-	if err := printer.Fprint(&buf, fset, n); err != nil {
86770-		return ""
86771-	}
86772-	return buf.String()
86773-}
86774-
86775-// FormatNodeFile is like FormatNode, but requires only the token.File for the
86776-// syntax containing the given ast node.
86777-func FormatNodeFile(file *token.File, n ast.Node) string {
86778-	fset := FileSetFor(file)
86779-	return FormatNode(fset, n)
86780-}
86781-
86782-// FileSetFor returns a new FileSet containing a sequence of new Files with
86783-// the same base, size, and line as the input files, for use in APIs that
86784-// require a FileSet.
86785-//
86786-// Precondition: the input files must be non-overlapping, and sorted in order
86787-// of their Base.
86788-func FileSetFor(files ...*token.File) *token.FileSet {
86789-	fset := token.NewFileSet()
86790-	for _, f := range files {
86791-		f2 := fset.AddFile(f.Name(), f.Base(), f.Size())
86792-		lines := tokeninternal.GetLines(f)
86793-		f2.SetLines(lines)
86794-	}
86795-	return fset
86796-}
86797-
86798-// Deref returns a pointer's element type, traversing as many levels as needed.
86799-// Otherwise it returns typ.
86800-//
86801-// It can return a pointer type for cyclic types (see golang/go#45510).
86802-func Deref(typ types.Type) types.Type {
86803-	var seen map[types.Type]struct{}
86804-	for {
86805-		p, ok := typ.Underlying().(*types.Pointer)
86806-		if !ok {
86807-			return typ
86808-		}
86809-		if _, ok := seen[p.Elem()]; ok {
86810-			return typ
86811-		}
86812-
86813-		typ = p.Elem()
86814-
86815-		if seen == nil {
86816-			seen = make(map[types.Type]struct{})
86817-		}
86818-		seen[typ] = struct{}{}
86819-	}
86820-}
86821-
86822-func SortDiagnostics(d []*Diagnostic) {
86823-	sort.Slice(d, func(i int, j int) bool {
86824-		return CompareDiagnostic(d[i], d[j]) < 0
86825-	})
86826-}
86827-
86828-func CompareDiagnostic(a, b *Diagnostic) int {
86829-	if r := protocol.CompareRange(a.Range, b.Range); r != 0 {
86830-		return r
86831-	}
86832-	if a.Source < b.Source {
86833-		return -1
86834-	}
86835-	if a.Source > b.Source {
86836-		return +1
86837-	}
86838-	if a.Message < b.Message {
86839-		return -1
86840-	}
86841-	if a.Message > b.Message {
86842-		return +1
86843-	}
86844-	return 0
86845-}
86846-
86847-// findFileInDeps finds package metadata containing URI in the transitive
86848-// dependencies of m. When using the Go command, the answer is unique.
86849-//
86850-// TODO(rfindley): refactor to share logic with findPackageInDeps?
86851-func findFileInDeps(s MetadataSource, m *Metadata, uri span.URI) *Metadata {
86852-	seen := make(map[PackageID]bool)
86853-	var search func(*Metadata) *Metadata
86854-	search = func(m *Metadata) *Metadata {
86855-		if seen[m.ID] {
86856-			return nil
86857-		}
86858-		seen[m.ID] = true
86859-		for _, cgf := range m.CompiledGoFiles {
86860-			if cgf == uri {
86861-				return m
86862-			}
86863-		}
86864-		for _, dep := range m.DepsByPkgPath {
86865-			m := s.Metadata(dep)
86866-			if m == nil {
86867-				bug.Reportf("nil metadata for %q", dep)
86868-				continue
86869-			}
86870-			if found := search(m); found != nil {
86871-				return found
86872-			}
86873-		}
86874-		return nil
86875-	}
86876-	return search(m)
86877-}
86878-
86879-// UnquoteImportPath returns the unquoted import path of s,
86880-// or "" if the path is not properly quoted.
86881-func UnquoteImportPath(s *ast.ImportSpec) ImportPath {
86882-	path, err := strconv.Unquote(s.Path.Value)
86883-	if err != nil {
86884-		return ""
86885-	}
86886-	return ImportPath(path)
86887-}
86888-
86889-// NodeContains returns true if a node encloses a given position pos.
86890-func NodeContains(n ast.Node, pos token.Pos) bool {
86891-	return n != nil && n.Pos() <= pos && pos <= n.End()
86892-}
86893-
86894-// CollectScopes returns all scopes in an ast path, ordered as innermost scope
86895-// first.
86896-func CollectScopes(info *types.Info, path []ast.Node, pos token.Pos) []*types.Scope {
86897-	// scopes[i], where i<len(path), is the possibly nil Scope of path[i].
86898-	var scopes []*types.Scope
86899-	for _, n := range path {
86900-		// Include *FuncType scope if pos is inside the function body.
86901-		switch node := n.(type) {
86902-		case *ast.FuncDecl:
86903-			if node.Body != nil && NodeContains(node.Body, pos) {
86904-				n = node.Type
86905-			}
86906-		case *ast.FuncLit:
86907-			if node.Body != nil && NodeContains(node.Body, pos) {
86908-				n = node.Type
86909-			}
86910-		}
86911-		scopes = append(scopes, info.Scopes[n])
86912-	}
86913-	return scopes
86914-}
86915-
86916-// Qualifier returns a function that appropriately formats a types.PkgName
86917-// appearing in a *ast.File.
86918-func Qualifier(f *ast.File, pkg *types.Package, info *types.Info) types.Qualifier {
86919-	// Construct mapping of import paths to their defined or implicit names.
86920-	imports := make(map[*types.Package]string)
86921-	for _, imp := range f.Imports {
86922-		var obj types.Object
86923-		if imp.Name != nil {
86924-			obj = info.Defs[imp.Name]
86925-		} else {
86926-			obj = info.Implicits[imp]
86927-		}
86928-		if pkgname, ok := obj.(*types.PkgName); ok {
86929-			imports[pkgname.Imported()] = pkgname.Name()
86930-		}
86931-	}
86932-	// Define qualifier to replace full package paths with names of the imports.
86933-	return func(p *types.Package) string {
86934-		if p == pkg {
86935-			return ""
86936-		}
86937-		if name, ok := imports[p]; ok {
86938-			if name == "." {
86939-				return ""
86940-			}
86941-			return name
86942-		}
86943-		return p.Name()
86944-	}
86945-}
86946-
86947-// requalifier returns a function that re-qualifies identifiers and qualified
86948-// identifiers contained in targetFile using the given metadata qualifier.
86949-func requalifier(s MetadataSource, targetFile *ast.File, targetMeta *Metadata, mq MetadataQualifier) func(string) string {
86950-	qm := map[string]string{
86951-		"": mq(targetMeta.Name, "", targetMeta.PkgPath),
86952-	}
86953-
86954-	// Construct mapping of import paths to their defined or implicit names.
86955-	for _, imp := range targetFile.Imports {
86956-		name, pkgName, impPath, pkgPath := importInfo(s, imp, targetMeta)
86957-
86958-		// Re-map the target name for the source file.
86959-		qm[name] = mq(pkgName, impPath, pkgPath)
86960-	}
86961-
86962-	return func(name string) string {
86963-		if newName, ok := qm[name]; ok {
86964-			return newName
86965-		}
86966-		return name
86967-	}
86968-}
86969-
86970-// A MetadataQualifier is a function that qualifies an identifier declared in a
86971-// package with the given package name, import path, and package path.
86972-//
86973-// In scenarios where metadata is missing the provided PackageName and
86974-// PackagePath may be empty, but ImportPath must always be non-empty.
86975-type MetadataQualifier func(PackageName, ImportPath, PackagePath) string
86976-
86977-// MetadataQualifierForFile returns a metadata qualifier that chooses the best
86978-// qualification of an imported package relative to the file f in package with
86979-// metadata m.
86980-func MetadataQualifierForFile(s MetadataSource, f *ast.File, m *Metadata) MetadataQualifier {
86981-	// Record local names for import paths.
86982-	localNames := make(map[ImportPath]string) // local names for imports in f
86983-	for _, imp := range f.Imports {
86984-		name, _, impPath, _ := importInfo(s, imp, m)
86985-		localNames[impPath] = name
86986-	}
86987-
86988-	// Record a package path -> import path mapping.
86989-	inverseDeps := make(map[PackageID]PackagePath)
86990-	for path, id := range m.DepsByPkgPath {
86991-		inverseDeps[id] = path
86992-	}
86993-	importsByPkgPath := make(map[PackagePath]ImportPath) // best import paths by pkgPath
86994-	for impPath, id := range m.DepsByImpPath {
86995-		if id == "" {
86996-			continue
86997-		}
86998-		pkgPath := inverseDeps[id]
86999-		_, hasPath := importsByPkgPath[pkgPath]
87000-		_, hasImp := localNames[impPath]
87001-		// In rare cases, there may be multiple import paths with the same package
87002-		// path. In such scenarios, prefer an import path that already exists in
87003-		// the file.
87004-		if !hasPath || hasImp {
87005-			importsByPkgPath[pkgPath] = impPath
87006-		}
87007-	}
87008-
87009-	return func(pkgName PackageName, impPath ImportPath, pkgPath PackagePath) string {
87010-		// If supplied, translate the package path to an import path in the source
87011-		// package.
87012-		if pkgPath != "" {
87013-			if srcImp := importsByPkgPath[pkgPath]; srcImp != "" {
87014-				impPath = srcImp
87015-			}
87016-			if pkgPath == m.PkgPath {
87017-				return ""
87018-			}
87019-		}
87020-		if localName, ok := localNames[impPath]; ok && impPath != "" {
87021-			return string(localName)
87022-		}
87023-		if pkgName != "" {
87024-			return string(pkgName)
87025-		}
87026-		idx := strings.LastIndexByte(string(impPath), '/')
87027-		return string(impPath[idx+1:])
87028-	}
87029-}
87030-
87031-// importInfo collects information about the import specified by imp,
87032-// extracting its file-local name, package name, import path, and package path.
87033-//
87034-// If metadata is missing for the import, the resulting package name and
87035-// package path may be empty, and the file local name may be guessed based on
87036-// the import path.
87037-//
87038-// Note: previous versions of this helper used a PackageID->PackagePath map
87039-// extracted from m, for extracting package path even in the case where
87040-// metadata for a dep was missing. This should not be necessary, as we should
87041-// always have metadata for IDs contained in DepsByPkgPath.
87042-func importInfo(s MetadataSource, imp *ast.ImportSpec, m *Metadata) (string, PackageName, ImportPath, PackagePath) {
87043-	var (
87044-		name    string // local name
87045-		pkgName PackageName
87046-		impPath = UnquoteImportPath(imp)
87047-		pkgPath PackagePath
87048-	)
87049-
87050-	// If the import has a local name, use it.
87051-	if imp.Name != nil {
87052-		name = imp.Name.Name
87053-	}
87054-
87055-	// Try to find metadata for the import. If successful and there is no local
87056-	// name, the package name is the local name.
87057-	if depID := m.DepsByImpPath[impPath]; depID != "" {
87058-		if depm := s.Metadata(depID); depm != nil {
87059-			if name == "" {
87060-				name = string(depm.Name)
87061-			}
87062-			pkgName = depm.Name
87063-			pkgPath = depm.PkgPath
87064-		}
87065-	}
87066-
87067-	// If the local name is still unknown, guess it based on the import path.
87068-	if name == "" {
87069-		idx := strings.LastIndexByte(string(impPath), '/')
87070-		name = string(impPath[idx+1:])
87071-	}
87072-	return name, pkgName, impPath, pkgPath
87073-}
87074-
87075-// isDirective reports whether c is a comment directive.
87076-//
87077-// Copied and adapted from go/src/go/ast/ast.go.
87078-func isDirective(c string) bool {
87079-	if len(c) < 3 {
87080-		return false
87081-	}
87082-	if c[1] != '/' {
87083-		return false
87084-	}
87085-	//-style comment (no newline at the end)
87086-	c = c[2:]
87087-	if len(c) == 0 {
87088-		// empty line
87089-		return false
87090-	}
87091-	// "//line " is a line directive.
87092-	// (The // has been removed.)
87093-	if strings.HasPrefix(c, "line ") {
87094-		return true
87095-	}
87096-
87097-	// "//[a-z0-9]+:[a-z0-9]"
87098-	// (The // has been removed.)
87099-	colon := strings.Index(c, ":")
87100-	if colon <= 0 || colon+1 >= len(c) {
87101-		return false
87102-	}
87103-	for i := 0; i <= colon+1; i++ {
87104-		if i == colon {
87105-			continue
87106-		}
87107-		b := c[i]
87108-		if !('a' <= b && b <= 'z' || '0' <= b && b <= '9') {
87109-			return false
87110-		}
87111-	}
87112-	return true
87113-}
87114-
87115-// InDir checks whether path is in the file tree rooted at dir.
87116-// It checks only the lexical form of the file names.
87117-// It does not consider symbolic links.
87118-//
87119-// Copied from go/src/cmd/go/internal/search/search.go.
87120-func InDir(dir, path string) bool {
87121-	pv := strings.ToUpper(filepath.VolumeName(path))
87122-	dv := strings.ToUpper(filepath.VolumeName(dir))
87123-	path = path[len(pv):]
87124-	dir = dir[len(dv):]
87125-	switch {
87126-	default:
87127-		return false
87128-	case pv != dv:
87129-		return false
87130-	case len(path) == len(dir):
87131-		if path == dir {
87132-			return true
87133-		}
87134-		return false
87135-	case dir == "":
87136-		return path != ""
87137-	case len(path) > len(dir):
87138-		if dir[len(dir)-1] == filepath.Separator {
87139-			if path[:len(dir)] == dir {
87140-				return path[len(dir):] != ""
87141-			}
87142-			return false
87143-		}
87144-		if path[len(dir)] == filepath.Separator && path[:len(dir)] == dir {
87145-			if len(path) == len(dir)+1 {
87146-				return true
87147-			}
87148-			return path[len(dir)+1:] != ""
87149-		}
87150-		return false
87151-	}
87152-}
87153-
87154-// IsValidImport returns whether importPkgPath is importable
87155-// by pkgPath
87156-func IsValidImport(pkgPath, importPkgPath PackagePath) bool {
87157-	i := strings.LastIndex(string(importPkgPath), "/internal/")
87158-	if i == -1 {
87159-		return true
87160-	}
87161-	// TODO(rfindley): this looks wrong: IsCommandLineArguments is meant to
87162-	// operate on package IDs, not package paths.
87163-	if IsCommandLineArguments(PackageID(pkgPath)) {
87164-		return true
87165-	}
87166-	// TODO(rfindley): this is wrong. mod.testx/p should not be able to
87167-	// import mod.test/internal: https://go.dev/play/p/-Ca6P-E4V4q
87168-	return strings.HasPrefix(string(pkgPath), string(importPkgPath[:i]))
87169-}
87170-
87171-// IsCommandLineArguments reports whether a given value denotes
87172-// "command-line-arguments" package, which is a package with an unknown ID
87173-// created by the go command. It can have a test variant, which is why callers
87174-// should not check that a value equals "command-line-arguments" directly.
87175-func IsCommandLineArguments(id PackageID) bool {
87176-	return strings.Contains(string(id), "command-line-arguments")
87177-}
87178-
87179-// embeddedIdent returns the type name identifier for an embedding x, if x in a
87180-// valid embedding. Otherwise, it returns nil.
87181-//
87182-// Spec: An embedded field must be specified as a type name T or as a pointer
87183-// to a non-interface type name *T
87184-func embeddedIdent(x ast.Expr) *ast.Ident {
87185-	if star, ok := x.(*ast.StarExpr); ok {
87186-		x = star.X
87187-	}
87188-	switch ix := x.(type) { // check for instantiated receivers
87189-	case *ast.IndexExpr:
87190-		x = ix.X
87191-	case *typeparams.IndexListExpr:
87192-		x = ix.X
87193-	}
87194-	switch x := x.(type) {
87195-	case *ast.Ident:
87196-		return x
87197-	case *ast.SelectorExpr:
87198-		if _, ok := x.X.(*ast.Ident); ok {
87199-			return x.Sel
87200-		}
87201-	}
87202-	return nil
87203-}
87204diff -urN a/gopls/internal/lsp/source/view.go b/gopls/internal/lsp/source/view.go
87205--- a/gopls/internal/lsp/source/view.go	2000-01-01 00:00:00.000000000 -0000
87206+++ b/gopls/internal/lsp/source/view.go	1970-01-01 00:00:00.000000000 +0000
87207@@ -1,857 +0,0 @@
87208-// Copyright 2018 The Go Authors. All rights reserved.
87209-// Use of this source code is governed by a BSD-style
87210-// license that can be found in the LICENSE file.
87211-
87212-package source
87213-
87214-import (
87215-	"bytes"
87216-	"context"
87217-	"crypto/sha256"
87218-	"errors"
87219-	"fmt"
87220-	"go/ast"
87221-	"go/scanner"
87222-	"go/token"
87223-	"go/types"
87224-	"io"
87225-
87226-	"golang.org/x/mod/modfile"
87227-	"golang.org/x/tools/go/analysis"
87228-	"golang.org/x/tools/go/packages"
87229-	"golang.org/x/tools/go/types/objectpath"
87230-	"golang.org/x/tools/gopls/internal/govulncheck"
87231-	"golang.org/x/tools/gopls/internal/lsp/protocol"
87232-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
87233-	"golang.org/x/tools/gopls/internal/lsp/source/methodsets"
87234-	"golang.org/x/tools/gopls/internal/span"
87235-	"golang.org/x/tools/internal/event/label"
87236-	"golang.org/x/tools/internal/event/tag"
87237-	"golang.org/x/tools/internal/gocommand"
87238-	"golang.org/x/tools/internal/imports"
87239-	"golang.org/x/tools/internal/packagesinternal"
87240-)
87241-
87242-// A GlobalSnapshotID uniquely identifies a snapshot within this process and
87243-// increases monotonically with snapshot creation time.
87244-//
87245-// We use a distinct integral type for global IDs to help enforce correct
87246-// usage.
87247-type GlobalSnapshotID uint64
87248-
87249-// Snapshot represents the current state for the given view.
87250-type Snapshot interface {
87251-	// SequenceID is the sequence id of this snapshot within its containing
87252-	// view.
87253-	//
87254-	// Relative to their view sequence ids are monotonically increasing, but this
87255-	// does not hold globally: when new views are created their initial snapshot
87256-	// has sequence ID 0. For operations that span multiple views, use global
87257-	// IDs.
87258-	SequenceID() uint64
87259-
87260-	// GlobalID is a globally unique identifier for this snapshot. Global IDs are
87261-	// monotonic: subsequent snapshots will have higher global ID, though
87262-	// subsequent snapshots in a view may not have adjacent global IDs.
87263-	GlobalID() GlobalSnapshotID
87264-
87265-	// View returns the View associated with this snapshot.
87266-	View() View
87267-
87268-	// BackgroundContext returns a context used for all background processing
87269-	// on behalf of this snapshot.
87270-	BackgroundContext() context.Context
87271-
87272-	// ValidBuildConfiguration returns true if there is some error in the
87273-	// user's workspace. In particular, if they are both outside of a module
87274-	// and their GOPATH.
87275-	ValidBuildConfiguration() bool
87276-
87277-	// FindFile returns the FileHandle for the given URI, if it is already
87278-	// in the given snapshot.
87279-	FindFile(uri span.URI) FileHandle
87280-
87281-	// GetFile returns the FileHandle for a given URI, initializing it if it is
87282-	// not already part of the snapshot.
87283-	GetFile(ctx context.Context, uri span.URI) (FileHandle, error)
87284-
87285-	// AwaitInitialized waits until the snapshot's view is initialized.
87286-	AwaitInitialized(ctx context.Context)
87287-
87288-	// IsOpen returns whether the editor currently has a file open.
87289-	IsOpen(uri span.URI) bool
87290-
87291-	// IgnoredFile reports if a file would be ignored by a `go list` of the whole
87292-	// workspace.
87293-	IgnoredFile(uri span.URI) bool
87294-
87295-	// Templates returns the .tmpl files
87296-	Templates() map[span.URI]FileHandle
87297-
87298-	// ParseGo returns the parsed AST for the file.
87299-	// If the file is not available, returns nil and an error.
87300-	// Position information is added to FileSet().
87301-	ParseGo(ctx context.Context, fh FileHandle, mode ParseMode) (*ParsedGoFile, error)
87302-
87303-	// Analyze runs the specified analyzers on the given package at this snapshot.
87304-	Analyze(ctx context.Context, id PackageID, analyzers []*Analyzer) ([]*Diagnostic, error)
87305-
87306-	// RunGoCommandPiped runs the given `go` command, writing its output
87307-	// to stdout and stderr. Verb, Args, and WorkingDir must be specified.
87308-	//
87309-	// RunGoCommandPiped runs the command serially using gocommand.RunPiped,
87310-	// enforcing that this command executes exclusively to other commands on the
87311-	// server.
87312-	RunGoCommandPiped(ctx context.Context, mode InvocationFlags, inv *gocommand.Invocation, stdout, stderr io.Writer) error
87313-
87314-	// RunGoCommandDirect runs the given `go` command. Verb, Args, and
87315-	// WorkingDir must be specified.
87316-	RunGoCommandDirect(ctx context.Context, mode InvocationFlags, inv *gocommand.Invocation) (*bytes.Buffer, error)
87317-
87318-	// RunGoCommands runs a series of `go` commands that updates the go.mod
87319-	// and go.sum file for wd, and returns their updated contents.
87320-	RunGoCommands(ctx context.Context, allowNetwork bool, wd string, run func(invoke func(...string) (*bytes.Buffer, error)) error) (bool, []byte, []byte, error)
87321-
87322-	// RunProcessEnvFunc runs fn with the process env for this snapshot's view.
87323-	// Note: the process env contains cached module and filesystem state.
87324-	RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options) error) error
87325-
87326-	// ModFiles are the go.mod files enclosed in the snapshot's view and known
87327-	// to the snapshot.
87328-	ModFiles() []span.URI
87329-
87330-	// ParseMod is used to parse go.mod files.
87331-	ParseMod(ctx context.Context, fh FileHandle) (*ParsedModule, error)
87332-
87333-	// ModWhy returns the results of `go mod why` for the module specified by
87334-	// the given go.mod file.
87335-	ModWhy(ctx context.Context, fh FileHandle) (map[string]string, error)
87336-
87337-	// ModTidy returns the results of `go mod tidy` for the module specified by
87338-	// the given go.mod file.
87339-	ModTidy(ctx context.Context, pm *ParsedModule) (*TidiedModule, error)
87340-
87341-	// ModVuln returns import vulnerability analysis for the given go.mod URI.
87342-	// Concurrent requests are combined into a single command.
87343-	ModVuln(ctx context.Context, modURI span.URI) (*govulncheck.Result, error)
87344-
87345-	// GoModForFile returns the URI of the go.mod file for the given URI.
87346-	GoModForFile(uri span.URI) span.URI
87347-
87348-	// WorkFile, if non-empty, is the go.work file for the workspace.
87349-	WorkFile() span.URI
87350-
87351-	// ParseWork is used to parse go.work files.
87352-	ParseWork(ctx context.Context, fh FileHandle) (*ParsedWorkFile, error)
87353-
87354-	// BuiltinFile returns information about the special builtin package.
87355-	BuiltinFile(ctx context.Context) (*ParsedGoFile, error)
87356-
87357-	// IsBuiltin reports whether uri is part of the builtin package.
87358-	IsBuiltin(ctx context.Context, uri span.URI) bool
87359-
87360-	// ReverseDependencies returns a new mapping whose entries are
87361-	// the ID and Metadata of each package in the workspace that
87362-	// directly or transitively depend on the package denoted by id,
87363-	// excluding id itself.
87364-	ReverseDependencies(ctx context.Context, id PackageID, transitive bool) (map[PackageID]*Metadata, error)
87365-
87366-	// ActiveMetadata returns a new, unordered slice containing
87367-	// metadata for all packages considered 'active' in the workspace.
87368-	//
87369-	// In normal memory mode, this is all workspace packages. In degraded memory
87370-	// mode, this is just the reverse transitive closure of open packages.
87371-	ActiveMetadata(ctx context.Context) ([]*Metadata, error)
87372-
87373-	// AllMetadata returns a new unordered array of metadata for all packages in the workspace.
87374-	AllMetadata(ctx context.Context) ([]*Metadata, error)
87375-
87376-	// Symbols returns all symbols in the snapshot.
87377-	Symbols(ctx context.Context) (map[span.URI][]Symbol, error)
87378-
87379-	// Metadata returns the metadata for the specified package,
87380-	// or nil if it was not found.
87381-	Metadata(id PackageID) *Metadata
87382-
87383-	// MetadataForFile returns a new slice containing metadata for each
87384-	// package containing the Go file identified by uri, ordered by the
87385-	// number of CompiledGoFiles (i.e. "narrowest" to "widest" package).
87386-	// The result may include tests and intermediate test variants of
87387-	// importable packages.
87388-	// It returns an error if the context was cancelled.
87389-	MetadataForFile(ctx context.Context, uri span.URI) ([]*Metadata, error)
87390-
87391-	// TypeCheck parses and type-checks the specified packages,
87392-	// and returns them in the same order as the ids.
87393-	// The resulting packages' types may belong to different importers,
87394-	// so types from different packages are incommensurable.
87395-	TypeCheck(ctx context.Context, ids ...PackageID) ([]Package, error)
87396-
87397-	// PackageDiagnostics returns diagnostics for files contained in specified
87398-	// packages.
87399-	//
87400-	// If these diagnostics cannot be loaded from cache, the requested packages
87401-	// may be type-checked.
87402-	PackageDiagnostics(ctx context.Context, ids ...PackageID) (map[span.URI][]*Diagnostic, error)
87403-
87404-	// References returns cross-references indexes for the specified packages.
87405-	//
87406-	// If these indexes cannot be loaded from cache, the requested packages may
87407-	// be type-checked.
87408-	References(ctx context.Context, ids ...PackageID) ([]XrefIndex, error)
87409-
87410-	// MethodSets returns method-set indexes for the specified packages.
87411-	//
87412-	// If these indexes cannot be loaded from cache, the requested packages may
87413-	// be type-checked.
87414-	MethodSets(ctx context.Context, ids ...PackageID) ([]*methodsets.Index, error)
87415-
87416-	// GetCriticalError returns any critical errors in the workspace.
87417-	//
87418-	// A nil result may mean success, or context cancellation.
87419-	GetCriticalError(ctx context.Context) *CriticalError
87420-}
87421-
87422-type XrefIndex interface {
87423-	Lookup(targets map[PackagePath]map[objectpath.Path]struct{}) (locs []protocol.Location)
87424-}
87425-
87426-// SnapshotLabels returns a new slice of labels that should be used for events
87427-// related to a snapshot.
87428-func SnapshotLabels(snapshot Snapshot) []label.Label {
87429-	return []label.Label{tag.Snapshot.Of(snapshot.SequenceID()), tag.Directory.Of(snapshot.View().Folder())}
87430-}
87431-
87432-// PackageForFile is a convenience function that selects a package to
87433-// which this file belongs (narrowest or widest), type-checks it in
87434-// the requested mode (full or workspace), and returns it, along with
87435-// the parse tree of that file.
87436-//
87437-// Type-checking is expensive. Call snapshot.ParseGo if all you need
87438-// is a parse tree, or snapshot.MetadataForFile if you only need metadata.
87439-func PackageForFile(ctx context.Context, snapshot Snapshot, uri span.URI, pkgSel PackageSelector) (Package, *ParsedGoFile, error) {
87440-	metas, err := snapshot.MetadataForFile(ctx, uri)
87441-	if err != nil {
87442-		return nil, nil, err
87443-	}
87444-	if len(metas) == 0 {
87445-		return nil, nil, fmt.Errorf("no package metadata for file %s", uri)
87446-	}
87447-	switch pkgSel {
87448-	case NarrowestPackage:
87449-		metas = metas[:1]
87450-	case WidestPackage:
87451-		metas = metas[len(metas)-1:]
87452-	}
87453-	pkgs, err := snapshot.TypeCheck(ctx, metas[0].ID)
87454-	if err != nil {
87455-		return nil, nil, err
87456-	}
87457-	pkg := pkgs[0]
87458-	pgf, err := pkg.File(uri)
87459-	if err != nil {
87460-		return nil, nil, err // "can't happen"
87461-	}
87462-	return pkg, pgf, err
87463-}
87464-
87465-// PackageSelector sets how a package is selected out from a set of packages
87466-// containing a given file.
87467-type PackageSelector int
87468-
87469-const (
87470-	// NarrowestPackage picks the "narrowest" package for a given file.
87471-	// By "narrowest" package, we mean the package with the fewest number of
87472-	// files that includes the given file. This solves the problem of test
87473-	// variants, as the test will have more files than the non-test package.
87474-	NarrowestPackage PackageSelector = iota
87475-
87476-	// WidestPackage returns the Package containing the most files.
87477-	// This is useful for something like diagnostics, where we'd prefer to
87478-	// offer diagnostics for as many files as possible.
87479-	WidestPackage
87480-)
87481-
87482-// InvocationFlags represents the settings of a particular go command invocation.
87483-// It is a mode, plus a set of flag bits.
87484-type InvocationFlags int
87485-
87486-const (
87487-	// Normal is appropriate for commands that might be run by a user and don't
87488-	// deliberately modify go.mod files, e.g. `go test`.
87489-	Normal InvocationFlags = iota
87490-	// WriteTemporaryModFile is for commands that need information from a
87491-	// modified version of the user's go.mod file, e.g. `go mod tidy` used to
87492-	// generate diagnostics.
87493-	WriteTemporaryModFile
87494-	// LoadWorkspace is for packages.Load, and other operations that should
87495-	// consider the whole workspace at once.
87496-	LoadWorkspace
87497-
87498-	// AllowNetwork is a flag bit that indicates the invocation should be
87499-	// allowed to access the network.
87500-	AllowNetwork InvocationFlags = 1 << 10
87501-)
87502-
87503-func (m InvocationFlags) Mode() InvocationFlags {
87504-	return m & (AllowNetwork - 1)
87505-}
87506-
87507-func (m InvocationFlags) AllowNetwork() bool {
87508-	return m&AllowNetwork != 0
87509-}
87510-
87511-// View represents a single workspace.
87512-// This is the level at which we maintain configuration like working directory
87513-// and build tags.
87514-type View interface {
87515-	// Name returns the name this view was constructed with.
87516-	Name() string
87517-
87518-	// Folder returns the folder with which this view was created.
87519-	Folder() span.URI
87520-
87521-	// Options returns a copy of the Options for this view.
87522-	Options() *Options
87523-
87524-	// Snapshot returns the current snapshot for the view, and a
87525-	// release function that must be called when the Snapshot is
87526-	// no longer needed.
87527-	//
87528-	// If the view is shut down, the resulting error will be non-nil, and the
87529-	// release function need not be called.
87530-	Snapshot() (Snapshot, func(), error)
87531-
87532-	// IsGoPrivatePath reports whether target is a private import path, as identified
87533-	// by the GOPRIVATE environment variable.
87534-	IsGoPrivatePath(path string) bool
87535-
87536-	// ModuleUpgrades returns known module upgrades for the dependencies of
87537-	// modfile.
87538-	ModuleUpgrades(modfile span.URI) map[string]string
87539-
87540-	// RegisterModuleUpgrades registers that upgrades exist for the given modules
87541-	// required by modfile.
87542-	RegisterModuleUpgrades(modfile span.URI, upgrades map[string]string)
87543-
87544-	// ClearModuleUpgrades clears all upgrades for the modules in modfile.
87545-	ClearModuleUpgrades(modfile span.URI)
87546-
87547-	// Vulnerabilities returns known vulnerabilities for the given modfile.
87548-	// TODO(suzmue): replace command.Vuln with a different type, maybe
87549-	// https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck/govulnchecklib#Summary?
87550-	Vulnerabilities(modfile ...span.URI) map[span.URI]*govulncheck.Result
87551-
87552-	// SetVulnerabilities resets the list of vulnerabilities that exists for the given modules
87553-	// required by modfile.
87554-	SetVulnerabilities(modfile span.URI, vulncheckResult *govulncheck.Result)
87555-
87556-	// FileKind returns the type of a file.
87557-	//
87558-	// We can't reliably deduce the kind from the file name alone,
87559-	// as some editors can be told to interpret a buffer as
87560-	// language different from the file name heuristic, e.g. that
87561-	// an .html file actually contains Go "html/template" syntax,
87562-	// or even that a .go file contains Python.
87563-	FileKind(FileHandle) FileKind
87564-
87565-	// GoVersion returns the configured Go version for this view.
87566-	GoVersion() int
87567-
87568-	// GoVersionString returns the go version string configured for this view.
87569-	// Unlike [GoVersion], this encodes the minor version and commit hash information.
87570-	GoVersionString() string
87571-}
87572-
87573-// A FileSource maps uris to FileHandles.
87574-type FileSource interface {
87575-	// GetFile returns the FileHandle for a given URI.
87576-	GetFile(ctx context.Context, uri span.URI) (FileHandle, error)
87577-}
87578-
87579-// A MetadataSource maps package IDs to metadata.
87580-//
87581-// TODO(rfindley): replace this with a concrete metadata graph, once it is
87582-// exposed from the snapshot.
87583-type MetadataSource interface {
87584-	// Metadata returns Metadata for the given package ID, or nil if it does not
87585-	// exist.
87586-	Metadata(PackageID) *Metadata
87587-}
87588-
87589-// A ParsedGoFile contains the results of parsing a Go file.
87590-type ParsedGoFile struct {
87591-	URI  span.URI
87592-	Mode ParseMode
87593-	File *ast.File
87594-	Tok  *token.File
87595-	// Source code used to build the AST. It may be different from the
87596-	// actual content of the file if we have fixed the AST.
87597-	Src      []byte
87598-	Fixed    bool
87599-	Mapper   *protocol.Mapper // may map fixed Src, not file content
87600-	ParseErr scanner.ErrorList
87601-}
87602-
87603-// -- go/token domain convenience helpers --
87604-
87605-// PositionPos returns the token.Pos of protocol position p within the file.
87606-func (pgf *ParsedGoFile) PositionPos(p protocol.Position) (token.Pos, error) {
87607-	offset, err := pgf.Mapper.PositionOffset(p)
87608-	if err != nil {
87609-		return token.NoPos, err
87610-	}
87611-	return safetoken.Pos(pgf.Tok, offset)
87612-}
87613-
87614-// PosRange returns a protocol Range for the token.Pos interval in this file.
87615-func (pgf *ParsedGoFile) PosRange(start, end token.Pos) (protocol.Range, error) {
87616-	return pgf.Mapper.PosRange(pgf.Tok, start, end)
87617-}
87618-
87619-// PosMappedRange returns a MappedRange for the token.Pos interval in this file.
87620-// A MappedRange can be converted to any other form.
87621-func (pgf *ParsedGoFile) PosMappedRange(start, end token.Pos) (protocol.MappedRange, error) {
87622-	return pgf.Mapper.PosMappedRange(pgf.Tok, start, end)
87623-}
87624-
87625-// PosLocation returns a protocol Location for the token.Pos interval in this file.
87626-func (pgf *ParsedGoFile) PosLocation(start, end token.Pos) (protocol.Location, error) {
87627-	return pgf.Mapper.PosLocation(pgf.Tok, start, end)
87628-}
87629-
87630-// NodeRange returns a protocol Range for the ast.Node interval in this file.
87631-func (pgf *ParsedGoFile) NodeRange(node ast.Node) (protocol.Range, error) {
87632-	return pgf.Mapper.NodeRange(pgf.Tok, node)
87633-}
87634-
87635-// NodeMappedRange returns a MappedRange for the ast.Node interval in this file.
87636-// A MappedRange can be converted to any other form.
87637-func (pgf *ParsedGoFile) NodeMappedRange(node ast.Node) (protocol.MappedRange, error) {
87638-	return pgf.Mapper.NodeMappedRange(pgf.Tok, node)
87639-}
87640-
87641-// NodeLocation returns a protocol Location for the ast.Node interval in this file.
87642-func (pgf *ParsedGoFile) NodeLocation(node ast.Node) (protocol.Location, error) {
87643-	return pgf.Mapper.PosLocation(pgf.Tok, node.Pos(), node.End())
87644-}
87645-
87646-// RangePos parses a protocol Range back into the go/token domain.
87647-func (pgf *ParsedGoFile) RangePos(r protocol.Range) (token.Pos, token.Pos, error) {
87648-	start, end, err := pgf.Mapper.RangeOffsets(r)
87649-	if err != nil {
87650-		return token.NoPos, token.NoPos, err
87651-	}
87652-	return pgf.Tok.Pos(start), pgf.Tok.Pos(end), nil
87653-}
87654-
87655-// A ParsedModule contains the results of parsing a go.mod file.
87656-type ParsedModule struct {
87657-	URI         span.URI
87658-	File        *modfile.File
87659-	Mapper      *protocol.Mapper
87660-	ParseErrors []*Diagnostic
87661-}
87662-
87663-// A ParsedWorkFile contains the results of parsing a go.work file.
87664-type ParsedWorkFile struct {
87665-	URI         span.URI
87666-	File        *modfile.WorkFile
87667-	Mapper      *protocol.Mapper
87668-	ParseErrors []*Diagnostic
87669-}
87670-
87671-// A TidiedModule contains the results of running `go mod tidy` on a module.
87672-type TidiedModule struct {
87673-	// Diagnostics representing changes made by `go mod tidy`.
87674-	Diagnostics []*Diagnostic
87675-	// The bytes of the go.mod file after it was tidied.
87676-	TidiedContent []byte
87677-}
87678-
87679-// Metadata represents package metadata retrieved from go/packages.
87680-type Metadata struct {
87681-	ID              PackageID
87682-	PkgPath         PackagePath
87683-	Name            PackageName
87684-	GoFiles         []span.URI
87685-	CompiledGoFiles []span.URI
87686-	ForTest         PackagePath // package path under test, or ""
87687-	TypesSizes      types.Sizes
87688-	Errors          []packages.Error
87689-	DepsByImpPath   map[ImportPath]PackageID  // may contain dups; empty ID => missing
87690-	DepsByPkgPath   map[PackagePath]PackageID // values are unique and non-empty
87691-	Module          *packages.Module
87692-	DepsErrors      []*packagesinternal.PackageError
87693-	Diagnostics     []*Diagnostic // processed diagnostics from 'go list'
87694-	LoadDir         string        // directory from which go/packages was run
87695-}
87696-
87697-func (m *Metadata) String() string { return string(m.ID) }
87698-
87699-// IsIntermediateTestVariant reports whether the given package is an
87700-// intermediate test variant, e.g. "net/http [net/url.test]".
87701-//
87702-// Such test variants arise when an x_test package (in this case net/url_test)
87703-// imports a package (in this case net/http) that itself imports the the
87704-// non-x_test package (in this case net/url).
87705-//
87706-// This is done so that the forward transitive closure of net/url_test has
87707-// only one package for the "net/url" import.
87708-// The intermediate test variant exists to hold the test variant import:
87709-//
87710-// net/url_test [net/url.test]
87711-//
87712-//	| "net/http" -> net/http [net/url.test]
87713-//	| "net/url" -> net/url [net/url.test]
87714-//	| ...
87715-//
87716-// net/http [net/url.test]
87717-//
87718-//	| "net/url" -> net/url [net/url.test]
87719-//	| ...
87720-//
87721-// This restriction propagates throughout the import graph of net/http: for
87722-// every package imported by net/http that imports net/url, there must be an
87723-// intermediate test variant that instead imports "net/url [net/url.test]".
87724-//
87725-// As one can see from the example of net/url and net/http, intermediate test
87726-// variants can result in many additional packages that are essentially (but
87727-// not quite) identical. For this reason, we filter these variants wherever
87728-// possible.
87729-func (m *Metadata) IsIntermediateTestVariant() bool {
87730-	return m.ForTest != "" && m.ForTest != m.PkgPath && m.ForTest+"_test" != m.PkgPath
87731-}
87732-
87733-// RemoveIntermediateTestVariants removes intermediate test variants, modifying the array.
87734-func RemoveIntermediateTestVariants(metas []*Metadata) []*Metadata {
87735-	res := metas[:0]
87736-	for _, m := range metas {
87737-		if !m.IsIntermediateTestVariant() {
87738-			res = append(res, m)
87739-		}
87740-	}
87741-	return res
87742-}
87743-
87744-var ErrViewExists = errors.New("view already exists for session")
87745-
87746-// FileModification represents a modification to a file.
87747-type FileModification struct {
87748-	URI    span.URI
87749-	Action FileAction
87750-
87751-	// OnDisk is true if a watched file is changed on disk.
87752-	// If true, Version will be -1 and Text will be nil.
87753-	OnDisk bool
87754-
87755-	// Version will be -1 and Text will be nil when they are not supplied,
87756-	// specifically on textDocument/didClose and for on-disk changes.
87757-	Version int32
87758-	Text    []byte
87759-
87760-	// LanguageID is only sent from the language client on textDocument/didOpen.
87761-	LanguageID string
87762-}
87763-
87764-type FileAction int
87765-
87766-const (
87767-	UnknownFileAction = FileAction(iota)
87768-	Open
87769-	Change
87770-	Close
87771-	Save
87772-	Create
87773-	Delete
87774-	InvalidateMetadata
87775-)
87776-
87777-func (a FileAction) String() string {
87778-	switch a {
87779-	case Open:
87780-		return "Open"
87781-	case Change:
87782-		return "Change"
87783-	case Close:
87784-		return "Close"
87785-	case Save:
87786-		return "Save"
87787-	case Create:
87788-		return "Create"
87789-	case Delete:
87790-		return "Delete"
87791-	case InvalidateMetadata:
87792-		return "InvalidateMetadata"
87793-	default:
87794-		return "Unknown"
87795-	}
87796-}
87797-
87798-var ErrTmpModfileUnsupported = errors.New("-modfile is unsupported for this Go version")
87799-var ErrNoModOnDisk = errors.New("go.mod file is not on disk")
87800-
87801-func IsNonFatalGoModError(err error) bool {
87802-	return err == ErrTmpModfileUnsupported || err == ErrNoModOnDisk
87803-}
87804-
87805-// ParseMode controls the content of the AST produced when parsing a source file.
87806-type ParseMode int
87807-
87808-const (
87809-	// ParseHeader specifies that the main package declaration and imports are needed.
87810-	// This is the mode used when attempting to examine the package graph structure.
87811-	ParseHeader ParseMode = iota
87812-
87813-	// ParseFull specifies the full AST is needed.
87814-	// This is used for files of direct interest where the entire contents must
87815-	// be considered.
87816-	ParseFull
87817-)
87818-
87819-// A FileHandle is an interface to files tracked by the LSP session, which may
87820-// be either files read from disk, or open in the editor session (overlays).
87821-type FileHandle interface {
87822-	// URI is the URI for this file handle.
87823-	// TODO(rfindley): this is not actually well-defined. In some cases, there
87824-	// may be more than one URI that resolve to the same FileHandle. Which one is
87825-	// this?
87826-	URI() span.URI
87827-	// FileIdentity returns a FileIdentity for the file, even if there was an
87828-	// error reading it.
87829-	FileIdentity() FileIdentity
87830-	// Saved reports whether the file has the same content on disk.
87831-	// For on-disk files, this is trivially true.
87832-	Saved() bool
87833-	// Version returns the file version, as defined by the LSP client.
87834-	// For on-disk file handles, Version returns 0.
87835-	Version() int32
87836-	// Read reads the contents of a file.
87837-	// If the file is not available, returns a nil slice and an error.
87838-	Read() ([]byte, error)
87839-}
87840-
87841-// A Hash is a cryptographic digest of the contents of a file.
87842-// (Although at 32B it is larger than a 16B string header, it is smaller
87843-// and has better locality than the string header + 64B of hex digits.)
87844-type Hash [sha256.Size]byte
87845-
87846-// HashOf returns the hash of some data.
87847-func HashOf(data []byte) Hash {
87848-	return Hash(sha256.Sum256(data))
87849-}
87850-
87851-// Hashf returns the hash of a printf-formatted string.
87852-func Hashf(format string, args ...interface{}) Hash {
87853-	// Although this looks alloc-heavy, it is faster than using
87854-	// Fprintf on sha256.New() because the allocations don't escape.
87855-	return HashOf([]byte(fmt.Sprintf(format, args...)))
87856-}
87857-
87858-// String returns the digest as a string of hex digits.
87859-func (h Hash) String() string {
87860-	return fmt.Sprintf("%64x", [sha256.Size]byte(h))
87861-}
87862-
87863-// Less returns true if the given hash is less than the other.
87864-func (h Hash) Less(other Hash) bool {
87865-	return bytes.Compare(h[:], other[:]) < 0
87866-}
87867-
87868-// XORWith updates *h to *h XOR h2.
87869-func (h *Hash) XORWith(h2 Hash) {
87870-	// Small enough that we don't need crypto/subtle.XORBytes.
87871-	for i := range h {
87872-		h[i] ^= h2[i]
87873-	}
87874-}
87875-
87876-// FileIdentity uniquely identifies a file at a version from a FileSystem.
87877-type FileIdentity struct {
87878-	URI  span.URI
87879-	Hash Hash // digest of file contents
87880-}
87881-
87882-func (id FileIdentity) String() string {
87883-	return fmt.Sprintf("%s%s", id.URI, id.Hash)
87884-}
87885-
87886-// FileKind describes the kind of the file in question.
87887-// It can be one of Go,mod, Sum, or Tmpl.
87888-type FileKind int
87889-
87890-const (
87891-	// UnknownKind is a file type we don't know about.
87892-	UnknownKind = FileKind(iota)
87893-
87894-	// Go is a normal go source file.
87895-	Go
87896-	// Mod is a go.mod file.
87897-	Mod
87898-	// Sum is a go.sum file.
87899-	Sum
87900-	// Tmpl is a template file.
87901-	Tmpl
87902-	// Work is a go.work file.
87903-	Work
87904-)
87905-
87906-func (k FileKind) String() string {
87907-	switch k {
87908-	case Go:
87909-		return "go"
87910-	case Mod:
87911-		return "go.mod"
87912-	case Sum:
87913-		return "go.sum"
87914-	case Tmpl:
87915-		return "tmpl"
87916-	case Work:
87917-		return "go.work"
87918-	default:
87919-		return fmt.Sprintf("internal error: unknown file kind %d", k)
87920-	}
87921-}
87922-
87923-// Analyzer represents a go/analysis analyzer with some boolean properties
87924-// that let the user know how to use the analyzer.
87925-type Analyzer struct {
87926-	Analyzer *analysis.Analyzer
87927-
87928-	// Enabled reports whether the analyzer is enabled. This value can be
87929-	// configured per-analysis in user settings. For staticcheck analyzers,
87930-	// the value of the Staticcheck setting overrides this field.
87931-	//
87932-	// Most clients should use the IsEnabled method.
87933-	Enabled bool
87934-
87935-	// Fix is the name of the suggested fix name used to invoke the suggested
87936-	// fixes for the analyzer. It is non-empty if we expect this analyzer to
87937-	// provide its fix separately from its diagnostics. That is, we should apply
87938-	// the analyzer's suggested fixes through a Command, not a TextEdit.
87939-	Fix string
87940-
87941-	// ActionKind is the kind of code action this analyzer produces. If
87942-	// unspecified the type defaults to quickfix.
87943-	ActionKind []protocol.CodeActionKind
87944-
87945-	// Severity is the severity set for diagnostics reported by this
87946-	// analyzer. If left unset it defaults to Warning.
87947-	Severity protocol.DiagnosticSeverity
87948-}
87949-
87950-func (a *Analyzer) String() string { return a.Analyzer.String() }
87951-
87952-// IsEnabled reports whether this analyzer is enabled by the given options.
87953-func (a Analyzer) IsEnabled(options *Options) bool {
87954-	// Staticcheck analyzers can only be enabled when staticcheck is on.
87955-	if _, ok := options.StaticcheckAnalyzers[a.Analyzer.Name]; ok {
87956-		if !options.Staticcheck {
87957-			return false
87958-		}
87959-	}
87960-	if enabled, ok := options.Analyses[a.Analyzer.Name]; ok {
87961-		return enabled
87962-	}
87963-	return a.Enabled
87964-}
87965-
87966-// Declare explicit types for package paths, names, and IDs to ensure that we
87967-// never use an ID where a path belongs, and vice versa. If we confused these,
87968-// it would result in confusing errors because package IDs often look like
87969-// package paths.
87970-type (
87971-	PackageID   string // go list's unique identifier for a package (e.g. "vendor/example.com/foo [vendor/example.com/bar.test]")
87972-	PackagePath string // name used to prefix linker symbols (e.g. "vendor/example.com/foo")
87973-	PackageName string // identifier in 'package' declaration (e.g. "foo")
87974-	ImportPath  string // path that appears in an import declaration (e.g. "example.com/foo")
87975-)
87976-
87977-// Package represents a Go package that has been parsed and type-checked.
87978-//
87979-// By design, there is no way to reach from a Package to the Package
87980-// representing one of its dependencies.
87981-//
87982-// Callers must not assume that two Packages share the same
87983-// token.FileSet or types.Importer and thus have commensurable
87984-// token.Pos values or types.Objects. Instead, use stable naming
87985-// schemes, such as (URI, byte offset) for positions, or (PackagePath,
87986-// objectpath.Path) for exported declarations.
87987-type Package interface {
87988-	Metadata() *Metadata
87989-
87990-	// Results of parsing:
87991-	FileSet() *token.FileSet
87992-	ParseMode() ParseMode
87993-	CompiledGoFiles() []*ParsedGoFile // (borrowed)
87994-	File(uri span.URI) (*ParsedGoFile, error)
87995-	GetSyntax() []*ast.File // (borrowed)
87996-	HasParseErrors() bool
87997-
87998-	// Results of type checking:
87999-	GetTypes() *types.Package
88000-	GetTypesInfo() *types.Info
88001-	DependencyTypes(PackagePath) *types.Package // nil for indirect dependency of no consequence
88002-	HasTypeErrors() bool
88003-	DiagnosticsForFile(ctx context.Context, s Snapshot, uri span.URI) ([]*Diagnostic, error)
88004-}
88005-
88006-type unit = struct{}
88007-
88008-// A CriticalError is a workspace-wide error that generally prevents gopls from
88009-// functioning correctly. In the presence of critical errors, other diagnostics
88010-// in the workspace may not make sense.
88011-type CriticalError struct {
88012-	// MainError is the primary error. Must be non-nil.
88013-	MainError error
88014-
88015-	// Diagnostics contains any supplemental (structured) diagnostics.
88016-	Diagnostics []*Diagnostic
88017-}
88018-
88019-// An Diagnostic corresponds to an LSP Diagnostic.
88020-// https://microsoft.github.io/language-server-protocol/specification#diagnostic
88021-type Diagnostic struct {
88022-	URI      span.URI
88023-	Range    protocol.Range
88024-	Severity protocol.DiagnosticSeverity
88025-	Code     string
88026-	CodeHref string
88027-
88028-	// Source is a human-readable description of the source of the error.
88029-	// Diagnostics generated by an analysis.Analyzer set it to Analyzer.Name.
88030-	Source DiagnosticSource
88031-
88032-	Message string
88033-
88034-	Tags    []protocol.DiagnosticTag
88035-	Related []protocol.DiagnosticRelatedInformation
88036-
88037-	// Fields below are used internally to generate quick fixes. They aren't
88038-	// part of the LSP spec and don't leave the server.
88039-	SuggestedFixes []SuggestedFix
88040-}
88041-
88042-func (d *Diagnostic) String() string {
88043-	return fmt.Sprintf("%v: %s", d.Range, d.Message)
88044-}
88045-
88046-type DiagnosticSource string
88047-
88048-const (
88049-	UnknownError             DiagnosticSource = "<Unknown source>"
88050-	ListError                DiagnosticSource = "go list"
88051-	ParseError               DiagnosticSource = "syntax"
88052-	TypeError                DiagnosticSource = "compiler"
88053-	ModTidyError             DiagnosticSource = "go mod tidy"
88054-	OptimizationDetailsError DiagnosticSource = "optimizer details"
88055-	UpgradeNotification      DiagnosticSource = "upgrade available"
88056-	Vulncheck                DiagnosticSource = "vulncheck imports"
88057-	Govulncheck              DiagnosticSource = "govulncheck"
88058-	TemplateError            DiagnosticSource = "template"
88059-	WorkFileError            DiagnosticSource = "go.work file"
88060-)
88061-
88062-func AnalyzerErrorKind(name string) DiagnosticSource {
88063-	return DiagnosticSource(name)
88064-}
88065diff -urN a/gopls/internal/lsp/source/workspace_symbol.go b/gopls/internal/lsp/source/workspace_symbol.go
88066--- a/gopls/internal/lsp/source/workspace_symbol.go	2000-01-01 00:00:00.000000000 -0000
88067+++ b/gopls/internal/lsp/source/workspace_symbol.go	1970-01-01 00:00:00.000000000 +0000
88068@@ -1,632 +0,0 @@
88069-// Copyright 2020 The Go Authors. All rights reserved.
88070-// Use of this source code is governed by a BSD-style
88071-// license that can be found in the LICENSE file.
88072-
88073-package source
88074-
88075-import (
88076-	"context"
88077-	"fmt"
88078-	"go/types"
88079-	"path"
88080-	"path/filepath"
88081-	"regexp"
88082-	"runtime"
88083-	"sort"
88084-	"strings"
88085-	"unicode"
88086-
88087-	"golang.org/x/tools/gopls/internal/lsp/protocol"
88088-	"golang.org/x/tools/gopls/internal/span"
88089-	"golang.org/x/tools/internal/event"
88090-	"golang.org/x/tools/internal/fuzzy"
88091-)
88092-
88093-// Symbol holds a precomputed symbol value. Note: we avoid using the
88094-// protocol.SymbolInformation struct here in order to reduce the size of each
88095-// symbol.
88096-type Symbol struct {
88097-	Name  string
88098-	Kind  protocol.SymbolKind
88099-	Range protocol.Range
88100-}
88101-
88102-// maxSymbols defines the maximum number of symbol results that should ever be
88103-// sent in response to a client.
88104-const maxSymbols = 100
88105-
88106-// WorkspaceSymbols matches symbols across all views using the given query,
88107-// according to the match semantics parameterized by matcherType and style.
88108-//
88109-// The workspace symbol method is defined in the spec as follows:
88110-//
88111-//	The workspace symbol request is sent from the client to the server to
88112-//	list project-wide symbols matching the query string.
88113-//
88114-// It is unclear what "project-wide" means here, but given the parameters of
88115-// workspace/symbol do not include any workspace identifier, then it has to be
88116-// assumed that "project-wide" means "across all workspaces".  Hence why
88117-// WorkspaceSymbols receives the views []View.
88118-//
88119-// However, it then becomes unclear what it would mean to call WorkspaceSymbols
88120-// with a different configured SymbolMatcher per View. Therefore we assume that
88121-// Session level configuration will define the SymbolMatcher to be used for the
88122-// WorkspaceSymbols method.
88123-func WorkspaceSymbols(ctx context.Context, matcher SymbolMatcher, style SymbolStyle, views []View, query string) ([]protocol.SymbolInformation, error) {
88124-	ctx, done := event.Start(ctx, "source.WorkspaceSymbols")
88125-	defer done()
88126-	if query == "" {
88127-		return nil, nil
88128-	}
88129-
88130-	var s symbolizer
88131-	switch style {
88132-	case DynamicSymbols:
88133-		s = dynamicSymbolMatch
88134-	case FullyQualifiedSymbols:
88135-		s = fullyQualifiedSymbolMatch
88136-	case PackageQualifiedSymbols:
88137-		s = packageSymbolMatch
88138-	default:
88139-		panic(fmt.Errorf("unknown symbol style: %v", style))
88140-	}
88141-
88142-	return collectSymbols(ctx, views, matcher, s, query)
88143-}
88144-
88145-// A matcherFunc returns the index and score of a symbol match.
88146-//
88147-// See the comment for symbolCollector for more information.
88148-type matcherFunc func(chunks []string) (int, float64)
88149-
88150-// A symbolizer returns the best symbol match for a name with pkg, according to
88151-// some heuristic. The symbol name is passed as the slice nameParts of logical
88152-// name pieces. For example, for myType.field the caller can pass either
88153-// []string{"myType.field"} or []string{"myType.", "field"}.
88154-//
88155-// See the comment for symbolCollector for more information.
88156-//
88157-// The space argument is an empty slice with spare capacity that may be used
88158-// to allocate the result.
88159-type symbolizer func(space []string, name string, pkg *Metadata, m matcherFunc) ([]string, float64)
88160-
88161-func fullyQualifiedSymbolMatch(space []string, name string, pkg *Metadata, matcher matcherFunc) ([]string, float64) {
88162-	if _, score := dynamicSymbolMatch(space, name, pkg, matcher); score > 0 {
88163-		return append(space, string(pkg.PkgPath), ".", name), score
88164-	}
88165-	return nil, 0
88166-}
88167-
88168-func dynamicSymbolMatch(space []string, name string, pkg *Metadata, matcher matcherFunc) ([]string, float64) {
88169-	if IsCommandLineArguments(pkg.ID) {
88170-		// command-line-arguments packages have a non-sensical package path, so
88171-		// just use their package name.
88172-		return packageSymbolMatch(space, name, pkg, matcher)
88173-	}
88174-
88175-	var score float64
88176-
88177-	endsInPkgName := strings.HasSuffix(string(pkg.PkgPath), string(pkg.Name))
88178-
88179-	// If the package path does not end in the package name, we need to check the
88180-	// package-qualified symbol as an extra pass first.
88181-	if !endsInPkgName {
88182-		pkgQualified := append(space, string(pkg.Name), ".", name)
88183-		idx, score := matcher(pkgQualified)
88184-		nameStart := len(pkg.Name) + 1
88185-		if score > 0 {
88186-			// If our match is contained entirely within the unqualified portion,
88187-			// just return that.
88188-			if idx >= nameStart {
88189-				return append(space, name), score
88190-			}
88191-			// Lower the score for matches that include the package name.
88192-			return pkgQualified, score * 0.8
88193-		}
88194-	}
88195-
88196-	// Now try matching the fully qualified symbol.
88197-	fullyQualified := append(space, string(pkg.PkgPath), ".", name)
88198-	idx, score := matcher(fullyQualified)
88199-
88200-	// As above, check if we matched just the unqualified symbol name.
88201-	nameStart := len(pkg.PkgPath) + 1
88202-	if idx >= nameStart {
88203-		return append(space, name), score
88204-	}
88205-
88206-	// If our package path ends in the package name, we'll have skipped the
88207-	// initial pass above, so check if we matched just the package-qualified
88208-	// name.
88209-	if endsInPkgName && idx >= 0 {
88210-		pkgStart := len(pkg.PkgPath) - len(pkg.Name)
88211-		if idx >= pkgStart {
88212-			return append(space, string(pkg.Name), ".", name), score
88213-		}
88214-	}
88215-
88216-	// Our match was not contained within the unqualified or package qualified
88217-	// symbol. Return the fully qualified symbol but discount the score.
88218-	return fullyQualified, score * 0.6
88219-}
88220-
88221-func packageSymbolMatch(space []string, name string, pkg *Metadata, matcher matcherFunc) ([]string, float64) {
88222-	qualified := append(space, string(pkg.Name), ".", name)
88223-	if _, s := matcher(qualified); s > 0 {
88224-		return qualified, s
88225-	}
88226-	return nil, 0
88227-}
88228-
88229-func buildMatcher(matcher SymbolMatcher, query string) matcherFunc {
88230-	switch matcher {
88231-	case SymbolFuzzy:
88232-		return parseQuery(query, newFuzzyMatcher)
88233-	case SymbolFastFuzzy:
88234-		return parseQuery(query, func(query string) matcherFunc {
88235-			return fuzzy.NewSymbolMatcher(query).Match
88236-		})
88237-	case SymbolCaseSensitive:
88238-		return matchExact(query)
88239-	case SymbolCaseInsensitive:
88240-		q := strings.ToLower(query)
88241-		exact := matchExact(q)
88242-		wrapper := []string{""}
88243-		return func(chunks []string) (int, float64) {
88244-			s := strings.Join(chunks, "")
88245-			wrapper[0] = strings.ToLower(s)
88246-			return exact(wrapper)
88247-		}
88248-	}
88249-	panic(fmt.Errorf("unknown symbol matcher: %v", matcher))
88250-}
88251-
88252-func newFuzzyMatcher(query string) matcherFunc {
88253-	fm := fuzzy.NewMatcher(query)
88254-	return func(chunks []string) (int, float64) {
88255-		score := float64(fm.ScoreChunks(chunks))
88256-		ranges := fm.MatchedRanges()
88257-		if len(ranges) > 0 {
88258-			return ranges[0], score
88259-		}
88260-		return -1, score
88261-	}
88262-}
88263-
88264-// parseQuery parses a field-separated symbol query, extracting the special
88265-// characters listed below, and returns a matcherFunc corresponding to the AND
88266-// of all field queries.
88267-//
88268-// Special characters:
88269-//
88270-//	^  match exact prefix
88271-//	$  match exact suffix
88272-//	'  match exact
88273-//
88274-// In all three of these special queries, matches are 'smart-cased', meaning
88275-// they are case sensitive if the symbol query contains any upper-case
88276-// characters, and case insensitive otherwise.
88277-func parseQuery(q string, newMatcher func(string) matcherFunc) matcherFunc {
88278-	fields := strings.Fields(q)
88279-	if len(fields) == 0 {
88280-		return func([]string) (int, float64) { return -1, 0 }
88281-	}
88282-	var funcs []matcherFunc
88283-	for _, field := range fields {
88284-		var f matcherFunc
88285-		switch {
88286-		case strings.HasPrefix(field, "^"):
88287-			prefix := field[1:]
88288-			f = smartCase(prefix, func(chunks []string) (int, float64) {
88289-				s := strings.Join(chunks, "")
88290-				if strings.HasPrefix(s, prefix) {
88291-					return 0, 1
88292-				}
88293-				return -1, 0
88294-			})
88295-		case strings.HasPrefix(field, "'"):
88296-			exact := field[1:]
88297-			f = smartCase(exact, matchExact(exact))
88298-		case strings.HasSuffix(field, "$"):
88299-			suffix := field[0 : len(field)-1]
88300-			f = smartCase(suffix, func(chunks []string) (int, float64) {
88301-				s := strings.Join(chunks, "")
88302-				if strings.HasSuffix(s, suffix) {
88303-					return len(s) - len(suffix), 1
88304-				}
88305-				return -1, 0
88306-			})
88307-		default:
88308-			f = newMatcher(field)
88309-		}
88310-		funcs = append(funcs, f)
88311-	}
88312-	if len(funcs) == 1 {
88313-		return funcs[0]
88314-	}
88315-	return comboMatcher(funcs).match
88316-}
88317-
88318-func matchExact(exact string) matcherFunc {
88319-	return func(chunks []string) (int, float64) {
88320-		s := strings.Join(chunks, "")
88321-		if idx := strings.LastIndex(s, exact); idx >= 0 {
88322-			return idx, 1
88323-		}
88324-		return -1, 0
88325-	}
88326-}
88327-
88328-// smartCase returns a matcherFunc that is case-sensitive if q contains any
88329-// upper-case characters, and case-insensitive otherwise.
88330-func smartCase(q string, m matcherFunc) matcherFunc {
88331-	insensitive := strings.ToLower(q) == q
88332-	wrapper := []string{""}
88333-	return func(chunks []string) (int, float64) {
88334-		s := strings.Join(chunks, "")
88335-		if insensitive {
88336-			s = strings.ToLower(s)
88337-		}
88338-		wrapper[0] = s
88339-		return m(wrapper)
88340-	}
88341-}
88342-
88343-type comboMatcher []matcherFunc
88344-
88345-func (c comboMatcher) match(chunks []string) (int, float64) {
88346-	score := 1.0
88347-	first := 0
88348-	for _, f := range c {
88349-		idx, s := f(chunks)
88350-		if idx < first {
88351-			first = idx
88352-		}
88353-		score *= s
88354-	}
88355-	return first, score
88356-}
88357-
88358-// collectSymbols calls snapshot.Symbols to walk the syntax trees of
88359-// all files in the views' current snapshots, and returns a sorted,
88360-// scored list of symbols that best match the parameters.
88361-//
88362-// How it matches symbols is parameterized by two interfaces:
88363-//   - A matcherFunc determines how well a string symbol matches a query. It
88364-//     returns a non-negative score indicating the quality of the match. A score
88365-//     of zero indicates no match.
88366-//   - A symbolizer determines how we extract the symbol for an object. This
88367-//     enables the 'symbolStyle' configuration option.
88368-func collectSymbols(ctx context.Context, views []View, matcherType SymbolMatcher, symbolizer symbolizer, query string) ([]protocol.SymbolInformation, error) {
88369-	// Extract symbols from all files.
88370-	var work []symbolFile
88371-	var roots []string
88372-	seen := make(map[span.URI]bool)
88373-	// TODO(adonovan): opt: parallelize this loop? How often is len > 1?
88374-	for _, v := range views {
88375-		snapshot, release, err := v.Snapshot()
88376-		if err != nil {
88377-			continue // view is shut down; continue with others
88378-		}
88379-		defer release()
88380-
88381-		// Use the root view URIs for determining (lexically)
88382-		// whether a URI is in any open workspace.
88383-		roots = append(roots, strings.TrimRight(string(v.Folder()), "/"))
88384-
88385-		filters := v.Options().DirectoryFilters
88386-		filterer := NewFilterer(filters)
88387-		folder := filepath.ToSlash(v.Folder().Filename())
88388-		symbols, err := snapshot.Symbols(ctx)
88389-		if err != nil {
88390-			return nil, err
88391-		}
88392-		for uri, syms := range symbols {
88393-			norm := filepath.ToSlash(uri.Filename())
88394-			nm := strings.TrimPrefix(norm, folder)
88395-			if filterer.Disallow(nm) {
88396-				continue
88397-			}
88398-			// Only scan each file once.
88399-			if seen[uri] {
88400-				continue
88401-			}
88402-			mds, err := snapshot.MetadataForFile(ctx, uri)
88403-			if err != nil {
88404-				event.Error(ctx, fmt.Sprintf("missing metadata for %q", uri), err)
88405-				continue
88406-			}
88407-			if len(mds) == 0 {
88408-				// TODO: should use the bug reporting API
88409-				continue
88410-			}
88411-			seen[uri] = true
88412-			work = append(work, symbolFile{uri, mds[0], syms})
88413-		}
88414-	}
88415-
88416-	// Match symbols in parallel.
88417-	// Each worker has its own symbolStore,
88418-	// which we merge at the end.
88419-	nmatchers := runtime.GOMAXPROCS(-1) // matching is CPU bound
88420-	results := make(chan *symbolStore)
88421-	for i := 0; i < nmatchers; i++ {
88422-		go func(i int) {
88423-			matcher := buildMatcher(matcherType, query)
88424-			store := new(symbolStore)
88425-			// Assign files to workers in round-robin fashion.
88426-			for j := i; j < len(work); j += nmatchers {
88427-				matchFile(store, symbolizer, matcher, roots, work[j])
88428-			}
88429-			results <- store
88430-		}(i)
88431-	}
88432-
88433-	// Gather and merge results as they arrive.
88434-	var unified symbolStore
88435-	for i := 0; i < nmatchers; i++ {
88436-		store := <-results
88437-		for _, syms := range store.res {
88438-			unified.store(syms)
88439-		}
88440-	}
88441-	return unified.results(), nil
88442-}
88443-
88444-type Filterer struct {
88445-	// Whether a filter is excluded depends on the operator (first char of the raw filter).
88446-	// Slices filters and excluded then should have the same length.
88447-	filters  []*regexp.Regexp
88448-	excluded []bool
88449-}
88450-
88451-// NewFilterer computes regular expression form of all raw filters
88452-func NewFilterer(rawFilters []string) *Filterer {
88453-	var f Filterer
88454-	for _, filter := range rawFilters {
88455-		filter = path.Clean(filepath.ToSlash(filter))
88456-		// TODO(dungtuanle): fix: validate [+-] prefix.
88457-		op, prefix := filter[0], filter[1:]
88458-		// convertFilterToRegexp adds "/" at the end of prefix to handle cases where a filter is a prefix of another filter.
88459-		// For example, it prevents [+foobar, -foo] from excluding "foobar".
88460-		f.filters = append(f.filters, convertFilterToRegexp(filepath.ToSlash(prefix)))
88461-		f.excluded = append(f.excluded, op == '-')
88462-	}
88463-
88464-	return &f
88465-}
88466-
88467-// Disallow return true if the path is excluded from the filterer's filters.
88468-func (f *Filterer) Disallow(path string) bool {
88469-	// Ensure trailing but not leading slash.
88470-	path = strings.TrimPrefix(path, "/")
88471-	if !strings.HasSuffix(path, "/") {
88472-		path += "/"
88473-	}
88474-
88475-	// TODO(adonovan): opt: iterate in reverse and break at first match.
88476-	excluded := false
88477-	for i, filter := range f.filters {
88478-		if filter.MatchString(path) {
88479-			excluded = f.excluded[i] // last match wins
88480-		}
88481-	}
88482-	return excluded
88483-}
88484-
88485-// convertFilterToRegexp replaces glob-like operator substrings in a string file path to their equivalent regex forms.
88486-// Supporting glob-like operators:
88487-//   - **: match zero or more complete path segments
88488-func convertFilterToRegexp(filter string) *regexp.Regexp {
88489-	if filter == "" {
88490-		return regexp.MustCompile(".*")
88491-	}
88492-	var ret strings.Builder
88493-	ret.WriteString("^")
88494-	segs := strings.Split(filter, "/")
88495-	for _, seg := range segs {
88496-		// Inv: seg != "" since path is clean.
88497-		if seg == "**" {
88498-			ret.WriteString(".*")
88499-		} else {
88500-			ret.WriteString(regexp.QuoteMeta(seg))
88501-		}
88502-		ret.WriteString("/")
88503-	}
88504-	pattern := ret.String()
88505-
88506-	// Remove unnecessary "^.*" prefix, which increased
88507-	// BenchmarkWorkspaceSymbols time by ~20% (even though
88508-	// filter CPU time increased by only by ~2.5%) when the
88509-	// default filter was changed to "**/node_modules".
88510-	pattern = strings.TrimPrefix(pattern, "^.*")
88511-
88512-	return regexp.MustCompile(pattern)
88513-}
88514-
88515-// symbolFile holds symbol information for a single file.
88516-type symbolFile struct {
88517-	uri  span.URI
88518-	md   *Metadata
88519-	syms []Symbol
88520-}
88521-
88522-// matchFile scans a symbol file and adds matching symbols to the store.
88523-func matchFile(store *symbolStore, symbolizer symbolizer, matcher matcherFunc, roots []string, i symbolFile) {
88524-	space := make([]string, 0, 3)
88525-	for _, sym := range i.syms {
88526-		symbolParts, score := symbolizer(space, sym.Name, i.md, matcher)
88527-
88528-		// Check if the score is too low before applying any downranking.
88529-		if store.tooLow(score) {
88530-			continue
88531-		}
88532-
88533-		// Factors to apply to the match score for the purpose of downranking
88534-		// results.
88535-		//
88536-		// These numbers were crudely calibrated based on trial-and-error using a
88537-		// small number of sample queries. Adjust as necessary.
88538-		//
88539-		// All factors are multiplicative, meaning if more than one applies they are
88540-		// multiplied together.
88541-		const (
88542-			// nonWorkspaceFactor is applied to symbols outside of any active
88543-			// workspace. Developers are less likely to want to jump to code that they
88544-			// are not actively working on.
88545-			nonWorkspaceFactor = 0.5
88546-			// nonWorkspaceUnexportedFactor is applied to unexported symbols outside of
88547-			// any active workspace. Since one wouldn't usually jump to unexported
88548-			// symbols to understand a package API, they are particularly irrelevant.
88549-			nonWorkspaceUnexportedFactor = 0.5
88550-			// every field or method nesting level to access the field decreases
88551-			// the score by a factor of 1.0 - depth*depthFactor, up to a depth of
88552-			// 3.
88553-			depthFactor = 0.2
88554-		)
88555-
88556-		startWord := true
88557-		exported := true
88558-		depth := 0.0
88559-		for _, r := range sym.Name {
88560-			if startWord && !unicode.IsUpper(r) {
88561-				exported = false
88562-			}
88563-			if r == '.' {
88564-				startWord = true
88565-				depth++
88566-			} else {
88567-				startWord = false
88568-			}
88569-		}
88570-
88571-		inWorkspace := false
88572-		for _, root := range roots {
88573-			if strings.HasPrefix(string(i.uri), root) {
88574-				inWorkspace = true
88575-				break
88576-			}
88577-		}
88578-
88579-		// Apply downranking based on workspace position.
88580-		if !inWorkspace {
88581-			score *= nonWorkspaceFactor
88582-			if !exported {
88583-				score *= nonWorkspaceUnexportedFactor
88584-			}
88585-		}
88586-
88587-		// Apply downranking based on symbol depth.
88588-		if depth > 3 {
88589-			depth = 3
88590-		}
88591-		score *= 1.0 - depth*depthFactor
88592-
88593-		if store.tooLow(score) {
88594-			continue
88595-		}
88596-
88597-		si := symbolInformation{
88598-			score:     score,
88599-			symbol:    strings.Join(symbolParts, ""),
88600-			kind:      sym.Kind,
88601-			uri:       i.uri,
88602-			rng:       sym.Range,
88603-			container: string(i.md.PkgPath),
88604-		}
88605-		store.store(si)
88606-	}
88607-}
88608-
88609-type symbolStore struct {
88610-	res [maxSymbols]symbolInformation
88611-}
88612-
88613-// store inserts si into the sorted results, if si has a high enough score.
88614-func (sc *symbolStore) store(si symbolInformation) {
88615-	if sc.tooLow(si.score) {
88616-		return
88617-	}
88618-	insertAt := sort.Search(len(sc.res), func(i int) bool {
88619-		// Sort by score, then symbol length, and finally lexically.
88620-		if sc.res[i].score != si.score {
88621-			return sc.res[i].score < si.score
88622-		}
88623-		if len(sc.res[i].symbol) != len(si.symbol) {
88624-			return len(sc.res[i].symbol) > len(si.symbol)
88625-		}
88626-		return sc.res[i].symbol > si.symbol
88627-	})
88628-	if insertAt < len(sc.res)-1 {
88629-		copy(sc.res[insertAt+1:], sc.res[insertAt:len(sc.res)-1])
88630-	}
88631-	sc.res[insertAt] = si
88632-}
88633-
88634-func (sc *symbolStore) tooLow(score float64) bool {
88635-	return score <= sc.res[len(sc.res)-1].score
88636-}
88637-
88638-func (sc *symbolStore) results() []protocol.SymbolInformation {
88639-	var res []protocol.SymbolInformation
88640-	for _, si := range sc.res {
88641-		if si.score <= 0 {
88642-			return res
88643-		}
88644-		res = append(res, si.asProtocolSymbolInformation())
88645-	}
88646-	return res
88647-}
88648-
88649-func typeToKind(typ types.Type) protocol.SymbolKind {
88650-	switch typ := typ.Underlying().(type) {
88651-	case *types.Interface:
88652-		return protocol.Interface
88653-	case *types.Struct:
88654-		return protocol.Struct
88655-	case *types.Signature:
88656-		if typ.Recv() != nil {
88657-			return protocol.Method
88658-		}
88659-		return protocol.Function
88660-	case *types.Named:
88661-		return typeToKind(typ.Underlying())
88662-	case *types.Basic:
88663-		i := typ.Info()
88664-		switch {
88665-		case i&types.IsNumeric != 0:
88666-			return protocol.Number
88667-		case i&types.IsBoolean != 0:
88668-			return protocol.Boolean
88669-		case i&types.IsString != 0:
88670-			return protocol.String
88671-		}
88672-	}
88673-	return protocol.Variable
88674-}
88675-
88676-// symbolInformation is a cut-down version of protocol.SymbolInformation that
88677-// allows struct values of this type to be used as map keys.
88678-type symbolInformation struct {
88679-	score     float64
88680-	symbol    string
88681-	container string
88682-	kind      protocol.SymbolKind
88683-	uri       span.URI
88684-	rng       protocol.Range
88685-}
88686-
88687-// asProtocolSymbolInformation converts s to a protocol.SymbolInformation value.
88688-//
88689-// TODO: work out how to handle tags if/when they are needed.
88690-func (s symbolInformation) asProtocolSymbolInformation() protocol.SymbolInformation {
88691-	return protocol.SymbolInformation{
88692-		Name: s.symbol,
88693-		Kind: s.kind,
88694-		Location: protocol.Location{
88695-			URI:   protocol.URIFromSpanURI(s.uri),
88696-			Range: s.rng,
88697-		},
88698-		ContainerName: s.container,
88699-	}
88700-}
88701diff -urN a/gopls/internal/lsp/source/workspace_symbol_test.go b/gopls/internal/lsp/source/workspace_symbol_test.go
88702--- a/gopls/internal/lsp/source/workspace_symbol_test.go	2000-01-01 00:00:00.000000000 -0000
88703+++ b/gopls/internal/lsp/source/workspace_symbol_test.go	1970-01-01 00:00:00.000000000 +0000
88704@@ -1,136 +0,0 @@
88705-// Copyright 2020 The Go Authors. All rights reserved.
88706-// Use of this source code is governed by a BSD-style
88707-// license that can be found in the LICENSE file.
88708-
88709-package source
88710-
88711-import (
88712-	"testing"
88713-)
88714-
88715-func TestParseQuery(t *testing.T) {
88716-	tests := []struct {
88717-		query, s  string
88718-		wantMatch bool
88719-	}{
88720-		{"", "anything", false},
88721-		{"any", "anything", true},
88722-		{"any$", "anything", false},
88723-		{"ing$", "anything", true},
88724-		{"ing$", "anythinG", true},
88725-		{"inG$", "anything", false},
88726-		{"^any", "anything", true},
88727-		{"^any", "Anything", true},
88728-		{"^Any", "anything", false},
88729-		{"at", "anything", true},
88730-		// TODO: this appears to be a bug in the fuzzy matching algorithm. 'At'
88731-		// should cause a case-sensitive match.
88732-		// {"At", "anything", false},
88733-		{"At", "Anything", true},
88734-		{"'yth", "Anything", true},
88735-		{"'yti", "Anything", false},
88736-		{"'any 'thing", "Anything", true},
88737-		{"anythn nythg", "Anything", true},
88738-		{"ntx", "Anything", false},
88739-		{"anythn", "anything", true},
88740-		{"ing", "anything", true},
88741-		{"anythn nythgx", "anything", false},
88742-	}
88743-
88744-	for _, test := range tests {
88745-		matcher := parseQuery(test.query, newFuzzyMatcher)
88746-		if _, score := matcher([]string{test.s}); score > 0 != test.wantMatch {
88747-			t.Errorf("parseQuery(%q) match for %q: %.2g, want match: %t", test.query, test.s, score, test.wantMatch)
88748-		}
88749-	}
88750-}
88751-
88752-func TestFiltererDisallow(t *testing.T) {
88753-	tests := []struct {
88754-		filters  []string
88755-		included []string
88756-		excluded []string
88757-	}{
88758-		{
88759-			[]string{"+**/c.go"},
88760-			[]string{"a/c.go", "a/b/c.go"},
88761-			[]string{},
88762-		},
88763-		{
88764-			[]string{"+a/**/c.go"},
88765-			[]string{"a/b/c.go", "a/b/d/c.go", "a/c.go"},
88766-			[]string{},
88767-		},
88768-		{
88769-			[]string{"-a/c.go", "+a/**"},
88770-			[]string{"a/c.go"},
88771-			[]string{},
88772-		},
88773-		{
88774-			[]string{"+a/**/c.go", "-**/c.go"},
88775-			[]string{},
88776-			[]string{"a/b/c.go"},
88777-		},
88778-		{
88779-			[]string{"+a/**/c.go", "-a/**"},
88780-			[]string{},
88781-			[]string{"a/b/c.go"},
88782-		},
88783-		{
88784-			[]string{"+**/c.go", "-a/**/c.go"},
88785-			[]string{},
88786-			[]string{"a/b/c.go"},
88787-		},
88788-		{
88789-			[]string{"+foobar", "-foo"},
88790-			[]string{"foobar", "foobar/a"},
88791-			[]string{"foo", "foo/a"},
88792-		},
88793-		{
88794-			[]string{"+", "-"},
88795-			[]string{},
88796-			[]string{"foobar", "foobar/a", "foo", "foo/a"},
88797-		},
88798-		{
88799-			[]string{"-", "+"},
88800-			[]string{"foobar", "foobar/a", "foo", "foo/a"},
88801-			[]string{},
88802-		},
88803-		{
88804-			[]string{"-a/**/b/**/c.go"},
88805-			[]string{},
88806-			[]string{"a/x/y/z/b/f/g/h/c.go"},
88807-		},
88808-		// tests for unsupported glob operators
88809-		{
88810-			[]string{"+**/c.go", "-a/*/c.go"},
88811-			[]string{"a/b/c.go"},
88812-			[]string{},
88813-		},
88814-		{
88815-			[]string{"+**/c.go", "-a/?/c.go"},
88816-			[]string{"a/b/c.go"},
88817-			[]string{},
88818-		},
88819-		{
88820-			[]string{"-b"}, // should only filter paths prefixed with the "b" directory
88821-			[]string{"a/b/c.go", "bb"},
88822-			[]string{"b/c/d.go", "b"},
88823-		},
88824-	}
88825-
88826-	for _, test := range tests {
88827-		filterer := NewFilterer(test.filters)
88828-		for _, inc := range test.included {
88829-			if filterer.Disallow(inc) {
88830-				t.Errorf("Filters %v excluded %v, wanted included", test.filters, inc)
88831-			}
88832-		}
88833-
88834-		for _, exc := range test.excluded {
88835-			if !filterer.Disallow(exc) {
88836-				t.Errorf("Filters %v included %v, wanted excluded", test.filters, exc)
88837-			}
88838-		}
88839-	}
88840-}
88841diff -urN a/gopls/internal/lsp/source/xrefs/xrefs.go b/gopls/internal/lsp/source/xrefs/xrefs.go
88842--- a/gopls/internal/lsp/source/xrefs/xrefs.go	2000-01-01 00:00:00.000000000 -0000
88843+++ b/gopls/internal/lsp/source/xrefs/xrefs.go	1970-01-01 00:00:00.000000000 +0000
88844@@ -1,216 +0,0 @@
88845-// Copyright 2022 The Go Authors. All rights reserved.
88846-// Use of this source code is governed by a BSD-style
88847-// license that can be found in the LICENSE file.
88848-
88849-// Package xrefs defines the serializable index of cross-package
88850-// references that is computed during type checking.
88851-//
88852-// See ../references2.go for the 'references' query.
88853-package xrefs
88854-
88855-import (
88856-	"bytes"
88857-	"encoding/gob"
88858-	"go/ast"
88859-	"go/types"
88860-	"log"
88861-	"sort"
88862-
88863-	"golang.org/x/tools/go/types/objectpath"
88864-	"golang.org/x/tools/gopls/internal/lsp/protocol"
88865-	"golang.org/x/tools/gopls/internal/lsp/source"
88866-	"golang.org/x/tools/internal/typesinternal"
88867-)
88868-
88869-// Index constructs a serializable index of outbound cross-references
88870-// for the specified type-checked package.
88871-func Index(files []*source.ParsedGoFile, pkg *types.Package, info *types.Info) []byte {
88872-	// pkgObjects maps each referenced package Q to a mapping:
88873-	// from each referenced symbol in Q to the ordered list
88874-	// of references to that symbol from this package.
88875-	// A nil types.Object indicates a reference
88876-	// to the package as a whole: an import.
88877-	pkgObjects := make(map[*types.Package]map[types.Object]*gobObject)
88878-
88879-	// getObjects returns the object-to-references mapping for a package.
88880-	getObjects := func(pkg *types.Package) map[types.Object]*gobObject {
88881-		objects, ok := pkgObjects[pkg]
88882-		if !ok {
88883-			objects = make(map[types.Object]*gobObject)
88884-			pkgObjects[pkg] = objects
88885-		}
88886-		return objects
88887-	}
88888-
88889-	objectpathFor := typesinternal.NewObjectpathFunc()
88890-
88891-	for fileIndex, pgf := range files {
88892-
88893-		nodeRange := func(n ast.Node) protocol.Range {
88894-			rng, err := pgf.PosRange(n.Pos(), n.End())
88895-			if err != nil {
88896-				panic(err) // can't fail
88897-			}
88898-			return rng
88899-		}
88900-
88901-		ast.Inspect(pgf.File, func(n ast.Node) bool {
88902-			switch n := n.(type) {
88903-			case *ast.Ident:
88904-				// Report a reference for each identifier that
88905-				// uses a symbol exported from another package.
88906-				// (The built-in error.Error method has no package.)
88907-				if n.IsExported() {
88908-					if obj, ok := info.Uses[n]; ok &&
88909-						obj.Pkg() != nil &&
88910-						obj.Pkg() != pkg {
88911-
88912-						objects := getObjects(obj.Pkg())
88913-						gobObj, ok := objects[obj]
88914-						if !ok {
88915-							path, err := objectpathFor(obj)
88916-							if err != nil {
88917-								// Capitalized but not exported
88918-								// (e.g. local const/var/type).
88919-								return true
88920-							}
88921-							gobObj = &gobObject{Path: path}
88922-							objects[obj] = gobObj
88923-						}
88924-
88925-						gobObj.Refs = append(gobObj.Refs, gobRef{
88926-							FileIndex: fileIndex,
88927-							Range:     nodeRange(n),
88928-						})
88929-					}
88930-				}
88931-
88932-			case *ast.ImportSpec:
88933-				// Report a reference from each import path
88934-				// string to the imported package.
88935-				var obj types.Object
88936-				if n.Name != nil {
88937-					obj = info.Defs[n.Name]
88938-				} else {
88939-					obj = info.Implicits[n]
88940-				}
88941-				if obj == nil {
88942-					return true // missing import
88943-				}
88944-				objects := getObjects(obj.(*types.PkgName).Imported())
88945-				gobObj, ok := objects[nil]
88946-				if !ok {
88947-					gobObj = &gobObject{Path: ""}
88948-					objects[nil] = gobObj
88949-				}
88950-				gobObj.Refs = append(gobObj.Refs, gobRef{
88951-					FileIndex: fileIndex,
88952-					Range:     nodeRange(n.Path),
88953-				})
88954-			}
88955-			return true
88956-		})
88957-	}
88958-
88959-	// Flatten the maps into slices, and sort for determinism.
88960-	var packages []*gobPackage
88961-	for p := range pkgObjects {
88962-		objects := pkgObjects[p]
88963-		gp := &gobPackage{
88964-			PkgPath: source.PackagePath(p.Path()),
88965-			Objects: make([]*gobObject, 0, len(objects)),
88966-		}
88967-		for _, gobObj := range objects {
88968-			gp.Objects = append(gp.Objects, gobObj)
88969-		}
88970-		sort.Slice(gp.Objects, func(i, j int) bool {
88971-			return gp.Objects[i].Path < gp.Objects[j].Path
88972-		})
88973-		packages = append(packages, gp)
88974-	}
88975-	sort.Slice(packages, func(i, j int) bool {
88976-		return packages[i].PkgPath < packages[j].PkgPath
88977-	})
88978-
88979-	return mustEncode(packages)
88980-}
88981-
88982-// Lookup searches a serialized index produced by an indexPackage
88983-// operation on m, and returns the locations of all references from m
88984-// to any object in the target set. Each object is denoted by a pair
88985-// of (package path, object path).
88986-func Lookup(m *source.Metadata, data []byte, targets map[source.PackagePath]map[objectpath.Path]struct{}) (locs []protocol.Location) {
88987-
88988-	// TODO(adonovan): opt: evaluate whether it would be faster to decode
88989-	// in two passes, first with struct { PkgPath string; Objects BLOB }
88990-	// to find the relevant record without decoding the Objects slice,
88991-	// then decode just the desired BLOB into a slice. BLOB would be a
88992-	// type whose Unmarshal method just retains (a copy of) the bytes.
88993-	var packages []gobPackage
88994-	mustDecode(data, &packages)
88995-
88996-	for _, gp := range packages {
88997-		if objectSet, ok := targets[gp.PkgPath]; ok {
88998-			for _, gobObj := range gp.Objects {
88999-				if _, ok := objectSet[gobObj.Path]; ok {
89000-					for _, ref := range gobObj.Refs {
89001-						uri := m.CompiledGoFiles[ref.FileIndex]
89002-						locs = append(locs, protocol.Location{
89003-							URI:   protocol.URIFromSpanURI(uri),
89004-							Range: ref.Range,
89005-						})
89006-					}
89007-				}
89008-			}
89009-		}
89010-	}
89011-
89012-	return locs
89013-}
89014-
89015-// -- serialized representation --
89016-
89017-// The cross-reference index records the location of all references
89018-// from one package to symbols defined in other packages
89019-// (dependencies). It does not record within-package references.
89020-// The index for package P consists of a list of gopPackage records,
89021-// each enumerating references to symbols defined a single dependency, Q.
89022-
89023-// TODO(adonovan): opt: choose a more compact encoding. Gzip reduces
89024-// the gob output to about one third its size, so clearly there's room
89025-// to improve. The gobRef.Range field is the obvious place to begin.
89026-// Even a zero-length slice gob-encodes to ~285 bytes.
89027-
89028-// A gobPackage records the set of outgoing references from the index
89029-// package to symbols defined in a dependency package.
89030-type gobPackage struct {
89031-	PkgPath source.PackagePath // defining package (Q)
89032-	Objects []*gobObject       // set of Q objects referenced by P
89033-}
89034-
89035-// A gobObject records all references to a particular symbol.
89036-type gobObject struct {
89037-	Path objectpath.Path // symbol name within package; "" => import of package itself
89038-	Refs []gobRef        // locations of references within P, in lexical order
89039-}
89040-
89041-type gobRef struct {
89042-	FileIndex int            // index of enclosing file within P's CompiledGoFiles
89043-	Range     protocol.Range // source range of reference
89044-}
89045-
89046-// -- duplicated from ../../cache/analysis.go --
89047-
89048-func mustEncode(x interface{}) []byte {
89049-	var buf bytes.Buffer
89050-	if err := gob.NewEncoder(&buf).Encode(x); err != nil {
89051-		log.Fatalf("internal error encoding %T: %v", x, err)
89052-	}
89053-	return buf.Bytes()
89054-}
89055-
89056-func mustDecode(data []byte, ptr interface{}) {
89057-	if err := gob.NewDecoder(bytes.NewReader(data)).Decode(ptr); err != nil {
89058-		log.Fatalf("internal error decoding %T: %v", ptr, err)
89059-	}
89060-}
89061diff -urN a/gopls/internal/lsp/symbols.go b/gopls/internal/lsp/symbols.go
89062--- a/gopls/internal/lsp/symbols.go	2000-01-01 00:00:00.000000000 -0000
89063+++ b/gopls/internal/lsp/symbols.go	1970-01-01 00:00:00.000000000 +0000
89064@@ -1,60 +0,0 @@
89065-// Copyright 2019 The Go Authors. All rights reserved.
89066-// Use of this source code is governed by a BSD-style
89067-// license that can be found in the LICENSE file.
89068-
89069-package lsp
89070-
89071-import (
89072-	"context"
89073-
89074-	"golang.org/x/tools/gopls/internal/lsp/protocol"
89075-	"golang.org/x/tools/gopls/internal/lsp/source"
89076-	"golang.org/x/tools/gopls/internal/lsp/template"
89077-	"golang.org/x/tools/internal/event"
89078-	"golang.org/x/tools/internal/event/tag"
89079-)
89080-
89081-func (s *Server) documentSymbol(ctx context.Context, params *protocol.DocumentSymbolParams) ([]interface{}, error) {
89082-	ctx, done := event.Start(ctx, "lsp.Server.documentSymbol")
89083-	defer done()
89084-
89085-	snapshot, fh, ok, release, err := s.beginFileRequest(ctx, params.TextDocument.URI, source.UnknownKind)
89086-	defer release()
89087-	if !ok {
89088-		return []interface{}{}, err
89089-	}
89090-	var docSymbols []protocol.DocumentSymbol
89091-	switch snapshot.View().FileKind(fh) {
89092-	case source.Tmpl:
89093-		docSymbols, err = template.DocumentSymbols(snapshot, fh)
89094-	case source.Go:
89095-		docSymbols, err = source.DocumentSymbols(ctx, snapshot, fh)
89096-	default:
89097-		return []interface{}{}, nil
89098-	}
89099-	if err != nil {
89100-		event.Error(ctx, "DocumentSymbols failed", err, tag.URI.Of(fh.URI()))
89101-		return []interface{}{}, nil
89102-	}
89103-	// Convert the symbols to an interface array.
89104-	// TODO: Remove this once the lsp deprecates SymbolInformation.
89105-	symbols := make([]interface{}, len(docSymbols))
89106-	for i, s := range docSymbols {
89107-		if snapshot.View().Options().HierarchicalDocumentSymbolSupport {
89108-			symbols[i] = s
89109-			continue
89110-		}
89111-		// If the client does not support hierarchical document symbols, then
89112-		// we need to be backwards compatible for now and return SymbolInformation.
89113-		symbols[i] = protocol.SymbolInformation{
89114-			Name:       s.Name,
89115-			Kind:       s.Kind,
89116-			Deprecated: s.Deprecated,
89117-			Location: protocol.Location{
89118-				URI:   params.TextDocument.URI,
89119-				Range: s.Range,
89120-			},
89121-		}
89122-	}
89123-	return symbols, nil
89124-}
89125diff -urN a/gopls/internal/lsp/template/completion.go b/gopls/internal/lsp/template/completion.go
89126--- a/gopls/internal/lsp/template/completion.go	2000-01-01 00:00:00.000000000 -0000
89127+++ b/gopls/internal/lsp/template/completion.go	1970-01-01 00:00:00.000000000 +0000
89128@@ -1,287 +0,0 @@
89129-// Copyright 2021 The Go Authors. All rights reserved.
89130-// Use of this source code is governed by a BSD-style
89131-// license that can be found in the LICENSE file.
89132-
89133-package template
89134-
89135-import (
89136-	"bytes"
89137-	"context"
89138-	"fmt"
89139-	"go/scanner"
89140-	"go/token"
89141-	"strings"
89142-
89143-	"golang.org/x/tools/gopls/internal/lsp/protocol"
89144-	"golang.org/x/tools/gopls/internal/lsp/source"
89145-)
89146-
89147-// information needed for completion
89148-type completer struct {
89149-	p      *Parsed
89150-	pos    protocol.Position
89151-	offset int // offset of the start of the Token
89152-	ctx    protocol.CompletionContext
89153-	syms   map[string]symbol
89154-}
89155-
89156-func Completion(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle, pos protocol.Position, context protocol.CompletionContext) (*protocol.CompletionList, error) {
89157-	all := New(snapshot.Templates())
89158-	var start int // the beginning of the Token (completed or not)
89159-	syms := make(map[string]symbol)
89160-	var p *Parsed
89161-	for fn, fc := range all.files {
89162-		// collect symbols from all template files
89163-		filterSyms(syms, fc.symbols)
89164-		if fn.Filename() != fh.URI().Filename() {
89165-			continue
89166-		}
89167-		if start = inTemplate(fc, pos); start == -1 {
89168-			return nil, nil
89169-		}
89170-		p = fc
89171-	}
89172-	if p == nil {
89173-		// this cannot happen unless the search missed a template file
89174-		return nil, fmt.Errorf("%s not found", fh.FileIdentity().URI.Filename())
89175-	}
89176-	c := completer{
89177-		p:      p,
89178-		pos:    pos,
89179-		offset: start + len(Left),
89180-		ctx:    context,
89181-		syms:   syms,
89182-	}
89183-	return c.complete()
89184-}
89185-
89186-func filterSyms(syms map[string]symbol, ns []symbol) {
89187-	for _, xsym := range ns {
89188-		switch xsym.kind {
89189-		case protocol.Method, protocol.Package, protocol.Boolean, protocol.Namespace,
89190-			protocol.Function:
89191-			syms[xsym.name] = xsym // we don't care which symbol we get
89192-		case protocol.Variable:
89193-			if xsym.name != "dot" {
89194-				syms[xsym.name] = xsym
89195-			}
89196-		case protocol.Constant:
89197-			if xsym.name == "nil" {
89198-				syms[xsym.name] = xsym
89199-			}
89200-		}
89201-	}
89202-}
89203-
89204-// return the starting position of the enclosing token, or -1 if none
89205-func inTemplate(fc *Parsed, pos protocol.Position) int {
89206-	// pos is the pos-th character. if the cursor is at the beginning
89207-	// of the file, pos is 0. That is, we've only seen characters before pos
89208-	// 1. pos might be in a Token, return tk.Start
89209-	// 2. pos might be after an elided but before a Token, return elided
89210-	// 3. return -1 for false
89211-	offset := fc.FromPosition(pos)
89212-	// this could be a binary search, as the tokens are ordered
89213-	for _, tk := range fc.tokens {
89214-		if tk.Start < offset && offset <= tk.End {
89215-			return tk.Start
89216-		}
89217-	}
89218-	for _, x := range fc.elided {
89219-		if x > offset {
89220-			// fc.elided is sorted
89221-			break
89222-		}
89223-		// If the interval [x,offset] does not contain Left or Right
89224-		// then provide completions. (do we need the test for Right?)
89225-		if !bytes.Contains(fc.buf[x:offset], []byte(Left)) && !bytes.Contains(fc.buf[x:offset], []byte(Right)) {
89226-			return x
89227-		}
89228-	}
89229-	return -1
89230-}
89231-
89232-var (
89233-	keywords = []string{"if", "with", "else", "block", "range", "template", "end}}", "end"}
89234-	globals  = []string{"and", "call", "html", "index", "slice", "js", "len", "not", "or",
89235-		"urlquery", "printf", "println", "print", "eq", "ne", "le", "lt", "ge", "gt"}
89236-)
89237-
89238-// find the completions. start is the offset of either the Token enclosing pos, or where
89239-// the incomplete token starts.
89240-// The error return is always nil.
89241-func (c *completer) complete() (*protocol.CompletionList, error) {
89242-	ans := &protocol.CompletionList{IsIncomplete: true, Items: []protocol.CompletionItem{}}
89243-	start := c.p.FromPosition(c.pos)
89244-	sofar := c.p.buf[c.offset:start]
89245-	if len(sofar) == 0 || sofar[len(sofar)-1] == ' ' || sofar[len(sofar)-1] == '\t' {
89246-		return ans, nil
89247-	}
89248-	// sofar could be parsed by either c.analyzer() or scan(). The latter is precise
89249-	// and slower, but fast enough
89250-	words := scan(sofar)
89251-	// 1. if pattern starts $, show variables
89252-	// 2. if pattern starts ., show methods (and . by itself?)
89253-	// 3. if len(words) == 1, show firstWords (but if it were a |, show functions and globals)
89254-	// 4. ...? (parenthetical expressions, arguments, ...) (packages, namespaces, nil?)
89255-	if len(words) == 0 {
89256-		return nil, nil // if this happens, why were we called?
89257-	}
89258-	pattern := string(words[len(words)-1])
89259-	if pattern[0] == '$' {
89260-		// should we also return a raw "$"?
89261-		for _, s := range c.syms {
89262-			if s.kind == protocol.Variable && weakMatch(s.name, pattern) > 0 {
89263-				ans.Items = append(ans.Items, protocol.CompletionItem{
89264-					Label:  s.name,
89265-					Kind:   protocol.VariableCompletion,
89266-					Detail: "Variable",
89267-				})
89268-			}
89269-		}
89270-		return ans, nil
89271-	}
89272-	if pattern[0] == '.' {
89273-		for _, s := range c.syms {
89274-			if s.kind == protocol.Method && weakMatch("."+s.name, pattern) > 0 {
89275-				ans.Items = append(ans.Items, protocol.CompletionItem{
89276-					Label:  s.name,
89277-					Kind:   protocol.MethodCompletion,
89278-					Detail: "Method/member",
89279-				})
89280-			}
89281-		}
89282-		return ans, nil
89283-	}
89284-	// could we get completion attempts in strings or numbers, and if so, do we care?
89285-	// globals
89286-	for _, kw := range globals {
89287-		if weakMatch(kw, string(pattern)) != 0 {
89288-			ans.Items = append(ans.Items, protocol.CompletionItem{
89289-				Label:  kw,
89290-				Kind:   protocol.KeywordCompletion,
89291-				Detail: "Function",
89292-			})
89293-		}
89294-	}
89295-	// and functions
89296-	for _, s := range c.syms {
89297-		if s.kind == protocol.Function && weakMatch(s.name, pattern) != 0 {
89298-			ans.Items = append(ans.Items, protocol.CompletionItem{
89299-				Label:  s.name,
89300-				Kind:   protocol.FunctionCompletion,
89301-				Detail: "Function",
89302-			})
89303-		}
89304-	}
89305-	// keywords if we're at the beginning
89306-	if len(words) <= 1 || len(words[len(words)-2]) == 1 && words[len(words)-2][0] == '|' {
89307-		for _, kw := range keywords {
89308-			if weakMatch(kw, string(pattern)) != 0 {
89309-				ans.Items = append(ans.Items, protocol.CompletionItem{
89310-					Label:  kw,
89311-					Kind:   protocol.KeywordCompletion,
89312-					Detail: "keyword",
89313-				})
89314-			}
89315-		}
89316-	}
89317-	return ans, nil
89318-}
89319-
89320-// someday think about comments, strings, backslashes, etc
89321-// this would repeat some of the template parsing, but because the user is typing
89322-// there may be no parse tree here.
89323-// (go/scanner will report 2 tokens for $a, as $ is not a legal go identifier character)
89324-// (go/scanner is about 2.7 times more expensive)
89325-func (c *completer) analyze(buf []byte) [][]byte {
89326-	// we want to split on whitespace and before dots
89327-	var working []byte
89328-	var ans [][]byte
89329-	for _, ch := range buf {
89330-		if ch == '.' && len(working) > 0 {
89331-			ans = append(ans, working)
89332-			working = []byte{'.'}
89333-			continue
89334-		}
89335-		if ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' {
89336-			if len(working) > 0 {
89337-				ans = append(ans, working)
89338-				working = []byte{}
89339-				continue
89340-			}
89341-		}
89342-		working = append(working, ch)
89343-	}
89344-	if len(working) > 0 {
89345-		ans = append(ans, working)
89346-	}
89347-	ch := buf[len(buf)-1]
89348-	if ch == ' ' || ch == '\t' {
89349-		// avoid completing on whitespace
89350-		ans = append(ans, []byte{ch})
89351-	}
89352-	return ans
89353-}
89354-
89355-// version of c.analyze that uses go/scanner.
89356-func scan(buf []byte) []string {
89357-	fset := token.NewFileSet()
89358-	fp := fset.AddFile("", -1, len(buf))
89359-	var sc scanner.Scanner
89360-	sc.Init(fp, buf, func(pos token.Position, msg string) {}, scanner.ScanComments)
89361-	ans := make([]string, 0, 10) // preallocating gives a measurable savings
89362-	for {
89363-		_, tok, lit := sc.Scan() // tok is an int
89364-		if tok == token.EOF {
89365-			break // done
89366-		} else if tok == token.SEMICOLON && lit == "\n" {
89367-			continue // don't care, but probably can't happen
89368-		} else if tok == token.PERIOD {
89369-			ans = append(ans, ".") // lit is empty
89370-		} else if tok == token.IDENT && len(ans) > 0 && ans[len(ans)-1] == "." {
89371-			ans[len(ans)-1] = "." + lit
89372-		} else if tok == token.IDENT && len(ans) > 0 && ans[len(ans)-1] == "$" {
89373-			ans[len(ans)-1] = "$" + lit
89374-		} else if lit != "" {
89375-			ans = append(ans, lit)
89376-		}
89377-	}
89378-	return ans
89379-}
89380-
89381-// pattern is what the user has typed
89382-func weakMatch(choice, pattern string) float64 {
89383-	lower := strings.ToLower(choice)
89384-	// for now, use only lower-case everywhere
89385-	pattern = strings.ToLower(pattern)
89386-	// The first char has to match
89387-	if pattern[0] != lower[0] {
89388-		return 0
89389-	}
89390-	// If they start with ., then the second char has to match
89391-	from := 1
89392-	if pattern[0] == '.' {
89393-		if len(pattern) < 2 {
89394-			return 1 // pattern just a ., so it matches
89395-		}
89396-		if pattern[1] != lower[1] {
89397-			return 0
89398-		}
89399-		from = 2
89400-	}
89401-	// check that all the characters of pattern occur as a subsequence of choice
89402-	i, j := from, from
89403-	for ; i < len(lower) && j < len(pattern); j++ {
89404-		if pattern[j] == lower[i] {
89405-			i++
89406-			if i >= len(lower) {
89407-				return 0
89408-			}
89409-		}
89410-	}
89411-	if j < len(pattern) {
89412-		return 0
89413-	}
89414-	return 1
89415-}
89416diff -urN a/gopls/internal/lsp/template/completion_test.go b/gopls/internal/lsp/template/completion_test.go
89417--- a/gopls/internal/lsp/template/completion_test.go	2000-01-01 00:00:00.000000000 -0000
89418+++ b/gopls/internal/lsp/template/completion_test.go	1970-01-01 00:00:00.000000000 +0000
89419@@ -1,102 +0,0 @@
89420-// Copyright 2021 The Go Authors. All rights reserved.
89421-// Use of this source code is governed by a BSD-style
89422-// license that can be found in the LICENSE file.
89423-
89424-package template
89425-
89426-import (
89427-	"log"
89428-	"sort"
89429-	"strings"
89430-	"testing"
89431-
89432-	"golang.org/x/tools/gopls/internal/lsp/protocol"
89433-)
89434-
89435-func init() {
89436-	log.SetFlags(log.Lshortfile)
89437-}
89438-
89439-type tparse struct {
89440-	marked string   // ^ shows where to ask for completions. (The user just typed the following character.)
89441-	wanted []string // expected completions
89442-}
89443-
89444-// Test completions in templates that parse enough (if completion needs symbols)
89445-// Seen characters up to the ^
89446-func TestParsed(t *testing.T) {
89447-	var tests = []tparse{
89448-		{"{{x}}{{12. xx^", nil}, // https://github.com/golang/go/issues/50430
89449-		{`<table class="chroma" data-new-comment-url="{{if $.PageIsPullFiles}}{{$.Issue.HTMLURL}}/files/reviews/new_comment{{else}}{{$.CommitHTML}}/new_comment^{{end}}">`, nil},
89450-		{"{{i^f}}", []string{"index", "if"}},
89451-		{"{{if .}}{{e^ {{end}}", []string{"eq", "end}}", "else", "end"}},
89452-		{"{{foo}}{{f^", []string{"foo"}},
89453-		{"{{$^}}", []string{"$"}},
89454-		{"{{$x:=4}}{{$^", []string{"$x"}},
89455-		{"{{$x:=4}}{{$ ^ ", []string{}},
89456-		{"{{len .Modified}}{{.^Mo", []string{"Modified"}},
89457-		{"{{len .Modified}}{{.mf^", []string{"Modified"}},
89458-		{"{{$^ }}", []string{"$"}},
89459-		{"{{$a =3}}{{$^", []string{"$a"}},
89460-		// .two is not good here: fix someday
89461-		{`{{.Modified}}{{.^{{if $.one.two}}xxx{{end}}`, []string{"Modified", "one", "two"}},
89462-		{`{{.Modified}}{{.o^{{if $.one.two}}xxx{{end}}`, []string{"one"}},
89463-		{"{{.Modiifed}}{{.one.t^{{if $.one.two}}xxx{{end}}", []string{"two"}},
89464-		{`{{block "foo" .}}{{i^`, []string{"index", "if"}},
89465-		{"{{in^{{Internal}}", []string{"index", "Internal", "if"}},
89466-		// simple number has no completions
89467-		{"{{4^e", []string{}},
89468-		// simple string has no completions
89469-		{"{{`e^", []string{}},
89470-		{"{{`No i^", []string{}}, // example of why go/scanner is used
89471-		{"{{xavier}}{{12. x^", []string{"xavier"}},
89472-	}
89473-	for _, tx := range tests {
89474-		c := testCompleter(t, tx)
89475-		var v []string
89476-		if c != nil {
89477-			ans, _ := c.complete()
89478-			for _, a := range ans.Items {
89479-				v = append(v, a.Label)
89480-			}
89481-		}
89482-		if len(v) != len(tx.wanted) {
89483-			t.Errorf("%q: got %q, wanted %q %d,%d", tx.marked, v, tx.wanted, len(v), len(tx.wanted))
89484-			continue
89485-		}
89486-		sort.Strings(tx.wanted)
89487-		sort.Strings(v)
89488-		for i := 0; i < len(v); i++ {
89489-			if tx.wanted[i] != v[i] {
89490-				t.Errorf("%q at %d: got %v, wanted %v", tx.marked, i, v, tx.wanted)
89491-				break
89492-			}
89493-		}
89494-	}
89495-}
89496-
89497-func testCompleter(t *testing.T, tx tparse) *completer {
89498-	t.Helper()
89499-	// seen chars up to ^
89500-	col := strings.Index(tx.marked, "^")
89501-	buf := strings.Replace(tx.marked, "^", "", 1)
89502-	p := parseBuffer([]byte(buf))
89503-	pos := protocol.Position{Line: 0, Character: uint32(col)}
89504-	if p.ParseErr != nil {
89505-		log.Printf("%q: %v", tx.marked, p.ParseErr)
89506-	}
89507-	offset := inTemplate(p, pos)
89508-	if offset == -1 {
89509-		return nil
89510-	}
89511-	syms := make(map[string]symbol)
89512-	filterSyms(syms, p.symbols)
89513-	c := &completer{
89514-		p:      p,
89515-		pos:    protocol.Position{Line: 0, Character: uint32(col)},
89516-		offset: offset + len(Left),
89517-		ctx:    protocol.CompletionContext{TriggerKind: protocol.Invoked},
89518-		syms:   syms,
89519-	}
89520-	return c
89521-}
89522diff -urN a/gopls/internal/lsp/template/highlight.go b/gopls/internal/lsp/template/highlight.go
89523--- a/gopls/internal/lsp/template/highlight.go	2000-01-01 00:00:00.000000000 -0000
89524+++ b/gopls/internal/lsp/template/highlight.go	1970-01-01 00:00:00.000000000 +0000
89525@@ -1,96 +0,0 @@
89526-// Copyright 2021 The Go Authors. All rights reserved.
89527-// Use of this source code is governed by a BSD-style
89528-// license that can be found in the LICENSE file.
89529-
89530-package template
89531-
89532-import (
89533-	"context"
89534-	"fmt"
89535-	"regexp"
89536-
89537-	"golang.org/x/tools/gopls/internal/lsp/protocol"
89538-	"golang.org/x/tools/gopls/internal/lsp/source"
89539-)
89540-
89541-func Highlight(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle, loc protocol.Position) ([]protocol.DocumentHighlight, error) {
89542-	buf, err := fh.Read()
89543-	if err != nil {
89544-		return nil, err
89545-	}
89546-	p := parseBuffer(buf)
89547-	pos := p.FromPosition(loc)
89548-	var ans []protocol.DocumentHighlight
89549-	if p.ParseErr == nil {
89550-		for _, s := range p.symbols {
89551-			if s.start <= pos && pos < s.start+s.length {
89552-				return markSymbols(p, s)
89553-			}
89554-		}
89555-	}
89556-	// these tokens exist whether or not there was a parse error
89557-	// (symbols require a successful parse)
89558-	for _, tok := range p.tokens {
89559-		if tok.Start <= pos && pos < tok.End {
89560-			wordAt := findWordAt(p, pos)
89561-			if len(wordAt) > 0 {
89562-				return markWordInToken(p, wordAt)
89563-			}
89564-		}
89565-	}
89566-	// find the 'word' at pos, etc: someday
89567-	// until then we get the default action, which doesn't respect word boundaries
89568-	return ans, nil
89569-}
89570-
89571-func markSymbols(p *Parsed, sym symbol) ([]protocol.DocumentHighlight, error) {
89572-	var ans []protocol.DocumentHighlight
89573-	for _, s := range p.symbols {
89574-		if s.name == sym.name {
89575-			kind := protocol.Read
89576-			if s.vardef {
89577-				kind = protocol.Write
89578-			}
89579-			ans = append(ans, protocol.DocumentHighlight{
89580-				Range: p.Range(s.start, s.length),
89581-				Kind:  kind,
89582-			})
89583-		}
89584-	}
89585-	return ans, nil
89586-}
89587-
89588-// A token is {{...}}, and this marks words in the token that equal the give word
89589-func markWordInToken(p *Parsed, wordAt string) ([]protocol.DocumentHighlight, error) {
89590-	var ans []protocol.DocumentHighlight
89591-	pat, err := regexp.Compile(fmt.Sprintf(`\b%s\b`, wordAt))
89592-	if err != nil {
89593-		return nil, fmt.Errorf("%q: unmatchable word (%v)", wordAt, err)
89594-	}
89595-	for _, tok := range p.tokens {
89596-		got := pat.FindAllIndex(p.buf[tok.Start:tok.End], -1)
89597-		for i := 0; i < len(got); i++ {
89598-			ans = append(ans, protocol.DocumentHighlight{
89599-				Range: p.Range(got[i][0], got[i][1]-got[i][0]),
89600-				Kind:  protocol.Text,
89601-			})
89602-		}
89603-	}
89604-	return ans, nil
89605-}
89606-
89607-var wordRe = regexp.MustCompile(`[$]?\w+$`)
89608-var moreRe = regexp.MustCompile(`^[$]?\w+`)
89609-
89610-// findWordAt finds the word the cursor is in (meaning in or just before)
89611-func findWordAt(p *Parsed, pos int) string {
89612-	if pos >= len(p.buf) {
89613-		return "" // can't happen, as we are called with pos < tok.End
89614-	}
89615-	after := moreRe.Find(p.buf[pos:])
89616-	if len(after) == 0 {
89617-		return "" // end of the word
89618-	}
89619-	got := wordRe.Find(p.buf[:pos+len(after)])
89620-	return string(got)
89621-}
89622diff -urN a/gopls/internal/lsp/template/implementations.go b/gopls/internal/lsp/template/implementations.go
89623--- a/gopls/internal/lsp/template/implementations.go	2000-01-01 00:00:00.000000000 -0000
89624+++ b/gopls/internal/lsp/template/implementations.go	1970-01-01 00:00:00.000000000 +0000
89625@@ -1,189 +0,0 @@
89626-// Copyright 2021 The Go Authors. All rights reserved.
89627-// Use of this source code is governed by a BSD-style
89628-// license that can be found in the LICENSE file.
89629-
89630-package template
89631-
89632-import (
89633-	"context"
89634-	"fmt"
89635-	"regexp"
89636-	"strconv"
89637-	"time"
89638-
89639-	"golang.org/x/tools/gopls/internal/lsp/protocol"
89640-	"golang.org/x/tools/gopls/internal/lsp/source"
89641-	"golang.org/x/tools/gopls/internal/span"
89642-)
89643-
89644-// line number (1-based) and message
89645-var errRe = regexp.MustCompile(`template.*:(\d+): (.*)`)
89646-
89647-// Diagnose returns parse errors. There is only one.
89648-// The errors are not always helpful. For instance { {end}}
89649-// will likely point to the end of the file.
89650-func Diagnose(f source.FileHandle) []*source.Diagnostic {
89651-	// no need for skipTemplate check, as Diagnose is called on the
89652-	// snapshot's template files
89653-	buf, err := f.Read()
89654-	if err != nil {
89655-		// Is a Diagnostic with no Range useful? event.Error also?
89656-		msg := fmt.Sprintf("failed to read %s (%v)", f.URI().Filename(), err)
89657-		d := source.Diagnostic{Message: msg, Severity: protocol.SeverityError, URI: f.URI(),
89658-			Source: source.TemplateError}
89659-		return []*source.Diagnostic{&d}
89660-	}
89661-	p := parseBuffer(buf)
89662-	if p.ParseErr == nil {
89663-		return nil
89664-	}
89665-	unknownError := func(msg string) []*source.Diagnostic {
89666-		s := fmt.Sprintf("malformed template error %q: %s", p.ParseErr.Error(), msg)
89667-		d := source.Diagnostic{
89668-			Message: s, Severity: protocol.SeverityError, Range: p.Range(p.nls[0], 1),
89669-			URI: f.URI(), Source: source.TemplateError}
89670-		return []*source.Diagnostic{&d}
89671-	}
89672-	// errors look like `template: :40: unexpected "}" in operand`
89673-	// so the string needs to be parsed
89674-	matches := errRe.FindStringSubmatch(p.ParseErr.Error())
89675-	if len(matches) != 3 {
89676-		msg := fmt.Sprintf("expected 3 matches, got %d (%v)", len(matches), matches)
89677-		return unknownError(msg)
89678-	}
89679-	lineno, err := strconv.Atoi(matches[1])
89680-	if err != nil {
89681-		msg := fmt.Sprintf("couldn't convert %q to int, %v", matches[1], err)
89682-		return unknownError(msg)
89683-	}
89684-	msg := matches[2]
89685-	d := source.Diagnostic{Message: msg, Severity: protocol.SeverityError,
89686-		Source: source.TemplateError}
89687-	start := p.nls[lineno-1]
89688-	if lineno < len(p.nls) {
89689-		size := p.nls[lineno] - start
89690-		d.Range = p.Range(start, size)
89691-	} else {
89692-		d.Range = p.Range(start, 1)
89693-	}
89694-	return []*source.Diagnostic{&d}
89695-}
89696-
89697-// Definition finds the definitions of the symbol at loc. It
89698-// does not understand scoping (if any) in templates. This code is
89699-// for definitions, type definitions, and implementations.
89700-// Results only for variables and templates.
89701-func Definition(snapshot source.Snapshot, fh source.FileHandle, loc protocol.Position) ([]protocol.Location, error) {
89702-	x, _, err := symAtPosition(fh, loc)
89703-	if err != nil {
89704-		return nil, err
89705-	}
89706-	sym := x.name
89707-	ans := []protocol.Location{}
89708-	// PJW: this is probably a pattern to abstract
89709-	a := New(snapshot.Templates())
89710-	for k, p := range a.files {
89711-		for _, s := range p.symbols {
89712-			if !s.vardef || s.name != sym {
89713-				continue
89714-			}
89715-			ans = append(ans, protocol.Location{URI: protocol.DocumentURI(k), Range: p.Range(s.start, s.length)})
89716-		}
89717-	}
89718-	return ans, nil
89719-}
89720-
89721-func Hover(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle, position protocol.Position) (*protocol.Hover, error) {
89722-	sym, p, err := symAtPosition(fh, position)
89723-	if sym == nil || err != nil {
89724-		return nil, err
89725-	}
89726-	ans := protocol.Hover{Range: p.Range(sym.start, sym.length), Contents: protocol.MarkupContent{Kind: protocol.Markdown}}
89727-	switch sym.kind {
89728-	case protocol.Function:
89729-		ans.Contents.Value = fmt.Sprintf("function: %s", sym.name)
89730-	case protocol.Variable:
89731-		ans.Contents.Value = fmt.Sprintf("variable: %s", sym.name)
89732-	case protocol.Constant:
89733-		ans.Contents.Value = fmt.Sprintf("constant %s", sym.name)
89734-	case protocol.Method: // field or method
89735-		ans.Contents.Value = fmt.Sprintf("%s: field or method", sym.name)
89736-	case protocol.Package: // template use, template def (PJW: do we want two?)
89737-		ans.Contents.Value = fmt.Sprintf("template %s\n(add definition)", sym.name)
89738-	case protocol.Namespace:
89739-		ans.Contents.Value = fmt.Sprintf("template %s defined", sym.name)
89740-	case protocol.Number:
89741-		ans.Contents.Value = "number"
89742-	case protocol.String:
89743-		ans.Contents.Value = "string"
89744-	case protocol.Boolean:
89745-		ans.Contents.Value = "boolean"
89746-	default:
89747-		ans.Contents.Value = fmt.Sprintf("oops, sym=%#v", sym)
89748-	}
89749-	return &ans, nil
89750-}
89751-
89752-func References(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle, params *protocol.ReferenceParams) ([]protocol.Location, error) {
89753-	sym, _, err := symAtPosition(fh, params.Position)
89754-	if sym == nil || err != nil || sym.name == "" {
89755-		return nil, err
89756-	}
89757-	ans := []protocol.Location{}
89758-
89759-	a := New(snapshot.Templates())
89760-	for k, p := range a.files {
89761-		for _, s := range p.symbols {
89762-			if s.name != sym.name {
89763-				continue
89764-			}
89765-			if s.vardef && !params.Context.IncludeDeclaration {
89766-				continue
89767-			}
89768-			ans = append(ans, protocol.Location{URI: protocol.DocumentURI(k), Range: p.Range(s.start, s.length)})
89769-		}
89770-	}
89771-	// do these need to be sorted? (a.files is a map)
89772-	return ans, nil
89773-}
89774-
89775-func SemanticTokens(ctx context.Context, snapshot source.Snapshot, spn span.URI, add func(line, start, len uint32), d func() []uint32) (*protocol.SemanticTokens, error) {
89776-	fh, err := snapshot.GetFile(ctx, spn)
89777-	if err != nil {
89778-		return nil, err
89779-	}
89780-	buf, err := fh.Read()
89781-	if err != nil {
89782-		return nil, err
89783-	}
89784-	p := parseBuffer(buf)
89785-
89786-	for _, t := range p.Tokens() {
89787-		if t.Multiline {
89788-			la, ca := p.LineCol(t.Start)
89789-			lb, cb := p.LineCol(t.End)
89790-			add(la, ca, p.RuneCount(la, ca, 0))
89791-			for l := la + 1; l < lb; l++ {
89792-				add(l, 0, p.RuneCount(l, 0, 0))
89793-			}
89794-			add(lb, 0, p.RuneCount(lb, 0, cb))
89795-			continue
89796-		}
89797-		sz, err := p.TokenSize(t)
89798-		if err != nil {
89799-			return nil, err
89800-		}
89801-		line, col := p.LineCol(t.Start)
89802-		add(line, col, uint32(sz))
89803-	}
89804-	data := d()
89805-	ans := &protocol.SemanticTokens{
89806-		Data: data,
89807-		// for small cache, some day. for now, the LSP client ignores this
89808-		// (that is, when the LSP client starts returning these, we can cache)
89809-		ResultID: fmt.Sprintf("%v", time.Now()),
89810-	}
89811-	return ans, nil
89812-}
89813-
89814-// still need to do rename, etc
89815diff -urN a/gopls/internal/lsp/template/parse.go b/gopls/internal/lsp/template/parse.go
89816--- a/gopls/internal/lsp/template/parse.go	2000-01-01 00:00:00.000000000 -0000
89817+++ b/gopls/internal/lsp/template/parse.go	1970-01-01 00:00:00.000000000 +0000
89818@@ -1,508 +0,0 @@
89819-// Copyright 2021 The Go Authors. All rights reserved.
89820-// Use of this source code is governed by a BSD-style
89821-// license that can be found in the LICENSE file.
89822-
89823-// Package template contains code for dealing with templates
89824-package template
89825-
89826-// template files are small enough that the code reprocesses them each time
89827-// this may be a bad choice for projects with lots of template files.
89828-
89829-// This file contains the parsing code, some debugging printing, and
89830-// implementations for Diagnose, Definition, Hover, References
89831-
89832-import (
89833-	"bytes"
89834-	"context"
89835-	"fmt"
89836-	"io"
89837-	"log"
89838-	"regexp"
89839-	"runtime"
89840-	"sort"
89841-	"text/template"
89842-	"text/template/parse"
89843-	"unicode/utf8"
89844-
89845-	"golang.org/x/tools/gopls/internal/lsp/protocol"
89846-	"golang.org/x/tools/gopls/internal/lsp/source"
89847-	"golang.org/x/tools/gopls/internal/span"
89848-	"golang.org/x/tools/internal/event"
89849-)
89850-
89851-var (
89852-	Left  = []byte("{{")
89853-	Right = []byte("}}")
89854-)
89855-
89856-type Parsed struct {
89857-	buf    []byte   //contents
89858-	lines  [][]byte // needed?, other than for debugging?
89859-	elided []int    // offsets where Left was replaced by blanks
89860-
89861-	// tokens are matched Left-Right pairs, computed before trying to parse
89862-	tokens []Token
89863-
89864-	// result of parsing
89865-	named    []*template.Template // the template and embedded templates
89866-	ParseErr error
89867-	symbols  []symbol
89868-	stack    []parse.Node // used while computing symbols
89869-
89870-	// for mapping from offsets in buf to LSP coordinates
89871-	// See FromPosition() and LineCol()
89872-	nls      []int // offset of newlines before each line (nls[0]==-1)
89873-	lastnl   int   // last line seen
89874-	check    int   // used to decide whether to use lastnl or search through nls
89875-	nonASCII bool  // are there any non-ascii runes in buf?
89876-}
89877-
89878-// Token is a single {{...}}. More precisely, Left...Right
89879-type Token struct {
89880-	Start, End int // offset from start of template
89881-	Multiline  bool
89882-}
89883-
89884-// All contains the Parse of all the template files
89885-type All struct {
89886-	files map[span.URI]*Parsed
89887-}
89888-
89889-// New returns the Parses of the snapshot's tmpl files
89890-// (maybe cache these, but then avoiding import cycles needs code rearrangements)
89891-func New(tmpls map[span.URI]source.FileHandle) *All {
89892-	all := make(map[span.URI]*Parsed)
89893-	for k, v := range tmpls {
89894-		buf, err := v.Read()
89895-		if err != nil { // PJW: decide what to do with these errors
89896-			log.Printf("failed to read %s (%v)", v.URI().Filename(), err)
89897-			continue
89898-		}
89899-		all[k] = parseBuffer(buf)
89900-	}
89901-	return &All{files: all}
89902-}
89903-
89904-func parseBuffer(buf []byte) *Parsed {
89905-	ans := &Parsed{
89906-		buf:   buf,
89907-		check: -1,
89908-		nls:   []int{-1},
89909-	}
89910-	if len(buf) == 0 {
89911-		return ans
89912-	}
89913-	// how to compute allAscii...
89914-	for _, b := range buf {
89915-		if b >= utf8.RuneSelf {
89916-			ans.nonASCII = true
89917-			break
89918-		}
89919-	}
89920-	if buf[len(buf)-1] != '\n' {
89921-		ans.buf = append(buf, '\n')
89922-	}
89923-	for i, p := range ans.buf {
89924-		if p == '\n' {
89925-			ans.nls = append(ans.nls, i)
89926-		}
89927-	}
89928-	ans.setTokens() // ans.buf may be a new []byte
89929-	ans.lines = bytes.Split(ans.buf, []byte{'\n'})
89930-	t, err := template.New("").Parse(string(ans.buf))
89931-	if err != nil {
89932-		funcs := make(template.FuncMap)
89933-		for t == nil && ans.ParseErr == nil {
89934-			// in 1.17 it may be possible to avoid getting this error
89935-			//  template: :2: function "foo" not defined
89936-			matches := parseErrR.FindStringSubmatch(err.Error())
89937-			if len(matches) == 2 {
89938-				// suppress the error by giving it a function with the right name
89939-				funcs[matches[1]] = func() interface{} { return nil }
89940-				t, err = template.New("").Funcs(funcs).Parse(string(ans.buf))
89941-				continue
89942-			}
89943-			ans.ParseErr = err // unfixed error
89944-			return ans
89945-		}
89946-	}
89947-	ans.named = t.Templates()
89948-	// set the symbols
89949-	for _, t := range ans.named {
89950-		ans.stack = append(ans.stack, t.Root)
89951-		ans.findSymbols()
89952-		if t.Name() != "" {
89953-			// defining a template. The pos is just after {{define...}} (or {{block...}}?)
89954-			at, sz := ans.FindLiteralBefore(int(t.Root.Pos))
89955-			s := symbol{start: at, length: sz, name: t.Name(), kind: protocol.Namespace, vardef: true}
89956-			ans.symbols = append(ans.symbols, s)
89957-		}
89958-	}
89959-
89960-	sort.Slice(ans.symbols, func(i, j int) bool {
89961-		left, right := ans.symbols[i], ans.symbols[j]
89962-		if left.start != right.start {
89963-			return left.start < right.start
89964-		}
89965-		if left.vardef != right.vardef {
89966-			return left.vardef
89967-		}
89968-		return left.kind < right.kind
89969-	})
89970-	return ans
89971-}
89972-
89973-// FindLiteralBefore locates the first preceding string literal
89974-// returning its position and length in buf
89975-// or returns -1 if there is none.
89976-// Assume double-quoted string rather than backquoted string for now.
89977-func (p *Parsed) FindLiteralBefore(pos int) (int, int) {
89978-	left, right := -1, -1
89979-	for i := pos - 1; i >= 0; i-- {
89980-		if p.buf[i] != '"' {
89981-			continue
89982-		}
89983-		if right == -1 {
89984-			right = i
89985-			continue
89986-		}
89987-		left = i
89988-		break
89989-	}
89990-	if left == -1 {
89991-		return -1, 0
89992-	}
89993-	return left + 1, right - left - 1
89994-}
89995-
89996-var (
89997-	parseErrR = regexp.MustCompile(`template:.*function "([^"]+)" not defined`)
89998-)
89999-
90000-func (p *Parsed) setTokens() {
90001-	const (
90002-		// InRaw and InString only occur inside an action (SeenLeft)
90003-		Start = iota
90004-		InRaw
90005-		InString
90006-		SeenLeft
90007-	)
90008-	state := Start
90009-	var left, oldState int
90010-	for n := 0; n < len(p.buf); n++ {
90011-		c := p.buf[n]
90012-		switch state {
90013-		case InRaw:
90014-			if c == '`' {
90015-				state = oldState
90016-			}
90017-		case InString:
90018-			if c == '"' && !isEscaped(p.buf[:n]) {
90019-				state = oldState
90020-			}
90021-		case SeenLeft:
90022-			if c == '`' {
90023-				oldState = state // it's SeenLeft, but a little clearer this way
90024-				state = InRaw
90025-				continue
90026-			}
90027-			if c == '"' {
90028-				oldState = state
90029-				state = InString
90030-				continue
90031-			}
90032-			if bytes.HasPrefix(p.buf[n:], Right) {
90033-				right := n + len(Right)
90034-				tok := Token{Start: left,
90035-					End:       right,
90036-					Multiline: bytes.Contains(p.buf[left:right], []byte{'\n'}),
90037-				}
90038-				p.tokens = append(p.tokens, tok)
90039-				state = Start
90040-			}
90041-			// If we see (unquoted) Left then the original left is probably the user
90042-			// typing. Suppress the original left
90043-			if bytes.HasPrefix(p.buf[n:], Left) {
90044-				p.elideAt(left)
90045-				left = n
90046-				n += len(Left) - 1 // skip the rest
90047-			}
90048-		case Start:
90049-			if bytes.HasPrefix(p.buf[n:], Left) {
90050-				left = n
90051-				state = SeenLeft
90052-				n += len(Left) - 1 // skip the rest (avoids {{{ bug)
90053-			}
90054-		}
90055-	}
90056-	// this error occurs after typing {{ at the end of the file
90057-	if state != Start {
90058-		// Unclosed Left. remove the Left at left
90059-		p.elideAt(left)
90060-	}
90061-}
90062-
90063-func (p *Parsed) elideAt(left int) {
90064-	if p.elided == nil {
90065-		// p.buf is the same buffer that v.Read() returns, so copy it.
90066-		// (otherwise the next time it's parsed, elided information is lost)
90067-		b := make([]byte, len(p.buf))
90068-		copy(b, p.buf)
90069-		p.buf = b
90070-	}
90071-	for i := 0; i < len(Left); i++ {
90072-		p.buf[left+i] = ' '
90073-	}
90074-	p.elided = append(p.elided, left)
90075-}
90076-
90077-// isEscaped reports whether the byte after buf is escaped
90078-func isEscaped(buf []byte) bool {
90079-	backSlashes := 0
90080-	for j := len(buf) - 1; j >= 0 && buf[j] == '\\'; j-- {
90081-		backSlashes++
90082-	}
90083-	return backSlashes%2 == 1
90084-}
90085-
90086-func (p *Parsed) Tokens() []Token {
90087-	return p.tokens
90088-}
90089-
90090-// TODO(adonovan): the next 100 lines could perhaps replaced by use of protocol.Mapper.
90091-
90092-func (p *Parsed) utf16len(buf []byte) int {
90093-	cnt := 0
90094-	if !p.nonASCII {
90095-		return len(buf)
90096-	}
90097-	// we need a utf16len(rune), but we don't have it
90098-	for _, r := range string(buf) {
90099-		cnt++
90100-		if r >= 1<<16 {
90101-			cnt++
90102-		}
90103-	}
90104-	return cnt
90105-}
90106-
90107-func (p *Parsed) TokenSize(t Token) (int, error) {
90108-	if t.Multiline {
90109-		return -1, fmt.Errorf("TokenSize called with Multiline token %#v", t)
90110-	}
90111-	ans := p.utf16len(p.buf[t.Start:t.End])
90112-	return ans, nil
90113-}
90114-
90115-// RuneCount counts runes in line l, from col s to e
90116-// (e==0 for end of line. called only for multiline tokens)
90117-func (p *Parsed) RuneCount(l, s, e uint32) uint32 {
90118-	start := p.nls[l] + 1 + int(s)
90119-	end := p.nls[l] + 1 + int(e)
90120-	if e == 0 || end > p.nls[l+1] {
90121-		end = p.nls[l+1]
90122-	}
90123-	return uint32(utf8.RuneCount(p.buf[start:end]))
90124-}
90125-
90126-// LineCol converts from a 0-based byte offset to 0-based line, col. col in runes
90127-func (p *Parsed) LineCol(x int) (uint32, uint32) {
90128-	if x < p.check {
90129-		p.lastnl = 0
90130-	}
90131-	p.check = x
90132-	for i := p.lastnl; i < len(p.nls); i++ {
90133-		if p.nls[i] <= x {
90134-			continue
90135-		}
90136-		p.lastnl = i
90137-		var count int
90138-		if i > 0 && x == p.nls[i-1] { // \n
90139-			count = 0
90140-		} else {
90141-			count = p.utf16len(p.buf[p.nls[i-1]+1 : x])
90142-		}
90143-		return uint32(i - 1), uint32(count)
90144-	}
90145-	if x == len(p.buf)-1 { // trailing \n
90146-		return uint32(len(p.nls) - 1), 0
90147-	}
90148-	// shouldn't happen
90149-	for i := 1; i < 4; i++ {
90150-		_, f, l, ok := runtime.Caller(i)
90151-		if !ok {
90152-			break
90153-		}
90154-		log.Printf("%d: %s:%d", i, f, l)
90155-	}
90156-
90157-	msg := fmt.Errorf("LineCol off the end, %d of %d, nls=%v, %q", x, len(p.buf), p.nls, p.buf[x:])
90158-	event.Error(context.Background(), "internal error", msg)
90159-	return 0, 0
90160-}
90161-
90162-// Position produces a protocol.Position from an offset in the template
90163-func (p *Parsed) Position(pos int) protocol.Position {
90164-	line, col := p.LineCol(pos)
90165-	return protocol.Position{Line: line, Character: col}
90166-}
90167-
90168-func (p *Parsed) Range(x, length int) protocol.Range {
90169-	line, col := p.LineCol(x)
90170-	ans := protocol.Range{
90171-		Start: protocol.Position{Line: line, Character: col},
90172-		End:   protocol.Position{Line: line, Character: col + uint32(length)},
90173-	}
90174-	return ans
90175-}
90176-
90177-// FromPosition translates a protocol.Position into an offset into the template
90178-func (p *Parsed) FromPosition(x protocol.Position) int {
90179-	l, c := int(x.Line), int(x.Character)
90180-	if l >= len(p.nls) || p.nls[l]+1 >= len(p.buf) {
90181-		// paranoia to avoid panic. return the largest offset
90182-		return len(p.buf)
90183-	}
90184-	line := p.buf[p.nls[l]+1:]
90185-	cnt := 0
90186-	for w := range string(line) {
90187-		if cnt >= c {
90188-			return w + p.nls[l] + 1
90189-		}
90190-		cnt++
90191-	}
90192-	// do we get here? NO
90193-	pos := int(x.Character) + p.nls[int(x.Line)] + 1
90194-	event.Error(context.Background(), "internal error", fmt.Errorf("surprise %#v", x))
90195-	return pos
90196-}
90197-
90198-func symAtPosition(fh source.FileHandle, loc protocol.Position) (*symbol, *Parsed, error) {
90199-	buf, err := fh.Read()
90200-	if err != nil {
90201-		return nil, nil, err
90202-	}
90203-	p := parseBuffer(buf)
90204-	pos := p.FromPosition(loc)
90205-	syms := p.SymsAtPos(pos)
90206-	if len(syms) == 0 {
90207-		return nil, p, fmt.Errorf("no symbol found")
90208-	}
90209-	if len(syms) > 1 {
90210-		log.Printf("Hover: %d syms, not 1 %v", len(syms), syms)
90211-	}
90212-	sym := syms[0]
90213-	return &sym, p, nil
90214-}
90215-
90216-func (p *Parsed) SymsAtPos(pos int) []symbol {
90217-	ans := []symbol{}
90218-	for _, s := range p.symbols {
90219-		if s.start <= pos && pos < s.start+s.length {
90220-			ans = append(ans, s)
90221-		}
90222-	}
90223-	return ans
90224-}
90225-
90226-type wrNode struct {
90227-	p *Parsed
90228-	w io.Writer
90229-}
90230-
90231-// WriteNode is for debugging
90232-func (p *Parsed) WriteNode(w io.Writer, n parse.Node) {
90233-	wr := wrNode{p: p, w: w}
90234-	wr.writeNode(n, "")
90235-}
90236-
90237-func (wr wrNode) writeNode(n parse.Node, indent string) {
90238-	if n == nil {
90239-		return
90240-	}
90241-	at := func(pos parse.Pos) string {
90242-		line, col := wr.p.LineCol(int(pos))
90243-		return fmt.Sprintf("(%d)%v:%v", pos, line, col)
90244-	}
90245-	switch x := n.(type) {
90246-	case *parse.ActionNode:
90247-		fmt.Fprintf(wr.w, "%sActionNode at %s\n", indent, at(x.Pos))
90248-		wr.writeNode(x.Pipe, indent+". ")
90249-	case *parse.BoolNode:
90250-		fmt.Fprintf(wr.w, "%sBoolNode at %s, %v\n", indent, at(x.Pos), x.True)
90251-	case *parse.BranchNode:
90252-		fmt.Fprintf(wr.w, "%sBranchNode at %s\n", indent, at(x.Pos))
90253-		wr.writeNode(x.Pipe, indent+"Pipe. ")
90254-		wr.writeNode(x.List, indent+"List. ")
90255-		wr.writeNode(x.ElseList, indent+"Else. ")
90256-	case *parse.ChainNode:
90257-		fmt.Fprintf(wr.w, "%sChainNode at %s, %v\n", indent, at(x.Pos), x.Field)
90258-	case *parse.CommandNode:
90259-		fmt.Fprintf(wr.w, "%sCommandNode at %s, %d children\n", indent, at(x.Pos), len(x.Args))
90260-		for _, a := range x.Args {
90261-			wr.writeNode(a, indent+". ")
90262-		}
90263-	//case *parse.CommentNode: // 1.16
90264-	case *parse.DotNode:
90265-		fmt.Fprintf(wr.w, "%sDotNode at %s\n", indent, at(x.Pos))
90266-	case *parse.FieldNode:
90267-		fmt.Fprintf(wr.w, "%sFieldNode at %s, %v\n", indent, at(x.Pos), x.Ident)
90268-	case *parse.IdentifierNode:
90269-		fmt.Fprintf(wr.w, "%sIdentifierNode at %s, %v\n", indent, at(x.Pos), x.Ident)
90270-	case *parse.IfNode:
90271-		fmt.Fprintf(wr.w, "%sIfNode at %s\n", indent, at(x.Pos))
90272-		wr.writeNode(&x.BranchNode, indent+". ")
90273-	case *parse.ListNode:
90274-		if x == nil {
90275-			return // nil BranchNode.ElseList
90276-		}
90277-		fmt.Fprintf(wr.w, "%sListNode at %s, %d children\n", indent, at(x.Pos), len(x.Nodes))
90278-		for _, n := range x.Nodes {
90279-			wr.writeNode(n, indent+". ")
90280-		}
90281-	case *parse.NilNode:
90282-		fmt.Fprintf(wr.w, "%sNilNode at %s\n", indent, at(x.Pos))
90283-	case *parse.NumberNode:
90284-		fmt.Fprintf(wr.w, "%sNumberNode at %s, %s\n", indent, at(x.Pos), x.Text)
90285-	case *parse.PipeNode:
90286-		if x == nil {
90287-			return // {{template "xxx"}}
90288-		}
90289-		fmt.Fprintf(wr.w, "%sPipeNode at %s, %d vars, %d cmds, IsAssign:%v\n",
90290-			indent, at(x.Pos), len(x.Decl), len(x.Cmds), x.IsAssign)
90291-		for _, d := range x.Decl {
90292-			wr.writeNode(d, indent+"Decl. ")
90293-		}
90294-		for _, c := range x.Cmds {
90295-			wr.writeNode(c, indent+"Cmd. ")
90296-		}
90297-	case *parse.RangeNode:
90298-		fmt.Fprintf(wr.w, "%sRangeNode at %s\n", indent, at(x.Pos))
90299-		wr.writeNode(&x.BranchNode, indent+". ")
90300-	case *parse.StringNode:
90301-		fmt.Fprintf(wr.w, "%sStringNode at %s, %s\n", indent, at(x.Pos), x.Quoted)
90302-	case *parse.TemplateNode:
90303-		fmt.Fprintf(wr.w, "%sTemplateNode at %s, %s\n", indent, at(x.Pos), x.Name)
90304-		wr.writeNode(x.Pipe, indent+". ")
90305-	case *parse.TextNode:
90306-		fmt.Fprintf(wr.w, "%sTextNode at %s, len %d\n", indent, at(x.Pos), len(x.Text))
90307-	case *parse.VariableNode:
90308-		fmt.Fprintf(wr.w, "%sVariableNode at %s, %v\n", indent, at(x.Pos), x.Ident)
90309-	case *parse.WithNode:
90310-		fmt.Fprintf(wr.w, "%sWithNode at %s\n", indent, at(x.Pos))
90311-		wr.writeNode(&x.BranchNode, indent+". ")
90312-	}
90313-}
90314-
90315-var kindNames = []string{"", "File", "Module", "Namespace", "Package", "Class", "Method", "Property",
90316-	"Field", "Constructor", "Enum", "Interface", "Function", "Variable", "Constant", "String",
90317-	"Number", "Boolean", "Array", "Object", "Key", "Null", "EnumMember", "Struct", "Event",
90318-	"Operator", "TypeParameter"}
90319-
90320-func kindStr(k protocol.SymbolKind) string {
90321-	n := int(k)
90322-	if n < 1 || n >= len(kindNames) {
90323-		return fmt.Sprintf("?SymbolKind %d?", n)
90324-	}
90325-	return kindNames[n]
90326-}
90327diff -urN a/gopls/internal/lsp/template/parse_test.go b/gopls/internal/lsp/template/parse_test.go
90328--- a/gopls/internal/lsp/template/parse_test.go	2000-01-01 00:00:00.000000000 -0000
90329+++ b/gopls/internal/lsp/template/parse_test.go	1970-01-01 00:00:00.000000000 +0000
90330@@ -1,238 +0,0 @@
90331-// Copyright 2021 The Go Authors. All rights reserved.
90332-// Use of this source code is governed by a BSD-style
90333-// license that can be found in the LICENSE file.
90334-
90335-package template
90336-
90337-import (
90338-	"strings"
90339-	"testing"
90340-)
90341-
90342-type datum struct {
90343-	buf  string
90344-	cnt  int
90345-	syms []string // the symbols in the parse of buf
90346-}
90347-
90348-var tmpl = []datum{{`
90349-{{if (foo .X.Y)}}{{$A := "hi"}}{{.Z $A}}{{else}}
90350-{{$A.X 12}}
90351-{{foo (.X.Y) 23 ($A.Zü)}}
90352-{{end}}`, 1, []string{"{7,3,foo,Function,false}", "{12,1,X,Method,false}",
90353-	"{14,1,Y,Method,false}", "{21,2,$A,Variable,true}", "{26,2,,String,false}",
90354-	"{35,1,Z,Method,false}", "{38,2,$A,Variable,false}",
90355-	"{53,2,$A,Variable,false}", "{56,1,X,Method,false}", "{57,2,,Number,false}",
90356-	"{64,3,foo,Function,false}", "{70,1,X,Method,false}",
90357-	"{72,1,Y,Method,false}", "{75,2,,Number,false}", "{80,2,$A,Variable,false}",
90358-	"{83,2,Zü,Method,false}", "{94,3,,Constant,false}"}},
90359-
90360-	{`{{define "zzz"}}{{.}}{{end}}
90361-{{template "zzz"}}`, 2, []string{"{10,3,zzz,Namespace,true}", "{18,1,dot,Variable,false}",
90362-		"{41,3,zzz,Package,false}"}},
90363-
90364-	{`{{block "aaa" foo}}b{{end}}`, 2, []string{"{9,3,aaa,Namespace,true}",
90365-		"{9,3,aaa,Package,false}", "{14,3,foo,Function,false}", "{19,1,,Constant,false}"}},
90366-	{"", 0, nil},
90367-}
90368-
90369-func TestSymbols(t *testing.T) {
90370-	for i, x := range tmpl {
90371-		got := parseBuffer([]byte(x.buf))
90372-		if got.ParseErr != nil {
90373-			t.Errorf("error:%v", got.ParseErr)
90374-			continue
90375-		}
90376-		if len(got.named) != x.cnt {
90377-			t.Errorf("%d: got %d, expected %d", i, len(got.named), x.cnt)
90378-		}
90379-		for n, s := range got.symbols {
90380-			if s.String() != x.syms[n] {
90381-				t.Errorf("%d: got %s, expected %s", i, s.String(), x.syms[n])
90382-			}
90383-		}
90384-	}
90385-}
90386-
90387-func TestWordAt(t *testing.T) {
90388-	want := []string{"", "", "$A", "$A", "", "", "", "", "", "",
90389-		"", "", "", "if", "if", "", "$A", "$A", "", "",
90390-		"B", "", "", "end", "end", "end", "", "", ""}
90391-	p := parseBuffer([]byte("{{$A := .}}{{if $A}}B{{end}}"))
90392-	for i := 0; i < len(p.buf); i++ {
90393-		got := findWordAt(p, i)
90394-		if got != want[i] {
90395-			t.Errorf("for %d, got %q, wanted %q", i, got, want[i])
90396-		}
90397-	}
90398-}
90399-
90400-func TestNLS(t *testing.T) {
90401-	buf := `{{if (foÜx .X.Y)}}{{$A := "hi"}}{{.Z $A}}{{else}}
90402-	{{$A.X 12}}
90403-	{{foo (.X.Y) 23 ($A.Z)}}
90404-	{{end}}
90405-	`
90406-	p := parseBuffer([]byte(buf))
90407-	if p.ParseErr != nil {
90408-		t.Fatal(p.ParseErr)
90409-	}
90410-	// line 0 doesn't have a \n in front of it
90411-	for i := 1; i < len(p.nls)-1; i++ {
90412-		if buf[p.nls[i]] != '\n' {
90413-			t.Errorf("line %d got %c", i, buf[p.nls[i]])
90414-		}
90415-	}
90416-	// fake line at end of file
90417-	if p.nls[len(p.nls)-1] != len(buf) {
90418-		t.Errorf("got %d expected %d", p.nls[len(p.nls)-1], len(buf))
90419-	}
90420-}
90421-
90422-func TestLineCol(t *testing.T) {
90423-	buf := `{{if (foÜx .X.Y)}}{{$A := "hi"}}{{.Z $A}}{{else}}
90424-	{{$A.X 12}}
90425-	{{foo (.X.Y) 23 ($A.Z)}}
90426-	{{end}}`
90427-	if false {
90428-		t.Error(buf)
90429-	}
90430-	for n, cx := range tmpl {
90431-		buf := cx.buf
90432-		p := parseBuffer([]byte(buf))
90433-		if p.ParseErr != nil {
90434-			t.Fatal(p.ParseErr)
90435-		}
90436-		type loc struct {
90437-			offset int
90438-			l, c   uint32
90439-		}
90440-		saved := []loc{}
90441-		// forwards
90442-		var lastl, lastc uint32
90443-		for offset := range buf {
90444-			l, c := p.LineCol(offset)
90445-			saved = append(saved, loc{offset, l, c})
90446-			if l > lastl {
90447-				lastl = l
90448-				if c != 0 {
90449-					t.Errorf("line %d, got %d instead of 0", l, c)
90450-				}
90451-			}
90452-			if c > lastc {
90453-				lastc = c
90454-			}
90455-		}
90456-		lines := strings.Split(buf, "\n")
90457-		mxlen := -1
90458-		for _, l := range lines {
90459-			if len(l) > mxlen {
90460-				mxlen = len(l)
90461-			}
90462-		}
90463-		if int(lastl) != len(lines)-1 && int(lastc) != mxlen {
90464-			// lastl is 0 if there is only 1 line(?)
90465-			t.Errorf("expected %d, %d, got %d, %d for case %d", len(lines)-1, mxlen, lastl, lastc, n)
90466-		}
90467-		// backwards
90468-		for j := len(saved) - 1; j >= 0; j-- {
90469-			s := saved[j]
90470-			xl, xc := p.LineCol(s.offset)
90471-			if xl != s.l || xc != s.c {
90472-				t.Errorf("at offset %d(%d), got (%d,%d), expected (%d,%d)", s.offset, j, xl, xc, s.l, s.c)
90473-			}
90474-		}
90475-	}
90476-}
90477-
90478-func TestLineColNL(t *testing.T) {
90479-	buf := "\n\n\n\n\n"
90480-	p := parseBuffer([]byte(buf))
90481-	if p.ParseErr != nil {
90482-		t.Fatal(p.ParseErr)
90483-	}
90484-	for i := 0; i < len(buf); i++ {
90485-		l, c := p.LineCol(i)
90486-		if c != 0 || int(l) != i+1 {
90487-			t.Errorf("got (%d,%d), expected (%d,0)", l, c, i)
90488-		}
90489-	}
90490-}
90491-
90492-func TestPos(t *testing.T) {
90493-	buf := `
90494-	{{if (foÜx .X.Y)}}{{$A := "hi"}}{{.Z $A}}{{else}}
90495-	{{$A.X 12}}
90496-	{{foo (.X.Y) 23 ($A.Z)}}
90497-	{{end}}`
90498-	p := parseBuffer([]byte(buf))
90499-	if p.ParseErr != nil {
90500-		t.Fatal(p.ParseErr)
90501-	}
90502-	for pos, r := range buf {
90503-		if r == '\n' {
90504-			continue
90505-		}
90506-		x := p.Position(pos)
90507-		n := p.FromPosition(x)
90508-		if n != pos {
90509-			// once it's wrong, it will be wrong forever
90510-			t.Fatalf("at pos %d (rune %c) got %d {%#v]", pos, r, n, x)
90511-		}
90512-
90513-	}
90514-}
90515-func TestLen(t *testing.T) {
90516-	data := []struct {
90517-		cnt int
90518-		v   string
90519-	}{{1, "a"}, {1, "膈"}, {4, "����"}, {7, "3��4567"}}
90520-	p := &Parsed{nonASCII: true}
90521-	for _, d := range data {
90522-		got := p.utf16len([]byte(d.v))
90523-		if got != d.cnt {
90524-			t.Errorf("%v, got %d wanted %d", d, got, d.cnt)
90525-		}
90526-	}
90527-}
90528-
90529-func TestUtf16(t *testing.T) {
90530-	buf := `
90531-	{{if (foÜx .X.Y)}}��{{$A := "hi"}}{{.Z $A}}{{else}}
90532-	{{$A.X 12}}
90533-	{{foo (.X.Y) 23 ($A.Z)}}
90534-	{{end}}`
90535-	p := parseBuffer([]byte(buf))
90536-	if p.nonASCII == false {
90537-		t.Error("expected nonASCII to be true")
90538-	}
90539-}
90540-
90541-type ttest struct {
90542-	tmpl      string
90543-	tokCnt    int
90544-	elidedCnt int8
90545-}
90546-
90547-func TestQuotes(t *testing.T) {
90548-	tsts := []ttest{
90549-		{"{{- /*comment*/ -}}", 1, 0},
90550-		{"{{/*`\ncomment\n`*/}}", 1, 0},
90551-		//{"{{foo\nbar}}\n", 1, 0}, // this action spanning lines parses in 1.16
90552-		{"{{\"{{foo}}{{\"}}", 1, 0},
90553-		{"{{\n{{- when}}", 1, 1},          // corrected
90554-		{"{{{{if .}}xx{{\n{{end}}", 2, 2}, // corrected
90555-	}
90556-	for _, s := range tsts {
90557-		p := parseBuffer([]byte(s.tmpl))
90558-		if len(p.tokens) != s.tokCnt {
90559-			t.Errorf("%q: got %d tokens, expected %d", s, len(p.tokens), s.tokCnt)
90560-		}
90561-		if p.ParseErr != nil {
90562-			t.Errorf("%q: %v", string(p.buf), p.ParseErr)
90563-		}
90564-		if len(p.elided) != int(s.elidedCnt) {
90565-			t.Errorf("%q: elided %d, expected %d", s, len(p.elided), s.elidedCnt)
90566-		}
90567-	}
90568-}
90569diff -urN a/gopls/internal/lsp/template/symbols.go b/gopls/internal/lsp/template/symbols.go
90570--- a/gopls/internal/lsp/template/symbols.go	2000-01-01 00:00:00.000000000 -0000
90571+++ b/gopls/internal/lsp/template/symbols.go	1970-01-01 00:00:00.000000000 +0000
90572@@ -1,230 +0,0 @@
90573-// Copyright 2021 The Go Authors. All rights reserved.
90574-// Use of this source code is governed by a BSD-style
90575-// license that can be found in the LICENSE file.
90576-
90577-package template
90578-
90579-import (
90580-	"bytes"
90581-	"context"
90582-	"fmt"
90583-	"text/template/parse"
90584-	"unicode/utf8"
90585-
90586-	"golang.org/x/tools/internal/event"
90587-	"golang.org/x/tools/gopls/internal/lsp/protocol"
90588-	"golang.org/x/tools/gopls/internal/lsp/source"
90589-)
90590-
90591-// in local coordinates, to be translated to protocol.DocumentSymbol
90592-type symbol struct {
90593-	start  int // for sorting
90594-	length int // in runes (unicode code points)
90595-	name   string
90596-	kind   protocol.SymbolKind
90597-	vardef bool // is this a variable definition?
90598-	// do we care about selection range, or children?
90599-	// no children yet, and selection range is the same as range
90600-}
90601-
90602-func (s symbol) String() string {
90603-	return fmt.Sprintf("{%d,%d,%s,%s,%v}", s.start, s.length, s.name, s.kind, s.vardef)
90604-}
90605-
90606-// for FieldNode or VariableNode (or ChainNode?)
90607-func (p *Parsed) fields(flds []string, x parse.Node) []symbol {
90608-	ans := []symbol{}
90609-	// guessing that there are no embedded blanks allowed. The doc is unclear
90610-	lookfor := ""
90611-	switch x.(type) {
90612-	case *parse.FieldNode:
90613-		for _, f := range flds {
90614-			lookfor += "." + f // quadratic, but probably ok
90615-		}
90616-	case *parse.VariableNode:
90617-		lookfor = flds[0]
90618-		for i := 1; i < len(flds); i++ {
90619-			lookfor += "." + flds[i]
90620-		}
90621-	case *parse.ChainNode: // PJW, what are these?
90622-		for _, f := range flds {
90623-			lookfor += "." + f // quadratic, but probably ok
90624-		}
90625-	default:
90626-		// If these happen they will happen even if gopls is restarted
90627-		// and the users does the same thing, so it is better not to panic.
90628-		// context.Background() is used because we don't have access
90629-		// to any other context. [we could, but it would be complicated]
90630-		event.Log(context.Background(), fmt.Sprintf("%T unexpected in fields()", x))
90631-		return nil
90632-	}
90633-	if len(lookfor) == 0 {
90634-		event.Log(context.Background(), fmt.Sprintf("no strings in fields() %#v", x))
90635-		return nil
90636-	}
90637-	startsAt := int(x.Position())
90638-	ix := bytes.Index(p.buf[startsAt:], []byte(lookfor)) // HasPrefix? PJW?
90639-	if ix < 0 || ix > len(lookfor) {                     // lookfor expected to be at start (or so)
90640-		// probably golang.go/#43388, so back up
90641-		startsAt -= len(flds[0]) + 1
90642-		ix = bytes.Index(p.buf[startsAt:], []byte(lookfor)) // ix might be 1? PJW
90643-		if ix < 0 {
90644-			return ans
90645-		}
90646-	}
90647-	at := ix + startsAt
90648-	for _, f := range flds {
90649-		at += 1 // .
90650-		kind := protocol.Method
90651-		if f[0] == '$' {
90652-			kind = protocol.Variable
90653-		}
90654-		sym := symbol{name: f, kind: kind, start: at, length: utf8.RuneCount([]byte(f))}
90655-		if kind == protocol.Variable && len(p.stack) > 1 {
90656-			if pipe, ok := p.stack[len(p.stack)-2].(*parse.PipeNode); ok {
90657-				for _, y := range pipe.Decl {
90658-					if x == y {
90659-						sym.vardef = true
90660-					}
90661-				}
90662-			}
90663-		}
90664-		ans = append(ans, sym)
90665-		at += len(f)
90666-	}
90667-	return ans
90668-}
90669-
90670-func (p *Parsed) findSymbols() {
90671-	if len(p.stack) == 0 {
90672-		return
90673-	}
90674-	n := p.stack[len(p.stack)-1]
90675-	pop := func() {
90676-		p.stack = p.stack[:len(p.stack)-1]
90677-	}
90678-	if n == nil { // allowing nil simplifies the code
90679-		pop()
90680-		return
90681-	}
90682-	nxt := func(nd parse.Node) {
90683-		p.stack = append(p.stack, nd)
90684-		p.findSymbols()
90685-	}
90686-	switch x := n.(type) {
90687-	case *parse.ActionNode:
90688-		nxt(x.Pipe)
90689-	case *parse.BoolNode:
90690-		// need to compute the length from the value
90691-		msg := fmt.Sprintf("%v", x.True)
90692-		p.symbols = append(p.symbols, symbol{start: int(x.Pos), length: len(msg), kind: protocol.Boolean})
90693-	case *parse.BranchNode:
90694-		nxt(x.Pipe)
90695-		nxt(x.List)
90696-		nxt(x.ElseList)
90697-	case *parse.ChainNode:
90698-		p.symbols = append(p.symbols, p.fields(x.Field, x)...)
90699-		nxt(x.Node)
90700-	case *parse.CommandNode:
90701-		for _, a := range x.Args {
90702-			nxt(a)
90703-		}
90704-	//case *parse.CommentNode: // go 1.16
90705-	//	log.Printf("implement %d", x.Type())
90706-	case *parse.DotNode:
90707-		sym := symbol{name: "dot", kind: protocol.Variable, start: int(x.Pos), length: 1}
90708-		p.symbols = append(p.symbols, sym)
90709-	case *parse.FieldNode:
90710-		p.symbols = append(p.symbols, p.fields(x.Ident, x)...)
90711-	case *parse.IdentifierNode:
90712-		sym := symbol{name: x.Ident, kind: protocol.Function, start: int(x.Pos),
90713-			length: utf8.RuneCount([]byte(x.Ident))}
90714-		p.symbols = append(p.symbols, sym)
90715-	case *parse.IfNode:
90716-		nxt(&x.BranchNode)
90717-	case *parse.ListNode:
90718-		if x != nil { // wretched typed nils. Node should have an IfNil
90719-			for _, nd := range x.Nodes {
90720-				nxt(nd)
90721-			}
90722-		}
90723-	case *parse.NilNode:
90724-		sym := symbol{name: "nil", kind: protocol.Constant, start: int(x.Pos), length: 3}
90725-		p.symbols = append(p.symbols, sym)
90726-	case *parse.NumberNode:
90727-		// no name; ascii
90728-		p.symbols = append(p.symbols, symbol{start: int(x.Pos), length: len(x.Text), kind: protocol.Number})
90729-	case *parse.PipeNode:
90730-		if x == nil { // {{template "foo"}}
90731-			return
90732-		}
90733-		for _, d := range x.Decl {
90734-			nxt(d)
90735-		}
90736-		for _, c := range x.Cmds {
90737-			nxt(c)
90738-		}
90739-	case *parse.RangeNode:
90740-		nxt(&x.BranchNode)
90741-	case *parse.StringNode:
90742-		// no name
90743-		sz := utf8.RuneCount([]byte(x.Text))
90744-		p.symbols = append(p.symbols, symbol{start: int(x.Pos), length: sz, kind: protocol.String})
90745-	case *parse.TemplateNode: // invoking a template
90746-		// x.Pos points to the quote before the name
90747-		p.symbols = append(p.symbols, symbol{name: x.Name, kind: protocol.Package, start: int(x.Pos) + 1,
90748-			length: utf8.RuneCount([]byte(x.Name))})
90749-		nxt(x.Pipe)
90750-	case *parse.TextNode:
90751-		if len(x.Text) == 1 && x.Text[0] == '\n' {
90752-			break
90753-		}
90754-		// nothing to report, but build one for hover
90755-		sz := utf8.RuneCount([]byte(x.Text))
90756-		p.symbols = append(p.symbols, symbol{start: int(x.Pos), length: sz, kind: protocol.Constant})
90757-	case *parse.VariableNode:
90758-		p.symbols = append(p.symbols, p.fields(x.Ident, x)...)
90759-	case *parse.WithNode:
90760-		nxt(&x.BranchNode)
90761-
90762-	}
90763-	pop()
90764-}
90765-
90766-// DocumentSymbols returns a hierarchy of the symbols defined in a template file.
90767-// (The hierarchy is flat. SymbolInformation might be better.)
90768-func DocumentSymbols(snapshot source.Snapshot, fh source.FileHandle) ([]protocol.DocumentSymbol, error) {
90769-	buf, err := fh.Read()
90770-	if err != nil {
90771-		return nil, err
90772-	}
90773-	p := parseBuffer(buf)
90774-	if p.ParseErr != nil {
90775-		return nil, p.ParseErr
90776-	}
90777-	var ans []protocol.DocumentSymbol
90778-	for _, s := range p.symbols {
90779-		if s.kind == protocol.Constant {
90780-			continue
90781-		}
90782-		d := kindStr(s.kind)
90783-		if d == "Namespace" {
90784-			d = "Template"
90785-		}
90786-		if s.vardef {
90787-			d += "(def)"
90788-		} else {
90789-			d += "(use)"
90790-		}
90791-		r := p.Range(s.start, s.length)
90792-		y := protocol.DocumentSymbol{
90793-			Name:           s.name,
90794-			Detail:         d,
90795-			Kind:           s.kind,
90796-			Range:          r,
90797-			SelectionRange: r, // or should this be the entire {{...}}?
90798-		}
90799-		ans = append(ans, y)
90800-	}
90801-	return ans, nil
90802-}
90803diff -urN a/gopls/internal/lsp/testdata/addimport/addimport.go.golden b/gopls/internal/lsp/testdata/addimport/addimport.go.golden
90804--- a/gopls/internal/lsp/testdata/addimport/addimport.go.golden	2000-01-01 00:00:00.000000000 -0000
90805+++ b/gopls/internal/lsp/testdata/addimport/addimport.go.golden	1970-01-01 00:00:00.000000000 +0000
90806@@ -1,7 +0,0 @@
90807--- addimport --
90808-package addimport //@addimport("", "bytes")
90809-
90810-import "bytes"
90811-
90812-func main() {}
90813-
90814diff -urN a/gopls/internal/lsp/testdata/addimport/addimport.go.in b/gopls/internal/lsp/testdata/addimport/addimport.go.in
90815--- a/gopls/internal/lsp/testdata/addimport/addimport.go.in	2000-01-01 00:00:00.000000000 -0000
90816+++ b/gopls/internal/lsp/testdata/addimport/addimport.go.in	1970-01-01 00:00:00.000000000 +0000
90817@@ -1,3 +0,0 @@
90818-package addimport //@addimport("", "bytes")
90819-
90820-func main() {}
90821diff -urN a/gopls/internal/lsp/testdata/address/address.go b/gopls/internal/lsp/testdata/address/address.go
90822--- a/gopls/internal/lsp/testdata/address/address.go	2000-01-01 00:00:00.000000000 -0000
90823+++ b/gopls/internal/lsp/testdata/address/address.go	1970-01-01 00:00:00.000000000 +0000
90824@@ -1,78 +0,0 @@
90825-package address
90826-
90827-func wantsPtr(*int)            {}
90828-func wantsVariadicPtr(...*int) {}
90829-
90830-func wantsVariadic(...int) {}
90831-
90832-type foo struct{ c int } //@item(addrFieldC, "c", "int", "field")
90833-
90834-func _() {
90835-	var (
90836-		a string //@item(addrA, "a", "string", "var")
90837-		b int    //@item(addrB, "b", "int", "var")
90838-	)
90839-
90840-	wantsPtr()   //@rank(")", addrB, addrA),snippet(")", addrB, "&b", "&b")
90841-	wantsPtr(&b) //@snippet(")", addrB, "b", "b")
90842-
90843-	wantsVariadicPtr() //@rank(")", addrB, addrA),snippet(")", addrB, "&b", "&b")
90844-
90845-	var s foo
90846-	s.c          //@item(addrDeepC, "s.c", "int", "field")
90847-	wantsPtr()   //@snippet(")", addrDeepC, "&s.c", "&s.c")
90848-	wantsPtr(s)  //@snippet(")", addrDeepC, "&s.c", "&s.c")
90849-	wantsPtr(&s) //@snippet(")", addrDeepC, "s.c", "s.c")
90850-
90851-	// don't add "&" in item (it gets added as an additional edit)
90852-	wantsPtr(&s.c) //@snippet(")", addrFieldC, "c", "c")
90853-
90854-	// check dereferencing as well
90855-	var c *int    //@item(addrCPtr, "c", "*int", "var")
90856-	var _ int = _ //@rank("_ //", addrCPtr, addrA),snippet("_ //", addrCPtr, "*c", "*c")
90857-
90858-	wantsVariadic() //@rank(")", addrCPtr, addrA),snippet(")", addrCPtr, "*c", "*c")
90859-
90860-	var d **int   //@item(addrDPtr, "d", "**int", "var")
90861-	var _ int = _ //@rank("_ //", addrDPtr, addrA),snippet("_ //", addrDPtr, "**d", "**d")
90862-
90863-	type namedPtr *int
90864-	var np namedPtr //@item(addrNamedPtr, "np", "namedPtr", "var")
90865-
90866-	var _ int = _ //@rank("_ //", addrNamedPtr, addrA)
90867-
90868-	// don't get tripped up by recursive pointer type
90869-	type dontMessUp *dontMessUp
90870-	var dmu *dontMessUp //@item(addrDMU, "dmu", "*dontMessUp", "var")
90871-
90872-	var _ int = dmu //@complete(" //", addrDMU)
90873-}
90874-
90875-func (f foo) ptr() *foo { return &f }
90876-
90877-func _() {
90878-	getFoo := func() foo { return foo{} }
90879-
90880-	// not addressable
90881-	getFoo().c //@item(addrGetFooC, "getFoo().c", "int", "field")
90882-
90883-	// addressable
90884-	getFoo().ptr().c //@item(addrGetFooPtrC, "getFoo().ptr().c", "int", "field")
90885-
90886-	wantsPtr()   //@rank(addrGetFooPtrC, addrGetFooC),snippet(")", addrGetFooPtrC, "&getFoo().ptr().c", "&getFoo().ptr().c")
90887-	wantsPtr(&g) //@rank(addrGetFooPtrC, addrGetFooC),snippet(")", addrGetFooPtrC, "getFoo().ptr().c", "getFoo().ptr().c")
90888-}
90889-
90890-type nested struct {
90891-	f foo
90892-}
90893-
90894-func _() {
90895-	getNested := func() nested { return nested{} }
90896-
90897-	getNested().f.c       //@item(addrNestedC, "getNested().f.c", "int", "field")
90898-	getNested().f.ptr().c //@item(addrNestedPtrC, "getNested().f.ptr().c", "int", "field")
90899-
90900-	// addrNestedC is not addressable, so rank lower
90901-	wantsPtr(getNestedfc) //@fuzzy(")", addrNestedPtrC, addrNestedC)
90902-}
90903diff -urN a/gopls/internal/lsp/testdata/analyzer/bad_test.go b/gopls/internal/lsp/testdata/analyzer/bad_test.go
90904--- a/gopls/internal/lsp/testdata/analyzer/bad_test.go	2000-01-01 00:00:00.000000000 -0000
90905+++ b/gopls/internal/lsp/testdata/analyzer/bad_test.go	1970-01-01 00:00:00.000000000 +0000
90906@@ -1,24 +0,0 @@
90907-package analyzer
90908-
90909-import (
90910-	"fmt"
90911-	"sync"
90912-	"testing"
90913-	"time"
90914-)
90915-
90916-func Testbad(t *testing.T) { //@diag("", "tests", "Testbad has malformed name: first letter after 'Test' must not be lowercase", "warning")
90917-	var x sync.Mutex
90918-	_ = x //@diag("x", "copylocks", "assignment copies lock value to _: sync.Mutex", "warning")
90919-
90920-	printfWrapper("%s") //@diag(re`printfWrapper\(.*\)`, "printf", "golang.org/lsptests/analyzer.printfWrapper format %s reads arg #1, but call has 0 args", "warning")
90921-}
90922-
90923-func printfWrapper(format string, args ...interface{}) {
90924-	fmt.Printf(format, args...)
90925-}
90926-
90927-func _() {
90928-	now := time.Now()
90929-	fmt.Println(now.Format("2006-02-01")) //@diag("2006-02-01", "timeformat", "2006-02-01 should be 2006-01-02", "warning")
90930-}
90931diff -urN a/gopls/internal/lsp/testdata/anon/anon.go.in b/gopls/internal/lsp/testdata/anon/anon.go.in
90932--- a/gopls/internal/lsp/testdata/anon/anon.go.in	2000-01-01 00:00:00.000000000 -0000
90933+++ b/gopls/internal/lsp/testdata/anon/anon.go.in	1970-01-01 00:00:00.000000000 +0000
90934@@ -1,23 +0,0 @@
90935-package anon
90936-
90937-func _() {
90938-	for _, _ := range []struct {
90939-		i, j int //@item(anonI, "i", "int", "field"),item(anonJ, "j", "int", "field")
90940-	}{
90941-		{
90942-			i: 1,
90943-			//@complete("", anonJ)
90944-		},
90945-		{
90946-			//@complete("", anonI, anonJ)
90947-		},
90948-	} {
90949-		continue
90950-	}
90951-
90952-	s := struct{ f int }{  } //@item(anonF, "f", "int", "field"),item(structS, "s", "struct{...}", "var"),complete("  }", anonF)
90953-
90954-	_ = map[struct{ x int }]int{ //@item(anonX, "x", "int", "field")
90955-		struct{ x int }{  }: 1, //@complete("  }", anonX, structS)
90956-	}
90957-}
90958diff -urN a/gopls/internal/lsp/testdata/append/append2.go.in b/gopls/internal/lsp/testdata/append/append2.go.in
90959--- a/gopls/internal/lsp/testdata/append/append2.go.in	2000-01-01 00:00:00.000000000 -0000
90960+++ b/gopls/internal/lsp/testdata/append/append2.go.in	1970-01-01 00:00:00.000000000 +0000
90961@@ -1,5 +0,0 @@
90962-package append
90963-
90964-func _() {
90965-	_ = append(a, struct) //@complete(")")
90966-}
90967\ No newline at end of file
90968diff -urN a/gopls/internal/lsp/testdata/append/append.go b/gopls/internal/lsp/testdata/append/append.go
90969--- a/gopls/internal/lsp/testdata/append/append.go	2000-01-01 00:00:00.000000000 -0000
90970+++ b/gopls/internal/lsp/testdata/append/append.go	1970-01-01 00:00:00.000000000 +0000
90971@@ -1,38 +0,0 @@
90972-package append
90973-
90974-func foo([]string)  {}
90975-func bar(...string) {}
90976-
90977-func _() {
90978-	var (
90979-		aInt     []int    //@item(appendInt, "aInt", "[]int", "var")
90980-		aStrings []string //@item(appendStrings, "aStrings", "[]string", "var")
90981-		aString  string   //@item(appendString, "aString", "string", "var")
90982-	)
90983-
90984-	append(aStrings, a)                     //@rank(")", appendString, appendInt)
90985-	var _ interface{} = append(aStrings, a) //@rank(")", appendString, appendInt)
90986-	var _ []string = append(oops, a)        //@rank(")", appendString, appendInt)
90987-
90988-	foo(append())                  //@rank("))", appendStrings, appendInt),rank("))", appendStrings, appendString)
90989-	foo(append([]string{}, a))     //@rank("))", appendStrings, appendInt),rank("))", appendString, appendInt),snippet("))", appendStrings, "aStrings...", "aStrings...")
90990-	foo(append([]string{}, "", a)) //@rank("))", appendString, appendInt),rank("))", appendString, appendStrings)
90991-
90992-	// Don't add "..." to append() argument.
90993-	bar(append()) //@snippet("))", appendStrings, "aStrings", "aStrings")
90994-
90995-	type baz struct{}
90996-	baz{}                       //@item(appendBazLiteral, "baz{}", "", "var")
90997-	var bazzes []baz            //@item(appendBazzes, "bazzes", "[]baz", "var")
90998-	var bazzy baz               //@item(appendBazzy, "bazzy", "baz", "var")
90999-	bazzes = append(bazzes, ba) //@rank(")", appendBazzy, appendBazLiteral, appendBazzes)
91000-
91001-	var b struct{ b []baz }
91002-	b.b                  //@item(appendNestedBaz, "b.b", "[]baz", "field")
91003-	b.b = append(b.b, b) //@rank(")", appendBazzy, appendBazLiteral, appendNestedBaz)
91004-
91005-	var aStringsPtr *[]string  //@item(appendStringsPtr, "aStringsPtr", "*[]string", "var")
91006-	foo(append([]string{}, a)) //@snippet("))", appendStringsPtr, "*aStringsPtr...", "*aStringsPtr...")
91007-
91008-	foo(append([]string{}, *a)) //@snippet("))", appendStringsPtr, "aStringsPtr...", "aStringsPtr...")
91009-}
91010diff -urN a/gopls/internal/lsp/testdata/arraytype/array_type.go.in b/gopls/internal/lsp/testdata/arraytype/array_type.go.in
91011--- a/gopls/internal/lsp/testdata/arraytype/array_type.go.in	2000-01-01 00:00:00.000000000 -0000
91012+++ b/gopls/internal/lsp/testdata/arraytype/array_type.go.in	1970-01-01 00:00:00.000000000 +0000
91013@@ -1,50 +0,0 @@
91014-package arraytype
91015-
91016-import (
91017-	"golang.org/lsptests/foo"
91018-)
91019-
91020-func _() {
91021-	var (
91022-		val string //@item(atVal, "val", "string", "var")
91023-	)
91024-
91025-	// disabled - see issue #54822
91026-	[] // complete(" //", PackageFoo)
91027-
91028-	[]val //@complete(" //")
91029-
91030-	[]foo.StructFoo //@complete(" //", StructFoo)
91031-
91032-	[]foo.StructFoo(nil) //@complete("(", StructFoo)
91033-
91034-	[]*foo.StructFoo //@complete(" //", StructFoo)
91035-
91036-	[...]foo.StructFoo //@complete(" //", StructFoo)
91037-
91038-	[2][][4]foo.StructFoo //@complete(" //", StructFoo)
91039-
91040-	[]struct { f []foo.StructFoo } //@complete(" }", StructFoo)
91041-}
91042-
91043-func _() {
91044-	type myInt int //@item(atMyInt, "myInt", "int", "type")
91045-
91046-	var mark []myInt //@item(atMark, "mark", "[]myInt", "var")
91047-
91048-	var s []myInt //@item(atS, "s", "[]myInt", "var")
91049-	s = []m //@complete(" //", atMyInt)
91050-	// disabled - see issue #54822
91051-	s = [] // complete(" //", atMyInt, PackageFoo)
91052-
91053-	var a [1]myInt
91054-	a = [1]m //@complete(" //", atMyInt)
91055-
91056-	var ds [][]myInt
91057-	ds = [][]m //@complete(" //", atMyInt)
91058-}
91059-
91060-func _() {
91061-	var b [0]byte //@item(atByte, "b", "[0]byte", "var")
91062-	var _ []byte = b //@snippet(" //", atByte, "b[:]", "b[:]")
91063-}
91064diff -urN a/gopls/internal/lsp/testdata/assign/assign.go.in b/gopls/internal/lsp/testdata/assign/assign.go.in
91065--- a/gopls/internal/lsp/testdata/assign/assign.go.in	2000-01-01 00:00:00.000000000 -0000
91066+++ b/gopls/internal/lsp/testdata/assign/assign.go.in	1970-01-01 00:00:00.000000000 +0000
91067@@ -1,26 +0,0 @@
91068-package assign
91069-
91070-import "golang.org/lsptests/assign/internal/secret"
91071-
91072-func _() {
91073-	secret.Hello()
91074-	var (
91075-		myInt int //@item(assignInt, "myInt", "int", "var")
91076-		myStr string //@item(assignStr, "myStr", "string", "var")
91077-	)
91078-
91079-	var _ string = my //@rank(" //", assignStr, assignInt)
91080-	var _ string = //@rank(" //", assignStr, assignInt)
91081-}
91082-
91083-func _() {
91084-	var a string = a //@complete(" //")
91085-}
91086-
91087-func _() {
91088-	fooBar := fooBa //@complete(" //"),item(assignFooBar, "fooBar", "", "var")
91089-	abc, fooBar := 123, fooBa //@complete(" //", assignFooBar)
91090-	{
91091-		fooBar := fooBa //@complete(" //", assignFooBar)
91092-	}
91093-}
91094diff -urN a/gopls/internal/lsp/testdata/assign/internal/secret/secret.go b/gopls/internal/lsp/testdata/assign/internal/secret/secret.go
91095--- a/gopls/internal/lsp/testdata/assign/internal/secret/secret.go	2000-01-01 00:00:00.000000000 -0000
91096+++ b/gopls/internal/lsp/testdata/assign/internal/secret/secret.go	1970-01-01 00:00:00.000000000 +0000
91097@@ -1,3 +0,0 @@
91098-package secret
91099-
91100-func Hello() {}
91101\ No newline at end of file
91102diff -urN a/gopls/internal/lsp/testdata/bad/bad0.go b/gopls/internal/lsp/testdata/bad/bad0.go
91103--- a/gopls/internal/lsp/testdata/bad/bad0.go	2000-01-01 00:00:00.000000000 -0000
91104+++ b/gopls/internal/lsp/testdata/bad/bad0.go	1970-01-01 00:00:00.000000000 +0000
91105@@ -1,24 +0,0 @@
91106-//go:build go1.11
91107-// +build go1.11
91108-
91109-package bad
91110-
91111-import _ "golang.org/lsptests/assign/internal/secret" //@diag("\"golang.org/lsptests/assign/internal/secret\"", "compiler", "could not import golang.org/lsptests/assign/internal/secret \\(invalid use of internal package \"golang.org/lsptests/assign/internal/secret\"\\)", "error")
91112-
91113-func stuff() { //@item(stuff, "stuff", "func()", "func")
91114-	x := "heeeeyyyy"
91115-	random2(x) //@diag("x", "compiler", "cannot use x \\(variable of type string\\) as int value in argument to random2", "error")
91116-	random2(1) //@complete("dom", random, random2, random3)
91117-	y := 3     //@diag("y", "compiler", "y declared (and|but) not used", "error")
91118-}
91119-
91120-type bob struct { //@item(bob, "bob", "struct{...}", "struct")
91121-	x int
91122-}
91123-
91124-func _() {
91125-	var q int
91126-	_ = &bob{
91127-		f: q, //@diag("f: q", "compiler", "unknown field f in struct literal", "error")
91128-	}
91129-}
91130diff -urN a/gopls/internal/lsp/testdata/bad/bad1.go b/gopls/internal/lsp/testdata/bad/bad1.go
91131--- a/gopls/internal/lsp/testdata/bad/bad1.go	2000-01-01 00:00:00.000000000 -0000
91132+++ b/gopls/internal/lsp/testdata/bad/bad1.go	1970-01-01 00:00:00.000000000 +0000
91133@@ -1,34 +0,0 @@
91134-//go:build go1.11
91135-// +build go1.11
91136-
91137-package bad
91138-
91139-// See #36637
91140-type stateFunc func() stateFunc //@item(stateFunc, "stateFunc", "func() stateFunc", "type")
91141-
91142-var a unknown //@item(global_a, "a", "unknown", "var"),diag("unknown", "compiler", "(undeclared name|undefined): unknown", "error")
91143-
91144-func random() int { //@item(random, "random", "func() int", "func")
91145-	//@complete("", global_a, bob, random, random2, random3, stateFunc, stuff)
91146-	return 0
91147-}
91148-
91149-func random2(y int) int { //@item(random2, "random2", "func(y int) int", "func"),item(bad_y_param, "y", "int", "var")
91150-	x := 6       //@item(x, "x", "int", "var"),diag("x", "compiler", "x declared (and|but) not used", "error")
91151-	var q blah   //@item(q, "q", "blah", "var"),diag("q", "compiler", "q declared (and|but) not used", "error"),diag("blah", "compiler", "(undeclared name|undefined): blah", "error")
91152-	var t **blob //@item(t, "t", "**blob", "var"),diag("t", "compiler", "t declared (and|but) not used", "error"),diag("blob", "compiler", "(undeclared name|undefined): blob", "error")
91153-	//@complete("", q, t, x, bad_y_param, global_a, bob, random, random2, random3, stateFunc, stuff)
91154-
91155-	return y
91156-}
91157-
91158-func random3(y ...int) { //@item(random3, "random3", "func(y ...int)", "func"),item(y_variadic_param, "y", "[]int", "var")
91159-	//@complete("", y_variadic_param, global_a, bob, random, random2, random3, stateFunc, stuff)
91160-
91161-	var ch chan (favType1)   //@item(ch, "ch", "chan (favType1)", "var"),diag("ch", "compiler", "ch declared (and|but) not used", "error"),diag("favType1", "compiler", "(undeclared name|undefined): favType1", "error")
91162-	var m map[keyType]int    //@item(m, "m", "map[keyType]int", "var"),diag("m", "compiler", "m declared (and|but) not used", "error"),diag("keyType", "compiler", "(undeclared name|undefined): keyType", "error")
91163-	var arr []favType2       //@item(arr, "arr", "[]favType2", "var"),diag("arr", "compiler", "arr declared (and|but) not used", "error"),diag("favType2", "compiler", "(undeclared name|undefined): favType2", "error")
91164-	var fn1 func() badResult //@item(fn1, "fn1", "func() badResult", "var"),diag("fn1", "compiler", "fn1 declared (and|but) not used", "error"),diag("badResult", "compiler", "(undeclared name|undefined): badResult", "error")
91165-	var fn2 func(badParam)   //@item(fn2, "fn2", "func(badParam)", "var"),diag("fn2", "compiler", "fn2 declared (and|but) not used", "error"),diag("badParam", "compiler", "(undeclared name|undefined): badParam", "error")
91166-	//@complete("", arr, ch, fn1, fn2, m, y_variadic_param, global_a, bob, random, random2, random3, stateFunc, stuff)
91167-}
91168diff -urN a/gopls/internal/lsp/testdata/badstmt/badstmt_2.go.in b/gopls/internal/lsp/testdata/badstmt/badstmt_2.go.in
91169--- a/gopls/internal/lsp/testdata/badstmt/badstmt_2.go.in	2000-01-01 00:00:00.000000000 -0000
91170+++ b/gopls/internal/lsp/testdata/badstmt/badstmt_2.go.in	1970-01-01 00:00:00.000000000 +0000
91171@@ -1,9 +0,0 @@
91172-package badstmt
91173-
91174-import (
91175-	"golang.org/lsptests/foo"
91176-)
91177-
91178-func _() {
91179-	defer func() { foo. } //@rank(" }", Foo)
91180-}
91181diff -urN a/gopls/internal/lsp/testdata/badstmt/badstmt_3.go.in b/gopls/internal/lsp/testdata/badstmt/badstmt_3.go.in
91182--- a/gopls/internal/lsp/testdata/badstmt/badstmt_3.go.in	2000-01-01 00:00:00.000000000 -0000
91183+++ b/gopls/internal/lsp/testdata/badstmt/badstmt_3.go.in	1970-01-01 00:00:00.000000000 +0000
91184@@ -1,9 +0,0 @@
91185-package badstmt
91186-
91187-import (
91188-	"golang.org/lsptests/foo"
91189-)
91190-
91191-func _() {
91192-	go foo. //@rank(" //", Foo, IntFoo),snippet(" //", Foo, "Foo()", "Foo()")
91193-}
91194diff -urN a/gopls/internal/lsp/testdata/badstmt/badstmt_4.go.in b/gopls/internal/lsp/testdata/badstmt/badstmt_4.go.in
91195--- a/gopls/internal/lsp/testdata/badstmt/badstmt_4.go.in	2000-01-01 00:00:00.000000000 -0000
91196+++ b/gopls/internal/lsp/testdata/badstmt/badstmt_4.go.in	1970-01-01 00:00:00.000000000 +0000
91197@@ -1,11 +0,0 @@
91198-package badstmt
91199-
91200-import (
91201-	"golang.org/lsptests/foo"
91202-)
91203-
91204-func _() {
91205-	go func() {
91206-		defer foo. //@rank(" //", Foo, IntFoo)
91207-	}
91208-}
91209diff -urN a/gopls/internal/lsp/testdata/badstmt/badstmt.go.in b/gopls/internal/lsp/testdata/badstmt/badstmt.go.in
91210--- a/gopls/internal/lsp/testdata/badstmt/badstmt.go.in	2000-01-01 00:00:00.000000000 -0000
91211+++ b/gopls/internal/lsp/testdata/badstmt/badstmt.go.in	1970-01-01 00:00:00.000000000 +0000
91212@@ -1,29 +0,0 @@
91213-package badstmt
91214-
91215-import (
91216-	"golang.org/lsptests/foo"
91217-)
91218-
91219-// The nonewvars expectation asserts that the go/analysis framework ran.
91220-// See comments in noparse.
91221-
91222-func _(x int) {
91223-	defer foo.F //@complete(" //", Foo),diag(" //", "syntax", "function must be invoked in defer statement|expression in defer must be function call", "error")
91224-	defer foo.F //@complete(" //", Foo)
91225-	x := 123 //@diag(":=", "nonewvars", "no new variables", "warning")
91226-}
91227-
91228-func _() {
91229-	switch true {
91230-	case true:
91231-		go foo.F //@complete(" //", Foo)
91232-	}
91233-}
91234-
91235-func _() {
91236-	defer func() {
91237-		foo.F //@complete(" //", Foo),snippet(" //", Foo, "Foo()", "Foo()")
91238-
91239-		foo. //@rank(" //", Foo)
91240-	}
91241-}
91242diff -urN a/gopls/internal/lsp/testdata/bar/bar.go.in b/gopls/internal/lsp/testdata/bar/bar.go.in
91243--- a/gopls/internal/lsp/testdata/bar/bar.go.in	2000-01-01 00:00:00.000000000 -0000
91244+++ b/gopls/internal/lsp/testdata/bar/bar.go.in	1970-01-01 00:00:00.000000000 +0000
91245@@ -1,47 +0,0 @@
91246-// +build go1.11
91247-
91248-package bar
91249-
91250-import (
91251-	"golang.org/lsptests/foo" //@item(foo, "foo", "\"golang.org/lsptests/foo\"", "package")
91252-)
91253-
91254-func helper(i foo.IntFoo) {} //@item(helper, "helper", "func(i foo.IntFoo)", "func")
91255-
91256-func _() {
91257-	help //@complete("l", helper)
91258-	_ = foo.StructFoo{} //@complete("S", IntFoo, StructFoo)
91259-}
91260-
91261-// Bar is a function.
91262-func Bar() { //@item(Bar, "Bar", "func()", "func", "Bar is a function.")
91263-	foo.Foo()        //@complete("F", Foo, IntFoo, StructFoo)
91264-	var _ foo.IntFoo //@complete("I", IntFoo, StructFoo)
91265-	foo.()           //@complete("(", Foo, IntFoo, StructFoo)
91266-}
91267-
91268-func _() {
91269-	var Valentine int //@item(Valentine, "Valentine", "int", "var")
91270-
91271-	_ = foo.StructFoo{
91272-		Valu //@complete(" //", Value)
91273-	}
91274-  	_ = foo.StructFoo{
91275-		Va        //@complete("a", Value, Valentine)
91276-	}
91277-	_ = foo.StructFoo{
91278-		Value: 5, //@complete("a", Value)
91279-	}
91280-	_ = foo.StructFoo{
91281-		//@complete("", Value, Valentine, foo, helper, Bar)
91282-	}
91283-	_ = foo.StructFoo{
91284-		Value: Valen //@complete("le", Valentine)
91285-	}
91286-	_ = foo.StructFoo{
91287-		Value:       //@complete(" //", Valentine, foo, helper, Bar)
91288-	}
91289-	_ = foo.StructFoo{
91290-		Value:       //@complete(" ", Valentine, foo, helper, Bar)
91291-	}
91292-}
91293diff -urN a/gopls/internal/lsp/testdata/basiclit/basiclit.go b/gopls/internal/lsp/testdata/basiclit/basiclit.go
91294--- a/gopls/internal/lsp/testdata/basiclit/basiclit.go	2000-01-01 00:00:00.000000000 -0000
91295+++ b/gopls/internal/lsp/testdata/basiclit/basiclit.go	1970-01-01 00:00:00.000000000 +0000
91296@@ -1,13 +0,0 @@
91297-package basiclit
91298-
91299-func _() {
91300-	var a int // something for lexical completions
91301-
91302-	_ = "hello." //@complete(".")
91303-
91304-	_ = 1 //@complete(" //")
91305-
91306-	_ = 1. //@complete(".")
91307-
91308-	_ = 'a' //@complete("' ")
91309-}
91310diff -urN a/gopls/internal/lsp/testdata/baz/baz.go.in b/gopls/internal/lsp/testdata/baz/baz.go.in
91311--- a/gopls/internal/lsp/testdata/baz/baz.go.in	2000-01-01 00:00:00.000000000 -0000
91312+++ b/gopls/internal/lsp/testdata/baz/baz.go.in	1970-01-01 00:00:00.000000000 +0000
91313@@ -1,33 +0,0 @@
91314-// +build go1.11
91315-
91316-package baz
91317-
91318-import (
91319-	"golang.org/lsptests/bar"
91320-
91321-	f "golang.org/lsptests/foo"
91322-)
91323-
91324-var FooStruct f.StructFoo
91325-
91326-func Baz() {
91327-	defer bar.Bar() //@complete("B", Bar)
91328-	// TODO(rstambler): Test completion here.
91329-	defer bar.B
91330-	var x f.IntFoo  //@complete("n", IntFoo),typdef("x", IntFoo)
91331-	bar.Bar()       //@complete("B", Bar)
91332-}
91333-
91334-func _() {
91335-	bob := f.StructFoo{Value: 5}
91336-	if x := bob. //@complete(" //", Value)
91337-	switch true == false {
91338-		case true:
91339-			if x := bob. //@complete(" //", Value)
91340-		case false:
91341-	}
91342-	if x := bob.Va //@complete("a", Value)
91343-	switch true == true {
91344-		default:
91345-	}
91346-}
91347diff -urN a/gopls/internal/lsp/testdata/builtins/builtin_args.go b/gopls/internal/lsp/testdata/builtins/builtin_args.go
91348--- a/gopls/internal/lsp/testdata/builtins/builtin_args.go	2000-01-01 00:00:00.000000000 -0000
91349+++ b/gopls/internal/lsp/testdata/builtins/builtin_args.go	1970-01-01 00:00:00.000000000 +0000
91350@@ -1,62 +0,0 @@
91351-package builtins
91352-
91353-func _() {
91354-	var (
91355-		aSlice    []int          //@item(builtinSlice, "aSlice", "[]int", "var")
91356-		aMap      map[string]int //@item(builtinMap, "aMap", "map[string]int", "var")
91357-		aString   string         //@item(builtinString, "aString", "string", "var")
91358-		aArray    [0]int         //@item(builtinArray, "aArray", "[0]int", "var")
91359-		aArrayPtr *[0]int        //@item(builtinArrayPtr, "aArrayPtr", "*[0]int", "var")
91360-		aChan     chan int       //@item(builtinChan, "aChan", "chan int", "var")
91361-		aPtr      *int           //@item(builtinPtr, "aPtr", "*int", "var")
91362-		aInt      int            //@item(builtinInt, "aInt", "int", "var")
91363-	)
91364-
91365-	type (
91366-		aSliceType []int          //@item(builtinSliceType, "aSliceType", "[]int", "type")
91367-		aChanType  chan int       //@item(builtinChanType, "aChanType", "chan int", "type")
91368-		aMapType   map[string]int //@item(builtinMapType, "aMapType", "map[string]int", "type")
91369-	)
91370-
91371-	close() //@rank(")", builtinChan, builtinSlice)
91372-
91373-	append() //@rank(")", builtinSlice, builtinChan)
91374-
91375-	var _ []byte = append([]byte(nil), ""...) //@rank(") //")
91376-
91377-	copy()           //@rank(")", builtinSlice, builtinChan)
91378-	copy(aSlice, aS) //@rank(")", builtinSlice, builtinString)
91379-	copy(aS, aSlice) //@rank(",", builtinSlice, builtinString)
91380-
91381-	delete()         //@rank(")", builtinMap, builtinChan)
91382-	delete(aMap, aS) //@rank(")", builtinString, builtinSlice)
91383-
91384-	aMapFunc := func() map[int]int { //@item(builtinMapFunc, "aMapFunc", "func() map[int]int", "var")
91385-		return nil
91386-	}
91387-	delete() //@rank(")", builtinMapFunc, builtinSlice)
91388-
91389-	len() //@rank(")", builtinSlice, builtinInt),rank(")", builtinMap, builtinInt),rank(")", builtinString, builtinInt),rank(")", builtinArray, builtinInt),rank(")", builtinArrayPtr, builtinPtr),rank(")", builtinChan, builtinInt)
91390-
91391-	cap() //@rank(")", builtinSlice, builtinMap),rank(")", builtinArray, builtinString),rank(")", builtinArrayPtr, builtinPtr),rank(")", builtinChan, builtinInt)
91392-
91393-	make()              //@rank(")", builtinMapType, int),rank(")", builtinChanType, int),rank(")", builtinSliceType, int),rank(")", builtinMapType, int)
91394-	make(aSliceType, a) //@rank(")", builtinInt, builtinSlice)
91395-
91396-	type myInt int
91397-	var mi myInt        //@item(builtinMyInt, "mi", "myInt", "var")
91398-	make(aSliceType, m) //@snippet(")", builtinMyInt, "mi", "mi")
91399-
91400-	var _ []int = make() //@rank(")", builtinSliceType, builtinMapType)
91401-
91402-	type myStruct struct{}  //@item(builtinStructType, "myStruct", "struct{...}", "struct")
91403-	var _ *myStruct = new() //@rank(")", builtinStructType, int)
91404-
91405-	for k := range a { //@rank(" {", builtinSlice, builtinInt),rank(" {", builtinString, builtinInt),rank(" {", builtinChan, builtinInt),rank(" {", builtinArray, builtinInt),rank(" {", builtinArrayPtr, builtinInt),rank(" {", builtinMap, builtinInt),
91406-	}
91407-
91408-	for k, v := range a { //@rank(" {", builtinSlice, builtinChan)
91409-	}
91410-
91411-	<-a //@rank(" //", builtinChan, builtinInt)
91412-}
91413diff -urN a/gopls/internal/lsp/testdata/builtins/builtin_go117.go b/gopls/internal/lsp/testdata/builtins/builtin_go117.go
91414--- a/gopls/internal/lsp/testdata/builtins/builtin_go117.go	2000-01-01 00:00:00.000000000 -0000
91415+++ b/gopls/internal/lsp/testdata/builtins/builtin_go117.go	1970-01-01 00:00:00.000000000 +0000
91416@@ -1,8 +0,0 @@
91417-//go:build !go1.18
91418-// +build !go1.18
91419-
91420-package builtins
91421-
91422-func _() {
91423-	//@complete("", append, bool, byte, cap, close, complex, complex128, complex64, copy, delete, error, _false, float32, float64, imag, int, int16, int32, int64, int8, len, make, new, panic, print, println, real, recover, rune, string, _true, uint, uint16, uint32, uint64, uint8, uintptr, _nil)
91424-}
91425diff -urN a/gopls/internal/lsp/testdata/builtins/builtin_go118.go b/gopls/internal/lsp/testdata/builtins/builtin_go118.go
91426--- a/gopls/internal/lsp/testdata/builtins/builtin_go118.go	2000-01-01 00:00:00.000000000 -0000
91427+++ b/gopls/internal/lsp/testdata/builtins/builtin_go118.go	1970-01-01 00:00:00.000000000 +0000
91428@@ -1,8 +0,0 @@
91429-//go:build go1.18 && !go1.21
91430-// +build go1.18,!go1.21
91431-
91432-package builtins
91433-
91434-func _() {
91435-	//@complete("", any, append, bool, byte, cap, close, comparable, complex, complex128, complex64, copy, delete, error, _false, float32, float64, imag, int, int16, int32, int64, int8, len, make, new, panic, print, println, real, recover, rune, string, _true, uint, uint16, uint32, uint64, uint8, uintptr, _nil)
91436-}
91437diff -urN a/gopls/internal/lsp/testdata/builtins/builtin_go121.go b/gopls/internal/lsp/testdata/builtins/builtin_go121.go
91438--- a/gopls/internal/lsp/testdata/builtins/builtin_go121.go	2000-01-01 00:00:00.000000000 -0000
91439+++ b/gopls/internal/lsp/testdata/builtins/builtin_go121.go	1970-01-01 00:00:00.000000000 +0000
91440@@ -1,8 +0,0 @@
91441-//go:build go1.21
91442-// +build go1.21
91443-
91444-package builtins
91445-
91446-func _() {
91447-	//@complete("", any, append, bool, byte, cap, clear, close, comparable, complex, complex128, complex64, copy, delete, error, _false, float32, float64, imag, int, int16, int32, int64, int8, len, make, new, panic, print, println, real, recover, rune, string, _true, uint, uint16, uint32, uint64, uint8, uintptr, _nil)
91448-}
91449diff -urN a/gopls/internal/lsp/testdata/builtins/builtins.go b/gopls/internal/lsp/testdata/builtins/builtins.go
91450--- a/gopls/internal/lsp/testdata/builtins/builtins.go	2000-01-01 00:00:00.000000000 -0000
91451+++ b/gopls/internal/lsp/testdata/builtins/builtins.go	1970-01-01 00:00:00.000000000 +0000
91452@@ -1,47 +0,0 @@
91453-package builtins
91454-
91455-// Definitions of builtin completion items.
91456-
91457-/* any */ //@item(any, "any", "", "interface")
91458-/* Create markers for builtin types. Only for use by this test.
91459-/* append(slice []Type, elems ...Type) []Type */ //@item(append, "append", "func(slice []Type, elems ...Type) []Type", "func")
91460-/* bool */ //@item(bool, "bool", "", "type")
91461-/* byte */ //@item(byte, "byte", "", "type")
91462-/* cap(v Type) int */ //@item(cap, "cap", "func(v Type) int", "func")
91463-/* clear[T interface{ ~[]Type | ~map[Type]Type1 }](t T) */ //@item(clear, "clear", "func(t T)", "func")
91464-/* close(c chan<- Type) */ //@item(close, "close", "func(c chan<- Type)", "func")
91465-/* comparable */ //@item(comparable, "comparable", "", "interface")
91466-/* complex(r float64, i float64) */ //@item(complex, "complex", "func(r float64, i float64) complex128", "func")
91467-/* complex128 */ //@item(complex128, "complex128", "", "type")
91468-/* complex64 */ //@item(complex64, "complex64", "", "type")
91469-/* copy(dst []Type, src []Type) int */ //@item(copy, "copy", "func(dst []Type, src []Type) int", "func")
91470-/* delete(m map[Type]Type1, key Type) */ //@item(delete, "delete", "func(m map[Type]Type1, key Type)", "func")
91471-/* error */ //@item(error, "error", "", "interface")
91472-/* false */ //@item(_false, "false", "", "const")
91473-/* float32 */ //@item(float32, "float32", "", "type")
91474-/* float64 */ //@item(float64, "float64", "", "type")
91475-/* imag(c complex128) float64 */ //@item(imag, "imag", "func(c complex128) float64", "func")
91476-/* int */ //@item(int, "int", "", "type")
91477-/* int16 */ //@item(int16, "int16", "", "type")
91478-/* int32 */ //@item(int32, "int32", "", "type")
91479-/* int64 */ //@item(int64, "int64", "", "type")
91480-/* int8 */ //@item(int8, "int8", "", "type")
91481-/* iota */ //@item(iota, "iota", "", "const")
91482-/* len(v Type) int */ //@item(len, "len", "func(v Type) int", "func")
91483-/* make(t Type, size ...int) Type */ //@item(make, "make", "func(t Type, size ...int) Type", "func")
91484-/* new(Type) *Type */ //@item(new, "new", "func(Type) *Type", "func")
91485-/* nil */ //@item(_nil, "nil", "", "var")
91486-/* panic(v interface{}) */ //@item(panic, "panic", "func(v interface{})", "func")
91487-/* print(args ...Type) */ //@item(print, "print", "func(args ...Type)", "func")
91488-/* println(args ...Type) */ //@item(println, "println", "func(args ...Type)", "func")
91489-/* real(c complex128) float64 */ //@item(real, "real", "func(c complex128) float64", "func")
91490-/* recover() interface{} */ //@item(recover, "recover", "func() interface{}", "func")
91491-/* rune */ //@item(rune, "rune", "", "type")
91492-/* string */ //@item(string, "string", "", "type")
91493-/* true */ //@item(_true, "true", "", "const")
91494-/* uint */ //@item(uint, "uint", "", "type")
91495-/* uint16 */ //@item(uint16, "uint16", "", "type")
91496-/* uint32 */ //@item(uint32, "uint32", "", "type")
91497-/* uint64 */ //@item(uint64, "uint64", "", "type")
91498-/* uint8 */ //@item(uint8, "uint8", "", "type")
91499-/* uintptr */ //@item(uintptr, "uintptr", "", "type")
91500diff -urN a/gopls/internal/lsp/testdata/builtins/builtin_types.go b/gopls/internal/lsp/testdata/builtins/builtin_types.go
91501--- a/gopls/internal/lsp/testdata/builtins/builtin_types.go	2000-01-01 00:00:00.000000000 -0000
91502+++ b/gopls/internal/lsp/testdata/builtins/builtin_types.go	1970-01-01 00:00:00.000000000 +0000
91503@@ -1,11 +0,0 @@
91504-package builtins
91505-
91506-func _() {
91507-	var _ []bool //@item(builtinBoolSliceType, "[]bool", "[]bool", "type")
91508-
91509-	var _ []bool = make() //@rank(")", builtinBoolSliceType, int)
91510-
91511-	var _ []bool = make([], 0) //@rank(",", bool, int)
91512-
91513-	var _ [][]bool = make([][], 0) //@rank(",", bool, int)
91514-}
91515diff -urN a/gopls/internal/lsp/testdata/builtins/constants.go b/gopls/internal/lsp/testdata/builtins/constants.go
91516--- a/gopls/internal/lsp/testdata/builtins/constants.go	2000-01-01 00:00:00.000000000 -0000
91517+++ b/gopls/internal/lsp/testdata/builtins/constants.go	1970-01-01 00:00:00.000000000 +0000
91518@@ -1,19 +0,0 @@
91519-package builtins
91520-
91521-func _() {
91522-	const (
91523-		foo = iota //@complete(" //", iota)
91524-	)
91525-
91526-	iota //@complete(" //")
91527-
91528-	var iota int //@item(iotaVar, "iota", "int", "var")
91529-
91530-	iota //@complete(" //", iotaVar)
91531-}
91532-
91533-func _() {
91534-	var twoRedUpEnd bool //@item(TRUEVar, "twoRedUpEnd", "bool", "var")
91535-
91536-	var _ bool = true //@rank(" //", _true, TRUEVar)
91537-}
91538diff -urN a/gopls/internal/lsp/testdata/callhierarchy/callhierarchy.go b/gopls/internal/lsp/testdata/callhierarchy/callhierarchy.go
91539--- a/gopls/internal/lsp/testdata/callhierarchy/callhierarchy.go	2000-01-01 00:00:00.000000000 -0000
91540+++ b/gopls/internal/lsp/testdata/callhierarchy/callhierarchy.go	1970-01-01 00:00:00.000000000 +0000
91541@@ -1,70 +0,0 @@
91542-// Copyright 2020 The Go Authors. All rights reserved.
91543-// Use of this source code is governed by a BSD-style
91544-// license that can be found in the LICENSE file.
91545-
91546-package callhierarchy
91547-
91548-import "golang.org/lsptests/callhierarchy/outgoing"
91549-
91550-func a() { //@mark(hierarchyA, "a")
91551-	D()
91552-}
91553-
91554-func b() { //@mark(hierarchyB, "b")
91555-	D()
91556-}
91557-
91558-// C is an exported function
91559-func C() { //@mark(hierarchyC, "C")
91560-	D()
91561-	D()
91562-}
91563-
91564-// To test hierarchy across function literals
91565-var x = func() { //@mark(hierarchyLiteral, "func"),mark(hierarchyLiteralOut, "x")
91566-	D()
91567-}
91568-
91569-// D is exported to test incoming/outgoing calls across packages
91570-func D() { //@mark(hierarchyD, "D"),incomingcalls(hierarchyD, hierarchyA, hierarchyB, hierarchyC, hierarchyLiteral, incomingA),outgoingcalls(hierarchyD, hierarchyE, hierarchyF, hierarchyG, hierarchyLiteralOut, outgoingB, hierarchyFoo, hierarchyH, hierarchyI, hierarchyJ, hierarchyK)
91571-	e()
91572-	x()
91573-	F()
91574-	outgoing.B()
91575-	foo := func() {} //@mark(hierarchyFoo, "foo"),incomingcalls(hierarchyFoo, hierarchyD),outgoingcalls(hierarchyFoo)
91576-	foo()
91577-
91578-	func() {
91579-		g()
91580-	}()
91581-
91582-	var i Interface = impl{}
91583-	i.H()
91584-	i.I()
91585-
91586-	s := Struct{}
91587-	s.J()
91588-	s.K()
91589-}
91590-
91591-func e() {} //@mark(hierarchyE, "e")
91592-
91593-// F is an exported function
91594-func F() {} //@mark(hierarchyF, "F")
91595-
91596-func g() {} //@mark(hierarchyG, "g")
91597-
91598-type Interface interface {
91599-	H() //@mark(hierarchyH, "H")
91600-	I() //@mark(hierarchyI, "I")
91601-}
91602-
91603-type impl struct{}
91604-
91605-func (i impl) H() {}
91606-func (i impl) I() {}
91607-
91608-type Struct struct {
91609-	J func() //@mark(hierarchyJ, "J")
91610-	K func() //@mark(hierarchyK, "K")
91611-}
91612diff -urN a/gopls/internal/lsp/testdata/callhierarchy/incoming/incoming.go b/gopls/internal/lsp/testdata/callhierarchy/incoming/incoming.go
91613--- a/gopls/internal/lsp/testdata/callhierarchy/incoming/incoming.go	2000-01-01 00:00:00.000000000 -0000
91614+++ b/gopls/internal/lsp/testdata/callhierarchy/incoming/incoming.go	1970-01-01 00:00:00.000000000 +0000
91615@@ -1,12 +0,0 @@
91616-// Copyright 2020 The Go Authors. All rights reserved.
91617-// Use of this source code is governed by a BSD-style
91618-// license that can be found in the LICENSE file.
91619-
91620-package incoming
91621-
91622-import "golang.org/lsptests/callhierarchy"
91623-
91624-// A is exported to test incoming calls across packages
91625-func A() { //@mark(incomingA, "A")
91626-	callhierarchy.D()
91627-}
91628diff -urN a/gopls/internal/lsp/testdata/callhierarchy/outgoing/outgoing.go b/gopls/internal/lsp/testdata/callhierarchy/outgoing/outgoing.go
91629--- a/gopls/internal/lsp/testdata/callhierarchy/outgoing/outgoing.go	2000-01-01 00:00:00.000000000 -0000
91630+++ b/gopls/internal/lsp/testdata/callhierarchy/outgoing/outgoing.go	1970-01-01 00:00:00.000000000 +0000
91631@@ -1,9 +0,0 @@
91632-// Copyright 2020 The Go Authors. All rights reserved.
91633-// Use of this source code is governed by a BSD-style
91634-// license that can be found in the LICENSE file.
91635-
91636-package outgoing
91637-
91638-// B is exported to test outgoing calls across packages
91639-func B() { //@mark(outgoingB, "B")
91640-}
91641diff -urN a/gopls/internal/lsp/testdata/casesensitive/casesensitive.go b/gopls/internal/lsp/testdata/casesensitive/casesensitive.go
91642--- a/gopls/internal/lsp/testdata/casesensitive/casesensitive.go	2000-01-01 00:00:00.000000000 -0000
91643+++ b/gopls/internal/lsp/testdata/casesensitive/casesensitive.go	1970-01-01 00:00:00.000000000 +0000
91644@@ -1,16 +0,0 @@
91645-// Copyright 2019 The Go Authors. All rights reserved.
91646-// Use of this source code is governed by a BSD-style
91647-// license that can be found in the LICENSE file.
91648-
91649-package casesensitive
91650-
91651-func _() {
91652-	var lower int //@item(lower, "lower", "int", "var")
91653-	var Upper int //@item(upper, "Upper", "int", "var")
91654-
91655-	l //@casesensitive(" //", lower)
91656-	U //@casesensitive(" //", upper)
91657-
91658-	L //@casesensitive(" //")
91659-	u //@casesensitive(" //")
91660-}
91661diff -urN a/gopls/internal/lsp/testdata/cast/cast.go.in b/gopls/internal/lsp/testdata/cast/cast.go.in
91662--- a/gopls/internal/lsp/testdata/cast/cast.go.in	2000-01-01 00:00:00.000000000 -0000
91663+++ b/gopls/internal/lsp/testdata/cast/cast.go.in	1970-01-01 00:00:00.000000000 +0000
91664@@ -1,11 +0,0 @@
91665-package cast
91666-
91667-func _() {
91668-	foo := struct{x int}{x: 1} //@item(x_field, "x", "int", "field")
91669-	_ = float64(foo.x) //@complete("x", x_field)
91670-}
91671-
91672-func _() {
91673-	foo := struct{x int}{x: 1}
91674-	_ = float64(foo. //@complete(" /", x_field)
91675-}
91676\ No newline at end of file
91677diff -urN a/gopls/internal/lsp/testdata/cgo/declarecgo.go b/gopls/internal/lsp/testdata/cgo/declarecgo.go
91678--- a/gopls/internal/lsp/testdata/cgo/declarecgo.go	2000-01-01 00:00:00.000000000 -0000
91679+++ b/gopls/internal/lsp/testdata/cgo/declarecgo.go	1970-01-01 00:00:00.000000000 +0000
91680@@ -1,27 +0,0 @@
91681-package cgo
91682-
91683-/*
91684-#include <stdio.h>
91685-#include <stdlib.h>
91686-
91687-void myprint(char* s) {
91688-	printf("%s\n", s);
91689-}
91690-*/
91691-import "C"
91692-
91693-import (
91694-	"fmt"
91695-	"unsafe"
91696-)
91697-
91698-func Example() { //@mark(funccgoexample, "Example"),item(funccgoexample, "Example", "func()", "func")
91699-	fmt.Println()
91700-	cs := C.CString("Hello from stdio\n")
91701-	C.myprint(cs)
91702-	C.free(unsafe.Pointer(cs))
91703-}
91704-
91705-func _() {
91706-	Example() //@godef("ample", funccgoexample),complete("ample", funccgoexample)
91707-}
91708diff -urN a/gopls/internal/lsp/testdata/cgo/declarecgo.go.golden b/gopls/internal/lsp/testdata/cgo/declarecgo.go.golden
91709--- a/gopls/internal/lsp/testdata/cgo/declarecgo.go.golden	2000-01-01 00:00:00.000000000 -0000
91710+++ b/gopls/internal/lsp/testdata/cgo/declarecgo.go.golden	1970-01-01 00:00:00.000000000 +0000
91711@@ -1,30 +0,0 @@
91712--- funccgoexample-definition --
91713-cgo/declarecgo.go:18:6-13: defined here as ```go
91714-func Example()
91715-```
91716-
91717-[`cgo.Example` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/cgo#Example)
91718--- funccgoexample-definition-json --
91719-{
91720-	"span": {
91721-		"uri": "file://cgo/declarecgo.go",
91722-		"start": {
91723-			"line": 18,
91724-			"column": 6,
91725-			"offset": 151
91726-		},
91727-		"end": {
91728-			"line": 18,
91729-			"column": 13,
91730-			"offset": 158
91731-		}
91732-	},
91733-	"description": "```go\nfunc Example()\n```\n\n[`cgo.Example` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/cgo#Example)"
91734-}
91735-
91736--- funccgoexample-hoverdef --
91737-```go
91738-func Example()
91739-```
91740-
91741-[`cgo.Example` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/cgo#Example)
91742diff -urN a/gopls/internal/lsp/testdata/cgo/declarecgo_nocgo.go b/gopls/internal/lsp/testdata/cgo/declarecgo_nocgo.go
91743--- a/gopls/internal/lsp/testdata/cgo/declarecgo_nocgo.go	2000-01-01 00:00:00.000000000 -0000
91744+++ b/gopls/internal/lsp/testdata/cgo/declarecgo_nocgo.go	1970-01-01 00:00:00.000000000 +0000
91745@@ -1,6 +0,0 @@
91746-//+build !cgo
91747-
91748-package cgo
91749-
91750-// Set a dummy marker to keep the test framework happy. The tests should be skipped.
91751-var _ = "Example" //@mark(funccgoexample, "Example"),godef("ample", funccgoexample),complete("ample", funccgoexample)
91752diff -urN a/gopls/internal/lsp/testdata/cgoimport/usecgo.go.golden b/gopls/internal/lsp/testdata/cgoimport/usecgo.go.golden
91753--- a/gopls/internal/lsp/testdata/cgoimport/usecgo.go.golden	2000-01-01 00:00:00.000000000 -0000
91754+++ b/gopls/internal/lsp/testdata/cgoimport/usecgo.go.golden	1970-01-01 00:00:00.000000000 +0000
91755@@ -1,30 +0,0 @@
91756--- funccgoexample-definition --
91757-cgo/declarecgo.go:18:6-13: defined here as ```go
91758-func cgo.Example()
91759-```
91760-
91761-[`cgo.Example` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/cgo#Example)
91762--- funccgoexample-definition-json --
91763-{
91764-	"span": {
91765-		"uri": "file://cgo/declarecgo.go",
91766-		"start": {
91767-			"line": 18,
91768-			"column": 6,
91769-			"offset": 151
91770-		},
91771-		"end": {
91772-			"line": 18,
91773-			"column": 13,
91774-			"offset": 158
91775-		}
91776-	},
91777-	"description": "```go\nfunc cgo.Example()\n```\n\n[`cgo.Example` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/cgo#Example)"
91778-}
91779-
91780--- funccgoexample-hoverdef --
91781-```go
91782-func cgo.Example()
91783-```
91784-
91785-[`cgo.Example` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/cgo#Example)
91786diff -urN a/gopls/internal/lsp/testdata/cgoimport/usecgo.go.in b/gopls/internal/lsp/testdata/cgoimport/usecgo.go.in
91787--- a/gopls/internal/lsp/testdata/cgoimport/usecgo.go.in	2000-01-01 00:00:00.000000000 -0000
91788+++ b/gopls/internal/lsp/testdata/cgoimport/usecgo.go.in	1970-01-01 00:00:00.000000000 +0000
91789@@ -1,9 +0,0 @@
91790-package cgoimport
91791-
91792-import (
91793-	"golang.org/lsptests/cgo"
91794-)
91795-
91796-func _() {
91797-	cgo.Example() //@godef("ample", funccgoexample),complete("ample", funccgoexample)
91798-}
91799diff -urN a/gopls/internal/lsp/testdata/channel/channel.go b/gopls/internal/lsp/testdata/channel/channel.go
91800--- a/gopls/internal/lsp/testdata/channel/channel.go	2000-01-01 00:00:00.000000000 -0000
91801+++ b/gopls/internal/lsp/testdata/channel/channel.go	1970-01-01 00:00:00.000000000 +0000
91802@@ -1,25 +0,0 @@
91803-package channel
91804-
91805-func _() {
91806-	var (
91807-		aa = "123" //@item(channelAA, "aa", "string", "var")
91808-		ab = 123   //@item(channelAB, "ab", "int", "var")
91809-	)
91810-
91811-	{
91812-		type myChan chan int
91813-		var mc myChan
91814-		mc <- a //@complete(" //", channelAB, channelAA)
91815-	}
91816-
91817-	{
91818-		var ac chan int //@item(channelAC, "ac", "chan int", "var")
91819-		a <- a //@complete(" <-", channelAC, channelAA, channelAB)
91820-	}
91821-
91822-	{
91823-		var foo chan int //@item(channelFoo, "foo", "chan int", "var")
91824-		wantsInt := func(int) {} //@item(channelWantsInt, "wantsInt", "func(int)", "var")
91825-		wantsInt(<-) //@rank(")", channelFoo, channelAB)
91826-	}
91827-}
91828diff -urN a/gopls/internal/lsp/testdata/codelens/codelens_test.go b/gopls/internal/lsp/testdata/codelens/codelens_test.go
91829--- a/gopls/internal/lsp/testdata/codelens/codelens_test.go	2000-01-01 00:00:00.000000000 -0000
91830+++ b/gopls/internal/lsp/testdata/codelens/codelens_test.go	1970-01-01 00:00:00.000000000 +0000
91831@@ -1,16 +0,0 @@
91832-package codelens //@codelens("package codelens", "run file benchmarks", "test")
91833-
91834-import "testing"
91835-
91836-func TestMain(m *testing.M) {} // no code lens for TestMain
91837-
91838-func TestFuncWithCodeLens(t *testing.T) { //@codelens("func", "run test", "test")
91839-}
91840-
91841-func thisShouldNotHaveACodeLens(t *testing.T) {
91842-}
91843-
91844-func BenchmarkFuncWithCodeLens(b *testing.B) { //@codelens("func", "run benchmark", "test")
91845-}
91846-
91847-func helper() {} // expect no code lens
91848diff -urN a/gopls/internal/lsp/testdata/comment_completion/comment_completion.go.in b/gopls/internal/lsp/testdata/comment_completion/comment_completion.go.in
91849--- a/gopls/internal/lsp/testdata/comment_completion/comment_completion.go.in	2000-01-01 00:00:00.000000000 -0000
91850+++ b/gopls/internal/lsp/testdata/comment_completion/comment_completion.go.in	1970-01-01 00:00:00.000000000 +0000
91851@@ -1,70 +0,0 @@
91852-package comment_completion
91853-
91854-var p bool
91855-
91856-//@complete(re"$")
91857-
91858-func _() {
91859-	var a int
91860-
91861-	switch a {
91862-	case 1:
91863-		//@complete(re"$")
91864-		_ = a
91865-	}
91866-
91867-	var b chan int
91868-	select {
91869-	case <-b:
91870-		//@complete(re"$")
91871-		_ = b
91872-	}
91873-
91874-	var (
91875-		//@complete(re"$")
91876-		_ = a
91877-	)
91878-}
91879-
91880-// //@complete(" ", variableC)
91881-var C string //@item(variableC, "C", "string", "var") //@complete(" ", variableC)
91882-
91883-// //@complete(" ", constant)
91884-const Constant = "example" //@item(constant, "Constant", "string", "const") //@complete(" ", constant)
91885-
91886-// //@complete(" ", structType, fieldB, fieldA)
91887-type StructType struct { //@item(structType, "StructType", "struct{...}", "struct") //@complete(" ", structType, fieldA, fieldB)
91888-	// //@complete(" ", fieldA, structType, fieldB)
91889-	A string //@item(fieldA, "A", "string", "field") //@complete(" ", fieldA, structType, fieldB)
91890-	b int    //@item(fieldB, "b", "int", "field") //@complete(" ", fieldB, structType, fieldA)
91891-}
91892-
91893-// //@complete(" ", method, structRecv, paramX, resultY, fieldB, fieldA)
91894-func (structType *StructType) Method(X int) (Y int) { //@item(structRecv, "structType", "*StructType", "var"),item(method, "Method", "func(X int) (Y int)", "method"),item(paramX, "X", "int", "var"),item(resultY, "Y", "int", "var")
91895-	// //@complete(" ", method, structRecv, paramX, resultY, fieldB, fieldA)
91896-	return
91897-}
91898-
91899-// //@complete(" ", newType)
91900-type NewType string //@item(newType, "NewType", "string", "type") //@complete(" ", newType)
91901-
91902-// //@complete(" ", testInterface, testA, testB)
91903-type TestInterface interface { //@item(testInterface, "TestInterface", "interface{...}", "interface")
91904-	// //@complete(" ", testA, testInterface, testB)
91905-	TestA(L string) (M int) //@item(testA, "TestA", "func(L string) (M int)", "method"),item(paramL, "L", "var", "string"),item(resM, "M", "var", "int") //@complete(" ", testA, testInterface, testB)
91906-	TestB(N int) bool       //@item(testB, "TestB", "func(N int) bool", "method"),item(paramN, "N", "var", "int") //@complete(" ", testB, testInterface, testA)
91907-}
91908-
91909-// //@complete(" ", function)
91910-func Function() int { //@item(function, "Function", "func() int", "func") //@complete(" ", function)
91911-	// //@complete(" ", function)
91912-	return 0
91913-}
91914-
91915-// This tests multiline block comments and completion with prefix
91916-// Lorem Ipsum Multili//@complete("Multi", multiline)
91917-// Lorem ipsum dolor sit ametom
91918-func Multiline() int { //@item(multiline, "Multiline", "func() int", "func")
91919-	// //@complete(" ", multiline)
91920-	return 0
91921-}
91922diff -urN a/gopls/internal/lsp/testdata/complit/complit.go.in b/gopls/internal/lsp/testdata/complit/complit.go.in
91923--- a/gopls/internal/lsp/testdata/complit/complit.go.in	2000-01-01 00:00:00.000000000 -0000
91924+++ b/gopls/internal/lsp/testdata/complit/complit.go.in	1970-01-01 00:00:00.000000000 +0000
91925@@ -1,90 +0,0 @@
91926-package complit
91927-
91928-// general completions
91929-
91930-type position struct { //@item(structPosition, "position", "struct{...}", "struct")
91931-	X, Y int //@item(fieldX, "X", "int", "field"),item(fieldY, "Y", "int", "field")
91932-}
91933-
91934-func _() {
91935-	_ = position{
91936-		//@complete("", fieldX, fieldY, structPosition)
91937-	}
91938-	_ = position{
91939-		X: 1,
91940-		//@complete("", fieldY)
91941-	}
91942-	_ = position{
91943-		//@complete("", fieldX)
91944-		Y: 1,
91945-	}
91946-	_ = []*position{
91947-        {
91948-            //@complete("", fieldX, fieldY, structPosition)
91949-        },
91950-	}
91951-}
91952-
91953-func _() {
91954-	var (
91955-		aa string //@item(aaVar, "aa", "string", "var")
91956-		ab int    //@item(abVar, "ab", "int", "var")
91957-	)
91958-
91959-	_ = map[int]int{
91960-		a: a, //@complete(":", abVar, aaVar),complete(",", abVar, aaVar)
91961-	}
91962-
91963-	_ = map[int]int{
91964-		//@complete("", abVar, aaVar, structPosition)
91965-	}
91966-
91967-	_ = []string{a: ""} //@complete(":", abVar, aaVar)
91968-	_ = [1]string{a: ""} //@complete(":", abVar, aaVar)
91969-
91970-	_ = position{X: a}   //@complete("}", abVar, aaVar)
91971-	_ = position{a}      //@complete("}", abVar, aaVar)
91972-	_ = position{a, }      //@complete("}", abVar, aaVar, structPosition)
91973-
91974-	_ = []int{a}  //@complete("}", abVar, aaVar)
91975-	_ = [1]int{a} //@complete("}", abVar, aaVar)
91976-
91977-	type myStruct struct {
91978-		AA int    //@item(fieldAA, "AA", "int", "field")
91979-		AB string //@item(fieldAB, "AB", "string", "field")
91980-	}
91981-
91982-	_ = myStruct{
91983-		AB: a, //@complete(",", aaVar, abVar)
91984-	}
91985-
91986-	var s myStruct
91987-
91988-	_ = map[int]string{1: "" + s.A}                                //@complete("}", fieldAB, fieldAA)
91989-	_ = map[int]string{1: (func(i int) string { return "" })(s.A)} //@complete(")}", fieldAA, fieldAB)
91990-	_ = map[int]string{1: func() string { s.A }}                   //@complete(" }", fieldAA, fieldAB)
91991-
91992-	_ = position{s.A} //@complete("}", fieldAA, fieldAB)
91993-
91994-	var X int //@item(varX, "X", "int", "var")
91995-	_ = position{X}      //@complete("}", fieldX, varX)
91996-}
91997-
91998-func _() {
91999-	type foo struct{} //@item(complitFoo, "foo", "struct{...}", "struct")
92000-
92001-	var _ *foo = &fo{} //@snippet("{", complitFoo, "foo", "foo")
92002-	var _ *foo = fo{} //@snippet("{", complitFoo, "&foo", "&foo")
92003-
92004-	struct { a, b *foo }{
92005-		a: &fo{}, //@rank("{", complitFoo)
92006-		b: fo{}, //@snippet("{", complitFoo, "&foo", "&foo")
92007-	}
92008-}
92009-
92010-func _() {
92011-	_ := position{
92012-		X: 1, //@complete("X", fieldX),complete(" 1", structPosition)
92013-		Y: ,  //@complete(":", fieldY),complete(" ,", structPosition)
92014-	}
92015-}
92016diff -urN a/gopls/internal/lsp/testdata/constant/constant.go b/gopls/internal/lsp/testdata/constant/constant.go
92017--- a/gopls/internal/lsp/testdata/constant/constant.go	2000-01-01 00:00:00.000000000 -0000
92018+++ b/gopls/internal/lsp/testdata/constant/constant.go	1970-01-01 00:00:00.000000000 +0000
92019@@ -1,14 +0,0 @@
92020-package constant
92021-
92022-const x = 1 //@item(constX, "x", "int", "const")
92023-
92024-const (
92025-	a int = iota << 2 //@item(constA, "a", "int", "const")
92026-	b                 //@item(constB, "b", "int", "const")
92027-	c                 //@item(constC, "c", "int", "const")
92028-)
92029-
92030-func _() {
92031-	const y = "hi" //@item(constY, "y", "string", "const")
92032-	//@complete("", constY, constA, constB, constC, constX)
92033-}
92034diff -urN a/gopls/internal/lsp/testdata/danglingstmt/dangling_for.go b/gopls/internal/lsp/testdata/danglingstmt/dangling_for.go
92035--- a/gopls/internal/lsp/testdata/danglingstmt/dangling_for.go	2000-01-01 00:00:00.000000000 -0000
92036+++ b/gopls/internal/lsp/testdata/danglingstmt/dangling_for.go	1970-01-01 00:00:00.000000000 +0000
92037@@ -1,9 +0,0 @@
92038-package danglingstmt
92039-
92040-func _() {
92041-	for bar //@rank(" //", danglingBar)
92042-}
92043-
92044-func bar() bool { //@item(danglingBar, "bar", "func() bool", "func")
92045-	return true
92046-}
92047diff -urN a/gopls/internal/lsp/testdata/danglingstmt/dangling_for_init_cond.go b/gopls/internal/lsp/testdata/danglingstmt/dangling_for_init_cond.go
92048--- a/gopls/internal/lsp/testdata/danglingstmt/dangling_for_init_cond.go	2000-01-01 00:00:00.000000000 -0000
92049+++ b/gopls/internal/lsp/testdata/danglingstmt/dangling_for_init_cond.go	1970-01-01 00:00:00.000000000 +0000
92050@@ -1,9 +0,0 @@
92051-package danglingstmt
92052-
92053-func _() {
92054-	for i := bar3(); i > bar //@rank(" //", danglingBar3)
92055-}
92056-
92057-func bar3() int { //@item(danglingBar3, "bar3", "func() int", "func")
92058-	return 0
92059-}
92060diff -urN a/gopls/internal/lsp/testdata/danglingstmt/dangling_for_init_cond_post.go b/gopls/internal/lsp/testdata/danglingstmt/dangling_for_init_cond_post.go
92061--- a/gopls/internal/lsp/testdata/danglingstmt/dangling_for_init_cond_post.go	2000-01-01 00:00:00.000000000 -0000
92062+++ b/gopls/internal/lsp/testdata/danglingstmt/dangling_for_init_cond_post.go	1970-01-01 00:00:00.000000000 +0000
92063@@ -1,9 +0,0 @@
92064-package danglingstmt
92065-
92066-func _() {
92067-	for i := bar4(); i > bar4(); i += bar //@rank(" //", danglingBar4)
92068-}
92069-
92070-func bar4() int { //@item(danglingBar4, "bar4", "func() int", "func")
92071-	return 0
92072-}
92073diff -urN a/gopls/internal/lsp/testdata/danglingstmt/dangling_for_init.go b/gopls/internal/lsp/testdata/danglingstmt/dangling_for_init.go
92074--- a/gopls/internal/lsp/testdata/danglingstmt/dangling_for_init.go	2000-01-01 00:00:00.000000000 -0000
92075+++ b/gopls/internal/lsp/testdata/danglingstmt/dangling_for_init.go	1970-01-01 00:00:00.000000000 +0000
92076@@ -1,9 +0,0 @@
92077-package danglingstmt
92078-
92079-func _() {
92080-	for i := bar //@rank(" //", danglingBar2)
92081-}
92082-
92083-func bar2() int { //@item(danglingBar2, "bar2", "func() int", "func")
92084-	return 0
92085-}
92086diff -urN a/gopls/internal/lsp/testdata/danglingstmt/dangling_if_eof.go b/gopls/internal/lsp/testdata/danglingstmt/dangling_if_eof.go
92087--- a/gopls/internal/lsp/testdata/danglingstmt/dangling_if_eof.go	2000-01-01 00:00:00.000000000 -0000
92088+++ b/gopls/internal/lsp/testdata/danglingstmt/dangling_if_eof.go	1970-01-01 00:00:00.000000000 +0000
92089@@ -1,8 +0,0 @@
92090-package danglingstmt
92091-
92092-func bar5() bool { //@item(danglingBar5, "bar5", "func() bool", "func")
92093-	return true
92094-}
92095-
92096-func _() {
92097-	if b //@rank(" //", danglingBar5)
92098diff -urN a/gopls/internal/lsp/testdata/danglingstmt/dangling_if.go b/gopls/internal/lsp/testdata/danglingstmt/dangling_if.go
92099--- a/gopls/internal/lsp/testdata/danglingstmt/dangling_if.go	2000-01-01 00:00:00.000000000 -0000
92100+++ b/gopls/internal/lsp/testdata/danglingstmt/dangling_if.go	1970-01-01 00:00:00.000000000 +0000
92101@@ -1,9 +0,0 @@
92102-package danglingstmt
92103-
92104-func _() {
92105-	if foo //@rank(" //", danglingFoo)
92106-}
92107-
92108-func foo() bool { //@item(danglingFoo, "foo", "func() bool", "func")
92109-	return true
92110-}
92111diff -urN a/gopls/internal/lsp/testdata/danglingstmt/dangling_if_init_cond.go b/gopls/internal/lsp/testdata/danglingstmt/dangling_if_init_cond.go
92112--- a/gopls/internal/lsp/testdata/danglingstmt/dangling_if_init_cond.go	2000-01-01 00:00:00.000000000 -0000
92113+++ b/gopls/internal/lsp/testdata/danglingstmt/dangling_if_init_cond.go	1970-01-01 00:00:00.000000000 +0000
92114@@ -1,9 +0,0 @@
92115-package danglingstmt
92116-
92117-func _() {
92118-	if i := 123; foo //@rank(" //", danglingFoo3)
92119-}
92120-
92121-func foo3() bool { //@item(danglingFoo3, "foo3", "func() bool", "func")
92122-	return true
92123-}
92124diff -urN a/gopls/internal/lsp/testdata/danglingstmt/dangling_if_init.go b/gopls/internal/lsp/testdata/danglingstmt/dangling_if_init.go
92125--- a/gopls/internal/lsp/testdata/danglingstmt/dangling_if_init.go	2000-01-01 00:00:00.000000000 -0000
92126+++ b/gopls/internal/lsp/testdata/danglingstmt/dangling_if_init.go	1970-01-01 00:00:00.000000000 +0000
92127@@ -1,9 +0,0 @@
92128-package danglingstmt
92129-
92130-func _() {
92131-	if i := foo //@rank(" //", danglingFoo2)
92132-}
92133-
92134-func foo2() bool { //@item(danglingFoo2, "foo2", "func() bool", "func")
92135-	return true
92136-}
92137diff -urN a/gopls/internal/lsp/testdata/danglingstmt/dangling_multiline_if.go b/gopls/internal/lsp/testdata/danglingstmt/dangling_multiline_if.go
92138--- a/gopls/internal/lsp/testdata/danglingstmt/dangling_multiline_if.go	2000-01-01 00:00:00.000000000 -0000
92139+++ b/gopls/internal/lsp/testdata/danglingstmt/dangling_multiline_if.go	1970-01-01 00:00:00.000000000 +0000
92140@@ -1,10 +0,0 @@
92141-package danglingstmt
92142-
92143-func walrus() bool { //@item(danglingWalrus, "walrus", "func() bool", "func")
92144-	return true
92145-}
92146-
92147-func _() {
92148-	if true &&
92149-		walrus //@complete(" //", danglingWalrus)
92150-}
92151diff -urN a/gopls/internal/lsp/testdata/danglingstmt/dangling_selector_1.go b/gopls/internal/lsp/testdata/danglingstmt/dangling_selector_1.go
92152--- a/gopls/internal/lsp/testdata/danglingstmt/dangling_selector_1.go	2000-01-01 00:00:00.000000000 -0000
92153+++ b/gopls/internal/lsp/testdata/danglingstmt/dangling_selector_1.go	1970-01-01 00:00:00.000000000 +0000
92154@@ -1,7 +0,0 @@
92155-package danglingstmt
92156-
92157-func _() {
92158-	x. //@rank(" //", danglingI)
92159-}
92160-
92161-var x struct { i int } //@item(danglingI, "i", "int", "field")
92162diff -urN a/gopls/internal/lsp/testdata/danglingstmt/dangling_selector_2.go b/gopls/internal/lsp/testdata/danglingstmt/dangling_selector_2.go
92163--- a/gopls/internal/lsp/testdata/danglingstmt/dangling_selector_2.go	2000-01-01 00:00:00.000000000 -0000
92164+++ b/gopls/internal/lsp/testdata/danglingstmt/dangling_selector_2.go	1970-01-01 00:00:00.000000000 +0000
92165@@ -1,8 +0,0 @@
92166-package danglingstmt
92167-
92168-import "golang.org/lsptests/foo"
92169-
92170-func _() {
92171-	foo. //@rank(" //", Foo)
92172-	var _ = []string{foo.} //@rank("}", Foo)
92173-}
92174diff -urN a/gopls/internal/lsp/testdata/danglingstmt/dangling_switch_init.go b/gopls/internal/lsp/testdata/danglingstmt/dangling_switch_init.go
92175--- a/gopls/internal/lsp/testdata/danglingstmt/dangling_switch_init.go	2000-01-01 00:00:00.000000000 -0000
92176+++ b/gopls/internal/lsp/testdata/danglingstmt/dangling_switch_init.go	1970-01-01 00:00:00.000000000 +0000
92177@@ -1,9 +0,0 @@
92178-package danglingstmt
92179-
92180-func _() {
92181-	switch i := baz //@rank(" //", danglingBaz)
92182-}
92183-
92184-func baz() int { //@item(danglingBaz, "baz", "func() int", "func")
92185-	return 0
92186-}
92187diff -urN a/gopls/internal/lsp/testdata/danglingstmt/dangling_switch_init_tag.go b/gopls/internal/lsp/testdata/danglingstmt/dangling_switch_init_tag.go
92188--- a/gopls/internal/lsp/testdata/danglingstmt/dangling_switch_init_tag.go	2000-01-01 00:00:00.000000000 -0000
92189+++ b/gopls/internal/lsp/testdata/danglingstmt/dangling_switch_init_tag.go	1970-01-01 00:00:00.000000000 +0000
92190@@ -1,9 +0,0 @@
92191-package danglingstmt
92192-
92193-func _() {
92194-	switch i := 0; baz //@rank(" //", danglingBaz2)
92195-}
92196-
92197-func baz2() int { //@item(danglingBaz2, "baz2", "func() int", "func")
92198-	return 0
92199-}
92200diff -urN a/gopls/internal/lsp/testdata/deep/deep.go b/gopls/internal/lsp/testdata/deep/deep.go
92201--- a/gopls/internal/lsp/testdata/deep/deep.go	2000-01-01 00:00:00.000000000 -0000
92202+++ b/gopls/internal/lsp/testdata/deep/deep.go	1970-01-01 00:00:00.000000000 +0000
92203@@ -1,142 +0,0 @@
92204-package deep
92205-
92206-import "context"
92207-
92208-type deepA struct {
92209-	b deepB //@item(deepBField, "b", "deepB", "field")
92210-}
92211-
92212-type deepB struct {
92213-}
92214-
92215-func wantsDeepB(deepB) {}
92216-
92217-func _() {
92218-	var a deepA   //@item(deepAVar, "a", "deepA", "var")
92219-	a.b           //@item(deepABField, "a.b", "deepB", "field")
92220-	wantsDeepB(a) //@deep(")", deepABField, deepAVar)
92221-
92222-	deepA{a} //@snippet("}", deepABField, "a.b", "a.b")
92223-}
92224-
92225-func wantsContext(context.Context) {}
92226-
92227-func _() {
92228-	context.Background() //@item(ctxBackground, "context.Background", "func() context.Context", "func", "Background returns a non-nil, empty Context.")
92229-	context.TODO()       //@item(ctxTODO, "context.TODO", "func() context.Context", "func", "TODO returns a non-nil, empty Context.")
92230-
92231-	wantsContext(c) //@rank(")", ctxBackground),rank(")", ctxTODO)
92232-}
92233-
92234-func _() {
92235-	var cork struct{ err error }
92236-	cork.err         //@item(deepCorkErr, "cork.err", "error", "field")
92237-	context          //@item(deepContextPkg, "context", "\"context\"", "package")
92238-	var _ error = co //@rank(" //", deepCorkErr, deepContextPkg)
92239-}
92240-
92241-func _() {
92242-	// deepCircle is circular.
92243-	type deepCircle struct {
92244-		*deepCircle
92245-	}
92246-	var circle deepCircle   //@item(deepCircle, "circle", "deepCircle", "var")
92247-	circle.deepCircle       //@item(deepCircleField, "circle.deepCircle", "*deepCircle", "field")
92248-	var _ deepCircle = circ //@deep(" //", deepCircle, deepCircleField),snippet(" //", deepCircleField, "*circle.deepCircle", "*circle.deepCircle")
92249-}
92250-
92251-func _() {
92252-	type deepEmbedC struct {
92253-	}
92254-	type deepEmbedB struct {
92255-		deepEmbedC
92256-	}
92257-	type deepEmbedA struct {
92258-		deepEmbedB
92259-	}
92260-
92261-	wantsC := func(deepEmbedC) {}
92262-
92263-	var a deepEmbedA //@item(deepEmbedA, "a", "deepEmbedA", "var")
92264-	a.deepEmbedB     //@item(deepEmbedB, "a.deepEmbedB", "deepEmbedB", "field")
92265-	a.deepEmbedC     //@item(deepEmbedC, "a.deepEmbedC", "deepEmbedC", "field")
92266-	wantsC(a)        //@deep(")", deepEmbedC, deepEmbedA, deepEmbedB)
92267-}
92268-
92269-func _() {
92270-	type nested struct {
92271-		a int
92272-		n *nested //@item(deepNestedField, "n", "*nested", "field")
92273-	}
92274-
92275-	nested{
92276-		a: 123, //@deep(" //", deepNestedField)
92277-	}
92278-}
92279-
92280-func _() {
92281-	var a struct {
92282-		b struct {
92283-			c int
92284-		}
92285-		d int
92286-	}
92287-
92288-	a.d   //@item(deepAD, "a.d", "int", "field")
92289-	a.b.c //@item(deepABC, "a.b.c", "int", "field")
92290-	a.b   //@item(deepAB, "a.b", "struct{...}", "field")
92291-	a     //@item(deepA, "a", "struct{...}", "var")
92292-
92293-	// "a.d" should be ranked above the deeper "a.b.c"
92294-	var i int
92295-	i = a //@deep(" //", deepAD, deepABC, deepA, deepAB)
92296-}
92297-
92298-type foo struct {
92299-	b bar
92300-}
92301-
92302-func (f foo) bar() bar {
92303-	return f.b
92304-}
92305-
92306-func (f foo) barPtr() *bar {
92307-	return &f.b
92308-}
92309-
92310-type bar struct{}
92311-
92312-func (b bar) valueReceiver() int {
92313-	return 0
92314-}
92315-
92316-func (b *bar) ptrReceiver() int {
92317-	return 0
92318-}
92319-
92320-func _() {
92321-	var (
92322-		i int
92323-		f foo
92324-	)
92325-
92326-	f.bar().valueReceiver    //@item(deepBarValue, "f.bar().valueReceiver", "func() int", "method")
92327-	f.barPtr().ptrReceiver   //@item(deepBarPtrPtr, "f.barPtr().ptrReceiver", "func() int", "method")
92328-	f.barPtr().valueReceiver //@item(deepBarPtrValue, "f.barPtr().valueReceiver", "func() int", "method")
92329-
92330-	i = fbar //@fuzzy(" //", deepBarValue, deepBarPtrPtr, deepBarPtrValue)
92331-}
92332-
92333-func (b baz) Thing() struct{ val int } {
92334-	return b.thing
92335-}
92336-
92337-type baz struct {
92338-	thing struct{ val int }
92339-}
92340-
92341-func (b baz) _() {
92342-	b.Thing().val    //@item(deepBazMethVal, "b.Thing().val", "int", "field")
92343-	b.thing.val      //@item(deepBazFieldVal, "b.thing.val", "int", "field")
92344-	var _ int = bval //@rank(" //", deepBazFieldVal, deepBazMethVal)
92345-}
92346diff -urN a/gopls/internal/lsp/testdata/errors/errors.go b/gopls/internal/lsp/testdata/errors/errors.go
92347--- a/gopls/internal/lsp/testdata/errors/errors.go	2000-01-01 00:00:00.000000000 -0000
92348+++ b/gopls/internal/lsp/testdata/errors/errors.go	1970-01-01 00:00:00.000000000 +0000
92349@@ -1,10 +0,0 @@
92350-package errors
92351-
92352-import (
92353-	"golang.org/lsptests/types"
92354-)
92355-
92356-func _() {
92357-	bob.Bob() //@complete(".")
92358-	types.b //@complete(" //", Bob_interface)
92359-}
92360diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_args_returns.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_args_returns.go
92361--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_args_returns.go	2000-01-01 00:00:00.000000000 -0000
92362+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_args_returns.go	1970-01-01 00:00:00.000000000 +0000
92363@@ -1,11 +0,0 @@
92364-package extract
92365-
92366-func _() {
92367-	a := 1
92368-	a = 5     //@mark(exSt0, "a")
92369-	a = a + 2 //@mark(exEn0, "2")
92370-	//@extractfunc(exSt0, exEn0)
92371-	b := a * 2 //@mark(exB, "	b")
92372-	_ = 3 + 4  //@mark(exEnd, "4")
92373-	//@extractfunc(exB, exEnd)
92374-}
92375diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_args_returns.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_args_returns.go.golden
92376--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_args_returns.go.golden	2000-01-01 00:00:00.000000000 -0000
92377+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_args_returns.go.golden	1970-01-01 00:00:00.000000000 +0000
92378@@ -1,37 +0,0 @@
92379--- functionextraction_extract_args_returns_5_2 --
92380-package extract
92381-
92382-func _() {
92383-	a := 1
92384-	//@mark(exSt0, "a")
92385-	a = newFunction(a) //@mark(exEn0, "2")
92386-	//@extractfunc(exSt0, exEn0)
92387-	b := a * 2 //@mark(exB, "	b")
92388-	_ = 3 + 4  //@mark(exEnd, "4")
92389-	//@extractfunc(exB, exEnd)
92390-}
92391-
92392-func newFunction(a int) int {
92393-	a = 5
92394-	a = a + 2
92395-	return a
92396-}
92397-
92398--- functionextraction_extract_args_returns_8_1 --
92399-package extract
92400-
92401-func _() {
92402-	a := 1
92403-	a = 5     //@mark(exSt0, "a")
92404-	a = a + 2 //@mark(exEn0, "2")
92405-	//@extractfunc(exSt0, exEn0)
92406-	//@mark(exB, "	b")
92407-	newFunction(a)  //@mark(exEnd, "4")
92408-	//@extractfunc(exB, exEnd)
92409-}
92410-
92411-func newFunction(a int) {
92412-	b := a * 2
92413-	_ = 3 + 4
92414-}
92415-
92416diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_basic_comment.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_basic_comment.go
92417--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_basic_comment.go	2000-01-01 00:00:00.000000000 -0000
92418+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_basic_comment.go	1970-01-01 00:00:00.000000000 +0000
92419@@ -1,12 +0,0 @@
92420-package extract
92421-
92422-func _() {
92423-	a := /* comment in the middle of a line */ 1 //@mark(exSt18, "a")
92424-	// Comment on its own line  //@mark(exSt19, "Comment")
92425-	_ = 3 + 4 //@mark(exEn18, "4"),mark(exEn19, "4"),mark(exSt20, "_")
92426-	// Comment right after 3 + 4
92427-
92428-	// Comment after with space //@mark(exEn20, "Comment")
92429-
92430-	//@extractfunc(exSt18, exEn18),extractfunc(exSt19, exEn19),extractfunc(exSt20, exEn20)
92431-}
92432diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_basic_comment.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_basic_comment.go.golden
92433--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_basic_comment.go.golden	2000-01-01 00:00:00.000000000 -0000
92434+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_basic_comment.go.golden	1970-01-01 00:00:00.000000000 +0000
92435@@ -1,57 +0,0 @@
92436--- functionextraction_extract_basic_comment_4_2 --
92437-package extract
92438-
92439-func _() {
92440-	/* comment in the middle of a line */
92441-	//@mark(exSt18, "a")
92442-	// Comment on its own line  //@mark(exSt19, "Comment")
92443-	newFunction() //@mark(exEn18, "4"),mark(exEn19, "4"),mark(exSt20, "_")
92444-	// Comment right after 3 + 4
92445-
92446-	// Comment after with space //@mark(exEn20, "Comment")
92447-
92448-	//@extractfunc(exSt18, exEn18),extractfunc(exSt19, exEn19),extractfunc(exSt20, exEn20)
92449-}
92450-
92451-func newFunction() {
92452-	a := 1
92453-
92454-	_ = 3 + 4
92455-}
92456-
92457--- functionextraction_extract_basic_comment_5_5 --
92458-package extract
92459-
92460-func _() {
92461-	a := /* comment in the middle of a line */ 1 //@mark(exSt18, "a")
92462-	// Comment on its own line  //@mark(exSt19, "Comment")
92463-	newFunction() //@mark(exEn18, "4"),mark(exEn19, "4"),mark(exSt20, "_")
92464-	// Comment right after 3 + 4
92465-
92466-	// Comment after with space //@mark(exEn20, "Comment")
92467-
92468-	//@extractfunc(exSt18, exEn18),extractfunc(exSt19, exEn19),extractfunc(exSt20, exEn20)
92469-}
92470-
92471-func newFunction() {
92472-	_ = 3 + 4
92473-}
92474-
92475--- functionextraction_extract_basic_comment_6_2 --
92476-package extract
92477-
92478-func _() {
92479-	a := /* comment in the middle of a line */ 1 //@mark(exSt18, "a")
92480-	// Comment on its own line  //@mark(exSt19, "Comment")
92481-	newFunction() //@mark(exEn18, "4"),mark(exEn19, "4"),mark(exSt20, "_")
92482-	// Comment right after 3 + 4
92483-
92484-	// Comment after with space //@mark(exEn20, "Comment")
92485-
92486-	//@extractfunc(exSt18, exEn18),extractfunc(exSt19, exEn19),extractfunc(exSt20, exEn20)
92487-}
92488-
92489-func newFunction() {
92490-	_ = 3 + 4
92491-}
92492-
92493diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_basic.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_basic.go
92494--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_basic.go	2000-01-01 00:00:00.000000000 -0000
92495+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_basic.go	1970-01-01 00:00:00.000000000 +0000
92496@@ -1,8 +0,0 @@
92497-package extract
92498-
92499-func _() { //@mark(exSt25, "{")
92500-	a := 1    //@mark(exSt1, "a")
92501-	_ = 3 + 4 //@mark(exEn1, "4")
92502-	//@extractfunc(exSt1, exEn1)
92503-	//@extractfunc(exSt25, exEn25)
92504-} //@mark(exEn25, "}")
92505diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_basic.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_basic.go.golden
92506--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_basic.go.golden	2000-01-01 00:00:00.000000000 -0000
92507+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_basic.go.golden	1970-01-01 00:00:00.000000000 +0000
92508@@ -1,30 +0,0 @@
92509--- functionextraction_extract_basic_3_10 --
92510-package extract
92511-
92512-func _() { //@mark(exSt25, "{")
92513-	//@mark(exSt1, "a")
92514-	newFunction() //@mark(exEn1, "4")
92515-	//@extractfunc(exSt1, exEn1)
92516-	//@extractfunc(exSt25, exEn25)
92517-}
92518-
92519-func newFunction() {
92520-	a := 1
92521-	_ = 3 + 4
92522-} //@mark(exEn25, "}")
92523-
92524--- functionextraction_extract_basic_4_2 --
92525-package extract
92526-
92527-func _() { //@mark(exSt25, "{")
92528-	//@mark(exSt1, "a")
92529-	newFunction() //@mark(exEn1, "4")
92530-	//@extractfunc(exSt1, exEn1)
92531-	//@extractfunc(exSt25, exEn25)
92532-}
92533-
92534-func newFunction() {
92535-	a := 1
92536-	_ = 3 + 4
92537-} //@mark(exEn25, "}")
92538-
92539diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_issue_44813.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_issue_44813.go
92540--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_issue_44813.go	2000-01-01 00:00:00.000000000 -0000
92541+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_issue_44813.go	1970-01-01 00:00:00.000000000 +0000
92542@@ -1,13 +0,0 @@
92543-package extract
92544-
92545-import "fmt"
92546-
92547-func main() {
92548-	x := []rune{} //@mark(exSt9, "x")
92549-	s := "HELLO"
92550-	for _, c := range s {
92551-		x = append(x, c)
92552-	} //@mark(exEn9, "}")
92553-	//@extractfunc(exSt9, exEn9)
92554-	fmt.Printf("%x\n", x)
92555-}
92556diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_issue_44813.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_issue_44813.go.golden
92557--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_issue_44813.go.golden	2000-01-01 00:00:00.000000000 -0000
92558+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_issue_44813.go.golden	1970-01-01 00:00:00.000000000 +0000
92559@@ -1,21 +0,0 @@
92560--- functionextraction_extract_issue_44813_6_2 --
92561-package extract
92562-
92563-import "fmt"
92564-
92565-func main() {
92566-	//@mark(exSt9, "x")
92567-	x := newFunction() //@mark(exEn9, "}")
92568-	//@extractfunc(exSt9, exEn9)
92569-	fmt.Printf("%x\n", x)
92570-}
92571-
92572-func newFunction() []rune {
92573-	x := []rune{}
92574-	s := "HELLO"
92575-	for _, c := range s {
92576-		x = append(x, c)
92577-	}
92578-	return x
92579-}
92580-
92581diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_redefine.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_redefine.go
92582--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_redefine.go	2000-01-01 00:00:00.000000000 -0000
92583+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_redefine.go	1970-01-01 00:00:00.000000000 +0000
92584@@ -1,11 +0,0 @@
92585-package extract
92586-
92587-import "strconv"
92588-
92589-func _() {
92590-	i, err := strconv.Atoi("1")
92591-	u, err := strconv.Atoi("2") //@extractfunc("u", ")")
92592-	if i == u || err == nil {
92593-		return
92594-	}
92595-}
92596diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_redefine.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_redefine.go.golden
92597--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_redefine.go.golden	2000-01-01 00:00:00.000000000 -0000
92598+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_redefine.go.golden	1970-01-01 00:00:00.000000000 +0000
92599@@ -1,18 +0,0 @@
92600--- functionextraction_extract_redefine_7_2 --
92601-package extract
92602-
92603-import "strconv"
92604-
92605-func _() {
92606-	i, err := strconv.Atoi("1")
92607-	u, err := newFunction() //@extractfunc("u", ")")
92608-	if i == u || err == nil {
92609-		return
92610-	}
92611-}
92612-
92613-func newFunction() (int, error) {
92614-	u, err := strconv.Atoi("2")
92615-	return u, err
92616-}
92617-
92618diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic.go
92619--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic.go	2000-01-01 00:00:00.000000000 -0000
92620+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic.go	1970-01-01 00:00:00.000000000 +0000
92621@@ -1,10 +0,0 @@
92622-package extract
92623-
92624-func _() bool {
92625-	x := 1
92626-	if x == 0 { //@mark(exSt2, "if")
92627-		return true
92628-	} //@mark(exEn2, "}")
92629-	return false
92630-	//@extractfunc(exSt2, exEn2)
92631-}
92632diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic.go.golden
92633--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic.go.golden	2000-01-01 00:00:00.000000000 -0000
92634+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic.go.golden	1970-01-01 00:00:00.000000000 +0000
92635@@ -1,21 +0,0 @@
92636--- functionextraction_extract_return_basic_5_2 --
92637-package extract
92638-
92639-func _() bool {
92640-	x := 1
92641-	//@mark(exSt2, "if")
92642-	shouldReturn, returnValue := newFunction(x)
92643-	if shouldReturn {
92644-		return returnValue
92645-	} //@mark(exEn2, "}")
92646-	return false
92647-	//@extractfunc(exSt2, exEn2)
92648-}
92649-
92650-func newFunction(x int) (bool, bool) {
92651-	if x == 0 {
92652-		return true, true
92653-	}
92654-	return false, false
92655-}
92656-
92657diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic_nonnested.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic_nonnested.go
92658--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic_nonnested.go	2000-01-01 00:00:00.000000000 -0000
92659+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic_nonnested.go	1970-01-01 00:00:00.000000000 +0000
92660@@ -1,10 +0,0 @@
92661-package extract
92662-
92663-func _() bool {
92664-	x := 1 //@mark(exSt13, "x")
92665-	if x == 0 {
92666-		return true
92667-	}
92668-	return false //@mark(exEn13, "false")
92669-	//@extractfunc(exSt13, exEn13)
92670-}
92671diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic_nonnested.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic_nonnested.go.golden
92672--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic_nonnested.go.golden	2000-01-01 00:00:00.000000000 -0000
92673+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_basic_nonnested.go.golden	1970-01-01 00:00:00.000000000 +0000
92674@@ -1,17 +0,0 @@
92675--- functionextraction_extract_return_basic_nonnested_4_2 --
92676-package extract
92677-
92678-func _() bool {
92679-	//@mark(exSt13, "x")
92680-	return newFunction() //@mark(exEn13, "false")
92681-	//@extractfunc(exSt13, exEn13)
92682-}
92683-
92684-func newFunction() bool {
92685-	x := 1
92686-	if x == 0 {
92687-		return true
92688-	}
92689-	return false
92690-}
92691-
92692diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex.go
92693--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex.go	2000-01-01 00:00:00.000000000 -0000
92694+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex.go	1970-01-01 00:00:00.000000000 +0000
92695@@ -1,17 +0,0 @@
92696-package extract
92697-
92698-import "fmt"
92699-
92700-func _() (int, string, error) {
92701-	x := 1
92702-	y := "hello"
92703-	z := "bye" //@mark(exSt3, "z")
92704-	if y == z {
92705-		return x, y, fmt.Errorf("same")
92706-	} else {
92707-		z = "hi"
92708-		return x, z, nil
92709-	} //@mark(exEn3, "}")
92710-	return x, z, nil
92711-	//@extractfunc(exSt3, exEn3)
92712-}
92713diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex.go.golden
92714--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex.go.golden	2000-01-01 00:00:00.000000000 -0000
92715+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex.go.golden	1970-01-01 00:00:00.000000000 +0000
92716@@ -1,28 +0,0 @@
92717--- functionextraction_extract_return_complex_8_2 --
92718-package extract
92719-
92720-import "fmt"
92721-
92722-func _() (int, string, error) {
92723-	x := 1
92724-	y := "hello"
92725-	//@mark(exSt3, "z")
92726-	z, shouldReturn, returnValue, returnValue1, returnValue2 := newFunction(y, x)
92727-	if shouldReturn {
92728-		return returnValue, returnValue1, returnValue2
92729-	} //@mark(exEn3, "}")
92730-	return x, z, nil
92731-	//@extractfunc(exSt3, exEn3)
92732-}
92733-
92734-func newFunction(y string, x int) (string, bool, int, string, error) {
92735-	z := "bye"
92736-	if y == z {
92737-		return "", true, x, y, fmt.Errorf("same")
92738-	} else {
92739-		z = "hi"
92740-		return "", true, x, z, nil
92741-	}
92742-	return z, false, 0, "", nil
92743-}
92744-
92745diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex_nonnested.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex_nonnested.go
92746--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex_nonnested.go	2000-01-01 00:00:00.000000000 -0000
92747+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex_nonnested.go	1970-01-01 00:00:00.000000000 +0000
92748@@ -1,17 +0,0 @@
92749-package extract
92750-
92751-import "fmt"
92752-
92753-func _() (int, string, error) {
92754-	x := 1
92755-	y := "hello"
92756-	z := "bye" //@mark(exSt10, "z")
92757-	if y == z {
92758-		return x, y, fmt.Errorf("same")
92759-	} else {
92760-		z = "hi"
92761-		return x, z, nil
92762-	}
92763-	return x, z, nil //@mark(exEn10, "nil")
92764-	//@extractfunc(exSt10, exEn10)
92765-}
92766diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex_nonnested.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex_nonnested.go.golden
92767--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex_nonnested.go.golden	2000-01-01 00:00:00.000000000 -0000
92768+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_complex_nonnested.go.golden	1970-01-01 00:00:00.000000000 +0000
92769@@ -1,24 +0,0 @@
92770--- functionextraction_extract_return_complex_nonnested_8_2 --
92771-package extract
92772-
92773-import "fmt"
92774-
92775-func _() (int, string, error) {
92776-	x := 1
92777-	y := "hello"
92778-	//@mark(exSt10, "z")
92779-	return newFunction(y, x) //@mark(exEn10, "nil")
92780-	//@extractfunc(exSt10, exEn10)
92781-}
92782-
92783-func newFunction(y string, x int) (int, string, error) {
92784-	z := "bye"
92785-	if y == z {
92786-		return x, y, fmt.Errorf("same")
92787-	} else {
92788-		z = "hi"
92789-		return x, z, nil
92790-	}
92791-	return x, z, nil
92792-}
92793-
92794diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit.go
92795--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit.go	2000-01-01 00:00:00.000000000 -0000
92796+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit.go	1970-01-01 00:00:00.000000000 +0000
92797@@ -1,13 +0,0 @@
92798-package extract
92799-
92800-import "go/ast"
92801-
92802-func _() {
92803-	ast.Inspect(ast.NewIdent("a"), func(n ast.Node) bool {
92804-		if n == nil { //@mark(exSt4, "if")
92805-			return true
92806-		} //@mark(exEn4, "}")
92807-		return false
92808-	})
92809-	//@extractfunc(exSt4, exEn4)
92810-}
92811diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit.go.golden
92812--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit.go.golden	2000-01-01 00:00:00.000000000 -0000
92813+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit.go.golden	1970-01-01 00:00:00.000000000 +0000
92814@@ -1,24 +0,0 @@
92815--- functionextraction_extract_return_func_lit_7_3 --
92816-package extract
92817-
92818-import "go/ast"
92819-
92820-func _() {
92821-	ast.Inspect(ast.NewIdent("a"), func(n ast.Node) bool {
92822-		//@mark(exSt4, "if")
92823-		shouldReturn, returnValue := newFunction(n)
92824-		if shouldReturn {
92825-			return returnValue
92826-		} //@mark(exEn4, "}")
92827-		return false
92828-	})
92829-	//@extractfunc(exSt4, exEn4)
92830-}
92831-
92832-func newFunction(n ast.Node) (bool, bool) {
92833-	if n == nil {
92834-		return true, true
92835-	}
92836-	return false, false
92837-}
92838-
92839diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit_nonnested.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit_nonnested.go
92840--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit_nonnested.go	2000-01-01 00:00:00.000000000 -0000
92841+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit_nonnested.go	1970-01-01 00:00:00.000000000 +0000
92842@@ -1,13 +0,0 @@
92843-package extract
92844-
92845-import "go/ast"
92846-
92847-func _() {
92848-	ast.Inspect(ast.NewIdent("a"), func(n ast.Node) bool {
92849-		if n == nil { //@mark(exSt11, "if")
92850-			return true
92851-		}
92852-		return false //@mark(exEn11, "false")
92853-	})
92854-	//@extractfunc(exSt11, exEn11)
92855-}
92856diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit_nonnested.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit_nonnested.go.golden
92857--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit_nonnested.go.golden	2000-01-01 00:00:00.000000000 -0000
92858+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_func_lit_nonnested.go.golden	1970-01-01 00:00:00.000000000 +0000
92859@@ -1,20 +0,0 @@
92860--- functionextraction_extract_return_func_lit_nonnested_7_3 --
92861-package extract
92862-
92863-import "go/ast"
92864-
92865-func _() {
92866-	ast.Inspect(ast.NewIdent("a"), func(n ast.Node) bool {
92867-		//@mark(exSt11, "if")
92868-		return newFunction(n) //@mark(exEn11, "false")
92869-	})
92870-	//@extractfunc(exSt11, exEn11)
92871-}
92872-
92873-func newFunction(n ast.Node) bool {
92874-	if n == nil {
92875-		return true
92876-	}
92877-	return false
92878-}
92879-
92880diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init.go
92881--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init.go	2000-01-01 00:00:00.000000000 -0000
92882+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init.go	1970-01-01 00:00:00.000000000 +0000
92883@@ -1,12 +0,0 @@
92884-package extract
92885-
92886-func _() string {
92887-	x := 1
92888-	if x == 0 { //@mark(exSt5, "if")
92889-		x = 3
92890-		return "a"
92891-	} //@mark(exEn5, "}")
92892-	x = 2
92893-	return "b"
92894-	//@extractfunc(exSt5, exEn5)
92895-}
92896diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init.go.golden
92897--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init.go.golden	2000-01-01 00:00:00.000000000 -0000
92898+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init.go.golden	1970-01-01 00:00:00.000000000 +0000
92899@@ -1,23 +0,0 @@
92900--- functionextraction_extract_return_init_5_2 --
92901-package extract
92902-
92903-func _() string {
92904-	x := 1
92905-	//@mark(exSt5, "if")
92906-	shouldReturn, returnValue := newFunction(x)
92907-	if shouldReturn {
92908-		return returnValue
92909-	} //@mark(exEn5, "}")
92910-	x = 2
92911-	return "b"
92912-	//@extractfunc(exSt5, exEn5)
92913-}
92914-
92915-func newFunction(x int) (bool, string) {
92916-	if x == 0 {
92917-		x = 3
92918-		return true, "a"
92919-	}
92920-	return false, ""
92921-}
92922-
92923diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init_nonnested.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init_nonnested.go
92924--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init_nonnested.go	2000-01-01 00:00:00.000000000 -0000
92925+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init_nonnested.go	1970-01-01 00:00:00.000000000 +0000
92926@@ -1,12 +0,0 @@
92927-package extract
92928-
92929-func _() string {
92930-	x := 1
92931-	if x == 0 { //@mark(exSt12, "if")
92932-		x = 3
92933-		return "a"
92934-	}
92935-	x = 2
92936-	return "b" //@mark(exEn12, "\"b\"")
92937-	//@extractfunc(exSt12, exEn12)
92938-}
92939diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init_nonnested.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init_nonnested.go.golden
92940--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init_nonnested.go.golden	2000-01-01 00:00:00.000000000 -0000
92941+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_return_init_nonnested.go.golden	1970-01-01 00:00:00.000000000 +0000
92942@@ -1,19 +0,0 @@
92943--- functionextraction_extract_return_init_nonnested_5_2 --
92944-package extract
92945-
92946-func _() string {
92947-	x := 1
92948-	//@mark(exSt12, "if")
92949-	return newFunction(x) //@mark(exEn12, "\"b\"")
92950-	//@extractfunc(exSt12, exEn12)
92951-}
92952-
92953-func newFunction(x int) string {
92954-	if x == 0 {
92955-		x = 3
92956-		return "a"
92957-	}
92958-	x = 2
92959-	return "b"
92960-}
92961-
92962diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_scope.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_scope.go
92963--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_scope.go	2000-01-01 00:00:00.000000000 -0000
92964+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_scope.go	1970-01-01 00:00:00.000000000 +0000
92965@@ -1,10 +0,0 @@
92966-package extract
92967-
92968-func _() {
92969-	newFunction := 1
92970-	a := newFunction //@extractfunc("a", "newFunction")
92971-}
92972-
92973-func newFunction1() int {
92974-	return 1
92975-}
92976diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_scope.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_scope.go.golden
92977--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_scope.go.golden	2000-01-01 00:00:00.000000000 -0000
92978+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_scope.go.golden	1970-01-01 00:00:00.000000000 +0000
92979@@ -1,16 +0,0 @@
92980--- functionextraction_extract_scope_5_2 --
92981-package extract
92982-
92983-func _() {
92984-	newFunction := 1
92985-	newFunction2(newFunction) //@extractfunc("a", "newFunction")
92986-}
92987-
92988-func newFunction2(newFunction int) {
92989-	a := newFunction
92990-}
92991-
92992-func newFunction1() int {
92993-	return 1
92994-}
92995-
92996diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_initialization.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_initialization.go
92997--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_initialization.go	2000-01-01 00:00:00.000000000 -0000
92998+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_initialization.go	1970-01-01 00:00:00.000000000 +0000
92999@@ -1,9 +0,0 @@
93000-package extract
93001-
93002-func _() {
93003-	var a []int
93004-	a = append(a, 2) //@mark(exSt6, "a")
93005-	b := 4           //@mark(exEn6, "4")
93006-	//@extractfunc(exSt6, exEn6)
93007-	a = append(a, b)
93008-}
93009diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_initialization.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_initialization.go.golden
93010--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_initialization.go.golden	2000-01-01 00:00:00.000000000 -0000
93011+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_initialization.go.golden	1970-01-01 00:00:00.000000000 +0000
93012@@ -1,17 +0,0 @@
93013--- functionextraction_extract_smart_initialization_5_2 --
93014-package extract
93015-
93016-func _() {
93017-	var a []int
93018-	//@mark(exSt6, "a")
93019-	a, b := newFunction(a)           //@mark(exEn6, "4")
93020-	//@extractfunc(exSt6, exEn6)
93021-	a = append(a, b)
93022-}
93023-
93024-func newFunction(a []int) ([]int, int) {
93025-	a = append(a, 2)
93026-	b := 4
93027-	return a, b
93028-}
93029-
93030diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_return.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_return.go
93031--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_return.go	2000-01-01 00:00:00.000000000 -0000
93032+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_return.go	1970-01-01 00:00:00.000000000 +0000
93033@@ -1,11 +0,0 @@
93034-package extract
93035-
93036-func _() {
93037-	var b []int
93038-	var a int
93039-	a = 2 //@mark(exSt7, "a")
93040-	b = []int{}
93041-	b = append(b, a) //@mark(exEn7, ")")
93042-	b[0] = 1
93043-	//@extractfunc(exSt7, exEn7)
93044-}
93045diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_return.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_return.go.golden
93046--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_return.go.golden	2000-01-01 00:00:00.000000000 -0000
93047+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_smart_return.go.golden	1970-01-01 00:00:00.000000000 +0000
93048@@ -1,19 +0,0 @@
93049--- functionextraction_extract_smart_return_6_2 --
93050-package extract
93051-
93052-func _() {
93053-	var b []int
93054-	var a int
93055-	//@mark(exSt7, "a")
93056-	b = newFunction(a, b) //@mark(exEn7, ")")
93057-	b[0] = 1
93058-	//@extractfunc(exSt7, exEn7)
93059-}
93060-
93061-func newFunction(a int, b []int) []int {
93062-	a = 2
93063-	b = []int{}
93064-	b = append(b, a)
93065-	return b
93066-}
93067-
93068diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_unnecessary_param.go b/gopls/internal/lsp/testdata/extract/extract_function/extract_unnecessary_param.go
93069--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_unnecessary_param.go	2000-01-01 00:00:00.000000000 -0000
93070+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_unnecessary_param.go	1970-01-01 00:00:00.000000000 +0000
93071@@ -1,14 +0,0 @@
93072-package extract
93073-
93074-func _() {
93075-	var b []int
93076-	var a int
93077-	a := 2 //@mark(exSt8, "a")
93078-	b = []int{}
93079-	b = append(b, a) //@mark(exEn8, ")")
93080-	b[0] = 1
93081-	if a == 2 {
93082-		return
93083-	}
93084-	//@extractfunc(exSt8, exEn8)
93085-}
93086diff -urN a/gopls/internal/lsp/testdata/extract/extract_function/extract_unnecessary_param.go.golden b/gopls/internal/lsp/testdata/extract/extract_function/extract_unnecessary_param.go.golden
93087--- a/gopls/internal/lsp/testdata/extract/extract_function/extract_unnecessary_param.go.golden	2000-01-01 00:00:00.000000000 -0000
93088+++ b/gopls/internal/lsp/testdata/extract/extract_function/extract_unnecessary_param.go.golden	1970-01-01 00:00:00.000000000 +0000
93089@@ -1,22 +0,0 @@
93090--- functionextraction_extract_unnecessary_param_6_2 --
93091-package extract
93092-
93093-func _() {
93094-	var b []int
93095-	var a int
93096-	//@mark(exSt8, "a")
93097-	a, b = newFunction(b) //@mark(exEn8, ")")
93098-	b[0] = 1
93099-	if a == 2 {
93100-		return
93101-	}
93102-	//@extractfunc(exSt8, exEn8)
93103-}
93104-
93105-func newFunction(b []int) (int, []int) {
93106-	a := 2
93107-	b = []int{}
93108-	b = append(b, a)
93109-	return a, b
93110-}
93111-
93112diff -urN a/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go b/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go
93113--- a/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go	2000-01-01 00:00:00.000000000 -0000
93114+++ b/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go	1970-01-01 00:00:00.000000000 +0000
93115@@ -1,24 +0,0 @@
93116-package extract
93117-
93118-type A struct {
93119-	x int
93120-	y int
93121-}
93122-
93123-func (a *A) XLessThanYP() bool {
93124-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93125-}
93126-
93127-func (a *A) AddP() int {
93128-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93129-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93130-}
93131-
93132-func (a A) XLessThanY() bool {
93133-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93134-}
93135-
93136-func (a A) Add() int {
93137-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93138-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93139-}
93140diff -urN a/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go.golden b/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go.golden
93141--- a/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go.golden	2000-01-01 00:00:00.000000000 -0000
93142+++ b/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go.golden	1970-01-01 00:00:00.000000000 +0000
93143@@ -1,364 +0,0 @@
93144--- functionextraction_extract_basic_13_2 --
93145-package extract
93146-
93147-type A struct {
93148-	x int
93149-	y int
93150-}
93151-
93152-func (a *A) XLessThanYP() bool {
93153-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93154-}
93155-
93156-func (a *A) AddP() int {
93157-	sum := newFunction(a) //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93158-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93159-}
93160-
93161-func newFunction(a *A) int {
93162-	sum := a.x + a.y
93163-	return sum
93164-}
93165-
93166-func (a A) XLessThanY() bool {
93167-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93168-}
93169-
93170-func (a A) Add() int {
93171-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93172-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93173-}
93174-
93175--- functionextraction_extract_basic_14_2 --
93176-package extract
93177-
93178-type A struct {
93179-	x int
93180-	y int
93181-}
93182-
93183-func (a *A) XLessThanYP() bool {
93184-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93185-}
93186-
93187-func (a *A) AddP() int {
93188-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93189-	return newFunction(sum)       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93190-}
93191-
93192-func newFunction(sum int) int {
93193-	return sum
93194-}
93195-
93196-func (a A) XLessThanY() bool {
93197-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93198-}
93199-
93200-func (a A) Add() int {
93201-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93202-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93203-}
93204-
93205--- functionextraction_extract_basic_18_2 --
93206-package extract
93207-
93208-type A struct {
93209-	x int
93210-	y int
93211-}
93212-
93213-func (a *A) XLessThanYP() bool {
93214-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93215-}
93216-
93217-func (a *A) AddP() int {
93218-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93219-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93220-}
93221-
93222-func (a A) XLessThanY() bool {
93223-	return newFunction(a) //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93224-}
93225-
93226-func newFunction(a A) bool {
93227-	return a.x < a.y
93228-}
93229-
93230-func (a A) Add() int {
93231-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93232-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93233-}
93234-
93235--- functionextraction_extract_basic_22_2 --
93236-package extract
93237-
93238-type A struct {
93239-	x int
93240-	y int
93241-}
93242-
93243-func (a *A) XLessThanYP() bool {
93244-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93245-}
93246-
93247-func (a *A) AddP() int {
93248-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93249-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93250-}
93251-
93252-func (a A) XLessThanY() bool {
93253-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93254-}
93255-
93256-func (a A) Add() int {
93257-	sum := newFunction(a) //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93258-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93259-}
93260-
93261-func newFunction(a A) int {
93262-	sum := a.x + a.y
93263-	return sum
93264-}
93265-
93266--- functionextraction_extract_basic_23_2 --
93267-package extract
93268-
93269-type A struct {
93270-	x int
93271-	y int
93272-}
93273-
93274-func (a *A) XLessThanYP() bool {
93275-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93276-}
93277-
93278-func (a *A) AddP() int {
93279-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93280-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93281-}
93282-
93283-func (a A) XLessThanY() bool {
93284-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93285-}
93286-
93287-func (a A) Add() int {
93288-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93289-	return newFunction(sum)       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93290-}
93291-
93292-func newFunction(sum int) int {
93293-	return sum
93294-}
93295-
93296--- functionextraction_extract_basic_9_2 --
93297-package extract
93298-
93299-type A struct {
93300-	x int
93301-	y int
93302-}
93303-
93304-func (a *A) XLessThanYP() bool {
93305-	return newFunction(a) //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93306-}
93307-
93308-func newFunction(a *A) bool {
93309-	return a.x < a.y
93310-}
93311-
93312-func (a *A) AddP() int {
93313-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93314-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93315-}
93316-
93317-func (a A) XLessThanY() bool {
93318-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93319-}
93320-
93321-func (a A) Add() int {
93322-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93323-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93324-}
93325-
93326--- methodextraction_extract_basic_13_2 --
93327-package extract
93328-
93329-type A struct {
93330-	x int
93331-	y int
93332-}
93333-
93334-func (a *A) XLessThanYP() bool {
93335-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93336-}
93337-
93338-func (a *A) AddP() int {
93339-	sum := a.newMethod() //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93340-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93341-}
93342-
93343-func (a *A) newMethod() int {
93344-	sum := a.x + a.y
93345-	return sum
93346-}
93347-
93348-func (a A) XLessThanY() bool {
93349-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93350-}
93351-
93352-func (a A) Add() int {
93353-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93354-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93355-}
93356-
93357--- methodextraction_extract_basic_14_2 --
93358-package extract
93359-
93360-type A struct {
93361-	x int
93362-	y int
93363-}
93364-
93365-func (a *A) XLessThanYP() bool {
93366-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93367-}
93368-
93369-func (a *A) AddP() int {
93370-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93371-	return a.newMethod(sum)       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93372-}
93373-
93374-func (*A) newMethod(sum int) int {
93375-	return sum
93376-}
93377-
93378-func (a A) XLessThanY() bool {
93379-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93380-}
93381-
93382-func (a A) Add() int {
93383-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93384-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93385-}
93386-
93387--- methodextraction_extract_basic_18_2 --
93388-package extract
93389-
93390-type A struct {
93391-	x int
93392-	y int
93393-}
93394-
93395-func (a *A) XLessThanYP() bool {
93396-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93397-}
93398-
93399-func (a *A) AddP() int {
93400-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93401-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93402-}
93403-
93404-func (a A) XLessThanY() bool {
93405-	return a.newMethod() //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93406-}
93407-
93408-func (a A) newMethod() bool {
93409-	return a.x < a.y
93410-}
93411-
93412-func (a A) Add() int {
93413-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93414-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93415-}
93416-
93417--- methodextraction_extract_basic_22_2 --
93418-package extract
93419-
93420-type A struct {
93421-	x int
93422-	y int
93423-}
93424-
93425-func (a *A) XLessThanYP() bool {
93426-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93427-}
93428-
93429-func (a *A) AddP() int {
93430-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93431-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93432-}
93433-
93434-func (a A) XLessThanY() bool {
93435-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93436-}
93437-
93438-func (a A) Add() int {
93439-	sum := a.newMethod() //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93440-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93441-}
93442-
93443-func (a A) newMethod() int {
93444-	sum := a.x + a.y
93445-	return sum
93446-}
93447-
93448--- methodextraction_extract_basic_23_2 --
93449-package extract
93450-
93451-type A struct {
93452-	x int
93453-	y int
93454-}
93455-
93456-func (a *A) XLessThanYP() bool {
93457-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93458-}
93459-
93460-func (a *A) AddP() int {
93461-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93462-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93463-}
93464-
93465-func (a A) XLessThanY() bool {
93466-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93467-}
93468-
93469-func (a A) Add() int {
93470-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93471-	return a.newMethod(sum)       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93472-}
93473-
93474-func (A) newMethod(sum int) int {
93475-	return sum
93476-}
93477-
93478--- methodextraction_extract_basic_9_2 --
93479-package extract
93480-
93481-type A struct {
93482-	x int
93483-	y int
93484-}
93485-
93486-func (a *A) XLessThanYP() bool {
93487-	return a.newMethod() //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93488-}
93489-
93490-func (a *A) newMethod() bool {
93491-	return a.x < a.y
93492-}
93493-
93494-func (a *A) AddP() int {
93495-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93496-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93497-}
93498-
93499-func (a A) XLessThanY() bool {
93500-	return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y")
93501-}
93502-
93503-func (a A) Add() int {
93504-	sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y")
93505-	return sum       //@extractmethod("return", "sum"),extractfunc("return", "sum")
93506-}
93507-
93508diff -urN a/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go b/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go
93509--- a/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go	2000-01-01 00:00:00.000000000 -0000
93510+++ b/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go	1970-01-01 00:00:00.000000000 +0000
93511@@ -1,6 +0,0 @@
93512-package extract
93513-
93514-func _() {
93515-	var _ = 1 + 2 //@suggestedfix("1", "refactor.extract", "")
93516-	var _ = 3 + 4 //@suggestedfix("3 + 4", "refactor.extract", "")
93517-}
93518diff -urN a/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go.golden b/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go.golden
93519--- a/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go.golden	2000-01-01 00:00:00.000000000 -0000
93520+++ b/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go.golden	1970-01-01 00:00:00.000000000 +0000
93521@@ -1,18 +0,0 @@
93522--- suggestedfix_extract_basic_lit_4_10 --
93523-package extract
93524-
93525-func _() {
93526-	x := 1
93527-	var _ = x + 2 //@suggestedfix("1", "refactor.extract", "")
93528-	var _ = 3 + 4 //@suggestedfix("3 + 4", "refactor.extract", "")
93529-}
93530-
93531--- suggestedfix_extract_basic_lit_5_10 --
93532-package extract
93533-
93534-func _() {
93535-	var _ = 1 + 2 //@suggestedfix("1", "refactor.extract", "")
93536-	x := 3 + 4
93537-	var _ = x //@suggestedfix("3 + 4", "refactor.extract", "")
93538-}
93539-
93540diff -urN a/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go b/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go
93541--- a/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go	2000-01-01 00:00:00.000000000 -0000
93542+++ b/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go	1970-01-01 00:00:00.000000000 +0000
93543@@ -1,9 +0,0 @@
93544-package extract
93545-
93546-import "strconv"
93547-
93548-func _() {
93549-	x0 := append([]int{}, 1) //@suggestedfix("append([]int{}, 1)", "refactor.extract", "")
93550-	str := "1"
93551-	b, err := strconv.Atoi(str) //@suggestedfix("strconv.Atoi(str)", "refactor.extract", "")
93552-}
93553diff -urN a/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go.golden b/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go.golden
93554--- a/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go.golden	2000-01-01 00:00:00.000000000 -0000
93555+++ b/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go.golden	1970-01-01 00:00:00.000000000 +0000
93556@@ -1,24 +0,0 @@
93557--- suggestedfix_extract_func_call_6_8 --
93558-package extract
93559-
93560-import "strconv"
93561-
93562-func _() {
93563-	x := append([]int{}, 1)
93564-	x0 := x //@suggestedfix("append([]int{}, 1)", "refactor.extract", "")
93565-	str := "1"
93566-	b, err := strconv.Atoi(str) //@suggestedfix("strconv.Atoi(str)", "refactor.extract", "")
93567-}
93568-
93569--- suggestedfix_extract_func_call_8_12 --
93570-package extract
93571-
93572-import "strconv"
93573-
93574-func _() {
93575-	x0 := append([]int{}, 1) //@suggestedfix("append([]int{}, 1)", "refactor.extract", "")
93576-	str := "1"
93577-	x, x1 := strconv.Atoi(str)
93578-	b, err := x, x1 //@suggestedfix("strconv.Atoi(str)", "refactor.extract", "")
93579-}
93580-
93581diff -urN a/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go b/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go
93582--- a/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go	2000-01-01 00:00:00.000000000 -0000
93583+++ b/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go	1970-01-01 00:00:00.000000000 +0000
93584@@ -1,13 +0,0 @@
93585-package extract
93586-
93587-import "go/ast"
93588-
93589-func _() {
93590-	x0 := 0
93591-	if true {
93592-		y := ast.CompositeLit{} //@suggestedfix("ast.CompositeLit{}", "refactor.extract", "")
93593-	}
93594-	if true {
93595-		x1 := !false //@suggestedfix("!false", "refactor.extract", "")
93596-	}
93597-}
93598diff -urN a/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go.golden b/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go.golden
93599--- a/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go.golden	2000-01-01 00:00:00.000000000 -0000
93600+++ b/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go.golden	1970-01-01 00:00:00.000000000 +0000
93601@@ -1,32 +0,0 @@
93602--- suggestedfix_extract_scope_11_9 --
93603-package extract
93604-
93605-import "go/ast"
93606-
93607-func _() {
93608-	x0 := 0
93609-	if true {
93610-		y := ast.CompositeLit{} //@suggestedfix("ast.CompositeLit{}", "refactor.extract", "")
93611-	}
93612-	if true {
93613-		x := !false
93614-		x1 := x //@suggestedfix("!false", "refactor.extract", "")
93615-	}
93616-}
93617-
93618--- suggestedfix_extract_scope_8_8 --
93619-package extract
93620-
93621-import "go/ast"
93622-
93623-func _() {
93624-	x0 := 0
93625-	if true {
93626-		x := ast.CompositeLit{}
93627-		y := x //@suggestedfix("ast.CompositeLit{}", "refactor.extract", "")
93628-	}
93629-	if true {
93630-		x1 := !false //@suggestedfix("!false", "refactor.extract", "")
93631-	}
93632-}
93633-
93634diff -urN a/gopls/internal/lsp/testdata/fieldlist/field_list.go b/gopls/internal/lsp/testdata/fieldlist/field_list.go
93635--- a/gopls/internal/lsp/testdata/fieldlist/field_list.go	2000-01-01 00:00:00.000000000 -0000
93636+++ b/gopls/internal/lsp/testdata/fieldlist/field_list.go	1970-01-01 00:00:00.000000000 +0000
93637@@ -1,27 +0,0 @@
93638-package fieldlist
93639-
93640-var myInt int   //@item(flVar, "myInt", "int", "var")
93641-type myType int //@item(flType, "myType", "int", "type")
93642-
93643-func (my) _()    {} //@complete(") _", flType)
93644-func (my my) _() {} //@complete(" my)"),complete(") _", flType)
93645-
93646-func (myType) _() {} //@complete(") {", flType)
93647-
93648-func (myType) _(my my) {} //@complete(" my)"),complete(") {", flType)
93649-
93650-func (myType) _() my {} //@complete(" {", flType)
93651-
93652-func (myType) _() (my my) {} //@complete(" my"),complete(") {", flType)
93653-
93654-func _() {
93655-	var _ struct {
93656-		//@complete("", flType)
93657-		m my //@complete(" my"),complete(" //", flType)
93658-	}
93659-
93660-	var _ interface {
93661-		//@complete("", flType)
93662-		m() my //@complete("("),complete(" //", flType)
93663-	}
93664-}
93665diff -urN a/gopls/internal/lsp/testdata/fillstruct/a2.go b/gopls/internal/lsp/testdata/fillstruct/a2.go
93666--- a/gopls/internal/lsp/testdata/fillstruct/a2.go	2000-01-01 00:00:00.000000000 -0000
93667+++ b/gopls/internal/lsp/testdata/fillstruct/a2.go	1970-01-01 00:00:00.000000000 +0000
93668@@ -1,29 +0,0 @@
93669-package fillstruct
93670-
93671-type typedStruct struct {
93672-	m  map[string]int
93673-	s  []int
93674-	c  chan int
93675-	c1 <-chan int
93676-	a  [2]string
93677-}
93678-
93679-var _ = typedStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93680-
93681-type funStruct struct {
93682-	fn func(i int) int
93683-}
93684-
93685-var _ = funStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93686-
93687-type funStructCompex struct {
93688-	fn func(i int, s string) (string, int)
93689-}
93690-
93691-var _ = funStructCompex{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93692-
93693-type funStructEmpty struct {
93694-	fn func()
93695-}
93696-
93697-var _ = funStructEmpty{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93698diff -urN a/gopls/internal/lsp/testdata/fillstruct/a2.go.golden b/gopls/internal/lsp/testdata/fillstruct/a2.go.golden
93699--- a/gopls/internal/lsp/testdata/fillstruct/a2.go.golden	2000-01-01 00:00:00.000000000 -0000
93700+++ b/gopls/internal/lsp/testdata/fillstruct/a2.go.golden	1970-01-01 00:00:00.000000000 +0000
93701@@ -1,139 +0,0 @@
93702--- suggestedfix_a2_11_21 --
93703-package fillstruct
93704-
93705-type typedStruct struct {
93706-	m  map[string]int
93707-	s  []int
93708-	c  chan int
93709-	c1 <-chan int
93710-	a  [2]string
93711-}
93712-
93713-var _ = typedStruct{
93714-	m:  map[string]int{},
93715-	s:  []int{},
93716-	c:  make(chan int),
93717-	c1: make(<-chan int),
93718-	a:  [2]string{},
93719-} //@suggestedfix("}", "refactor.rewrite", "Fill")
93720-
93721-type funStruct struct {
93722-	fn func(i int) int
93723-}
93724-
93725-var _ = funStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93726-
93727-type funStructCompex struct {
93728-	fn func(i int, s string) (string, int)
93729-}
93730-
93731-var _ = funStructCompex{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93732-
93733-type funStructEmpty struct {
93734-	fn func()
93735-}
93736-
93737-var _ = funStructEmpty{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93738-
93739--- suggestedfix_a2_17_19 --
93740-package fillstruct
93741-
93742-type typedStruct struct {
93743-	m  map[string]int
93744-	s  []int
93745-	c  chan int
93746-	c1 <-chan int
93747-	a  [2]string
93748-}
93749-
93750-var _ = typedStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93751-
93752-type funStruct struct {
93753-	fn func(i int) int
93754-}
93755-
93756-var _ = funStruct{
93757-	fn: func(i int) int {
93758-	},
93759-} //@suggestedfix("}", "refactor.rewrite", "Fill")
93760-
93761-type funStructCompex struct {
93762-	fn func(i int, s string) (string, int)
93763-}
93764-
93765-var _ = funStructCompex{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93766-
93767-type funStructEmpty struct {
93768-	fn func()
93769-}
93770-
93771-var _ = funStructEmpty{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93772-
93773--- suggestedfix_a2_23_25 --
93774-package fillstruct
93775-
93776-type typedStruct struct {
93777-	m  map[string]int
93778-	s  []int
93779-	c  chan int
93780-	c1 <-chan int
93781-	a  [2]string
93782-}
93783-
93784-var _ = typedStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93785-
93786-type funStruct struct {
93787-	fn func(i int) int
93788-}
93789-
93790-var _ = funStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93791-
93792-type funStructCompex struct {
93793-	fn func(i int, s string) (string, int)
93794-}
93795-
93796-var _ = funStructCompex{
93797-	fn: func(i int, s string) (string, int) {
93798-	},
93799-} //@suggestedfix("}", "refactor.rewrite", "Fill")
93800-
93801-type funStructEmpty struct {
93802-	fn func()
93803-}
93804-
93805-var _ = funStructEmpty{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93806-
93807--- suggestedfix_a2_29_24 --
93808-package fillstruct
93809-
93810-type typedStruct struct {
93811-	m  map[string]int
93812-	s  []int
93813-	c  chan int
93814-	c1 <-chan int
93815-	a  [2]string
93816-}
93817-
93818-var _ = typedStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93819-
93820-type funStruct struct {
93821-	fn func(i int) int
93822-}
93823-
93824-var _ = funStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93825-
93826-type funStructCompex struct {
93827-	fn func(i int, s string) (string, int)
93828-}
93829-
93830-var _ = funStructCompex{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93831-
93832-type funStructEmpty struct {
93833-	fn func()
93834-}
93835-
93836-var _ = funStructEmpty{
93837-	fn: func() {
93838-	},
93839-} //@suggestedfix("}", "refactor.rewrite", "Fill")
93840-
93841diff -urN a/gopls/internal/lsp/testdata/fillstruct/a3.go b/gopls/internal/lsp/testdata/fillstruct/a3.go
93842--- a/gopls/internal/lsp/testdata/fillstruct/a3.go	2000-01-01 00:00:00.000000000 -0000
93843+++ b/gopls/internal/lsp/testdata/fillstruct/a3.go	1970-01-01 00:00:00.000000000 +0000
93844@@ -1,42 +0,0 @@
93845-package fillstruct
93846-
93847-import (
93848-	"go/ast"
93849-	"go/token"
93850-)
93851-
93852-type Foo struct {
93853-	A int
93854-}
93855-
93856-type Bar struct {
93857-	X *Foo
93858-	Y *Foo
93859-}
93860-
93861-var _ = Bar{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93862-
93863-type importedStruct struct {
93864-	m  map[*ast.CompositeLit]ast.Field
93865-	s  []ast.BadExpr
93866-	a  [3]token.Token
93867-	c  chan ast.EmptyStmt
93868-	fn func(ast_decl ast.DeclStmt) ast.Ellipsis
93869-	st ast.CompositeLit
93870-}
93871-
93872-var _ = importedStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93873-
93874-type pointerBuiltinStruct struct {
93875-	b *bool
93876-	s *string
93877-	i *int
93878-}
93879-
93880-var _ = pointerBuiltinStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93881-
93882-var _ = []ast.BasicLit{
93883-	{}, //@suggestedfix("}", "refactor.rewrite", "Fill")
93884-}
93885-
93886-var _ = []ast.BasicLit{{}} //@suggestedfix("}", "refactor.rewrite", "Fill")
93887diff -urN a/gopls/internal/lsp/testdata/fillstruct/a3.go.golden b/gopls/internal/lsp/testdata/fillstruct/a3.go.golden
93888--- a/gopls/internal/lsp/testdata/fillstruct/a3.go.golden	2000-01-01 00:00:00.000000000 -0000
93889+++ b/gopls/internal/lsp/testdata/fillstruct/a3.go.golden	1970-01-01 00:00:00.000000000 +0000
93890@@ -1,243 +0,0 @@
93891--- suggestedfix_a3_17_13 --
93892-package fillstruct
93893-
93894-import (
93895-	"go/ast"
93896-	"go/token"
93897-)
93898-
93899-type Foo struct {
93900-	A int
93901-}
93902-
93903-type Bar struct {
93904-	X *Foo
93905-	Y *Foo
93906-}
93907-
93908-var _ = Bar{
93909-	X: &Foo{},
93910-	Y: &Foo{},
93911-} //@suggestedfix("}", "refactor.rewrite", "Fill")
93912-
93913-type importedStruct struct {
93914-	m  map[*ast.CompositeLit]ast.Field
93915-	s  []ast.BadExpr
93916-	a  [3]token.Token
93917-	c  chan ast.EmptyStmt
93918-	fn func(ast_decl ast.DeclStmt) ast.Ellipsis
93919-	st ast.CompositeLit
93920-}
93921-
93922-var _ = importedStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93923-
93924-type pointerBuiltinStruct struct {
93925-	b *bool
93926-	s *string
93927-	i *int
93928-}
93929-
93930-var _ = pointerBuiltinStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93931-
93932-var _ = []ast.BasicLit{
93933-	{}, //@suggestedfix("}", "refactor.rewrite", "Fill")
93934-}
93935-
93936-var _ = []ast.BasicLit{{}} //@suggestedfix("}", "refactor.rewrite", "Fill")
93937-
93938--- suggestedfix_a3_28_24 --
93939-package fillstruct
93940-
93941-import (
93942-	"go/ast"
93943-	"go/token"
93944-)
93945-
93946-type Foo struct {
93947-	A int
93948-}
93949-
93950-type Bar struct {
93951-	X *Foo
93952-	Y *Foo
93953-}
93954-
93955-var _ = Bar{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93956-
93957-type importedStruct struct {
93958-	m  map[*ast.CompositeLit]ast.Field
93959-	s  []ast.BadExpr
93960-	a  [3]token.Token
93961-	c  chan ast.EmptyStmt
93962-	fn func(ast_decl ast.DeclStmt) ast.Ellipsis
93963-	st ast.CompositeLit
93964-}
93965-
93966-var _ = importedStruct{
93967-	m: map[*ast.CompositeLit]ast.Field{},
93968-	s: []ast.BadExpr{},
93969-	a: [3]token.Token{},
93970-	c: make(chan ast.EmptyStmt),
93971-	fn: func(ast_decl ast.DeclStmt) ast.Ellipsis {
93972-	},
93973-	st: ast.CompositeLit{},
93974-} //@suggestedfix("}", "refactor.rewrite", "Fill")
93975-
93976-type pointerBuiltinStruct struct {
93977-	b *bool
93978-	s *string
93979-	i *int
93980-}
93981-
93982-var _ = pointerBuiltinStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
93983-
93984-var _ = []ast.BasicLit{
93985-	{}, //@suggestedfix("}", "refactor.rewrite", "Fill")
93986-}
93987-
93988-var _ = []ast.BasicLit{{}} //@suggestedfix("}", "refactor.rewrite", "Fill")
93989-
93990--- suggestedfix_a3_36_30 --
93991-package fillstruct
93992-
93993-import (
93994-	"go/ast"
93995-	"go/token"
93996-)
93997-
93998-type Foo struct {
93999-	A int
94000-}
94001-
94002-type Bar struct {
94003-	X *Foo
94004-	Y *Foo
94005-}
94006-
94007-var _ = Bar{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94008-
94009-type importedStruct struct {
94010-	m  map[*ast.CompositeLit]ast.Field
94011-	s  []ast.BadExpr
94012-	a  [3]token.Token
94013-	c  chan ast.EmptyStmt
94014-	fn func(ast_decl ast.DeclStmt) ast.Ellipsis
94015-	st ast.CompositeLit
94016-}
94017-
94018-var _ = importedStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94019-
94020-type pointerBuiltinStruct struct {
94021-	b *bool
94022-	s *string
94023-	i *int
94024-}
94025-
94026-var _ = pointerBuiltinStruct{
94027-	b: new(bool),
94028-	s: new(string),
94029-	i: new(int),
94030-} //@suggestedfix("}", "refactor.rewrite", "Fill")
94031-
94032-var _ = []ast.BasicLit{
94033-	{}, //@suggestedfix("}", "refactor.rewrite", "Fill")
94034-}
94035-
94036-var _ = []ast.BasicLit{{}} //@suggestedfix("}", "refactor.rewrite", "Fill")
94037-
94038--- suggestedfix_a3_39_3 --
94039-package fillstruct
94040-
94041-import (
94042-	"go/ast"
94043-	"go/token"
94044-)
94045-
94046-type Foo struct {
94047-	A int
94048-}
94049-
94050-type Bar struct {
94051-	X *Foo
94052-	Y *Foo
94053-}
94054-
94055-var _ = Bar{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94056-
94057-type importedStruct struct {
94058-	m  map[*ast.CompositeLit]ast.Field
94059-	s  []ast.BadExpr
94060-	a  [3]token.Token
94061-	c  chan ast.EmptyStmt
94062-	fn func(ast_decl ast.DeclStmt) ast.Ellipsis
94063-	st ast.CompositeLit
94064-}
94065-
94066-var _ = importedStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94067-
94068-type pointerBuiltinStruct struct {
94069-	b *bool
94070-	s *string
94071-	i *int
94072-}
94073-
94074-var _ = pointerBuiltinStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94075-
94076-var _ = []ast.BasicLit{
94077-	{
94078-		ValuePos: 0,
94079-		Kind:     0,
94080-		Value:    "",
94081-	}, //@suggestedfix("}", "refactor.rewrite", "Fill")
94082-}
94083-
94084-var _ = []ast.BasicLit{{}} //@suggestedfix("}", "refactor.rewrite", "Fill")
94085-
94086--- suggestedfix_a3_42_25 --
94087-package fillstruct
94088-
94089-import (
94090-	"go/ast"
94091-	"go/token"
94092-)
94093-
94094-type Foo struct {
94095-	A int
94096-}
94097-
94098-type Bar struct {
94099-	X *Foo
94100-	Y *Foo
94101-}
94102-
94103-var _ = Bar{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94104-
94105-type importedStruct struct {
94106-	m  map[*ast.CompositeLit]ast.Field
94107-	s  []ast.BadExpr
94108-	a  [3]token.Token
94109-	c  chan ast.EmptyStmt
94110-	fn func(ast_decl ast.DeclStmt) ast.Ellipsis
94111-	st ast.CompositeLit
94112-}
94113-
94114-var _ = importedStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94115-
94116-type pointerBuiltinStruct struct {
94117-	b *bool
94118-	s *string
94119-	i *int
94120-}
94121-
94122-var _ = pointerBuiltinStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94123-
94124-var _ = []ast.BasicLit{
94125-	{}, //@suggestedfix("}", "refactor.rewrite", "Fill")
94126-}
94127-
94128-var _ = []ast.BasicLit{{
94129-	ValuePos: 0,
94130-	Kind:     0,
94131-	Value:    "",
94132-}} //@suggestedfix("}", "refactor.rewrite", "Fill")
94133-
94134diff -urN a/gopls/internal/lsp/testdata/fillstruct/a4.go b/gopls/internal/lsp/testdata/fillstruct/a4.go
94135--- a/gopls/internal/lsp/testdata/fillstruct/a4.go	2000-01-01 00:00:00.000000000 -0000
94136+++ b/gopls/internal/lsp/testdata/fillstruct/a4.go	1970-01-01 00:00:00.000000000 +0000
94137@@ -1,39 +0,0 @@
94138-package fillstruct
94139-
94140-import "go/ast"
94141-
94142-type iStruct struct {
94143-	X int
94144-}
94145-
94146-type sStruct struct {
94147-	str string
94148-}
94149-
94150-type multiFill struct {
94151-	num   int
94152-	strin string
94153-	arr   []int
94154-}
94155-
94156-type assignStruct struct {
94157-	n ast.Node
94158-}
94159-
94160-func fill() {
94161-	var x int
94162-	var _ = iStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94163-
94164-	var s string
94165-	var _ = sStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94166-
94167-	var n int
94168-	_ = []int{}
94169-	if true {
94170-		arr := []int{1, 2}
94171-	}
94172-	var _ = multiFill{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94173-
94174-	var node *ast.CompositeLit
94175-	var _ = assignStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94176-}
94177diff -urN a/gopls/internal/lsp/testdata/fillstruct/a4.go.golden b/gopls/internal/lsp/testdata/fillstruct/a4.go.golden
94178--- a/gopls/internal/lsp/testdata/fillstruct/a4.go.golden	2000-01-01 00:00:00.000000000 -0000
94179+++ b/gopls/internal/lsp/testdata/fillstruct/a4.go.golden	1970-01-01 00:00:00.000000000 +0000
94180@@ -1,174 +0,0 @@
94181--- suggestedfix_a4_25_18 --
94182-package fillstruct
94183-
94184-import "go/ast"
94185-
94186-type iStruct struct {
94187-	X int
94188-}
94189-
94190-type sStruct struct {
94191-	str string
94192-}
94193-
94194-type multiFill struct {
94195-	num   int
94196-	strin string
94197-	arr   []int
94198-}
94199-
94200-type assignStruct struct {
94201-	n ast.Node
94202-}
94203-
94204-func fill() {
94205-	var x int
94206-	var _ = iStruct{
94207-		X: x,
94208-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94209-
94210-	var s string
94211-	var _ = sStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94212-
94213-	var n int
94214-	_ = []int{}
94215-	if true {
94216-		arr := []int{1, 2}
94217-	}
94218-	var _ = multiFill{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94219-
94220-	var node *ast.CompositeLit
94221-	var _ = assignStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94222-}
94223-
94224--- suggestedfix_a4_28_18 --
94225-package fillstruct
94226-
94227-import "go/ast"
94228-
94229-type iStruct struct {
94230-	X int
94231-}
94232-
94233-type sStruct struct {
94234-	str string
94235-}
94236-
94237-type multiFill struct {
94238-	num   int
94239-	strin string
94240-	arr   []int
94241-}
94242-
94243-type assignStruct struct {
94244-	n ast.Node
94245-}
94246-
94247-func fill() {
94248-	var x int
94249-	var _ = iStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94250-
94251-	var s string
94252-	var _ = sStruct{
94253-		str: s,
94254-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94255-
94256-	var n int
94257-	_ = []int{}
94258-	if true {
94259-		arr := []int{1, 2}
94260-	}
94261-	var _ = multiFill{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94262-
94263-	var node *ast.CompositeLit
94264-	var _ = assignStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94265-}
94266-
94267--- suggestedfix_a4_35_20 --
94268-package fillstruct
94269-
94270-import "go/ast"
94271-
94272-type iStruct struct {
94273-	X int
94274-}
94275-
94276-type sStruct struct {
94277-	str string
94278-}
94279-
94280-type multiFill struct {
94281-	num   int
94282-	strin string
94283-	arr   []int
94284-}
94285-
94286-type assignStruct struct {
94287-	n ast.Node
94288-}
94289-
94290-func fill() {
94291-	var x int
94292-	var _ = iStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94293-
94294-	var s string
94295-	var _ = sStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94296-
94297-	var n int
94298-	_ = []int{}
94299-	if true {
94300-		arr := []int{1, 2}
94301-	}
94302-	var _ = multiFill{
94303-		num:   n,
94304-		strin: s,
94305-		arr:   []int{},
94306-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94307-
94308-	var node *ast.CompositeLit
94309-	var _ = assignStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94310-}
94311-
94312--- suggestedfix_a4_38_23 --
94313-package fillstruct
94314-
94315-import "go/ast"
94316-
94317-type iStruct struct {
94318-	X int
94319-}
94320-
94321-type sStruct struct {
94322-	str string
94323-}
94324-
94325-type multiFill struct {
94326-	num   int
94327-	strin string
94328-	arr   []int
94329-}
94330-
94331-type assignStruct struct {
94332-	n ast.Node
94333-}
94334-
94335-func fill() {
94336-	var x int
94337-	var _ = iStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94338-
94339-	var s string
94340-	var _ = sStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94341-
94342-	var n int
94343-	_ = []int{}
94344-	if true {
94345-		arr := []int{1, 2}
94346-	}
94347-	var _ = multiFill{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94348-
94349-	var node *ast.CompositeLit
94350-	var _ = assignStruct{
94351-		n: node,
94352-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94353-}
94354-
94355diff -urN a/gopls/internal/lsp/testdata/fillstruct/a.go b/gopls/internal/lsp/testdata/fillstruct/a.go
94356--- a/gopls/internal/lsp/testdata/fillstruct/a.go	2000-01-01 00:00:00.000000000 -0000
94357+++ b/gopls/internal/lsp/testdata/fillstruct/a.go	1970-01-01 00:00:00.000000000 +0000
94358@@ -1,27 +0,0 @@
94359-package fillstruct
94360-
94361-import (
94362-	"golang.org/lsptests/fillstruct/data"
94363-)
94364-
94365-type basicStruct struct {
94366-	foo int
94367-}
94368-
94369-var _ = basicStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94370-
94371-type twoArgStruct struct {
94372-	foo int
94373-	bar string
94374-}
94375-
94376-var _ = twoArgStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94377-
94378-type nestedStruct struct {
94379-	bar   string
94380-	basic basicStruct
94381-}
94382-
94383-var _ = nestedStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94384-
94385-var _ = data.B{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94386diff -urN a/gopls/internal/lsp/testdata/fillstruct/a.go.golden b/gopls/internal/lsp/testdata/fillstruct/a.go.golden
94387--- a/gopls/internal/lsp/testdata/fillstruct/a.go.golden	2000-01-01 00:00:00.000000000 -0000
94388+++ b/gopls/internal/lsp/testdata/fillstruct/a.go.golden	1970-01-01 00:00:00.000000000 +0000
94389@@ -1,126 +0,0 @@
94390--- suggestedfix_a_11_21 --
94391-package fillstruct
94392-
94393-import (
94394-	"golang.org/lsptests/fillstruct/data"
94395-)
94396-
94397-type basicStruct struct {
94398-	foo int
94399-}
94400-
94401-var _ = basicStruct{
94402-	foo: 0,
94403-} //@suggestedfix("}", "refactor.rewrite", "Fill")
94404-
94405-type twoArgStruct struct {
94406-	foo int
94407-	bar string
94408-}
94409-
94410-var _ = twoArgStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94411-
94412-type nestedStruct struct {
94413-	bar   string
94414-	basic basicStruct
94415-}
94416-
94417-var _ = nestedStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94418-
94419-var _ = data.B{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94420-
94421--- suggestedfix_a_18_22 --
94422-package fillstruct
94423-
94424-import (
94425-	"golang.org/lsptests/fillstruct/data"
94426-)
94427-
94428-type basicStruct struct {
94429-	foo int
94430-}
94431-
94432-var _ = basicStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94433-
94434-type twoArgStruct struct {
94435-	foo int
94436-	bar string
94437-}
94438-
94439-var _ = twoArgStruct{
94440-	foo: 0,
94441-	bar: "",
94442-} //@suggestedfix("}", "refactor.rewrite", "Fill")
94443-
94444-type nestedStruct struct {
94445-	bar   string
94446-	basic basicStruct
94447-}
94448-
94449-var _ = nestedStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94450-
94451-var _ = data.B{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94452-
94453--- suggestedfix_a_25_22 --
94454-package fillstruct
94455-
94456-import (
94457-	"golang.org/lsptests/fillstruct/data"
94458-)
94459-
94460-type basicStruct struct {
94461-	foo int
94462-}
94463-
94464-var _ = basicStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94465-
94466-type twoArgStruct struct {
94467-	foo int
94468-	bar string
94469-}
94470-
94471-var _ = twoArgStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94472-
94473-type nestedStruct struct {
94474-	bar   string
94475-	basic basicStruct
94476-}
94477-
94478-var _ = nestedStruct{
94479-	bar:   "",
94480-	basic: basicStruct{},
94481-} //@suggestedfix("}", "refactor.rewrite", "Fill")
94482-
94483-var _ = data.B{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94484-
94485--- suggestedfix_a_27_16 --
94486-package fillstruct
94487-
94488-import (
94489-	"golang.org/lsptests/fillstruct/data"
94490-)
94491-
94492-type basicStruct struct {
94493-	foo int
94494-}
94495-
94496-var _ = basicStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94497-
94498-type twoArgStruct struct {
94499-	foo int
94500-	bar string
94501-}
94502-
94503-var _ = twoArgStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94504-
94505-type nestedStruct struct {
94506-	bar   string
94507-	basic basicStruct
94508-}
94509-
94510-var _ = nestedStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94511-
94512-var _ = data.B{
94513-	ExportedInt: 0,
94514-} //@suggestedfix("}", "refactor.rewrite", "Fill")
94515-
94516diff -urN a/gopls/internal/lsp/testdata/fillstruct/data/a.go b/gopls/internal/lsp/testdata/fillstruct/data/a.go
94517--- a/gopls/internal/lsp/testdata/fillstruct/data/a.go	2000-01-01 00:00:00.000000000 -0000
94518+++ b/gopls/internal/lsp/testdata/fillstruct/data/a.go	1970-01-01 00:00:00.000000000 +0000
94519@@ -1,6 +0,0 @@
94520-package data
94521-
94522-type B struct {
94523-	ExportedInt   int
94524-	unexportedInt int
94525-}
94526diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct_anon.go b/gopls/internal/lsp/testdata/fillstruct/fill_struct_anon.go
94527--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct_anon.go	2000-01-01 00:00:00.000000000 -0000
94528+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct_anon.go	1970-01-01 00:00:00.000000000 +0000
94529@@ -1,14 +0,0 @@
94530-package fillstruct
94531-
94532-type StructAnon struct {
94533-	a struct{}
94534-	b map[string]interface{}
94535-	c map[string]struct {
94536-		d int
94537-		e bool
94538-	}
94539-}
94540-
94541-func fill() {
94542-	_ := StructAnon{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94543-}
94544diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct_anon.go.golden b/gopls/internal/lsp/testdata/fillstruct/fill_struct_anon.go.golden
94545--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct_anon.go.golden	2000-01-01 00:00:00.000000000 -0000
94546+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct_anon.go.golden	1970-01-01 00:00:00.000000000 +0000
94547@@ -1,20 +0,0 @@
94548--- suggestedfix_fill_struct_anon_13_18 --
94549-package fillstruct
94550-
94551-type StructAnon struct {
94552-	a struct{}
94553-	b map[string]interface{}
94554-	c map[string]struct {
94555-		d int
94556-		e bool
94557-	}
94558-}
94559-
94560-func fill() {
94561-	_ := StructAnon{
94562-		a: struct{}{},
94563-		b: map[string]interface{}{},
94564-		c: map[string]struct{d int; e bool}{},
94565-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94566-}
94567-
94568diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct.go b/gopls/internal/lsp/testdata/fillstruct/fill_struct.go
94569--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct.go	2000-01-01 00:00:00.000000000 -0000
94570+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct.go	1970-01-01 00:00:00.000000000 +0000
94571@@ -1,26 +0,0 @@
94572-package fillstruct
94573-
94574-type StructA struct {
94575-	unexportedIntField int
94576-	ExportedIntField   int
94577-	MapA               map[int]string
94578-	Array              []int
94579-	StructB
94580-}
94581-
94582-type StructA2 struct {
94583-	B *StructB
94584-}
94585-
94586-type StructA3 struct {
94587-	B StructB
94588-}
94589-
94590-func fill() {
94591-	a := StructA{}  //@suggestedfix("}", "refactor.rewrite", "Fill")
94592-	b := StructA2{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94593-	c := StructA3{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94594-	if true {
94595-		_ = StructA3{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94596-	}
94597-}
94598diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct.go.golden b/gopls/internal/lsp/testdata/fillstruct/fill_struct.go.golden
94599--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct.go.golden	2000-01-01 00:00:00.000000000 -0000
94600+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct.go.golden	1970-01-01 00:00:00.000000000 +0000
94601@@ -1,124 +0,0 @@
94602--- suggestedfix_fill_struct_20_15 --
94603-package fillstruct
94604-
94605-type StructA struct {
94606-	unexportedIntField int
94607-	ExportedIntField   int
94608-	MapA               map[int]string
94609-	Array              []int
94610-	StructB
94611-}
94612-
94613-type StructA2 struct {
94614-	B *StructB
94615-}
94616-
94617-type StructA3 struct {
94618-	B StructB
94619-}
94620-
94621-func fill() {
94622-	a := StructA{
94623-		unexportedIntField: 0,
94624-		ExportedIntField:   0,
94625-		MapA:               map[int]string{},
94626-		Array:              []int{},
94627-		StructB:            StructB{},
94628-	}  //@suggestedfix("}", "refactor.rewrite", "Fill")
94629-	b := StructA2{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94630-	c := StructA3{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94631-	if true {
94632-		_ = StructA3{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94633-	}
94634-}
94635-
94636--- suggestedfix_fill_struct_21_16 --
94637-package fillstruct
94638-
94639-type StructA struct {
94640-	unexportedIntField int
94641-	ExportedIntField   int
94642-	MapA               map[int]string
94643-	Array              []int
94644-	StructB
94645-}
94646-
94647-type StructA2 struct {
94648-	B *StructB
94649-}
94650-
94651-type StructA3 struct {
94652-	B StructB
94653-}
94654-
94655-func fill() {
94656-	a := StructA{}  //@suggestedfix("}", "refactor.rewrite", "Fill")
94657-	b := StructA2{
94658-		B: &StructB{},
94659-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94660-	c := StructA3{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94661-	if true {
94662-		_ = StructA3{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94663-	}
94664-}
94665-
94666--- suggestedfix_fill_struct_22_16 --
94667-package fillstruct
94668-
94669-type StructA struct {
94670-	unexportedIntField int
94671-	ExportedIntField   int
94672-	MapA               map[int]string
94673-	Array              []int
94674-	StructB
94675-}
94676-
94677-type StructA2 struct {
94678-	B *StructB
94679-}
94680-
94681-type StructA3 struct {
94682-	B StructB
94683-}
94684-
94685-func fill() {
94686-	a := StructA{}  //@suggestedfix("}", "refactor.rewrite", "Fill")
94687-	b := StructA2{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94688-	c := StructA3{
94689-		B: StructB{},
94690-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94691-	if true {
94692-		_ = StructA3{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94693-	}
94694-}
94695-
94696--- suggestedfix_fill_struct_24_16 --
94697-package fillstruct
94698-
94699-type StructA struct {
94700-	unexportedIntField int
94701-	ExportedIntField   int
94702-	MapA               map[int]string
94703-	Array              []int
94704-	StructB
94705-}
94706-
94707-type StructA2 struct {
94708-	B *StructB
94709-}
94710-
94711-type StructA3 struct {
94712-	B StructB
94713-}
94714-
94715-func fill() {
94716-	a := StructA{}  //@suggestedfix("}", "refactor.rewrite", "Fill")
94717-	b := StructA2{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94718-	c := StructA3{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94719-	if true {
94720-		_ = StructA3{
94721-			B: StructB{},
94722-		} //@suggestedfix("}", "refactor.rewrite", "Fill")
94723-	}
94724-}
94725-
94726diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct_nested.go b/gopls/internal/lsp/testdata/fillstruct/fill_struct_nested.go
94727--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct_nested.go	2000-01-01 00:00:00.000000000 -0000
94728+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct_nested.go	1970-01-01 00:00:00.000000000 +0000
94729@@ -1,15 +0,0 @@
94730-package fillstruct
94731-
94732-type StructB struct {
94733-	StructC
94734-}
94735-
94736-type StructC struct {
94737-	unexportedInt int
94738-}
94739-
94740-func nested() {
94741-	c := StructB{
94742-		StructC: StructC{}, //@suggestedfix("}", "refactor.rewrite", "Fill")
94743-	}
94744-}
94745diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct_nested.go.golden b/gopls/internal/lsp/testdata/fillstruct/fill_struct_nested.go.golden
94746--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct_nested.go.golden	2000-01-01 00:00:00.000000000 -0000
94747+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct_nested.go.golden	1970-01-01 00:00:00.000000000 +0000
94748@@ -1,19 +0,0 @@
94749--- suggestedfix_fill_struct_nested_13_20 --
94750-package fillstruct
94751-
94752-type StructB struct {
94753-	StructC
94754-}
94755-
94756-type StructC struct {
94757-	unexportedInt int
94758-}
94759-
94760-func nested() {
94761-	c := StructB{
94762-		StructC: StructC{
94763-			unexportedInt: 0,
94764-		}, //@suggestedfix("}", "refactor.rewrite", "Fill")
94765-	}
94766-}
94767-
94768diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct_package.go b/gopls/internal/lsp/testdata/fillstruct/fill_struct_package.go
94769--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct_package.go	2000-01-01 00:00:00.000000000 -0000
94770+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct_package.go	1970-01-01 00:00:00.000000000 +0000
94771@@ -1,12 +0,0 @@
94772-package fillstruct
94773-
94774-import (
94775-	h2 "net/http"
94776-
94777-	"golang.org/lsptests/fillstruct/data"
94778-)
94779-
94780-func unexported() {
94781-	a := data.B{}   //@suggestedfix("}", "refactor.rewrite", "Fill")
94782-	_ = h2.Client{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94783-}
94784diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct_package.go.golden b/gopls/internal/lsp/testdata/fillstruct/fill_struct_package.go.golden
94785--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct_package.go.golden	2000-01-01 00:00:00.000000000 -0000
94786+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct_package.go.golden	1970-01-01 00:00:00.000000000 +0000
94787@@ -1,36 +0,0 @@
94788--- suggestedfix_fill_struct_package_10_14 --
94789-package fillstruct
94790-
94791-import (
94792-	h2 "net/http"
94793-
94794-	"golang.org/lsptests/fillstruct/data"
94795-)
94796-
94797-func unexported() {
94798-	a := data.B{
94799-		ExportedInt: 0,
94800-	}   //@suggestedfix("}", "refactor.rewrite", "Fill")
94801-	_ = h2.Client{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94802-}
94803-
94804--- suggestedfix_fill_struct_package_11_16 --
94805-package fillstruct
94806-
94807-import (
94808-	h2 "net/http"
94809-
94810-	"golang.org/lsptests/fillstruct/data"
94811-)
94812-
94813-func unexported() {
94814-	a := data.B{}   //@suggestedfix("}", "refactor.rewrite", "Fill")
94815-	_ = h2.Client{
94816-		Transport: nil,
94817-		CheckRedirect: func(req *h2.Request, via []*h2.Request) error {
94818-		},
94819-		Jar:     nil,
94820-		Timeout: 0,
94821-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94822-}
94823-
94824diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct_partial.go b/gopls/internal/lsp/testdata/fillstruct/fill_struct_partial.go
94825--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct_partial.go	2000-01-01 00:00:00.000000000 -0000
94826+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct_partial.go	1970-01-01 00:00:00.000000000 +0000
94827@@ -1,24 +0,0 @@
94828-package fillstruct
94829-
94830-type StructPartialA struct {
94831-	PrefilledInt int
94832-	UnfilledInt  int
94833-	StructPartialB
94834-}
94835-
94836-type StructPartialB struct {
94837-	PrefilledInt int
94838-	UnfilledInt  int
94839-}
94840-
94841-func fill() {
94842-	a := StructPartialA{
94843-		PrefilledInt: 5,
94844-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94845-	b := StructPartialB{
94846-		/* this comment should disappear */
94847-		PrefilledInt: 7, // This comment should be blown away.
94848-		/* As should
94849-		this one */
94850-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94851-}
94852diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct_partial.go.golden b/gopls/internal/lsp/testdata/fillstruct/fill_struct_partial.go.golden
94853--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct_partial.go.golden	2000-01-01 00:00:00.000000000 -0000
94854+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct_partial.go.golden	1970-01-01 00:00:00.000000000 +0000
94855@@ -1,52 +0,0 @@
94856--- suggestedfix_fill_struct_partial_17_2 --
94857-package fillstruct
94858-
94859-type StructPartialA struct {
94860-	PrefilledInt int
94861-	UnfilledInt  int
94862-	StructPartialB
94863-}
94864-
94865-type StructPartialB struct {
94866-	PrefilledInt int
94867-	UnfilledInt  int
94868-}
94869-
94870-func fill() {
94871-	a := StructPartialA{
94872-		PrefilledInt:   5,
94873-		UnfilledInt:    0,
94874-		StructPartialB: StructPartialB{},
94875-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94876-	b := StructPartialB{
94877-		/* this comment should disappear */
94878-		PrefilledInt: 7, // This comment should be blown away.
94879-		/* As should
94880-		this one */
94881-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94882-}
94883-
94884--- suggestedfix_fill_struct_partial_23_2 --
94885-package fillstruct
94886-
94887-type StructPartialA struct {
94888-	PrefilledInt int
94889-	UnfilledInt  int
94890-	StructPartialB
94891-}
94892-
94893-type StructPartialB struct {
94894-	PrefilledInt int
94895-	UnfilledInt  int
94896-}
94897-
94898-func fill() {
94899-	a := StructPartialA{
94900-		PrefilledInt: 5,
94901-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94902-	b := StructPartialB{
94903-		PrefilledInt: 7,
94904-		UnfilledInt:  0,
94905-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94906-}
94907-
94908diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct_spaces.go b/gopls/internal/lsp/testdata/fillstruct/fill_struct_spaces.go
94909--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct_spaces.go	2000-01-01 00:00:00.000000000 -0000
94910+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct_spaces.go	1970-01-01 00:00:00.000000000 +0000
94911@@ -1,9 +0,0 @@
94912-package fillstruct
94913-
94914-type StructD struct {
94915-	ExportedIntField int
94916-}
94917-
94918-func spaces() {
94919-	d := StructD{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94920-}
94921diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct_spaces.go.golden b/gopls/internal/lsp/testdata/fillstruct/fill_struct_spaces.go.golden
94922--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct_spaces.go.golden	2000-01-01 00:00:00.000000000 -0000
94923+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct_spaces.go.golden	1970-01-01 00:00:00.000000000 +0000
94924@@ -1,13 +0,0 @@
94925--- suggestedfix_fill_struct_spaces_8_15 --
94926-package fillstruct
94927-
94928-type StructD struct {
94929-	ExportedIntField int
94930-}
94931-
94932-func spaces() {
94933-	d := StructD{
94934-		ExportedIntField: 0,
94935-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94936-}
94937-
94938diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct_unsafe.go b/gopls/internal/lsp/testdata/fillstruct/fill_struct_unsafe.go
94939--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct_unsafe.go	2000-01-01 00:00:00.000000000 -0000
94940+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct_unsafe.go	1970-01-01 00:00:00.000000000 +0000
94941@@ -1,12 +0,0 @@
94942-package fillstruct
94943-
94944-import "unsafe"
94945-
94946-type unsafeStruct struct {
94947-	x int
94948-	p unsafe.Pointer
94949-}
94950-
94951-func fill() {
94952-	_ := unsafeStruct{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94953-}
94954diff -urN a/gopls/internal/lsp/testdata/fillstruct/fill_struct_unsafe.go.golden b/gopls/internal/lsp/testdata/fillstruct/fill_struct_unsafe.go.golden
94955--- a/gopls/internal/lsp/testdata/fillstruct/fill_struct_unsafe.go.golden	2000-01-01 00:00:00.000000000 -0000
94956+++ b/gopls/internal/lsp/testdata/fillstruct/fill_struct_unsafe.go.golden	1970-01-01 00:00:00.000000000 +0000
94957@@ -1,17 +0,0 @@
94958--- suggestedfix_fill_struct_unsafe_11_20 --
94959-package fillstruct
94960-
94961-import "unsafe"
94962-
94963-type unsafeStruct struct {
94964-	x int
94965-	p unsafe.Pointer
94966-}
94967-
94968-func fill() {
94969-	_ := unsafeStruct{
94970-		x: 0,
94971-		p: nil,
94972-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
94973-}
94974-
94975diff -urN a/gopls/internal/lsp/testdata/fillstruct/typeparams.go b/gopls/internal/lsp/testdata/fillstruct/typeparams.go
94976--- a/gopls/internal/lsp/testdata/fillstruct/typeparams.go	2000-01-01 00:00:00.000000000 -0000
94977+++ b/gopls/internal/lsp/testdata/fillstruct/typeparams.go	1970-01-01 00:00:00.000000000 +0000
94978@@ -1,37 +0,0 @@
94979-//go:build go1.18
94980-// +build go1.18
94981-
94982-package fillstruct
94983-
94984-type emptyStructWithTypeParams[A any] struct{}
94985-
94986-var _ = emptyStructWithTypeParams[int]{} // no suggested fix
94987-
94988-type basicStructWithTypeParams[T any] struct {
94989-	foo T
94990-}
94991-
94992-var _ = basicStructWithTypeParams[int]{} //@suggestedfix("}", "refactor.rewrite", "Fill")
94993-
94994-type twoArgStructWithTypeParams[F, B any] struct {
94995-	foo F
94996-	bar B
94997-}
94998-
94999-var _ = twoArgStructWithTypeParams[string, int]{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95000-
95001-var _ = twoArgStructWithTypeParams[int, string]{
95002-	bar: "bar",
95003-} //@suggestedfix("}", "refactor.rewrite", "Fill")
95004-
95005-type nestedStructWithTypeParams struct {
95006-	bar   string
95007-	basic basicStructWithTypeParams[int]
95008-}
95009-
95010-var _ = nestedStructWithTypeParams{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95011-
95012-func _[T any]() {
95013-	type S struct{ t T }
95014-	_ = S{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95015-}
95016diff -urN a/gopls/internal/lsp/testdata/fillstruct/typeparams.go.golden b/gopls/internal/lsp/testdata/fillstruct/typeparams.go.golden
95017--- a/gopls/internal/lsp/testdata/fillstruct/typeparams.go.golden	2000-01-01 00:00:00.000000000 -0000
95018+++ b/gopls/internal/lsp/testdata/fillstruct/typeparams.go.golden	1970-01-01 00:00:00.000000000 +0000
95019@@ -1,206 +0,0 @@
95020--- suggestedfix_typeparams_14_40 --
95021-//go:build go1.18
95022-// +build go1.18
95023-
95024-package fillstruct
95025-
95026-type emptyStructWithTypeParams[A any] struct{}
95027-
95028-var _ = emptyStructWithTypeParams[int]{} // no suggested fix
95029-
95030-type basicStructWithTypeParams[T any] struct {
95031-	foo T
95032-}
95033-
95034-var _ = basicStructWithTypeParams[int]{
95035-	foo: 0,
95036-} //@suggestedfix("}", "refactor.rewrite", "Fill")
95037-
95038-type twoArgStructWithTypeParams[F, B any] struct {
95039-	foo F
95040-	bar B
95041-}
95042-
95043-var _ = twoArgStructWithTypeParams[string, int]{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95044-
95045-var _ = twoArgStructWithTypeParams[int, string]{
95046-	bar: "bar",
95047-} //@suggestedfix("}", "refactor.rewrite", "Fill")
95048-
95049-type nestedStructWithTypeParams struct {
95050-	bar   string
95051-	basic basicStructWithTypeParams[int]
95052-}
95053-
95054-var _ = nestedStructWithTypeParams{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95055-
95056-func _[T any]() {
95057-	type S struct{ t T }
95058-	_ = S{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95059-}
95060-
95061--- suggestedfix_typeparams_21_49 --
95062-//go:build go1.18
95063-// +build go1.18
95064-
95065-package fillstruct
95066-
95067-type emptyStructWithTypeParams[A any] struct{}
95068-
95069-var _ = emptyStructWithTypeParams[int]{} // no suggested fix
95070-
95071-type basicStructWithTypeParams[T any] struct {
95072-	foo T
95073-}
95074-
95075-var _ = basicStructWithTypeParams[int]{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95076-
95077-type twoArgStructWithTypeParams[F, B any] struct {
95078-	foo F
95079-	bar B
95080-}
95081-
95082-var _ = twoArgStructWithTypeParams[string, int]{
95083-	foo: "",
95084-	bar: 0,
95085-} //@suggestedfix("}", "refactor.rewrite", "Fill")
95086-
95087-var _ = twoArgStructWithTypeParams[int, string]{
95088-	bar: "bar",
95089-} //@suggestedfix("}", "refactor.rewrite", "Fill")
95090-
95091-type nestedStructWithTypeParams struct {
95092-	bar   string
95093-	basic basicStructWithTypeParams[int]
95094-}
95095-
95096-var _ = nestedStructWithTypeParams{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95097-
95098-func _[T any]() {
95099-	type S struct{ t T }
95100-	_ = S{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95101-}
95102-
95103--- suggestedfix_typeparams_25_1 --
95104-//go:build go1.18
95105-// +build go1.18
95106-
95107-package fillstruct
95108-
95109-type emptyStructWithTypeParams[A any] struct{}
95110-
95111-var _ = emptyStructWithTypeParams[int]{} // no suggested fix
95112-
95113-type basicStructWithTypeParams[T any] struct {
95114-	foo T
95115-}
95116-
95117-var _ = basicStructWithTypeParams[int]{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95118-
95119-type twoArgStructWithTypeParams[F, B any] struct {
95120-	foo F
95121-	bar B
95122-}
95123-
95124-var _ = twoArgStructWithTypeParams[string, int]{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95125-
95126-var _ = twoArgStructWithTypeParams[int, string]{
95127-	foo: 0,
95128-	bar: "bar",
95129-} //@suggestedfix("}", "refactor.rewrite", "Fill")
95130-
95131-type nestedStructWithTypeParams struct {
95132-	bar   string
95133-	basic basicStructWithTypeParams[int]
95134-}
95135-
95136-var _ = nestedStructWithTypeParams{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95137-
95138-func _[T any]() {
95139-	type S struct{ t T }
95140-	_ = S{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95141-}
95142-
95143--- suggestedfix_typeparams_32_36 --
95144-//go:build go1.18
95145-// +build go1.18
95146-
95147-package fillstruct
95148-
95149-type emptyStructWithTypeParams[A any] struct{}
95150-
95151-var _ = emptyStructWithTypeParams[int]{} // no suggested fix
95152-
95153-type basicStructWithTypeParams[T any] struct {
95154-	foo T
95155-}
95156-
95157-var _ = basicStructWithTypeParams[int]{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95158-
95159-type twoArgStructWithTypeParams[F, B any] struct {
95160-	foo F
95161-	bar B
95162-}
95163-
95164-var _ = twoArgStructWithTypeParams[string, int]{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95165-
95166-var _ = twoArgStructWithTypeParams[int, string]{
95167-	bar: "bar",
95168-} //@suggestedfix("}", "refactor.rewrite", "Fill")
95169-
95170-type nestedStructWithTypeParams struct {
95171-	bar   string
95172-	basic basicStructWithTypeParams[int]
95173-}
95174-
95175-var _ = nestedStructWithTypeParams{
95176-	bar:   "",
95177-	basic: basicStructWithTypeParams{},
95178-} //@suggestedfix("}", "refactor.rewrite", "Fill")
95179-
95180-func _[T any]() {
95181-	type S struct{ t T }
95182-	_ = S{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95183-}
95184-
95185--- suggestedfix_typeparams_36_8 --
95186-//go:build go1.18
95187-// +build go1.18
95188-
95189-package fillstruct
95190-
95191-type emptyStructWithTypeParams[A any] struct{}
95192-
95193-var _ = emptyStructWithTypeParams[int]{} // no suggested fix
95194-
95195-type basicStructWithTypeParams[T any] struct {
95196-	foo T
95197-}
95198-
95199-var _ = basicStructWithTypeParams[int]{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95200-
95201-type twoArgStructWithTypeParams[F, B any] struct {
95202-	foo F
95203-	bar B
95204-}
95205-
95206-var _ = twoArgStructWithTypeParams[string, int]{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95207-
95208-var _ = twoArgStructWithTypeParams[int, string]{
95209-	bar: "bar",
95210-} //@suggestedfix("}", "refactor.rewrite", "Fill")
95211-
95212-type nestedStructWithTypeParams struct {
95213-	bar   string
95214-	basic basicStructWithTypeParams[int]
95215-}
95216-
95217-var _ = nestedStructWithTypeParams{} //@suggestedfix("}", "refactor.rewrite", "Fill")
95218-
95219-func _[T any]() {
95220-	type S struct{ t T }
95221-	_ = S{
95222-		t: *new(T),
95223-	} //@suggestedfix("}", "refactor.rewrite", "Fill")
95224-}
95225-
95226diff -urN a/gopls/internal/lsp/testdata/folding/a.go b/gopls/internal/lsp/testdata/folding/a.go
95227--- a/gopls/internal/lsp/testdata/folding/a.go	2000-01-01 00:00:00.000000000 -0000
95228+++ b/gopls/internal/lsp/testdata/folding/a.go	1970-01-01 00:00:00.000000000 +0000
95229@@ -1,75 +0,0 @@
95230-package folding //@fold("package")
95231-
95232-import (
95233-	"fmt"
95234-	_ "log"
95235-)
95236-
95237-import _ "os"
95238-
95239-// bar is a function.
95240-// With a multiline doc comment.
95241-func bar() string {
95242-	/* This is a single line comment */
95243-	switch {
95244-	case true:
95245-		if true {
95246-			fmt.Println("true")
95247-		} else {
95248-			fmt.Println("false")
95249-		}
95250-	case false:
95251-		fmt.Println("false")
95252-	default:
95253-		fmt.Println("default")
95254-	}
95255-	/* This is a multiline
95256-	block
95257-	comment */
95258-
95259-	/* This is a multiline
95260-	block
95261-	comment */
95262-	// Followed by another comment.
95263-	_ = []int{
95264-		1,
95265-		2,
95266-		3,
95267-	}
95268-	_ = [2]string{"d",
95269-		"e",
95270-	}
95271-	_ = map[string]int{
95272-		"a": 1,
95273-		"b": 2,
95274-		"c": 3,
95275-	}
95276-	type T struct {
95277-		f string
95278-		g int
95279-		h string
95280-	}
95281-	_ = T{
95282-		f: "j",
95283-		g: 4,
95284-		h: "i",
95285-	}
95286-	x, y := make(chan bool), make(chan bool)
95287-	select {
95288-	case val := <-x:
95289-		if val {
95290-			fmt.Println("true from x")
95291-		} else {
95292-			fmt.Println("false from x")
95293-		}
95294-	case <-y:
95295-		fmt.Println("y")
95296-	default:
95297-		fmt.Println("default")
95298-	}
95299-	// This is a multiline comment
95300-	// that is not a doc comment.
95301-	return `
95302-this string
95303-is not indented`
95304-}
95305diff -urN a/gopls/internal/lsp/testdata/folding/a.go.golden b/gopls/internal/lsp/testdata/folding/a.go.golden
95306--- a/gopls/internal/lsp/testdata/folding/a.go.golden	2000-01-01 00:00:00.000000000 -0000
95307+++ b/gopls/internal/lsp/testdata/folding/a.go.golden	1970-01-01 00:00:00.000000000 +0000
95308@@ -1,722 +0,0 @@
95309--- foldingRange-0 --
95310-package folding //@fold("package")
95311-
95312-import (<>)
95313-
95314-import _ "os"
95315-
95316-// bar is a function.<>
95317-func bar(<>) string {<>}
95318-
95319--- foldingRange-1 --
95320-package folding //@fold("package")
95321-
95322-import (
95323-	"fmt"
95324-	_ "log"
95325-)
95326-
95327-import _ "os"
95328-
95329-// bar is a function.
95330-// With a multiline doc comment.
95331-func bar() string {
95332-	/* This is a single line comment */
95333-	switch {<>}
95334-	/* This is a multiline<>
95335-
95336-	/* This is a multiline<>
95337-	_ = []int{<>}
95338-	_ = [2]string{<>}
95339-	_ = map[string]int{<>}
95340-	type T struct {<>}
95341-	_ = T{<>}
95342-	x, y := make(<>), make(<>)
95343-	select {<>}
95344-	// This is a multiline comment<>
95345-	return <>
95346-}
95347-
95348--- foldingRange-2 --
95349-package folding //@fold("package")
95350-
95351-import (
95352-	"fmt"
95353-	_ "log"
95354-)
95355-
95356-import _ "os"
95357-
95358-// bar is a function.
95359-// With a multiline doc comment.
95360-func bar() string {
95361-	/* This is a single line comment */
95362-	switch {
95363-	case true:<>
95364-	case false:<>
95365-	default:<>
95366-	}
95367-	/* This is a multiline
95368-	block
95369-	comment */
95370-
95371-	/* This is a multiline
95372-	block
95373-	comment */
95374-	// Followed by another comment.
95375-	_ = []int{
95376-		1,
95377-		2,
95378-		3,
95379-	}
95380-	_ = [2]string{"d",
95381-		"e",
95382-	}
95383-	_ = map[string]int{
95384-		"a": 1,
95385-		"b": 2,
95386-		"c": 3,
95387-	}
95388-	type T struct {
95389-		f string
95390-		g int
95391-		h string
95392-	}
95393-	_ = T{
95394-		f: "j",
95395-		g: 4,
95396-		h: "i",
95397-	}
95398-	x, y := make(chan bool), make(chan bool)
95399-	select {
95400-	case val := <-x:<>
95401-	case <-y:<>
95402-	default:<>
95403-	}
95404-	// This is a multiline comment
95405-	// that is not a doc comment.
95406-	return `
95407-this string
95408-is not indented`
95409-}
95410-
95411--- foldingRange-3 --
95412-package folding //@fold("package")
95413-
95414-import (
95415-	"fmt"
95416-	_ "log"
95417-)
95418-
95419-import _ "os"
95420-
95421-// bar is a function.
95422-// With a multiline doc comment.
95423-func bar() string {
95424-	/* This is a single line comment */
95425-	switch {
95426-	case true:
95427-		if true {<>} else {<>}
95428-	case false:
95429-		fmt.Println(<>)
95430-	default:
95431-		fmt.Println(<>)
95432-	}
95433-	/* This is a multiline
95434-	block
95435-	comment */
95436-
95437-	/* This is a multiline
95438-	block
95439-	comment */
95440-	// Followed by another comment.
95441-	_ = []int{
95442-		1,
95443-		2,
95444-		3,
95445-	}
95446-	_ = [2]string{"d",
95447-		"e",
95448-	}
95449-	_ = map[string]int{
95450-		"a": 1,
95451-		"b": 2,
95452-		"c": 3,
95453-	}
95454-	type T struct {
95455-		f string
95456-		g int
95457-		h string
95458-	}
95459-	_ = T{
95460-		f: "j",
95461-		g: 4,
95462-		h: "i",
95463-	}
95464-	x, y := make(chan bool), make(chan bool)
95465-	select {
95466-	case val := <-x:
95467-		if val {<>} else {<>}
95468-	case <-y:
95469-		fmt.Println(<>)
95470-	default:
95471-		fmt.Println(<>)
95472-	}
95473-	// This is a multiline comment
95474-	// that is not a doc comment.
95475-	return `
95476-this string
95477-is not indented`
95478-}
95479-
95480--- foldingRange-4 --
95481-package folding //@fold("package")
95482-
95483-import (
95484-	"fmt"
95485-	_ "log"
95486-)
95487-
95488-import _ "os"
95489-
95490-// bar is a function.
95491-// With a multiline doc comment.
95492-func bar() string {
95493-	/* This is a single line comment */
95494-	switch {
95495-	case true:
95496-		if true {
95497-			fmt.Println(<>)
95498-		} else {
95499-			fmt.Println(<>)
95500-		}
95501-	case false:
95502-		fmt.Println("false")
95503-	default:
95504-		fmt.Println("default")
95505-	}
95506-	/* This is a multiline
95507-	block
95508-	comment */
95509-
95510-	/* This is a multiline
95511-	block
95512-	comment */
95513-	// Followed by another comment.
95514-	_ = []int{
95515-		1,
95516-		2,
95517-		3,
95518-	}
95519-	_ = [2]string{"d",
95520-		"e",
95521-	}
95522-	_ = map[string]int{
95523-		"a": 1,
95524-		"b": 2,
95525-		"c": 3,
95526-	}
95527-	type T struct {
95528-		f string
95529-		g int
95530-		h string
95531-	}
95532-	_ = T{
95533-		f: "j",
95534-		g: 4,
95535-		h: "i",
95536-	}
95537-	x, y := make(chan bool), make(chan bool)
95538-	select {
95539-	case val := <-x:
95540-		if val {
95541-			fmt.Println(<>)
95542-		} else {
95543-			fmt.Println(<>)
95544-		}
95545-	case <-y:
95546-		fmt.Println("y")
95547-	default:
95548-		fmt.Println("default")
95549-	}
95550-	// This is a multiline comment
95551-	// that is not a doc comment.
95552-	return `
95553-this string
95554-is not indented`
95555-}
95556-
95557--- foldingRange-comment-0 --
95558-package folding //@fold("package")
95559-
95560-import (
95561-	"fmt"
95562-	_ "log"
95563-)
95564-
95565-import _ "os"
95566-
95567-// bar is a function.<>
95568-func bar() string {
95569-	/* This is a single line comment */
95570-	switch {
95571-	case true:
95572-		if true {
95573-			fmt.Println("true")
95574-		} else {
95575-			fmt.Println("false")
95576-		}
95577-	case false:
95578-		fmt.Println("false")
95579-	default:
95580-		fmt.Println("default")
95581-	}
95582-	/* This is a multiline<>
95583-
95584-	/* This is a multiline<>
95585-	_ = []int{
95586-		1,
95587-		2,
95588-		3,
95589-	}
95590-	_ = [2]string{"d",
95591-		"e",
95592-	}
95593-	_ = map[string]int{
95594-		"a": 1,
95595-		"b": 2,
95596-		"c": 3,
95597-	}
95598-	type T struct {
95599-		f string
95600-		g int
95601-		h string
95602-	}
95603-	_ = T{
95604-		f: "j",
95605-		g: 4,
95606-		h: "i",
95607-	}
95608-	x, y := make(chan bool), make(chan bool)
95609-	select {
95610-	case val := <-x:
95611-		if val {
95612-			fmt.Println("true from x")
95613-		} else {
95614-			fmt.Println("false from x")
95615-		}
95616-	case <-y:
95617-		fmt.Println("y")
95618-	default:
95619-		fmt.Println("default")
95620-	}
95621-	// This is a multiline comment<>
95622-	return `
95623-this string
95624-is not indented`
95625-}
95626-
95627--- foldingRange-imports-0 --
95628-package folding //@fold("package")
95629-
95630-import (<>)
95631-
95632-import _ "os"
95633-
95634-// bar is a function.
95635-// With a multiline doc comment.
95636-func bar() string {
95637-	/* This is a single line comment */
95638-	switch {
95639-	case true:
95640-		if true {
95641-			fmt.Println("true")
95642-		} else {
95643-			fmt.Println("false")
95644-		}
95645-	case false:
95646-		fmt.Println("false")
95647-	default:
95648-		fmt.Println("default")
95649-	}
95650-	/* This is a multiline
95651-	block
95652-	comment */
95653-
95654-	/* This is a multiline
95655-	block
95656-	comment */
95657-	// Followed by another comment.
95658-	_ = []int{
95659-		1,
95660-		2,
95661-		3,
95662-	}
95663-	_ = [2]string{"d",
95664-		"e",
95665-	}
95666-	_ = map[string]int{
95667-		"a": 1,
95668-		"b": 2,
95669-		"c": 3,
95670-	}
95671-	type T struct {
95672-		f string
95673-		g int
95674-		h string
95675-	}
95676-	_ = T{
95677-		f: "j",
95678-		g: 4,
95679-		h: "i",
95680-	}
95681-	x, y := make(chan bool), make(chan bool)
95682-	select {
95683-	case val := <-x:
95684-		if val {
95685-			fmt.Println("true from x")
95686-		} else {
95687-			fmt.Println("false from x")
95688-		}
95689-	case <-y:
95690-		fmt.Println("y")
95691-	default:
95692-		fmt.Println("default")
95693-	}
95694-	// This is a multiline comment
95695-	// that is not a doc comment.
95696-	return `
95697-this string
95698-is not indented`
95699-}
95700-
95701--- foldingRange-lineFolding-0 --
95702-package folding //@fold("package")
95703-
95704-import (<>
95705-)
95706-
95707-import _ "os"
95708-
95709-// bar is a function.<>
95710-func bar() string {<>
95711-}
95712-
95713--- foldingRange-lineFolding-1 --
95714-package folding //@fold("package")
95715-
95716-import (
95717-	"fmt"
95718-	_ "log"
95719-)
95720-
95721-import _ "os"
95722-
95723-// bar is a function.
95724-// With a multiline doc comment.
95725-func bar() string {
95726-	/* This is a single line comment */
95727-	switch {<>
95728-	}
95729-	/* This is a multiline<>
95730-
95731-	/* This is a multiline<>
95732-	_ = []int{<>,
95733-	}
95734-	_ = [2]string{"d",
95735-		"e",
95736-	}
95737-	_ = map[string]int{<>,
95738-	}
95739-	type T struct {<>
95740-	}
95741-	_ = T{<>,
95742-	}
95743-	x, y := make(chan bool), make(chan bool)
95744-	select {<>
95745-	}
95746-	// This is a multiline comment<>
95747-	return <>
95748-}
95749-
95750--- foldingRange-lineFolding-2 --
95751-package folding //@fold("package")
95752-
95753-import (
95754-	"fmt"
95755-	_ "log"
95756-)
95757-
95758-import _ "os"
95759-
95760-// bar is a function.
95761-// With a multiline doc comment.
95762-func bar() string {
95763-	/* This is a single line comment */
95764-	switch {
95765-	case true:<>
95766-	case false:<>
95767-	default:<>
95768-	}
95769-	/* This is a multiline
95770-	block
95771-	comment */
95772-
95773-	/* This is a multiline
95774-	block
95775-	comment */
95776-	// Followed by another comment.
95777-	_ = []int{
95778-		1,
95779-		2,
95780-		3,
95781-	}
95782-	_ = [2]string{"d",
95783-		"e",
95784-	}
95785-	_ = map[string]int{
95786-		"a": 1,
95787-		"b": 2,
95788-		"c": 3,
95789-	}
95790-	type T struct {
95791-		f string
95792-		g int
95793-		h string
95794-	}
95795-	_ = T{
95796-		f: "j",
95797-		g: 4,
95798-		h: "i",
95799-	}
95800-	x, y := make(chan bool), make(chan bool)
95801-	select {
95802-	case val := <-x:<>
95803-	case <-y:<>
95804-	default:<>
95805-	}
95806-	// This is a multiline comment
95807-	// that is not a doc comment.
95808-	return `
95809-this string
95810-is not indented`
95811-}
95812-
95813--- foldingRange-lineFolding-3 --
95814-package folding //@fold("package")
95815-
95816-import (
95817-	"fmt"
95818-	_ "log"
95819-)
95820-
95821-import _ "os"
95822-
95823-// bar is a function.
95824-// With a multiline doc comment.
95825-func bar() string {
95826-	/* This is a single line comment */
95827-	switch {
95828-	case true:
95829-		if true {<>
95830-		} else {<>
95831-		}
95832-	case false:
95833-		fmt.Println("false")
95834-	default:
95835-		fmt.Println("default")
95836-	}
95837-	/* This is a multiline
95838-	block
95839-	comment */
95840-
95841-	/* This is a multiline
95842-	block
95843-	comment */
95844-	// Followed by another comment.
95845-	_ = []int{
95846-		1,
95847-		2,
95848-		3,
95849-	}
95850-	_ = [2]string{"d",
95851-		"e",
95852-	}
95853-	_ = map[string]int{
95854-		"a": 1,
95855-		"b": 2,
95856-		"c": 3,
95857-	}
95858-	type T struct {
95859-		f string
95860-		g int
95861-		h string
95862-	}
95863-	_ = T{
95864-		f: "j",
95865-		g: 4,
95866-		h: "i",
95867-	}
95868-	x, y := make(chan bool), make(chan bool)
95869-	select {
95870-	case val := <-x:
95871-		if val {<>
95872-		} else {<>
95873-		}
95874-	case <-y:
95875-		fmt.Println("y")
95876-	default:
95877-		fmt.Println("default")
95878-	}
95879-	// This is a multiline comment
95880-	// that is not a doc comment.
95881-	return `
95882-this string
95883-is not indented`
95884-}
95885-
95886--- foldingRange-lineFolding-comment-0 --
95887-package folding //@fold("package")
95888-
95889-import (
95890-	"fmt"
95891-	_ "log"
95892-)
95893-
95894-import _ "os"
95895-
95896-// bar is a function.<>
95897-func bar() string {
95898-	/* This is a single line comment */
95899-	switch {
95900-	case true:
95901-		if true {
95902-			fmt.Println("true")
95903-		} else {
95904-			fmt.Println("false")
95905-		}
95906-	case false:
95907-		fmt.Println("false")
95908-	default:
95909-		fmt.Println("default")
95910-	}
95911-	/* This is a multiline<>
95912-
95913-	/* This is a multiline<>
95914-	_ = []int{
95915-		1,
95916-		2,
95917-		3,
95918-	}
95919-	_ = [2]string{"d",
95920-		"e",
95921-	}
95922-	_ = map[string]int{
95923-		"a": 1,
95924-		"b": 2,
95925-		"c": 3,
95926-	}
95927-	type T struct {
95928-		f string
95929-		g int
95930-		h string
95931-	}
95932-	_ = T{
95933-		f: "j",
95934-		g: 4,
95935-		h: "i",
95936-	}
95937-	x, y := make(chan bool), make(chan bool)
95938-	select {
95939-	case val := <-x:
95940-		if val {
95941-			fmt.Println("true from x")
95942-		} else {
95943-			fmt.Println("false from x")
95944-		}
95945-	case <-y:
95946-		fmt.Println("y")
95947-	default:
95948-		fmt.Println("default")
95949-	}
95950-	// This is a multiline comment<>
95951-	return `
95952-this string
95953-is not indented`
95954-}
95955-
95956--- foldingRange-lineFolding-imports-0 --
95957-package folding //@fold("package")
95958-
95959-import (<>
95960-)
95961-
95962-import _ "os"
95963-
95964-// bar is a function.
95965-// With a multiline doc comment.
95966-func bar() string {
95967-	/* This is a single line comment */
95968-	switch {
95969-	case true:
95970-		if true {
95971-			fmt.Println("true")
95972-		} else {
95973-			fmt.Println("false")
95974-		}
95975-	case false:
95976-		fmt.Println("false")
95977-	default:
95978-		fmt.Println("default")
95979-	}
95980-	/* This is a multiline
95981-	block
95982-	comment */
95983-
95984-	/* This is a multiline
95985-	block
95986-	comment */
95987-	// Followed by another comment.
95988-	_ = []int{
95989-		1,
95990-		2,
95991-		3,
95992-	}
95993-	_ = [2]string{"d",
95994-		"e",
95995-	}
95996-	_ = map[string]int{
95997-		"a": 1,
95998-		"b": 2,
95999-		"c": 3,
96000-	}
96001-	type T struct {
96002-		f string
96003-		g int
96004-		h string
96005-	}
96006-	_ = T{
96007-		f: "j",
96008-		g: 4,
96009-		h: "i",
96010-	}
96011-	x, y := make(chan bool), make(chan bool)
96012-	select {
96013-	case val := <-x:
96014-		if val {
96015-			fmt.Println("true from x")
96016-		} else {
96017-			fmt.Println("false from x")
96018-		}
96019-	case <-y:
96020-		fmt.Println("y")
96021-	default:
96022-		fmt.Println("default")
96023-	}
96024-	// This is a multiline comment
96025-	// that is not a doc comment.
96026-	return `
96027-this string
96028-is not indented`
96029-}
96030-
96031diff -urN a/gopls/internal/lsp/testdata/folding/bad.go.golden b/gopls/internal/lsp/testdata/folding/bad.go.golden
96032--- a/gopls/internal/lsp/testdata/folding/bad.go.golden	2000-01-01 00:00:00.000000000 -0000
96033+++ b/gopls/internal/lsp/testdata/folding/bad.go.golden	1970-01-01 00:00:00.000000000 +0000
96034@@ -1,81 +0,0 @@
96035--- foldingRange-0 --
96036-package folding //@fold("package")
96037-
96038-import (<>)
96039-
96040-import (<>)
96041-
96042-// badBar is a function.
96043-func badBar(<>) string {<>}
96044-
96045--- foldingRange-1 --
96046-package folding //@fold("package")
96047-
96048-import ( "fmt"
96049-	_ "log"
96050-)
96051-
96052-import (
96053-	_ "os" )
96054-
96055-// badBar is a function.
96056-func badBar() string { x := true
96057-	if x {<>} else {<>}
96058-	return
96059-}
96060-
96061--- foldingRange-2 --
96062-package folding //@fold("package")
96063-
96064-import ( "fmt"
96065-	_ "log"
96066-)
96067-
96068-import (
96069-	_ "os" )
96070-
96071-// badBar is a function.
96072-func badBar() string { x := true
96073-	if x {
96074-		// This is the only foldable thing in this file when lineFoldingOnly
96075-		fmt.Println(<>)
96076-	} else {
96077-		fmt.Println(<>) }
96078-	return
96079-}
96080-
96081--- foldingRange-imports-0 --
96082-package folding //@fold("package")
96083-
96084-import (<>)
96085-
96086-import (<>)
96087-
96088-// badBar is a function.
96089-func badBar() string { x := true
96090-	if x {
96091-		// This is the only foldable thing in this file when lineFoldingOnly
96092-		fmt.Println("true")
96093-	} else {
96094-		fmt.Println("false") }
96095-	return
96096-}
96097-
96098--- foldingRange-lineFolding-0 --
96099-package folding //@fold("package")
96100-
96101-import ( "fmt"
96102-	_ "log"
96103-)
96104-
96105-import (
96106-	_ "os" )
96107-
96108-// badBar is a function.
96109-func badBar() string { x := true
96110-	if x {<>
96111-	} else {
96112-		fmt.Println("false") }
96113-	return
96114-}
96115-
96116diff -urN a/gopls/internal/lsp/testdata/folding/bad.go.in b/gopls/internal/lsp/testdata/folding/bad.go.in
96117--- a/gopls/internal/lsp/testdata/folding/bad.go.in	2000-01-01 00:00:00.000000000 -0000
96118+++ b/gopls/internal/lsp/testdata/folding/bad.go.in	1970-01-01 00:00:00.000000000 +0000
96119@@ -1,18 +0,0 @@
96120-package folding //@fold("package")
96121-
96122-import ( "fmt"
96123-	_ "log"
96124-)
96125-
96126-import (
96127-	_ "os" )
96128-
96129-// badBar is a function.
96130-func badBar() string { x := true
96131-	if x {
96132-		// This is the only foldable thing in this file when lineFoldingOnly
96133-		fmt.Println("true")
96134-	} else {
96135-		fmt.Println("false") }
96136-	return
96137-}
96138diff -urN a/gopls/internal/lsp/testdata/foo/foo.go b/gopls/internal/lsp/testdata/foo/foo.go
96139--- a/gopls/internal/lsp/testdata/foo/foo.go	2000-01-01 00:00:00.000000000 -0000
96140+++ b/gopls/internal/lsp/testdata/foo/foo.go	1970-01-01 00:00:00.000000000 +0000
96141@@ -1,30 +0,0 @@
96142-package foo //@mark(PackageFoo, "foo"),item(PackageFoo, "foo", "\"golang.org/lsptests/foo\"", "package")
96143-
96144-type StructFoo struct { //@item(StructFoo, "StructFoo", "struct{...}", "struct")
96145-	Value int //@item(Value, "Value", "int", "field")
96146-}
96147-
96148-// Pre-set this marker, as we don't have a "source" for it in this package.
96149-/* Error() */ //@item(Error, "Error", "func() string", "method")
96150-
96151-func Foo() { //@item(Foo, "Foo", "func()", "func")
96152-	var err error
96153-	err.Error() //@complete("E", Error)
96154-}
96155-
96156-func _() {
96157-	var sFoo StructFoo           //@mark(sFoo1, "sFoo"),complete("t", StructFoo)
96158-	if x := sFoo; x.Value == 1 { //@mark(sFoo2, "sFoo"),complete("V", Value),typdef("sFoo", StructFoo),refs("sFo", sFoo1, sFoo2)
96159-		return
96160-	}
96161-}
96162-
96163-func _() {
96164-	shadowed := 123
96165-	{
96166-		shadowed := "hi" //@item(shadowed, "shadowed", "string", "var"),refs("shadowed", shadowed)
96167-		sha              //@complete("a", shadowed)
96168-	}
96169-}
96170-
96171-type IntFoo int //@item(IntFoo, "IntFoo", "int", "type")
96172diff -urN a/gopls/internal/lsp/testdata/format/bad_format.go.golden b/gopls/internal/lsp/testdata/format/bad_format.go.golden
96173--- a/gopls/internal/lsp/testdata/format/bad_format.go.golden	2000-01-01 00:00:00.000000000 -0000
96174+++ b/gopls/internal/lsp/testdata/format/bad_format.go.golden	1970-01-01 00:00:00.000000000 +0000
96175@@ -1,21 +0,0 @@
96176--- gofmt --
96177-package format //@format("package")
96178-
96179-import (
96180-	"fmt"
96181-	"log"
96182-	"runtime"
96183-)
96184-
96185-func hello() {
96186-
96187-	var x int //@diag("x", "compiler", "x declared (and|but) not used", "error")
96188-}
96189-
96190-func hi() {
96191-	runtime.GOROOT()
96192-	fmt.Printf("")
96193-
96194-	log.Printf("")
96195-}
96196-
96197diff -urN a/gopls/internal/lsp/testdata/format/bad_format.go.in b/gopls/internal/lsp/testdata/format/bad_format.go.in
96198--- a/gopls/internal/lsp/testdata/format/bad_format.go.in	2000-01-01 00:00:00.000000000 -0000
96199+++ b/gopls/internal/lsp/testdata/format/bad_format.go.in	1970-01-01 00:00:00.000000000 +0000
96200@@ -1,22 +0,0 @@
96201-package format //@format("package")
96202-
96203-import (
96204-	"runtime"
96205-	"fmt"
96206-	"log"
96207-)
96208-
96209-func hello() {
96210-
96211-
96212-
96213-
96214-	var x int //@diag("x", "compiler", "x declared (and|but) not used", "error")
96215-}
96216-
96217-func hi() {
96218-	runtime.GOROOT()
96219-	fmt.Printf("")
96220-
96221-	log.Printf("")
96222-}
96223diff -urN a/gopls/internal/lsp/testdata/format/good_format.go b/gopls/internal/lsp/testdata/format/good_format.go
96224--- a/gopls/internal/lsp/testdata/format/good_format.go	2000-01-01 00:00:00.000000000 -0000
96225+++ b/gopls/internal/lsp/testdata/format/good_format.go	1970-01-01 00:00:00.000000000 +0000
96226@@ -1,9 +0,0 @@
96227-package format //@format("package")
96228-
96229-import (
96230-	"log"
96231-)
96232-
96233-func goodbye() {
96234-	log.Printf("byeeeee")
96235-}
96236diff -urN a/gopls/internal/lsp/testdata/format/good_format.go.golden b/gopls/internal/lsp/testdata/format/good_format.go.golden
96237--- a/gopls/internal/lsp/testdata/format/good_format.go.golden	2000-01-01 00:00:00.000000000 -0000
96238+++ b/gopls/internal/lsp/testdata/format/good_format.go.golden	1970-01-01 00:00:00.000000000 +0000
96239@@ -1,11 +0,0 @@
96240--- gofmt --
96241-package format //@format("package")
96242-
96243-import (
96244-	"log"
96245-)
96246-
96247-func goodbye() {
96248-	log.Printf("byeeeee")
96249-}
96250-
96251diff -urN a/gopls/internal/lsp/testdata/format/newline_format.go.golden b/gopls/internal/lsp/testdata/format/newline_format.go.golden
96252--- a/gopls/internal/lsp/testdata/format/newline_format.go.golden	2000-01-01 00:00:00.000000000 -0000
96253+++ b/gopls/internal/lsp/testdata/format/newline_format.go.golden	1970-01-01 00:00:00.000000000 +0000
96254@@ -1,4 +0,0 @@
96255--- gofmt --
96256-package format //@format("package")
96257-func _()       {}
96258-
96259diff -urN a/gopls/internal/lsp/testdata/format/newline_format.go.in b/gopls/internal/lsp/testdata/format/newline_format.go.in
96260--- a/gopls/internal/lsp/testdata/format/newline_format.go.in	2000-01-01 00:00:00.000000000 -0000
96261+++ b/gopls/internal/lsp/testdata/format/newline_format.go.in	1970-01-01 00:00:00.000000000 +0000
96262@@ -1,2 +0,0 @@
96263-package format //@format("package")
96264-func _() {}
96265\ No newline at end of file
96266diff -urN a/gopls/internal/lsp/testdata/format/one_line.go.golden b/gopls/internal/lsp/testdata/format/one_line.go.golden
96267--- a/gopls/internal/lsp/testdata/format/one_line.go.golden	2000-01-01 00:00:00.000000000 -0000
96268+++ b/gopls/internal/lsp/testdata/format/one_line.go.golden	1970-01-01 00:00:00.000000000 +0000
96269@@ -1,3 +0,0 @@
96270--- gofmt --
96271-package format //@format("package")
96272-
96273diff -urN a/gopls/internal/lsp/testdata/format/one_line.go.in b/gopls/internal/lsp/testdata/format/one_line.go.in
96274--- a/gopls/internal/lsp/testdata/format/one_line.go.in	2000-01-01 00:00:00.000000000 -0000
96275+++ b/gopls/internal/lsp/testdata/format/one_line.go.in	1970-01-01 00:00:00.000000000 +0000
96276@@ -1 +0,0 @@
96277-package format //@format("package")
96278\ No newline at end of file
96279diff -urN a/gopls/internal/lsp/testdata/func_rank/func_rank.go.in b/gopls/internal/lsp/testdata/func_rank/func_rank.go.in
96280--- a/gopls/internal/lsp/testdata/func_rank/func_rank.go.in	2000-01-01 00:00:00.000000000 -0000
96281+++ b/gopls/internal/lsp/testdata/func_rank/func_rank.go.in	1970-01-01 00:00:00.000000000 +0000
96282@@ -1,70 +0,0 @@
96283-package func_rank
96284-
96285-import "net/http"
96286-
96287-var stringAVar = "var"    //@item(stringAVar, "stringAVar", "string", "var")
96288-func stringBFunc() string { return "str" } //@item(stringBFunc, "stringBFunc", "func() string", "func")
96289-type stringer struct{}    //@item(stringer, "stringer", "struct{...}", "struct")
96290-
96291-func _() stringer //@complete("tr", stringer)
96292-
96293-func _(val stringer) {} //@complete("tr", stringer)
96294-
96295-func (stringer) _() {} //@complete("tr", stringer)
96296-
96297-func _() {
96298-	var s struct {
96299-		AA int    //@item(rankAA, "AA", "int", "field")
96300-		AB string //@item(rankAB, "AB", "string", "field")
96301-		AC int    //@item(rankAC, "AC", "int", "field")
96302-	}
96303-	fnStr := func(string) {}
96304-	fnStr(s.A)      //@complete(")", rankAB, rankAA, rankAC)
96305-	fnStr("" + s.A) //@complete(")", rankAB, rankAA, rankAC)
96306-
96307-	fnInt := func(int) {}
96308-	fnInt(-s.A) //@complete(")", rankAA, rankAC, rankAB)
96309-
96310-	// no expected type
96311-	fnInt(func() int { s.A }) //@complete(" }", rankAA, rankAB, rankAC)
96312-	fnInt(s.A())              //@complete("()", rankAA, rankAC, rankAB)
96313-	fnInt([]int{}[s.A])       //@complete("])", rankAA, rankAC, rankAB)
96314-	fnInt([]int{}[:s.A])      //@complete("])", rankAA, rankAC, rankAB)
96315-
96316-	fnInt(s.A.(int)) //@complete(".(", rankAA, rankAC, rankAB)
96317-
96318-	fnPtr := func(*string) {}
96319-	fnPtr(&s.A) //@complete(")", rankAB, rankAA, rankAC)
96320-
96321-	var aaPtr *string //@item(rankAAPtr, "aaPtr", "*string", "var")
96322-	var abPtr *int    //@item(rankABPtr, "abPtr", "*int", "var")
96323-	fnInt(*a)         //@complete(")", rankABPtr, rankAAPtr)
96324-
96325-	_ = func() string {
96326-		return s.A //@complete(" //", rankAB, rankAA, rankAC)
96327-	}
96328-}
96329-
96330-type foo struct {
96331-	fooPrivateField int //@item(rankFooPrivField, "fooPrivateField", "int", "field")
96332-	FooPublicField  int //@item(rankFooPubField, "FooPublicField", "int", "field")
96333-}
96334-
96335-func (foo) fooPrivateMethod() int { //@item(rankFooPrivMeth, "fooPrivateMethod", "func() int", "method")
96336-	return 0
96337-}
96338-
96339-func (foo) FooPublicMethod() int { //@item(rankFooPubMeth, "FooPublicMethod", "func() int", "method")
96340-	return 0
96341-}
96342-
96343-func _() {
96344-	var _ int = foo{}. //@rank(" //", rankFooPrivField, rankFooPubField),rank(" //", rankFooPrivMeth, rankFooPubMeth),rank(" //", rankFooPrivField, rankFooPrivMeth)
96345-}
96346-
96347-func _() {
96348-	HandleFunc //@item(httpHandleFunc, "HandleFunc", "func(pattern string, handler func(http.ResponseWriter, *http.Request))", "func")
96349-	HandlerFunc //@item(httpHandlerFunc, "HandlerFunc", "func(http.ResponseWriter, *http.Request)", "type")
96350-
96351-	http.HandleFunc //@rank(" //", httpHandleFunc, httpHandlerFunc)
96352-}
96353diff -urN a/gopls/internal/lsp/testdata/funcsig/func_sig.go b/gopls/internal/lsp/testdata/funcsig/func_sig.go
96354--- a/gopls/internal/lsp/testdata/funcsig/func_sig.go	2000-01-01 00:00:00.000000000 -0000
96355+++ b/gopls/internal/lsp/testdata/funcsig/func_sig.go	1970-01-01 00:00:00.000000000 +0000
96356@@ -1,9 +0,0 @@
96357-package funcsig
96358-
96359-type someType int //@item(sigSomeType, "someType", "int", "type")
96360-
96361-// Don't complete "foo" in signature.
96362-func (foo someType) _() { //@item(sigFoo, "foo", "someType", "var"),complete(") {", sigSomeType)
96363-
96364-	//@complete("", sigFoo, sigSomeType)
96365-}
96366diff -urN a/gopls/internal/lsp/testdata/funcvalue/func_value.go b/gopls/internal/lsp/testdata/funcvalue/func_value.go
96367--- a/gopls/internal/lsp/testdata/funcvalue/func_value.go	2000-01-01 00:00:00.000000000 -0000
96368+++ b/gopls/internal/lsp/testdata/funcvalue/func_value.go	1970-01-01 00:00:00.000000000 +0000
96369@@ -1,27 +0,0 @@
96370-package funcvalue
96371-
96372-func fooFunc() int { //@item(fvFooFunc, "fooFunc", "func() int", "func")
96373-	return 0
96374-}
96375-
96376-var _ = fooFunc() //@item(fvFooFuncCall, "fooFunc", "func() int", "func")
96377-
96378-var fooVar = func() int { //@item(fvFooVar, "fooVar", "func() int", "var")
96379-	return 0
96380-}
96381-
96382-var _ = fooVar() //@item(fvFooVarCall, "fooVar", "func() int", "var")
96383-
96384-type myFunc func() int
96385-
96386-var fooType myFunc = fooVar //@item(fvFooType, "fooType", "myFunc", "var")
96387-
96388-var _ = fooType() //@item(fvFooTypeCall, "fooType", "func() int", "var")
96389-
96390-func _() {
96391-	var f func() int
96392-	f = foo //@complete(" //", fvFooFunc, fvFooType, fvFooVar)
96393-
96394-	var i int
96395-	i = foo //@complete(" //", fvFooFuncCall, fvFooTypeCall, fvFooVarCall)
96396-}
96397diff -urN a/gopls/internal/lsp/testdata/fuzzymatch/fuzzymatch.go b/gopls/internal/lsp/testdata/fuzzymatch/fuzzymatch.go
96398--- a/gopls/internal/lsp/testdata/fuzzymatch/fuzzymatch.go	2000-01-01 00:00:00.000000000 -0000
96399+++ b/gopls/internal/lsp/testdata/fuzzymatch/fuzzymatch.go	1970-01-01 00:00:00.000000000 +0000
96400@@ -1,48 +0,0 @@
96401-// Copyright 2019 The Go Authors. All rights reserved.
96402-// Use of this source code is governed by a BSD-style
96403-// license that can be found in the LICENSE file.
96404-
96405-package fuzzy
96406-
96407-func _() {
96408-	var a struct {
96409-		fabar  int
96410-		fooBar string
96411-	}
96412-
96413-	a.fabar  //@item(fuzzFabarField, "a.fabar", "int", "field")
96414-	a.fooBar //@item(fuzzFooBarField, "a.fooBar", "string", "field")
96415-
96416-	afa //@fuzzy(" //", fuzzFabarField, fuzzFooBarField)
96417-	afb //@fuzzy(" //", fuzzFooBarField, fuzzFabarField)
96418-
96419-	fab //@fuzzy(" //", fuzzFabarField)
96420-
96421-	var myString string
96422-	myString = af //@fuzzy(" //", fuzzFooBarField, fuzzFabarField)
96423-
96424-	var b struct {
96425-		c struct {
96426-			d struct {
96427-				e struct {
96428-					abc string
96429-				}
96430-				abc float32
96431-			}
96432-			abc bool
96433-		}
96434-		abc int
96435-	}
96436-
96437-	b.abc       //@item(fuzzABCInt, "b.abc", "int", "field")
96438-	b.c.abc     //@item(fuzzABCbool, "b.c.abc", "bool", "field")
96439-	b.c.d.abc   //@item(fuzzABCfloat, "b.c.d.abc", "float32", "field")
96440-	b.c.d.e.abc //@item(fuzzABCstring, "b.c.d.e.abc", "string", "field")
96441-
96442-	// in depth order by default
96443-	abc //@fuzzy(" //", fuzzABCInt, fuzzABCbool, fuzzABCfloat)
96444-
96445-	// deep candidate that matches expected type should still ranked first
96446-	var s string
96447-	s = abc //@fuzzy(" //", fuzzABCstring, fuzzABCInt, fuzzABCbool)
96448-}
96449diff -urN a/gopls/internal/lsp/testdata/generate/generate.go b/gopls/internal/lsp/testdata/generate/generate.go
96450--- a/gopls/internal/lsp/testdata/generate/generate.go	2000-01-01 00:00:00.000000000 -0000
96451+++ b/gopls/internal/lsp/testdata/generate/generate.go	1970-01-01 00:00:00.000000000 +0000
96452@@ -1,4 +0,0 @@
96453-package generate
96454-
96455-//go:generate echo Hi //@ codelens("//go:generate", "run go generate", "generate"), codelens("//go:generate", "run go generate ./...", "generate")
96456-//go:generate echo I shall have no CodeLens
96457diff -urN a/gopls/internal/lsp/testdata/generated/generated.go b/gopls/internal/lsp/testdata/generated/generated.go
96458--- a/gopls/internal/lsp/testdata/generated/generated.go	2000-01-01 00:00:00.000000000 -0000
96459+++ b/gopls/internal/lsp/testdata/generated/generated.go	1970-01-01 00:00:00.000000000 +0000
96460@@ -1,7 +0,0 @@
96461-package generated
96462-
96463-// Code generated by generator.go. DO NOT EDIT.
96464-
96465-func _() {
96466-	var y int //@diag("y", "compiler", "y declared (and|but) not used", "error")
96467-}
96468diff -urN a/gopls/internal/lsp/testdata/generated/generator.go b/gopls/internal/lsp/testdata/generated/generator.go
96469--- a/gopls/internal/lsp/testdata/generated/generator.go	2000-01-01 00:00:00.000000000 -0000
96470+++ b/gopls/internal/lsp/testdata/generated/generator.go	1970-01-01 00:00:00.000000000 +0000
96471@@ -1,5 +0,0 @@
96472-package generated
96473-
96474-func _() {
96475-	var x int //@diag("x", "compiler", "x declared (and|but) not used", "error")
96476-}
96477diff -urN a/gopls/internal/lsp/testdata/godef/a/a_x_test.go b/gopls/internal/lsp/testdata/godef/a/a_x_test.go
96478--- a/gopls/internal/lsp/testdata/godef/a/a_x_test.go	2000-01-01 00:00:00.000000000 -0000
96479+++ b/gopls/internal/lsp/testdata/godef/a/a_x_test.go	1970-01-01 00:00:00.000000000 +0000
96480@@ -1,9 +0,0 @@
96481-package a_test
96482-
96483-import (
96484-	"testing"
96485-)
96486-
96487-func TestA2(t *testing.T) { //@TestA2,godef(TestA2, TestA2)
96488-	Nonexistant() //@diag("Nonexistant", "compiler", "(undeclared name|undefined): Nonexistant", "error")
96489-}
96490diff -urN a/gopls/internal/lsp/testdata/godef/a/a_x_test.go.golden b/gopls/internal/lsp/testdata/godef/a/a_x_test.go.golden
96491--- a/gopls/internal/lsp/testdata/godef/a/a_x_test.go.golden	2000-01-01 00:00:00.000000000 -0000
96492+++ b/gopls/internal/lsp/testdata/godef/a/a_x_test.go.golden	1970-01-01 00:00:00.000000000 +0000
96493@@ -1,26 +0,0 @@
96494--- TestA2-definition --
96495-godef/a/a_x_test.go:7:6-12: defined here as ```go
96496-func TestA2(t *testing.T)
96497-```
96498--- TestA2-definition-json --
96499-{
96500-	"span": {
96501-		"uri": "file://godef/a/a_x_test.go",
96502-		"start": {
96503-			"line": 7,
96504-			"column": 6,
96505-			"offset": 44
96506-		},
96507-		"end": {
96508-			"line": 7,
96509-			"column": 12,
96510-			"offset": 50
96511-		}
96512-	},
96513-	"description": "```go\nfunc TestA2(t *testing.T)\n```"
96514-}
96515-
96516--- TestA2-hoverdef --
96517-```go
96518-func TestA2(t *testing.T)
96519-```
96520diff -urN a/gopls/internal/lsp/testdata/godef/a/d.go b/gopls/internal/lsp/testdata/godef/a/d.go
96521--- a/gopls/internal/lsp/testdata/godef/a/d.go	2000-01-01 00:00:00.000000000 -0000
96522+++ b/gopls/internal/lsp/testdata/godef/a/d.go	1970-01-01 00:00:00.000000000 +0000
96523@@ -1,69 +0,0 @@
96524-package a //@mark(a, "a "),hoverdef("a ", a)
96525-
96526-import "fmt"
96527-
96528-type Thing struct { //@Thing
96529-	Member string //@Member
96530-}
96531-
96532-var Other Thing //@Other
96533-
96534-func Things(val []string) []Thing { //@Things
96535-	return nil
96536-}
96537-
96538-func (t Thing) Method(i int) string { //@Method
96539-	return t.Member
96540-}
96541-
96542-func (t Thing) Method3() {
96543-}
96544-
96545-func (t *Thing) Method2(i int, j int) (error, string) {
96546-	return nil, t.Member
96547-}
96548-
96549-func (t *Thing) private() {
96550-}
96551-
96552-func useThings() {
96553-	t := Thing{ //@mark(aStructType, "ing")
96554-		Member: "string", //@mark(fMember, "ember")
96555-	}
96556-	fmt.Print(t.Member) //@mark(aMember, "ember")
96557-	fmt.Print(Other)    //@mark(aVar, "ther")
96558-	Things()            //@mark(aFunc, "ings")
96559-	t.Method()          //@mark(aMethod, "eth")
96560-}
96561-
96562-type NextThing struct { //@NextThing
96563-	Thing
96564-	Value int
96565-}
96566-
96567-func (n NextThing) another() string {
96568-	return n.Member
96569-}
96570-
96571-// Shadows Thing.Method3
96572-func (n *NextThing) Method3() int {
96573-	return n.Value
96574-}
96575-
96576-var nextThing NextThing //@hoverdef("NextThing", NextThing)
96577-
96578-/*@
96579-godef(aStructType, Thing)
96580-godef(aMember, Member)
96581-godef(aVar, Other)
96582-godef(aFunc, Things)
96583-godef(aMethod, Method)
96584-godef(fMember, Member)
96585-godef(Member, Member)
96586-
96587-//param
96588-//package name
96589-//const
96590-//anon field
96591-
96592-*/
96593diff -urN a/gopls/internal/lsp/testdata/godef/a/d.go.golden b/gopls/internal/lsp/testdata/godef/a/d.go.golden
96594--- a/gopls/internal/lsp/testdata/godef/a/d.go.golden	2000-01-01 00:00:00.000000000 -0000
96595+++ b/gopls/internal/lsp/testdata/godef/a/d.go.golden	1970-01-01 00:00:00.000000000 +0000
96596@@ -1,191 +0,0 @@
96597--- Member-definition --
96598-godef/a/d.go:6:2-8: defined here as ```go
96599-field Member string
96600-```
96601-
96602-@Member
96603-
96604-
96605-[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing.Member)
96606--- Member-definition-json --
96607-{
96608-	"span": {
96609-		"uri": "file://godef/a/d.go",
96610-		"start": {
96611-			"line": 6,
96612-			"column": 2,
96613-			"offset": 90
96614-		},
96615-		"end": {
96616-			"line": 6,
96617-			"column": 8,
96618-			"offset": 96
96619-		}
96620-	},
96621-	"description": "```go\nfield Member string\n```\n\n@Member\n\n\n[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing.Member)"
96622-}
96623-
96624--- Member-hoverdef --
96625-```go
96626-field Member string
96627-```
96628-
96629-@Member
96630-
96631-
96632-[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing.Member)
96633--- Method-definition --
96634-godef/a/d.go:15:16-22: defined here as ```go
96635-func (Thing).Method(i int) string
96636-```
96637-
96638-[`(a.Thing).Method` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing.Method)
96639--- Method-definition-json --
96640-{
96641-	"span": {
96642-		"uri": "file://godef/a/d.go",
96643-		"start": {
96644-			"line": 15,
96645-			"column": 16,
96646-			"offset": 219
96647-		},
96648-		"end": {
96649-			"line": 15,
96650-			"column": 22,
96651-			"offset": 225
96652-		}
96653-	},
96654-	"description": "```go\nfunc (Thing).Method(i int) string\n```\n\n[`(a.Thing).Method` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing.Method)"
96655-}
96656-
96657--- Method-hoverdef --
96658-```go
96659-func (Thing).Method(i int) string
96660-```
96661-
96662-[`(a.Thing).Method` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing.Method)
96663--- NextThing-hoverdef --
96664-```go
96665-type NextThing struct {
96666-	Thing
96667-	Value int
96668-}
96669-
96670-func (*NextThing).Method3() int
96671-func (NextThing).another() string
96672-```
96673-
96674-[`a.NextThing` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#NextThing)
96675--- Other-definition --
96676-godef/a/d.go:9:5-10: defined here as ```go
96677-var Other Thing
96678-```
96679-
96680-@Other
96681-
96682-
96683-[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Other)
96684--- Other-definition-json --
96685-{
96686-	"span": {
96687-		"uri": "file://godef/a/d.go",
96688-		"start": {
96689-			"line": 9,
96690-			"column": 5,
96691-			"offset": 121
96692-		},
96693-		"end": {
96694-			"line": 9,
96695-			"column": 10,
96696-			"offset": 126
96697-		}
96698-	},
96699-	"description": "```go\nvar Other Thing\n```\n\n@Other\n\n\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Other)"
96700-}
96701-
96702--- Other-hoverdef --
96703-```go
96704-var Other Thing
96705-```
96706-
96707-@Other
96708-
96709-
96710-[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Other)
96711--- Thing-definition --
96712-godef/a/d.go:5:6-11: defined here as ```go
96713-type Thing struct {
96714-	Member string //@Member
96715-}
96716-
96717-func (Thing).Method(i int) string
96718-func (*Thing).Method2(i int, j int) (error, string)
96719-func (Thing).Method3()
96720-func (*Thing).private()
96721-```
96722-
96723-[`a.Thing` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing)
96724--- Thing-definition-json --
96725-{
96726-	"span": {
96727-		"uri": "file://godef/a/d.go",
96728-		"start": {
96729-			"line": 5,
96730-			"column": 6,
96731-			"offset": 65
96732-		},
96733-		"end": {
96734-			"line": 5,
96735-			"column": 11,
96736-			"offset": 70
96737-		}
96738-	},
96739-	"description": "```go\ntype Thing struct {\n\tMember string //@Member\n}\n\nfunc (Thing).Method(i int) string\nfunc (*Thing).Method2(i int, j int) (error, string)\nfunc (Thing).Method3()\nfunc (*Thing).private()\n```\n\n[`a.Thing` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing)"
96740-}
96741-
96742--- Thing-hoverdef --
96743-```go
96744-type Thing struct {
96745-	Member string //@Member
96746-}
96747-
96748-func (Thing).Method(i int) string
96749-func (*Thing).Method2(i int, j int) (error, string)
96750-func (Thing).Method3()
96751-func (*Thing).private()
96752-```
96753-
96754-[`a.Thing` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing)
96755--- Things-definition --
96756-godef/a/d.go:11:6-12: defined here as ```go
96757-func Things(val []string) []Thing
96758-```
96759-
96760-[`a.Things` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Things)
96761--- Things-definition-json --
96762-{
96763-	"span": {
96764-		"uri": "file://godef/a/d.go",
96765-		"start": {
96766-			"line": 11,
96767-			"column": 6,
96768-			"offset": 148
96769-		},
96770-		"end": {
96771-			"line": 11,
96772-			"column": 12,
96773-			"offset": 154
96774-		}
96775-	},
96776-	"description": "```go\nfunc Things(val []string) []Thing\n```\n\n[`a.Things` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Things)"
96777-}
96778-
96779--- Things-hoverdef --
96780-```go
96781-func Things(val []string) []Thing
96782-```
96783-
96784-[`a.Things` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Things)
96785--- a-hoverdef --
96786-Package a is a package for testing go to definition.
96787-
96788diff -urN a/gopls/internal/lsp/testdata/godef/a/f.go b/gopls/internal/lsp/testdata/godef/a/f.go
96789--- a/gopls/internal/lsp/testdata/godef/a/f.go	2000-01-01 00:00:00.000000000 -0000
96790+++ b/gopls/internal/lsp/testdata/godef/a/f.go	1970-01-01 00:00:00.000000000 +0000
96791@@ -1,16 +0,0 @@
96792-// Package a is a package for testing go to definition.
96793-package a
96794-
96795-import "fmt"
96796-
96797-func TypeStuff() { //@Stuff
96798-	var x string
96799-
96800-	switch y := interface{}(x).(type) { //@mark(switchY, "y"),godef("y", switchY)
96801-	case int: //@mark(intY, "int")
96802-		fmt.Printf("%v", y) //@hoverdef("y", intY)
96803-	case string: //@mark(stringY, "string")
96804-		fmt.Printf("%v", y) //@hoverdef("y", stringY)
96805-	}
96806-
96807-}
96808diff -urN a/gopls/internal/lsp/testdata/godef/a/f.go.golden b/gopls/internal/lsp/testdata/godef/a/f.go.golden
96809--- a/gopls/internal/lsp/testdata/godef/a/f.go.golden	2000-01-01 00:00:00.000000000 -0000
96810+++ b/gopls/internal/lsp/testdata/godef/a/f.go.golden	1970-01-01 00:00:00.000000000 +0000
96811@@ -1,34 +0,0 @@
96812--- intY-hoverdef --
96813-```go
96814-var y int
96815-```
96816--- stringY-hoverdef --
96817-```go
96818-var y string
96819-```
96820--- switchY-definition --
96821-godef/a/f.go:8:9-10: defined here as ```go
96822-var y interface{}
96823-```
96824--- switchY-definition-json --
96825-{
96826-	"span": {
96827-		"uri": "file://godef/a/f.go",
96828-		"start": {
96829-			"line": 8,
96830-			"column": 9,
96831-			"offset": 76
96832-		},
96833-		"end": {
96834-			"line": 8,
96835-			"column": 10,
96836-			"offset": 77
96837-		}
96838-	},
96839-	"description": "```go\nvar y interface{}\n```"
96840-}
96841-
96842--- switchY-hoverdef --
96843-```go
96844-var y interface{}
96845-```
96846diff -urN a/gopls/internal/lsp/testdata/godef/a/g.go b/gopls/internal/lsp/testdata/godef/a/g.go
96847--- a/gopls/internal/lsp/testdata/godef/a/g.go	2000-01-01 00:00:00.000000000 -0000
96848+++ b/gopls/internal/lsp/testdata/godef/a/g.go	1970-01-01 00:00:00.000000000 +0000
96849@@ -1,6 +0,0 @@
96850-package a
96851-
96852-import "time"
96853-
96854-// dur is a constant of type time.Duration.
96855-const dur = 15*time.Minute + 10*time.Second + 350*time.Millisecond //@dur,hoverdef("dur", dur)
96856diff -urN a/gopls/internal/lsp/testdata/godef/a/g.go.golden b/gopls/internal/lsp/testdata/godef/a/g.go.golden
96857--- a/gopls/internal/lsp/testdata/godef/a/g.go.golden	2000-01-01 00:00:00.000000000 -0000
96858+++ b/gopls/internal/lsp/testdata/godef/a/g.go.golden	1970-01-01 00:00:00.000000000 +0000
96859@@ -1,7 +0,0 @@
96860--- dur-hoverdef --
96861-```go
96862-const dur time.Duration = 910350000000 // 15m10.35s
96863-```
96864-
96865-dur is a constant of type time.Duration.
96866-
96867diff -urN a/gopls/internal/lsp/testdata/godef/a/h.go b/gopls/internal/lsp/testdata/godef/a/h.go
96868--- a/gopls/internal/lsp/testdata/godef/a/h.go	2000-01-01 00:00:00.000000000 -0000
96869+++ b/gopls/internal/lsp/testdata/godef/a/h.go	1970-01-01 00:00:00.000000000 +0000
96870@@ -1,147 +0,0 @@
96871-package a
96872-
96873-func _() {
96874-	type s struct {
96875-		nested struct {
96876-			// nested number
96877-			number int64 //@mark(nestedNumber, "number")
96878-		}
96879-		nested2 []struct {
96880-			// nested string
96881-			str string //@mark(nestedString, "str")
96882-		}
96883-		x struct {
96884-			x struct {
96885-				x struct {
96886-					x struct {
96887-						x struct {
96888-							// nested map
96889-							m map[string]float64 //@mark(nestedMap, "m")
96890-						}
96891-					}
96892-				}
96893-			}
96894-		}
96895-	}
96896-
96897-	var t s
96898-	_ = t.nested.number  //@hoverdef("number", nestedNumber)
96899-	_ = t.nested2[0].str //@hoverdef("str", nestedString)
96900-	_ = t.x.x.x.x.x.m    //@hoverdef("m", nestedMap)
96901-}
96902-
96903-func _() {
96904-	var s struct {
96905-		// a field
96906-		a int //@mark(structA, "a")
96907-		// b nested struct
96908-		b struct { //@mark(structB, "b")
96909-			// c field of nested struct
96910-			c int //@mark(structC, "c")
96911-		}
96912-	}
96913-	_ = s.a   //@hoverdef("a", structA)
96914-	_ = s.b   //@hoverdef("b", structB)
96915-	_ = s.b.c //@hoverdef("c", structC)
96916-
96917-	var arr []struct {
96918-		// d field
96919-		d int //@mark(arrD, "d")
96920-		// e nested struct
96921-		e struct { //@mark(arrE, "e")
96922-			// f field of nested struct
96923-			f int //@mark(arrF, "f")
96924-		}
96925-	}
96926-	_ = arr[0].d   //@hoverdef("d", arrD)
96927-	_ = arr[0].e   //@hoverdef("e", arrE)
96928-	_ = arr[0].e.f //@hoverdef("f", arrF)
96929-
96930-	var complex []struct {
96931-		c <-chan map[string][]struct {
96932-			// h field
96933-			h int //@mark(complexH, "h")
96934-			// i nested struct
96935-			i struct { //@mark(complexI, "i")
96936-				// j field of nested struct
96937-				j int //@mark(complexJ, "j")
96938-			}
96939-		}
96940-	}
96941-	_ = (<-complex[0].c)["0"][0].h   //@hoverdef("h", complexH)
96942-	_ = (<-complex[0].c)["0"][0].i   //@hoverdef("i", complexI)
96943-	_ = (<-complex[0].c)["0"][0].i.j //@hoverdef("j", complexJ)
96944-
96945-	var mapWithStructKey map[struct {
96946-		// X key field
96947-		x []string //@mark(mapStructKeyX, "x")
96948-	}]int
96949-	for k := range mapWithStructKey {
96950-		_ = k.x //@hoverdef("x", mapStructKeyX)
96951-	}
96952-
96953-	var mapWithStructKeyAndValue map[struct {
96954-		// Y key field
96955-		y string //@mark(mapStructKeyY, "y")
96956-	}]struct {
96957-		// X value field
96958-		x string //@mark(mapStructValueX, "x")
96959-	}
96960-	for k, v := range mapWithStructKeyAndValue {
96961-		// TODO: we don't show docs for y field because both map key and value
96962-		// are structs. And in this case, we parse only map value
96963-		_ = k.y //@hoverdef("y", mapStructKeyY)
96964-		_ = v.x //@hoverdef("x", mapStructValueX)
96965-	}
96966-
96967-	var i []map[string]interface {
96968-		// open method comment
96969-		open() error //@mark(openMethod, "open")
96970-	}
96971-	i[0]["1"].open() //@hoverdef("open", openMethod)
96972-}
96973-
96974-func _() {
96975-	test := struct {
96976-		// test description
96977-		desc string //@mark(testDescription, "desc")
96978-	}{}
96979-	_ = test.desc //@hoverdef("desc", testDescription)
96980-
96981-	for _, tt := range []struct {
96982-		// test input
96983-		in map[string][]struct { //@mark(testInput, "in")
96984-			// test key
96985-			key string //@mark(testInputKey, "key")
96986-			// test value
96987-			value interface{} //@mark(testInputValue, "value")
96988-		}
96989-		result struct {
96990-			v <-chan struct {
96991-				// expected test value
96992-				value int //@mark(testResultValue, "value")
96993-			}
96994-		}
96995-	}{} {
96996-		_ = tt.in               //@hoverdef("in", testInput)
96997-		_ = tt.in["0"][0].key   //@hoverdef("key", testInputKey)
96998-		_ = tt.in["0"][0].value //@hoverdef("value", testInputValue)
96999-
97000-		_ = (<-tt.result.v).value //@hoverdef("value", testResultValue)
97001-	}
97002-}
97003-
97004-func _() {
97005-	getPoints := func() []struct {
97006-		// X coord
97007-		x int //@mark(returnX, "x")
97008-		// Y coord
97009-		y int //@mark(returnY, "y")
97010-	} {
97011-		return nil
97012-	}
97013-
97014-	r := getPoints()
97015-	r[0].x //@hoverdef("x", returnX)
97016-	r[0].y //@hoverdef("y", returnY)
97017-}
97018diff -urN a/gopls/internal/lsp/testdata/godef/a/h.go.golden b/gopls/internal/lsp/testdata/godef/a/h.go.golden
97019--- a/gopls/internal/lsp/testdata/godef/a/h.go.golden	2000-01-01 00:00:00.000000000 -0000
97020+++ b/gopls/internal/lsp/testdata/godef/a/h.go.golden	1970-01-01 00:00:00.000000000 +0000
97021@@ -1,161 +0,0 @@
97022--- arrD-hoverdef --
97023-```go
97024-field d int
97025-```
97026-
97027-d field
97028-
97029--- arrE-hoverdef --
97030-```go
97031-field e struct{f int}
97032-```
97033-
97034-e nested struct
97035-
97036--- arrF-hoverdef --
97037-```go
97038-field f int
97039-```
97040-
97041-f field of nested struct
97042-
97043--- complexH-hoverdef --
97044-```go
97045-field h int
97046-```
97047-
97048-h field
97049-
97050--- complexI-hoverdef --
97051-```go
97052-field i struct{j int}
97053-```
97054-
97055-i nested struct
97056-
97057--- complexJ-hoverdef --
97058-```go
97059-field j int
97060-```
97061-
97062-j field of nested struct
97063-
97064--- mapStructKeyX-hoverdef --
97065-```go
97066-field x []string
97067-```
97068-
97069-X key field
97070-
97071--- mapStructKeyY-hoverdef --
97072-```go
97073-field y string
97074-```
97075-
97076-Y key field
97077-
97078--- mapStructValueX-hoverdef --
97079-```go
97080-field x string
97081-```
97082-
97083-X value field
97084-
97085--- nestedMap-hoverdef --
97086-```go
97087-field m map[string]float64
97088-```
97089-
97090-nested map
97091-
97092--- nestedNumber-hoverdef --
97093-```go
97094-field number int64
97095-```
97096-
97097-nested number
97098-
97099--- nestedString-hoverdef --
97100-```go
97101-field str string
97102-```
97103-
97104-nested string
97105-
97106--- openMethod-hoverdef --
97107-```go
97108-func (interface).open() error
97109-```
97110-
97111-open method comment
97112-
97113--- returnX-hoverdef --
97114-```go
97115-field x int
97116-```
97117-
97118-X coord
97119-
97120--- returnY-hoverdef --
97121-```go
97122-field y int
97123-```
97124-
97125-Y coord
97126-
97127--- structA-hoverdef --
97128-```go
97129-field a int
97130-```
97131-
97132-a field
97133-
97134--- structB-hoverdef --
97135-```go
97136-field b struct{c int}
97137-```
97138-
97139-b nested struct
97140-
97141--- structC-hoverdef --
97142-```go
97143-field c int
97144-```
97145-
97146-c field of nested struct
97147-
97148--- testDescription-hoverdef --
97149-```go
97150-field desc string
97151-```
97152-
97153-test description
97154-
97155--- testInput-hoverdef --
97156-```go
97157-field in map[string][]struct{key string; value interface{}}
97158-```
97159-
97160-test input
97161-
97162--- testInputKey-hoverdef --
97163-```go
97164-field key string
97165-```
97166-
97167-test key
97168-
97169--- testInputValue-hoverdef --
97170-```go
97171-field value interface{}
97172-```
97173-
97174-test value
97175-
97176--- testResultValue-hoverdef --
97177-```go
97178-field value int
97179-```
97180-
97181-expected test value
97182-
97183diff -urN a/gopls/internal/lsp/testdata/godef/b/e.go b/gopls/internal/lsp/testdata/godef/b/e.go
97184--- a/gopls/internal/lsp/testdata/godef/b/e.go	2000-01-01 00:00:00.000000000 -0000
97185+++ b/gopls/internal/lsp/testdata/godef/b/e.go	1970-01-01 00:00:00.000000000 +0000
97186@@ -1,31 +0,0 @@
97187-package b
97188-
97189-import (
97190-	"fmt"
97191-
97192-	"golang.org/lsptests/godef/a"
97193-)
97194-
97195-func useThings() {
97196-	t := a.Thing{}      //@mark(bStructType, "ing")
97197-	fmt.Print(t.Member) //@mark(bMember, "ember")
97198-	fmt.Print(a.Other)  //@mark(bVar, "ther")
97199-	a.Things()          //@mark(bFunc, "ings")
97200-}
97201-
97202-/*@
97203-godef(bStructType, Thing)
97204-godef(bMember, Member)
97205-godef(bVar, Other)
97206-godef(bFunc, Things)
97207-*/
97208-
97209-func _() {
97210-	var x interface{}      //@mark(eInterface, "interface{}")
97211-	switch x := x.(type) { //@hoverdef("x", eInterface)
97212-	case string: //@mark(eString, "string")
97213-		fmt.Println(x) //@hoverdef("x", eString)
97214-	case int: //@mark(eInt, "int")
97215-		fmt.Println(x) //@hoverdef("x", eInt)
97216-	}
97217-}
97218diff -urN a/gopls/internal/lsp/testdata/godef/b/e.go.golden b/gopls/internal/lsp/testdata/godef/b/e.go.golden
97219--- a/gopls/internal/lsp/testdata/godef/b/e.go.golden	2000-01-01 00:00:00.000000000 -0000
97220+++ b/gopls/internal/lsp/testdata/godef/b/e.go.golden	1970-01-01 00:00:00.000000000 +0000
97221@@ -1,156 +0,0 @@
97222--- Member-definition --
97223-godef/a/d.go:6:2-8: defined here as ```go
97224-field Member string
97225-```
97226-
97227-@Member
97228-
97229-
97230-[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing.Member)
97231--- Member-definition-json --
97232-{
97233-	"span": {
97234-		"uri": "file://godef/a/d.go",
97235-		"start": {
97236-			"line": 6,
97237-			"column": 2,
97238-			"offset": 90
97239-		},
97240-		"end": {
97241-			"line": 6,
97242-			"column": 8,
97243-			"offset": 96
97244-		}
97245-	},
97246-	"description": "```go\nfield Member string\n```\n\n@Member\n\n\n[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing.Member)"
97247-}
97248-
97249--- Member-hoverdef --
97250-```go
97251-field Member string
97252-```
97253-
97254-@Member
97255-
97256-
97257-[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing.Member)
97258--- Other-definition --
97259-godef/a/d.go:9:5-10: defined here as ```go
97260-var a.Other a.Thing
97261-```
97262-
97263-@Other
97264-
97265-
97266-[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Other)
97267--- Other-definition-json --
97268-{
97269-	"span": {
97270-		"uri": "file://godef/a/d.go",
97271-		"start": {
97272-			"line": 9,
97273-			"column": 5,
97274-			"offset": 121
97275-		},
97276-		"end": {
97277-			"line": 9,
97278-			"column": 10,
97279-			"offset": 126
97280-		}
97281-	},
97282-	"description": "```go\nvar a.Other a.Thing\n```\n\n@Other\n\n\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Other)"
97283-}
97284-
97285--- Other-hoverdef --
97286-```go
97287-var a.Other a.Thing
97288-```
97289-
97290-@Other
97291-
97292-
97293-[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Other)
97294--- Thing-definition --
97295-godef/a/d.go:5:6-11: defined here as ```go
97296-type Thing struct {
97297-	Member string //@Member
97298-}
97299-
97300-func (a.Thing).Method(i int) string
97301-func (*a.Thing).Method2(i int, j int) (error, string)
97302-func (a.Thing).Method3()
97303-```
97304-
97305-[`a.Thing` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing)
97306--- Thing-definition-json --
97307-{
97308-	"span": {
97309-		"uri": "file://godef/a/d.go",
97310-		"start": {
97311-			"line": 5,
97312-			"column": 6,
97313-			"offset": 65
97314-		},
97315-		"end": {
97316-			"line": 5,
97317-			"column": 11,
97318-			"offset": 70
97319-		}
97320-	},
97321-	"description": "```go\ntype Thing struct {\n\tMember string //@Member\n}\n\nfunc (a.Thing).Method(i int) string\nfunc (*a.Thing).Method2(i int, j int) (error, string)\nfunc (a.Thing).Method3()\n```\n\n[`a.Thing` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing)"
97322-}
97323-
97324--- Thing-hoverdef --
97325-```go
97326-type Thing struct {
97327-	Member string //@Member
97328-}
97329-
97330-func (a.Thing).Method(i int) string
97331-func (*a.Thing).Method2(i int, j int) (error, string)
97332-func (a.Thing).Method3()
97333-```
97334-
97335-[`a.Thing` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Thing)
97336--- Things-definition --
97337-godef/a/d.go:11:6-12: defined here as ```go
97338-func a.Things(val []string) []a.Thing
97339-```
97340-
97341-[`a.Things` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Things)
97342--- Things-definition-json --
97343-{
97344-	"span": {
97345-		"uri": "file://godef/a/d.go",
97346-		"start": {
97347-			"line": 11,
97348-			"column": 6,
97349-			"offset": 148
97350-		},
97351-		"end": {
97352-			"line": 11,
97353-			"column": 12,
97354-			"offset": 154
97355-		}
97356-	},
97357-	"description": "```go\nfunc a.Things(val []string) []a.Thing\n```\n\n[`a.Things` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Things)"
97358-}
97359-
97360--- Things-hoverdef --
97361-```go
97362-func a.Things(val []string) []a.Thing
97363-```
97364-
97365-[`a.Things` on pkg.go.dev](https://pkg.go.dev/golang.org/lsptests/godef/a#Things)
97366--- eInt-hoverdef --
97367-```go
97368-var x int
97369-```
97370--- eInterface-hoverdef --
97371-```go
97372-var x interface{}
97373-```
97374--- eString-hoverdef --
97375-```go
97376-var x string
97377-```
97378diff -urN a/gopls/internal/lsp/testdata/godef/broken/unclosedIf.go.golden b/gopls/internal/lsp/testdata/godef/broken/unclosedIf.go.golden
97379--- a/gopls/internal/lsp/testdata/godef/broken/unclosedIf.go.golden	2000-01-01 00:00:00.000000000 -0000
97380+++ b/gopls/internal/lsp/testdata/godef/broken/unclosedIf.go.golden	1970-01-01 00:00:00.000000000 +0000
97381@@ -1,31 +0,0 @@
97382--- myUnclosedIf-definition --
97383-godef/broken/unclosedIf.go:7:7-19: defined here as ```go
97384-var myUnclosedIf string
97385-```
97386-
97387-@myUnclosedIf
97388--- myUnclosedIf-definition-json --
97389-{
97390-	"span": {
97391-		"uri": "file://godef/broken/unclosedIf.go",
97392-		"start": {
97393-			"line": 7,
97394-			"column": 7,
97395-			"offset": 68
97396-		},
97397-		"end": {
97398-			"line": 7,
97399-			"column": 19,
97400-			"offset": 80
97401-		}
97402-	},
97403-	"description": "```go\nvar myUnclosedIf string\n```\n\n@myUnclosedIf"
97404-}
97405-
97406--- myUnclosedIf-hoverdef --
97407-```go
97408-var myUnclosedIf string
97409-```
97410-
97411-@myUnclosedIf
97412-
97413diff -urN a/gopls/internal/lsp/testdata/godef/broken/unclosedIf.go.in b/gopls/internal/lsp/testdata/godef/broken/unclosedIf.go.in
97414--- a/gopls/internal/lsp/testdata/godef/broken/unclosedIf.go.in	2000-01-01 00:00:00.000000000 -0000
97415+++ b/gopls/internal/lsp/testdata/godef/broken/unclosedIf.go.in	1970-01-01 00:00:00.000000000 +0000
97416@@ -1,9 +0,0 @@
97417-package broken
97418-
97419-import "fmt"
97420-
97421-func unclosedIf() {
97422-	if false {
97423-		var myUnclosedIf string              //@myUnclosedIf
97424-		fmt.Printf("s = %v\n", myUnclosedIf) //@godef("my", myUnclosedIf)
97425-}
97426diff -urN a/gopls/internal/lsp/testdata/good/good0.go b/gopls/internal/lsp/testdata/good/good0.go
97427--- a/gopls/internal/lsp/testdata/good/good0.go	2000-01-01 00:00:00.000000000 -0000
97428+++ b/gopls/internal/lsp/testdata/good/good0.go	1970-01-01 00:00:00.000000000 +0000
97429@@ -1,6 +0,0 @@
97430-package good //@diag("package", "no_diagnostics", "", "error")
97431-
97432-func stuff() { //@item(good_stuff, "stuff", "func()", "func"),prepare("stu", "stuff", "stuff")
97433-	x := 5
97434-	random2(x) //@prepare("dom", "random2", "random2")
97435-}
97436diff -urN a/gopls/internal/lsp/testdata/good/good1.go b/gopls/internal/lsp/testdata/good/good1.go
97437--- a/gopls/internal/lsp/testdata/good/good1.go	2000-01-01 00:00:00.000000000 -0000
97438+++ b/gopls/internal/lsp/testdata/good/good1.go	1970-01-01 00:00:00.000000000 +0000
97439@@ -1,21 +0,0 @@
97440-package good //@diag("package", "no_diagnostics", "", "error")
97441-
97442-import (
97443-	"golang.org/lsptests/types" //@item(types_import, "types", "\"golang.org/lsptests/types\"", "package")
97444-)
97445-
97446-func random() int { //@item(good_random, "random", "func() int", "func")
97447-	_ = "random() int" //@prepare("random", "", "")
97448-	y := 6 + 7         //@prepare("7", "", "")
97449-	return y           //@prepare("return", "","")
97450-}
97451-
97452-func random2(y int) int { //@item(good_random2, "random2", "func(y int) int", "func"),item(good_y_param, "y", "int", "var")
97453-	//@complete("", good_y_param, types_import, good_random, good_random2, good_stuff)
97454-	var b types.Bob = &types.X{}   //@prepare("ypes","types", "types")
97455-	if _, ok := b.(*types.X); ok { //@complete("X", X_struct, Y_struct, Bob_interface, CoolAlias)
97456-		_ = 0 // suppress "empty branch" diagnostic
97457-	}
97458-
97459-	return y
97460-}
97461diff -urN a/gopls/internal/lsp/testdata/highlights/highlights.go b/gopls/internal/lsp/testdata/highlights/highlights.go
97462--- a/gopls/internal/lsp/testdata/highlights/highlights.go	2000-01-01 00:00:00.000000000 -0000
97463+++ b/gopls/internal/lsp/testdata/highlights/highlights.go	1970-01-01 00:00:00.000000000 +0000
97464@@ -1,151 +0,0 @@
97465-package highlights
97466-
97467-import (
97468-	"fmt"         //@mark(fmtImp, "\"fmt\""),highlight(fmtImp, fmtImp, fmt1, fmt2, fmt3, fmt4)
97469-	h2 "net/http" //@mark(hImp, "h2"),highlight(hImp, hImp, hUse)
97470-	"sort"
97471-)
97472-
97473-type F struct{ bar int } //@mark(barDeclaration, "bar"),highlight(barDeclaration, barDeclaration, bar1, bar2, bar3)
97474-
97475-func _() F {
97476-	return F{
97477-		bar: 123, //@mark(bar1, "bar"),highlight(bar1, barDeclaration, bar1, bar2, bar3)
97478-	}
97479-}
97480-
97481-var foo = F{bar: 52} //@mark(fooDeclaration, "foo"),mark(bar2, "bar"),highlight(fooDeclaration, fooDeclaration, fooUse),highlight(bar2, barDeclaration, bar1, bar2, bar3)
97482-
97483-func Print() { //@mark(printFunc, "Print"),highlight(printFunc, printFunc, printTest)
97484-	_ = h2.Client{} //@mark(hUse, "h2"),highlight(hUse, hImp, hUse)
97485-
97486-	fmt.Println(foo) //@mark(fooUse, "foo"),highlight(fooUse, fooDeclaration, fooUse),mark(fmt1, "fmt"),highlight(fmt1, fmtImp, fmt1, fmt2, fmt3, fmt4)
97487-	fmt.Print("yo")  //@mark(printSep, "Print"),highlight(printSep, printSep, print1, print2),mark(fmt2, "fmt"),highlight(fmt2, fmtImp, fmt1, fmt2, fmt3, fmt4)
97488-}
97489-
97490-func (x *F) Inc() { //@mark(xRightDecl, "x"),mark(xLeftDecl, " *"),highlight(xRightDecl, xRightDecl, xUse),highlight(xLeftDecl, xRightDecl, xUse)
97491-	x.bar++ //@mark(xUse, "x"),mark(bar3, "bar"),highlight(xUse, xRightDecl, xUse),highlight(bar3, barDeclaration, bar1, bar2, bar3)
97492-}
97493-
97494-func testFunctions() {
97495-	fmt.Print("main start") //@mark(print1, "Print"),highlight(print1, printSep, print1, print2),mark(fmt3, "fmt"),highlight(fmt3, fmtImp, fmt1, fmt2, fmt3, fmt4)
97496-	fmt.Print("ok")         //@mark(print2, "Print"),highlight(print2, printSep, print1, print2),mark(fmt4, "fmt"),highlight(fmt4, fmtImp, fmt1, fmt2, fmt3, fmt4)
97497-	Print()                 //@mark(printTest, "Print"),highlight(printTest, printFunc, printTest)
97498-}
97499-
97500-func toProtocolHighlight(rngs []int) []DocumentHighlight { //@mark(doc1, "DocumentHighlight"),mark(docRet1, "[]DocumentHighlight"),highlight(doc1, docRet1, doc1, doc2, doc3, result)
97501-	result := make([]DocumentHighlight, 0, len(rngs)) //@mark(doc2, "DocumentHighlight"),highlight(doc2, doc1, doc2, doc3)
97502-	for _, rng := range rngs {
97503-		result = append(result, DocumentHighlight{ //@mark(doc3, "DocumentHighlight"),highlight(doc3, doc1, doc2, doc3)
97504-			Range: rng,
97505-		})
97506-	}
97507-	return result //@mark(result, "result")
97508-}
97509-
97510-func testForLoops() {
97511-	for i := 0; i < 10; i++ { //@mark(forDecl1, "for"),highlight(forDecl1, forDecl1, brk1, cont1)
97512-		if i > 8 {
97513-			break //@mark(brk1, "break"),highlight(brk1, forDecl1, brk1, cont1)
97514-		}
97515-		if i < 2 {
97516-			for j := 1; j < 10; j++ { //@mark(forDecl2, "for"),highlight(forDecl2, forDecl2, cont2)
97517-				if j < 3 {
97518-					for k := 1; k < 10; k++ { //@mark(forDecl3, "for"),highlight(forDecl3, forDecl3, cont3)
97519-						if k < 3 {
97520-							continue //@mark(cont3, "continue"),highlight(cont3, forDecl3, cont3)
97521-						}
97522-					}
97523-					continue //@mark(cont2, "continue"),highlight(cont2, forDecl2, cont2)
97524-				}
97525-			}
97526-			continue //@mark(cont1, "continue"),highlight(cont1, forDecl1, brk1, cont1)
97527-		}
97528-	}
97529-
97530-	arr := []int{}
97531-	for i := range arr { //@mark(forDecl4, "for"),highlight(forDecl4, forDecl4, brk4, cont4)
97532-		if i > 8 {
97533-			break //@mark(brk4, "break"),highlight(brk4, forDecl4, brk4, cont4)
97534-		}
97535-		if i < 4 {
97536-			continue //@mark(cont4, "continue"),highlight(cont4, forDecl4, brk4, cont4)
97537-		}
97538-	}
97539-
97540-Outer:
97541-	for i := 0; i < 10; i++ { //@mark(forDecl5, "for"),highlight(forDecl5, forDecl5, brk5, brk6, brk8)
97542-		break //@mark(brk5, "break"),highlight(brk5, forDecl5, brk5, brk6, brk8)
97543-		for { //@mark(forDecl6, "for"),highlight(forDecl6, forDecl6, cont5)
97544-			if i == 1 {
97545-				break Outer //@mark(brk6, "break Outer"),highlight(brk6, forDecl5, brk5, brk6, brk8)
97546-			}
97547-			switch i { //@mark(switch1, "switch"),highlight(switch1, switch1, brk7)
97548-			case 5:
97549-				break //@mark(brk7, "break"),highlight(brk7, switch1, brk7)
97550-			case 6:
97551-				continue //@mark(cont5, "continue"),highlight(cont5, forDecl6, cont5)
97552-			case 7:
97553-				break Outer //@mark(brk8, "break Outer"),highlight(brk8, forDecl5, brk5, brk6, brk8)
97554-			}
97555-		}
97556-	}
97557-}
97558-
97559-func testSwitch() {
97560-	var i, j int
97561-
97562-L1:
97563-	for { //@mark(forDecl7, "for"),highlight(forDecl7, forDecl7, brk10, cont6)
97564-	L2:
97565-		switch i { //@mark(switch2, "switch"),highlight(switch2, switch2, brk11, brk12, brk13)
97566-		case 1:
97567-			switch j { //@mark(switch3, "switch"),highlight(switch3, switch3, brk9)
97568-			case 1:
97569-				break //@mark(brk9, "break"),highlight(brk9, switch3, brk9)
97570-			case 2:
97571-				break L1 //@mark(brk10, "break L1"),highlight(brk10, forDecl7, brk10, cont6)
97572-			case 3:
97573-				break L2 //@mark(brk11, "break L2"),highlight(brk11, switch2, brk11, brk12, brk13)
97574-			default:
97575-				continue //@mark(cont6, "continue"),highlight(cont6, forDecl7, brk10, cont6)
97576-			}
97577-		case 2:
97578-			break //@mark(brk12, "break"),highlight(brk12, switch2, brk11, brk12, brk13)
97579-		default:
97580-			break L2 //@mark(brk13, "break L2"),highlight(brk13, switch2, brk11, brk12, brk13)
97581-		}
97582-	}
97583-}
97584-
97585-func testReturn() bool { //@mark(func1, "func"),mark(bool1, "bool"),highlight(func1, func1, fullRet11, fullRet12),highlight(bool1, bool1, false1, bool2, true1)
97586-	if 1 < 2 {
97587-		return false //@mark(ret11, "return"),mark(fullRet11, "return false"),mark(false1, "false"),highlight(ret11, func1, fullRet11, fullRet12)
97588-	}
97589-	candidates := []int{}
97590-	sort.SliceStable(candidates, func(i, j int) bool { //@mark(func2, "func"),mark(bool2, "bool"),highlight(func2, func2, fullRet2)
97591-		return candidates[i] > candidates[j] //@mark(ret2, "return"),mark(fullRet2, "return candidates[i] > candidates[j]"),highlight(ret2, func2, fullRet2)
97592-	})
97593-	return true //@mark(ret12, "return"),mark(fullRet12, "return true"),mark(true1, "true"),highlight(ret12, func1, fullRet11, fullRet12)
97594-}
97595-
97596-func testReturnFields() float64 { //@mark(retVal1, "float64"),highlight(retVal1, retVal1, retVal11, retVal21)
97597-	if 1 < 2 {
97598-		return 20.1 //@mark(retVal11, "20.1"),highlight(retVal11, retVal1, retVal11, retVal21)
97599-	}
97600-	z := 4.3 //@mark(zDecl, "z")
97601-	return z //@mark(retVal21, "z"),highlight(retVal21, retVal1, retVal11, zDecl, retVal21)
97602-}
97603-
97604-func testReturnMultipleFields() (float32, string) { //@mark(retVal31, "float32"),mark(retVal32, "string"),highlight(retVal31, retVal31, retVal41, retVal51),highlight(retVal32, retVal32, retVal42, retVal52)
97605-	y := "im a var" //@mark(yDecl, "y"),
97606-	if 1 < 2 {
97607-		return 20.1, y //@mark(retVal41, "20.1"),mark(retVal42, "y"),highlight(retVal41, retVal31, retVal41, retVal51),highlight(retVal42, retVal32, yDecl, retVal42, retVal52)
97608-	}
97609-	return 4.9, "test" //@mark(retVal51, "4.9"),mark(retVal52, "\"test\""),highlight(retVal51, retVal31, retVal41, retVal51),highlight(retVal52, retVal32, retVal42, retVal52)
97610-}
97611-
97612-func testReturnFunc() int32 { //@mark(retCall, "int32")
97613-	mulch := 1          //@mark(mulchDec, "mulch"),highlight(mulchDec, mulchDec, mulchRet)
97614-	return int32(mulch) //@mark(mulchRet, "mulch"),mark(retFunc, "int32"),mark(retTotal, "int32(mulch)"),highlight(mulchRet, mulchDec, mulchRet),highlight(retFunc, retCall, retFunc, retTotal)
97615-}
97616diff -urN a/gopls/internal/lsp/testdata/implementation/implementation_generics.go b/gopls/internal/lsp/testdata/implementation/implementation_generics.go
97617--- a/gopls/internal/lsp/testdata/implementation/implementation_generics.go	2000-01-01 00:00:00.000000000 -0000
97618+++ b/gopls/internal/lsp/testdata/implementation/implementation_generics.go	1970-01-01 00:00:00.000000000 +0000
97619@@ -1,16 +0,0 @@
97620-//go:build go1.18
97621-// +build go1.18
97622-
97623-package implementation
97624-
97625-// -- generics --
97626-
97627-type GenIface[T any] interface { //@mark(GenIface, "GenIface"),implementations("GenIface", GC)
97628-	F(int, string, T) //@mark(GenIfaceF, "F"),implementations("F", GCF)
97629-}
97630-
97631-type GenConc[U any] int //@mark(GenConc, "GenConc"),implementations("GenConc", GI)
97632-
97633-func (GenConc[V]) F(int, string, V) {} //@mark(GenConcF, "F"),implementations("F", GIF)
97634-
97635-type GenConcString struct{ GenConc[string] } //@mark(GenConcString, "GenConcString"),implementations(GenConcString, GIString)
97636diff -urN a/gopls/internal/lsp/testdata/implementation/implementation.go b/gopls/internal/lsp/testdata/implementation/implementation.go
97637--- a/gopls/internal/lsp/testdata/implementation/implementation.go	2000-01-01 00:00:00.000000000 -0000
97638+++ b/gopls/internal/lsp/testdata/implementation/implementation.go	1970-01-01 00:00:00.000000000 +0000
97639@@ -1,37 +0,0 @@
97640-package implementation
97641-
97642-import "golang.org/lsptests/implementation/other"
97643-
97644-type ImpP struct{} //@ImpP,implementations("ImpP", Laugher, OtherLaugher)
97645-
97646-func (*ImpP) Laugh() { //@mark(LaughP, "Laugh"),implementations("Laugh", Laugh, OtherLaugh)
97647-}
97648-
97649-type ImpS struct{} //@ImpS,implementations("ImpS", Laugher, OtherLaugher)
97650-
97651-func (ImpS) Laugh() { //@mark(LaughS, "Laugh"),implementations("Laugh", Laugh, OtherLaugh)
97652-}
97653-
97654-type Laugher interface { //@Laugher,implementations("Laugher", ImpP, OtherImpP, ImpS, OtherImpS, embedsImpP)
97655-	Laugh() //@Laugh,implementations("Laugh", LaughP, OtherLaughP, LaughS, OtherLaughS)
97656-}
97657-
97658-type Foo struct { //@implementations("Foo", Joker)
97659-	other.Foo
97660-}
97661-
97662-type Joker interface { //@Joker
97663-	Joke() //@Joke,implementations("Joke", ImpJoker)
97664-}
97665-
97666-type cryer int //@implementations("cryer", Cryer)
97667-
97668-func (cryer) Cry(other.CryType) {} //@mark(CryImpl, "Cry"),implementations("Cry", Cry)
97669-
97670-type Empty interface{} //@implementations("Empty")
97671-
97672-var _ interface{ Joke() } //@implementations("Joke", ImpJoker)
97673-
97674-type embedsImpP struct { //@embedsImpP
97675-	ImpP //@implementations("ImpP", Laugher, OtherLaugher)
97676-}
97677diff -urN a/gopls/internal/lsp/testdata/implementation/other/other_generics.go b/gopls/internal/lsp/testdata/implementation/other/other_generics.go
97678--- a/gopls/internal/lsp/testdata/implementation/other/other_generics.go	2000-01-01 00:00:00.000000000 -0000
97679+++ b/gopls/internal/lsp/testdata/implementation/other/other_generics.go	1970-01-01 00:00:00.000000000 +0000
97680@@ -1,16 +0,0 @@
97681-//go:build go1.18
97682-// +build go1.18
97683-
97684-package other
97685-
97686-// -- generics (limited support) --
97687-
97688-type GI[T any] interface { //@mark(GI, "GI"),implementations("GI", GenConc)
97689-	F(int, string, T) //@mark(GIF, "F"),implementations("F", GenConcF)
97690-}
97691-
97692-type GIString GI[string] //@mark(GIString, "GIString"),implementations("GIString", GenConcString)
97693-
97694-type GC[U any] int //@mark(GC, "GC"),implementations("GC", GenIface)
97695-
97696-func (GC[V]) F(int, string, V) {} //@mark(GCF, "F"),implementations("F", GenIfaceF)
97697diff -urN a/gopls/internal/lsp/testdata/implementation/other/other.go b/gopls/internal/lsp/testdata/implementation/other/other.go
97698--- a/gopls/internal/lsp/testdata/implementation/other/other.go	2000-01-01 00:00:00.000000000 -0000
97699+++ b/gopls/internal/lsp/testdata/implementation/other/other.go	1970-01-01 00:00:00.000000000 +0000
97700@@ -1,27 +0,0 @@
97701-package other
97702-
97703-type ImpP struct{} //@mark(OtherImpP, "ImpP")
97704-
97705-func (*ImpP) Laugh() { //@mark(OtherLaughP, "Laugh")
97706-}
97707-
97708-type ImpS struct{} //@mark(OtherImpS, "ImpS")
97709-
97710-func (ImpS) Laugh() { //@mark(OtherLaughS, "Laugh")
97711-}
97712-
97713-type ImpI interface { //@mark(OtherLaugher, "ImpI")
97714-	Laugh() //@mark(OtherLaugh, "Laugh")
97715-}
97716-
97717-type Foo struct { //@implementations("Foo", Joker)
97718-}
97719-
97720-func (Foo) Joke() { //@mark(ImpJoker, "Joke"),implementations("Joke", Joke)
97721-}
97722-
97723-type CryType int
97724-
97725-type Cryer interface { //@Cryer
97726-	Cry(CryType) //@Cry,implementations("Cry", CryImpl)
97727-}
97728diff -urN a/gopls/internal/lsp/testdata/implementation/other/other_test.go b/gopls/internal/lsp/testdata/implementation/other/other_test.go
97729--- a/gopls/internal/lsp/testdata/implementation/other/other_test.go	2000-01-01 00:00:00.000000000 -0000
97730+++ b/gopls/internal/lsp/testdata/implementation/other/other_test.go	1970-01-01 00:00:00.000000000 +0000
97731@@ -1,10 +0,0 @@
97732-package other
97733-
97734-import (
97735-	"testing"
97736-)
97737-
97738-// This exists so the other.test package comes into existence.
97739-
97740-func TestOther(t *testing.T) {
97741-}
97742diff -urN a/gopls/internal/lsp/testdata/importedcomplit/imported_complit.go.in b/gopls/internal/lsp/testdata/importedcomplit/imported_complit.go.in
97743--- a/gopls/internal/lsp/testdata/importedcomplit/imported_complit.go.in	2000-01-01 00:00:00.000000000 -0000
97744+++ b/gopls/internal/lsp/testdata/importedcomplit/imported_complit.go.in	1970-01-01 00:00:00.000000000 +0000
97745@@ -1,42 +0,0 @@
97746-package importedcomplit
97747-
97748-import (
97749-	"golang.org/lsptests/foo"
97750-
97751-	// import completions
97752-	"fm" //@complete("\" //", fmtImport)
97753-	"go/pars" //@complete("\" //", parserImport)
97754-	"golang.org/lsptests/signa" //@complete("na\" //", signatureImport)
97755-	"golang.org/lspte" //@complete("\" //", lsptestsImport)
97756-	"crypto/elli" //@complete("\" //", cryptoImport)
97757-	"golang.org/lsptests/sign" //@complete("\" //", signatureImport)
97758-	"golang.org/lsptests/sign" //@complete("ests", lsptestsImport)
97759-	namedParser "go/pars" //@complete("\" //", parserImport)
97760-)
97761-
97762-func _() {
97763-	var V int //@item(icVVar, "V", "int", "var")
97764-	_ = foo.StructFoo{V} //@complete("}", Value, icVVar)
97765-}
97766-
97767-func _() {
97768-	var (
97769-		aa string //@item(icAAVar, "aa", "string", "var")
97770-		ab int    //@item(icABVar, "ab", "int", "var")
97771-	)
97772-
97773-	_ = foo.StructFoo{a} //@complete("}", abVar, aaVar)
97774-
97775-	var s struct {
97776-		AA string //@item(icFieldAA, "AA", "string", "field")
97777-		AB int    //@item(icFieldAB, "AB", "int", "field")
97778-	}
97779-
97780-	_ = foo.StructFoo{s.} //@complete("}", icFieldAB, icFieldAA)
97781-}
97782-
97783-/* "fmt" */ //@item(fmtImport, "fmt", "\"fmt\"", "package")
97784-/* "go/parser" */ //@item(parserImport, "parser", "\"go/parser\"", "package")
97785-/* "golang.org/lsptests/signature" */ //@item(signatureImport, "signature", "\"golang.org/lsptests/signature\"", "package")
97786-/* "golang.org/lsptests/" */ //@item(lsptestsImport, "lsptests/", "\"golang.org/lsptests/\"", "package")
97787-/* "crypto/elliptic" */ //@item(cryptoImport, "elliptic", "\"crypto/elliptic\"", "package")
97788diff -urN a/gopls/internal/lsp/testdata/imports/add_import.go.golden b/gopls/internal/lsp/testdata/imports/add_import.go.golden
97789--- a/gopls/internal/lsp/testdata/imports/add_import.go.golden	2000-01-01 00:00:00.000000000 -0000
97790+++ b/gopls/internal/lsp/testdata/imports/add_import.go.golden	1970-01-01 00:00:00.000000000 +0000
97791@@ -1,13 +0,0 @@
97792--- goimports --
97793-package imports //@import("package")
97794-
97795-import (
97796-	"bytes"
97797-	"fmt"
97798-)
97799-
97800-func _() {
97801-	fmt.Println("")
97802-	bytes.NewBuffer(nil)
97803-}
97804-
97805diff -urN a/gopls/internal/lsp/testdata/imports/add_import.go.in b/gopls/internal/lsp/testdata/imports/add_import.go.in
97806--- a/gopls/internal/lsp/testdata/imports/add_import.go.in	2000-01-01 00:00:00.000000000 -0000
97807+++ b/gopls/internal/lsp/testdata/imports/add_import.go.in	1970-01-01 00:00:00.000000000 +0000
97808@@ -1,10 +0,0 @@
97809-package imports //@import("package")
97810-
97811-import (
97812-	"fmt"
97813-)
97814-
97815-func _() {
97816-	fmt.Println("")
97817-	bytes.NewBuffer(nil)
97818-}
97819diff -urN a/gopls/internal/lsp/testdata/imports/good_imports.go.golden b/gopls/internal/lsp/testdata/imports/good_imports.go.golden
97820--- a/gopls/internal/lsp/testdata/imports/good_imports.go.golden	2000-01-01 00:00:00.000000000 -0000
97821+++ b/gopls/internal/lsp/testdata/imports/good_imports.go.golden	1970-01-01 00:00:00.000000000 +0000
97822@@ -1,9 +0,0 @@
97823--- goimports --
97824-package imports //@import("package")
97825-
97826-import "fmt"
97827-
97828-func _() {
97829-fmt.Println("")
97830-}
97831-
97832diff -urN a/gopls/internal/lsp/testdata/imports/good_imports.go.in b/gopls/internal/lsp/testdata/imports/good_imports.go.in
97833--- a/gopls/internal/lsp/testdata/imports/good_imports.go.in	2000-01-01 00:00:00.000000000 -0000
97834+++ b/gopls/internal/lsp/testdata/imports/good_imports.go.in	1970-01-01 00:00:00.000000000 +0000
97835@@ -1,7 +0,0 @@
97836-package imports //@import("package")
97837-
97838-import "fmt"
97839-
97840-func _() {
97841-fmt.Println("")
97842-}
97843diff -urN a/gopls/internal/lsp/testdata/imports/issue35458.go.golden b/gopls/internal/lsp/testdata/imports/issue35458.go.golden
97844--- a/gopls/internal/lsp/testdata/imports/issue35458.go.golden	2000-01-01 00:00:00.000000000 -0000
97845+++ b/gopls/internal/lsp/testdata/imports/issue35458.go.golden	1970-01-01 00:00:00.000000000 +0000
97846@@ -1,20 +0,0 @@
97847--- goimports --
97848-// package doc
97849-package imports //@import("package")
97850-
97851-
97852-
97853-
97854-
97855-
97856-func _() {
97857-	println("Hello, world!")
97858-}
97859-
97860-
97861-
97862-
97863-
97864-
97865-
97866-
97867diff -urN a/gopls/internal/lsp/testdata/imports/issue35458.go.in b/gopls/internal/lsp/testdata/imports/issue35458.go.in
97868--- a/gopls/internal/lsp/testdata/imports/issue35458.go.in	2000-01-01 00:00:00.000000000 -0000
97869+++ b/gopls/internal/lsp/testdata/imports/issue35458.go.in	1970-01-01 00:00:00.000000000 +0000
97870@@ -1,23 +0,0 @@
97871-
97872-
97873-
97874-
97875-
97876-// package doc
97877-package imports //@import("package")
97878-
97879-
97880-
97881-
97882-
97883-
97884-func _() {
97885-	println("Hello, world!")
97886-}
97887-
97888-
97889-
97890-
97891-
97892-
97893-
97894diff -urN a/gopls/internal/lsp/testdata/imports/multiple_blocks.go.golden b/gopls/internal/lsp/testdata/imports/multiple_blocks.go.golden
97895--- a/gopls/internal/lsp/testdata/imports/multiple_blocks.go.golden	2000-01-01 00:00:00.000000000 -0000
97896+++ b/gopls/internal/lsp/testdata/imports/multiple_blocks.go.golden	1970-01-01 00:00:00.000000000 +0000
97897@@ -1,9 +0,0 @@
97898--- goimports --
97899-package imports //@import("package")
97900-
97901-import "fmt"
97902-
97903-func _() {
97904-	fmt.Println("")
97905-}
97906-
97907diff -urN a/gopls/internal/lsp/testdata/imports/multiple_blocks.go.in b/gopls/internal/lsp/testdata/imports/multiple_blocks.go.in
97908--- a/gopls/internal/lsp/testdata/imports/multiple_blocks.go.in	2000-01-01 00:00:00.000000000 -0000
97909+++ b/gopls/internal/lsp/testdata/imports/multiple_blocks.go.in	1970-01-01 00:00:00.000000000 +0000
97910@@ -1,9 +0,0 @@
97911-package imports //@import("package")
97912-
97913-import "fmt"
97914-
97915-import "bytes"
97916-
97917-func _() {
97918-	fmt.Println("")
97919-}
97920diff -urN a/gopls/internal/lsp/testdata/imports/needs_imports.go.golden b/gopls/internal/lsp/testdata/imports/needs_imports.go.golden
97921--- a/gopls/internal/lsp/testdata/imports/needs_imports.go.golden	2000-01-01 00:00:00.000000000 -0000
97922+++ b/gopls/internal/lsp/testdata/imports/needs_imports.go.golden	1970-01-01 00:00:00.000000000 +0000
97923@@ -1,13 +0,0 @@
97924--- goimports --
97925-package imports //@import("package")
97926-
97927-import (
97928-	"fmt"
97929-	"log"
97930-)
97931-
97932-func goodbye() {
97933-	fmt.Printf("HI")
97934-	log.Printf("byeeeee")
97935-}
97936-
97937diff -urN a/gopls/internal/lsp/testdata/imports/needs_imports.go.in b/gopls/internal/lsp/testdata/imports/needs_imports.go.in
97938--- a/gopls/internal/lsp/testdata/imports/needs_imports.go.in	2000-01-01 00:00:00.000000000 -0000
97939+++ b/gopls/internal/lsp/testdata/imports/needs_imports.go.in	1970-01-01 00:00:00.000000000 +0000
97940@@ -1,6 +0,0 @@
97941-package imports //@import("package")
97942-
97943-func goodbye() {
97944-	fmt.Printf("HI")
97945-	log.Printf("byeeeee")
97946-}
97947diff -urN a/gopls/internal/lsp/testdata/imports/remove_import.go.golden b/gopls/internal/lsp/testdata/imports/remove_import.go.golden
97948--- a/gopls/internal/lsp/testdata/imports/remove_import.go.golden	2000-01-01 00:00:00.000000000 -0000
97949+++ b/gopls/internal/lsp/testdata/imports/remove_import.go.golden	1970-01-01 00:00:00.000000000 +0000
97950@@ -1,11 +0,0 @@
97951--- goimports --
97952-package imports //@import("package")
97953-
97954-import (
97955-	"fmt"
97956-)
97957-
97958-func _() {
97959-	fmt.Println("")
97960-}
97961-
97962diff -urN a/gopls/internal/lsp/testdata/imports/remove_import.go.in b/gopls/internal/lsp/testdata/imports/remove_import.go.in
97963--- a/gopls/internal/lsp/testdata/imports/remove_import.go.in	2000-01-01 00:00:00.000000000 -0000
97964+++ b/gopls/internal/lsp/testdata/imports/remove_import.go.in	1970-01-01 00:00:00.000000000 +0000
97965@@ -1,10 +0,0 @@
97966-package imports //@import("package")
97967-
97968-import (
97969-	"bytes"
97970-	"fmt"
97971-)
97972-
97973-func _() {
97974-	fmt.Println("")
97975-}
97976diff -urN a/gopls/internal/lsp/testdata/imports/remove_imports.go.golden b/gopls/internal/lsp/testdata/imports/remove_imports.go.golden
97977--- a/gopls/internal/lsp/testdata/imports/remove_imports.go.golden	2000-01-01 00:00:00.000000000 -0000
97978+++ b/gopls/internal/lsp/testdata/imports/remove_imports.go.golden	1970-01-01 00:00:00.000000000 +0000
97979@@ -1,6 +0,0 @@
97980--- goimports --
97981-package imports //@import("package")
97982-
97983-func _() {
97984-}
97985-
97986diff -urN a/gopls/internal/lsp/testdata/imports/remove_imports.go.in b/gopls/internal/lsp/testdata/imports/remove_imports.go.in
97987--- a/gopls/internal/lsp/testdata/imports/remove_imports.go.in	2000-01-01 00:00:00.000000000 -0000
97988+++ b/gopls/internal/lsp/testdata/imports/remove_imports.go.in	1970-01-01 00:00:00.000000000 +0000
97989@@ -1,9 +0,0 @@
97990-package imports //@import("package")
97991-
97992-import (
97993-	"bytes"
97994-	"fmt"
97995-)
97996-
97997-func _() {
97998-}
97999diff -urN a/gopls/internal/lsp/testdata/imports/two_lines.go.golden b/gopls/internal/lsp/testdata/imports/two_lines.go.golden
98000--- a/gopls/internal/lsp/testdata/imports/two_lines.go.golden	2000-01-01 00:00:00.000000000 -0000
98001+++ b/gopls/internal/lsp/testdata/imports/two_lines.go.golden	1970-01-01 00:00:00.000000000 +0000
98002@@ -1,4 +0,0 @@
98003--- goimports --
98004-package main
98005-func main()  {} //@import("main")
98006-
98007diff -urN a/gopls/internal/lsp/testdata/imports/two_lines.go.in b/gopls/internal/lsp/testdata/imports/two_lines.go.in
98008--- a/gopls/internal/lsp/testdata/imports/two_lines.go.in	2000-01-01 00:00:00.000000000 -0000
98009+++ b/gopls/internal/lsp/testdata/imports/two_lines.go.in	1970-01-01 00:00:00.000000000 +0000
98010@@ -1,2 +0,0 @@
98011-package main
98012-func main()  {} //@import("main")
98013diff -urN a/gopls/internal/lsp/testdata/index/index.go b/gopls/internal/lsp/testdata/index/index.go
98014--- a/gopls/internal/lsp/testdata/index/index.go	2000-01-01 00:00:00.000000000 -0000
98015+++ b/gopls/internal/lsp/testdata/index/index.go	1970-01-01 00:00:00.000000000 +0000
98016@@ -1,25 +0,0 @@
98017-package index
98018-
98019-func _() {
98020-	var (
98021-		aa = "123" //@item(indexAA, "aa", "string", "var")
98022-		ab = 123   //@item(indexAB, "ab", "int", "var")
98023-	)
98024-
98025-	var foo [1]int
98026-	foo[a]  //@complete("]", indexAB, indexAA)
98027-	foo[:a] //@complete("]", indexAB, indexAA)
98028-	a[:a]   //@complete("[", indexAA, indexAB)
98029-	a[a]    //@complete("[", indexAA, indexAB)
98030-
98031-	var bar map[string]int
98032-	bar[a] //@complete("]", indexAA, indexAB)
98033-
98034-	type myMap map[string]int
98035-	var baz myMap
98036-	baz[a] //@complete("]", indexAA, indexAB)
98037-
98038-	type myInt int
98039-	var mi myInt //@item(indexMyInt, "mi", "myInt", "var")
98040-	foo[m]       //@snippet("]", indexMyInt, "mi", "mi")
98041-}
98042diff -urN a/gopls/internal/lsp/testdata/inlay_hint/composite_literals.go b/gopls/internal/lsp/testdata/inlay_hint/composite_literals.go
98043--- a/gopls/internal/lsp/testdata/inlay_hint/composite_literals.go	2000-01-01 00:00:00.000000000 -0000
98044+++ b/gopls/internal/lsp/testdata/inlay_hint/composite_literals.go	1970-01-01 00:00:00.000000000 +0000
98045@@ -1,27 +0,0 @@
98046-package inlayHint //@inlayHint("package")
98047-
98048-import "fmt"
98049-
98050-func fieldNames() {
98051-	for _, c := range []struct {
98052-		in, want string
98053-	}{
98054-		struct{ in, want string }{"Hello, world", "dlrow ,olleH"},
98055-		{"Hello, 世界", "界世 ,olleH"},
98056-		{"", ""},
98057-	} {
98058-		fmt.Println(c.in == c.want)
98059-	}
98060-}
98061-
98062-func fieldNamesPointers() {
98063-	for _, c := range []*struct {
98064-		in, want string
98065-	}{
98066-		&struct{ in, want string }{"Hello, world", "dlrow ,olleH"},
98067-		{"Hello, 世界", "界世 ,olleH"},
98068-		{"", ""},
98069-	} {
98070-		fmt.Println(c.in == c.want)
98071-	}
98072-}
98073diff -urN a/gopls/internal/lsp/testdata/inlay_hint/composite_literals.go.golden b/gopls/internal/lsp/testdata/inlay_hint/composite_literals.go.golden
98074--- a/gopls/internal/lsp/testdata/inlay_hint/composite_literals.go.golden	2000-01-01 00:00:00.000000000 -0000
98075+++ b/gopls/internal/lsp/testdata/inlay_hint/composite_literals.go.golden	1970-01-01 00:00:00.000000000 +0000
98076@@ -1,29 +0,0 @@
98077--- inlayHint --
98078-package inlayHint //@inlayHint("package")
98079-
98080-import "fmt"
98081-
98082-func fieldNames() {
98083-	for _< int>, c< struct{in string; want string}> := range []struct {
98084-		in, want string
98085-	}{
98086-		struct{ in, want string }{<in: >"Hello, world", <want: >"dlrow ,olleH"},
98087-		<struct{in string; want string}>{<in: >"Hello, 世界", <want: >"界世 ,olleH"},
98088-		<struct{in string; want string}>{<in: >"", <want: >""},
98089-	} {
98090-		fmt.Println(<a...: >c.in == c.want)
98091-	}
98092-}
98093-
98094-func fieldNamesPointers() {
98095-	for _< int>, c< *struct{in string; want string}> := range []*struct {
98096-		in, want string
98097-	}{
98098-		&struct{ in, want string }{<in: >"Hello, world", <want: >"dlrow ,olleH"},
98099-		<&struct{in string; want string}>{<in: >"Hello, 世界", <want: >"界世 ,olleH"},
98100-		<&struct{in string; want string}>{<in: >"", <want: >""},
98101-	} {
98102-		fmt.Println(<a...: >c.in == c.want)
98103-	}
98104-}
98105-
98106diff -urN a/gopls/internal/lsp/testdata/inlay_hint/constant_values.go b/gopls/internal/lsp/testdata/inlay_hint/constant_values.go
98107--- a/gopls/internal/lsp/testdata/inlay_hint/constant_values.go	2000-01-01 00:00:00.000000000 -0000
98108+++ b/gopls/internal/lsp/testdata/inlay_hint/constant_values.go	1970-01-01 00:00:00.000000000 +0000
98109@@ -1,45 +0,0 @@
98110-package inlayHint //@inlayHint("package")
98111-
98112-const True = true
98113-
98114-type Kind int
98115-
98116-const (
98117-	KindNone Kind = iota
98118-	KindPrint
98119-	KindPrintf
98120-	KindErrorf
98121-)
98122-
98123-const (
98124-	u         = iota * 4
98125-	v float64 = iota * 42
98126-	w         = iota * 42
98127-)
98128-
98129-const (
98130-	a, b = 1, 2
98131-	c, d
98132-	e, f = 5 * 5, "hello" + "world"
98133-	g, h
98134-	i, j = true, f
98135-)
98136-
98137-// No hint
98138-const (
98139-	Int     = 3
98140-	Float   = 3.14
98141-	Bool    = true
98142-	Rune    = '3'
98143-	Complex = 2.7i
98144-	String  = "Hello, world!"
98145-)
98146-
98147-var (
98148-	varInt     = 3
98149-	varFloat   = 3.14
98150-	varBool    = true
98151-	varRune    = '3' + '4'
98152-	varComplex = 2.7i
98153-	varString  = "Hello, world!"
98154-)
98155diff -urN a/gopls/internal/lsp/testdata/inlay_hint/constant_values.go.golden b/gopls/internal/lsp/testdata/inlay_hint/constant_values.go.golden
98156--- a/gopls/internal/lsp/testdata/inlay_hint/constant_values.go.golden	2000-01-01 00:00:00.000000000 -0000
98157+++ b/gopls/internal/lsp/testdata/inlay_hint/constant_values.go.golden	1970-01-01 00:00:00.000000000 +0000
98158@@ -1,47 +0,0 @@
98159--- inlayHint --
98160-package inlayHint //@inlayHint("package")
98161-
98162-const True = true
98163-
98164-type Kind int
98165-
98166-const (
98167-	KindNone Kind = iota< = 0>
98168-	KindPrint< = 1>
98169-	KindPrintf< = 2>
98170-	KindErrorf< = 3>
98171-)
98172-
98173-const (
98174-	u         = iota * 4< = 0>
98175-	v float64 = iota * 42< = 42>
98176-	w         = iota * 42< = 84>
98177-)
98178-
98179-const (
98180-	a, b = 1, 2
98181-	c, d< = 1, 2>
98182-	e, f = 5 * 5, "hello" + "world"< = 25, "helloworld">
98183-	g, h< = 25, "helloworld">
98184-	i, j = true, f< = true, "helloworld">
98185-)
98186-
98187-// No hint
98188-const (
98189-	Int     = 3
98190-	Float   = 3.14
98191-	Bool    = true
98192-	Rune    = '3'
98193-	Complex = 2.7i
98194-	String  = "Hello, world!"
98195-)
98196-
98197-var (
98198-	varInt     = 3
98199-	varFloat   = 3.14
98200-	varBool    = true
98201-	varRune    = '3' + '4'
98202-	varComplex = 2.7i
98203-	varString  = "Hello, world!"
98204-)
98205-
98206diff -urN a/gopls/internal/lsp/testdata/inlay_hint/parameter_names.go b/gopls/internal/lsp/testdata/inlay_hint/parameter_names.go
98207--- a/gopls/internal/lsp/testdata/inlay_hint/parameter_names.go	2000-01-01 00:00:00.000000000 -0000
98208+++ b/gopls/internal/lsp/testdata/inlay_hint/parameter_names.go	1970-01-01 00:00:00.000000000 +0000
98209@@ -1,50 +0,0 @@
98210-package inlayHint //@inlayHint("package")
98211-
98212-import "fmt"
98213-
98214-func hello(name string) string {
98215-	return "Hello " + name
98216-}
98217-
98218-func helloWorld() string {
98219-	return hello("World")
98220-}
98221-
98222-type foo struct{}
98223-
98224-func (*foo) bar(baz string, qux int) int {
98225-	if baz != "" {
98226-		return qux + 1
98227-	}
98228-	return qux
98229-}
98230-
98231-func kase(foo int, bar bool, baz ...string) {
98232-	fmt.Println(foo, bar, baz)
98233-}
98234-
98235-func kipp(foo string, bar, baz string) {
98236-	fmt.Println(foo, bar, baz)
98237-}
98238-
98239-func plex(foo, bar string, baz string) {
98240-	fmt.Println(foo, bar, baz)
98241-}
98242-
98243-func tars(foo string, bar, baz string) {
98244-	fmt.Println(foo, bar, baz)
98245-}
98246-
98247-func foobar() {
98248-	var x foo
98249-	x.bar("", 1)
98250-	kase(0, true, "c", "d", "e")
98251-	kipp("a", "b", "c")
98252-	plex("a", "b", "c")
98253-	tars("a", "b", "c")
98254-	foo, bar, baz := "a", "b", "c"
98255-	kipp(foo, bar, baz)
98256-	plex("a", bar, baz)
98257-	tars(foo+foo, (bar), "c")
98258-
98259-}
98260diff -urN a/gopls/internal/lsp/testdata/inlay_hint/parameter_names.go.golden b/gopls/internal/lsp/testdata/inlay_hint/parameter_names.go.golden
98261--- a/gopls/internal/lsp/testdata/inlay_hint/parameter_names.go.golden	2000-01-01 00:00:00.000000000 -0000
98262+++ b/gopls/internal/lsp/testdata/inlay_hint/parameter_names.go.golden	1970-01-01 00:00:00.000000000 +0000
98263@@ -1,52 +0,0 @@
98264--- inlayHint --
98265-package inlayHint //@inlayHint("package")
98266-
98267-import "fmt"
98268-
98269-func hello(name string) string {
98270-	return "Hello " + name
98271-}
98272-
98273-func helloWorld() string {
98274-	return hello(<name: >"World")
98275-}
98276-
98277-type foo struct{}
98278-
98279-func (*foo) bar(baz string, qux int) int {
98280-	if baz != "" {
98281-		return qux + 1
98282-	}
98283-	return qux
98284-}
98285-
98286-func kase(foo int, bar bool, baz ...string) {
98287-	fmt.Println(<a...: >foo, bar, baz)
98288-}
98289-
98290-func kipp(foo string, bar, baz string) {
98291-	fmt.Println(<a...: >foo, bar, baz)
98292-}
98293-
98294-func plex(foo, bar string, baz string) {
98295-	fmt.Println(<a...: >foo, bar, baz)
98296-}
98297-
98298-func tars(foo string, bar, baz string) {
98299-	fmt.Println(<a...: >foo, bar, baz)
98300-}
98301-
98302-func foobar() {
98303-	var x foo
98304-	x.bar(<baz: >"", <qux: >1)
98305-	kase(<foo: >0, <bar: >true, <baz...: >"c", "d", "e")
98306-	kipp(<foo: >"a", <bar: >"b", <baz: >"c")
98307-	plex(<foo: >"a", <bar: >"b", <baz: >"c")
98308-	tars(<foo: >"a", <bar: >"b", <baz: >"c")
98309-	foo< string>, bar< string>, baz< string> := "a", "b", "c"
98310-	kipp(foo, bar, baz)
98311-	plex(<foo: >"a", bar, baz)
98312-	tars(<foo: >foo+foo, <bar: >(bar), <baz: >"c")
98313-
98314-}
98315-
98316diff -urN a/gopls/internal/lsp/testdata/inlay_hint/type_params.go b/gopls/internal/lsp/testdata/inlay_hint/type_params.go
98317--- a/gopls/internal/lsp/testdata/inlay_hint/type_params.go	2000-01-01 00:00:00.000000000 -0000
98318+++ b/gopls/internal/lsp/testdata/inlay_hint/type_params.go	1970-01-01 00:00:00.000000000 +0000
98319@@ -1,45 +0,0 @@
98320-//go:build go1.18
98321-// +build go1.18
98322-
98323-package inlayHint //@inlayHint("package")
98324-
98325-func main() {
98326-	ints := map[string]int64{
98327-		"first":  34,
98328-		"second": 12,
98329-	}
98330-
98331-	floats := map[string]float64{
98332-		"first":  35.98,
98333-		"second": 26.99,
98334-	}
98335-
98336-	SumIntsOrFloats[string, int64](ints)
98337-	SumIntsOrFloats[string, float64](floats)
98338-
98339-	SumIntsOrFloats(ints)
98340-	SumIntsOrFloats(floats)
98341-
98342-	SumNumbers(ints)
98343-	SumNumbers(floats)
98344-}
98345-
98346-type Number interface {
98347-	int64 | float64
98348-}
98349-
98350-func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {
98351-	var s V
98352-	for _, v := range m {
98353-		s += v
98354-	}
98355-	return s
98356-}
98357-
98358-func SumNumbers[K comparable, V Number](m map[K]V) V {
98359-	var s V
98360-	for _, v := range m {
98361-		s += v
98362-	}
98363-	return s
98364-}
98365diff -urN a/gopls/internal/lsp/testdata/inlay_hint/type_params.go.golden b/gopls/internal/lsp/testdata/inlay_hint/type_params.go.golden
98366--- a/gopls/internal/lsp/testdata/inlay_hint/type_params.go.golden	2000-01-01 00:00:00.000000000 -0000
98367+++ b/gopls/internal/lsp/testdata/inlay_hint/type_params.go.golden	1970-01-01 00:00:00.000000000 +0000
98368@@ -1,47 +0,0 @@
98369--- inlayHint --
98370-//go:build go1.18
98371-// +build go1.18
98372-
98373-package inlayHint //@inlayHint("package")
98374-
98375-func main() {
98376-	ints< map[string]int64> := map[string]int64{
98377-		"first":  34,
98378-		"second": 12,
98379-	}
98380-
98381-	floats< map[string]float64> := map[string]float64{
98382-		"first":  35.98,
98383-		"second": 26.99,
98384-	}
98385-
98386-	SumIntsOrFloats[string, int64](<m: >ints)
98387-	SumIntsOrFloats[string, float64](<m: >floats)
98388-
98389-	SumIntsOrFloats<[string, int64]>(<m: >ints)
98390-	SumIntsOrFloats<[string, float64]>(<m: >floats)
98391-
98392-	SumNumbers<[string, int64]>(<m: >ints)
98393-	SumNumbers<[string, float64]>(<m: >floats)
98394-}
98395-
98396-type Number interface {
98397-	int64 | float64
98398-}
98399-
98400-func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {
98401-	var s V
98402-	for _< K>, v< V> := range m {
98403-		s += v
98404-	}
98405-	return s
98406-}
98407-
98408-func SumNumbers[K comparable, V Number](m map[K]V) V {
98409-	var s V
98410-	for _< K>, v< V> := range m {
98411-		s += v
98412-	}
98413-	return s
98414-}
98415-
98416diff -urN a/gopls/internal/lsp/testdata/inlay_hint/variable_types.go b/gopls/internal/lsp/testdata/inlay_hint/variable_types.go
98417--- a/gopls/internal/lsp/testdata/inlay_hint/variable_types.go	2000-01-01 00:00:00.000000000 -0000
98418+++ b/gopls/internal/lsp/testdata/inlay_hint/variable_types.go	1970-01-01 00:00:00.000000000 +0000
98419@@ -1,20 +0,0 @@
98420-package inlayHint //@inlayHint("package")
98421-
98422-func assignTypes() {
98423-	i, j := 0, len([]string{})-1
98424-	println(i, j)
98425-}
98426-
98427-func rangeTypes() {
98428-	for k, v := range []string{} {
98429-		println(k, v)
98430-	}
98431-}
98432-
98433-func funcLitType() {
98434-	myFunc := func(a string) string { return "" }
98435-}
98436-
98437-func compositeLitType() {
98438-	foo := map[string]interface{}{"": ""}
98439-}
98440diff -urN a/gopls/internal/lsp/testdata/inlay_hint/variable_types.go.golden b/gopls/internal/lsp/testdata/inlay_hint/variable_types.go.golden
98441--- a/gopls/internal/lsp/testdata/inlay_hint/variable_types.go.golden	2000-01-01 00:00:00.000000000 -0000
98442+++ b/gopls/internal/lsp/testdata/inlay_hint/variable_types.go.golden	1970-01-01 00:00:00.000000000 +0000
98443@@ -1,22 +0,0 @@
98444--- inlayHint --
98445-package inlayHint //@inlayHint("package")
98446-
98447-func assignTypes() {
98448-	i< int>, j< int> := 0, len([]string{})-1
98449-	println(i, j)
98450-}
98451-
98452-func rangeTypes() {
98453-	for k< int>, v< string> := range []string{} {
98454-		println(k, v)
98455-	}
98456-}
98457-
98458-func funcLitType() {
98459-	myFunc< func(a string) string> := func(a string) string { return "" }
98460-}
98461-
98462-func compositeLitType() {
98463-	foo< map[string]interface{}> := map[string]interface{}{"": ""}
98464-}
98465-
98466diff -urN a/gopls/internal/lsp/testdata/interfacerank/interface_rank.go b/gopls/internal/lsp/testdata/interfacerank/interface_rank.go
98467--- a/gopls/internal/lsp/testdata/interfacerank/interface_rank.go	2000-01-01 00:00:00.000000000 -0000
98468+++ b/gopls/internal/lsp/testdata/interfacerank/interface_rank.go	1970-01-01 00:00:00.000000000 +0000
98469@@ -1,23 +0,0 @@
98470-package interfacerank
98471-
98472-type foo interface {
98473-	foo()
98474-}
98475-
98476-type fooImpl int
98477-
98478-func (*fooImpl) foo() {}
98479-
98480-func wantsFoo(foo) {}
98481-
98482-func _() {
98483-	var (
98484-		aa string   //@item(irAA, "aa", "string", "var")
98485-		ab *fooImpl //@item(irAB, "ab", "*fooImpl", "var")
98486-	)
98487-
98488-	wantsFoo(a) //@complete(")", irAB, irAA)
98489-
98490-	var ac fooImpl //@item(irAC, "ac", "fooImpl", "var")
98491-	wantsFoo(&a)   //@complete(")", irAC, irAA, irAB)
98492-}
98493diff -urN a/gopls/internal/lsp/testdata/issues/issue56505.go b/gopls/internal/lsp/testdata/issues/issue56505.go
98494--- a/gopls/internal/lsp/testdata/issues/issue56505.go	2000-01-01 00:00:00.000000000 -0000
98495+++ b/gopls/internal/lsp/testdata/issues/issue56505.go	1970-01-01 00:00:00.000000000 +0000
98496@@ -1,8 +0,0 @@
98497-package issues
98498-
98499-// Test for golang/go#56505: completion on variables of type *error should not
98500-// panic.
98501-func _() {
98502-	var e *error
98503-	e.x //@complete(" //")
98504-}
98505diff -urN a/gopls/internal/lsp/testdata/keywords/accidental_keywords.go.in b/gopls/internal/lsp/testdata/keywords/accidental_keywords.go.in
98506--- a/gopls/internal/lsp/testdata/keywords/accidental_keywords.go.in	2000-01-01 00:00:00.000000000 -0000
98507+++ b/gopls/internal/lsp/testdata/keywords/accidental_keywords.go.in	1970-01-01 00:00:00.000000000 +0000
98508@@ -1,31 +0,0 @@
98509-package keywords
98510-
98511-// non-matching candidate - shouldn't show up as completion
98512-var apple = "apple"
98513-
98514-func _() {
98515-	foo.bar() // insert some extra statements to exercise our AST surgery
98516-	variance := 123 //@item(kwVariance, "variance", "int", "var")
98517-	foo.bar()
98518-	println(var) //@complete(")", kwVariance)
98519-}
98520-
98521-func _() {
98522-	foo.bar()
98523-	var s struct { variance int } //@item(kwVarianceField, "variance", "int", "field")
98524-	foo.bar()
98525-	s.var //@complete(" //", kwVarianceField)
98526-}
98527-
98528-func _() {
98529-	channel := 123 //@item(kwChannel, "channel", "int", "var")
98530-	chan //@complete(" //", kwChannel)
98531-	foo.bar()
98532-}
98533-
98534-func _() {
98535-	foo.bar()
98536-	var typeName string //@item(kwTypeName, "typeName", "string", "var")
98537-	foo.bar()
98538-	type //@complete(" //", kwTypeName)
98539-}
98540diff -urN a/gopls/internal/lsp/testdata/keywords/empty_select.go b/gopls/internal/lsp/testdata/keywords/empty_select.go
98541--- a/gopls/internal/lsp/testdata/keywords/empty_select.go	2000-01-01 00:00:00.000000000 -0000
98542+++ b/gopls/internal/lsp/testdata/keywords/empty_select.go	1970-01-01 00:00:00.000000000 +0000
98543@@ -1,7 +0,0 @@
98544-package keywords
98545-
98546-func _() {
98547-	select {
98548-		c //@complete(" //", case)
98549-	}
98550-}
98551diff -urN a/gopls/internal/lsp/testdata/keywords/empty_switch.go b/gopls/internal/lsp/testdata/keywords/empty_switch.go
98552--- a/gopls/internal/lsp/testdata/keywords/empty_switch.go	2000-01-01 00:00:00.000000000 -0000
98553+++ b/gopls/internal/lsp/testdata/keywords/empty_switch.go	1970-01-01 00:00:00.000000000 +0000
98554@@ -1,11 +0,0 @@
98555-package keywords
98556-
98557-func _() {
98558-	switch {
98559-		//@complete("", case, default)
98560-	}
98561-
98562-	switch test.(type) {
98563-		d //@complete(" //", default)
98564-	}
98565-}
98566diff -urN a/gopls/internal/lsp/testdata/keywords/keywords.go b/gopls/internal/lsp/testdata/keywords/keywords.go
98567--- a/gopls/internal/lsp/testdata/keywords/keywords.go	2000-01-01 00:00:00.000000000 -0000
98568+++ b/gopls/internal/lsp/testdata/keywords/keywords.go	1970-01-01 00:00:00.000000000 +0000
98569@@ -1,100 +0,0 @@
98570-package keywords
98571-
98572-//@rank("", type),rank("", func),rank("", var),rank("", const),rank("", import)
98573-
98574-func _() {
98575-	var test int //@rank(" //", int, interface)
98576-	var tChan chan int
98577-	var _ m //@complete(" //", map)
98578-	var _ f //@complete(" //", func)
98579-	var _ c //@complete(" //", chan)
98580-
98581-	var _ str //@rank(" //", string, struct)
98582-
98583-	type _ int //@rank(" //", interface, int)
98584-
98585-	type _ str //@rank(" //", struct, string)
98586-
98587-	switch test {
98588-	case 1: // TODO: trying to complete case here will break because the parser won't return *ast.Ident
98589-		b //@complete(" //", break)
98590-	case 2:
98591-		f //@complete(" //", fallthrough, for)
98592-		r //@complete(" //", return)
98593-		d //@complete(" //", default, defer)
98594-		c //@complete(" //", case, const)
98595-	}
98596-
98597-	switch test.(type) {
98598-	case fo: //@complete(":")
98599-	case int:
98600-		b //@complete(" //", break)
98601-	case int32:
98602-		f //@complete(" //", for)
98603-		d //@complete(" //", default, defer)
98604-		r //@complete(" //", return)
98605-		c //@complete(" //", case, const)
98606-	}
98607-
98608-	select {
98609-	case <-tChan:
98610-		b //@complete(" //", break)
98611-		c //@complete(" //", case, const)
98612-	}
98613-
98614-	for index := 0; index < test; index++ {
98615-		c //@complete(" //", const, continue)
98616-		b //@complete(" //", break)
98617-	}
98618-
98619-	for range []int{} {
98620-		c //@complete(" //", const, continue)
98621-		b //@complete(" //", break)
98622-	}
98623-
98624-	// Test function level keywords
98625-
98626-	//Using 2 characters to test because map output order is random
98627-	sw //@complete(" //", switch)
98628-	se //@complete(" //", select)
98629-
98630-	f //@complete(" //", for)
98631-	d //@complete(" //", defer)
98632-	g //@rank(" //", go),rank(" //", goto)
98633-	r //@complete(" //", return)
98634-	i //@complete(" //", if)
98635-	e //@complete(" //", else)
98636-	v //@complete(" //", var)
98637-	c //@complete(" //", const)
98638-
98639-	for i := r //@complete(" //", range)
98640-}
98641-
98642-/* package */ //@item(package, "package", "", "keyword")
98643-/* import */ //@item(import, "import", "", "keyword")
98644-/* func */ //@item(func, "func", "", "keyword")
98645-/* type */ //@item(type, "type", "", "keyword")
98646-/* var */ //@item(var, "var", "", "keyword")
98647-/* const */ //@item(const, "const", "", "keyword")
98648-/* break */ //@item(break, "break", "", "keyword")
98649-/* default */ //@item(default, "default", "", "keyword")
98650-/* case */ //@item(case, "case", "", "keyword")
98651-/* defer */ //@item(defer, "defer", "", "keyword")
98652-/* go */ //@item(go, "go", "", "keyword")
98653-/* for */ //@item(for, "for", "", "keyword")
98654-/* if */ //@item(if, "if", "", "keyword")
98655-/* else */ //@item(else, "else", "", "keyword")
98656-/* switch */ //@item(switch, "switch", "", "keyword")
98657-/* select */ //@item(select, "select", "", "keyword")
98658-/* fallthrough */ //@item(fallthrough, "fallthrough", "", "keyword")
98659-/* continue */ //@item(continue, "continue", "", "keyword")
98660-/* return */ //@item(return, "return", "", "keyword")
98661-/* var */ //@item(var, "var", "", "keyword")
98662-/* const */ //@item(const, "const", "", "keyword")
98663-/* goto */ //@item(goto, "goto", "", "keyword")
98664-/* struct */ //@item(struct, "struct", "", "keyword")
98665-/* interface */ //@item(interface, "interface", "", "keyword")
98666-/* map */ //@item(map, "map", "", "keyword")
98667-/* func */ //@item(func, "func", "", "keyword")
98668-/* chan */ //@item(chan, "chan", "", "keyword")
98669-/* range */ //@item(range, "range", "", "keyword")
98670diff -urN a/gopls/internal/lsp/testdata/labels/labels.go b/gopls/internal/lsp/testdata/labels/labels.go
98671--- a/gopls/internal/lsp/testdata/labels/labels.go	2000-01-01 00:00:00.000000000 -0000
98672+++ b/gopls/internal/lsp/testdata/labels/labels.go	1970-01-01 00:00:00.000000000 +0000
98673@@ -1,49 +0,0 @@
98674-package labels
98675-
98676-func _() {
98677-	goto F //@complete(" //", label1, label5)
98678-
98679-Foo1: //@item(label1, "Foo1", "label", "const")
98680-	for a, b := range []int{} {
98681-	Foo2: //@item(label2, "Foo2", "label", "const")
98682-		switch {
98683-		case true:
98684-			break F //@complete(" //", label2, label1)
98685-
98686-			continue F //@complete(" //", label1)
98687-
98688-			{
98689-			FooUnjumpable:
98690-			}
98691-
98692-			goto F //@complete(" //", label1, label2, label4, label5)
98693-
98694-			func() {
98695-				goto F //@complete(" //", label3)
98696-
98697-				break F //@complete(" //")
98698-
98699-				continue F //@complete(" //")
98700-
98701-			Foo3: //@item(label3, "Foo3", "label", "const")
98702-			}()
98703-		}
98704-
98705-	Foo4: //@item(label4, "Foo4", "label", "const")
98706-		switch interface{}(a).(type) {
98707-		case int:
98708-			break F //@complete(" //", label4, label1)
98709-		}
98710-	}
98711-
98712-	break F //@complete(" //")
98713-
98714-	continue F //@complete(" //")
98715-
98716-Foo5: //@item(label5, "Foo5", "label", "const")
98717-	for {
98718-		break F //@complete(" //", label5)
98719-	}
98720-
98721-	return
98722-}
98723diff -urN a/gopls/internal/lsp/testdata/links/links.go b/gopls/internal/lsp/testdata/links/links.go
98724--- a/gopls/internal/lsp/testdata/links/links.go	2000-01-01 00:00:00.000000000 -0000
98725+++ b/gopls/internal/lsp/testdata/links/links.go	1970-01-01 00:00:00.000000000 +0000
98726@@ -1,26 +0,0 @@
98727-package links
98728-
98729-import (
98730-	"fmt" //@link(`fmt`,"https://pkg.go.dev/fmt")
98731-
98732-	"golang.org/lsptests/foo" //@link(`golang.org/lsptests/foo`,`https://pkg.go.dev/golang.org/lsptests/foo`)
98733-
98734-	_ "database/sql" //@link(`database/sql`, `https://pkg.go.dev/database/sql`)
98735-)
98736-
98737-var (
98738-	_ fmt.Formatter
98739-	_ foo.StructFoo
98740-	_ errors.Formatter
98741-)
98742-
98743-// Foo function
98744-func Foo() string {
98745-	/*https://example.com/comment */ //@link("https://example.com/comment","https://example.com/comment")
98746-
98747-	url := "https://example.com/string_literal" //@link("https://example.com/string_literal","https://example.com/string_literal")
98748-	return url
98749-
98750-	// TODO(golang/go#1234): Link the relevant issue. //@link("golang/go#1234", "https://github.com/golang/go/issues/1234")
98751-	// TODO(microsoft/vscode-go#12): Another issue. //@link("microsoft/vscode-go#12", "https://github.com/microsoft/vscode-go/issues/12")
98752-}
98753diff -urN a/gopls/internal/lsp/testdata/maps/maps.go.in b/gopls/internal/lsp/testdata/maps/maps.go.in
98754--- a/gopls/internal/lsp/testdata/maps/maps.go.in	2000-01-01 00:00:00.000000000 -0000
98755+++ b/gopls/internal/lsp/testdata/maps/maps.go.in	1970-01-01 00:00:00.000000000 +0000
98756@@ -1,18 +0,0 @@
98757-package maps
98758-
98759-func _() {
98760-	var aVar int          //@item(mapVar, "aVar", "int", "var")
98761-
98762-	// not comparabale
98763-	type aSlice []int     //@item(mapSliceType, "aSlice", "[]int", "type")
98764-
98765-	*aSlice     //@item(mapSliceTypePtr, "*aSlice", "[]int", "type")
98766-
98767-	// comparable
98768-	type aStruct struct{} //@item(mapStructType, "aStruct", "struct{...}", "struct")
98769-
98770-	map[]a{} //@complete("]", mapSliceType, mapStructType),snippet("]", mapSliceType, "*aSlice", "*aSlice")
98771-
98772-	map[a]a{} //@complete("]", mapSliceType, mapStructType)
98773-	map[a]a{} //@complete("{", mapSliceType, mapStructType)
98774-}
98775diff -urN a/gopls/internal/lsp/testdata/missingfunction/channels.go b/gopls/internal/lsp/testdata/missingfunction/channels.go
98776--- a/gopls/internal/lsp/testdata/missingfunction/channels.go	2000-01-01 00:00:00.000000000 -0000
98777+++ b/gopls/internal/lsp/testdata/missingfunction/channels.go	1970-01-01 00:00:00.000000000 +0000
98778@@ -1,9 +0,0 @@
98779-package missingfunction
98780-
98781-func channels(s string) {
98782-	undefinedChannels(c()) //@suggestedfix("undefinedChannels", "quickfix", "")
98783-}
98784-
98785-func c() (<-chan string, chan string) {
98786-	return make(<-chan string), make(chan string)
98787-}
98788diff -urN a/gopls/internal/lsp/testdata/missingfunction/channels.go.golden b/gopls/internal/lsp/testdata/missingfunction/channels.go.golden
98789--- a/gopls/internal/lsp/testdata/missingfunction/channels.go.golden	2000-01-01 00:00:00.000000000 -0000
98790+++ b/gopls/internal/lsp/testdata/missingfunction/channels.go.golden	1970-01-01 00:00:00.000000000 +0000
98791@@ -1,15 +0,0 @@
98792--- suggestedfix_channels_4_2 --
98793-package missingfunction
98794-
98795-func channels(s string) {
98796-	undefinedChannels(c()) //@suggestedfix("undefinedChannels", "quickfix", "")
98797-}
98798-
98799-func undefinedChannels(ch1 <-chan string, ch2 chan string) {
98800-	panic("unimplemented")
98801-}
98802-
98803-func c() (<-chan string, chan string) {
98804-	return make(<-chan string), make(chan string)
98805-}
98806-
98807diff -urN a/gopls/internal/lsp/testdata/missingfunction/consecutive_params.go b/gopls/internal/lsp/testdata/missingfunction/consecutive_params.go
98808--- a/gopls/internal/lsp/testdata/missingfunction/consecutive_params.go	2000-01-01 00:00:00.000000000 -0000
98809+++ b/gopls/internal/lsp/testdata/missingfunction/consecutive_params.go	1970-01-01 00:00:00.000000000 +0000
98810@@ -1,6 +0,0 @@
98811-package missingfunction
98812-
98813-func consecutiveParams() {
98814-	var s string
98815-	undefinedConsecutiveParams(s, s) //@suggestedfix("undefinedConsecutiveParams", "quickfix", "")
98816-}
98817diff -urN a/gopls/internal/lsp/testdata/missingfunction/consecutive_params.go.golden b/gopls/internal/lsp/testdata/missingfunction/consecutive_params.go.golden
98818--- a/gopls/internal/lsp/testdata/missingfunction/consecutive_params.go.golden	2000-01-01 00:00:00.000000000 -0000
98819+++ b/gopls/internal/lsp/testdata/missingfunction/consecutive_params.go.golden	1970-01-01 00:00:00.000000000 +0000
98820@@ -1,12 +0,0 @@
98821--- suggestedfix_consecutive_params_5_2 --
98822-package missingfunction
98823-
98824-func consecutiveParams() {
98825-	var s string
98826-	undefinedConsecutiveParams(s, s) //@suggestedfix("undefinedConsecutiveParams", "quickfix", "")
98827-}
98828-
98829-func undefinedConsecutiveParams(s1, s2 string) {
98830-	panic("unimplemented")
98831-}
98832-
98833diff -urN a/gopls/internal/lsp/testdata/missingfunction/error_param.go b/gopls/internal/lsp/testdata/missingfunction/error_param.go
98834--- a/gopls/internal/lsp/testdata/missingfunction/error_param.go	2000-01-01 00:00:00.000000000 -0000
98835+++ b/gopls/internal/lsp/testdata/missingfunction/error_param.go	1970-01-01 00:00:00.000000000 +0000
98836@@ -1,6 +0,0 @@
98837-package missingfunction
98838-
98839-func errorParam() {
98840-	var err error
98841-	undefinedErrorParam(err) //@suggestedfix("undefinedErrorParam", "quickfix", "")
98842-}
98843diff -urN a/gopls/internal/lsp/testdata/missingfunction/error_param.go.golden b/gopls/internal/lsp/testdata/missingfunction/error_param.go.golden
98844--- a/gopls/internal/lsp/testdata/missingfunction/error_param.go.golden	2000-01-01 00:00:00.000000000 -0000
98845+++ b/gopls/internal/lsp/testdata/missingfunction/error_param.go.golden	1970-01-01 00:00:00.000000000 +0000
98846@@ -1,12 +0,0 @@
98847--- suggestedfix_error_param_5_2 --
98848-package missingfunction
98849-
98850-func errorParam() {
98851-	var err error
98852-	undefinedErrorParam(err) //@suggestedfix("undefinedErrorParam", "quickfix", "")
98853-}
98854-
98855-func undefinedErrorParam(err error) {
98856-	panic("unimplemented")
98857-}
98858-
98859diff -urN a/gopls/internal/lsp/testdata/missingfunction/literals.go b/gopls/internal/lsp/testdata/missingfunction/literals.go
98860--- a/gopls/internal/lsp/testdata/missingfunction/literals.go	2000-01-01 00:00:00.000000000 -0000
98861+++ b/gopls/internal/lsp/testdata/missingfunction/literals.go	1970-01-01 00:00:00.000000000 +0000
98862@@ -1,7 +0,0 @@
98863-package missingfunction
98864-
98865-type T struct{}
98866-
98867-func literals() {
98868-	undefinedLiterals("hey compiler", T{}, &T{}) //@suggestedfix("undefinedLiterals", "quickfix", "")
98869-}
98870diff -urN a/gopls/internal/lsp/testdata/missingfunction/literals.go.golden b/gopls/internal/lsp/testdata/missingfunction/literals.go.golden
98871--- a/gopls/internal/lsp/testdata/missingfunction/literals.go.golden	2000-01-01 00:00:00.000000000 -0000
98872+++ b/gopls/internal/lsp/testdata/missingfunction/literals.go.golden	1970-01-01 00:00:00.000000000 +0000
98873@@ -1,13 +0,0 @@
98874--- suggestedfix_literals_6_2 --
98875-package missingfunction
98876-
98877-type T struct{}
98878-
98879-func literals() {
98880-	undefinedLiterals("hey compiler", T{}, &T{}) //@suggestedfix("undefinedLiterals", "quickfix", "")
98881-}
98882-
98883-func undefinedLiterals(s string, t1 T, t2 *T) {
98884-	panic("unimplemented")
98885-}
98886-
98887diff -urN a/gopls/internal/lsp/testdata/missingfunction/operation.go b/gopls/internal/lsp/testdata/missingfunction/operation.go
98888--- a/gopls/internal/lsp/testdata/missingfunction/operation.go	2000-01-01 00:00:00.000000000 -0000
98889+++ b/gopls/internal/lsp/testdata/missingfunction/operation.go	1970-01-01 00:00:00.000000000 +0000
98890@@ -1,7 +0,0 @@
98891-package missingfunction
98892-
98893-import "time"
98894-
98895-func operation() {
98896-	undefinedOperation(10 * time.Second) //@suggestedfix("undefinedOperation", "quickfix", "")
98897-}
98898diff -urN a/gopls/internal/lsp/testdata/missingfunction/operation.go.golden b/gopls/internal/lsp/testdata/missingfunction/operation.go.golden
98899--- a/gopls/internal/lsp/testdata/missingfunction/operation.go.golden	2000-01-01 00:00:00.000000000 -0000
98900+++ b/gopls/internal/lsp/testdata/missingfunction/operation.go.golden	1970-01-01 00:00:00.000000000 +0000
98901@@ -1,13 +0,0 @@
98902--- suggestedfix_operation_6_2 --
98903-package missingfunction
98904-
98905-import "time"
98906-
98907-func operation() {
98908-	undefinedOperation(10 * time.Second) //@suggestedfix("undefinedOperation", "quickfix", "")
98909-}
98910-
98911-func undefinedOperation(duration time.Duration) {
98912-	panic("unimplemented")
98913-}
98914-
98915diff -urN a/gopls/internal/lsp/testdata/missingfunction/selector.go b/gopls/internal/lsp/testdata/missingfunction/selector.go
98916--- a/gopls/internal/lsp/testdata/missingfunction/selector.go	2000-01-01 00:00:00.000000000 -0000
98917+++ b/gopls/internal/lsp/testdata/missingfunction/selector.go	1970-01-01 00:00:00.000000000 +0000
98918@@ -1,6 +0,0 @@
98919-package missingfunction
98920-
98921-func selector() {
98922-	m := map[int]bool{}
98923-	undefinedSelector(m[1]) //@suggestedfix("undefinedSelector", "quickfix", "")
98924-}
98925diff -urN a/gopls/internal/lsp/testdata/missingfunction/selector.go.golden b/gopls/internal/lsp/testdata/missingfunction/selector.go.golden
98926--- a/gopls/internal/lsp/testdata/missingfunction/selector.go.golden	2000-01-01 00:00:00.000000000 -0000
98927+++ b/gopls/internal/lsp/testdata/missingfunction/selector.go.golden	1970-01-01 00:00:00.000000000 +0000
98928@@ -1,12 +0,0 @@
98929--- suggestedfix_selector_5_2 --
98930-package missingfunction
98931-
98932-func selector() {
98933-	m := map[int]bool{}
98934-	undefinedSelector(m[1]) //@suggestedfix("undefinedSelector", "quickfix", "")
98935-}
98936-
98937-func undefinedSelector(b bool) {
98938-	panic("unimplemented")
98939-}
98940-
98941diff -urN a/gopls/internal/lsp/testdata/missingfunction/slice.go b/gopls/internal/lsp/testdata/missingfunction/slice.go
98942--- a/gopls/internal/lsp/testdata/missingfunction/slice.go	2000-01-01 00:00:00.000000000 -0000
98943+++ b/gopls/internal/lsp/testdata/missingfunction/slice.go	1970-01-01 00:00:00.000000000 +0000
98944@@ -1,5 +0,0 @@
98945-package missingfunction
98946-
98947-func slice() {
98948-	undefinedSlice([]int{1, 2}) //@suggestedfix("undefinedSlice", "quickfix", "")
98949-}
98950diff -urN a/gopls/internal/lsp/testdata/missingfunction/slice.go.golden b/gopls/internal/lsp/testdata/missingfunction/slice.go.golden
98951--- a/gopls/internal/lsp/testdata/missingfunction/slice.go.golden	2000-01-01 00:00:00.000000000 -0000
98952+++ b/gopls/internal/lsp/testdata/missingfunction/slice.go.golden	1970-01-01 00:00:00.000000000 +0000
98953@@ -1,11 +0,0 @@
98954--- suggestedfix_slice_4_2 --
98955-package missingfunction
98956-
98957-func slice() {
98958-	undefinedSlice([]int{1, 2}) //@suggestedfix("undefinedSlice", "quickfix", "")
98959-}
98960-
98961-func undefinedSlice(i []int) {
98962-	panic("unimplemented")
98963-}
98964-
98965diff -urN a/gopls/internal/lsp/testdata/missingfunction/tuple.go b/gopls/internal/lsp/testdata/missingfunction/tuple.go
98966--- a/gopls/internal/lsp/testdata/missingfunction/tuple.go	2000-01-01 00:00:00.000000000 -0000
98967+++ b/gopls/internal/lsp/testdata/missingfunction/tuple.go	1970-01-01 00:00:00.000000000 +0000
98968@@ -1,9 +0,0 @@
98969-package missingfunction
98970-
98971-func tuple() {
98972-	undefinedTuple(b()) //@suggestedfix("undefinedTuple", "quickfix", "")
98973-}
98974-
98975-func b() (string, error) {
98976-	return "", nil
98977-}
98978diff -urN a/gopls/internal/lsp/testdata/missingfunction/tuple.go.golden b/gopls/internal/lsp/testdata/missingfunction/tuple.go.golden
98979--- a/gopls/internal/lsp/testdata/missingfunction/tuple.go.golden	2000-01-01 00:00:00.000000000 -0000
98980+++ b/gopls/internal/lsp/testdata/missingfunction/tuple.go.golden	1970-01-01 00:00:00.000000000 +0000
98981@@ -1,15 +0,0 @@
98982--- suggestedfix_tuple_4_2 --
98983-package missingfunction
98984-
98985-func tuple() {
98986-	undefinedTuple(b()) //@suggestedfix("undefinedTuple", "quickfix", "")
98987-}
98988-
98989-func undefinedTuple(s string, err error) {
98990-	panic("unimplemented")
98991-}
98992-
98993-func b() (string, error) {
98994-	return "", nil
98995-}
98996-
98997diff -urN a/gopls/internal/lsp/testdata/missingfunction/unique_params.go b/gopls/internal/lsp/testdata/missingfunction/unique_params.go
98998--- a/gopls/internal/lsp/testdata/missingfunction/unique_params.go	2000-01-01 00:00:00.000000000 -0000
98999+++ b/gopls/internal/lsp/testdata/missingfunction/unique_params.go	1970-01-01 00:00:00.000000000 +0000
99000@@ -1,7 +0,0 @@
99001-package missingfunction
99002-
99003-func uniqueArguments() {
99004-	var s string
99005-	var i int
99006-	undefinedUniqueArguments(s, i, s) //@suggestedfix("undefinedUniqueArguments", "quickfix", "")
99007-}
99008diff -urN a/gopls/internal/lsp/testdata/missingfunction/unique_params.go.golden b/gopls/internal/lsp/testdata/missingfunction/unique_params.go.golden
99009--- a/gopls/internal/lsp/testdata/missingfunction/unique_params.go.golden	2000-01-01 00:00:00.000000000 -0000
99010+++ b/gopls/internal/lsp/testdata/missingfunction/unique_params.go.golden	1970-01-01 00:00:00.000000000 +0000
99011@@ -1,13 +0,0 @@
99012--- suggestedfix_unique_params_6_2 --
99013-package missingfunction
99014-
99015-func uniqueArguments() {
99016-	var s string
99017-	var i int
99018-	undefinedUniqueArguments(s, i, s) //@suggestedfix("undefinedUniqueArguments", "quickfix", "")
99019-}
99020-
99021-func undefinedUniqueArguments(s1 string, i int, s2 string) {
99022-	panic("unimplemented")
99023-}
99024-
99025diff -urN a/gopls/internal/lsp/testdata/multireturn/multi_return.go.in b/gopls/internal/lsp/testdata/multireturn/multi_return.go.in
99026--- a/gopls/internal/lsp/testdata/multireturn/multi_return.go.in	2000-01-01 00:00:00.000000000 -0000
99027+++ b/gopls/internal/lsp/testdata/multireturn/multi_return.go.in	1970-01-01 00:00:00.000000000 +0000
99028@@ -1,48 +0,0 @@
99029-package multireturn
99030-
99031-func f0() {} //@item(multiF0, "f0", "func()", "func")
99032-
99033-func f1(int) int { return 0 } //@item(multiF1, "f1", "func(int) int", "func")
99034-
99035-func f2(int, int) (int, int) { return 0, 0 } //@item(multiF2, "f2", "func(int, int) (int, int)", "func")
99036-
99037-func f2Str(string, string) (string, string) { return "", "" } //@item(multiF2Str, "f2Str", "func(string, string) (string, string)", "func")
99038-
99039-func f3(int, int, int) (int, int, int) { return 0, 0, 0 } //@item(multiF3, "f3", "func(int, int, int) (int, int, int)", "func")
99040-
99041-func _() {
99042-	_ := f //@rank(" //", multiF1, multiF2)
99043-
99044-	_, _ := f //@rank(" //", multiF2, multiF0),rank(" //", multiF1, multiF0)
99045-
99046-	_, _ := _, f //@rank(" //", multiF1, multiF2),rank(" //", multiF1, multiF0)
99047-
99048-	_, _ := f, abc //@rank(", abc", multiF1, multiF2)
99049-
99050-	f1()     //@rank(")", multiF1, multiF0)
99051-	f1(f)    //@rank(")", multiF1, multiF2)
99052-	f2(f)    //@rank(")", multiF2, multiF3),rank(")", multiF1, multiF3)
99053-	f2(1, f) //@rank(")", multiF1, multiF2),rank(")", multiF1, multiF0)
99054-	f2(1, )  //@rank(")", multiF1, multiF2),rank(")", multiF1, multiF0)
99055-	f2Str()  //@rank(")", multiF2Str, multiF2)
99056-
99057-	var i int
99058-	i, _ := f //@rank(" //", multiF2, multiF2Str)
99059-
99060-	var s string
99061-	_, s := f //@rank(" //", multiF2Str, multiF2)
99062-
99063-	banana, s = f //@rank(" //", multiF2, multiF3)
99064-
99065-	var variadic func(int, ...int)
99066-	variadic() //@rank(")", multiF1, multiF0),rank(")", multiF2, multiF0),rank(")", multiF3, multiF0)
99067-}
99068-
99069-func _() {
99070-	var baz func(...interface{})
99071-
99072-	var otterNap func() (int, int) //@item(multiTwo, "otterNap", "func() (int, int)", "var")
99073-	var one int                    //@item(multiOne, "one", "int", "var")
99074-
99075-	baz(on) //@rank(")", multiOne, multiTwo)
99076-}
99077diff -urN a/gopls/internal/lsp/testdata/nested_complit/nested_complit.go.in b/gopls/internal/lsp/testdata/nested_complit/nested_complit.go.in
99078--- a/gopls/internal/lsp/testdata/nested_complit/nested_complit.go.in	2000-01-01 00:00:00.000000000 -0000
99079+++ b/gopls/internal/lsp/testdata/nested_complit/nested_complit.go.in	1970-01-01 00:00:00.000000000 +0000
99080@@ -1,15 +0,0 @@
99081-package nested_complit
99082-
99083-type ncFoo struct {} //@item(structNCFoo, "ncFoo", "struct{...}", "struct")
99084-
99085-type ncBar struct { //@item(structNCBar, "ncBar", "struct{...}", "struct")
99086-	baz []ncFoo
99087-}
99088-
99089-func _() {
99090-	[]ncFoo{} //@item(litNCFoo, "[]ncFoo{}", "", "var")
99091-	_ := ncBar{
99092-		// disabled - see issue #54822
99093-		baz: [] // complete(" //", structNCFoo, structNCBar)
99094-	}
99095-}
99096diff -urN a/gopls/internal/lsp/testdata/nodisk/empty b/gopls/internal/lsp/testdata/nodisk/empty
99097--- a/gopls/internal/lsp/testdata/nodisk/empty	2000-01-01 00:00:00.000000000 -0000
99098+++ b/gopls/internal/lsp/testdata/nodisk/empty	1970-01-01 00:00:00.000000000 +0000
99099@@ -1 +0,0 @@
99100-an empty file so that this directory exists
99101\ No newline at end of file
99102diff -urN a/gopls/internal/lsp/testdata/nodisk/nodisk.overlay.go b/gopls/internal/lsp/testdata/nodisk/nodisk.overlay.go
99103--- a/gopls/internal/lsp/testdata/nodisk/nodisk.overlay.go	2000-01-01 00:00:00.000000000 -0000
99104+++ b/gopls/internal/lsp/testdata/nodisk/nodisk.overlay.go	1970-01-01 00:00:00.000000000 +0000
99105@@ -1,9 +0,0 @@
99106-package nodisk
99107-
99108-import (
99109-	"golang.org/lsptests/foo"
99110-)
99111-
99112-func _() {
99113-	foo.Foo() //@complete("F", Foo, IntFoo, StructFoo)
99114-}
99115diff -urN a/gopls/internal/lsp/testdata/noparse/noparse.go.in b/gopls/internal/lsp/testdata/noparse/noparse.go.in
99116--- a/gopls/internal/lsp/testdata/noparse/noparse.go.in	2000-01-01 00:00:00.000000000 -0000
99117+++ b/gopls/internal/lsp/testdata/noparse/noparse.go.in	1970-01-01 00:00:00.000000000 +0000
99118@@ -1,24 +0,0 @@
99119-package noparse
99120-
99121-// The type error was chosen carefully to exercise a type-error analyzer.
99122-// We use the 'nonewvars' analyzer because the other candidates are tricky:
99123-//
99124-// - The 'unusedvariable' analyzer is disabled by default, so it is not
99125-//   consistently enabled across Test{LSP,CommandLine} tests, which
99126-//   both process this file.
99127-// - The 'undeclaredname' analyzer depends on the text of the go/types
99128-//   "undeclared name" error, which changed in go1.20.
99129-// - The 'noresultvalues' analyzer produces a diagnostic containing newlines,
99130-//   which breaks the parser used by TestCommandLine.
99131-//
99132-// This comment is all that remains of my afternoon.
99133-
99134-func bye(x int) {
99135-	x := 123 //@diag(":=", "nonewvars", "no new variables", "warning")
99136-}
99137-
99138-func stuff() {
99139-
99140-}
99141-
99142-func .() {} //@diag(".", "syntax", "expected 'IDENT', found '.'", "error")
99143diff -urN a/gopls/internal/lsp/testdata/noparse_format/noparse_format.go.golden b/gopls/internal/lsp/testdata/noparse_format/noparse_format.go.golden
99144--- a/gopls/internal/lsp/testdata/noparse_format/noparse_format.go.golden	2000-01-01 00:00:00.000000000 -0000
99145+++ b/gopls/internal/lsp/testdata/noparse_format/noparse_format.go.golden	1970-01-01 00:00:00.000000000 +0000
99146@@ -1,2 +0,0 @@
99147--- gofmt --
99148-
99149diff -urN a/gopls/internal/lsp/testdata/noparse_format/noparse_format.go.in b/gopls/internal/lsp/testdata/noparse_format/noparse_format.go.in
99150--- a/gopls/internal/lsp/testdata/noparse_format/noparse_format.go.in	2000-01-01 00:00:00.000000000 -0000
99151+++ b/gopls/internal/lsp/testdata/noparse_format/noparse_format.go.in	1970-01-01 00:00:00.000000000 +0000
99152@@ -1,14 +0,0 @@
99153-// +build go1.11
99154-
99155-package noparse_format //@format("package")
99156-
99157-// The nonewvars expectation asserts that the go/analysis framework ran.
99158-// See comments in badstmt.
99159-
99160-func what() {
99161-	var hi func()
99162-	if {		hi() //@diag("{", "syntax", "missing condition in if statement", "error")
99163-	}
99164-	hi := nil //@diag(":=", "nonewvars", "no new variables", "warning")
99165-}
99166-
99167diff -urN a/gopls/internal/lsp/testdata/noparse_format/parse_format.go.golden b/gopls/internal/lsp/testdata/noparse_format/parse_format.go.golden
99168--- a/gopls/internal/lsp/testdata/noparse_format/parse_format.go.golden	2000-01-01 00:00:00.000000000 -0000
99169+++ b/gopls/internal/lsp/testdata/noparse_format/parse_format.go.golden	1970-01-01 00:00:00.000000000 +0000
99170@@ -1,7 +0,0 @@
99171--- gofmt --
99172-package noparse_format //@format("package")
99173-
99174-func _() {
99175-	f()
99176-}
99177-
99178diff -urN a/gopls/internal/lsp/testdata/noparse_format/parse_format.go.in b/gopls/internal/lsp/testdata/noparse_format/parse_format.go.in
99179--- a/gopls/internal/lsp/testdata/noparse_format/parse_format.go.in	2000-01-01 00:00:00.000000000 -0000
99180+++ b/gopls/internal/lsp/testdata/noparse_format/parse_format.go.in	1970-01-01 00:00:00.000000000 +0000
99181@@ -1,5 +0,0 @@
99182-package noparse_format //@format("package")
99183-
99184-func _() {
99185-f()
99186-}
99187\ No newline at end of file
99188diff -urN a/gopls/internal/lsp/testdata/%percent/perc%ent.go b/gopls/internal/lsp/testdata/%percent/perc%ent.go
99189--- a/gopls/internal/lsp/testdata/%percent/perc%ent.go	2000-01-01 00:00:00.000000000 -0000
99190+++ b/gopls/internal/lsp/testdata/%percent/perc%ent.go	1970-01-01 00:00:00.000000000 +0000
99191@@ -1 +0,0 @@
99192-package percent
99193diff -urN a/gopls/internal/lsp/testdata/printf/printf.go b/gopls/internal/lsp/testdata/printf/printf.go
99194--- a/gopls/internal/lsp/testdata/printf/printf.go	2000-01-01 00:00:00.000000000 -0000
99195+++ b/gopls/internal/lsp/testdata/printf/printf.go	1970-01-01 00:00:00.000000000 +0000
99196@@ -1,33 +0,0 @@
99197-package printf
99198-
99199-import "fmt"
99200-
99201-func myPrintf(string, ...interface{}) {}
99202-
99203-func _() {
99204-	var (
99205-		aInt      int          //@item(printfInt, "aInt", "int", "var")
99206-		aFloat    float64      //@item(printfFloat, "aFloat", "float64", "var")
99207-		aString   string       //@item(printfString, "aString", "string", "var")
99208-		aBytes    []byte       //@item(printfBytes, "aBytes", "[]byte", "var")
99209-		aStringer fmt.Stringer //@item(printfStringer, "aStringer", "fmt.Stringer", "var")
99210-		aError    error        //@item(printfError, "aError", "error", "var")
99211-		aBool     bool         //@item(printfBool, "aBool", "bool", "var")
99212-	)
99213-
99214-	myPrintf("%d", a)       //@rank(")", printfInt, printfFloat)
99215-	myPrintf("%s", a)       //@rank(")", printfString, printfInt),rank(")", printfBytes, printfInt),rank(")", printfStringer, printfInt),rank(")", printfError, printfInt)
99216-	myPrintf("%w", a)       //@rank(")", printfError, printfInt)
99217-	myPrintf("%x %[1]b", a) //@rank(")", printfInt, printfString)
99218-
99219-	fmt.Printf("%t", a) //@rank(")", printfBool, printfInt)
99220-
99221-	fmt.Fprintf(nil, "%f", a) //@rank(")", printfFloat, printfInt)
99222-
99223-	fmt.Sprintf("%[2]q %[1]*.[3]*[4]f",
99224-		a, //@rank(",", printfInt, printfFloat)
99225-		a, //@rank(",", printfString, printfFloat)
99226-		a, //@rank(",", printfInt, printfFloat)
99227-		a, //@rank(",", printfFloat, printfInt)
99228-	)
99229-}
99230diff -urN a/gopls/internal/lsp/testdata/rank/assign_rank.go.in b/gopls/internal/lsp/testdata/rank/assign_rank.go.in
99231--- a/gopls/internal/lsp/testdata/rank/assign_rank.go.in	2000-01-01 00:00:00.000000000 -0000
99232+++ b/gopls/internal/lsp/testdata/rank/assign_rank.go.in	1970-01-01 00:00:00.000000000 +0000
99233@@ -1,19 +0,0 @@
99234-package rank
99235-
99236-var (
99237-	apple int = 3         //@item(apple, "apple", "int", "var")
99238-	pear string = "hello" //@item(pear, "pear", "string", "var")
99239-)
99240-
99241-func _() {
99242-	orange := 1      //@item(orange, "orange", "int", "var")
99243-	grape := "hello" //@item(grape, "grape", "string", "var")
99244-	orange, grape = 2, "hello"  //@complete(" \"", grape, pear, orange, apple)
99245-}
99246-
99247-func _() {
99248-	var pineapple int //@item(pineapple, "pineapple", "int", "var")
99249-	pineapple = 1    //@complete(" 1", pineapple, apple, pear)
99250-
99251-	y := //@complete(" /", pineapple, apple, pear)
99252-}
99253diff -urN a/gopls/internal/lsp/testdata/rank/binexpr_rank.go.in b/gopls/internal/lsp/testdata/rank/binexpr_rank.go.in
99254--- a/gopls/internal/lsp/testdata/rank/binexpr_rank.go.in	2000-01-01 00:00:00.000000000 -0000
99255+++ b/gopls/internal/lsp/testdata/rank/binexpr_rank.go.in	1970-01-01 00:00:00.000000000 +0000
99256@@ -1,8 +0,0 @@
99257-package rank
99258-
99259-func _() {
99260-  _ = 5 +  ; //@complete(" ;", apple, pear)
99261-  y :=  + 5; //@complete(" +", apple, pear)
99262-
99263-  if 6 ==  {} //@complete(" {", apple, pear)
99264-}
99265diff -urN a/gopls/internal/lsp/testdata/rank/boolexpr_rank.go b/gopls/internal/lsp/testdata/rank/boolexpr_rank.go
99266--- a/gopls/internal/lsp/testdata/rank/boolexpr_rank.go	2000-01-01 00:00:00.000000000 -0000
99267+++ b/gopls/internal/lsp/testdata/rank/boolexpr_rank.go	1970-01-01 00:00:00.000000000 +0000
99268@@ -1,11 +0,0 @@
99269-package rank
99270-
99271-func _() {
99272-	someRandomBoolFunc := func() bool { //@item(boolExprFunc, "someRandomBoolFunc", "func() bool", "var")
99273-		return true
99274-	}
99275-
99276-	var foo, bar int     //@item(boolExprBar, "bar", "int", "var")
99277-	if foo == 123 && b { //@rank(" {", boolExprBar, boolExprFunc)
99278-	}
99279-}
99280diff -urN a/gopls/internal/lsp/testdata/rank/convert_rank.go.in b/gopls/internal/lsp/testdata/rank/convert_rank.go.in
99281--- a/gopls/internal/lsp/testdata/rank/convert_rank.go.in	2000-01-01 00:00:00.000000000 -0000
99282+++ b/gopls/internal/lsp/testdata/rank/convert_rank.go.in	1970-01-01 00:00:00.000000000 +0000
99283@@ -1,54 +0,0 @@
99284-package rank
99285-
99286-import "time"
99287-
99288-func _() {
99289-	type strList []string
99290-	wantsStrList := func(strList) {}
99291-
99292-	var (
99293-		convA string   //@item(convertA, "convA", "string", "var")
99294-		convB []string //@item(convertB, "convB", "[]string", "var")
99295-	)
99296-	wantsStrList(strList(conv)) //@complete("))", convertB, convertA)
99297-}
99298-
99299-func _() {
99300-	type myInt int
99301-
99302-	const (
99303-		convC        = "hi"    //@item(convertC, "convC", "string", "const")
99304-		convD        = 123     //@item(convertD, "convD", "int", "const")
99305-		convE int    = 123     //@item(convertE, "convE", "int", "const")
99306-		convF string = "there" //@item(convertF, "convF", "string", "const")
99307-		convG myInt  = 123     //@item(convertG, "convG", "myInt", "const")
99308-	)
99309-
99310-	var foo int
99311-	foo = conv //@rank(" //", convertE, convertD)
99312-
99313-	var mi myInt
99314-	mi = conv //@rank(" //", convertG, convertD, convertE)
99315-	mi + conv //@rank(" //", convertG, convertD, convertE)
99316-
99317-	1 + conv //@rank(" //", convertD, convertC),rank(" //", convertE, convertC),rank(" //", convertG, convertC)
99318-
99319-	type myString string
99320-	var ms myString
99321-	ms = conv //@rank(" //", convertC, convertF)
99322-
99323-	type myUint uint32
99324-	var mu myUint
99325-	mu = conv //@rank(" //", convertD, convertE)
99326-
99327-	// don't downrank constants when assigning to interface{}
99328-	var _ interface{} = c //@rank(" //", convertD, complex)
99329-
99330-	var _ time.Duration = conv //@rank(" //", convertD, convertE),snippet(" //", convertE, "time.Duration(convE)", "time.Duration(convE)")
99331-
99332-	var convP myInt   //@item(convertP, "convP", "myInt", "var")
99333-	var _ *int = conv //@snippet(" //", convertP, "(*int)(&convP)", "(*int)(&convP)")
99334-
99335-	var ff float64 //@item(convertFloat, "ff", "float64", "var")
99336-	f == convD     //@snippet(" =", convertFloat, "ff", "ff")
99337-}
99338diff -urN a/gopls/internal/lsp/testdata/rank/struct/struct_rank.go b/gopls/internal/lsp/testdata/rank/struct/struct_rank.go
99339--- a/gopls/internal/lsp/testdata/rank/struct/struct_rank.go	2000-01-01 00:00:00.000000000 -0000
99340+++ b/gopls/internal/lsp/testdata/rank/struct/struct_rank.go	1970-01-01 00:00:00.000000000 +0000
99341@@ -1,11 +0,0 @@
99342-package struct_rank
99343-
99344-type foo struct {
99345-	c int //@item(c_rank, "c", "int", "field")
99346-	b int //@item(b_rank, "b", "int", "field")
99347-	a int //@item(a_rank, "a", "int", "field")
99348-}
99349-
99350-func f() {
99351-	foo := foo{} //@rank("}", c_rank, b_rank, a_rank)
99352-}
99353diff -urN a/gopls/internal/lsp/testdata/rank/switch_rank.go.in b/gopls/internal/lsp/testdata/rank/switch_rank.go.in
99354--- a/gopls/internal/lsp/testdata/rank/switch_rank.go.in	2000-01-01 00:00:00.000000000 -0000
99355+++ b/gopls/internal/lsp/testdata/rank/switch_rank.go.in	1970-01-01 00:00:00.000000000 +0000
99356@@ -1,29 +0,0 @@
99357-package rank
99358-
99359-import "time"
99360-
99361-func _() {
99362-	switch pear {
99363-	case _: //@rank("_", pear, apple)
99364-	}
99365-
99366-	time.Monday //@item(timeMonday, "time.Monday", "time.Weekday", "const"),item(monday ,"Monday", "time.Weekday", "const")
99367-	time.Friday //@item(timeFriday, "time.Friday", "time.Weekday", "const"),item(friday ,"Friday", "time.Weekday", "const")
99368-
99369-	now := time.Now()
99370-	now.Weekday //@item(nowWeekday, "now.Weekday", "func() time.Weekday", "method")
99371-
99372-	then := time.Now()
99373-	then.Weekday //@item(thenWeekday, "then.Weekday", "func() time.Weekday", "method")
99374-
99375-	switch time.Weekday(0) {
99376-	case time.Monday, time.Tuesday:
99377-	case time.Wednesday, time.Thursday:
99378-	case time.Saturday, time.Sunday:
99379-	case t: //@rank(":", timeFriday, timeMonday)
99380-	case time.: //@rank(":", friday, monday)
99381-
99382-	case now.Weekday():
99383-	case week: //@rank(":", thenWeekday, nowWeekday)
99384-	}
99385-}
99386diff -urN a/gopls/internal/lsp/testdata/rank/type_assert_rank.go.in b/gopls/internal/lsp/testdata/rank/type_assert_rank.go.in
99387--- a/gopls/internal/lsp/testdata/rank/type_assert_rank.go.in	2000-01-01 00:00:00.000000000 -0000
99388+++ b/gopls/internal/lsp/testdata/rank/type_assert_rank.go.in	1970-01-01 00:00:00.000000000 +0000
99389@@ -1,8 +0,0 @@
99390-package rank
99391-
99392-func _() {
99393-	type flower int //@item(flower, "flower", "int", "type")
99394-	var fig string  //@item(fig, "fig", "string", "var")
99395-
99396-	_ = interface{}(nil).(f) //@complete(") //", flower)
99397-}
99398diff -urN a/gopls/internal/lsp/testdata/rank/type_switch_rank.go.in b/gopls/internal/lsp/testdata/rank/type_switch_rank.go.in
99399--- a/gopls/internal/lsp/testdata/rank/type_switch_rank.go.in	2000-01-01 00:00:00.000000000 -0000
99400+++ b/gopls/internal/lsp/testdata/rank/type_switch_rank.go.in	1970-01-01 00:00:00.000000000 +0000
99401@@ -1,31 +0,0 @@
99402-package rank
99403-
99404-import (
99405-	"fmt"
99406-	"go/ast"
99407-)
99408-
99409-func _() {
99410-	type basket int   //@item(basket, "basket", "int", "type")
99411-	var banana string //@item(banana, "banana", "string", "var")
99412-
99413-	switch interface{}(pear).(type) {
99414-	case b: //@complete(":", basket)
99415-		b //@complete(" //", banana, basket)
99416-	}
99417-
99418-	Ident  //@item(astIdent, "Ident", "struct{...}", "struct")
99419-	IfStmt //@item(astIfStmt, "IfStmt", "struct{...}", "struct")
99420-
99421-	switch ast.Node(nil).(type) {
99422-	case *ast.Ident:
99423-	case *ast.I: //@rank(":", astIfStmt, astIdent)
99424-	}
99425-
99426-	Stringer   //@item(fmtStringer, "Stringer", "interface{...}", "interface")
99427-	GoStringer //@item(fmtGoStringer, "GoStringer", "interface{...}", "interface")
99428-
99429-	switch interface{}(nil).(type) {
99430-	case fmt.Stringer: //@rank(":", fmtStringer, fmtGoStringer)
99431-	}
99432-}
99433diff -urN a/gopls/internal/lsp/testdata/references/another/another.go b/gopls/internal/lsp/testdata/references/another/another.go
99434--- a/gopls/internal/lsp/testdata/references/another/another.go	2000-01-01 00:00:00.000000000 -0000
99435+++ b/gopls/internal/lsp/testdata/references/another/another.go	1970-01-01 00:00:00.000000000 +0000
99436@@ -1,13 +0,0 @@
99437-// Package another has another type.
99438-package another
99439-
99440-import (
99441-	other "golang.org/lsptests/references/other"
99442-)
99443-
99444-func _() {
99445-	xes := other.GetXes()
99446-	for _, x := range xes { //@mark(defX, "x")
99447-		_ = x.Y //@mark(useX, "x"),mark(anotherXY, "Y"),refs("Y", typeXY, anotherXY, GetXesY),refs(".", defX, useX),refs("x", defX, useX)
99448-	}
99449-}
99450diff -urN a/gopls/internal/lsp/testdata/references/interfaces/interfaces.go b/gopls/internal/lsp/testdata/references/interfaces/interfaces.go
99451--- a/gopls/internal/lsp/testdata/references/interfaces/interfaces.go	2000-01-01 00:00:00.000000000 -0000
99452+++ b/gopls/internal/lsp/testdata/references/interfaces/interfaces.go	1970-01-01 00:00:00.000000000 +0000
99453@@ -1,34 +0,0 @@
99454-package interfaces
99455-
99456-type first interface {
99457-	common() //@mark(firCommon, "common"),refs("common", firCommon, xCommon, zCommon)
99458-	firstMethod() //@mark(firMethod, "firstMethod"),refs("firstMethod", firMethod, xfMethod, zfMethod)
99459-}
99460-
99461-type second interface {
99462-	common() //@mark(secCommon, "common"),refs("common", secCommon, yCommon, zCommon)
99463-	secondMethod() //@mark(secMethod, "secondMethod"),refs("secondMethod", secMethod, ysMethod, zsMethod)
99464-}
99465-
99466-type s struct {}
99467-
99468-func (*s) common() {} //@mark(sCommon, "common"),refs("common", sCommon, xCommon, yCommon, zCommon)
99469-
99470-func (*s) firstMethod() {} //@mark(sfMethod, "firstMethod"),refs("firstMethod", sfMethod, xfMethod, zfMethod)
99471-
99472-func (*s) secondMethod() {} //@mark(ssMethod, "secondMethod"),refs("secondMethod", ssMethod, ysMethod, zsMethod)
99473-
99474-func main() {
99475-	var x first = &s{}
99476-	var y second = &s{}
99477-
99478-	x.common() //@mark(xCommon, "common"),refs("common", firCommon, xCommon, zCommon)
99479-	x.firstMethod() //@mark(xfMethod, "firstMethod"),refs("firstMethod", firMethod, xfMethod, zfMethod)
99480-	y.common() //@mark(yCommon, "common"),refs("common", secCommon, yCommon, zCommon)
99481-	y.secondMethod() //@mark(ysMethod, "secondMethod"),refs("secondMethod", secMethod, ysMethod, zsMethod)
99482-
99483-	var z *s = &s{}
99484-	z.firstMethod() //@mark(zfMethod, "firstMethod"),refs("firstMethod", sfMethod, xfMethod, zfMethod)
99485-	z.secondMethod() //@mark(zsMethod, "secondMethod"),refs("secondMethod", ssMethod, ysMethod, zsMethod)
99486-	z.common() //@mark(zCommon, "common"),refs("common", sCommon, xCommon, yCommon, zCommon)
99487-}
99488diff -urN a/gopls/internal/lsp/testdata/references/other/other.go b/gopls/internal/lsp/testdata/references/other/other.go
99489--- a/gopls/internal/lsp/testdata/references/other/other.go	2000-01-01 00:00:00.000000000 -0000
99490+++ b/gopls/internal/lsp/testdata/references/other/other.go	1970-01-01 00:00:00.000000000 +0000
99491@@ -1,19 +0,0 @@
99492-package other
99493-
99494-import (
99495-	references "golang.org/lsptests/references"
99496-)
99497-
99498-func GetXes() []references.X {
99499-	return []references.X{
99500-		{
99501-			Y: 1, //@mark(GetXesY, "Y"),refs("Y", typeXY, GetXesY, anotherXY)
99502-		},
99503-	}
99504-}
99505-
99506-func _() {
99507-	references.Q = "hello" //@mark(assignExpQ, "Q")
99508-	bob := func(_ string) {}
99509-	bob(references.Q) //@mark(bobExpQ, "Q")
99510-}
99511diff -urN a/gopls/internal/lsp/testdata/references/refs.go b/gopls/internal/lsp/testdata/references/refs.go
99512--- a/gopls/internal/lsp/testdata/references/refs.go	2000-01-01 00:00:00.000000000 -0000
99513+++ b/gopls/internal/lsp/testdata/references/refs.go	1970-01-01 00:00:00.000000000 +0000
99514@@ -1,53 +0,0 @@
99515-// Package refs is a package used to test find references.
99516-package refs
99517-
99518-import "os" //@mark(osDecl, `"os"`),refs("os", osDecl, osUse)
99519-
99520-type i int //@mark(typeI, "i"),refs("i", typeI, argI, returnI, embeddedI)
99521-
99522-type X struct {
99523-	Y int //@mark(typeXY, "Y")
99524-}
99525-
99526-func _(_ i) []bool { //@mark(argI, "i")
99527-	return nil
99528-}
99529-
99530-func _(_ []byte) i { //@mark(returnI, "i")
99531-	return 0
99532-}
99533-
99534-var q string //@mark(declQ, "q"),refs("q", declQ, assignQ, bobQ)
99535-
99536-var Q string //@mark(declExpQ, "Q"),refs("Q", declExpQ, assignExpQ, bobExpQ)
99537-
99538-func _() {
99539-	q = "hello" //@mark(assignQ, "q")
99540-	bob := func(_ string) {}
99541-	bob(q) //@mark(bobQ, "q")
99542-}
99543-
99544-type e struct {
99545-	i //@mark(embeddedI, "i"),refs("i", embeddedI, embeddedIUse)
99546-}
99547-
99548-func _() {
99549-	_ = e{}.i //@mark(embeddedIUse, "i")
99550-}
99551-
99552-const (
99553-	foo = iota //@refs("iota")
99554-)
99555-
99556-func _(x interface{}) {
99557-	// We use the _ prefix because the markers inhabit a single
99558-	// namespace and yDecl is already used in ../highlights/highlights.go.
99559-	switch _y := x.(type) { //@mark(_yDecl, "_y"),refs("_y", _yDecl, _yInt, _yDefault)
99560-	case int:
99561-		println(_y) //@mark(_yInt, "_y"),refs("_y", _yDecl, _yInt, _yDefault)
99562-	default:
99563-		println(_y) //@mark(_yDefault, "_y")
99564-	}
99565-
99566-	os.Getwd() //@mark(osUse, "os")
99567-}
99568diff -urN a/gopls/internal/lsp/testdata/references/refs_test.go b/gopls/internal/lsp/testdata/references/refs_test.go
99569--- a/gopls/internal/lsp/testdata/references/refs_test.go	2000-01-01 00:00:00.000000000 -0000
99570+++ b/gopls/internal/lsp/testdata/references/refs_test.go	1970-01-01 00:00:00.000000000 +0000
99571@@ -1,10 +0,0 @@
99572-package references
99573-
99574-import (
99575-	"testing"
99576-)
99577-
99578-// This test exists to bring the test package into existence.
99579-
99580-func TestReferences(t *testing.T) {
99581-}
99582diff -urN a/gopls/internal/lsp/testdata/rename/a/random.go.golden b/gopls/internal/lsp/testdata/rename/a/random.go.golden
99583--- a/gopls/internal/lsp/testdata/rename/a/random.go.golden	2000-01-01 00:00:00.000000000 -0000
99584+++ b/gopls/internal/lsp/testdata/rename/a/random.go.golden	1970-01-01 00:00:00.000000000 +0000
99585@@ -1,616 +0,0 @@
99586--- GetSum-rename --
99587-package a
99588-
99589-import (
99590-	lg "log"
99591-	"fmt" //@rename("fmt", "fmty")
99592-	f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
99593-)
99594-
99595-func Random() int {
99596-	y := 6 + 7
99597-	return y
99598-}
99599-
99600-func Random2(y int) int { //@rename("y", "z")
99601-	return y
99602-}
99603-
99604-type Pos struct {
99605-	x, y int
99606-}
99607-
99608-func (p *Pos) GetSum() int {
99609-	return p.x + p.y //@rename("x", "myX")
99610-}
99611-
99612-func _() {
99613-	var p Pos   //@rename("p", "pos")
99614-	_ = p.GetSum() //@rename("Sum", "GetSum")
99615-}
99616-
99617-func sw() {
99618-	var x interface{}
99619-
99620-	switch y := x.(type) { //@rename("y", "y0")
99621-	case int:
99622-		fmt.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format")
99623-	case string:
99624-		lg.Printf("%s", y) //@rename("y", "y2"),rename("lg","log")
99625-	default:
99626-		f2.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2")
99627-	}
99628-}
99629-
99630--- f2name-rename --
99631-package a
99632-
99633-import (
99634-	lg "log"
99635-	"fmt" //@rename("fmt", "fmty")
99636-	f2name "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
99637-)
99638-
99639-func Random() int {
99640-	y := 6 + 7
99641-	return y
99642-}
99643-
99644-func Random2(y int) int { //@rename("y", "z")
99645-	return y
99646-}
99647-
99648-type Pos struct {
99649-	x, y int
99650-}
99651-
99652-func (p *Pos) Sum() int {
99653-	return p.x + p.y //@rename("x", "myX")
99654-}
99655-
99656-func _() {
99657-	var p Pos   //@rename("p", "pos")
99658-	_ = p.Sum() //@rename("Sum", "GetSum")
99659-}
99660-
99661-func sw() {
99662-	var x interface{}
99663-
99664-	switch y := x.(type) { //@rename("y", "y0")
99665-	case int:
99666-		fmt.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format")
99667-	case string:
99668-		lg.Printf("%s", y) //@rename("y", "y2"),rename("lg","log")
99669-	default:
99670-		f2name.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2")
99671-	}
99672-}
99673-
99674--- f2y-rename --
99675-package a
99676-
99677-import (
99678-	lg "log"
99679-	"fmt" //@rename("fmt", "fmty")
99680-	f2y "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
99681-)
99682-
99683-func Random() int {
99684-	y := 6 + 7
99685-	return y
99686-}
99687-
99688-func Random2(y int) int { //@rename("y", "z")
99689-	return y
99690-}
99691-
99692-type Pos struct {
99693-	x, y int
99694-}
99695-
99696-func (p *Pos) Sum() int {
99697-	return p.x + p.y //@rename("x", "myX")
99698-}
99699-
99700-func _() {
99701-	var p Pos   //@rename("p", "pos")
99702-	_ = p.Sum() //@rename("Sum", "GetSum")
99703-}
99704-
99705-func sw() {
99706-	var x interface{}
99707-
99708-	switch y := x.(type) { //@rename("y", "y0")
99709-	case int:
99710-		fmt.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format")
99711-	case string:
99712-		lg.Printf("%s", y) //@rename("y", "y2"),rename("lg","log")
99713-	default:
99714-		f2y.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2")
99715-	}
99716-}
99717-
99718--- fmt2-rename --
99719-package a
99720-
99721-import (
99722-	lg "log"
99723-	"fmt" //@rename("fmt", "fmty")
99724-	fmt2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
99725-)
99726-
99727-func Random() int {
99728-	y := 6 + 7
99729-	return y
99730-}
99731-
99732-func Random2(y int) int { //@rename("y", "z")
99733-	return y
99734-}
99735-
99736-type Pos struct {
99737-	x, y int
99738-}
99739-
99740-func (p *Pos) Sum() int {
99741-	return p.x + p.y //@rename("x", "myX")
99742-}
99743-
99744-func _() {
99745-	var p Pos   //@rename("p", "pos")
99746-	_ = p.Sum() //@rename("Sum", "GetSum")
99747-}
99748-
99749-func sw() {
99750-	var x interface{}
99751-
99752-	switch y := x.(type) { //@rename("y", "y0")
99753-	case int:
99754-		fmt.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format")
99755-	case string:
99756-		lg.Printf("%s", y) //@rename("y", "y2"),rename("lg","log")
99757-	default:
99758-		fmt2.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2")
99759-	}
99760-}
99761-
99762--- fmty-rename --
99763-package a
99764-
99765-import (
99766-	lg "log"
99767-	fmty "fmt" //@rename("fmt", "fmty")
99768-	f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
99769-)
99770-
99771-func Random() int {
99772-	y := 6 + 7
99773-	return y
99774-}
99775-
99776-func Random2(y int) int { //@rename("y", "z")
99777-	return y
99778-}
99779-
99780-type Pos struct {
99781-	x, y int
99782-}
99783-
99784-func (p *Pos) Sum() int {
99785-	return p.x + p.y //@rename("x", "myX")
99786-}
99787-
99788-func _() {
99789-	var p Pos   //@rename("p", "pos")
99790-	_ = p.Sum() //@rename("Sum", "GetSum")
99791-}
99792-
99793-func sw() {
99794-	var x interface{}
99795-
99796-	switch y := x.(type) { //@rename("y", "y0")
99797-	case int:
99798-		fmty.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format")
99799-	case string:
99800-		lg.Printf("%s", y) //@rename("y", "y2"),rename("lg","log")
99801-	default:
99802-		f2.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2")
99803-	}
99804-}
99805-
99806--- format-rename --
99807-package a
99808-
99809-import (
99810-	lg "log"
99811-	format "fmt" //@rename("fmt", "fmty")
99812-	f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
99813-)
99814-
99815-func Random() int {
99816-	y := 6 + 7
99817-	return y
99818-}
99819-
99820-func Random2(y int) int { //@rename("y", "z")
99821-	return y
99822-}
99823-
99824-type Pos struct {
99825-	x, y int
99826-}
99827-
99828-func (p *Pos) Sum() int {
99829-	return p.x + p.y //@rename("x", "myX")
99830-}
99831-
99832-func _() {
99833-	var p Pos   //@rename("p", "pos")
99834-	_ = p.Sum() //@rename("Sum", "GetSum")
99835-}
99836-
99837-func sw() {
99838-	var x interface{}
99839-
99840-	switch y := x.(type) { //@rename("y", "y0")
99841-	case int:
99842-		format.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format")
99843-	case string:
99844-		lg.Printf("%s", y) //@rename("y", "y2"),rename("lg","log")
99845-	default:
99846-		f2.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2")
99847-	}
99848-}
99849-
99850--- log-rename --
99851-package a
99852-
99853-import (
99854-	"log"
99855-	"fmt" //@rename("fmt", "fmty")
99856-	f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
99857-)
99858-
99859-func Random() int {
99860-	y := 6 + 7
99861-	return y
99862-}
99863-
99864-func Random2(y int) int { //@rename("y", "z")
99865-	return y
99866-}
99867-
99868-type Pos struct {
99869-	x, y int
99870-}
99871-
99872-func (p *Pos) Sum() int {
99873-	return p.x + p.y //@rename("x", "myX")
99874-}
99875-
99876-func _() {
99877-	var p Pos   //@rename("p", "pos")
99878-	_ = p.Sum() //@rename("Sum", "GetSum")
99879-}
99880-
99881-func sw() {
99882-	var x interface{}
99883-
99884-	switch y := x.(type) { //@rename("y", "y0")
99885-	case int:
99886-		fmt.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format")
99887-	case string:
99888-		log.Printf("%s", y) //@rename("y", "y2"),rename("lg","log")
99889-	default:
99890-		f2.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2")
99891-	}
99892-}
99893-
99894--- myX-rename --
99895-package a
99896-
99897-import (
99898-	lg "log"
99899-	"fmt" //@rename("fmt", "fmty")
99900-	f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
99901-)
99902-
99903-func Random() int {
99904-	y := 6 + 7
99905-	return y
99906-}
99907-
99908-func Random2(y int) int { //@rename("y", "z")
99909-	return y
99910-}
99911-
99912-type Pos struct {
99913-	myX, y int
99914-}
99915-
99916-func (p *Pos) Sum() int {
99917-	return p.myX + p.y //@rename("x", "myX")
99918-}
99919-
99920-func _() {
99921-	var p Pos   //@rename("p", "pos")
99922-	_ = p.Sum() //@rename("Sum", "GetSum")
99923-}
99924-
99925-func sw() {
99926-	var x interface{}
99927-
99928-	switch y := x.(type) { //@rename("y", "y0")
99929-	case int:
99930-		fmt.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format")
99931-	case string:
99932-		lg.Printf("%s", y) //@rename("y", "y2"),rename("lg","log")
99933-	default:
99934-		f2.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2")
99935-	}
99936-}
99937-
99938--- pos-rename --
99939-package a
99940-
99941-import (
99942-	lg "log"
99943-	"fmt" //@rename("fmt", "fmty")
99944-	f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
99945-)
99946-
99947-func Random() int {
99948-	y := 6 + 7
99949-	return y
99950-}
99951-
99952-func Random2(y int) int { //@rename("y", "z")
99953-	return y
99954-}
99955-
99956-type Pos struct {
99957-	x, y int
99958-}
99959-
99960-func (p *Pos) Sum() int {
99961-	return p.x + p.y //@rename("x", "myX")
99962-}
99963-
99964-func _() {
99965-	var pos Pos   //@rename("p", "pos")
99966-	_ = pos.Sum() //@rename("Sum", "GetSum")
99967-}
99968-
99969-func sw() {
99970-	var x interface{}
99971-
99972-	switch y := x.(type) { //@rename("y", "y0")
99973-	case int:
99974-		fmt.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format")
99975-	case string:
99976-		lg.Printf("%s", y) //@rename("y", "y2"),rename("lg","log")
99977-	default:
99978-		f2.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2")
99979-	}
99980-}
99981-
99982--- y0-rename --
99983-package a
99984-
99985-import (
99986-	lg "log"
99987-	"fmt" //@rename("fmt", "fmty")
99988-	f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
99989-)
99990-
99991-func Random() int {
99992-	y := 6 + 7
99993-	return y
99994-}
99995-
99996-func Random2(y int) int { //@rename("y", "z")
99997-	return y
99998-}
99999-
100000-type Pos struct {
100001-	x, y int
100002-}
100003-
100004-func (p *Pos) Sum() int {
100005-	return p.x + p.y //@rename("x", "myX")
100006-}
100007-
100008-func _() {
100009-	var p Pos   //@rename("p", "pos")
100010-	_ = p.Sum() //@rename("Sum", "GetSum")
100011-}
100012-
100013-func sw() {
100014-	var x interface{}
100015-
100016-	switch y0 := x.(type) { //@rename("y", "y0")
100017-	case int:
100018-		fmt.Printf("%d", y0) //@rename("y", "y1"),rename("fmt", "format")
100019-	case string:
100020-		lg.Printf("%s", y0) //@rename("y", "y2"),rename("lg","log")
100021-	default:
100022-		f2.Printf("%v", y0) //@rename("y", "y3"),rename("f2","fmt2")
100023-	}
100024-}
100025-
100026--- y1-rename --
100027-package a
100028-
100029-import (
100030-	lg "log"
100031-	"fmt" //@rename("fmt", "fmty")
100032-	f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
100033-)
100034-
100035-func Random() int {
100036-	y := 6 + 7
100037-	return y
100038-}
100039-
100040-func Random2(y int) int { //@rename("y", "z")
100041-	return y
100042-}
100043-
100044-type Pos struct {
100045-	x, y int
100046-}
100047-
100048-func (p *Pos) Sum() int {
100049-	return p.x + p.y //@rename("x", "myX")
100050-}
100051-
100052-func _() {
100053-	var p Pos   //@rename("p", "pos")
100054-	_ = p.Sum() //@rename("Sum", "GetSum")
100055-}
100056-
100057-func sw() {
100058-	var x interface{}
100059-
100060-	switch y1 := x.(type) { //@rename("y", "y0")
100061-	case int:
100062-		fmt.Printf("%d", y1) //@rename("y", "y1"),rename("fmt", "format")
100063-	case string:
100064-		lg.Printf("%s", y1) //@rename("y", "y2"),rename("lg","log")
100065-	default:
100066-		f2.Printf("%v", y1) //@rename("y", "y3"),rename("f2","fmt2")
100067-	}
100068-}
100069-
100070--- y2-rename --
100071-package a
100072-
100073-import (
100074-	lg "log"
100075-	"fmt" //@rename("fmt", "fmty")
100076-	f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
100077-)
100078-
100079-func Random() int {
100080-	y := 6 + 7
100081-	return y
100082-}
100083-
100084-func Random2(y int) int { //@rename("y", "z")
100085-	return y
100086-}
100087-
100088-type Pos struct {
100089-	x, y int
100090-}
100091-
100092-func (p *Pos) Sum() int {
100093-	return p.x + p.y //@rename("x", "myX")
100094-}
100095-
100096-func _() {
100097-	var p Pos   //@rename("p", "pos")
100098-	_ = p.Sum() //@rename("Sum", "GetSum")
100099-}
100100-
100101-func sw() {
100102-	var x interface{}
100103-
100104-	switch y2 := x.(type) { //@rename("y", "y0")
100105-	case int:
100106-		fmt.Printf("%d", y2) //@rename("y", "y1"),rename("fmt", "format")
100107-	case string:
100108-		lg.Printf("%s", y2) //@rename("y", "y2"),rename("lg","log")
100109-	default:
100110-		f2.Printf("%v", y2) //@rename("y", "y3"),rename("f2","fmt2")
100111-	}
100112-}
100113-
100114--- y3-rename --
100115-package a
100116-
100117-import (
100118-	lg "log"
100119-	"fmt" //@rename("fmt", "fmty")
100120-	f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
100121-)
100122-
100123-func Random() int {
100124-	y := 6 + 7
100125-	return y
100126-}
100127-
100128-func Random2(y int) int { //@rename("y", "z")
100129-	return y
100130-}
100131-
100132-type Pos struct {
100133-	x, y int
100134-}
100135-
100136-func (p *Pos) Sum() int {
100137-	return p.x + p.y //@rename("x", "myX")
100138-}
100139-
100140-func _() {
100141-	var p Pos   //@rename("p", "pos")
100142-	_ = p.Sum() //@rename("Sum", "GetSum")
100143-}
100144-
100145-func sw() {
100146-	var x interface{}
100147-
100148-	switch y3 := x.(type) { //@rename("y", "y0")
100149-	case int:
100150-		fmt.Printf("%d", y3) //@rename("y", "y1"),rename("fmt", "format")
100151-	case string:
100152-		lg.Printf("%s", y3) //@rename("y", "y2"),rename("lg","log")
100153-	default:
100154-		f2.Printf("%v", y3) //@rename("y", "y3"),rename("f2","fmt2")
100155-	}
100156-}
100157-
100158--- z-rename --
100159-package a
100160-
100161-import (
100162-	lg "log"
100163-	"fmt" //@rename("fmt", "fmty")
100164-	f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
100165-)
100166-
100167-func Random() int {
100168-	y := 6 + 7
100169-	return y
100170-}
100171-
100172-func Random2(z int) int { //@rename("y", "z")
100173-	return z
100174-}
100175-
100176-type Pos struct {
100177-	x, y int
100178-}
100179-
100180-func (p *Pos) Sum() int {
100181-	return p.x + p.y //@rename("x", "myX")
100182-}
100183-
100184-func _() {
100185-	var p Pos   //@rename("p", "pos")
100186-	_ = p.Sum() //@rename("Sum", "GetSum")
100187-}
100188-
100189-func sw() {
100190-	var x interface{}
100191-
100192-	switch y := x.(type) { //@rename("y", "y0")
100193-	case int:
100194-		fmt.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format")
100195-	case string:
100196-		lg.Printf("%s", y) //@rename("y", "y2"),rename("lg","log")
100197-	default:
100198-		f2.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2")
100199-	}
100200-}
100201-
100202diff -urN a/gopls/internal/lsp/testdata/rename/a/random.go.in b/gopls/internal/lsp/testdata/rename/a/random.go.in
100203--- a/gopls/internal/lsp/testdata/rename/a/random.go.in	2000-01-01 00:00:00.000000000 -0000
100204+++ b/gopls/internal/lsp/testdata/rename/a/random.go.in	1970-01-01 00:00:00.000000000 +0000
100205@@ -1,42 +0,0 @@
100206-package a
100207-
100208-import (
100209-	lg "log"
100210-	"fmt" //@rename("fmt", "fmty")
100211-	f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y")
100212-)
100213-
100214-func Random() int {
100215-	y := 6 + 7
100216-	return y
100217-}
100218-
100219-func Random2(y int) int { //@rename("y", "z")
100220-	return y
100221-}
100222-
100223-type Pos struct {
100224-	x, y int
100225-}
100226-
100227-func (p *Pos) Sum() int {
100228-	return p.x + p.y //@rename("x", "myX")
100229-}
100230-
100231-func _() {
100232-	var p Pos   //@rename("p", "pos")
100233-	_ = p.Sum() //@rename("Sum", "GetSum")
100234-}
100235-
100236-func sw() {
100237-	var x interface{}
100238-
100239-	switch y := x.(type) { //@rename("y", "y0")
100240-	case int:
100241-		fmt.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format")
100242-	case string:
100243-		lg.Printf("%s", y) //@rename("y", "y2"),rename("lg","log")
100244-	default:
100245-		f2.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2")
100246-	}
100247-}
100248diff -urN a/gopls/internal/lsp/testdata/rename/b/b.go b/gopls/internal/lsp/testdata/rename/b/b.go
100249--- a/gopls/internal/lsp/testdata/rename/b/b.go	2000-01-01 00:00:00.000000000 -0000
100250+++ b/gopls/internal/lsp/testdata/rename/b/b.go	1970-01-01 00:00:00.000000000 +0000
100251@@ -1,20 +0,0 @@
100252-package b
100253-
100254-var c int //@rename("int", "uint")
100255-
100256-func _() {
100257-	a := 1 //@rename("a", "error")
100258-	a = 2
100259-	_ = a
100260-}
100261-
100262-var (
100263-	// Hello there.
100264-	// Foo does the thing.
100265-	Foo int //@rename("Foo", "Bob")
100266-)
100267-
100268-/*
100269-Hello description
100270-*/
100271-func Hello() {} //@rename("Hello", "Goodbye")
100272diff -urN a/gopls/internal/lsp/testdata/rename/b/b.go.golden b/gopls/internal/lsp/testdata/rename/b/b.go.golden
100273--- a/gopls/internal/lsp/testdata/rename/b/b.go.golden	2000-01-01 00:00:00.000000000 -0000
100274+++ b/gopls/internal/lsp/testdata/rename/b/b.go.golden	1970-01-01 00:00:00.000000000 +0000
100275@@ -1,78 +0,0 @@
100276--- Bob-rename --
100277-package b
100278-
100279-var c int //@rename("int", "uint")
100280-
100281-func _() {
100282-	a := 1 //@rename("a", "error")
100283-	a = 2
100284-	_ = a
100285-}
100286-
100287-var (
100288-	// Hello there.
100289-	// Bob does the thing.
100290-	Bob int //@rename("Foo", "Bob")
100291-)
100292-
100293-/*
100294-Hello description
100295-*/
100296-func Hello() {} //@rename("Hello", "Goodbye")
100297-
100298--- Goodbye-rename --
100299-b.go:
100300-package b
100301-
100302-var c int //@rename("int", "uint")
100303-
100304-func _() {
100305-	a := 1 //@rename("a", "error")
100306-	a = 2
100307-	_ = a
100308-}
100309-
100310-var (
100311-	// Hello there.
100312-	// Foo does the thing.
100313-	Foo int //@rename("Foo", "Bob")
100314-)
100315-
100316-/*
100317-Goodbye description
100318-*/
100319-func Goodbye() {} //@rename("Hello", "Goodbye")
100320-
100321-c.go:
100322-package c
100323-
100324-import "golang.org/lsptests/rename/b"
100325-
100326-func _() {
100327-	b.Goodbye() //@rename("Hello", "Goodbye")
100328-}
100329-
100330--- error-rename --
100331-package b
100332-
100333-var c int //@rename("int", "uint")
100334-
100335-func _() {
100336-	error := 1 //@rename("a", "error")
100337-	error = 2
100338-	_ = error
100339-}
100340-
100341-var (
100342-	// Hello there.
100343-	// Foo does the thing.
100344-	Foo int //@rename("Foo", "Bob")
100345-)
100346-
100347-/*
100348-Hello description
100349-*/
100350-func Hello() {} //@rename("Hello", "Goodbye")
100351-
100352--- uint-rename --
100353-int is built in and cannot be renamed
100354diff -urN a/gopls/internal/lsp/testdata/rename/bad/bad.go.golden b/gopls/internal/lsp/testdata/rename/bad/bad.go.golden
100355--- a/gopls/internal/lsp/testdata/rename/bad/bad.go.golden	2000-01-01 00:00:00.000000000 -0000
100356+++ b/gopls/internal/lsp/testdata/rename/bad/bad.go.golden	1970-01-01 00:00:00.000000000 +0000
100357@@ -1,2 +0,0 @@
100358--- rFunc-rename --
100359-renaming "sFunc" to "rFunc" not possible because "golang.org/lsptests/rename/bad" has errors
100360diff -urN a/gopls/internal/lsp/testdata/rename/bad/bad.go.in b/gopls/internal/lsp/testdata/rename/bad/bad.go.in
100361--- a/gopls/internal/lsp/testdata/rename/bad/bad.go.in	2000-01-01 00:00:00.000000000 -0000
100362+++ b/gopls/internal/lsp/testdata/rename/bad/bad.go.in	1970-01-01 00:00:00.000000000 +0000
100363@@ -1,8 +0,0 @@
100364-package bad
100365-
100366-type myStruct struct {
100367-}
100368-
100369-func (s *myStruct) sFunc() bool { //@rename("sFunc", "rFunc")
100370-	return s.Bad
100371-}
100372diff -urN a/gopls/internal/lsp/testdata/rename/bad/bad_test.go.in b/gopls/internal/lsp/testdata/rename/bad/bad_test.go.in
100373--- a/gopls/internal/lsp/testdata/rename/bad/bad_test.go.in	2000-01-01 00:00:00.000000000 -0000
100374+++ b/gopls/internal/lsp/testdata/rename/bad/bad_test.go.in	1970-01-01 00:00:00.000000000 +0000
100375@@ -1 +0,0 @@
100376-package bad
100377\ No newline at end of file
100378diff -urN a/gopls/internal/lsp/testdata/rename/c/c2.go b/gopls/internal/lsp/testdata/rename/c/c2.go
100379--- a/gopls/internal/lsp/testdata/rename/c/c2.go	2000-01-01 00:00:00.000000000 -0000
100380+++ b/gopls/internal/lsp/testdata/rename/c/c2.go	1970-01-01 00:00:00.000000000 +0000
100381@@ -1,4 +0,0 @@
100382-package c
100383-
100384-//go:embed Static/*
100385-var Static embed.FS //@rename("Static", "static")
100386\ No newline at end of file
100387diff -urN a/gopls/internal/lsp/testdata/rename/c/c2.go.golden b/gopls/internal/lsp/testdata/rename/c/c2.go.golden
100388--- a/gopls/internal/lsp/testdata/rename/c/c2.go.golden	2000-01-01 00:00:00.000000000 -0000
100389+++ b/gopls/internal/lsp/testdata/rename/c/c2.go.golden	1970-01-01 00:00:00.000000000 +0000
100390@@ -1,5 +0,0 @@
100391--- static-rename --
100392-package c
100393-
100394-//go:embed Static/*
100395-var static embed.FS //@rename("Static", "static")
100396diff -urN a/gopls/internal/lsp/testdata/rename/c/c.go b/gopls/internal/lsp/testdata/rename/c/c.go
100397--- a/gopls/internal/lsp/testdata/rename/c/c.go	2000-01-01 00:00:00.000000000 -0000
100398+++ b/gopls/internal/lsp/testdata/rename/c/c.go	1970-01-01 00:00:00.000000000 +0000
100399@@ -1,7 +0,0 @@
100400-package c
100401-
100402-import "golang.org/lsptests/rename/b"
100403-
100404-func _() {
100405-	b.Hello() //@rename("Hello", "Goodbye")
100406-}
100407diff -urN a/gopls/internal/lsp/testdata/rename/c/c.go.golden b/gopls/internal/lsp/testdata/rename/c/c.go.golden
100408--- a/gopls/internal/lsp/testdata/rename/c/c.go.golden	2000-01-01 00:00:00.000000000 -0000
100409+++ b/gopls/internal/lsp/testdata/rename/c/c.go.golden	1970-01-01 00:00:00.000000000 +0000
100410@@ -1,32 +0,0 @@
100411--- Goodbye-rename --
100412-b.go:
100413-package b
100414-
100415-var c int //@rename("int", "uint")
100416-
100417-func _() {
100418-	a := 1 //@rename("a", "error")
100419-	a = 2
100420-	_ = a
100421-}
100422-
100423-var (
100424-	// Hello there.
100425-	// Foo does the thing.
100426-	Foo int //@rename("Foo", "Bob")
100427-)
100428-
100429-/*
100430-Goodbye description
100431-*/
100432-func Goodbye() {} //@rename("Hello", "Goodbye")
100433-
100434-c.go:
100435-package c
100436-
100437-import "golang.org/lsptests/rename/b"
100438-
100439-func _() {
100440-	b.Goodbye() //@rename("Hello", "Goodbye")
100441-}
100442-
100443diff -urN a/gopls/internal/lsp/testdata/rename/crosspkg/another/another.go b/gopls/internal/lsp/testdata/rename/crosspkg/another/another.go
100444--- a/gopls/internal/lsp/testdata/rename/crosspkg/another/another.go	2000-01-01 00:00:00.000000000 -0000
100445+++ b/gopls/internal/lsp/testdata/rename/crosspkg/another/another.go	1970-01-01 00:00:00.000000000 +0000
100446@@ -1,13 +0,0 @@
100447-package another
100448-
100449-type (
100450-	I interface{ F() }
100451-	C struct{ I }
100452-)
100453-
100454-func (C) g()
100455-
100456-func _() {
100457-	var x I = C{}
100458-	x.F() //@rename("F", "G")
100459-}
100460diff -urN a/gopls/internal/lsp/testdata/rename/crosspkg/another/another.go.golden b/gopls/internal/lsp/testdata/rename/crosspkg/another/another.go.golden
100461--- a/gopls/internal/lsp/testdata/rename/crosspkg/another/another.go.golden	2000-01-01 00:00:00.000000000 -0000
100462+++ b/gopls/internal/lsp/testdata/rename/crosspkg/another/another.go.golden	1970-01-01 00:00:00.000000000 +0000
100463@@ -1,15 +0,0 @@
100464--- G-rename --
100465-package another
100466-
100467-type (
100468-	I interface{ G() }
100469-	C struct{ I }
100470-)
100471-
100472-func (C) g()
100473-
100474-func _() {
100475-	var x I = C{}
100476-	x.G() //@rename("F", "G")
100477-}
100478-
100479diff -urN a/gopls/internal/lsp/testdata/rename/crosspkg/crosspkg.go b/gopls/internal/lsp/testdata/rename/crosspkg/crosspkg.go
100480--- a/gopls/internal/lsp/testdata/rename/crosspkg/crosspkg.go	2000-01-01 00:00:00.000000000 -0000
100481+++ b/gopls/internal/lsp/testdata/rename/crosspkg/crosspkg.go	1970-01-01 00:00:00.000000000 +0000
100482@@ -1,7 +0,0 @@
100483-package crosspkg
100484-
100485-func Foo() { //@rename("Foo", "Dolphin")
100486-
100487-}
100488-
100489-var Bar int //@rename("Bar", "Tomato")
100490diff -urN a/gopls/internal/lsp/testdata/rename/crosspkg/crosspkg.go.golden b/gopls/internal/lsp/testdata/rename/crosspkg/crosspkg.go.golden
100491--- a/gopls/internal/lsp/testdata/rename/crosspkg/crosspkg.go.golden	2000-01-01 00:00:00.000000000 -0000
100492+++ b/gopls/internal/lsp/testdata/rename/crosspkg/crosspkg.go.golden	1970-01-01 00:00:00.000000000 +0000
100493@@ -1,40 +0,0 @@
100494--- Dolphin-rename --
100495-crosspkg.go:
100496-package crosspkg
100497-
100498-func Dolphin() { //@rename("Foo", "Dolphin")
100499-
100500-}
100501-
100502-var Bar int //@rename("Bar", "Tomato")
100503-
100504-other.go:
100505-package other
100506-
100507-import "golang.org/lsptests/rename/crosspkg"
100508-
100509-func Other() {
100510-	crosspkg.Bar
100511-	crosspkg.Dolphin() //@rename("Foo", "Flamingo")
100512-}
100513-
100514--- Tomato-rename --
100515-crosspkg.go:
100516-package crosspkg
100517-
100518-func Foo() { //@rename("Foo", "Dolphin")
100519-
100520-}
100521-
100522-var Tomato int //@rename("Bar", "Tomato")
100523-
100524-other.go:
100525-package other
100526-
100527-import "golang.org/lsptests/rename/crosspkg"
100528-
100529-func Other() {
100530-	crosspkg.Tomato
100531-	crosspkg.Foo() //@rename("Foo", "Flamingo")
100532-}
100533-
100534diff -urN a/gopls/internal/lsp/testdata/rename/crosspkg/other/other.go b/gopls/internal/lsp/testdata/rename/crosspkg/other/other.go
100535--- a/gopls/internal/lsp/testdata/rename/crosspkg/other/other.go	2000-01-01 00:00:00.000000000 -0000
100536+++ b/gopls/internal/lsp/testdata/rename/crosspkg/other/other.go	1970-01-01 00:00:00.000000000 +0000
100537@@ -1,8 +0,0 @@
100538-package other
100539-
100540-import "golang.org/lsptests/rename/crosspkg"
100541-
100542-func Other() {
100543-	crosspkg.Bar
100544-	crosspkg.Foo() //@rename("Foo", "Flamingo")
100545-}
100546diff -urN a/gopls/internal/lsp/testdata/rename/crosspkg/other/other.go.golden b/gopls/internal/lsp/testdata/rename/crosspkg/other/other.go.golden
100547--- a/gopls/internal/lsp/testdata/rename/crosspkg/other/other.go.golden	2000-01-01 00:00:00.000000000 -0000
100548+++ b/gopls/internal/lsp/testdata/rename/crosspkg/other/other.go.golden	1970-01-01 00:00:00.000000000 +0000
100549@@ -1,20 +0,0 @@
100550--- Flamingo-rename --
100551-crosspkg.go:
100552-package crosspkg
100553-
100554-func Flamingo() { //@rename("Foo", "Dolphin")
100555-
100556-}
100557-
100558-var Bar int //@rename("Bar", "Tomato")
100559-
100560-other.go:
100561-package other
100562-
100563-import "golang.org/lsptests/rename/crosspkg"
100564-
100565-func Other() {
100566-	crosspkg.Bar
100567-	crosspkg.Flamingo() //@rename("Foo", "Flamingo")
100568-}
100569-
100570diff -urN a/gopls/internal/lsp/testdata/rename/generics/embedded.go b/gopls/internal/lsp/testdata/rename/generics/embedded.go
100571--- a/gopls/internal/lsp/testdata/rename/generics/embedded.go	2000-01-01 00:00:00.000000000 -0000
100572+++ b/gopls/internal/lsp/testdata/rename/generics/embedded.go	1970-01-01 00:00:00.000000000 +0000
100573@@ -1,10 +0,0 @@
100574-//go:build go1.18
100575-// +build go1.18
100576-
100577-package generics
100578-
100579-type foo[P any] int //@rename("foo","bar")
100580-
100581-var x struct{ foo[int] }
100582-
100583-var _ = x.foo
100584diff -urN a/gopls/internal/lsp/testdata/rename/generics/embedded.go.golden b/gopls/internal/lsp/testdata/rename/generics/embedded.go.golden
100585--- a/gopls/internal/lsp/testdata/rename/generics/embedded.go.golden	2000-01-01 00:00:00.000000000 -0000
100586+++ b/gopls/internal/lsp/testdata/rename/generics/embedded.go.golden	1970-01-01 00:00:00.000000000 +0000
100587@@ -1,12 +0,0 @@
100588--- bar-rename --
100589-//go:build go1.18
100590-// +build go1.18
100591-
100592-package generics
100593-
100594-type bar[P any] int //@rename("foo","bar")
100595-
100596-var x struct{ bar[int] }
100597-
100598-var _ = x.bar
100599-
100600diff -urN a/gopls/internal/lsp/testdata/rename/generics/generics.go b/gopls/internal/lsp/testdata/rename/generics/generics.go
100601--- a/gopls/internal/lsp/testdata/rename/generics/generics.go	2000-01-01 00:00:00.000000000 -0000
100602+++ b/gopls/internal/lsp/testdata/rename/generics/generics.go	1970-01-01 00:00:00.000000000 +0000
100603@@ -1,25 +0,0 @@
100604-//go:build go1.18
100605-// +build go1.18
100606-
100607-package generics
100608-
100609-type G[P any] struct {
100610-	F int
100611-}
100612-
100613-func (G[_]) M() {}
100614-
100615-func F[P any](P) {
100616-	var p P //@rename("P", "Q")
100617-	_ = p
100618-}
100619-
100620-func _() {
100621-	var x G[int] //@rename("G", "H")
100622-	_ = x.F      //@rename("F", "K")
100623-	x.M()        //@rename("M", "N")
100624-
100625-	var y G[string]
100626-	_ = y.F
100627-	y.M()
100628-}
100629diff -urN a/gopls/internal/lsp/testdata/rename/generics/generics.go.golden b/gopls/internal/lsp/testdata/rename/generics/generics.go.golden
100630--- a/gopls/internal/lsp/testdata/rename/generics/generics.go.golden	2000-01-01 00:00:00.000000000 -0000
100631+++ b/gopls/internal/lsp/testdata/rename/generics/generics.go.golden	1970-01-01 00:00:00.000000000 +0000
100632@@ -1,108 +0,0 @@
100633--- H-rename --
100634-//go:build go1.18
100635-// +build go1.18
100636-
100637-package generics
100638-
100639-type H[P any] struct {
100640-	F int
100641-}
100642-
100643-func (H[_]) M() {}
100644-
100645-func F[P any](P) {
100646-	var p P //@rename("P", "Q")
100647-	_ = p
100648-}
100649-
100650-func _() {
100651-	var x H[int] //@rename("G", "H")
100652-	_ = x.F      //@rename("F", "K")
100653-	x.M()        //@rename("M", "N")
100654-
100655-	var y H[string]
100656-	_ = y.F
100657-	y.M()
100658-}
100659-
100660--- K-rename --
100661-//go:build go1.18
100662-// +build go1.18
100663-
100664-package generics
100665-
100666-type G[P any] struct {
100667-	K int
100668-}
100669-
100670-func (G[_]) M() {}
100671-
100672-func F[P any](P) {
100673-	var p P //@rename("P", "Q")
100674-	_ = p
100675-}
100676-
100677-func _() {
100678-	var x G[int] //@rename("G", "H")
100679-	_ = x.K      //@rename("F", "K")
100680-	x.M()        //@rename("M", "N")
100681-
100682-	var y G[string]
100683-	_ = y.K
100684-	y.M()
100685-}
100686-
100687--- N-rename --
100688-//go:build go1.18
100689-// +build go1.18
100690-
100691-package generics
100692-
100693-type G[P any] struct {
100694-	F int
100695-}
100696-
100697-func (G[_]) N() {}
100698-
100699-func F[P any](P) {
100700-	var p P //@rename("P", "Q")
100701-	_ = p
100702-}
100703-
100704-func _() {
100705-	var x G[int] //@rename("G", "H")
100706-	_ = x.F      //@rename("F", "K")
100707-	x.N()        //@rename("M", "N")
100708-
100709-	var y G[string]
100710-	_ = y.F
100711-	y.N()
100712-}
100713-
100714--- Q-rename --
100715-//go:build go1.18
100716-// +build go1.18
100717-
100718-package generics
100719-
100720-type G[P any] struct {
100721-	F int
100722-}
100723-
100724-func (G[_]) M() {}
100725-
100726-func F[Q any](Q) {
100727-	var p Q //@rename("P", "Q")
100728-	_ = p
100729-}
100730-
100731-func _() {
100732-	var x G[int] //@rename("G", "H")
100733-	_ = x.F      //@rename("F", "K")
100734-	x.M()        //@rename("M", "N")
100735-
100736-	var y G[string]
100737-	_ = y.F
100738-	y.M()
100739-}
100740-
100741diff -urN a/gopls/internal/lsp/testdata/rename/generics/unions.go b/gopls/internal/lsp/testdata/rename/generics/unions.go
100742--- a/gopls/internal/lsp/testdata/rename/generics/unions.go	2000-01-01 00:00:00.000000000 -0000
100743+++ b/gopls/internal/lsp/testdata/rename/generics/unions.go	1970-01-01 00:00:00.000000000 +0000
100744@@ -1,10 +0,0 @@
100745-//go:build go1.18
100746-// +build go1.18
100747-
100748-package generics
100749-
100750-type T string //@rename("T", "R")
100751-
100752-type C interface {
100753-	T | ~int //@rename("T", "S")
100754-}
100755diff -urN a/gopls/internal/lsp/testdata/rename/generics/unions.go.golden b/gopls/internal/lsp/testdata/rename/generics/unions.go.golden
100756--- a/gopls/internal/lsp/testdata/rename/generics/unions.go.golden	2000-01-01 00:00:00.000000000 -0000
100757+++ b/gopls/internal/lsp/testdata/rename/generics/unions.go.golden	1970-01-01 00:00:00.000000000 +0000
100758@@ -1,24 +0,0 @@
100759--- R-rename --
100760-//go:build go1.18
100761-// +build go1.18
100762-
100763-package generics
100764-
100765-type R string //@rename("T", "R")
100766-
100767-type C interface {
100768-	R | ~int //@rename("T", "S")
100769-}
100770-
100771--- S-rename --
100772-//go:build go1.18
100773-// +build go1.18
100774-
100775-package generics
100776-
100777-type S string //@rename("T", "R")
100778-
100779-type C interface {
100780-	S | ~int //@rename("T", "S")
100781-}
100782-
100783diff -urN a/gopls/internal/lsp/testdata/rename/issue39614/issue39614.go.golden b/gopls/internal/lsp/testdata/rename/issue39614/issue39614.go.golden
100784--- a/gopls/internal/lsp/testdata/rename/issue39614/issue39614.go.golden	2000-01-01 00:00:00.000000000 -0000
100785+++ b/gopls/internal/lsp/testdata/rename/issue39614/issue39614.go.golden	1970-01-01 00:00:00.000000000 +0000
100786@@ -1,10 +0,0 @@
100787--- bar-rename --
100788-package issue39614
100789-
100790-func fn() {
100791-	var bar bool //@rename("foo","bar")
100792-	make(map[string]bool
100793-	if true {
100794-	}
100795-}
100796-
100797diff -urN a/gopls/internal/lsp/testdata/rename/issue39614/issue39614.go.in b/gopls/internal/lsp/testdata/rename/issue39614/issue39614.go.in
100798--- a/gopls/internal/lsp/testdata/rename/issue39614/issue39614.go.in	2000-01-01 00:00:00.000000000 -0000
100799+++ b/gopls/internal/lsp/testdata/rename/issue39614/issue39614.go.in	1970-01-01 00:00:00.000000000 +0000
100800@@ -1,8 +0,0 @@
100801-package issue39614
100802-
100803-func fn() {
100804-	var foo bool //@rename("foo","bar")
100805-	make(map[string]bool
100806-	if true {
100807-	}
100808-}
100809diff -urN a/gopls/internal/lsp/testdata/rename/issue42134/1.go b/gopls/internal/lsp/testdata/rename/issue42134/1.go
100810--- a/gopls/internal/lsp/testdata/rename/issue42134/1.go	2000-01-01 00:00:00.000000000 -0000
100811+++ b/gopls/internal/lsp/testdata/rename/issue42134/1.go	1970-01-01 00:00:00.000000000 +0000
100812@@ -1,8 +0,0 @@
100813-package issue42134
100814-
100815-func _() {
100816-	// foo computes things.
100817-	foo := func() {}
100818-
100819-	foo() //@rename("foo", "bar")
100820-}
100821diff -urN a/gopls/internal/lsp/testdata/rename/issue42134/1.go.golden b/gopls/internal/lsp/testdata/rename/issue42134/1.go.golden
100822--- a/gopls/internal/lsp/testdata/rename/issue42134/1.go.golden	2000-01-01 00:00:00.000000000 -0000
100823+++ b/gopls/internal/lsp/testdata/rename/issue42134/1.go.golden	1970-01-01 00:00:00.000000000 +0000
100824@@ -1,10 +0,0 @@
100825--- bar-rename --
100826-package issue42134
100827-
100828-func _() {
100829-	// bar computes things.
100830-	bar := func() {}
100831-
100832-	bar() //@rename("foo", "bar")
100833-}
100834-
100835diff -urN a/gopls/internal/lsp/testdata/rename/issue42134/2.go b/gopls/internal/lsp/testdata/rename/issue42134/2.go
100836--- a/gopls/internal/lsp/testdata/rename/issue42134/2.go	2000-01-01 00:00:00.000000000 -0000
100837+++ b/gopls/internal/lsp/testdata/rename/issue42134/2.go	1970-01-01 00:00:00.000000000 +0000
100838@@ -1,12 +0,0 @@
100839-package issue42134
100840-
100841-import "fmt"
100842-
100843-func _() {
100844-	// minNumber is a min number.
100845-	// Second line.
100846-	minNumber := min(1, 2)
100847-	fmt.Println(minNumber) //@rename("minNumber", "res")
100848-}
100849-
100850-func min(a, b int) int { return a }
100851diff -urN a/gopls/internal/lsp/testdata/rename/issue42134/2.go.golden b/gopls/internal/lsp/testdata/rename/issue42134/2.go.golden
100852--- a/gopls/internal/lsp/testdata/rename/issue42134/2.go.golden	2000-01-01 00:00:00.000000000 -0000
100853+++ b/gopls/internal/lsp/testdata/rename/issue42134/2.go.golden	1970-01-01 00:00:00.000000000 +0000
100854@@ -1,14 +0,0 @@
100855--- res-rename --
100856-package issue42134
100857-
100858-import "fmt"
100859-
100860-func _() {
100861-	// res is a min number.
100862-	// Second line.
100863-	res := min(1, 2)
100864-	fmt.Println(res) //@rename("minNumber", "res")
100865-}
100866-
100867-func min(a, b int) int { return a }
100868-
100869diff -urN a/gopls/internal/lsp/testdata/rename/issue42134/3.go b/gopls/internal/lsp/testdata/rename/issue42134/3.go
100870--- a/gopls/internal/lsp/testdata/rename/issue42134/3.go	2000-01-01 00:00:00.000000000 -0000
100871+++ b/gopls/internal/lsp/testdata/rename/issue42134/3.go	1970-01-01 00:00:00.000000000 +0000
100872@@ -1,11 +0,0 @@
100873-package issue42134
100874-
100875-func _() {
100876-	/*
100877-	tests contains test cases
100878-	*/
100879-	tests := []struct { //@rename("tests", "testCases")
100880-		in, out string
100881-	}{}
100882-	_ = tests
100883-}
100884diff -urN a/gopls/internal/lsp/testdata/rename/issue42134/3.go.golden b/gopls/internal/lsp/testdata/rename/issue42134/3.go.golden
100885--- a/gopls/internal/lsp/testdata/rename/issue42134/3.go.golden	2000-01-01 00:00:00.000000000 -0000
100886+++ b/gopls/internal/lsp/testdata/rename/issue42134/3.go.golden	1970-01-01 00:00:00.000000000 +0000
100887@@ -1,13 +0,0 @@
100888--- testCases-rename --
100889-package issue42134
100890-
100891-func _() {
100892-	/*
100893-	testCases contains test cases
100894-	*/
100895-	testCases := []struct { //@rename("tests", "testCases")
100896-		in, out string
100897-	}{}
100898-	_ = testCases
100899-}
100900-
100901diff -urN a/gopls/internal/lsp/testdata/rename/issue42134/4.go b/gopls/internal/lsp/testdata/rename/issue42134/4.go
100902--- a/gopls/internal/lsp/testdata/rename/issue42134/4.go	2000-01-01 00:00:00.000000000 -0000
100903+++ b/gopls/internal/lsp/testdata/rename/issue42134/4.go	1970-01-01 00:00:00.000000000 +0000
100904@@ -1,8 +0,0 @@
100905-package issue42134
100906-
100907-func _() {
100908-	// a is equal to 5. Comment must stay the same
100909-
100910-	a := 5
100911-	_ = a //@rename("a", "b")
100912-}
100913diff -urN a/gopls/internal/lsp/testdata/rename/issue42134/4.go.golden b/gopls/internal/lsp/testdata/rename/issue42134/4.go.golden
100914--- a/gopls/internal/lsp/testdata/rename/issue42134/4.go.golden	2000-01-01 00:00:00.000000000 -0000
100915+++ b/gopls/internal/lsp/testdata/rename/issue42134/4.go.golden	1970-01-01 00:00:00.000000000 +0000
100916@@ -1,10 +0,0 @@
100917--- b-rename --
100918-package issue42134
100919-
100920-func _() {
100921-	// a is equal to 5. Comment must stay the same
100922-
100923-	b := 5
100924-	_ = b //@rename("a", "b")
100925-}
100926-
100927diff -urN a/gopls/internal/lsp/testdata/rename/issue43616/issue43616.go.golden b/gopls/internal/lsp/testdata/rename/issue43616/issue43616.go.golden
100928--- a/gopls/internal/lsp/testdata/rename/issue43616/issue43616.go.golden	2000-01-01 00:00:00.000000000 -0000
100929+++ b/gopls/internal/lsp/testdata/rename/issue43616/issue43616.go.golden	1970-01-01 00:00:00.000000000 +0000
100930@@ -1,13 +0,0 @@
100931--- bar-rename --
100932-package issue43616
100933-
100934-type bar int //@rename("foo","bar"),prepare("oo","foo","foo")
100935-
100936-var x struct{ bar } //@rename("foo","baz")
100937-
100938-var _ = x.bar //@rename("foo","quux")
100939-
100940--- baz-rename --
100941-can't rename embedded fields: rename the type directly or name the field
100942--- quux-rename --
100943-can't rename embedded fields: rename the type directly or name the field
100944diff -urN a/gopls/internal/lsp/testdata/rename/issue43616/issue43616.go.in b/gopls/internal/lsp/testdata/rename/issue43616/issue43616.go.in
100945--- a/gopls/internal/lsp/testdata/rename/issue43616/issue43616.go.in	2000-01-01 00:00:00.000000000 -0000
100946+++ b/gopls/internal/lsp/testdata/rename/issue43616/issue43616.go.in	1970-01-01 00:00:00.000000000 +0000
100947@@ -1,7 +0,0 @@
100948-package issue43616
100949-
100950-type foo int //@rename("foo","bar"),prepare("oo","foo","foo")
100951-
100952-var x struct{ foo } //@rename("foo","baz")
100953-
100954-var _ = x.foo //@rename("foo","quux")
100955diff -urN a/gopls/internal/lsp/testdata/rename/shadow/shadow.go b/gopls/internal/lsp/testdata/rename/shadow/shadow.go
100956--- a/gopls/internal/lsp/testdata/rename/shadow/shadow.go	2000-01-01 00:00:00.000000000 -0000
100957+++ b/gopls/internal/lsp/testdata/rename/shadow/shadow.go	1970-01-01 00:00:00.000000000 +0000
100958@@ -1,20 +0,0 @@
100959-package shadow
100960-
100961-func _() {
100962-	a := true
100963-	b, c, _ := A(), B(), D() //@rename("A", "a"),rename("B", "b"),rename("b", "c"),rename("D", "d")
100964-	d := false
100965-	_, _, _, _ = a, b, c, d
100966-}
100967-
100968-func A() int {
100969-	return 0
100970-}
100971-
100972-func B() int {
100973-	return 0
100974-}
100975-
100976-func D() int {
100977-	return 0
100978-}
100979diff -urN a/gopls/internal/lsp/testdata/rename/shadow/shadow.go.golden b/gopls/internal/lsp/testdata/rename/shadow/shadow.go.golden
100980--- a/gopls/internal/lsp/testdata/rename/shadow/shadow.go.golden	2000-01-01 00:00:00.000000000 -0000
100981+++ b/gopls/internal/lsp/testdata/rename/shadow/shadow.go.golden	1970-01-01 00:00:00.000000000 +0000
100982@@ -1,51 +0,0 @@
100983--- a-rename --
100984-shadow/shadow.go:10:6: renaming this func "A" to "a"
100985-shadow/shadow.go:5:13:	would cause this reference to become shadowed
100986-shadow/shadow.go:4:2:	by this intervening var definition
100987--- b-rename --
100988-package shadow
100989-
100990-func _() {
100991-	a := true
100992-	b, c, _ := A(), b(), D() //@rename("A", "a"),rename("B", "b"),rename("b", "c"),rename("D", "d")
100993-	d := false
100994-	_, _, _, _ = a, b, c, d
100995-}
100996-
100997-func A() int {
100998-	return 0
100999-}
101000-
101001-func b() int {
101002-	return 0
101003-}
101004-
101005-func D() int {
101006-	return 0
101007-}
101008-
101009--- c-rename --
101010-shadow/shadow.go:5:2: renaming this var "b" to "c"
101011-shadow/shadow.go:5:5:	conflicts with var in same block
101012--- d-rename --
101013-package shadow
101014-
101015-func _() {
101016-	a := true
101017-	b, c, _ := A(), B(), d() //@rename("A", "a"),rename("B", "b"),rename("b", "c"),rename("D", "d")
101018-	d := false
101019-	_, _, _, _ = a, b, c, d
101020-}
101021-
101022-func A() int {
101023-	return 0
101024-}
101025-
101026-func B() int {
101027-	return 0
101028-}
101029-
101030-func d() int {
101031-	return 0
101032-}
101033-
101034diff -urN a/gopls/internal/lsp/testdata/rename/testy/testy.go b/gopls/internal/lsp/testdata/rename/testy/testy.go
101035--- a/gopls/internal/lsp/testdata/rename/testy/testy.go	2000-01-01 00:00:00.000000000 -0000
101036+++ b/gopls/internal/lsp/testdata/rename/testy/testy.go	1970-01-01 00:00:00.000000000 +0000
101037@@ -1,7 +0,0 @@
101038-package testy
101039-
101040-type tt int //@rename("tt", "testyType")
101041-
101042-func a() {
101043-	foo := 42 //@rename("foo", "bar")
101044-}
101045diff -urN a/gopls/internal/lsp/testdata/rename/testy/testy.go.golden b/gopls/internal/lsp/testdata/rename/testy/testy.go.golden
101046--- a/gopls/internal/lsp/testdata/rename/testy/testy.go.golden	2000-01-01 00:00:00.000000000 -0000
101047+++ b/gopls/internal/lsp/testdata/rename/testy/testy.go.golden	1970-01-01 00:00:00.000000000 +0000
101048@@ -1,18 +0,0 @@
101049--- bar-rename --
101050-package testy
101051-
101052-type tt int //@rename("tt", "testyType")
101053-
101054-func a() {
101055-	bar := 42 //@rename("foo", "bar")
101056-}
101057-
101058--- testyType-rename --
101059-package testy
101060-
101061-type testyType int //@rename("tt", "testyType")
101062-
101063-func a() {
101064-	foo := 42 //@rename("foo", "bar")
101065-}
101066-
101067diff -urN a/gopls/internal/lsp/testdata/rename/testy/testy_test.go b/gopls/internal/lsp/testdata/rename/testy/testy_test.go
101068--- a/gopls/internal/lsp/testdata/rename/testy/testy_test.go	2000-01-01 00:00:00.000000000 -0000
101069+++ b/gopls/internal/lsp/testdata/rename/testy/testy_test.go	1970-01-01 00:00:00.000000000 +0000
101070@@ -1,8 +0,0 @@
101071-package testy
101072-
101073-import "testing"
101074-
101075-func TestSomething(t *testing.T) {
101076-	var x int //@rename("x", "testyX")
101077-	a()       //@rename("a", "b")
101078-}
101079diff -urN a/gopls/internal/lsp/testdata/rename/testy/testy_test.go.golden b/gopls/internal/lsp/testdata/rename/testy/testy_test.go.golden
101080--- a/gopls/internal/lsp/testdata/rename/testy/testy_test.go.golden	2000-01-01 00:00:00.000000000 -0000
101081+++ b/gopls/internal/lsp/testdata/rename/testy/testy_test.go.golden	1970-01-01 00:00:00.000000000 +0000
101082@@ -1,30 +0,0 @@
101083--- b-rename --
101084-testy.go:
101085-package testy
101086-
101087-type tt int //@rename("tt", "testyType")
101088-
101089-func b() {
101090-	foo := 42 //@rename("foo", "bar")
101091-}
101092-
101093-testy_test.go:
101094-package testy
101095-
101096-import "testing"
101097-
101098-func TestSomething(t *testing.T) {
101099-	var x int //@rename("x", "testyX")
101100-	b()       //@rename("a", "b")
101101-}
101102-
101103--- testyX-rename --
101104-package testy
101105-
101106-import "testing"
101107-
101108-func TestSomething(t *testing.T) {
101109-	var testyX int //@rename("x", "testyX")
101110-	a()       //@rename("a", "b")
101111-}
101112-
101113diff -urN a/gopls/internal/lsp/testdata/rundespiteerrors/rundespiteerrors.go b/gopls/internal/lsp/testdata/rundespiteerrors/rundespiteerrors.go
101114--- a/gopls/internal/lsp/testdata/rundespiteerrors/rundespiteerrors.go	2000-01-01 00:00:00.000000000 -0000
101115+++ b/gopls/internal/lsp/testdata/rundespiteerrors/rundespiteerrors.go	1970-01-01 00:00:00.000000000 +0000
101116@@ -1,14 +0,0 @@
101117-package rundespiteerrors
101118-
101119-// This test verifies that analyzers without RunDespiteErrors are not
101120-// executed on a package containing type errors (see issue #54762).
101121-func _() {
101122-	// A type error.
101123-	_ = 1 + "" //@diag("1", "compiler", "mismatched types|cannot convert", "error")
101124-
101125-	// A violation of an analyzer for which RunDespiteErrors=false:
101126-	// no diagnostic is produced; the diag comment is merely illustrative.
101127-	for _ = range "" { //diag("for _", "simplifyrange", "simplify range expression", "warning")
101128-
101129-	}
101130-}
101131diff -urN a/gopls/internal/lsp/testdata/selectionrange/foo.go b/gopls/internal/lsp/testdata/selectionrange/foo.go
101132--- a/gopls/internal/lsp/testdata/selectionrange/foo.go	2000-01-01 00:00:00.000000000 -0000
101133+++ b/gopls/internal/lsp/testdata/selectionrange/foo.go	1970-01-01 00:00:00.000000000 +0000
101134@@ -1,13 +0,0 @@
101135-package foo
101136-
101137-import "time"
101138-
101139-func Bar(x, y int, t time.Time) int {
101140-	zs := []int{1, 2, 3} //@selectionrange("1")
101141-
101142-	for _, z := range zs {
101143-		x = x + z + y + zs[1] //@selectionrange("1")
101144-	}
101145-
101146-	return x + y //@selectionrange("+")
101147-}
101148diff -urN a/gopls/internal/lsp/testdata/selectionrange/foo.go.golden b/gopls/internal/lsp/testdata/selectionrange/foo.go.golden
101149--- a/gopls/internal/lsp/testdata/selectionrange/foo.go.golden	2000-01-01 00:00:00.000000000 -0000
101150+++ b/gopls/internal/lsp/testdata/selectionrange/foo.go.golden	1970-01-01 00:00:00.000000000 +0000
101151@@ -1,29 +0,0 @@
101152--- selectionrange_foo_12_11 --
101153-Ranges 0:
101154-	11:8-11:13 "x + y"
101155-	11:1-11:13 "return x + y"
101156-	4:36-12:1 "{\\n\tzs := []int{...ionrange(\"+\")\\n}"
101157-	4:0-12:1 "func Bar(x, y i...ionrange(\"+\")\\n}"
101158-	0:0-12:1 "package foo\\n\\nim...ionrange(\"+\")\\n}"
101159-
101160--- selectionrange_foo_6_14 --
101161-Ranges 0:
101162-	5:13-5:14 "1"
101163-	5:7-5:21 "[]int{1, 2, 3}"
101164-	5:1-5:21 "zs := []int{1, 2, 3}"
101165-	4:36-12:1 "{\\n\tzs := []int{...ionrange(\"+\")\\n}"
101166-	4:0-12:1 "func Bar(x, y i...ionrange(\"+\")\\n}"
101167-	0:0-12:1 "package foo\\n\\nim...ionrange(\"+\")\\n}"
101168-
101169--- selectionrange_foo_9_22 --
101170-Ranges 0:
101171-	8:21-8:22 "1"
101172-	8:18-8:23 "zs[1]"
101173-	8:6-8:23 "x + z + y + zs[1]"
101174-	8:2-8:23 "x = x + z + y + zs[1]"
101175-	7:22-9:2 "{\\n\t\tx = x + z +...onrange(\"1\")\\n\t}"
101176-	7:1-9:2 "for _, z := ran...onrange(\"1\")\\n\t}"
101177-	4:36-12:1 "{\\n\tzs := []int{...ionrange(\"+\")\\n}"
101178-	4:0-12:1 "func Bar(x, y i...ionrange(\"+\")\\n}"
101179-	0:0-12:1 "package foo\\n\\nim...ionrange(\"+\")\\n}"
101180-
101181diff -urN a/gopls/internal/lsp/testdata/selector/selector.go.in b/gopls/internal/lsp/testdata/selector/selector.go.in
101182--- a/gopls/internal/lsp/testdata/selector/selector.go.in	2000-01-01 00:00:00.000000000 -0000
101183+++ b/gopls/internal/lsp/testdata/selector/selector.go.in	1970-01-01 00:00:00.000000000 +0000
101184@@ -1,66 +0,0 @@
101185-// +build go1.11
101186-
101187-package selector
101188-
101189-import (
101190-	"golang.org/lsptests/bar"
101191-)
101192-
101193-type S struct {
101194-	B, A, C int //@item(Bf, "B", "int", "field"),item(Af, "A", "int", "field"),item(Cf, "C", "int", "field")
101195-}
101196-
101197-func _() {
101198-	_ = S{}.; //@complete(";", Af, Bf, Cf)
101199-}
101200-
101201-type bob struct { a int } //@item(a, "a", "int", "field")
101202-type george struct { b int }
101203-type jack struct { c int } //@item(c, "c", "int", "field")
101204-type jill struct { d int }
101205-
101206-func (b *bob) george() *george {} //@item(george, "george", "func() *george", "method")
101207-func (g *george) jack() *jack {}
101208-func (j *jack) jill() *jill {} //@item(jill, "jill", "func() *jill", "method")
101209-
101210-func _() {
101211-	b := &bob{}
101212-	y := b.george().
101213-		jack();
101214-	y.; //@complete(";", c, jill)
101215-}
101216-
101217-func _() {
101218-	bar. //@complete(" /", Bar)
101219-	x := 5
101220-
101221-	var b *bob
101222-	b. //@complete(" /", a, george)
101223-	y, z := 5, 6
101224-
101225-	b. //@complete(" /", a, george)
101226-	y, z, a, b, c := 5, 6
101227-}
101228-
101229-func _() {
101230-	bar. //@complete(" /", Bar)
101231-	bar.Bar()
101232-
101233-	bar. //@complete(" /", Bar)
101234-	go f()
101235-}
101236-
101237-func _() {
101238-	var b *bob
101239-	if y != b. //@complete(" /", a, george)
101240-	z := 5
101241-
101242-	if z + y + 1 + b. //@complete(" /", a, george)
101243-	r, s, t := 4, 5
101244-
101245-	if y != b. //@complete(" /", a, george)
101246-	z = 5
101247-
101248-	if z + y + 1 + b. //@complete(" /", a, george)
101249-	r = 4
101250-}
101251diff -urN a/gopls/internal/lsp/testdata/semantic/a.go b/gopls/internal/lsp/testdata/semantic/a.go
101252--- a/gopls/internal/lsp/testdata/semantic/a.go	2000-01-01 00:00:00.000000000 -0000
101253+++ b/gopls/internal/lsp/testdata/semantic/a.go	1970-01-01 00:00:00.000000000 +0000
101254@@ -1,81 +0,0 @@
101255-package semantictokens //@ semantic("")
101256-
101257-import (
101258-	_ "encoding/utf8"
101259-	utf "encoding/utf8"
101260-	"fmt" //@ semantic("fmt")
101261-	. "fmt"
101262-	"unicode/utf8"
101263-)
101264-
101265-var (
101266-	a           = fmt.Print
101267-	b  []string = []string{"foo"}
101268-	c1 chan int
101269-	c2 <-chan int
101270-	c3 = make([]chan<- int)
101271-	b  = A{X: 23}
101272-	m  map[bool][3]*float64
101273-)
101274-
101275-const (
101276-	xx F = iota
101277-	yy   = xx + 3
101278-	zz   = ""
101279-	ww   = "not " + zz
101280-)
101281-
101282-type A struct {
101283-	X int `foof`
101284-}
101285-type B interface {
101286-	A
101287-	sad(int) bool
101288-}
101289-
101290-type F int
101291-
101292-func (a *A) f() bool {
101293-	var z string
101294-	x := "foo"
101295-	a(x)
101296-	y := "bar" + x
101297-	switch z {
101298-	case "xx":
101299-	default:
101300-	}
101301-	select {
101302-	case z := <-c3[0]:
101303-	default:
101304-	}
101305-	for k, v := range m {
101306-		return (!k) && v[0] == nil
101307-	}
101308-	c2 <- A.X
101309-	w := b[4:]
101310-	j := len(x)
101311-	j--
101312-	q := []interface{}{j, 23i, &y}
101313-	g(q...)
101314-	return true
101315-}
101316-
101317-func g(vv ...interface{}) {
101318-	ff := func() {}
101319-	defer ff()
101320-	go utf.RuneCount("")
101321-	go utf8.RuneCount(vv.(string))
101322-	if true {
101323-	} else {
101324-	}
101325-Never:
101326-	for i := 0; i < 10; {
101327-		break Never
101328-	}
101329-	_, ok := vv[0].(A)
101330-	if !ok {
101331-		switch x := vv[0].(type) {
101332-		}
101333-		goto Never
101334-	}
101335-}
101336diff -urN a/gopls/internal/lsp/testdata/semantic/a.go.golden b/gopls/internal/lsp/testdata/semantic/a.go.golden
101337--- a/gopls/internal/lsp/testdata/semantic/a.go.golden	2000-01-01 00:00:00.000000000 -0000
101338+++ b/gopls/internal/lsp/testdata/semantic/a.go.golden	1970-01-01 00:00:00.000000000 +0000
101339@@ -1,83 +0,0 @@
101340--- semantic --
101341-/*⇒7,keyword,[]*/package /*⇒14,namespace,[]*/semantictokens /*⇒16,comment,[]*///@ semantic("")
101342-
101343-/*⇒6,keyword,[]*/import (
101344-	_ "encoding/utf8"
101345-	/*⇒3,namespace,[]*/utf "encoding/utf8"
101346-	"fmt"/*⇐3,namespace,[]*/ /*⇒19,comment,[]*///@ semantic("fmt")
101347-	. "fmt"
101348-	"unicode/utf8"/*⇐4,namespace,[]*/
101349-)
101350-
101351-/*⇒3,keyword,[]*/var (
101352-	/*⇒1,variable,[definition]*/a           = /*⇒3,namespace,[]*/fmt./*⇒5,function,[]*/Print
101353-	/*⇒1,variable,[definition]*/b  []/*⇒6,type,[defaultLibrary]*/string = []/*⇒6,type,[defaultLibrary]*/string{/*⇒5,string,[]*/"foo"}
101354-	/*⇒2,variable,[definition]*/c1 /*⇒4,keyword,[]*/chan /*⇒3,type,[defaultLibrary]*/int
101355-	/*⇒2,variable,[definition]*/c2 /*⇒2,operator,[]*/<-/*⇒4,keyword,[]*/chan /*⇒3,type,[defaultLibrary]*/int
101356-	/*⇒2,variable,[definition]*/c3 = /*⇒4,function,[defaultLibrary]*/make([]/*⇒4,keyword,[]*/chan/*⇒2,operator,[]*/<- /*⇒3,type,[defaultLibrary]*/int)
101357-	/*⇒1,variable,[definition]*/b  = /*⇒1,type,[]*/A{/*⇒1,variable,[]*/X: /*⇒2,number,[]*/23}
101358-	/*⇒1,variable,[definition]*/m  /*⇒3,keyword,[]*/map[/*⇒4,type,[defaultLibrary]*/bool][/*⇒1,number,[]*/3]/*⇒1,operator,[]*/*/*⇒7,type,[defaultLibrary]*/float64
101359-)
101360-
101361-/*⇒5,keyword,[]*/const (
101362-	/*⇒2,variable,[definition readonly]*/xx /*⇒1,type,[]*/F = /*⇒4,variable,[readonly]*/iota
101363-	/*⇒2,variable,[definition readonly]*/yy   = /*⇒2,variable,[readonly]*/xx /*⇒1,operator,[]*/+ /*⇒1,number,[]*/3
101364-	/*⇒2,variable,[definition readonly]*/zz   = /*⇒2,string,[]*/""
101365-	/*⇒2,variable,[definition readonly]*/ww   = /*⇒6,string,[]*/"not " /*⇒1,operator,[]*/+ /*⇒2,variable,[readonly]*/zz
101366-)
101367-
101368-/*⇒4,keyword,[]*/type /*⇒1,type,[definition]*/A /*⇒6,keyword,[]*/struct {
101369-	/*⇒1,variable,[definition]*/X /*⇒3,type,[defaultLibrary]*/int /*⇒6,string,[]*/`foof`
101370-}
101371-/*⇒4,keyword,[]*/type /*⇒1,type,[definition]*/B /*⇒9,keyword,[]*/interface {
101372-	/*⇒1,type,[]*/A
101373-	/*⇒3,method,[definition]*/sad(/*⇒3,type,[defaultLibrary]*/int) /*⇒4,type,[defaultLibrary]*/bool
101374-}
101375-
101376-/*⇒4,keyword,[]*/type /*⇒1,type,[definition]*/F /*⇒3,type,[defaultLibrary]*/int
101377-
101378-/*⇒4,keyword,[]*/func (/*⇒1,variable,[]*/a /*⇒1,operator,[]*/*/*⇒1,type,[]*/A) /*⇒1,method,[definition]*/f() /*⇒4,type,[defaultLibrary]*/bool {
101379-	/*⇒3,keyword,[]*/var /*⇒1,variable,[definition]*/z /*⇒6,type,[defaultLibrary]*/string
101380-	/*⇒1,variable,[definition]*/x /*⇒2,operator,[]*/:= /*⇒5,string,[]*/"foo"
101381-	/*⇒1,variable,[]*/a(/*⇒1,variable,[]*/x)
101382-	/*⇒1,variable,[definition]*/y /*⇒2,operator,[]*/:= /*⇒5,string,[]*/"bar" /*⇒1,operator,[]*/+ /*⇒1,variable,[]*/x
101383-	/*⇒6,keyword,[]*/switch /*⇒1,variable,[]*/z {
101384-	/*⇒4,keyword,[]*/case /*⇒4,string,[]*/"xx":
101385-	/*⇒7,keyword,[]*/default:
101386-	}
101387-	/*⇒6,keyword,[]*/select {
101388-	/*⇒4,keyword,[]*/case /*⇒1,variable,[definition]*/z /*⇒2,operator,[]*/:= /*⇒2,operator,[]*/<-/*⇒2,variable,[]*/c3[/*⇒1,number,[]*/0]:
101389-	/*⇒7,keyword,[]*/default:
101390-	}
101391-	/*⇒3,keyword,[]*/for /*⇒1,variable,[definition]*/k, /*⇒1,variable,[definition]*/v := /*⇒5,keyword,[]*/range /*⇒1,variable,[]*/m {
101392-		/*⇒6,keyword,[]*/return (/*⇒1,operator,[]*/!/*⇒1,variable,[]*/k) /*⇒2,operator,[]*/&& /*⇒1,variable,[]*/v[/*⇒1,number,[]*/0] /*⇒2,operator,[]*/== /*⇒3,variable,[readonly defaultLibrary]*/nil
101393-	}
101394-	/*⇒2,variable,[]*/c2 /*⇒2,operator,[]*/<- /*⇒1,type,[]*/A./*⇒1,variable,[]*/X
101395-	/*⇒1,variable,[definition]*/w /*⇒2,operator,[]*/:= /*⇒1,variable,[]*/b[/*⇒1,number,[]*/4:]
101396-	/*⇒1,variable,[definition]*/j /*⇒2,operator,[]*/:= /*⇒3,function,[defaultLibrary]*/len(/*⇒1,variable,[]*/x)
101397-	/*⇒1,variable,[]*/j/*⇒2,operator,[]*/--
101398-	/*⇒1,variable,[definition]*/q /*⇒2,operator,[]*/:= []/*⇒9,keyword,[]*/interface{}{/*⇒1,variable,[]*/j, /*⇒3,number,[]*/23i, /*⇒1,operator,[]*/&/*⇒1,variable,[]*/y}
101399-	/*⇒1,function,[]*/g(/*⇒1,variable,[]*/q/*⇒3,operator,[]*/...)
101400-	/*⇒6,keyword,[]*/return /*⇒4,variable,[readonly]*/true
101401-}
101402-
101403-/*⇒4,keyword,[]*/func /*⇒1,function,[definition]*/g(/*⇒2,parameter,[definition]*/vv /*⇒3,operator,[]*/.../*⇒9,keyword,[]*/interface{}) {
101404-	/*⇒2,variable,[definition]*/ff /*⇒2,operator,[]*/:= /*⇒4,keyword,[]*/func() {}
101405-	/*⇒5,keyword,[]*/defer /*⇒2,function,[]*/ff()
101406-	/*⇒2,keyword,[]*/go /*⇒3,namespace,[]*/utf./*⇒9,function,[]*/RuneCount(/*⇒2,string,[]*/"")
101407-	/*⇒2,keyword,[]*/go /*⇒4,namespace,[]*/utf8./*⇒9,function,[]*/RuneCount(/*⇒2,parameter,[]*/vv.(/*⇒6,type,[]*/string))
101408-	/*⇒2,keyword,[]*/if /*⇒4,variable,[readonly]*/true {
101409-	} /*⇒4,keyword,[]*/else {
101410-	}
101411-/*⇒5,parameter,[definition]*/Never:
101412-	/*⇒3,keyword,[]*/for /*⇒1,variable,[definition]*/i /*⇒2,operator,[]*/:= /*⇒1,number,[]*/0; /*⇒1,variable,[]*/i /*⇒1,operator,[]*/< /*⇒2,number,[]*/10; {
101413-		/*⇒5,keyword,[]*/break Never
101414-	}
101415-	_, /*⇒2,variable,[definition]*/ok /*⇒2,operator,[]*/:= /*⇒2,parameter,[]*/vv[/*⇒1,number,[]*/0].(/*⇒1,type,[]*/A)
101416-	/*⇒2,keyword,[]*/if /*⇒1,operator,[]*/!/*⇒2,variable,[]*/ok {
101417-		/*⇒6,keyword,[]*/switch /*⇒1,variable,[definition]*/x /*⇒2,operator,[]*/:= /*⇒2,parameter,[]*/vv[/*⇒1,number,[]*/0].(/*⇒4,keyword,[]*/type) {
101418-		}
101419-		/*⇒4,keyword,[]*/goto Never
101420-	}
101421-}
101422-
101423diff -urN a/gopls/internal/lsp/testdata/semantic/b.go b/gopls/internal/lsp/testdata/semantic/b.go
101424--- a/gopls/internal/lsp/testdata/semantic/b.go	2000-01-01 00:00:00.000000000 -0000
101425+++ b/gopls/internal/lsp/testdata/semantic/b.go	1970-01-01 00:00:00.000000000 +0000
101426@@ -1,38 +0,0 @@
101427-package semantictokens //@ semantic("")
101428-
101429-func f(x ...interface{}) {
101430-}
101431-
101432-func weirⰀd() { /*��*/ // comment
101433-	const (
101434-		snil   = nil
101435-		nil    = true
101436-		true   = false
101437-		false  = snil
101438-		cmd    = `foof`
101439-		double = iota
101440-		iota   = copy
101441-		four   = (len(cmd)/2 < 5)
101442-		five   = four
101443-	)
101444-	f(cmd, nil, double, iota)
101445-}
101446-
101447-/*
101448-
101449-multiline */ /*
101450-multiline
101451-*/
101452-type AA int
101453-type BB struct {
101454-	AA
101455-}
101456-type CC struct {
101457-	AA int
101458-}
101459-type D func(aa AA) (BB error)
101460-type E func(AA) BB
101461-
101462-var a chan<- chan int
101463-var b chan<- <-chan int
101464-var c <-chan <-chan int
101465diff -urN a/gopls/internal/lsp/testdata/semantic/b.go.golden b/gopls/internal/lsp/testdata/semantic/b.go.golden
101466--- a/gopls/internal/lsp/testdata/semantic/b.go.golden	2000-01-01 00:00:00.000000000 -0000
101467+++ b/gopls/internal/lsp/testdata/semantic/b.go.golden	1970-01-01 00:00:00.000000000 +0000
101468@@ -1,40 +0,0 @@
101469--- semantic --
101470-/*⇒7,keyword,[]*/package /*⇒14,namespace,[]*/semantictokens /*⇒16,comment,[]*///@ semantic("")
101471-
101472-/*⇒4,keyword,[]*/func /*⇒1,function,[definition]*/f(/*⇒1,parameter,[definition]*/x /*⇒3,operator,[]*/.../*⇒9,keyword,[]*/interface{}) {
101473-}
101474-
101475-/*⇒4,keyword,[]*/func /*⇒6,function,[definition]*/weirⰀd() { /*⇒5,comment,[]*//*��*/ /*⇒10,comment,[]*/// comment
101476-	/*⇒5,keyword,[]*/const (
101477-		/*⇒4,variable,[definition readonly]*/snil   = /*⇒3,variable,[readonly defaultLibrary]*/nil
101478-		/*⇒3,variable,[definition readonly]*/nil    = /*⇒4,variable,[readonly]*/true
101479-		/*⇒4,variable,[definition readonly]*/true   = /*⇒5,variable,[readonly]*/false
101480-		/*⇒5,variable,[definition readonly]*/false  = /*⇒4,variable,[readonly]*/snil
101481-		/*⇒3,variable,[definition readonly]*/cmd    = /*⇒6,string,[]*/`foof`
101482-		/*⇒6,variable,[definition readonly]*/double = /*⇒4,variable,[readonly]*/iota
101483-		/*⇒4,variable,[definition readonly]*/iota   = /*⇒4,function,[defaultLibrary]*/copy
101484-		/*⇒4,variable,[definition readonly]*/four   = (/*⇒3,function,[defaultLibrary]*/len(/*⇒3,variable,[readonly]*/cmd)/*⇒1,operator,[]*// /*⇒1,number,[]*/2 /*⇒1,operator,[]*/< /*⇒1,number,[]*/5)
101485-		/*⇒4,variable,[definition readonly]*/five   = /*⇒4,variable,[readonly]*/four
101486-	)
101487-	/*⇒1,function,[]*/f(/*⇒3,variable,[readonly]*/cmd, /*⇒3,variable,[readonly]*/nil, /*⇒6,variable,[readonly]*/double, /*⇒4,variable,[readonly]*/iota)
101488-}
101489-
101490-/*⇒2,comment,[]*//*
101491-/*⇒0,comment,[]*/
101492-/*⇒12,comment,[]*/multiline */ /*⇒2,comment,[]*//*
101493-/*⇒9,comment,[]*/multiline
101494-/*⇒2,comment,[]*/*/
101495-/*⇒4,keyword,[]*/type /*⇒2,type,[definition]*/AA /*⇒3,type,[defaultLibrary]*/int
101496-/*⇒4,keyword,[]*/type /*⇒2,type,[definition]*/BB /*⇒6,keyword,[]*/struct {
101497-	/*⇒2,type,[]*/AA
101498-}
101499-/*⇒4,keyword,[]*/type /*⇒2,type,[definition]*/CC /*⇒6,keyword,[]*/struct {
101500-	/*⇒2,variable,[definition]*/AA /*⇒3,type,[defaultLibrary]*/int
101501-}
101502-/*⇒4,keyword,[]*/type /*⇒1,type,[definition]*/D /*⇒4,keyword,[]*/func(/*⇒2,parameter,[definition]*/aa /*⇒2,type,[]*/AA) (/*⇒2,parameter,[definition]*/BB /*⇒5,type,[]*/error)
101503-/*⇒4,keyword,[]*/type /*⇒1,type,[definition]*/E /*⇒4,keyword,[]*/func(/*⇒2,type,[]*/AA) /*⇒2,type,[]*/BB
101504-
101505-/*⇒3,keyword,[]*/var /*⇒1,variable,[definition]*/a /*⇒4,keyword,[]*/chan/*⇒2,operator,[]*/<- /*⇒4,keyword,[]*/chan /*⇒3,type,[defaultLibrary]*/int
101506-/*⇒3,keyword,[]*/var /*⇒1,variable,[definition]*/b /*⇒4,keyword,[]*/chan/*⇒2,operator,[]*/<- /*⇒2,operator,[]*/<-/*⇒4,keyword,[]*/chan /*⇒3,type,[defaultLibrary]*/int
101507-/*⇒3,keyword,[]*/var /*⇒1,variable,[definition]*/c /*⇒2,operator,[]*/<-/*⇒4,keyword,[]*/chan /*⇒2,operator,[]*/<-/*⇒4,keyword,[]*/chan /*⇒3,type,[defaultLibrary]*/int
101508-
101509diff -urN a/gopls/internal/lsp/testdata/semantic/README.md b/gopls/internal/lsp/testdata/semantic/README.md
101510--- a/gopls/internal/lsp/testdata/semantic/README.md	2000-01-01 00:00:00.000000000 -0000
101511+++ b/gopls/internal/lsp/testdata/semantic/README.md	1970-01-01 00:00:00.000000000 +0000
101512@@ -1,2 +0,0 @@
101513-The golden files are the output of `gopls semtok <src-file>`, with `-- semantic --`
101514-inserted as the first line (the spaces are mandatory) and an extra newline at the end.
101515diff -urN a/gopls/internal/lsp/testdata/semantic/semantic_test.go b/gopls/internal/lsp/testdata/semantic/semantic_test.go
101516--- a/gopls/internal/lsp/testdata/semantic/semantic_test.go	2000-01-01 00:00:00.000000000 -0000
101517+++ b/gopls/internal/lsp/testdata/semantic/semantic_test.go	1970-01-01 00:00:00.000000000 +0000
101518@@ -1,13 +0,0 @@
101519-package semantictokens
101520-
101521-import (
101522-	"os"
101523-	"testing"
101524-)
101525-
101526-func TestSemanticTokens(t *testing.T) {
101527-	a, _ := os.Getwd()
101528-	// climb up to find internal/lsp
101529-	// find all the .go files
101530-
101531-}
101532diff -urN a/gopls/internal/lsp/testdata/signature/signature2.go.golden b/gopls/internal/lsp/testdata/signature/signature2.go.golden
101533--- a/gopls/internal/lsp/testdata/signature/signature2.go.golden	2000-01-01 00:00:00.000000000 -0000
101534+++ b/gopls/internal/lsp/testdata/signature/signature2.go.golden	1970-01-01 00:00:00.000000000 +0000
101535@@ -1,3 +0,0 @@
101536--- Foo(a string, b int) (c bool)-signature --
101537-Foo(a string, b int) (c bool)
101538-
101539diff -urN a/gopls/internal/lsp/testdata/signature/signature2.go.in b/gopls/internal/lsp/testdata/signature/signature2.go.in
101540--- a/gopls/internal/lsp/testdata/signature/signature2.go.in	2000-01-01 00:00:00.000000000 -0000
101541+++ b/gopls/internal/lsp/testdata/signature/signature2.go.in	1970-01-01 00:00:00.000000000 +0000
101542@@ -1,5 +0,0 @@
101543-package signature
101544-
101545-func _() {
101546-	Foo(//@signature("//", "Foo(a string, b int) (c bool)", 0)
101547-}
101548diff -urN a/gopls/internal/lsp/testdata/signature/signature3.go.golden b/gopls/internal/lsp/testdata/signature/signature3.go.golden
101549--- a/gopls/internal/lsp/testdata/signature/signature3.go.golden	2000-01-01 00:00:00.000000000 -0000
101550+++ b/gopls/internal/lsp/testdata/signature/signature3.go.golden	1970-01-01 00:00:00.000000000 +0000
101551@@ -1,3 +0,0 @@
101552--- Foo(a string, b int) (c bool)-signature --
101553-Foo(a string, b int) (c bool)
101554-
101555diff -urN a/gopls/internal/lsp/testdata/signature/signature3.go.in b/gopls/internal/lsp/testdata/signature/signature3.go.in
101556--- a/gopls/internal/lsp/testdata/signature/signature3.go.in	2000-01-01 00:00:00.000000000 -0000
101557+++ b/gopls/internal/lsp/testdata/signature/signature3.go.in	1970-01-01 00:00:00.000000000 +0000
101558@@ -1,5 +0,0 @@
101559-package signature
101560-
101561-func _() {
101562-	Foo("hello",//@signature("//", "Foo(a string, b int) (c bool)", 1)
101563-}
101564\ No newline at end of file
101565diff -urN a/gopls/internal/lsp/testdata/signature/signature.go b/gopls/internal/lsp/testdata/signature/signature.go
101566--- a/gopls/internal/lsp/testdata/signature/signature.go	2000-01-01 00:00:00.000000000 -0000
101567+++ b/gopls/internal/lsp/testdata/signature/signature.go	1970-01-01 00:00:00.000000000 +0000
101568@@ -1,85 +0,0 @@
101569-// Package signature has tests for signature help.
101570-package signature
101571-
101572-import (
101573-	"bytes"
101574-	"encoding/json"
101575-	"math/big"
101576-)
101577-
101578-func Foo(a string, b int) (c bool) {
101579-	return
101580-}
101581-
101582-func Bar(float64, ...byte) {
101583-}
101584-
101585-type myStruct struct{}
101586-
101587-func (*myStruct) foo(e *json.Decoder) (*big.Int, error) {
101588-	return nil, nil
101589-}
101590-
101591-type MyType struct{}
101592-
101593-type MyFunc func(foo int) string
101594-
101595-type Alias = int
101596-type OtherAlias = int
101597-type StringAlias = string
101598-
101599-func AliasSlice(a []*Alias) (b Alias)                                 { return 0 }
101600-func AliasMap(a map[*Alias]StringAlias) (b, c map[*Alias]StringAlias) { return nil, nil }
101601-func OtherAliasMap(a, b map[Alias]OtherAlias) map[Alias]OtherAlias    { return nil }
101602-
101603-func Qux() {
101604-	Foo("foo", 123) //@signature("(", "Foo(a string, b int) (c bool)", 0)
101605-	Foo("foo", 123) //@signature("123", "Foo(a string, b int) (c bool)", 1)
101606-	Foo("foo", 123) //@signature(",", "Foo(a string, b int) (c bool)", 0)
101607-	Foo("foo", 123) //@signature(" 1", "Foo(a string, b int) (c bool)", 1)
101608-	Foo("foo", 123) //@signature(")", "Foo(a string, b int) (c bool)", 1)
101609-
101610-	Bar(13.37, 0x13)       //@signature("13.37", "Bar(float64, ...byte)", 0)
101611-	Bar(13.37, 0x37)       //@signature("0x37", "Bar(float64, ...byte)", 1)
101612-	Bar(13.37, 1, 2, 3, 4) //@signature("4", "Bar(float64, ...byte)", 1)
101613-
101614-	fn := func(hi, there string) func(i int) rune {
101615-		return func(int) rune { return 0 }
101616-	}
101617-
101618-	fn("hi", "there")    //@signature("hi", "", 0)
101619-	fn("hi", "there")    //@signature(",", "fn(hi string, there string) func(i int) rune", 0)
101620-	fn("hi", "there")(1) //@signature("1", "func(i int) rune", 0)
101621-
101622-	fnPtr := &fn
101623-	(*fnPtr)("hi", "there") //@signature(",", "func(hi string, there string) func(i int) rune", 0)
101624-
101625-	var fnIntf interface{} = Foo
101626-	fnIntf.(func(string, int) bool)("hi", 123) //@signature("123", "func(string, int) bool", 1)
101627-
101628-	(&bytes.Buffer{}).Next(2) //@signature("2", "Next(n int) []byte", 0)
101629-
101630-	myFunc := MyFunc(func(n int) string { return "" })
101631-	myFunc(123) //@signature("123", "myFunc(foo int) string", 0)
101632-
101633-	var ms myStruct
101634-	ms.foo(nil) //@signature("nil", "foo(e *json.Decoder) (*big.Int, error)", 0)
101635-
101636-	_ = make([]int, 1, 2) //@signature("2", "make(t Type, size ...int) Type", 1)
101637-
101638-	Foo(myFunc(123), 456) //@signature("myFunc", "Foo(a string, b int) (c bool)", 0)
101639-	Foo(myFunc(123), 456) //@signature("123", "myFunc(foo int) string", 0)
101640-
101641-	panic("oops!")            //@signature(")", "panic(v interface{})", 0)
101642-	println("hello", "world") //@signature(",", "println(args ...Type)", 0)
101643-
101644-	Hello(func() {
101645-		//@signature("//", "", 0)
101646-	})
101647-
101648-	AliasSlice()    //@signature(")", "AliasSlice(a []*Alias) (b Alias)", 0)
101649-	AliasMap()      //@signature(")", "AliasMap(a map[*Alias]StringAlias) (b map[*Alias]StringAlias, c map[*Alias]StringAlias)", 0)
101650-	OtherAliasMap() //@signature(")", "OtherAliasMap(a map[Alias]OtherAlias, b map[Alias]OtherAlias) map[Alias]OtherAlias", 0)
101651-}
101652-
101653-func Hello(func()) {}
101654diff -urN a/gopls/internal/lsp/testdata/signature/signature.go.golden b/gopls/internal/lsp/testdata/signature/signature.go.golden
101655--- a/gopls/internal/lsp/testdata/signature/signature.go.golden	2000-01-01 00:00:00.000000000 -0000
101656+++ b/gopls/internal/lsp/testdata/signature/signature.go.golden	1970-01-01 00:00:00.000000000 +0000
101657@@ -1,53 +0,0 @@
101658--- AliasMap(a map[*Alias]StringAlias) (b map[*Alias]StringAlias, c map[*Alias]StringAlias)-signature --
101659-AliasMap(a map[*Alias]StringAlias) (b map[*Alias]StringAlias, c map[*Alias]StringAlias)
101660-
101661--- AliasSlice(a []*Alias) (b Alias)-signature --
101662-AliasSlice(a []*Alias) (b Alias)
101663-
101664--- Bar(float64, ...byte)-signature --
101665-Bar(float64, ...byte)
101666-
101667--- Foo(a string, b int) (c bool)-signature --
101668-Foo(a string, b int) (c bool)
101669-
101670--- Next(n int) []byte-signature --
101671-Next(n int) []byte
101672-
101673-Next returns a slice containing the next n bytes from the buffer, advancing the buffer as if the bytes had been returned by Read.
101674-
101675--- OtherAliasMap(a map[Alias]OtherAlias, b map[Alias]OtherAlias) map[Alias]OtherAlias-signature --
101676-OtherAliasMap(a map[Alias]OtherAlias, b map[Alias]OtherAlias) map[Alias]OtherAlias
101677-
101678--- fn(hi string, there string) func(i int) rune-signature --
101679-fn(hi string, there string) func(i int) rune
101680-
101681--- foo(e *json.Decoder) (*big.Int, error)-signature --
101682-foo(e *json.Decoder) (*big.Int, error)
101683-
101684--- func(hi string, there string) func(i int) rune-signature --
101685-func(hi string, there string) func(i int) rune
101686-
101687--- func(i int) rune-signature --
101688-func(i int) rune
101689-
101690--- func(string, int) bool-signature --
101691-func(string, int) bool
101692-
101693--- make(t Type, size ...int) Type-signature --
101694-make(t Type, size ...int) Type
101695-
101696-The make built-in function allocates and initializes an object of type slice, map, or chan (only).
101697-
101698--- myFunc(foo int) string-signature --
101699-myFunc(foo int) string
101700-
101701--- panic(v interface{})-signature --
101702-panic(v any)
101703-
101704-The panic built-in function stops normal execution of the current goroutine.
101705-
101706--- println(args ...Type)-signature --
101707-println(args ...Type)
101708-
101709-The println built-in function formats its arguments in an implementation-specific way and writes the result to standard error.
101710-
101711diff -urN a/gopls/internal/lsp/testdata/signature/signature_test.go b/gopls/internal/lsp/testdata/signature/signature_test.go
101712--- a/gopls/internal/lsp/testdata/signature/signature_test.go	2000-01-01 00:00:00.000000000 -0000
101713+++ b/gopls/internal/lsp/testdata/signature/signature_test.go	1970-01-01 00:00:00.000000000 +0000
101714@@ -1,13 +0,0 @@
101715-package signature_test
101716-
101717-import (
101718-	"testing"
101719-
101720-	sig "golang.org/lsptests/signature"
101721-)
101722-
101723-func TestSignature(t *testing.T) {
101724-	sig.AliasSlice()    //@signature(")", "AliasSlice(a []*sig.Alias) (b sig.Alias)", 0)
101725-	sig.AliasMap()      //@signature(")", "AliasMap(a map[*sig.Alias]sig.StringAlias) (b map[*sig.Alias]sig.StringAlias, c map[*sig.Alias]sig.StringAlias)", 0)
101726-	sig.OtherAliasMap() //@signature(")", "OtherAliasMap(a map[sig.Alias]sig.OtherAlias, b map[sig.Alias]sig.OtherAlias) map[sig.Alias]sig.OtherAlias", 0)
101727-}
101728diff -urN a/gopls/internal/lsp/testdata/signature/signature_test.go.golden b/gopls/internal/lsp/testdata/signature/signature_test.go.golden
101729--- a/gopls/internal/lsp/testdata/signature/signature_test.go.golden	2000-01-01 00:00:00.000000000 -0000
101730+++ b/gopls/internal/lsp/testdata/signature/signature_test.go.golden	1970-01-01 00:00:00.000000000 +0000
101731@@ -1,9 +0,0 @@
101732--- AliasMap(a map[*sig.Alias]sig.StringAlias) (b map[*sig.Alias]sig.StringAlias, c map[*sig.Alias]sig.StringAlias)-signature --
101733-AliasMap(a map[*sig.Alias]sig.StringAlias) (b map[*sig.Alias]sig.StringAlias, c map[*sig.Alias]sig.StringAlias)
101734-
101735--- AliasSlice(a []*sig.Alias) (b sig.Alias)-signature --
101736-AliasSlice(a []*sig.Alias) (b sig.Alias)
101737-
101738--- OtherAliasMap(a map[sig.Alias]sig.OtherAlias, b map[sig.Alias]sig.OtherAlias) map[sig.Alias]sig.OtherAlias-signature --
101739-OtherAliasMap(a map[sig.Alias]sig.OtherAlias, b map[sig.Alias]sig.OtherAlias) map[sig.Alias]sig.OtherAlias
101740-
101741diff -urN a/gopls/internal/lsp/testdata/snippets/func_snippets118.go.in b/gopls/internal/lsp/testdata/snippets/func_snippets118.go.in
101742--- a/gopls/internal/lsp/testdata/snippets/func_snippets118.go.in	2000-01-01 00:00:00.000000000 -0000
101743+++ b/gopls/internal/lsp/testdata/snippets/func_snippets118.go.in	1970-01-01 00:00:00.000000000 +0000
101744@@ -1,19 +0,0 @@
101745-// +build go1.18
101746-//go:build go1.18
101747-
101748-package snippets
101749-
101750-type SyncMap[K comparable, V any] struct{}
101751-
101752-func NewSyncMap[K comparable, V any]() (result *SyncMap[K, V]) { //@item(NewSyncMap, "NewSyncMap", "", "")
101753-	return
101754-}
101755-
101756-func Identity[P ~int](p P) P { //@item(Identity, "Identity", "", "")
101757-	return p
101758-}
101759-
101760-func _() {
101761-	_ = NewSyncM //@snippet(" //", NewSyncMap, "NewSyncMap[${1:}]()", "NewSyncMap[${1:K comparable}, ${2:V any}]()")
101762-	_ = Identi //@snippet(" //", Identity, "Identity[${1:}](${2:})", "Identity[${1:P ~int}](${2:p P})")
101763-}
101764diff -urN a/gopls/internal/lsp/testdata/snippets/literal.go b/gopls/internal/lsp/testdata/snippets/literal.go
101765--- a/gopls/internal/lsp/testdata/snippets/literal.go	2000-01-01 00:00:00.000000000 -0000
101766+++ b/gopls/internal/lsp/testdata/snippets/literal.go	1970-01-01 00:00:00.000000000 +0000
101767@@ -1,22 +0,0 @@
101768-package snippets
101769-
101770-import (
101771-	"golang.org/lsptests/signature"
101772-	t "golang.org/lsptests/types"
101773-)
101774-
101775-type structy struct {
101776-	x signature.MyType
101777-}
101778-
101779-func X(_ map[signature.Alias]t.CoolAlias) (map[signature.Alias]t.CoolAlias) {
101780-	return nil
101781-}
101782-
101783-func _() {
101784-	X() //@signature(")", "X(_ map[signature.Alias]t.CoolAlias) map[signature.Alias]t.CoolAlias", 0)
101785-	_ = signature.MyType{} //@item(literalMyType, "signature.MyType{}", "", "var")
101786-	s := structy{
101787-		x: //@snippet(" //", literalMyType, "signature.MyType{\\}", "signature.MyType{\\}")
101788-	}
101789-}
101790\ No newline at end of file
101791diff -urN a/gopls/internal/lsp/testdata/snippets/literal.go.golden b/gopls/internal/lsp/testdata/snippets/literal.go.golden
101792--- a/gopls/internal/lsp/testdata/snippets/literal.go.golden	2000-01-01 00:00:00.000000000 -0000
101793+++ b/gopls/internal/lsp/testdata/snippets/literal.go.golden	1970-01-01 00:00:00.000000000 +0000
101794@@ -1,3 +0,0 @@
101795--- X(_ map[signature.Alias]t.CoolAlias) map[signature.Alias]t.CoolAlias-signature --
101796-X(_ map[signature.Alias]t.CoolAlias) map[signature.Alias]t.CoolAlias
101797-
101798diff -urN a/gopls/internal/lsp/testdata/snippets/literal_snippets118.go.in b/gopls/internal/lsp/testdata/snippets/literal_snippets118.go.in
101799--- a/gopls/internal/lsp/testdata/snippets/literal_snippets118.go.in	2000-01-01 00:00:00.000000000 -0000
101800+++ b/gopls/internal/lsp/testdata/snippets/literal_snippets118.go.in	1970-01-01 00:00:00.000000000 +0000
101801@@ -1,14 +0,0 @@
101802-// +build go1.18
101803-//go:build go1.18
101804-
101805-package snippets
101806-
101807-type Tree[T any] struct{}
101808-
101809-func (tree Tree[T]) Do(f func(s T)) {}
101810-
101811-func _() {
101812-    _ = "func(...) {}" //@item(litFunc, "func(...) {}", "", "var")
101813-	var t Tree[string]
101814-	t.Do(fun) //@complete(")", litFunc),snippet(")", litFunc, "func(s string) {$0\\}", "func(s string) {$0\\}")
101815-}
101816diff -urN a/gopls/internal/lsp/testdata/snippets/literal_snippets.go.in b/gopls/internal/lsp/testdata/snippets/literal_snippets.go.in
101817--- a/gopls/internal/lsp/testdata/snippets/literal_snippets.go.in	2000-01-01 00:00:00.000000000 -0000
101818+++ b/gopls/internal/lsp/testdata/snippets/literal_snippets.go.in	1970-01-01 00:00:00.000000000 +0000
101819@@ -1,233 +0,0 @@
101820-package snippets
101821-
101822-import (
101823-	"bytes"
101824-	"context"
101825-	"go/ast"
101826-	"net/http"
101827-	"sort"
101828-
101829-	"golang.org/lsptests/foo"
101830-)
101831-
101832-func _() {
101833-	[]int{}        //@item(litIntSlice, "[]int{}", "", "var")
101834-	&[]int{}       //@item(litIntSliceAddr, "&[]int{}", "", "var")
101835-	make([]int, 0) //@item(makeIntSlice, "make([]int, 0)", "", "func")
101836-
101837-	var _ *[]int = in //@snippet(" //", litIntSliceAddr, "&[]int{$0\\}", "&[]int{$0\\}")
101838-	var _ **[]int = in //@complete(" //")
101839-
101840-	var slice []int
101841-	slice = i //@snippet(" //", litIntSlice, "[]int{$0\\}", "[]int{$0\\}")
101842-	slice = m //@snippet(" //", makeIntSlice, "make([]int, ${1:})", "make([]int, ${1:0})")
101843-}
101844-
101845-func _() {
101846-	type namedInt []int
101847-
101848-	namedInt{}        //@item(litNamedSlice, "namedInt{}", "", "var")
101849-	make(namedInt, 0) //@item(makeNamedSlice, "make(namedInt, 0)", "", "func")
101850-
101851-	var namedSlice namedInt
101852-	namedSlice = n //@snippet(" //", litNamedSlice, "namedInt{$0\\}", "namedInt{$0\\}")
101853-	namedSlice = m //@snippet(" //", makeNamedSlice, "make(namedInt, ${1:})", "make(namedInt, ${1:0})")
101854-}
101855-
101856-func _() {
101857-	make(chan int) //@item(makeChan, "make(chan int)", "", "func")
101858-
101859-	var ch chan int
101860-	ch = m //@snippet(" //", makeChan, "make(chan int)", "make(chan int)")
101861-}
101862-
101863-func _() {
101864-	map[string]struct{}{}     //@item(litMap, "map[string]struct{}{}", "", "var")
101865-	make(map[string]struct{}) //@item(makeMap, "make(map[string]struct{})", "", "func")
101866-
101867-	var m map[string]struct{}
101868-	m = m //@snippet(" //", litMap, "map[string]struct{\\}{$0\\}", "map[string]struct{\\}{$0\\}")
101869-	m = m //@snippet(" //", makeMap, "make(map[string]struct{\\})", "make(map[string]struct{\\})")
101870-
101871-	struct{}{} //@item(litEmptyStruct, "struct{}{}", "", "var")
101872-
101873-	m["hi"] = s //@snippet(" //", litEmptyStruct, "struct{\\}{\\}", "struct{\\}{\\}")
101874-}
101875-
101876-func _() {
101877-	type myStruct struct{ i int } //@item(myStructType, "myStruct", "struct{...}", "struct")
101878-
101879-	myStruct{}  //@item(litStruct, "myStruct{}", "", "var")
101880-	&myStruct{} //@item(litStructPtr, "&myStruct{}", "", "var")
101881-
101882-	var ms myStruct
101883-	ms = m //@snippet(" //", litStruct, "myStruct{$0\\}", "myStruct{$0\\}")
101884-
101885-	var msPtr *myStruct
101886-	msPtr = m //@snippet(" //", litStructPtr, "&myStruct{$0\\}", "&myStruct{$0\\}")
101887-
101888-	msPtr = &m //@snippet(" //", litStruct, "myStruct{$0\\}", "myStruct{$0\\}")
101889-
101890-	type myStructCopy struct { i int } //@item(myStructCopyType, "myStructCopy", "struct{...}", "struct")
101891-
101892-	// Don't offer literal completion for convertible structs.
101893-	ms = myStruct //@complete(" //", litStruct, myStructType, myStructCopyType)
101894-}
101895-
101896-type myImpl struct{}
101897-
101898-func (myImpl) foo() {}
101899-
101900-func (*myImpl) bar() {}
101901-
101902-type myBasicImpl string
101903-
101904-func (myBasicImpl) foo() {}
101905-
101906-func _() {
101907-	type myIntf interface {
101908-		foo()
101909-	}
101910-
101911-	myImpl{} //@item(litImpl, "myImpl{}", "", "var")
101912-
101913-	var mi myIntf
101914-	mi = m //@snippet(" //", litImpl, "myImpl{\\}", "myImpl{\\}")
101915-
101916-	myBasicImpl() //@item(litBasicImpl, "myBasicImpl()", "string", "var")
101917-
101918-	mi = m //@snippet(" //", litBasicImpl, "myBasicImpl($0)", "myBasicImpl($0)")
101919-
101920-	// only satisfied by pointer to myImpl
101921-	type myPtrIntf interface {
101922-		bar()
101923-	}
101924-
101925-	&myImpl{} //@item(litImplPtr, "&myImpl{}", "", "var")
101926-
101927-	var mpi myPtrIntf
101928-	mpi = m //@snippet(" //", litImplPtr, "&myImpl{\\}", "&myImpl{\\}")
101929-}
101930-
101931-func _() {
101932-	var s struct{ i []int } //@item(litSliceField, "i", "[]int", "field")
101933-	var foo []int
101934-	// no literal completions after selector
101935-	foo = s.i //@complete(" //", litSliceField)
101936-}
101937-
101938-func _() {
101939-	type myStruct struct{ i int } //@item(litMyStructType, "myStruct", "struct{...}", "struct")
101940-	myStruct{} //@item(litMyStruct, "myStruct{}", "", "var")
101941-
101942-	foo := func(s string, args ...myStruct) {}
101943-	// Don't give literal slice candidate for variadic arg.
101944-	// Do give literal candidates for variadic element.
101945-	foo("", myStruct) //@complete(")", litMyStruct, litMyStructType)
101946-}
101947-
101948-func _() {
101949-	Buffer{} //@item(litBuffer, "Buffer{}", "", "var")
101950-
101951-	var b *bytes.Buffer
101952-	b = bytes.Bu //@snippet(" //", litBuffer, "Buffer{\\}", "Buffer{\\}")
101953-}
101954-
101955-func _() {
101956-	_ = "func(...) {}" //@item(litFunc, "func(...) {}", "", "var")
101957-
101958-	sort.Slice(nil, fun) //@complete(")", litFunc),snippet(")", litFunc, "func(i, j int) bool {$0\\}", "func(i, j int) bool {$0\\}")
101959-
101960-	http.HandleFunc("", f) //@snippet(")", litFunc, "func(w http.ResponseWriter, r *http.Request) {$0\\}", "func(${1:w} http.ResponseWriter, ${2:r} *http.Request) {$0\\}")
101961-
101962-	// no literal "func" completions
101963-	http.Handle("", fun) //@complete(")")
101964-
101965-	http.HandlerFunc() //@item(handlerFunc, "http.HandlerFunc()", "", "var")
101966-	http.Handle("", h) //@snippet(")", handlerFunc, "http.HandlerFunc($0)", "http.HandlerFunc($0)")
101967-	http.Handle("", http.HandlerFunc()) //@snippet("))", litFunc, "func(w http.ResponseWriter, r *http.Request) {$0\\}", "func(${1:w} http.ResponseWriter, ${2:r} *http.Request) {$0\\}")
101968-
101969-	var namedReturn func(s string) (b bool)
101970-	namedReturn = f //@snippet(" //", litFunc, "func(s string) (b bool) {$0\\}", "func(s string) (b bool) {$0\\}")
101971-
101972-	var multiReturn func() (bool, int)
101973-	multiReturn = f //@snippet(" //", litFunc, "func() (bool, int) {$0\\}", "func() (bool, int) {$0\\}")
101974-
101975-	var multiNamedReturn func() (b bool, i int)
101976-	multiNamedReturn = f //@snippet(" //", litFunc, "func() (b bool, i int) {$0\\}", "func() (b bool, i int) {$0\\}")
101977-
101978-	var duplicateParams func(myImpl, int, myImpl)
101979-	duplicateParams = f //@snippet(" //", litFunc, "func(mi1 myImpl, i int, mi2 myImpl) {$0\\}", "func(${1:mi1} myImpl, ${2:i} int, ${3:mi2} myImpl) {$0\\}")
101980-
101981-	type aliasImpl = myImpl
101982-	var aliasParams func(aliasImpl) aliasImpl
101983-	aliasParams = f //@snippet(" //", litFunc, "func(ai aliasImpl) aliasImpl {$0\\}", "func(${1:ai} aliasImpl) aliasImpl {$0\\}")
101984-
101985-	const two = 2
101986-	var builtinTypes func([]int, [two]bool, map[string]string, struct{ i int }, interface{ foo() }, <-chan int)
101987-	builtinTypes = f //@snippet(" //", litFunc, "func(i1 []int, b [two]bool, m map[string]string, s struct{ i int \\}, i2 interface{ foo() \\}, c <-chan int) {$0\\}", "func(${1:i1} []int, ${2:b} [two]bool, ${3:m} map[string]string, ${4:s} struct{ i int \\}, ${5:i2} interface{ foo() \\}, ${6:c} <-chan int) {$0\\}")
101988-
101989-	var _ func(ast.Node) = f //@snippet(" //", litFunc, "func(n ast.Node) {$0\\}", "func(${1:n} ast.Node) {$0\\}")
101990-	var _ func(error) = f //@snippet(" //", litFunc, "func(err error) {$0\\}", "func(${1:err} error) {$0\\}")
101991-	var _ func(context.Context) = f //@snippet(" //", litFunc, "func(ctx context.Context) {$0\\}", "func(${1:ctx} context.Context) {$0\\}")
101992-
101993-	type context struct {}
101994-	var _ func(context) = f //@snippet(" //", litFunc, "func(ctx context) {$0\\}", "func(${1:ctx} context) {$0\\}")
101995-}
101996-
101997-func _() {
101998-	StructFoo{} //@item(litStructFoo, "StructFoo{}", "struct{...}", "struct")
101999-
102000-	var sfp *foo.StructFoo
102001-	// Don't insert the "&" before "StructFoo{}".
102002-	sfp = foo.Str //@snippet(" //", litStructFoo, "StructFoo{$0\\}", "StructFoo{$0\\}")
102003-
102004-	var sf foo.StructFoo
102005-	sf = foo.Str //@snippet(" //", litStructFoo, "StructFoo{$0\\}", "StructFoo{$0\\}")
102006-	sf = foo. //@snippet(" //", litStructFoo, "StructFoo{$0\\}", "StructFoo{$0\\}")
102007-}
102008-
102009-func _() {
102010-	float64() //@item(litFloat64, "float64()", "float64", "var")
102011-
102012-	// don't complete to "&float64()"
102013-	var _ *float64 = float64 //@complete(" //")
102014-
102015-	var f float64
102016-	f = fl //@complete(" //", litFloat64),snippet(" //", litFloat64, "float64($0)", "float64($0)")
102017-
102018-	type myInt int
102019-	myInt() //@item(litMyInt, "myInt()", "", "var")
102020-
102021-	var mi myInt
102022-	mi = my //@snippet(" //", litMyInt, "myInt($0)", "myInt($0)")
102023-}
102024-
102025-func _() {
102026-	type ptrStruct struct {
102027-		p *ptrStruct
102028-	}
102029-
102030-	ptrStruct{} //@item(litPtrStruct, "ptrStruct{}", "", "var")
102031-
102032-	ptrStruct{
102033-		p: &ptrSt, //@rank(",", litPtrStruct)
102034-	}
102035-
102036-	&ptrStruct{} //@item(litPtrStructPtr, "&ptrStruct{}", "", "var")
102037-
102038-	&ptrStruct{
102039-		p: ptrSt, //@rank(",", litPtrStructPtr)
102040-	}
102041-}
102042-
102043-func _() {
102044-	f := func(...[]int) {}
102045-	f() //@snippet(")", litIntSlice, "[]int{$0\\}", "[]int{$0\\}")
102046-}
102047-
102048-
102049-func _() {
102050-	// don't complete to "untyped int()"
102051-	[]int{}[untyped] //@complete("] //")
102052-}
102053diff -urN a/gopls/internal/lsp/testdata/snippets/postfix.go b/gopls/internal/lsp/testdata/snippets/postfix.go
102054--- a/gopls/internal/lsp/testdata/snippets/postfix.go	2000-01-01 00:00:00.000000000 -0000
102055+++ b/gopls/internal/lsp/testdata/snippets/postfix.go	1970-01-01 00:00:00.000000000 +0000
102056@@ -1,42 +0,0 @@
102057-package snippets
102058-
102059-// These tests check that postfix completions do and do not show up in
102060-// certain cases. Tests for the postfix completion contents are under
102061-// regtest.
102062-
102063-func _() {
102064-	/* append! */ //@item(postfixAppend, "append!", "append and re-assign slice", "snippet")
102065-	var foo []int
102066-	foo.append //@rank(" //", postfixAppend)
102067-
102068-	[]int{}.append //@complete(" //")
102069-
102070-	[]int{}.last //@complete(" //")
102071-
102072-	/* copy! */ //@item(postfixCopy, "copy!", "duplicate slice", "snippet")
102073-
102074-	foo.copy //@rank(" //", postfixCopy)
102075-
102076-	var s struct{ i []int }
102077-	s.i.copy //@rank(" //", postfixCopy)
102078-
102079-	var _ []int = s.i.copy //@complete(" //")
102080-
102081-	var blah func() []int
102082-	blah().append //@complete(" //")
102083-}
102084-
102085-func _() {
102086-	/* append! */ //@item(postfixAppend, "append!", "append and re-assign slice", "snippet")
102087-	/* last! */ //@item(postfixLast, "last!", "s[len(s)-1]", "snippet")
102088-	/* print! */ //@item(postfixPrint, "print!", "print to stdout", "snippet")
102089-	/* range! */ //@item(postfixRange, "range!", "range over slice", "snippet")
102090-	/* reverse! */ //@item(postfixReverse, "reverse!", "reverse slice", "snippet")
102091-	/* sort! */ //@item(postfixSort, "sort!", "sort.Slice()", "snippet")
102092-	/* var! */ //@item(postfixVar, "var!", "assign to variable", "snippet")
102093-
102094-	var foo []int
102095-	foo. //@complete(" //", postfixAppend, postfixCopy, postfixLast, postfixPrint, postfixRange, postfixReverse, postfixSort, postfixVar)
102096-
102097-		foo = nil
102098-}
102099diff -urN a/gopls/internal/lsp/testdata/snippets/snippets.go.golden b/gopls/internal/lsp/testdata/snippets/snippets.go.golden
102100--- a/gopls/internal/lsp/testdata/snippets/snippets.go.golden	2000-01-01 00:00:00.000000000 -0000
102101+++ b/gopls/internal/lsp/testdata/snippets/snippets.go.golden	1970-01-01 00:00:00.000000000 +0000
102102@@ -1,3 +0,0 @@
102103--- baz(at AliasType, b bool)-signature --
102104-baz(at AliasType, b bool)
102105-
102106diff -urN a/gopls/internal/lsp/testdata/snippets/snippets.go.in b/gopls/internal/lsp/testdata/snippets/snippets.go.in
102107--- a/gopls/internal/lsp/testdata/snippets/snippets.go.in	2000-01-01 00:00:00.000000000 -0000
102108+++ b/gopls/internal/lsp/testdata/snippets/snippets.go.in	1970-01-01 00:00:00.000000000 +0000
102109@@ -1,61 +0,0 @@
102110-package snippets
102111-
102112-type AliasType = int //@item(sigAliasType, "AliasType", "AliasType", "type")
102113-
102114-func foo(i int, b bool) {} //@item(snipFoo, "foo", "func(i int, b bool)", "func")
102115-func bar(fn func()) func()    {} //@item(snipBar, "bar", "func(fn func())", "func")
102116-func baz(at AliasType, b bool) {} //@item(snipBaz, "baz", "func(at AliasType, b bool)", "func")
102117-
102118-type Foo struct {
102119-	Bar int //@item(snipFieldBar, "Bar", "int", "field")
102120-	Func func(at AliasType) error //@item(snipFieldFunc, "Func", "func(at AliasType) error", "field")
102121-}
102122-
102123-func (Foo) Baz() func() {} //@item(snipMethodBaz, "Baz", "func() func()", "method")
102124-func (Foo) BazBar() func() {} //@item(snipMethodBazBar, "BazBar", "func() func()", "method")
102125-func (Foo) BazBaz(at AliasType) func() {} //@item(snipMethodBazBaz, "BazBaz", "func(at AliasType) func()", "method")
102126-
102127-func _() {
102128-	f //@snippet(" //", snipFoo, "foo(${1:})", "foo(${1:i int}, ${2:b bool})")
102129-
102130-	bar //@snippet(" //", snipBar, "bar(${1:})", "bar(${1:fn func()})")
102131-
102132-	baz //@snippet(" //", snipBaz, "baz(${1:})", "baz(${1:at AliasType}, ${2:b bool})")
102133-	baz() //@signature("(", "baz(at AliasType, b bool)", 0)
102134-
102135-	bar(nil) //@snippet("(", snipBar, "bar", "bar")
102136-	bar(ba) //@snippet(")", snipBar, "bar(${1:})", "bar(${1:fn func()})")
102137-	var f Foo
102138-	bar(f.Ba) //@snippet(")", snipMethodBaz, "Baz()", "Baz()")
102139-	(bar)(nil) //@snippet(")", snipBar, "bar(${1:})", "bar(${1:fn func()})")
102140-	(f.Ba)() //@snippet(")", snipMethodBaz, "Baz()", "Baz()")
102141-
102142-	Foo{
102143-		B //@snippet(" //", snipFieldBar, "Bar: ${1:},", "Bar: ${1:int},")
102144-	}
102145-
102146-	Foo{
102147-		F //@snippet(" //", snipFieldFunc, "Func: ${1:},", "Func: ${1:func(at AliasType) error},")
102148-	}
102149-
102150-	Foo{B} //@snippet("}", snipFieldBar, "Bar: ${1:}", "Bar: ${1:int}")
102151-	Foo{} //@snippet("}", snipFieldBar, "Bar: ${1:}", "Bar: ${1:int}")
102152-
102153-	Foo{Foo{}.B} //@snippet("} ", snipFieldBar, "Bar", "Bar")
102154-
102155-	var err error
102156-	err.Error() //@snippet("E", Error, "Error()", "Error()")
102157-	f.Baz()     //@snippet("B", snipMethodBaz, "Baz()", "Baz()")
102158-
102159-	f.Baz()     //@snippet("(", snipMethodBazBar, "BazBar", "BazBar")
102160-
102161-	f.Baz()     //@snippet("B", snipMethodBazBaz, "BazBaz(${1:})", "BazBaz(${1:at AliasType})")
102162-}
102163-
102164-func _() {
102165-	type bar struct {
102166-		a int
102167-		b float64 //@item(snipBarB, "b", "float64", "field")
102168-	}
102169-	bar{b} //@snippet("}", snipBarB, "b: ${1:}", "b: ${1:float64}")
102170-}
102171diff -urN a/gopls/internal/lsp/testdata/statements/append.go b/gopls/internal/lsp/testdata/statements/append.go
102172--- a/gopls/internal/lsp/testdata/statements/append.go	2000-01-01 00:00:00.000000000 -0000
102173+++ b/gopls/internal/lsp/testdata/statements/append.go	1970-01-01 00:00:00.000000000 +0000
102174@@ -1,42 +0,0 @@
102175-package statements
102176-
102177-func _() {
102178-	type mySlice []int
102179-
102180-	var (
102181-		abc    []int   //@item(stmtABC, "abc", "[]int", "var")
102182-		abcdef mySlice //@item(stmtABCDEF, "abcdef", "mySlice", "var")
102183-	)
102184-
102185-	/* abcdef = append(abcdef, ) */ //@item(stmtABCDEFAssignAppend, "abcdef = append(abcdef, )", "", "func")
102186-
102187-	// don't offer "abc = append(abc, )" because "abc" isn't necessarily
102188-	// better than "abcdef".
102189-	abc //@complete(" //", stmtABC, stmtABCDEF)
102190-
102191-	abcdef //@complete(" //", stmtABCDEF, stmtABCDEFAssignAppend)
102192-
102193-	/* append(abc, ) */ //@item(stmtABCAppend, "append(abc, )", "", "func")
102194-
102195-	abc = app //@snippet(" //", stmtABCAppend, "append(abc, ${1:})", "append(abc, ${1:})")
102196-}
102197-
102198-func _() {
102199-	var s struct{ xyz []int }
102200-
102201-	/* xyz = append(s.xyz, ) */ //@item(stmtXYZAppend, "xyz = append(s.xyz, )", "", "func")
102202-
102203-	s.x //@snippet(" //", stmtXYZAppend, "xyz = append(s.xyz, ${1:})", "xyz = append(s.xyz, ${1:})")
102204-
102205-	/* s.xyz = append(s.xyz, ) */ //@item(stmtDeepXYZAppend, "s.xyz = append(s.xyz, )", "", "func")
102206-
102207-	sx //@snippet(" //", stmtDeepXYZAppend, "s.xyz = append(s.xyz, ${1:})", "s.xyz = append(s.xyz, ${1:})")
102208-}
102209-
102210-func _() {
102211-	var foo [][]int
102212-
102213-	/* append(foo[0], ) */ //@item(stmtFooAppend, "append(foo[0], )", "", "func")
102214-
102215-	foo[0] = app //@complete(" //"),snippet(" //", stmtFooAppend, "append(foo[0], ${1:})", "append(foo[0], ${1:})")
102216-}
102217diff -urN a/gopls/internal/lsp/testdata/statements/if_err_check_return_2.go b/gopls/internal/lsp/testdata/statements/if_err_check_return_2.go
102218--- a/gopls/internal/lsp/testdata/statements/if_err_check_return_2.go	2000-01-01 00:00:00.000000000 -0000
102219+++ b/gopls/internal/lsp/testdata/statements/if_err_check_return_2.go	1970-01-01 00:00:00.000000000 +0000
102220@@ -1,12 +0,0 @@
102221-package statements
102222-
102223-import "os"
102224-
102225-func two() error {
102226-	var s struct{ err error }
102227-
102228-	/* if s.err != nil { return s.err } */ //@item(stmtTwoIfErrReturn, "if s.err != nil { return s.err }", "", "")
102229-
102230-	_, s.err = os.Open("foo")
102231-	//@snippet("", stmtTwoIfErrReturn, "", "if s.err != nil {\n\treturn ${1:s.err}\n\\}")
102232-}
102233diff -urN a/gopls/internal/lsp/testdata/statements/if_err_check_return.go b/gopls/internal/lsp/testdata/statements/if_err_check_return.go
102234--- a/gopls/internal/lsp/testdata/statements/if_err_check_return.go	2000-01-01 00:00:00.000000000 -0000
102235+++ b/gopls/internal/lsp/testdata/statements/if_err_check_return.go	1970-01-01 00:00:00.000000000 +0000
102236@@ -1,27 +0,0 @@
102237-package statements
102238-
102239-import (
102240-	"bytes"
102241-	"io"
102242-	"os"
102243-)
102244-
102245-func one() (int, float32, io.Writer, *int, []int, bytes.Buffer, error) {
102246-	/* if err != nil { return err } */ //@item(stmtOneIfErrReturn, "if err != nil { return err }", "", "")
102247-	/* err != nil { return err } */ //@item(stmtOneErrReturn, "err != nil { return err }", "", "")
102248-
102249-	_, err := os.Open("foo")
102250-	//@snippet("", stmtOneIfErrReturn, "", "if err != nil {\n\treturn 0, 0, nil, nil, nil, bytes.Buffer{\\}, ${1:err}\n\\}")
102251-
102252-	_, err = os.Open("foo")
102253-	i //@snippet(" //", stmtOneIfErrReturn, "", "if err != nil {\n\treturn 0, 0, nil, nil, nil, bytes.Buffer{\\}, ${1:err}\n\\}")
102254-
102255-	_, err = os.Open("foo")
102256-	if er //@snippet(" //", stmtOneErrReturn, "", "err != nil {\n\treturn 0, 0, nil, nil, nil, bytes.Buffer{\\}, ${1:err}\n\\}")
102257-
102258-	_, err = os.Open("foo")
102259-	if //@snippet(" //", stmtOneIfErrReturn, "", "if err != nil {\n\treturn 0, 0, nil, nil, nil, bytes.Buffer{\\}, ${1:err}\n\\}")
102260-
102261-	_, err = os.Open("foo")
102262-	if //@snippet("//", stmtOneIfErrReturn, "", "if err != nil {\n\treturn 0, 0, nil, nil, nil, bytes.Buffer{\\}, ${1:err}\n\\}")
102263-}
102264diff -urN a/gopls/internal/lsp/testdata/statements/if_err_check_test.go b/gopls/internal/lsp/testdata/statements/if_err_check_test.go
102265--- a/gopls/internal/lsp/testdata/statements/if_err_check_test.go	2000-01-01 00:00:00.000000000 -0000
102266+++ b/gopls/internal/lsp/testdata/statements/if_err_check_test.go	1970-01-01 00:00:00.000000000 +0000
102267@@ -1,20 +0,0 @@
102268-package statements
102269-
102270-import (
102271-	"os"
102272-	"testing"
102273-)
102274-
102275-func TestErr(t *testing.T) {
102276-	/* if err != nil { t.Fatal(err) } */ //@item(stmtOneIfErrTFatal, "if err != nil { t.Fatal(err) }", "", "")
102277-
102278-	_, err := os.Open("foo")
102279-	//@snippet("", stmtOneIfErrTFatal, "", "if err != nil {\n\tt.Fatal(err)\n\\}")
102280-}
102281-
102282-func BenchmarkErr(b *testing.B) {
102283-	/* if err != nil { b.Fatal(err) } */ //@item(stmtOneIfErrBFatal, "if err != nil { b.Fatal(err) }", "", "")
102284-
102285-	_, err := os.Open("foo")
102286-	//@snippet("", stmtOneIfErrBFatal, "", "if err != nil {\n\tb.Fatal(err)\n\\}")
102287-}
102288diff -urN a/gopls/internal/lsp/testdata/stub/other/other.go b/gopls/internal/lsp/testdata/stub/other/other.go
102289--- a/gopls/internal/lsp/testdata/stub/other/other.go	2000-01-01 00:00:00.000000000 -0000
102290+++ b/gopls/internal/lsp/testdata/stub/other/other.go	1970-01-01 00:00:00.000000000 +0000
102291@@ -1,10 +0,0 @@
102292-package other
102293-
102294-import (
102295-	"bytes"
102296-	renamed_context "context"
102297-)
102298-
102299-type Interface interface {
102300-	Get(renamed_context.Context) *bytes.Buffer
102301-}
102302diff -urN a/gopls/internal/lsp/testdata/stub/stub_add_selector.go b/gopls/internal/lsp/testdata/stub/stub_add_selector.go
102303--- a/gopls/internal/lsp/testdata/stub/stub_add_selector.go	2000-01-01 00:00:00.000000000 -0000
102304+++ b/gopls/internal/lsp/testdata/stub/stub_add_selector.go	1970-01-01 00:00:00.000000000 +0000
102305@@ -1,12 +0,0 @@
102306-package stub
102307-
102308-import "io"
102309-
102310-// This file tests that if an interface
102311-// method references a type from its own package
102312-// then our implementation must add the import/package selector
102313-// in the concrete method if the concrete type is outside of the interface
102314-// package
102315-var _ io.ReaderFrom = &readerFrom{} //@suggestedfix("&readerFrom", "refactor.rewrite", "")
102316-
102317-type readerFrom struct{}
102318diff -urN a/gopls/internal/lsp/testdata/stub/stub_add_selector.go.golden b/gopls/internal/lsp/testdata/stub/stub_add_selector.go.golden
102319--- a/gopls/internal/lsp/testdata/stub/stub_add_selector.go.golden	2000-01-01 00:00:00.000000000 -0000
102320+++ b/gopls/internal/lsp/testdata/stub/stub_add_selector.go.golden	1970-01-01 00:00:00.000000000 +0000
102321@@ -1,19 +0,0 @@
102322--- suggestedfix_stub_add_selector_10_23 --
102323-package stub
102324-
102325-import "io"
102326-
102327-// This file tests that if an interface
102328-// method references a type from its own package
102329-// then our implementation must add the import/package selector
102330-// in the concrete method if the concrete type is outside of the interface
102331-// package
102332-var _ io.ReaderFrom = &readerFrom{} //@suggestedfix("&readerFrom", "refactor.rewrite", "")
102333-
102334-type readerFrom struct{}
102335-
102336-// ReadFrom implements io.ReaderFrom
102337-func (*readerFrom) ReadFrom(r io.Reader) (n int64, err error) {
102338-	panic("unimplemented")
102339-}
102340-
102341diff -urN a/gopls/internal/lsp/testdata/stub/stub_assign.go b/gopls/internal/lsp/testdata/stub/stub_assign.go
102342--- a/gopls/internal/lsp/testdata/stub/stub_assign.go	2000-01-01 00:00:00.000000000 -0000
102343+++ b/gopls/internal/lsp/testdata/stub/stub_assign.go	1970-01-01 00:00:00.000000000 +0000
102344@@ -1,10 +0,0 @@
102345-package stub
102346-
102347-import "io"
102348-
102349-func main() {
102350-	var br io.ByteWriter
102351-	br = &byteWriter{} //@suggestedfix("&", "refactor.rewrite", "")
102352-}
102353-
102354-type byteWriter struct{}
102355diff -urN a/gopls/internal/lsp/testdata/stub/stub_assign.go.golden b/gopls/internal/lsp/testdata/stub/stub_assign.go.golden
102356--- a/gopls/internal/lsp/testdata/stub/stub_assign.go.golden	2000-01-01 00:00:00.000000000 -0000
102357+++ b/gopls/internal/lsp/testdata/stub/stub_assign.go.golden	1970-01-01 00:00:00.000000000 +0000
102358@@ -1,17 +0,0 @@
102359--- suggestedfix_stub_assign_7_7 --
102360-package stub
102361-
102362-import "io"
102363-
102364-func main() {
102365-	var br io.ByteWriter
102366-	br = &byteWriter{} //@suggestedfix("&", "refactor.rewrite", "")
102367-}
102368-
102369-type byteWriter struct{}
102370-
102371-// WriteByte implements io.ByteWriter
102372-func (*byteWriter) WriteByte(c byte) error {
102373-	panic("unimplemented")
102374-}
102375-
102376diff -urN a/gopls/internal/lsp/testdata/stub/stub_assign_multivars.go b/gopls/internal/lsp/testdata/stub/stub_assign_multivars.go
102377--- a/gopls/internal/lsp/testdata/stub/stub_assign_multivars.go	2000-01-01 00:00:00.000000000 -0000
102378+++ b/gopls/internal/lsp/testdata/stub/stub_assign_multivars.go	1970-01-01 00:00:00.000000000 +0000
102379@@ -1,11 +0,0 @@
102380-package stub
102381-
102382-import "io"
102383-
102384-func main() {
102385-	var br io.ByteWriter
102386-	var i int
102387-	i, br = 1, &multiByteWriter{} //@suggestedfix("&", "refactor.rewrite", "")
102388-}
102389-
102390-type multiByteWriter struct{}
102391diff -urN a/gopls/internal/lsp/testdata/stub/stub_assign_multivars.go.golden b/gopls/internal/lsp/testdata/stub/stub_assign_multivars.go.golden
102392--- a/gopls/internal/lsp/testdata/stub/stub_assign_multivars.go.golden	2000-01-01 00:00:00.000000000 -0000
102393+++ b/gopls/internal/lsp/testdata/stub/stub_assign_multivars.go.golden	1970-01-01 00:00:00.000000000 +0000
102394@@ -1,18 +0,0 @@
102395--- suggestedfix_stub_assign_multivars_8_13 --
102396-package stub
102397-
102398-import "io"
102399-
102400-func main() {
102401-	var br io.ByteWriter
102402-	var i int
102403-	i, br = 1, &multiByteWriter{} //@suggestedfix("&", "refactor.rewrite", "")
102404-}
102405-
102406-type multiByteWriter struct{}
102407-
102408-// WriteByte implements io.ByteWriter
102409-func (*multiByteWriter) WriteByte(c byte) error {
102410-	panic("unimplemented")
102411-}
102412-
102413diff -urN a/gopls/internal/lsp/testdata/stub/stub_call_expr.go b/gopls/internal/lsp/testdata/stub/stub_call_expr.go
102414--- a/gopls/internal/lsp/testdata/stub/stub_call_expr.go	2000-01-01 00:00:00.000000000 -0000
102415+++ b/gopls/internal/lsp/testdata/stub/stub_call_expr.go	1970-01-01 00:00:00.000000000 +0000
102416@@ -1,13 +0,0 @@
102417-package stub
102418-
102419-func main() {
102420-	check(&callExpr{}) //@suggestedfix("&", "refactor.rewrite", "")
102421-}
102422-
102423-func check(err error) {
102424-	if err != nil {
102425-		panic(err)
102426-	}
102427-}
102428-
102429-type callExpr struct{}
102430diff -urN a/gopls/internal/lsp/testdata/stub/stub_call_expr.go.golden b/gopls/internal/lsp/testdata/stub/stub_call_expr.go.golden
102431--- a/gopls/internal/lsp/testdata/stub/stub_call_expr.go.golden	2000-01-01 00:00:00.000000000 -0000
102432+++ b/gopls/internal/lsp/testdata/stub/stub_call_expr.go.golden	1970-01-01 00:00:00.000000000 +0000
102433@@ -1,20 +0,0 @@
102434--- suggestedfix_stub_call_expr_4_8 --
102435-package stub
102436-
102437-func main() {
102438-	check(&callExpr{}) //@suggestedfix("&", "refactor.rewrite", "")
102439-}
102440-
102441-func check(err error) {
102442-	if err != nil {
102443-		panic(err)
102444-	}
102445-}
102446-
102447-type callExpr struct{}
102448-
102449-// Error implements error
102450-func (*callExpr) Error() string {
102451-	panic("unimplemented")
102452-}
102453-
102454diff -urN a/gopls/internal/lsp/testdata/stub/stub_embedded.go b/gopls/internal/lsp/testdata/stub/stub_embedded.go
102455--- a/gopls/internal/lsp/testdata/stub/stub_embedded.go	2000-01-01 00:00:00.000000000 -0000
102456+++ b/gopls/internal/lsp/testdata/stub/stub_embedded.go	1970-01-01 00:00:00.000000000 +0000
102457@@ -1,15 +0,0 @@
102458-package stub
102459-
102460-import (
102461-	"io"
102462-	"sort"
102463-)
102464-
102465-var _ embeddedInterface = (*embeddedConcrete)(nil) //@suggestedfix("(", "refactor.rewrite", "")
102466-
102467-type embeddedConcrete struct{}
102468-
102469-type embeddedInterface interface {
102470-	sort.Interface
102471-	io.Reader
102472-}
102473diff -urN a/gopls/internal/lsp/testdata/stub/stub_embedded.go.golden b/gopls/internal/lsp/testdata/stub/stub_embedded.go.golden
102474--- a/gopls/internal/lsp/testdata/stub/stub_embedded.go.golden	2000-01-01 00:00:00.000000000 -0000
102475+++ b/gopls/internal/lsp/testdata/stub/stub_embedded.go.golden	1970-01-01 00:00:00.000000000 +0000
102476@@ -1,37 +0,0 @@
102477--- suggestedfix_stub_embedded_8_27 --
102478-package stub
102479-
102480-import (
102481-	"io"
102482-	"sort"
102483-)
102484-
102485-var _ embeddedInterface = (*embeddedConcrete)(nil) //@suggestedfix("(", "refactor.rewrite", "")
102486-
102487-type embeddedConcrete struct{}
102488-
102489-// Len implements embeddedInterface
102490-func (*embeddedConcrete) Len() int {
102491-	panic("unimplemented")
102492-}
102493-
102494-// Less implements embeddedInterface
102495-func (*embeddedConcrete) Less(i int, j int) bool {
102496-	panic("unimplemented")
102497-}
102498-
102499-// Read implements embeddedInterface
102500-func (*embeddedConcrete) Read(p []byte) (n int, err error) {
102501-	panic("unimplemented")
102502-}
102503-
102504-// Swap implements embeddedInterface
102505-func (*embeddedConcrete) Swap(i int, j int) {
102506-	panic("unimplemented")
102507-}
102508-
102509-type embeddedInterface interface {
102510-	sort.Interface
102511-	io.Reader
102512-}
102513-
102514diff -urN a/gopls/internal/lsp/testdata/stub/stub_err.go b/gopls/internal/lsp/testdata/stub/stub_err.go
102515--- a/gopls/internal/lsp/testdata/stub/stub_err.go	2000-01-01 00:00:00.000000000 -0000
102516+++ b/gopls/internal/lsp/testdata/stub/stub_err.go	1970-01-01 00:00:00.000000000 +0000
102517@@ -1,7 +0,0 @@
102518-package stub
102519-
102520-func main() {
102521-	var br error = &customErr{} //@suggestedfix("&", "refactor.rewrite", "")
102522-}
102523-
102524-type customErr struct{}
102525diff -urN a/gopls/internal/lsp/testdata/stub/stub_err.go.golden b/gopls/internal/lsp/testdata/stub/stub_err.go.golden
102526--- a/gopls/internal/lsp/testdata/stub/stub_err.go.golden	2000-01-01 00:00:00.000000000 -0000
102527+++ b/gopls/internal/lsp/testdata/stub/stub_err.go.golden	1970-01-01 00:00:00.000000000 +0000
102528@@ -1,14 +0,0 @@
102529--- suggestedfix_stub_err_4_17 --
102530-package stub
102531-
102532-func main() {
102533-	var br error = &customErr{} //@suggestedfix("&", "refactor.rewrite", "")
102534-}
102535-
102536-type customErr struct{}
102537-
102538-// Error implements error
102539-func (*customErr) Error() string {
102540-	panic("unimplemented")
102541-}
102542-
102543diff -urN a/gopls/internal/lsp/testdata/stub/stub_function_return.go b/gopls/internal/lsp/testdata/stub/stub_function_return.go
102544--- a/gopls/internal/lsp/testdata/stub/stub_function_return.go	2000-01-01 00:00:00.000000000 -0000
102545+++ b/gopls/internal/lsp/testdata/stub/stub_function_return.go	1970-01-01 00:00:00.000000000 +0000
102546@@ -1,11 +0,0 @@
102547-package stub
102548-
102549-import (
102550-	"io"
102551-)
102552-
102553-func newCloser() io.Closer {
102554-	return closer{} //@suggestedfix("c", "refactor.rewrite", "")
102555-}
102556-
102557-type closer struct{}
102558diff -urN a/gopls/internal/lsp/testdata/stub/stub_function_return.go.golden b/gopls/internal/lsp/testdata/stub/stub_function_return.go.golden
102559--- a/gopls/internal/lsp/testdata/stub/stub_function_return.go.golden	2000-01-01 00:00:00.000000000 -0000
102560+++ b/gopls/internal/lsp/testdata/stub/stub_function_return.go.golden	1970-01-01 00:00:00.000000000 +0000
102561@@ -1,18 +0,0 @@
102562--- suggestedfix_stub_function_return_8_9 --
102563-package stub
102564-
102565-import (
102566-	"io"
102567-)
102568-
102569-func newCloser() io.Closer {
102570-	return closer{} //@suggestedfix("c", "refactor.rewrite", "")
102571-}
102572-
102573-type closer struct{}
102574-
102575-// Close implements io.Closer
102576-func (closer) Close() error {
102577-	panic("unimplemented")
102578-}
102579-
102580diff -urN a/gopls/internal/lsp/testdata/stub/stub_generic_receiver.go b/gopls/internal/lsp/testdata/stub/stub_generic_receiver.go
102581--- a/gopls/internal/lsp/testdata/stub/stub_generic_receiver.go	2000-01-01 00:00:00.000000000 -0000
102582+++ b/gopls/internal/lsp/testdata/stub/stub_generic_receiver.go	1970-01-01 00:00:00.000000000 +0000
102583@@ -1,15 +0,0 @@
102584-//go:build go1.18
102585-// +build go1.18
102586-
102587-package stub
102588-
102589-import "io"
102590-
102591-// This file tests that that the stub method generator accounts for concrete
102592-// types that have type parameters defined.
102593-var _ io.ReaderFrom = &genReader[string, int]{} //@suggestedfix("&genReader", "refactor.rewrite", "Implement io.ReaderFrom")
102594-
102595-type genReader[T, Y any] struct {
102596-	T T
102597-	Y Y
102598-}
102599diff -urN a/gopls/internal/lsp/testdata/stub/stub_generic_receiver.go.golden b/gopls/internal/lsp/testdata/stub/stub_generic_receiver.go.golden
102600--- a/gopls/internal/lsp/testdata/stub/stub_generic_receiver.go.golden	2000-01-01 00:00:00.000000000 -0000
102601+++ b/gopls/internal/lsp/testdata/stub/stub_generic_receiver.go.golden	1970-01-01 00:00:00.000000000 +0000
102602@@ -1,22 +0,0 @@
102603--- suggestedfix_stub_generic_receiver_10_23 --
102604-//go:build go1.18
102605-// +build go1.18
102606-
102607-package stub
102608-
102609-import "io"
102610-
102611-// This file tests that that the stub method generator accounts for concrete
102612-// types that have type parameters defined.
102613-var _ io.ReaderFrom = &genReader[string, int]{} //@suggestedfix("&genReader", "refactor.rewrite", "Implement io.ReaderFrom")
102614-
102615-type genReader[T, Y any] struct {
102616-	T T
102617-	Y Y
102618-}
102619-
102620-// ReadFrom implements io.ReaderFrom
102621-func (*genReader[T, Y]) ReadFrom(r io.Reader) (n int64, err error) {
102622-	panic("unimplemented")
102623-}
102624-
102625diff -urN a/gopls/internal/lsp/testdata/stub/stub_ignored_imports.go b/gopls/internal/lsp/testdata/stub/stub_ignored_imports.go
102626--- a/gopls/internal/lsp/testdata/stub/stub_ignored_imports.go	2000-01-01 00:00:00.000000000 -0000
102627+++ b/gopls/internal/lsp/testdata/stub/stub_ignored_imports.go	1970-01-01 00:00:00.000000000 +0000
102628@@ -1,18 +0,0 @@
102629-package stub
102630-
102631-import (
102632-	"compress/zlib"
102633-	. "io"
102634-	_ "io"
102635-)
102636-
102637-// This file tests that dot-imports and underscore imports
102638-// are properly ignored and that a new import is added to
102639-// reference method types
102640-
102641-var (
102642-	_ Reader
102643-	_ zlib.Resetter = (*ignoredResetter)(nil) //@suggestedfix("(", "refactor.rewrite", "")
102644-)
102645-
102646-type ignoredResetter struct{}
102647diff -urN a/gopls/internal/lsp/testdata/stub/stub_ignored_imports.go.golden b/gopls/internal/lsp/testdata/stub/stub_ignored_imports.go.golden
102648--- a/gopls/internal/lsp/testdata/stub/stub_ignored_imports.go.golden	2000-01-01 00:00:00.000000000 -0000
102649+++ b/gopls/internal/lsp/testdata/stub/stub_ignored_imports.go.golden	1970-01-01 00:00:00.000000000 +0000
102650@@ -1,25 +0,0 @@
102651--- suggestedfix_stub_ignored_imports_15_20 --
102652-package stub
102653-
102654-import (
102655-	"compress/zlib"
102656-	. "io"
102657-	_ "io"
102658-)
102659-
102660-// This file tests that dot-imports and underscore imports
102661-// are properly ignored and that a new import is added to
102662-// reference method types
102663-
102664-var (
102665-	_ Reader
102666-	_ zlib.Resetter = (*ignoredResetter)(nil) //@suggestedfix("(", "refactor.rewrite", "")
102667-)
102668-
102669-type ignoredResetter struct{}
102670-
102671-// Reset implements zlib.Resetter
102672-func (*ignoredResetter) Reset(r Reader, dict []byte) error {
102673-	panic("unimplemented")
102674-}
102675-
102676diff -urN a/gopls/internal/lsp/testdata/stub/stub_issue2606.go b/gopls/internal/lsp/testdata/stub/stub_issue2606.go
102677--- a/gopls/internal/lsp/testdata/stub/stub_issue2606.go	2000-01-01 00:00:00.000000000 -0000
102678+++ b/gopls/internal/lsp/testdata/stub/stub_issue2606.go	1970-01-01 00:00:00.000000000 +0000
102679@@ -1,7 +0,0 @@
102680-package stub
102681-
102682-type I interface{ error }
102683-
102684-type C int
102685-
102686-var _ I = C(0) //@suggestedfix("C", "refactor.rewrite", "")
102687diff -urN a/gopls/internal/lsp/testdata/stub/stub_issue2606.go.golden b/gopls/internal/lsp/testdata/stub/stub_issue2606.go.golden
102688--- a/gopls/internal/lsp/testdata/stub/stub_issue2606.go.golden	2000-01-01 00:00:00.000000000 -0000
102689+++ b/gopls/internal/lsp/testdata/stub/stub_issue2606.go.golden	1970-01-01 00:00:00.000000000 +0000
102690@@ -1,14 +0,0 @@
102691--- suggestedfix_stub_issue2606_7_11 --
102692-package stub
102693-
102694-type I interface{ error }
102695-
102696-type C int
102697-
102698-// Error implements I
102699-func (C) Error() string {
102700-	panic("unimplemented")
102701-}
102702-
102703-var _ I = C(0) //@suggestedfix("C", "refactor.rewrite", "")
102704-
102705diff -urN a/gopls/internal/lsp/testdata/stub/stub_multi_var.go b/gopls/internal/lsp/testdata/stub/stub_multi_var.go
102706--- a/gopls/internal/lsp/testdata/stub/stub_multi_var.go	2000-01-01 00:00:00.000000000 -0000
102707+++ b/gopls/internal/lsp/testdata/stub/stub_multi_var.go	1970-01-01 00:00:00.000000000 +0000
102708@@ -1,11 +0,0 @@
102709-package stub
102710-
102711-import "io"
102712-
102713-// This test ensures that a variable declaration that
102714-// has multiple values on the same line can still be
102715-// analyzed correctly to target the interface implementation
102716-// diagnostic.
102717-var one, two, three io.Reader = nil, &multiVar{}, nil //@suggestedfix("&", "refactor.rewrite", "")
102718-
102719-type multiVar struct{}
102720diff -urN a/gopls/internal/lsp/testdata/stub/stub_multi_var.go.golden b/gopls/internal/lsp/testdata/stub/stub_multi_var.go.golden
102721--- a/gopls/internal/lsp/testdata/stub/stub_multi_var.go.golden	2000-01-01 00:00:00.000000000 -0000
102722+++ b/gopls/internal/lsp/testdata/stub/stub_multi_var.go.golden	1970-01-01 00:00:00.000000000 +0000
102723@@ -1,18 +0,0 @@
102724--- suggestedfix_stub_multi_var_9_38 --
102725-package stub
102726-
102727-import "io"
102728-
102729-// This test ensures that a variable declaration that
102730-// has multiple values on the same line can still be
102731-// analyzed correctly to target the interface implementation
102732-// diagnostic.
102733-var one, two, three io.Reader = nil, &multiVar{}, nil //@suggestedfix("&", "refactor.rewrite", "")
102734-
102735-type multiVar struct{}
102736-
102737-// Read implements io.Reader
102738-func (*multiVar) Read(p []byte) (n int, err error) {
102739-	panic("unimplemented")
102740-}
102741-
102742diff -urN a/gopls/internal/lsp/testdata/stub/stub_pointer.go b/gopls/internal/lsp/testdata/stub/stub_pointer.go
102743--- a/gopls/internal/lsp/testdata/stub/stub_pointer.go	2000-01-01 00:00:00.000000000 -0000
102744+++ b/gopls/internal/lsp/testdata/stub/stub_pointer.go	1970-01-01 00:00:00.000000000 +0000
102745@@ -1,9 +0,0 @@
102746-package stub
102747-
102748-import "io"
102749-
102750-func getReaderFrom() io.ReaderFrom {
102751-	return &pointerImpl{} //@suggestedfix("&", "refactor.rewrite", "")
102752-}
102753-
102754-type pointerImpl struct{}
102755diff -urN a/gopls/internal/lsp/testdata/stub/stub_pointer.go.golden b/gopls/internal/lsp/testdata/stub/stub_pointer.go.golden
102756--- a/gopls/internal/lsp/testdata/stub/stub_pointer.go.golden	2000-01-01 00:00:00.000000000 -0000
102757+++ b/gopls/internal/lsp/testdata/stub/stub_pointer.go.golden	1970-01-01 00:00:00.000000000 +0000
102758@@ -1,16 +0,0 @@
102759--- suggestedfix_stub_pointer_6_9 --
102760-package stub
102761-
102762-import "io"
102763-
102764-func getReaderFrom() io.ReaderFrom {
102765-	return &pointerImpl{} //@suggestedfix("&", "refactor.rewrite", "")
102766-}
102767-
102768-type pointerImpl struct{}
102769-
102770-// ReadFrom implements io.ReaderFrom
102771-func (*pointerImpl) ReadFrom(r io.Reader) (n int64, err error) {
102772-	panic("unimplemented")
102773-}
102774-
102775diff -urN a/gopls/internal/lsp/testdata/stub/stub_renamed_import.go b/gopls/internal/lsp/testdata/stub/stub_renamed_import.go
102776--- a/gopls/internal/lsp/testdata/stub/stub_renamed_import.go	2000-01-01 00:00:00.000000000 -0000
102777+++ b/gopls/internal/lsp/testdata/stub/stub_renamed_import.go	1970-01-01 00:00:00.000000000 +0000
102778@@ -1,11 +0,0 @@
102779-package stub
102780-
102781-import (
102782-	"compress/zlib"
102783-	myio "io"
102784-)
102785-
102786-var _ zlib.Resetter = &myIO{} //@suggestedfix("&", "refactor.rewrite", "")
102787-var _ myio.Reader
102788-
102789-type myIO struct{}
102790diff -urN a/gopls/internal/lsp/testdata/stub/stub_renamed_import.go.golden b/gopls/internal/lsp/testdata/stub/stub_renamed_import.go.golden
102791--- a/gopls/internal/lsp/testdata/stub/stub_renamed_import.go.golden	2000-01-01 00:00:00.000000000 -0000
102792+++ b/gopls/internal/lsp/testdata/stub/stub_renamed_import.go.golden	1970-01-01 00:00:00.000000000 +0000
102793@@ -1,18 +0,0 @@
102794--- suggestedfix_stub_renamed_import_8_23 --
102795-package stub
102796-
102797-import (
102798-	"compress/zlib"
102799-	myio "io"
102800-)
102801-
102802-var _ zlib.Resetter = &myIO{} //@suggestedfix("&", "refactor.rewrite", "")
102803-var _ myio.Reader
102804-
102805-type myIO struct{}
102806-
102807-// Reset implements zlib.Resetter
102808-func (*myIO) Reset(r myio.Reader, dict []byte) error {
102809-	panic("unimplemented")
102810-}
102811-
102812diff -urN a/gopls/internal/lsp/testdata/stub/stub_renamed_import_iface.go b/gopls/internal/lsp/testdata/stub/stub_renamed_import_iface.go
102813--- a/gopls/internal/lsp/testdata/stub/stub_renamed_import_iface.go	2000-01-01 00:00:00.000000000 -0000
102814+++ b/gopls/internal/lsp/testdata/stub/stub_renamed_import_iface.go	1970-01-01 00:00:00.000000000 +0000
102815@@ -1,13 +0,0 @@
102816-package stub
102817-
102818-import (
102819-	"golang.org/lsptests/stub/other"
102820-)
102821-
102822-// This file tests that if an interface
102823-// method references an import from its own package
102824-// that the concrete type does not yet import, and that import happens
102825-// to be renamed, then we prefer the renaming of the interface.
102826-var _ other.Interface = &otherInterfaceImpl{} //@suggestedfix("&otherInterfaceImpl", "refactor.rewrite", "")
102827-
102828-type otherInterfaceImpl struct{}
102829diff -urN a/gopls/internal/lsp/testdata/stub/stub_renamed_import_iface.go.golden b/gopls/internal/lsp/testdata/stub/stub_renamed_import_iface.go.golden
102830--- a/gopls/internal/lsp/testdata/stub/stub_renamed_import_iface.go.golden	2000-01-01 00:00:00.000000000 -0000
102831+++ b/gopls/internal/lsp/testdata/stub/stub_renamed_import_iface.go.golden	1970-01-01 00:00:00.000000000 +0000
102832@@ -1,22 +0,0 @@
102833--- suggestedfix_stub_renamed_import_iface_11_25 --
102834-package stub
102835-
102836-import (
102837-	"bytes"
102838-	"context"
102839-	"golang.org/lsptests/stub/other"
102840-)
102841-
102842-// This file tests that if an interface
102843-// method references an import from its own package
102844-// that the concrete type does not yet import, and that import happens
102845-// to be renamed, then we prefer the renaming of the interface.
102846-var _ other.Interface = &otherInterfaceImpl{} //@suggestedfix("&otherInterfaceImpl", "refactor.rewrite", "")
102847-
102848-type otherInterfaceImpl struct{}
102849-
102850-// Get implements other.Interface
102851-func (*otherInterfaceImpl) Get(context.Context) *bytes.Buffer {
102852-	panic("unimplemented")
102853-}
102854-
102855diff -urN a/gopls/internal/lsp/testdata/stub/stub_stdlib.go b/gopls/internal/lsp/testdata/stub/stub_stdlib.go
102856--- a/gopls/internal/lsp/testdata/stub/stub_stdlib.go	2000-01-01 00:00:00.000000000 -0000
102857+++ b/gopls/internal/lsp/testdata/stub/stub_stdlib.go	1970-01-01 00:00:00.000000000 +0000
102858@@ -1,9 +0,0 @@
102859-package stub
102860-
102861-import (
102862-	"io"
102863-)
102864-
102865-var _ io.Writer = writer{} //@suggestedfix("w", "refactor.rewrite", "")
102866-
102867-type writer struct{}
102868diff -urN a/gopls/internal/lsp/testdata/stub/stub_stdlib.go.golden b/gopls/internal/lsp/testdata/stub/stub_stdlib.go.golden
102869--- a/gopls/internal/lsp/testdata/stub/stub_stdlib.go.golden	2000-01-01 00:00:00.000000000 -0000
102870+++ b/gopls/internal/lsp/testdata/stub/stub_stdlib.go.golden	1970-01-01 00:00:00.000000000 +0000
102871@@ -1,16 +0,0 @@
102872--- suggestedfix_stub_stdlib_7_19 --
102873-package stub
102874-
102875-import (
102876-	"io"
102877-)
102878-
102879-var _ io.Writer = writer{} //@suggestedfix("w", "refactor.rewrite", "")
102880-
102881-type writer struct{}
102882-
102883-// Write implements io.Writer
102884-func (writer) Write(p []byte) (n int, err error) {
102885-	panic("unimplemented")
102886-}
102887-
102888diff -urN a/gopls/internal/lsp/testdata/stub/stub_typedecl_group.go b/gopls/internal/lsp/testdata/stub/stub_typedecl_group.go
102889--- a/gopls/internal/lsp/testdata/stub/stub_typedecl_group.go	2000-01-01 00:00:00.000000000 -0000
102890+++ b/gopls/internal/lsp/testdata/stub/stub_typedecl_group.go	1970-01-01 00:00:00.000000000 +0000
102891@@ -1,27 +0,0 @@
102892-package stub
102893-
102894-// Regression test for Issue #56825: file corrupted by insertion of
102895-// methods after TypeSpec in a parenthesized TypeDecl.
102896-
102897-import "io"
102898-
102899-func newReadCloser() io.ReadCloser {
102900-	return rdcloser{} //@suggestedfix("rd", "refactor.rewrite", "")
102901-}
102902-
102903-type (
102904-	A        int
102905-	rdcloser struct{}
102906-	B        int
102907-)
102908-
102909-func _() {
102910-	// Local types can't be stubbed as there's nowhere to put the methods.
102911-	// The suggestedfix assertion can't express this yet. TODO(adonovan): support it.
102912-	type local struct{}
102913-	var _ io.ReadCloser = local{} // want error: `local type "local" cannot be stubbed`
102914-}
102915-
102916-type (
102917-	C int
102918-)
102919diff -urN a/gopls/internal/lsp/testdata/stub/stub_typedecl_group.go.golden b/gopls/internal/lsp/testdata/stub/stub_typedecl_group.go.golden
102920--- a/gopls/internal/lsp/testdata/stub/stub_typedecl_group.go.golden	2000-01-01 00:00:00.000000000 -0000
102921+++ b/gopls/internal/lsp/testdata/stub/stub_typedecl_group.go.golden	1970-01-01 00:00:00.000000000 +0000
102922@@ -1,39 +0,0 @@
102923--- suggestedfix_stub_typedecl_group_9_9 --
102924-package stub
102925-
102926-// Regression test for Issue #56825: file corrupted by insertion of
102927-// methods after TypeSpec in a parenthesized TypeDecl.
102928-
102929-import "io"
102930-
102931-func newReadCloser() io.ReadCloser {
102932-	return rdcloser{} //@suggestedfix("rd", "refactor.rewrite", "")
102933-}
102934-
102935-type (
102936-	A        int
102937-	rdcloser struct{}
102938-	B        int
102939-)
102940-
102941-// Close implements io.ReadCloser
102942-func (rdcloser) Close() error {
102943-	panic("unimplemented")
102944-}
102945-
102946-// Read implements io.ReadCloser
102947-func (rdcloser) Read(p []byte) (n int, err error) {
102948-	panic("unimplemented")
102949-}
102950-
102951-func _() {
102952-	// Local types can't be stubbed as there's nowhere to put the methods.
102953-	// The suggestedfix assertion can't express this yet. TODO(adonovan): support it.
102954-	type local struct{}
102955-	var _ io.ReadCloser = local{} // want error: `local type "local" cannot be stubbed`
102956-}
102957-
102958-type (
102959-	C int
102960-)
102961-
102962diff -urN a/gopls/internal/lsp/testdata/suggestedfix/has_suggested_fix.go b/gopls/internal/lsp/testdata/suggestedfix/has_suggested_fix.go
102963--- a/gopls/internal/lsp/testdata/suggestedfix/has_suggested_fix.go	2000-01-01 00:00:00.000000000 -0000
102964+++ b/gopls/internal/lsp/testdata/suggestedfix/has_suggested_fix.go	1970-01-01 00:00:00.000000000 +0000
102965@@ -1,11 +0,0 @@
102966-package suggestedfix
102967-
102968-import (
102969-	"log"
102970-)
102971-
102972-func goodbye() {
102973-	s := "hiiiiiii"
102974-	s = s //@suggestedfix("s = s", "quickfix", "")
102975-	log.Print(s)
102976-}
102977diff -urN a/gopls/internal/lsp/testdata/suggestedfix/has_suggested_fix.go.golden b/gopls/internal/lsp/testdata/suggestedfix/has_suggested_fix.go.golden
102978--- a/gopls/internal/lsp/testdata/suggestedfix/has_suggested_fix.go.golden	2000-01-01 00:00:00.000000000 -0000
102979+++ b/gopls/internal/lsp/testdata/suggestedfix/has_suggested_fix.go.golden	1970-01-01 00:00:00.000000000 +0000
102980@@ -1,13 +0,0 @@
102981--- suggestedfix_has_suggested_fix_9_2 --
102982-package suggestedfix
102983-
102984-import (
102985-	"log"
102986-)
102987-
102988-func goodbye() {
102989-	s := "hiiiiiii"
102990-	 //@suggestedfix("s = s", "quickfix", "")
102991-	log.Print(s)
102992-}
102993-
102994diff -urN a/gopls/internal/lsp/testdata/summary_go1.18.txt.golden b/gopls/internal/lsp/testdata/summary_go1.18.txt.golden
102995--- a/gopls/internal/lsp/testdata/summary_go1.18.txt.golden	2000-01-01 00:00:00.000000000 -0000
102996+++ b/gopls/internal/lsp/testdata/summary_go1.18.txt.golden	1970-01-01 00:00:00.000000000 +0000
102997@@ -1,32 +0,0 @@
102998--- summary --
102999-CallHierarchyCount = 2
103000-CodeLensCount = 5
103001-CompletionsCount = 264
103002-CompletionSnippetCount = 115
103003-UnimportedCompletionsCount = 5
103004-DeepCompletionsCount = 5
103005-FuzzyCompletionsCount = 8
103006-RankedCompletionsCount = 174
103007-CaseSensitiveCompletionsCount = 4
103008-DiagnosticsCount = 42
103009-FoldingRangesCount = 2
103010-FormatCount = 6
103011-ImportCount = 8
103012-SemanticTokenCount = 3
103013-SuggestedFixCount = 71
103014-FunctionExtractionCount = 27
103015-MethodExtractionCount = 6
103016-DefinitionsCount = 47
103017-TypeDefinitionsCount = 18
103018-HighlightsCount = 69
103019-InlayHintsCount = 5
103020-ReferencesCount = 30
103021-RenamesCount = 48
103022-PrepareRenamesCount = 7
103023-SymbolsCount = 2
103024-WorkspaceSymbolsCount = 20
103025-SignaturesCount = 33
103026-LinksCount = 7
103027-ImplementationsCount = 26
103028-SelectionRangesCount = 3
103029-
103030diff -urN a/gopls/internal/lsp/testdata/summary.txt.golden b/gopls/internal/lsp/testdata/summary.txt.golden
103031--- a/gopls/internal/lsp/testdata/summary.txt.golden	2000-01-01 00:00:00.000000000 -0000
103032+++ b/gopls/internal/lsp/testdata/summary.txt.golden	1970-01-01 00:00:00.000000000 +0000
103033@@ -1,32 +0,0 @@
103034--- summary --
103035-CallHierarchyCount = 2
103036-CodeLensCount = 5
103037-CompletionsCount = 263
103038-CompletionSnippetCount = 106
103039-UnimportedCompletionsCount = 5
103040-DeepCompletionsCount = 5
103041-FuzzyCompletionsCount = 8
103042-RankedCompletionsCount = 164
103043-CaseSensitiveCompletionsCount = 4
103044-DiagnosticsCount = 42
103045-FoldingRangesCount = 2
103046-FormatCount = 6
103047-ImportCount = 8
103048-SemanticTokenCount = 3
103049-SuggestedFixCount = 65
103050-FunctionExtractionCount = 27
103051-MethodExtractionCount = 6
103052-DefinitionsCount = 47
103053-TypeDefinitionsCount = 18
103054-HighlightsCount = 69
103055-InlayHintsCount = 4
103056-ReferencesCount = 30
103057-RenamesCount = 41
103058-PrepareRenamesCount = 7
103059-SymbolsCount = 1
103060-WorkspaceSymbolsCount = 20
103061-SignaturesCount = 33
103062-LinksCount = 7
103063-ImplementationsCount = 16
103064-SelectionRangesCount = 3
103065-
103066diff -urN a/gopls/internal/lsp/testdata/symbols/go1.18.go b/gopls/internal/lsp/testdata/symbols/go1.18.go
103067--- a/gopls/internal/lsp/testdata/symbols/go1.18.go	2000-01-01 00:00:00.000000000 -0000
103068+++ b/gopls/internal/lsp/testdata/symbols/go1.18.go	1970-01-01 00:00:00.000000000 +0000
103069@@ -1,16 +0,0 @@
103070-//go:build go1.18
103071-// +build go1.18
103072-
103073-package main
103074-
103075-type T[P any] struct { //@symbol("T", "T", "Struct", "struct{...}", "T", "")
103076-	F P //@symbol("F", "F", "Field", "P", "", "T")
103077-}
103078-
103079-type Constraint interface { //@symbol("Constraint", "Constraint", "Interface", "interface{...}", "Constraint", "")
103080-	~int | struct{ int } //@symbol("~int | struct{int}", "~int | struct{ int }", "Field", "", "", "Constraint")
103081-
103082-	// TODO(rfindley): the selection range below is the entire interface field.
103083-	// Can we reduce it?
103084-	interface{ M() } //@symbol("interface{...}", "interface{ M() }", "Field", "", "iFaceField", "Constraint"), symbol("M", "M", "Method", "func()", "", "iFaceField")
103085-}
103086diff -urN a/gopls/internal/lsp/testdata/symbols/go1.18.go.golden b/gopls/internal/lsp/testdata/symbols/go1.18.go.golden
103087--- a/gopls/internal/lsp/testdata/symbols/go1.18.go.golden	2000-01-01 00:00:00.000000000 -0000
103088+++ b/gopls/internal/lsp/testdata/symbols/go1.18.go.golden	1970-01-01 00:00:00.000000000 +0000
103089@@ -1,7 +0,0 @@
103090--- symbols --
103091-T Struct 6:6-6:7
103092-	F Field 7:2-7:3
103093-Constraint Interface 10:6-10:16
103094-	interface{...} Field 15:2-15:18
103095-	~int | struct{int} Field 11:2-11:22
103096-
103097diff -urN a/gopls/internal/lsp/testdata/symbols/main.go b/gopls/internal/lsp/testdata/symbols/main.go
103098--- a/gopls/internal/lsp/testdata/symbols/main.go	2000-01-01 00:00:00.000000000 -0000
103099+++ b/gopls/internal/lsp/testdata/symbols/main.go	1970-01-01 00:00:00.000000000 +0000
103100@@ -1,91 +0,0 @@
103101-package main
103102-
103103-import (
103104-	"io"
103105-)
103106-
103107-// Each symbol marker in this file defines the following information:
103108-//  symbol(name, selectionSpan, kind, detail, id, parentID)
103109-//    - name: DocumentSymbol.Name
103110-//    - selectionSpan: DocumentSymbol.SelectionRange
103111-//    - kind: DocumentSymbol.Kind
103112-//    - detail: DocumentSymbol.Detail
103113-//    - id: if non-empty, a unique identifier for this symbol
103114-//    - parentID: if non-empty, the id of the parent of this symbol
103115-//
103116-// This data in aggregate defines a set of document symbols and their
103117-// parent-child relationships, which is compared against the DocummentSymbols
103118-// response from gopls for the current file.
103119-//
103120-// TODO(rfindley): the symbol annotations here are complicated and difficult to
103121-// maintain. It would be simpler to just write out the full expected response
103122-// in the golden file, perhaps as raw JSON.
103123-
103124-var _ = 1
103125-
103126-var x = 42 //@symbol("x", "x", "Variable", "", "", "")
103127-
103128-var nested struct { //@symbol("nested", "nested", "Variable", "struct{...}", "nested", "")
103129-	nestedField struct { //@symbol("nestedField", "nestedField", "Field", "struct{...}", "nestedField", "nested")
103130-		f int //@symbol("f", "f", "Field", "int", "", "nestedField")
103131-	}
103132-}
103133-
103134-const y = 43 //@symbol("y", "y", "Constant", "", "", "")
103135-
103136-type Number int //@symbol("Number", "Number", "Class", "int", "", "")
103137-
103138-type Alias = string //@symbol("Alias", "Alias", "Class", "string", "", "")
103139-
103140-type NumberAlias = Number //@symbol("NumberAlias", "NumberAlias", "Class", "Number", "", "")
103141-
103142-type (
103143-	Boolean   bool   //@symbol("Boolean", "Boolean", "Class", "bool", "", "")
103144-	BoolAlias = bool //@symbol("BoolAlias", "BoolAlias", "Class", "bool", "", "")
103145-)
103146-
103147-type Foo struct { //@symbol("Foo", "Foo", "Struct", "struct{...}", "Foo", "")
103148-	Quux                    //@symbol("Quux", "Quux", "Field", "Quux", "", "Foo")
103149-	W         io.Writer     //@symbol("W", "W", "Field", "io.Writer", "", "Foo")
103150-	Bar       int           //@symbol("Bar", "Bar", "Field", "int", "", "Foo")
103151-	baz       string        //@symbol("baz", "baz", "Field", "string", "", "Foo")
103152-	funcField func(int) int //@symbol("funcField", "funcField", "Field", "func(int) int", "", "Foo")
103153-}
103154-
103155-type Quux struct { //@symbol("Quux", "Quux", "Struct", "struct{...}", "Quux", "")
103156-	X, Y float64 //@symbol("X", "X", "Field", "float64", "", "Quux"), symbol("Y", "Y", "Field", "float64", "", "Quux")
103157-}
103158-
103159-type EmptyStruct struct{} //@symbol("EmptyStruct", "EmptyStruct", "Struct", "struct{}", "", "")
103160-
103161-func (f Foo) Baz() string { //@symbol("(Foo).Baz", "Baz", "Method", "func() string", "", "")
103162-	return f.baz
103163-}
103164-
103165-func _() {}
103166-
103167-func (q *Quux) Do() {} //@symbol("(*Quux).Do", "Do", "Method", "func()", "", "")
103168-
103169-func main() { //@symbol("main", "main", "Function", "func()", "", "")
103170-}
103171-
103172-type Stringer interface { //@symbol("Stringer", "Stringer", "Interface", "interface{...}", "Stringer", "")
103173-	String() string //@symbol("String", "String", "Method", "func() string", "", "Stringer")
103174-}
103175-
103176-type ABer interface { //@symbol("ABer", "ABer", "Interface", "interface{...}", "ABer", "")
103177-	B()        //@symbol("B", "B", "Method", "func()", "", "ABer")
103178-	A() string //@symbol("A", "A", "Method", "func() string", "", "ABer")
103179-}
103180-
103181-type WithEmbeddeds interface { //@symbol("WithEmbeddeds", "WithEmbeddeds", "Interface", "interface{...}", "WithEmbeddeds", "")
103182-	Do()      //@symbol("Do", "Do", "Method", "func()", "", "WithEmbeddeds")
103183-	ABer      //@symbol("ABer", "ABer", "Field", "ABer", "", "WithEmbeddeds")
103184-	io.Writer //@symbol("Writer", "Writer", "Field", "io.Writer", "", "WithEmbeddeds")
103185-}
103186-
103187-type EmptyInterface interface{} //@symbol("EmptyInterface", "EmptyInterface", "Interface", "interface{}", "", "")
103188-
103189-func Dunk() int { return 0 } //@symbol("Dunk", "Dunk", "Function", "func() int", "", "")
103190-
103191-func dunk() {} //@symbol("dunk", "dunk", "Function", "func()", "", "")
103192diff -urN a/gopls/internal/lsp/testdata/symbols/main.go.golden b/gopls/internal/lsp/testdata/symbols/main.go.golden
103193--- a/gopls/internal/lsp/testdata/symbols/main.go.golden	2000-01-01 00:00:00.000000000 -0000
103194+++ b/gopls/internal/lsp/testdata/symbols/main.go.golden	1970-01-01 00:00:00.000000000 +0000
103195@@ -1,36 +0,0 @@
103196--- symbols --
103197-x Variable 26:5-26:6
103198-nested Variable 28:5-28:11
103199-	nestedField Field 29:2-29:13
103200-y Constant 34:7-34:8
103201-Number Class 36:6-36:12
103202-Alias Class 38:6-38:11
103203-NumberAlias Class 40:6-40:17
103204-Boolean Class 43:2-43:9
103205-BoolAlias Class 44:2-44:11
103206-Foo Struct 47:6-47:9
103207-	Bar Field 50:2-50:5
103208-	Quux Field 48:2-48:6
103209-	W Field 49:2-49:3
103210-	baz Field 51:2-51:5
103211-	funcField Field 52:2-52:11
103212-Quux Struct 55:6-55:10
103213-	X Field 56:2-56:3
103214-	Y Field 56:5-56:6
103215-EmptyStruct Struct 59:6-59:17
103216-(Foo).Baz Method 61:14-61:17
103217-(*Quux).Do Method 67:16-67:18
103218-main Function 69:6-69:10
103219-Stringer Interface 72:6-72:14
103220-	String Method 73:2-73:8
103221-ABer Interface 76:6-76:10
103222-	A Method 78:2-78:3
103223-	B Method 77:2-77:3
103224-WithEmbeddeds Interface 81:6-81:19
103225-	ABer Field 83:2-83:6
103226-	Do Method 82:2-82:4
103227-	Writer Field 84:5-84:11
103228-EmptyInterface Interface 87:6-87:20
103229-Dunk Function 89:6-89:10
103230-dunk Function 91:6-91:10
103231-
103232diff -urN a/gopls/internal/lsp/testdata/testy/testy.go b/gopls/internal/lsp/testdata/testy/testy.go
103233--- a/gopls/internal/lsp/testdata/testy/testy.go	2000-01-01 00:00:00.000000000 -0000
103234+++ b/gopls/internal/lsp/testdata/testy/testy.go	1970-01-01 00:00:00.000000000 +0000
103235@@ -1,5 +0,0 @@
103236-package testy
103237-
103238-func a() { //@mark(identA, "a"),item(funcA, "a", "func()", "func"),refs("a", identA, testyA)
103239-	//@complete("", funcA)
103240-}
103241diff -urN a/gopls/internal/lsp/testdata/testy/testy_test.go b/gopls/internal/lsp/testdata/testy/testy_test.go
103242--- a/gopls/internal/lsp/testdata/testy/testy_test.go	2000-01-01 00:00:00.000000000 -0000
103243+++ b/gopls/internal/lsp/testdata/testy/testy_test.go	1970-01-01 00:00:00.000000000 +0000
103244@@ -1,18 +0,0 @@
103245-package testy
103246-
103247-import (
103248-	"testing"
103249-
103250-	sig "golang.org/lsptests/signature"
103251-	"golang.org/lsptests/snippets"
103252-)
103253-
103254-func TestSomething(t *testing.T) { //@item(TestSomething, "TestSomething(t *testing.T)", "", "func")
103255-	var x int //@mark(testyX, "x"),diag("x", "compiler", "x declared (and|but) not used", "error"),refs("x", testyX)
103256-	a()       //@mark(testyA, "a")
103257-}
103258-
103259-func _() {
103260-	_ = snippets.X(nil) //@signature("nil", "X(_ map[sig.Alias]types.CoolAlias) map[sig.Alias]types.CoolAlias", 0)
103261-	var _ sig.Alias
103262-}
103263diff -urN a/gopls/internal/lsp/testdata/testy/testy_test.go.golden b/gopls/internal/lsp/testdata/testy/testy_test.go.golden
103264--- a/gopls/internal/lsp/testdata/testy/testy_test.go.golden	2000-01-01 00:00:00.000000000 -0000
103265+++ b/gopls/internal/lsp/testdata/testy/testy_test.go.golden	1970-01-01 00:00:00.000000000 +0000
103266@@ -1,3 +0,0 @@
103267--- X(_ map[sig.Alias]types.CoolAlias) map[sig.Alias]types.CoolAlias-signature --
103268-X(_ map[sig.Alias]types.CoolAlias) map[sig.Alias]types.CoolAlias
103269-
103270diff -urN a/gopls/internal/lsp/testdata/typdef/typdef.go b/gopls/internal/lsp/testdata/typdef/typdef.go
103271--- a/gopls/internal/lsp/testdata/typdef/typdef.go	2000-01-01 00:00:00.000000000 -0000
103272+++ b/gopls/internal/lsp/testdata/typdef/typdef.go	1970-01-01 00:00:00.000000000 +0000
103273@@ -1,65 +0,0 @@
103274-package typdef
103275-
103276-type Struct struct { //@item(Struct, "Struct", "struct{...}", "struct")
103277-	Field string
103278-}
103279-
103280-type Int int //@item(Int, "Int", "int", "type")
103281-
103282-func _() {
103283-	var (
103284-		value Struct
103285-		point *Struct
103286-	)
103287-	_ = value //@typdef("value", Struct)
103288-	_ = point //@typdef("point", Struct)
103289-
103290-	var (
103291-		array   [3]Struct
103292-		slice   []Struct
103293-		ch      chan Struct
103294-		complex [3]chan *[5][]Int
103295-	)
103296-	_ = array   //@typdef("array", Struct)
103297-	_ = slice   //@typdef("slice", Struct)
103298-	_ = ch      //@typdef("ch", Struct)
103299-	_ = complex //@typdef("complex", Int)
103300-
103301-	var s struct {
103302-		x struct {
103303-			xx struct {
103304-				field1 []Struct
103305-				field2 []Int
103306-			}
103307-		}
103308-	}
103309-	s.x.xx.field1 //@typdef("field1", Struct)
103310-	s.x.xx.field2 //@typdef("field2", Int)
103311-}
103312-
103313-func F1() Int                              { return 0 }
103314-func F2() (Int, float64)                   { return 0, 0 }
103315-func F3() (Struct, int, bool, error)       { return Struct{}, 0, false, nil }
103316-func F4() (**int, Int, bool, *error)       { return nil, Struct{}, false, nil }
103317-func F5() (int, float64, error, Struct)    { return 0, 0, nil, Struct{} }
103318-func F6() (int, float64, ***Struct, error) { return 0, 0, nil, nil }
103319-
103320-func _() {
103321-	F1() //@typdef("F1", Int)
103322-	F2() //@typdef("F2", Int)
103323-	F3() //@typdef("F3", Struct)
103324-	F4() //@typdef("F4", Int)
103325-	F5() //@typdef("F5", Struct)
103326-	F6() //@typdef("F6", Struct)
103327-
103328-	f := func() Int { return 0 }
103329-	f() //@typdef("f", Int)
103330-}
103331-
103332-// https://github.com/golang/go/issues/38589#issuecomment-620350922
103333-func _() {
103334-	type myFunc func(int) Int //@item(myFunc, "myFunc", "func", "type")
103335-
103336-	var foo myFunc
103337-	bar := foo() //@typdef("foo", myFunc)
103338-}
103339diff -urN a/gopls/internal/lsp/testdata/typeassert/type_assert.go b/gopls/internal/lsp/testdata/typeassert/type_assert.go
103340--- a/gopls/internal/lsp/testdata/typeassert/type_assert.go	2000-01-01 00:00:00.000000000 -0000
103341+++ b/gopls/internal/lsp/testdata/typeassert/type_assert.go	1970-01-01 00:00:00.000000000 +0000
103342@@ -1,24 +0,0 @@
103343-package typeassert
103344-
103345-type abc interface { //@item(abcIntf, "abc", "interface{...}", "interface")
103346-	abc()
103347-}
103348-
103349-type abcImpl struct{} //@item(abcImpl, "abcImpl", "struct{...}", "struct")
103350-func (abcImpl) abc()
103351-
103352-type abcPtrImpl struct{} //@item(abcPtrImpl, "abcPtrImpl", "struct{...}", "struct")
103353-func (*abcPtrImpl) abc()
103354-
103355-type abcNotImpl struct{} //@item(abcNotImpl, "abcNotImpl", "struct{...}", "struct")
103356-
103357-func _() {
103358-	var a abc
103359-	switch a.(type) {
103360-	case ab: //@complete(":", abcImpl, abcPtrImpl, abcIntf, abcNotImpl)
103361-	case *ab: //@complete(":", abcImpl, abcPtrImpl, abcIntf, abcNotImpl)
103362-	}
103363-
103364-	a.(ab)  //@complete(")", abcImpl, abcPtrImpl, abcIntf, abcNotImpl)
103365-	a.(*ab) //@complete(")", abcImpl, abcPtrImpl, abcIntf, abcNotImpl)
103366-}
103367diff -urN a/gopls/internal/lsp/testdata/typeerrors/noresultvalues.go b/gopls/internal/lsp/testdata/typeerrors/noresultvalues.go
103368--- a/gopls/internal/lsp/testdata/typeerrors/noresultvalues.go	2000-01-01 00:00:00.000000000 -0000
103369+++ b/gopls/internal/lsp/testdata/typeerrors/noresultvalues.go	1970-01-01 00:00:00.000000000 +0000
103370@@ -1,5 +0,0 @@
103371-package typeerrors
103372-
103373-func x() { return nil } //@suggestedfix("nil", "quickfix", "")
103374-
103375-func y() { return nil, "hello" } //@suggestedfix("nil", "quickfix", "")
103376diff -urN a/gopls/internal/lsp/testdata/typeerrors/noresultvalues.go.golden b/gopls/internal/lsp/testdata/typeerrors/noresultvalues.go.golden
103377--- a/gopls/internal/lsp/testdata/typeerrors/noresultvalues.go.golden	2000-01-01 00:00:00.000000000 -0000
103378+++ b/gopls/internal/lsp/testdata/typeerrors/noresultvalues.go.golden	1970-01-01 00:00:00.000000000 +0000
103379@@ -1,14 +0,0 @@
103380--- suggestedfix_noresultvalues_3_19 --
103381-package typeerrors
103382-
103383-func x() { return } //@suggestedfix("nil", "quickfix", "")
103384-
103385-func y() { return nil, "hello" } //@suggestedfix("nil", "quickfix", "")
103386-
103387--- suggestedfix_noresultvalues_5_19 --
103388-package typeerrors
103389-
103390-func x() { return nil } //@suggestedfix("nil", "quickfix", "")
103391-
103392-func y() { return } //@suggestedfix("nil", "quickfix", "")
103393-
103394diff -urN a/gopls/internal/lsp/testdata/typemods/type_mods.go b/gopls/internal/lsp/testdata/typemods/type_mods.go
103395--- a/gopls/internal/lsp/testdata/typemods/type_mods.go	2000-01-01 00:00:00.000000000 -0000
103396+++ b/gopls/internal/lsp/testdata/typemods/type_mods.go	1970-01-01 00:00:00.000000000 +0000
103397@@ -1,21 +0,0 @@
103398-package typemods
103399-
103400-func fooFunc() func() int { //@item(modFooFunc, "fooFunc", "func() func() int", "func")
103401-	return func() int {
103402-		return 0
103403-	}
103404-}
103405-
103406-func fooPtr() *int { //@item(modFooPtr, "fooPtr", "func() *int", "func")
103407-	return nil
103408-}
103409-
103410-func _() {
103411-	var _ int = foo //@snippet(" //", modFooFunc, "fooFunc()()", "fooFunc()()"),snippet(" //", modFooPtr, "*fooPtr()", "*fooPtr()")
103412-}
103413-
103414-func _() {
103415-	var m map[int][]chan int //@item(modMapChanPtr, "m", "map[int]chan *int", "var")
103416-
103417-	var _ int = m //@snippet(" //", modMapChanPtr, "<-m[${1:}][${2:}]", "<-m[${1:}][${2:}]")
103418-}
103419diff -urN a/gopls/internal/lsp/testdata/typeparams/type_params.go b/gopls/internal/lsp/testdata/typeparams/type_params.go
103420--- a/gopls/internal/lsp/testdata/typeparams/type_params.go	2000-01-01 00:00:00.000000000 -0000
103421+++ b/gopls/internal/lsp/testdata/typeparams/type_params.go	1970-01-01 00:00:00.000000000 +0000
103422@@ -1,61 +0,0 @@
103423-//go:build go1.18
103424-// +build go1.18
103425-
103426-package typeparams
103427-
103428-func one[a int | string]()            {}
103429-func two[a int | string, b float64 | int]() {}
103430-
103431-func _() {
103432-	one[]() //@rank("]", string, float64)
103433-	two[]() //@rank("]", int, float64)
103434-	two[int, f]() //@rank("]", float64, float32)
103435-}
103436-
103437-func slices[a []int | []float64]() {} //@item(tpInts, "[]int", "[]int", "type"),item(tpFloats, "[]float64", "[]float64", "type")
103438-
103439-func _() {
103440-	slices[]() //@rank("]", tpInts),rank("]", tpFloats)
103441-}
103442-
103443-type s[a int | string] struct{}
103444-
103445-func _() {
103446-	s[]{} //@rank("]", int, float64)
103447-}
103448-
103449-func takesGeneric[a int | string](s[a]) {
103450-	"s[a]{}" //@item(tpInScopeLit, "s[a]{}", "", "var")
103451-	takesGeneric() //@rank(")", tpInScopeLit),snippet(")", tpInScopeLit, "s[a]{\\}", "s[a]{\\}")
103452-}
103453-
103454-func _() {
103455-	s[int]{} //@item(tpInstLit, "s[int]{}", "", "var")
103456-	takesGeneric[int]() //@rank(")", tpInstLit),snippet(")", tpInstLit, "s[int]{\\}", "s[int]{\\}")
103457-
103458-	"s[...]{}" //@item(tpUninstLit, "s[...]{}", "", "var")
103459-	takesGeneric() //@rank(")", tpUninstLit),snippet(")", tpUninstLit, "s[${1:}]{\\}", "s[${1:a}]{\\}")
103460-}
103461-
103462-func returnTP[A int | float64](a A) A { //@item(returnTP, "returnTP", "something", "func")
103463-	return a
103464-}
103465-
103466-func _() {
103467-	// disabled - see issue #54822
103468-	var _ int = returnTP // snippet(" //", returnTP, "returnTP[${1:}](${2:})", "returnTP[${1:A int|float64}](${2:a A})")
103469-
103470-	var aa int //@item(tpInt, "aa", "int", "var")
103471-	var ab float64 //@item(tpFloat, "ab", "float64", "var")
103472-	returnTP[int](a) //@rank(")", tpInt, tpFloat)
103473-}
103474-
103475-func takesFunc[T any](func(T) T) {
103476-	var _ func(t T) T = f //@snippet(" //", tpLitFunc, "func(t T) T {$0\\}", "func(t T) T {$0\\}")
103477-}
103478-
103479-func _() {
103480-	_ = "func(...) {}" //@item(tpLitFunc, "func(...) {}", "", "var")
103481-	takesFunc() //@snippet(")", tpLitFunc, "func(${1:}) ${2:} {$0\\}", "func(${1:t} ${2:T}) ${3:T} {$0\\}")
103482-	takesFunc[int]() //@snippet(")", tpLitFunc, "func(i int) int {$0\\}", "func(${1:i} int) int {$0\\}")
103483-}
103484diff -urN a/gopls/internal/lsp/testdata/types/types.go b/gopls/internal/lsp/testdata/types/types.go
103485--- a/gopls/internal/lsp/testdata/types/types.go	2000-01-01 00:00:00.000000000 -0000
103486+++ b/gopls/internal/lsp/testdata/types/types.go	1970-01-01 00:00:00.000000000 +0000
103487@@ -1,18 +0,0 @@
103488-package types
103489-
103490-type CoolAlias = int //@item(CoolAlias, "CoolAlias", "int", "type")
103491-
103492-type X struct { //@item(X_struct, "X", "struct{...}", "struct")
103493-	x int
103494-}
103495-
103496-type Y struct { //@item(Y_struct, "Y", "struct{...}", "struct")
103497-	y int
103498-}
103499-
103500-type Bob interface { //@item(Bob_interface, "Bob", "interface{...}", "interface")
103501-	Bobby()
103502-}
103503-
103504-func (*X) Bobby() {}
103505-func (*Y) Bobby() {}
103506diff -urN a/gopls/internal/lsp/testdata/undeclared/var.go b/gopls/internal/lsp/testdata/undeclared/var.go
103507--- a/gopls/internal/lsp/testdata/undeclared/var.go	2000-01-01 00:00:00.000000000 -0000
103508+++ b/gopls/internal/lsp/testdata/undeclared/var.go	1970-01-01 00:00:00.000000000 +0000
103509@@ -1,14 +0,0 @@
103510-package undeclared
103511-
103512-func m() int {
103513-	z, _ := 1+y, 11 //@diag("y", "compiler", "(undeclared name|undefined): y", "error"),suggestedfix("y", "quickfix", "")
103514-	if 100 < 90 {
103515-		z = 1
103516-	} else if 100 > n+2 { //@diag("n", "compiler", "(undeclared name|undefined): n", "error"),suggestedfix("n", "quickfix", "")
103517-		z = 4
103518-	}
103519-	for i < 200 { //@diag("i", "compiler", "(undeclared name|undefined): i", "error"),suggestedfix("i", "quickfix", "")
103520-	}
103521-	r() //@diag("r", "compiler", "(undeclared name|undefined): r", "error")
103522-	return z
103523-}
103524diff -urN a/gopls/internal/lsp/testdata/undeclared/var.go.golden b/gopls/internal/lsp/testdata/undeclared/var.go.golden
103525--- a/gopls/internal/lsp/testdata/undeclared/var.go.golden	2000-01-01 00:00:00.000000000 -0000
103526+++ b/gopls/internal/lsp/testdata/undeclared/var.go.golden	1970-01-01 00:00:00.000000000 +0000
103527@@ -1,51 +0,0 @@
103528--- suggestedfix_var_10_6 --
103529-package undeclared
103530-
103531-func m() int {
103532-	z, _ := 1+y, 11 //@diag("y", "compiler", "(undeclared name|undefined): y", "error"),suggestedfix("y", "quickfix", "")
103533-	if 100 < 90 {
103534-		z = 1
103535-	} else if 100 > n+2 { //@diag("n", "compiler", "(undeclared name|undefined): n", "error"),suggestedfix("n", "quickfix", "")
103536-		z = 4
103537-	}
103538-	i :=
103539-	for i < 200 { //@diag("i", "compiler", "(undeclared name|undefined): i", "error"),suggestedfix("i", "quickfix", "")
103540-	}
103541-	r() //@diag("r", "compiler", "(undeclared name|undefined): r", "error")
103542-	return z
103543-}
103544-
103545--- suggestedfix_var_4_12 --
103546-package undeclared
103547-
103548-func m() int {
103549-	y :=
103550-	z, _ := 1+y, 11 //@diag("y", "compiler", "(undeclared name|undefined): y", "error"),suggestedfix("y", "quickfix", "")
103551-	if 100 < 90 {
103552-		z = 1
103553-	} else if 100 > n+2 { //@diag("n", "compiler", "(undeclared name|undefined): n", "error"),suggestedfix("n", "quickfix", "")
103554-		z = 4
103555-	}
103556-	for i < 200 { //@diag("i", "compiler", "(undeclared name|undefined): i", "error"),suggestedfix("i", "quickfix", "")
103557-	}
103558-	r() //@diag("r", "compiler", "(undeclared name|undefined): r", "error")
103559-	return z
103560-}
103561-
103562--- suggestedfix_var_7_18 --
103563-package undeclared
103564-
103565-func m() int {
103566-	z, _ := 1+y, 11 //@diag("y", "compiler", "(undeclared name|undefined): y", "error"),suggestedfix("y", "quickfix", "")
103567-	n :=
103568-	if 100 < 90 {
103569-		z = 1
103570-	} else if 100 > n+2 { //@diag("n", "compiler", "(undeclared name|undefined): n", "error"),suggestedfix("n", "quickfix", "")
103571-		z = 4
103572-	}
103573-	for i < 200 { //@diag("i", "compiler", "(undeclared name|undefined): i", "error"),suggestedfix("i", "quickfix", "")
103574-	}
103575-	r() //@diag("r", "compiler", "(undeclared name|undefined): r", "error")
103576-	return z
103577-}
103578-
103579diff -urN a/gopls/internal/lsp/testdata/unimported/export_test.go b/gopls/internal/lsp/testdata/unimported/export_test.go
103580--- a/gopls/internal/lsp/testdata/unimported/export_test.go	2000-01-01 00:00:00.000000000 -0000
103581+++ b/gopls/internal/lsp/testdata/unimported/export_test.go	1970-01-01 00:00:00.000000000 +0000
103582@@ -1,3 +0,0 @@
103583-package unimported
103584-
103585-var TestExport int //@item(testexport, "TestExport", "var (from \"golang.org/lsptests/unimported\")", "var")
103586diff -urN a/gopls/internal/lsp/testdata/unimported/unimported_cand_type.go b/gopls/internal/lsp/testdata/unimported/unimported_cand_type.go
103587--- a/gopls/internal/lsp/testdata/unimported/unimported_cand_type.go	2000-01-01 00:00:00.000000000 -0000
103588+++ b/gopls/internal/lsp/testdata/unimported/unimported_cand_type.go	1970-01-01 00:00:00.000000000 +0000
103589@@ -1,16 +0,0 @@
103590-package unimported
103591-
103592-import (
103593-	_ "context"
103594-
103595-	"golang.org/lsptests/baz"
103596-	_ "golang.org/lsptests/signature" // provide type information for unimported completions in the other file
103597-)
103598-
103599-func _() {
103600-	foo.StructFoo{} //@item(litFooStructFoo, "foo.StructFoo{}", "struct{...}", "struct")
103601-
103602-	// We get the literal completion for "foo.StructFoo{}" even though we haven't
103603-	// imported "foo" yet.
103604-	baz.FooStruct = f //@snippet(" //", litFooStructFoo, "foo.StructFoo{$0\\}", "foo.StructFoo{$0\\}")
103605-}
103606diff -urN a/gopls/internal/lsp/testdata/unimported/unimported.go.in b/gopls/internal/lsp/testdata/unimported/unimported.go.in
103607--- a/gopls/internal/lsp/testdata/unimported/unimported.go.in	2000-01-01 00:00:00.000000000 -0000
103608+++ b/gopls/internal/lsp/testdata/unimported/unimported.go.in	1970-01-01 00:00:00.000000000 +0000
103609@@ -1,23 +0,0 @@
103610-package unimported
103611-
103612-func _() {
103613-	http //@unimported("p", nethttp)
103614-	// container/ring is extremely unlikely to be imported by anything, so shouldn't have type information.
103615-	ring.Ring     //@unimported("Ring", ringring)
103616-	signature.Foo //@unimported("Foo", signaturefoo)
103617-
103618-	context.Bac //@unimported(" //", contextBackground)
103619-}
103620-
103621-// Create markers for unimported std lib packages. Only for use by this test.
103622-/* http */ //@item(nethttp, "http", "\"net/http\"", "package")
103623-
103624-/* ring.Ring */ //@item(ringring, "Ring", "(from \"container/ring\")", "var")
103625-
103626-/* signature.Foo */ //@item(signaturefoo, "Foo", "func (from \"golang.org/lsptests/signature\")", "func")
103627-
103628-/* context.Background */ //@item(contextBackground, "Background", "func (from \"context\")", "func")
103629-
103630-// Now that we no longer type-check imported completions,
103631-// we don't expect the context.Background().Err method (see golang/go#58663).
103632-/* context.Background().Err */ //@item(contextBackgroundErr, "Background().Err", "func (from \"context\")", "method")
103633diff -urN a/gopls/internal/lsp/testdata/unimported/x_test.go b/gopls/internal/lsp/testdata/unimported/x_test.go
103634--- a/gopls/internal/lsp/testdata/unimported/x_test.go	2000-01-01 00:00:00.000000000 -0000
103635+++ b/gopls/internal/lsp/testdata/unimported/x_test.go	1970-01-01 00:00:00.000000000 +0000
103636@@ -1,9 +0,0 @@
103637-package unimported_test
103638-
103639-import (
103640-	"testing"
103641-)
103642-
103643-func TestSomething(t *testing.T) {
103644-	_ = unimported.TestExport //@unimported("TestExport", testexport)
103645-}
103646diff -urN a/gopls/internal/lsp/testdata/unresolved/unresolved.go.in b/gopls/internal/lsp/testdata/unresolved/unresolved.go.in
103647--- a/gopls/internal/lsp/testdata/unresolved/unresolved.go.in	2000-01-01 00:00:00.000000000 -0000
103648+++ b/gopls/internal/lsp/testdata/unresolved/unresolved.go.in	1970-01-01 00:00:00.000000000 +0000
103649@@ -1,6 +0,0 @@
103650-package unresolved
103651-
103652-func foo(interface{}) {
103653-	// don't crash on fake "resolved" type
103654-	foo(func(i, j f //@complete(" //")
103655-}
103656diff -urN a/gopls/internal/lsp/testdata/unsafe/unsafe.go b/gopls/internal/lsp/testdata/unsafe/unsafe.go
103657--- a/gopls/internal/lsp/testdata/unsafe/unsafe.go	2000-01-01 00:00:00.000000000 -0000
103658+++ b/gopls/internal/lsp/testdata/unsafe/unsafe.go	1970-01-01 00:00:00.000000000 +0000
103659@@ -1,13 +0,0 @@
103660-package unsafe
103661-
103662-import (
103663-	"unsafe"
103664-)
103665-
103666-// Pre-set this marker, as we don't have a "source" for it in this package.
103667-/* unsafe.Sizeof */ //@item(Sizeof, "Sizeof", "invalid type", "text")
103668-
103669-func _() {
103670-	x := struct{}{}
103671-	_ = unsafe.Sizeof(x) //@complete("z", Sizeof)
103672-}
103673diff -urN a/gopls/internal/lsp/testdata/variadic/variadic.go.in b/gopls/internal/lsp/testdata/variadic/variadic.go.in
103674--- a/gopls/internal/lsp/testdata/variadic/variadic.go.in	2000-01-01 00:00:00.000000000 -0000
103675+++ b/gopls/internal/lsp/testdata/variadic/variadic.go.in	1970-01-01 00:00:00.000000000 +0000
103676@@ -1,38 +0,0 @@
103677-package variadic
103678-
103679-func foo(i int, strs ...string) {}
103680-
103681-func bar() []string { //@item(vFunc, "bar", "func() []string", "func")
103682-	return nil
103683-}
103684-
103685-func _() {
103686-	var (
103687-		i  int        //@item(vInt, "i", "int", "var")
103688-		s  string     //@item(vStr, "s", "string", "var")
103689-		ss []string   //@item(vStrSlice, "ss", "[]string", "var")
103690-		v interface{} //@item(vIntf, "v", "interface{}", "var")
103691-	)
103692-
103693-	foo()           //@rank(")", vInt, vStr),rank(")", vInt, vStrSlice)
103694-	foo(123, )      //@rank(")", vStr, vInt),rank(")", vStrSlice, vInt)
103695-	foo(123, "", )  //@rank(")", vStr, vInt),rank(")", vStr, vStrSlice)
103696-	foo(123, s, "") //@rank(", \"", vStr, vStrSlice)
103697-
103698-  // snippet will add the "..." for you
103699-	foo(123, ) //@snippet(")", vStrSlice, "ss...", "ss..."),snippet(")", vFunc, "bar()...", "bar()..."),snippet(")", vStr, "s", "s")
103700-
103701-	// don't add "..." for interface{}
103702-	foo(123, ) //@snippet(")", vIntf, "v", "v")
103703-}
103704-
103705-func qux(...func()) {}
103706-func f()            {} //@item(vVarArg, "f", "func()", "func")
103707-
103708-func _() {
103709-	qux(f) //@snippet(")", vVarArg, "f", "f")
103710-}
103711-
103712-func _() {
103713-	foo(0, []string{}...) //@complete(")")
103714-}
103715diff -urN a/gopls/internal/lsp/testdata/variadic/variadic_intf.go b/gopls/internal/lsp/testdata/variadic/variadic_intf.go
103716--- a/gopls/internal/lsp/testdata/variadic/variadic_intf.go	2000-01-01 00:00:00.000000000 -0000
103717+++ b/gopls/internal/lsp/testdata/variadic/variadic_intf.go	1970-01-01 00:00:00.000000000 +0000
103718@@ -1,21 +0,0 @@
103719-package variadic
103720-
103721-type baz interface {
103722-	baz()
103723-}
103724-
103725-func wantsBaz(...baz) {}
103726-
103727-type bazImpl int
103728-
103729-func (bazImpl) baz() {}
103730-
103731-func _() {
103732-	var (
103733-		impls []bazImpl //@item(vImplSlice, "impls", "[]bazImpl", "var")
103734-		impl  bazImpl   //@item(vImpl, "impl", "bazImpl", "var")
103735-		bazes []baz     //@item(vIntfSlice, "bazes", "[]baz", "var")
103736-	)
103737-
103738-	wantsBaz() //@rank(")", vImpl, vImplSlice),rank(")", vIntfSlice, vImplSlice)
103739-}
103740diff -urN a/gopls/internal/lsp/testdata/workspacesymbol/a/a.go b/gopls/internal/lsp/testdata/workspacesymbol/a/a.go
103741--- a/gopls/internal/lsp/testdata/workspacesymbol/a/a.go	2000-01-01 00:00:00.000000000 -0000
103742+++ b/gopls/internal/lsp/testdata/workspacesymbol/a/a.go	1970-01-01 00:00:00.000000000 +0000
103743@@ -1,9 +0,0 @@
103744-package a
103745-
103746-var RandomGopherVariableA = "a"
103747-
103748-const RandomGopherConstantA = "a"
103749-
103750-const (
103751-	randomgopherinvariable = iota
103752-)
103753diff -urN a/gopls/internal/lsp/testdata/workspacesymbol/a/a_test.go b/gopls/internal/lsp/testdata/workspacesymbol/a/a_test.go
103754--- a/gopls/internal/lsp/testdata/workspacesymbol/a/a_test.go	2000-01-01 00:00:00.000000000 -0000
103755+++ b/gopls/internal/lsp/testdata/workspacesymbol/a/a_test.go	1970-01-01 00:00:00.000000000 +0000
103756@@ -1,3 +0,0 @@
103757-package a
103758-
103759-var RandomGopherTestVariableA = "a"
103760diff -urN a/gopls/internal/lsp/testdata/workspacesymbol/a/a_x_test.go b/gopls/internal/lsp/testdata/workspacesymbol/a/a_x_test.go
103761--- a/gopls/internal/lsp/testdata/workspacesymbol/a/a_x_test.go	2000-01-01 00:00:00.000000000 -0000
103762+++ b/gopls/internal/lsp/testdata/workspacesymbol/a/a_x_test.go	1970-01-01 00:00:00.000000000 +0000
103763@@ -1,3 +0,0 @@
103764-package a_test
103765-
103766-var RandomGopherXTestVariableA = "a"
103767diff -urN a/gopls/internal/lsp/testdata/workspacesymbol/b/b.go b/gopls/internal/lsp/testdata/workspacesymbol/b/b.go
103768--- a/gopls/internal/lsp/testdata/workspacesymbol/b/b.go	2000-01-01 00:00:00.000000000 -0000
103769+++ b/gopls/internal/lsp/testdata/workspacesymbol/b/b.go	1970-01-01 00:00:00.000000000 +0000
103770@@ -1,7 +0,0 @@
103771-package b
103772-
103773-var RandomGopherVariableB = "b"
103774-
103775-type RandomGopherStructB struct {
103776-	Bar int
103777-}
103778diff -urN a/gopls/internal/lsp/testdata/workspacesymbol/issue44806.go b/gopls/internal/lsp/testdata/workspacesymbol/issue44806.go
103779--- a/gopls/internal/lsp/testdata/workspacesymbol/issue44806.go	2000-01-01 00:00:00.000000000 -0000
103780+++ b/gopls/internal/lsp/testdata/workspacesymbol/issue44806.go	1970-01-01 00:00:00.000000000 +0000
103781@@ -1,10 +0,0 @@
103782-package main
103783-
103784-type T struct{}
103785-
103786-// We should accept all valid receiver syntax when scanning symbols.
103787-func (*(T)) m1() {}
103788-func (*T) m2()   {}
103789-func (T) m3()    {}
103790-func ((T)) m4()    {}
103791-func ((*T)) m5()   {}
103792diff -urN a/gopls/internal/lsp/testdata/workspacesymbol/main.go b/gopls/internal/lsp/testdata/workspacesymbol/main.go
103793--- a/gopls/internal/lsp/testdata/workspacesymbol/main.go	2000-01-01 00:00:00.000000000 -0000
103794+++ b/gopls/internal/lsp/testdata/workspacesymbol/main.go	1970-01-01 00:00:00.000000000 +0000
103795@@ -1,47 +0,0 @@
103796-package main
103797-
103798-import (
103799-	"encoding/json"
103800-	"fmt"
103801-)
103802-
103803-func main() { // function
103804-	fmt.Println("Hello")
103805-}
103806-
103807-var myvar int // variable
103808-
103809-type myType string // basic type
103810-
103811-type myDecoder json.Decoder // to use the encoding/json import
103812-
103813-func (m *myType) Blahblah() {} // method
103814-
103815-type myStruct struct { // struct type
103816-	myStructField int // struct field
103817-}
103818-
103819-type myInterface interface { // interface
103820-	DoSomeCoolStuff() string // interface method
103821-}
103822-
103823-type embed struct {
103824-	myStruct
103825-
103826-	nestedStruct struct {
103827-		nestedField int
103828-
103829-		nestedStruct2 struct {
103830-			int
103831-		}
103832-	}
103833-
103834-	nestedInterface interface {
103835-		myInterface
103836-		nestedMethod()
103837-	}
103838-}
103839-
103840-func Dunk() int { return 0 }
103841-
103842-func dunk() {}
103843diff -urN a/gopls/internal/lsp/testdata/workspacesymbol/p/p.go b/gopls/internal/lsp/testdata/workspacesymbol/p/p.go
103844--- a/gopls/internal/lsp/testdata/workspacesymbol/p/p.go	2000-01-01 00:00:00.000000000 -0000
103845+++ b/gopls/internal/lsp/testdata/workspacesymbol/p/p.go	1970-01-01 00:00:00.000000000 +0000
103846@@ -1,3 +0,0 @@
103847-package p
103848-
103849-const Message = "Hello World." // constant
103850diff -urN a/gopls/internal/lsp/testdata/workspacesymbol/query.go b/gopls/internal/lsp/testdata/workspacesymbol/query.go
103851--- a/gopls/internal/lsp/testdata/workspacesymbol/query.go	2000-01-01 00:00:00.000000000 -0000
103852+++ b/gopls/internal/lsp/testdata/workspacesymbol/query.go	1970-01-01 00:00:00.000000000 +0000
103853@@ -1,29 +0,0 @@
103854-package main
103855-
103856-// Contains all of the workspace symbol queries.
103857-
103858-// -- Fuzzy matching --
103859-//@workspacesymbolfuzzy("rgop")
103860-//@workspacesymbolfuzzy("randoma")
103861-//@workspacesymbolfuzzy("randomb")
103862-
103863-// -- Case sensitive --
103864-//@workspacesymbolcasesensitive("main.main")
103865-//@workspacesymbolcasesensitive("p.Message")
103866-//@workspacesymbolcasesensitive("main.myvar")
103867-//@workspacesymbolcasesensitive("main.myType")
103868-//@workspacesymbolcasesensitive("main.myType.Blahblah")
103869-//@workspacesymbolcasesensitive("main.myStruct")
103870-//@workspacesymbolcasesensitive("main.myStruct.myStructField")
103871-//@workspacesymbolcasesensitive("main.myInterface")
103872-//@workspacesymbolcasesensitive("main.myInterface.DoSomeCoolStuff")
103873-//@workspacesymbolcasesensitive("main.embed.myStruct")
103874-//@workspacesymbolcasesensitive("main.embed.nestedStruct.nestedStruct2.int")
103875-//@workspacesymbolcasesensitive("main.embed.nestedInterface.myInterface")
103876-//@workspacesymbolcasesensitive("main.embed.nestedInterface.nestedMethod")
103877-//@workspacesymbolcasesensitive("dunk")
103878-//@workspacesymbolcasesensitive("Dunk")
103879-
103880-// -- Standard --
103881-//@workspacesymbol("")
103882-//@workspacesymbol("randomgophervar")
103883diff -urN a/gopls/internal/lsp/testdata/workspacesymbol/query.go.golden b/gopls/internal/lsp/testdata/workspacesymbol/query.go.golden
103884--- a/gopls/internal/lsp/testdata/workspacesymbol/query.go.golden	2000-01-01 00:00:00.000000000 -0000
103885+++ b/gopls/internal/lsp/testdata/workspacesymbol/query.go.golden	1970-01-01 00:00:00.000000000 +0000
103886@@ -1,83 +0,0 @@
103887--- workspace_symbol-caseinsensitive- --
103888-
103889-
103890--- workspace_symbol-caseinsensitive-randomgophervar --
103891-workspacesymbol/a/a.go:3:5-26 RandomGopherVariableA Variable
103892-workspacesymbol/b/b.go:3:5-26 RandomGopherVariableB Variable
103893-
103894--- workspace_symbol-casesensitive-Dunk --
103895-workspacesymbol/main.go:45:6-10 Dunk Function
103896-
103897--- workspace_symbol-casesensitive-dunk --
103898-workspacesymbol/main.go:47:6-10 dunk Function
103899-
103900--- workspace_symbol-casesensitive-main.embed.myStruct --
103901-workspacesymbol/main.go:29:2-10 main.embed.myStruct Field
103902-
103903--- workspace_symbol-casesensitive-main.embed.nestedInterface.myInterface --
103904-workspacesymbol/main.go:40:3-14 main.embed.nestedInterface.myInterface Interface
103905-
103906--- workspace_symbol-casesensitive-main.embed.nestedInterface.nestedMethod --
103907-workspacesymbol/main.go:41:3-15 main.embed.nestedInterface.nestedMethod Method
103908-
103909--- workspace_symbol-casesensitive-main.embed.nestedStruct.nestedStruct2.int --
103910-workspacesymbol/main.go:35:4-7 main.embed.nestedStruct.nestedStruct2.int Field
103911-
103912--- workspace_symbol-casesensitive-main.main --
103913-workspacesymbol/main.go:8:6-10 main.main Function
103914-
103915--- workspace_symbol-casesensitive-main.myInterface --
103916-workspacesymbol/main.go:24:6-17 main.myInterface Interface
103917-workspacesymbol/main.go:25:2-17 main.myInterface.DoSomeCoolStuff Method
103918-
103919--- workspace_symbol-casesensitive-main.myInterface.DoSomeCoolStuff --
103920-workspacesymbol/main.go:25:2-17 main.myInterface.DoSomeCoolStuff Method
103921-
103922--- workspace_symbol-casesensitive-main.myStruct --
103923-workspacesymbol/main.go:20:6-14 main.myStruct Struct
103924-workspacesymbol/main.go:21:2-15 main.myStruct.myStructField Field
103925-
103926--- workspace_symbol-casesensitive-main.myStruct.myStructField --
103927-workspacesymbol/main.go:21:2-15 main.myStruct.myStructField Field
103928-
103929--- workspace_symbol-casesensitive-main.myType --
103930-workspacesymbol/main.go:14:6-12 main.myType Class
103931-workspacesymbol/main.go:18:18-26 main.myType.Blahblah Method
103932-
103933--- workspace_symbol-casesensitive-main.myType.Blahblah --
103934-workspacesymbol/main.go:18:18-26 main.myType.Blahblah Method
103935-
103936--- workspace_symbol-casesensitive-main.myvar --
103937-workspacesymbol/main.go:12:5-10 main.myvar Variable
103938-
103939--- workspace_symbol-casesensitive-p.Message --
103940-workspacesymbol/p/p.go:3:7-14 p.Message Constant
103941-
103942--- workspace_symbol-fuzzy-randoma --
103943-workspacesymbol/a/a.go:3:5-26 RandomGopherVariableA Variable
103944-workspacesymbol/a/a.go:5:7-28 RandomGopherConstantA Constant
103945-workspacesymbol/a/a.go:8:2-24 randomgopherinvariable Constant
103946-workspacesymbol/a/a_test.go:3:5-30 RandomGopherTestVariableA Variable
103947-workspacesymbol/a/a_x_test.go:3:5-31 RandomGopherXTestVariableA Variable
103948-workspacesymbol/b/b.go:3:5-26 RandomGopherVariableB Variable
103949-workspacesymbol/b/b.go:6:2-5 RandomGopherStructB.Bar Field
103950-
103951--- workspace_symbol-fuzzy-randomb --
103952-workspacesymbol/a/a.go:3:5-26 RandomGopherVariableA Variable
103953-workspacesymbol/a/a.go:8:2-24 randomgopherinvariable Constant
103954-workspacesymbol/a/a_test.go:3:5-30 RandomGopherTestVariableA Variable
103955-workspacesymbol/a/a_x_test.go:3:5-31 RandomGopherXTestVariableA Variable
103956-workspacesymbol/b/b.go:3:5-26 RandomGopherVariableB Variable
103957-workspacesymbol/b/b.go:5:6-25 RandomGopherStructB Struct
103958-workspacesymbol/b/b.go:6:2-5 RandomGopherStructB.Bar Field
103959-
103960--- workspace_symbol-fuzzy-rgop --
103961-workspacesymbol/a/a.go:3:5-26 RandomGopherVariableA Variable
103962-workspacesymbol/a/a.go:5:7-28 RandomGopherConstantA Constant
103963-workspacesymbol/a/a.go:8:2-24 randomgopherinvariable Constant
103964-workspacesymbol/a/a_test.go:3:5-30 RandomGopherTestVariableA Variable
103965-workspacesymbol/a/a_x_test.go:3:5-31 RandomGopherXTestVariableA Variable
103966-workspacesymbol/b/b.go:3:5-26 RandomGopherVariableB Variable
103967-workspacesymbol/b/b.go:5:6-25 RandomGopherStructB Struct
103968-workspacesymbol/b/b.go:6:2-5 RandomGopherStructB.Bar Field
103969-
103970diff -urN a/gopls/internal/lsp/tests/compare/text.go b/gopls/internal/lsp/tests/compare/text.go
103971--- a/gopls/internal/lsp/tests/compare/text.go	2000-01-01 00:00:00.000000000 -0000
103972+++ b/gopls/internal/lsp/tests/compare/text.go	1970-01-01 00:00:00.000000000 +0000
103973@@ -1,49 +0,0 @@
103974-// Copyright 2022 The Go Authors. All rights reserved.
103975-// Use of this source code is governed by a BSD-style
103976-// license that can be found in the LICENSE file.
103977-
103978-package compare
103979-
103980-import (
103981-	"bytes"
103982-
103983-	"golang.org/x/tools/internal/diff"
103984-)
103985-
103986-// Text returns a formatted unified diff of the edits to go from want to
103987-// got, returning "" if and only if want == got.
103988-//
103989-// This function is intended for use in testing, and panics if any error occurs
103990-// while computing the diff. It is not sufficiently tested for production use.
103991-func Text(want, got string) string {
103992-	return NamedText("want", "got", want, got)
103993-}
103994-
103995-// NamedText is like text, but allows passing custom names of the 'want' and
103996-// 'got' content.
103997-func NamedText(wantName, gotName, want, got string) string {
103998-	if want == got {
103999-		return ""
104000-	}
104001-
104002-	// Add newlines to avoid verbose newline messages ("No newline at end of file").
104003-	unified := diff.Unified(wantName, gotName, want+"\n", got+"\n")
104004-
104005-	// Defensively assert that we get an actual diff, so that we guarantee the
104006-	// invariant that we return "" if and only if want == got.
104007-	//
104008-	// This is probably unnecessary, but convenient.
104009-	if unified == "" {
104010-		panic("empty diff for non-identical input")
104011-	}
104012-
104013-	return unified
104014-}
104015-
104016-// Bytes is like Text but using byte slices.
104017-func Bytes(want, got []byte) string {
104018-	if bytes.Equal(want, got) {
104019-		return "" // common case
104020-	}
104021-	return Text(string(want), string(got))
104022-}
104023diff -urN a/gopls/internal/lsp/tests/compare/text_test.go b/gopls/internal/lsp/tests/compare/text_test.go
104024--- a/gopls/internal/lsp/tests/compare/text_test.go	2000-01-01 00:00:00.000000000 -0000
104025+++ b/gopls/internal/lsp/tests/compare/text_test.go	1970-01-01 00:00:00.000000000 +0000
104026@@ -1,28 +0,0 @@
104027-// Copyright 2022 The Go Authors. All rights reserved.
104028-// Use of this source code is governed by a BSD-style
104029-// license that can be found in the LICENSE file.
104030-
104031-package compare_test
104032-
104033-import (
104034-	"testing"
104035-
104036-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
104037-)
104038-
104039-func TestText(t *testing.T) {
104040-	tests := []struct {
104041-		got, want, wantDiff string
104042-	}{
104043-		{"", "", ""},
104044-		{"equal", "equal", ""},
104045-		{"a", "b", "--- want\n+++ got\n@@ -1 +1 @@\n-b\n+a\n"},
104046-		{"a\nd\nc\n", "a\nb\nc\n", "--- want\n+++ got\n@@ -1,4 +1,4 @@\n a\n-b\n+d\n c\n \n"},
104047-	}
104048-
104049-	for _, test := range tests {
104050-		if gotDiff := compare.Text(test.want, test.got); gotDiff != test.wantDiff {
104051-			t.Errorf("compare.Text(%q, %q) =\n%q, want\n%q", test.want, test.got, gotDiff, test.wantDiff)
104052-		}
104053-	}
104054-}
104055diff -urN a/gopls/internal/lsp/tests/markdown_go118.go b/gopls/internal/lsp/tests/markdown_go118.go
104056--- a/gopls/internal/lsp/tests/markdown_go118.go	2000-01-01 00:00:00.000000000 -0000
104057+++ b/gopls/internal/lsp/tests/markdown_go118.go	1970-01-01 00:00:00.000000000 +0000
104058@@ -1,69 +0,0 @@
104059-// Copyright 2022 The Go Authors. All rights reserved.
104060-// Use of this source code is governed by a BSD-style
104061-// license that can be found in the LICENSE file.
104062-
104063-//go:build !go1.19
104064-// +build !go1.19
104065-
104066-package tests
104067-
104068-import (
104069-	"regexp"
104070-	"strings"
104071-
104072-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
104073-)
104074-
104075-// DiffMarkdown compares two markdown strings produced by parsing go doc
104076-// comments.
104077-//
104078-// For go1.19 and later, markdown conversion is done using go/doc/comment.
104079-// Compared to the newer version, the older version has extra escapes, and
104080-// treats code blocks slightly differently.
104081-func DiffMarkdown(want, got string) string {
104082-	want = normalizeMarkdown(want)
104083-	got = normalizeMarkdown(got)
104084-	return compare.Text(want, got)
104085-}
104086-
104087-// normalizeMarkdown normalizes whitespace and escaping of the input string, to
104088-// eliminate differences between the Go 1.18 and Go 1.19 generated markdown for
104089-// doc comments. Note that it does not normalize to either the 1.18 or 1.19
104090-// formatting: it simplifies both so that they may be compared.
104091-//
104092-// This function may need to be adjusted as we encounter more differences in
104093-// the generated text.
104094-//
104095-// TODO(rfindley): this function doesn't correctly handle the case of
104096-// multi-line docstrings.
104097-func normalizeMarkdown(input string) string {
104098-	input = strings.TrimSpace(input)
104099-
104100-	// For simplicity, eliminate blank lines.
104101-	input = regexp.MustCompile("\n+").ReplaceAllString(input, "\n")
104102-
104103-	// Replace common escaped characters with their unescaped version.
104104-	//
104105-	// This list may not be exhaustive: it was just sufficient to make tests
104106-	// pass.
104107-	input = strings.NewReplacer(
104108-		`\\`, ``,
104109-		`\@`, `@`,
104110-		`\(`, `(`,
104111-		`\)`, `)`,
104112-		`\{`, `{`,
104113-		`\}`, `}`,
104114-		`\"`, `"`,
104115-		`\.`, `.`,
104116-		`\-`, `-`,
104117-		`\'`, `'`,
104118-		`\+`, `+`,
104119-		`\~`, `~`,
104120-		`\=`, `=`,
104121-		`\:`, `:`,
104122-		`\?`, `?`,
104123-		`\n\n\n`, `\n\n`, // Note that these are *escaped* newlines.
104124-	).Replace(input)
104125-
104126-	return input
104127-}
104128diff -urN a/gopls/internal/lsp/tests/markdown_go119.go b/gopls/internal/lsp/tests/markdown_go119.go
104129--- a/gopls/internal/lsp/tests/markdown_go119.go	2000-01-01 00:00:00.000000000 -0000
104130+++ b/gopls/internal/lsp/tests/markdown_go119.go	1970-01-01 00:00:00.000000000 +0000
104131@@ -1,22 +0,0 @@
104132-// Copyright 2022 The Go Authors. All rights reserved.
104133-// Use of this source code is governed by a BSD-style
104134-// license that can be found in the LICENSE file.
104135-
104136-//go:build go1.19
104137-// +build go1.19
104138-
104139-package tests
104140-
104141-import (
104142-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
104143-)
104144-
104145-// DiffMarkdown compares two markdown strings produced by parsing go doc
104146-// comments.
104147-//
104148-// For go1.19 and later, markdown conversion is done using go/doc/comment.
104149-// Compared to the newer version, the older version has extra escapes, and
104150-// treats code blocks slightly differently.
104151-func DiffMarkdown(want, got string) string {
104152-	return compare.Text(want, got)
104153-}
104154diff -urN a/gopls/internal/lsp/tests/normalizer.go b/gopls/internal/lsp/tests/normalizer.go
104155--- a/gopls/internal/lsp/tests/normalizer.go	2000-01-01 00:00:00.000000000 -0000
104156+++ b/gopls/internal/lsp/tests/normalizer.go	1970-01-01 00:00:00.000000000 +0000
104157@@ -1,113 +0,0 @@
104158-// Copyright 2019 The Go Authors. All rights reserved.
104159-// Use of this source code is governed by a BSD-style
104160-// license that can be found in the LICENSE file.
104161-
104162-package tests
104163-
104164-import (
104165-	"path/filepath"
104166-	"strconv"
104167-	"strings"
104168-
104169-	"golang.org/x/tools/go/packages/packagestest"
104170-)
104171-
104172-type Normalizer struct {
104173-	path     string
104174-	slashed  string
104175-	escaped  string
104176-	fragment string
104177-}
104178-
104179-func CollectNormalizers(exported *packagestest.Exported) []Normalizer {
104180-	// build the path normalizing patterns
104181-	var normalizers []Normalizer
104182-	for _, m := range exported.Modules {
104183-		for fragment := range m.Files {
104184-			n := Normalizer{
104185-				path:     exported.File(m.Name, fragment),
104186-				fragment: fragment,
104187-			}
104188-			if n.slashed = filepath.ToSlash(n.path); n.slashed == n.path {
104189-				n.slashed = ""
104190-			}
104191-			quoted := strconv.Quote(n.path)
104192-			if n.escaped = quoted[1 : len(quoted)-1]; n.escaped == n.path {
104193-				n.escaped = ""
104194-			}
104195-			normalizers = append(normalizers, n)
104196-		}
104197-	}
104198-	return normalizers
104199-}
104200-
104201-// Normalize replaces all paths present in s with just the fragment portion
104202-// this is used to make golden files not depend on the temporary paths of the files
104203-func Normalize(s string, normalizers []Normalizer) string {
104204-	type entry struct {
104205-		path     string
104206-		index    int
104207-		fragment string
104208-	}
104209-	var match []entry
104210-	// collect the initial state of all the matchers
104211-	for _, n := range normalizers {
104212-		index := strings.Index(s, n.path)
104213-		if index >= 0 {
104214-			match = append(match, entry{n.path, index, n.fragment})
104215-		}
104216-		if n.slashed != "" {
104217-			index := strings.Index(s, n.slashed)
104218-			if index >= 0 {
104219-				match = append(match, entry{n.slashed, index, n.fragment})
104220-			}
104221-		}
104222-		if n.escaped != "" {
104223-			index := strings.Index(s, n.escaped)
104224-			if index >= 0 {
104225-				match = append(match, entry{n.escaped, index, n.fragment})
104226-			}
104227-		}
104228-	}
104229-	// result should be the same or shorter than the input
104230-	var b strings.Builder
104231-	last := 0
104232-	for {
104233-		// find the nearest path match to the start of the buffer
104234-		next := -1
104235-		nearest := len(s)
104236-		for i, c := range match {
104237-			if c.index >= 0 && nearest > c.index {
104238-				nearest = c.index
104239-				next = i
104240-			}
104241-		}
104242-		// if there are no matches, we copy the rest of the string and are done
104243-		if next < 0 {
104244-			b.WriteString(s[last:])
104245-			return b.String()
104246-		}
104247-		// we have a match
104248-		n := &match[next]
104249-		// copy up to the start of the match
104250-		b.WriteString(s[last:n.index])
104251-		// skip over the filename
104252-		last = n.index + len(n.path)
104253-
104254-		// Hack: In multi-module mode, we add a "testmodule/" prefix, so trim
104255-		// it from the fragment.
104256-		fragment := n.fragment
104257-		if strings.HasPrefix(fragment, "testmodule") {
104258-			split := strings.Split(filepath.ToSlash(fragment), "/")
104259-			fragment = filepath.FromSlash(strings.Join(split[1:], "/"))
104260-		}
104261-
104262-		// add in the fragment instead
104263-		b.WriteString(fragment)
104264-		// see what the next match for this path is
104265-		n.index = strings.Index(s[last:], n.path)
104266-		if n.index >= 0 {
104267-			n.index += last
104268-		}
104269-	}
104270-}
104271diff -urN a/gopls/internal/lsp/tests/README.md b/gopls/internal/lsp/tests/README.md
104272--- a/gopls/internal/lsp/tests/README.md	2000-01-01 00:00:00.000000000 -0000
104273+++ b/gopls/internal/lsp/tests/README.md	1970-01-01 00:00:00.000000000 +0000
104274@@ -1,66 +0,0 @@
104275-# Testing
104276-
104277-LSP has "marker tests" defined in `internal/lsp/testdata`, as well as
104278-traditional tests.
104279-
104280-## Marker tests
104281-
104282-Marker tests have a standard input file, like
104283-`internal/lsp/testdata/foo/bar.go`, and some may have a corresponding golden
104284-file, like `internal/lsp/testdata/foo/bar.go.golden`. The former is the "input"
104285-and the latter is the expected output.
104286-
104287-Each input file contains annotations like
104288-`//@suggestedfix("}", "refactor.rewrite", "Fill anonymous struct")`. These annotations are interpreted by
104289-test runners to perform certain actions. The expected output after those actions
104290-is encoded in the golden file.
104291-
104292-When tests are run, each annotation results in a new subtest, which is encoded
104293-in the golden file with a heading like,
104294-
104295-```bash
104296--- suggestedfix_bar_11_21 --
104297-// expected contents go here
104298--- suggestedfix_bar_13_20 --
104299-// expected contents go here
104300-```
104301-
104302-The format of these headings vary: they are defined by the
104303-[`Golden`](https://pkg.go.dev/golang.org/x/tools/gopls/internal/lsp/tests#Data.Golden)
104304-function for each annotation. In the case above, the format is: annotation
104305-name, file name, annotation line location, annotation character location.
104306-
104307-So, if `internal/lsp/testdata/foo/bar.go` has three `suggestedfix` annotations,
104308-the golden file should have three headers with `suggestedfix_bar_xx_yy`
104309-headings.
104310-
104311-To see a list of all available annotations, see the exported "expectations" in
104312-[tests.go](https://github.com/golang/tools/blob/299f270db45902e93469b1152fafed034bb3f033/internal/lsp/tests/tests.go#L418-L447).
104313-
104314-To run marker tests,
104315-
104316-```bash
104317-cd /path/to/tools
104318-
104319-# The marker tests are located in "internal/lsp", "internal/lsp/cmd, and
104320-# "internal/lsp/source".
104321-go test ./internal/lsp/...
104322-```
104323-
104324-There are quite a lot of marker tests, so to run one individually, pass the test
104325-path and heading into a -run argument:
104326-
104327-```bash
104328-cd /path/to/tools
104329-go test ./internal/lsp/... -v -run TestLSP/Modules/SuggestedFix/bar_11_21
104330-```
104331-
104332-## Resetting marker tests
104333-
104334-Sometimes, a change is made to lsp that requires a change to multiple golden
104335-files. When this happens, you can run,
104336-
104337-```bash
104338-cd /path/to/tools
104339-./internal/lsp/reset_golden.sh
104340-```
104341diff -urN a/gopls/internal/lsp/tests/tests.go b/gopls/internal/lsp/tests/tests.go
104342--- a/gopls/internal/lsp/tests/tests.go	2000-01-01 00:00:00.000000000 -0000
104343+++ b/gopls/internal/lsp/tests/tests.go	1970-01-01 00:00:00.000000000 +0000
104344@@ -1,1446 +0,0 @@
104345-// Copyright 2019 The Go Authors. All rights reserved.
104346-// Use of this source code is governed by a BSD-style
104347-// license that can be found in the LICENSE file.
104348-
104349-// Package tests exports functionality to be used across a variety of gopls tests.
104350-package tests
104351-
104352-import (
104353-	"bytes"
104354-	"context"
104355-	"flag"
104356-	"fmt"
104357-	"go/ast"
104358-	"go/token"
104359-	"io"
104360-	"io/ioutil"
104361-	"os"
104362-	"path/filepath"
104363-	"regexp"
104364-	"sort"
104365-	"strconv"
104366-	"strings"
104367-	"sync"
104368-	"testing"
104369-	"time"
104370-
104371-	"golang.org/x/tools/go/expect"
104372-	"golang.org/x/tools/go/packages"
104373-	"golang.org/x/tools/go/packages/packagestest"
104374-	"golang.org/x/tools/gopls/internal/lsp/command"
104375-	"golang.org/x/tools/gopls/internal/lsp/protocol"
104376-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
104377-	"golang.org/x/tools/gopls/internal/lsp/source"
104378-	"golang.org/x/tools/gopls/internal/lsp/source/completion"
104379-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
104380-	"golang.org/x/tools/gopls/internal/span"
104381-	"golang.org/x/tools/internal/testenv"
104382-	"golang.org/x/tools/internal/typeparams"
104383-	"golang.org/x/tools/txtar"
104384-)
104385-
104386-const (
104387-	overlayFileSuffix = ".overlay"
104388-	goldenFileSuffix  = ".golden"
104389-	inFileSuffix      = ".in"
104390-
104391-	// The module path containing the testdata packages.
104392-	//
104393-	// Warning: the length of this module path matters, as we have bumped up
104394-	// against command-line limitations on windows (golang/go#54800).
104395-	testModule = "golang.org/lsptests"
104396-)
104397-
104398-var summaryFile = "summary.txt"
104399-
104400-func init() {
104401-	if typeparams.Enabled {
104402-		summaryFile = "summary_go1.18.txt"
104403-	}
104404-}
104405-
104406-var UpdateGolden = flag.Bool("golden", false, "Update golden files")
104407-
104408-// These type names apparently avoid the need to repeat the
104409-// type in the field name and the make() expression.
104410-type CallHierarchy = map[span.Span]*CallHierarchyResult
104411-type CodeLens = map[span.URI][]protocol.CodeLens
104412-type Diagnostics = map[span.URI][]*source.Diagnostic
104413-type CompletionItems = map[token.Pos]*completion.CompletionItem
104414-type Completions = map[span.Span][]Completion
104415-type CompletionSnippets = map[span.Span][]CompletionSnippet
104416-type UnimportedCompletions = map[span.Span][]Completion
104417-type DeepCompletions = map[span.Span][]Completion
104418-type FuzzyCompletions = map[span.Span][]Completion
104419-type CaseSensitiveCompletions = map[span.Span][]Completion
104420-type RankCompletions = map[span.Span][]Completion
104421-type FoldingRanges = []span.Span
104422-type Formats = []span.Span
104423-type Imports = []span.Span
104424-type SemanticTokens = []span.Span
104425-type SuggestedFixes = map[span.Span][]SuggestedFix
104426-type FunctionExtractions = map[span.Span]span.Span
104427-type MethodExtractions = map[span.Span]span.Span
104428-type Definitions = map[span.Span]Definition
104429-type Implementations = map[span.Span][]span.Span
104430-type Highlights = map[span.Span][]span.Span
104431-type References = map[span.Span][]span.Span
104432-type Renames = map[span.Span]string
104433-type PrepareRenames = map[span.Span]*source.PrepareItem
104434-type Symbols = map[span.URI][]*symbol
104435-type InlayHints = []span.Span
104436-type WorkspaceSymbols = map[WorkspaceSymbolsTestType]map[span.URI][]string
104437-type Signatures = map[span.Span]*protocol.SignatureHelp
104438-type Links = map[span.URI][]Link
104439-type AddImport = map[span.URI]string
104440-type SelectionRanges = []span.Span
104441-
104442-type Data struct {
104443-	Config                   packages.Config
104444-	Exported                 *packagestest.Exported
104445-	CallHierarchy            CallHierarchy
104446-	CodeLens                 CodeLens
104447-	Diagnostics              Diagnostics
104448-	CompletionItems          CompletionItems
104449-	Completions              Completions
104450-	CompletionSnippets       CompletionSnippets
104451-	UnimportedCompletions    UnimportedCompletions
104452-	DeepCompletions          DeepCompletions
104453-	FuzzyCompletions         FuzzyCompletions
104454-	CaseSensitiveCompletions CaseSensitiveCompletions
104455-	RankCompletions          RankCompletions
104456-	FoldingRanges            FoldingRanges
104457-	Formats                  Formats
104458-	Imports                  Imports
104459-	SemanticTokens           SemanticTokens
104460-	SuggestedFixes           SuggestedFixes
104461-	FunctionExtractions      FunctionExtractions
104462-	MethodExtractions        MethodExtractions
104463-	Definitions              Definitions
104464-	Implementations          Implementations
104465-	Highlights               Highlights
104466-	References               References
104467-	Renames                  Renames
104468-	InlayHints               InlayHints
104469-	PrepareRenames           PrepareRenames
104470-	Symbols                  Symbols
104471-	WorkspaceSymbols         WorkspaceSymbols
104472-	Signatures               Signatures
104473-	Links                    Links
104474-	AddImport                AddImport
104475-	SelectionRanges          SelectionRanges
104476-
104477-	fragments map[string]string
104478-	dir       string
104479-	golden    map[string]*Golden
104480-	mode      string
104481-
104482-	ModfileFlagAvailable bool
104483-
104484-	mappersMu sync.Mutex
104485-	mappers   map[span.URI]*protocol.Mapper
104486-}
104487-
104488-// The Tests interface abstracts the LSP-based implementation of the marker
104489-// test operators (such as @codelens) appearing in files beneath ../testdata/.
104490-//
104491-// TODO(adonovan): reduce duplication; see https://github.com/golang/go/issues/54845.
104492-// There is only one implementation (*runner in ../lsp_test.go), so
104493-// we can abolish the interface now.
104494-type Tests interface {
104495-	CallHierarchy(*testing.T, span.Span, *CallHierarchyResult)
104496-	CodeLens(*testing.T, span.URI, []protocol.CodeLens)
104497-	Diagnostics(*testing.T, span.URI, []*source.Diagnostic)
104498-	Completion(*testing.T, span.Span, Completion, CompletionItems)
104499-	CompletionSnippet(*testing.T, span.Span, CompletionSnippet, bool, CompletionItems)
104500-	UnimportedCompletion(*testing.T, span.Span, Completion, CompletionItems)
104501-	DeepCompletion(*testing.T, span.Span, Completion, CompletionItems)
104502-	FuzzyCompletion(*testing.T, span.Span, Completion, CompletionItems)
104503-	CaseSensitiveCompletion(*testing.T, span.Span, Completion, CompletionItems)
104504-	RankCompletion(*testing.T, span.Span, Completion, CompletionItems)
104505-	FoldingRanges(*testing.T, span.Span)
104506-	Format(*testing.T, span.Span)
104507-	Import(*testing.T, span.Span)
104508-	SemanticTokens(*testing.T, span.Span)
104509-	SuggestedFix(*testing.T, span.Span, []SuggestedFix, int)
104510-	FunctionExtraction(*testing.T, span.Span, span.Span)
104511-	MethodExtraction(*testing.T, span.Span, span.Span)
104512-	Definition(*testing.T, span.Span, Definition)
104513-	Implementation(*testing.T, span.Span, []span.Span)
104514-	Highlight(*testing.T, span.Span, []span.Span)
104515-	InlayHints(*testing.T, span.Span)
104516-	References(*testing.T, span.Span, []span.Span)
104517-	Rename(*testing.T, span.Span, string)
104518-	PrepareRename(*testing.T, span.Span, *source.PrepareItem)
104519-	Symbols(*testing.T, span.URI, []protocol.DocumentSymbol)
104520-	WorkspaceSymbols(*testing.T, span.URI, string, WorkspaceSymbolsTestType)
104521-	SignatureHelp(*testing.T, span.Span, *protocol.SignatureHelp)
104522-	Link(*testing.T, span.URI, []Link)
104523-	AddImport(*testing.T, span.URI, string)
104524-	SelectionRanges(*testing.T, span.Span)
104525-}
104526-
104527-type Definition struct {
104528-	Name      string
104529-	IsType    bool
104530-	OnlyHover bool
104531-	Src, Def  span.Span
104532-}
104533-
104534-type CompletionTestType int
104535-
104536-const (
104537-	// Default runs the standard completion tests.
104538-	CompletionDefault = CompletionTestType(iota)
104539-
104540-	// Unimported tests the autocompletion of unimported packages.
104541-	CompletionUnimported
104542-
104543-	// Deep tests deep completion.
104544-	CompletionDeep
104545-
104546-	// Fuzzy tests deep completion and fuzzy matching.
104547-	CompletionFuzzy
104548-
104549-	// CaseSensitive tests case sensitive completion.
104550-	CompletionCaseSensitive
104551-
104552-	// CompletionRank candidates in test must be valid and in the right relative order.
104553-	CompletionRank
104554-)
104555-
104556-type WorkspaceSymbolsTestType int
104557-
104558-const (
104559-	// Default runs the standard workspace symbols tests.
104560-	WorkspaceSymbolsDefault = WorkspaceSymbolsTestType(iota)
104561-
104562-	// Fuzzy tests workspace symbols with fuzzy matching.
104563-	WorkspaceSymbolsFuzzy
104564-
104565-	// CaseSensitive tests workspace symbols with case sensitive.
104566-	WorkspaceSymbolsCaseSensitive
104567-)
104568-
104569-type Completion struct {
104570-	CompletionItems []token.Pos
104571-}
104572-
104573-type CompletionSnippet struct {
104574-	CompletionItem     token.Pos
104575-	PlainSnippet       string
104576-	PlaceholderSnippet string
104577-}
104578-
104579-type CallHierarchyResult struct {
104580-	IncomingCalls, OutgoingCalls []protocol.CallHierarchyItem
104581-}
104582-
104583-type Link struct {
104584-	Src          span.Span
104585-	Target       string
104586-	NotePosition token.Position
104587-}
104588-
104589-type SuggestedFix struct {
104590-	ActionKind, Title string
104591-}
104592-
104593-// A symbol holds a DocumentSymbol along with its parent-child edge.
104594-type symbol struct {
104595-	pSymbol      protocol.DocumentSymbol
104596-	id, parentID string
104597-}
104598-
104599-type Golden struct {
104600-	Filename string
104601-	Archive  *txtar.Archive
104602-	Modified bool
104603-}
104604-
104605-func Context(t testing.TB) context.Context {
104606-	return context.Background()
104607-}
104608-
104609-func DefaultOptions(o *source.Options) {
104610-	o.SupportedCodeActions = map[source.FileKind]map[protocol.CodeActionKind]bool{
104611-		source.Go: {
104612-			protocol.SourceOrganizeImports: true,
104613-			protocol.QuickFix:              true,
104614-			protocol.RefactorRewrite:       true,
104615-			protocol.RefactorExtract:       true,
104616-			protocol.SourceFixAll:          true,
104617-		},
104618-		source.Mod: {
104619-			protocol.SourceOrganizeImports: true,
104620-		},
104621-		source.Sum:  {},
104622-		source.Work: {},
104623-		source.Tmpl: {},
104624-	}
104625-	o.UserOptions.Codelenses[string(command.Test)] = true
104626-	o.HoverKind = source.SynopsisDocumentation
104627-	o.InsertTextFormat = protocol.SnippetTextFormat
104628-	o.CompletionBudget = time.Minute
104629-	o.HierarchicalDocumentSymbolSupport = true
104630-	o.SemanticTokens = true
104631-	o.InternalOptions.NewDiff = "both"
104632-}
104633-
104634-func RunTests(t *testing.T, dataDir string, includeMultiModule bool, f func(*testing.T, *Data)) {
104635-	t.Helper()
104636-	modes := []string{"Modules", "GOPATH"}
104637-	if includeMultiModule {
104638-		modes = append(modes, "MultiModule")
104639-	}
104640-	for _, mode := range modes {
104641-		t.Run(mode, func(t *testing.T) {
104642-			datum := load(t, mode, dataDir)
104643-			t.Helper()
104644-			f(t, datum)
104645-		})
104646-	}
104647-}
104648-
104649-func load(t testing.TB, mode string, dir string) *Data {
104650-	datum := &Data{
104651-		CallHierarchy:            make(CallHierarchy),
104652-		CodeLens:                 make(CodeLens),
104653-		Diagnostics:              make(Diagnostics),
104654-		CompletionItems:          make(CompletionItems),
104655-		Completions:              make(Completions),
104656-		CompletionSnippets:       make(CompletionSnippets),
104657-		UnimportedCompletions:    make(UnimportedCompletions),
104658-		DeepCompletions:          make(DeepCompletions),
104659-		FuzzyCompletions:         make(FuzzyCompletions),
104660-		RankCompletions:          make(RankCompletions),
104661-		CaseSensitiveCompletions: make(CaseSensitiveCompletions),
104662-		Definitions:              make(Definitions),
104663-		Implementations:          make(Implementations),
104664-		Highlights:               make(Highlights),
104665-		References:               make(References),
104666-		Renames:                  make(Renames),
104667-		PrepareRenames:           make(PrepareRenames),
104668-		SuggestedFixes:           make(SuggestedFixes),
104669-		FunctionExtractions:      make(FunctionExtractions),
104670-		MethodExtractions:        make(MethodExtractions),
104671-		Symbols:                  make(Symbols),
104672-		WorkspaceSymbols:         make(WorkspaceSymbols),
104673-		Signatures:               make(Signatures),
104674-		Links:                    make(Links),
104675-		AddImport:                make(AddImport),
104676-
104677-		dir:       dir,
104678-		fragments: map[string]string{},
104679-		golden:    map[string]*Golden{},
104680-		mode:      mode,
104681-		mappers:   map[span.URI]*protocol.Mapper{},
104682-	}
104683-
104684-	if !*UpdateGolden {
104685-		summary := filepath.Join(filepath.FromSlash(dir), summaryFile+goldenFileSuffix)
104686-		if _, err := os.Stat(summary); os.IsNotExist(err) {
104687-			t.Fatalf("could not find golden file summary.txt in %#v", dir)
104688-		}
104689-		archive, err := txtar.ParseFile(summary)
104690-		if err != nil {
104691-			t.Fatalf("could not read golden file %v/%v: %v", dir, summary, err)
104692-		}
104693-		datum.golden[summaryFile] = &Golden{
104694-			Filename: summary,
104695-			Archive:  archive,
104696-		}
104697-	}
104698-
104699-	files := packagestest.MustCopyFileTree(dir)
104700-	// Prune test cases that exercise generics.
104701-	if !typeparams.Enabled {
104702-		for name := range files {
104703-			if strings.Contains(name, "_generics") {
104704-				delete(files, name)
104705-			}
104706-		}
104707-	}
104708-	overlays := map[string][]byte{}
104709-	for fragment, operation := range files {
104710-		if trimmed := strings.TrimSuffix(fragment, goldenFileSuffix); trimmed != fragment {
104711-			delete(files, fragment)
104712-			goldFile := filepath.Join(dir, fragment)
104713-			archive, err := txtar.ParseFile(goldFile)
104714-			if err != nil {
104715-				t.Fatalf("could not read golden file %v: %v", fragment, err)
104716-			}
104717-			datum.golden[trimmed] = &Golden{
104718-				Filename: goldFile,
104719-				Archive:  archive,
104720-			}
104721-		} else if trimmed := strings.TrimSuffix(fragment, inFileSuffix); trimmed != fragment {
104722-			delete(files, fragment)
104723-			files[trimmed] = operation
104724-		} else if index := strings.Index(fragment, overlayFileSuffix); index >= 0 {
104725-			delete(files, fragment)
104726-			partial := fragment[:index] + fragment[index+len(overlayFileSuffix):]
104727-			contents, err := ioutil.ReadFile(filepath.Join(dir, fragment))
104728-			if err != nil {
104729-				t.Fatal(err)
104730-			}
104731-			overlays[partial] = contents
104732-		}
104733-	}
104734-
104735-	modules := []packagestest.Module{
104736-		{
104737-			Name:    testModule,
104738-			Files:   files,
104739-			Overlay: overlays,
104740-		},
104741-	}
104742-	switch mode {
104743-	case "Modules":
104744-		datum.Exported = packagestest.Export(t, packagestest.Modules, modules)
104745-	case "GOPATH":
104746-		datum.Exported = packagestest.Export(t, packagestest.GOPATH, modules)
104747-	case "MultiModule":
104748-		files := map[string]interface{}{}
104749-		for k, v := range modules[0].Files {
104750-			files[filepath.Join("testmodule", k)] = v
104751-		}
104752-		modules[0].Files = files
104753-
104754-		overlays := map[string][]byte{}
104755-		for k, v := range modules[0].Overlay {
104756-			overlays[filepath.Join("testmodule", k)] = v
104757-		}
104758-		modules[0].Overlay = overlays
104759-
104760-		golden := map[string]*Golden{}
104761-		for k, v := range datum.golden {
104762-			if k == summaryFile {
104763-				golden[k] = v
104764-			} else {
104765-				golden[filepath.Join("testmodule", k)] = v
104766-			}
104767-		}
104768-		datum.golden = golden
104769-
104770-		datum.Exported = packagestest.Export(t, packagestest.Modules, modules)
104771-	default:
104772-		panic("unknown mode " + mode)
104773-	}
104774-
104775-	for _, m := range modules {
104776-		for fragment := range m.Files {
104777-			filename := datum.Exported.File(m.Name, fragment)
104778-			datum.fragments[filename] = fragment
104779-		}
104780-	}
104781-
104782-	// Turn off go/packages debug logging.
104783-	datum.Exported.Config.Logf = nil
104784-	datum.Config.Logf = nil
104785-
104786-	// Merge the exported.Config with the view.Config.
104787-	datum.Config = *datum.Exported.Config
104788-	datum.Config.Fset = token.NewFileSet()
104789-	datum.Config.Context = Context(nil)
104790-	datum.Config.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
104791-		panic("ParseFile should not be called")
104792-	}
104793-
104794-	// Do a first pass to collect special markers for completion and workspace symbols.
104795-	if err := datum.Exported.Expect(map[string]interface{}{
104796-		"item": func(name string, r packagestest.Range, _ []string) {
104797-			datum.Exported.Mark(name, r)
104798-		},
104799-		"symbol": func(name string, r packagestest.Range, _ []string) {
104800-			datum.Exported.Mark(name, r)
104801-		},
104802-	}); err != nil {
104803-		t.Fatal(err)
104804-	}
104805-
104806-	// Collect any data that needs to be used by subsequent tests.
104807-	if err := datum.Exported.Expect(map[string]interface{}{
104808-		"codelens":        datum.collectCodeLens,
104809-		"diag":            datum.collectDiagnostics,
104810-		"item":            datum.collectCompletionItems,
104811-		"complete":        datum.collectCompletions(CompletionDefault),
104812-		"unimported":      datum.collectCompletions(CompletionUnimported),
104813-		"deep":            datum.collectCompletions(CompletionDeep),
104814-		"fuzzy":           datum.collectCompletions(CompletionFuzzy),
104815-		"casesensitive":   datum.collectCompletions(CompletionCaseSensitive),
104816-		"rank":            datum.collectCompletions(CompletionRank),
104817-		"snippet":         datum.collectCompletionSnippets,
104818-		"fold":            datum.collectFoldingRanges,
104819-		"format":          datum.collectFormats,
104820-		"import":          datum.collectImports,
104821-		"semantic":        datum.collectSemanticTokens,
104822-		"godef":           datum.collectDefinitions,
104823-		"implementations": datum.collectImplementations,
104824-		"typdef":          datum.collectTypeDefinitions,
104825-		"hoverdef":        datum.collectHoverDefinitions,
104826-		"highlight":       datum.collectHighlights,
104827-		"inlayHint":       datum.collectInlayHints,
104828-		"refs":            datum.collectReferences,
104829-		"rename":          datum.collectRenames,
104830-		"prepare":         datum.collectPrepareRenames,
104831-		"symbol":          datum.collectSymbols,
104832-		"signature":       datum.collectSignatures,
104833-		"link":            datum.collectLinks,
104834-		"suggestedfix":    datum.collectSuggestedFixes,
104835-		"extractfunc":     datum.collectFunctionExtractions,
104836-		"extractmethod":   datum.collectMethodExtractions,
104837-		"incomingcalls":   datum.collectIncomingCalls,
104838-		"outgoingcalls":   datum.collectOutgoingCalls,
104839-		"addimport":       datum.collectAddImports,
104840-		"selectionrange":  datum.collectSelectionRanges,
104841-	}); err != nil {
104842-		t.Fatal(err)
104843-	}
104844-
104845-	// Collect names for the entries that require golden files.
104846-	if err := datum.Exported.Expect(map[string]interface{}{
104847-		"godef":                        datum.collectDefinitionNames,
104848-		"hoverdef":                     datum.collectDefinitionNames,
104849-		"workspacesymbol":              datum.collectWorkspaceSymbols(WorkspaceSymbolsDefault),
104850-		"workspacesymbolfuzzy":         datum.collectWorkspaceSymbols(WorkspaceSymbolsFuzzy),
104851-		"workspacesymbolcasesensitive": datum.collectWorkspaceSymbols(WorkspaceSymbolsCaseSensitive),
104852-	}); err != nil {
104853-		t.Fatal(err)
104854-	}
104855-	if mode == "MultiModule" {
104856-		if err := moveFile(filepath.Join(datum.Config.Dir, "go.mod"), filepath.Join(datum.Config.Dir, "testmodule/go.mod")); err != nil {
104857-			t.Fatal(err)
104858-		}
104859-	}
104860-
104861-	return datum
104862-}
104863-
104864-// moveFile moves the file at oldpath to newpath, by renaming if possible
104865-// or copying otherwise.
104866-func moveFile(oldpath, newpath string) (err error) {
104867-	renameErr := os.Rename(oldpath, newpath)
104868-	if renameErr == nil {
104869-		return nil
104870-	}
104871-
104872-	src, err := os.Open(oldpath)
104873-	if err != nil {
104874-		return err
104875-	}
104876-	defer func() {
104877-		src.Close()
104878-		if err == nil {
104879-			err = os.Remove(oldpath)
104880-		}
104881-	}()
104882-
104883-	perm := os.ModePerm
104884-	fi, err := src.Stat()
104885-	if err == nil {
104886-		perm = fi.Mode().Perm()
104887-	}
104888-
104889-	dst, err := os.OpenFile(newpath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
104890-	if err != nil {
104891-		return err
104892-	}
104893-
104894-	_, err = io.Copy(dst, src)
104895-	if closeErr := dst.Close(); err == nil {
104896-		err = closeErr
104897-	}
104898-	return err
104899-}
104900-
104901-func Run(t *testing.T, tests Tests, data *Data) {
104902-	t.Helper()
104903-	checkData(t, data)
104904-
104905-	eachCompletion := func(t *testing.T, cases map[span.Span][]Completion, test func(*testing.T, span.Span, Completion, CompletionItems)) {
104906-		t.Helper()
104907-
104908-		for src, exp := range cases {
104909-			for i, e := range exp {
104910-				t.Run(SpanName(src)+"_"+strconv.Itoa(i), func(t *testing.T) {
104911-					t.Helper()
104912-					if strings.Contains(t.Name(), "cgo") {
104913-						testenv.NeedsTool(t, "cgo")
104914-					}
104915-					test(t, src, e, data.CompletionItems)
104916-				})
104917-			}
104918-
104919-		}
104920-	}
104921-
104922-	t.Run("CallHierarchy", func(t *testing.T) {
104923-		t.Helper()
104924-		for spn, callHierarchyResult := range data.CallHierarchy {
104925-			t.Run(SpanName(spn), func(t *testing.T) {
104926-				t.Helper()
104927-				tests.CallHierarchy(t, spn, callHierarchyResult)
104928-			})
104929-		}
104930-	})
104931-
104932-	t.Run("Completion", func(t *testing.T) {
104933-		t.Helper()
104934-		eachCompletion(t, data.Completions, tests.Completion)
104935-	})
104936-
104937-	t.Run("CompletionSnippets", func(t *testing.T) {
104938-		t.Helper()
104939-		for _, placeholders := range []bool{true, false} {
104940-			for src, expecteds := range data.CompletionSnippets {
104941-				for i, expected := range expecteds {
104942-					name := SpanName(src) + "_" + strconv.Itoa(i+1)
104943-					if placeholders {
104944-						name += "_placeholders"
104945-					}
104946-
104947-					t.Run(name, func(t *testing.T) {
104948-						t.Helper()
104949-						tests.CompletionSnippet(t, src, expected, placeholders, data.CompletionItems)
104950-					})
104951-				}
104952-			}
104953-		}
104954-	})
104955-
104956-	t.Run("UnimportedCompletion", func(t *testing.T) {
104957-		t.Helper()
104958-		eachCompletion(t, data.UnimportedCompletions, tests.UnimportedCompletion)
104959-	})
104960-
104961-	t.Run("DeepCompletion", func(t *testing.T) {
104962-		t.Helper()
104963-		eachCompletion(t, data.DeepCompletions, tests.DeepCompletion)
104964-	})
104965-
104966-	t.Run("FuzzyCompletion", func(t *testing.T) {
104967-		t.Helper()
104968-		eachCompletion(t, data.FuzzyCompletions, tests.FuzzyCompletion)
104969-	})
104970-
104971-	t.Run("CaseSensitiveCompletion", func(t *testing.T) {
104972-		t.Helper()
104973-		eachCompletion(t, data.CaseSensitiveCompletions, tests.CaseSensitiveCompletion)
104974-	})
104975-
104976-	t.Run("RankCompletions", func(t *testing.T) {
104977-		t.Helper()
104978-		eachCompletion(t, data.RankCompletions, tests.RankCompletion)
104979-	})
104980-
104981-	t.Run("CodeLens", func(t *testing.T) {
104982-		t.Helper()
104983-		for uri, want := range data.CodeLens {
104984-			// Check if we should skip this URI if the -modfile flag is not available.
104985-			if shouldSkip(data, uri) {
104986-				continue
104987-			}
104988-			t.Run(uriName(uri), func(t *testing.T) {
104989-				t.Helper()
104990-				tests.CodeLens(t, uri, want)
104991-			})
104992-		}
104993-	})
104994-
104995-	t.Run("Diagnostics", func(t *testing.T) {
104996-		t.Helper()
104997-		for uri, want := range data.Diagnostics {
104998-			// Check if we should skip this URI if the -modfile flag is not available.
104999-			if shouldSkip(data, uri) {
105000-				continue
105001-			}
105002-			t.Run(uriName(uri), func(t *testing.T) {
105003-				t.Helper()
105004-				tests.Diagnostics(t, uri, want)
105005-			})
105006-		}
105007-	})
105008-
105009-	t.Run("FoldingRange", func(t *testing.T) {
105010-		t.Helper()
105011-		for _, spn := range data.FoldingRanges {
105012-			t.Run(uriName(spn.URI()), func(t *testing.T) {
105013-				t.Helper()
105014-				tests.FoldingRanges(t, spn)
105015-			})
105016-		}
105017-	})
105018-
105019-	t.Run("Format", func(t *testing.T) {
105020-		t.Helper()
105021-		for _, spn := range data.Formats {
105022-			t.Run(uriName(spn.URI()), func(t *testing.T) {
105023-				t.Helper()
105024-				tests.Format(t, spn)
105025-			})
105026-		}
105027-	})
105028-
105029-	t.Run("Import", func(t *testing.T) {
105030-		t.Helper()
105031-		for _, spn := range data.Imports {
105032-			t.Run(uriName(spn.URI()), func(t *testing.T) {
105033-				t.Helper()
105034-				tests.Import(t, spn)
105035-			})
105036-		}
105037-	})
105038-
105039-	t.Run("SemanticTokens", func(t *testing.T) {
105040-		t.Helper()
105041-		for _, spn := range data.SemanticTokens {
105042-			t.Run(uriName(spn.URI()), func(t *testing.T) {
105043-				t.Helper()
105044-				tests.SemanticTokens(t, spn)
105045-			})
105046-		}
105047-	})
105048-
105049-	t.Run("SuggestedFix", func(t *testing.T) {
105050-		t.Helper()
105051-		for spn, actionKinds := range data.SuggestedFixes {
105052-			// Check if we should skip this spn if the -modfile flag is not available.
105053-			if shouldSkip(data, spn.URI()) {
105054-				continue
105055-			}
105056-			t.Run(SpanName(spn), func(t *testing.T) {
105057-				t.Helper()
105058-				tests.SuggestedFix(t, spn, actionKinds, 1)
105059-			})
105060-		}
105061-	})
105062-
105063-	t.Run("FunctionExtraction", func(t *testing.T) {
105064-		t.Helper()
105065-		for start, end := range data.FunctionExtractions {
105066-			// Check if we should skip this spn if the -modfile flag is not available.
105067-			if shouldSkip(data, start.URI()) {
105068-				continue
105069-			}
105070-			t.Run(SpanName(start), func(t *testing.T) {
105071-				t.Helper()
105072-				tests.FunctionExtraction(t, start, end)
105073-			})
105074-		}
105075-	})
105076-
105077-	t.Run("MethodExtraction", func(t *testing.T) {
105078-		t.Helper()
105079-		for start, end := range data.MethodExtractions {
105080-			// Check if we should skip this spn if the -modfile flag is not available.
105081-			if shouldSkip(data, start.URI()) {
105082-				continue
105083-			}
105084-			t.Run(SpanName(start), func(t *testing.T) {
105085-				t.Helper()
105086-				tests.MethodExtraction(t, start, end)
105087-			})
105088-		}
105089-	})
105090-
105091-	t.Run("Definition", func(t *testing.T) {
105092-		t.Helper()
105093-		for spn, d := range data.Definitions {
105094-			t.Run(SpanName(spn), func(t *testing.T) {
105095-				t.Helper()
105096-				if strings.Contains(t.Name(), "cgo") {
105097-					testenv.NeedsTool(t, "cgo")
105098-				}
105099-				tests.Definition(t, spn, d)
105100-			})
105101-		}
105102-	})
105103-
105104-	t.Run("Implementation", func(t *testing.T) {
105105-		t.Helper()
105106-		for spn, m := range data.Implementations {
105107-			t.Run(SpanName(spn), func(t *testing.T) {
105108-				t.Helper()
105109-				tests.Implementation(t, spn, m)
105110-			})
105111-		}
105112-	})
105113-
105114-	t.Run("Highlight", func(t *testing.T) {
105115-		t.Helper()
105116-		for pos, locations := range data.Highlights {
105117-			t.Run(SpanName(pos), func(t *testing.T) {
105118-				t.Helper()
105119-				tests.Highlight(t, pos, locations)
105120-			})
105121-		}
105122-	})
105123-
105124-	t.Run("InlayHints", func(t *testing.T) {
105125-		t.Helper()
105126-		for _, src := range data.InlayHints {
105127-			t.Run(SpanName(src), func(t *testing.T) {
105128-				t.Helper()
105129-				tests.InlayHints(t, src)
105130-			})
105131-		}
105132-	})
105133-
105134-	t.Run("References", func(t *testing.T) {
105135-		t.Helper()
105136-		for src, itemList := range data.References {
105137-			t.Run(SpanName(src), func(t *testing.T) {
105138-				t.Helper()
105139-				tests.References(t, src, itemList)
105140-			})
105141-		}
105142-	})
105143-
105144-	t.Run("Renames", func(t *testing.T) {
105145-		t.Helper()
105146-		for spn, newText := range data.Renames {
105147-			t.Run(uriName(spn.URI())+"_"+newText, func(t *testing.T) {
105148-				t.Helper()
105149-				tests.Rename(t, spn, newText)
105150-			})
105151-		}
105152-	})
105153-
105154-	t.Run("PrepareRenames", func(t *testing.T) {
105155-		t.Helper()
105156-		for src, want := range data.PrepareRenames {
105157-			t.Run(SpanName(src), func(t *testing.T) {
105158-				t.Helper()
105159-				tests.PrepareRename(t, src, want)
105160-			})
105161-		}
105162-	})
105163-
105164-	t.Run("Symbols", func(t *testing.T) {
105165-		t.Helper()
105166-		for uri, allSymbols := range data.Symbols {
105167-			byParent := make(map[string][]*symbol)
105168-			for _, sym := range allSymbols {
105169-				if sym.parentID != "" {
105170-					byParent[sym.parentID] = append(byParent[sym.parentID], sym)
105171-				}
105172-			}
105173-
105174-			// collectChildren does a depth-first traversal of the symbol tree,
105175-			// computing children of child nodes before returning to their parent.
105176-			// This is necessary as the Children field is slice of non-pointer types,
105177-			// and therefore we need to be careful to mutate children first before
105178-			// assigning them to their parent.
105179-			var collectChildren func(id string) []protocol.DocumentSymbol
105180-			collectChildren = func(id string) []protocol.DocumentSymbol {
105181-				children := byParent[id]
105182-				// delete from byParent before recursing, to ensure that
105183-				// collectChildren terminates even in the presence of cycles.
105184-				delete(byParent, id)
105185-				var result []protocol.DocumentSymbol
105186-				for _, child := range children {
105187-					child.pSymbol.Children = collectChildren(child.id)
105188-					result = append(result, child.pSymbol)
105189-				}
105190-				return result
105191-			}
105192-
105193-			var topLevel []protocol.DocumentSymbol
105194-			for _, sym := range allSymbols {
105195-				if sym.parentID == "" {
105196-					sym.pSymbol.Children = collectChildren(sym.id)
105197-					topLevel = append(topLevel, sym.pSymbol)
105198-				}
105199-			}
105200-
105201-			t.Run(uriName(uri), func(t *testing.T) {
105202-				t.Helper()
105203-				tests.Symbols(t, uri, topLevel)
105204-			})
105205-		}
105206-	})
105207-
105208-	t.Run("WorkspaceSymbols", func(t *testing.T) {
105209-		t.Helper()
105210-
105211-		for _, typ := range []WorkspaceSymbolsTestType{
105212-			WorkspaceSymbolsDefault,
105213-			WorkspaceSymbolsCaseSensitive,
105214-			WorkspaceSymbolsFuzzy,
105215-		} {
105216-			for uri, cases := range data.WorkspaceSymbols[typ] {
105217-				for _, query := range cases {
105218-					name := query
105219-					if name == "" {
105220-						name = "EmptyQuery"
105221-					}
105222-					t.Run(name, func(t *testing.T) {
105223-						t.Helper()
105224-						tests.WorkspaceSymbols(t, uri, query, typ)
105225-					})
105226-				}
105227-			}
105228-		}
105229-
105230-	})
105231-
105232-	t.Run("SignatureHelp", func(t *testing.T) {
105233-		t.Helper()
105234-		for spn, expectedSignature := range data.Signatures {
105235-			t.Run(SpanName(spn), func(t *testing.T) {
105236-				t.Helper()
105237-				tests.SignatureHelp(t, spn, expectedSignature)
105238-			})
105239-		}
105240-	})
105241-
105242-	t.Run("Link", func(t *testing.T) {
105243-		t.Helper()
105244-		for uri, wantLinks := range data.Links {
105245-			// If we are testing GOPATH, then we do not want links with the versions
105246-			// attached (pkg.go.dev/repoa/moda@v1.1.0/pkg), unless the file is a
105247-			// go.mod, then we can skip it altogether.
105248-			if data.Exported.Exporter == packagestest.GOPATH {
105249-				if strings.HasSuffix(uri.Filename(), ".mod") {
105250-					continue
105251-				}
105252-				re := regexp.MustCompile(`@v\d+\.\d+\.[\w-]+`)
105253-				for i, link := range wantLinks {
105254-					wantLinks[i].Target = re.ReplaceAllString(link.Target, "")
105255-				}
105256-			}
105257-			t.Run(uriName(uri), func(t *testing.T) {
105258-				t.Helper()
105259-				tests.Link(t, uri, wantLinks)
105260-			})
105261-		}
105262-	})
105263-
105264-	t.Run("AddImport", func(t *testing.T) {
105265-		t.Helper()
105266-		for uri, exp := range data.AddImport {
105267-			t.Run(uriName(uri), func(t *testing.T) {
105268-				tests.AddImport(t, uri, exp)
105269-			})
105270-		}
105271-	})
105272-
105273-	t.Run("SelectionRanges", func(t *testing.T) {
105274-		t.Helper()
105275-		for _, span := range data.SelectionRanges {
105276-			t.Run(SpanName(span), func(t *testing.T) {
105277-				tests.SelectionRanges(t, span)
105278-			})
105279-		}
105280-	})
105281-
105282-	if *UpdateGolden {
105283-		for _, golden := range data.golden {
105284-			if !golden.Modified {
105285-				continue
105286-			}
105287-			sort.Slice(golden.Archive.Files, func(i, j int) bool {
105288-				return golden.Archive.Files[i].Name < golden.Archive.Files[j].Name
105289-			})
105290-			if err := ioutil.WriteFile(golden.Filename, txtar.Format(golden.Archive), 0666); err != nil {
105291-				t.Fatal(err)
105292-			}
105293-		}
105294-	}
105295-}
105296-
105297-func checkData(t *testing.T, data *Data) {
105298-	buf := &bytes.Buffer{}
105299-	diagnosticsCount := 0
105300-	for _, want := range data.Diagnostics {
105301-		diagnosticsCount += len(want)
105302-	}
105303-	linksCount := 0
105304-	for _, want := range data.Links {
105305-		linksCount += len(want)
105306-	}
105307-	definitionCount := 0
105308-	typeDefinitionCount := 0
105309-	for _, d := range data.Definitions {
105310-		if d.IsType {
105311-			typeDefinitionCount++
105312-		} else {
105313-			definitionCount++
105314-		}
105315-	}
105316-
105317-	snippetCount := 0
105318-	for _, want := range data.CompletionSnippets {
105319-		snippetCount += len(want)
105320-	}
105321-
105322-	countCompletions := func(c map[span.Span][]Completion) (count int) {
105323-		for _, want := range c {
105324-			count += len(want)
105325-		}
105326-		return count
105327-	}
105328-
105329-	countCodeLens := func(c map[span.URI][]protocol.CodeLens) (count int) {
105330-		for _, want := range c {
105331-			count += len(want)
105332-		}
105333-		return count
105334-	}
105335-
105336-	countWorkspaceSymbols := func(c map[WorkspaceSymbolsTestType]map[span.URI][]string) (count int) {
105337-		for _, typs := range c {
105338-			for _, queries := range typs {
105339-				count += len(queries)
105340-			}
105341-		}
105342-		return count
105343-	}
105344-
105345-	fmt.Fprintf(buf, "CallHierarchyCount = %v\n", len(data.CallHierarchy))
105346-	fmt.Fprintf(buf, "CodeLensCount = %v\n", countCodeLens(data.CodeLens))
105347-	fmt.Fprintf(buf, "CompletionsCount = %v\n", countCompletions(data.Completions))
105348-	fmt.Fprintf(buf, "CompletionSnippetCount = %v\n", snippetCount)
105349-	fmt.Fprintf(buf, "UnimportedCompletionsCount = %v\n", countCompletions(data.UnimportedCompletions))
105350-	fmt.Fprintf(buf, "DeepCompletionsCount = %v\n", countCompletions(data.DeepCompletions))
105351-	fmt.Fprintf(buf, "FuzzyCompletionsCount = %v\n", countCompletions(data.FuzzyCompletions))
105352-	fmt.Fprintf(buf, "RankedCompletionsCount = %v\n", countCompletions(data.RankCompletions))
105353-	fmt.Fprintf(buf, "CaseSensitiveCompletionsCount = %v\n", countCompletions(data.CaseSensitiveCompletions))
105354-	fmt.Fprintf(buf, "DiagnosticsCount = %v\n", diagnosticsCount)
105355-	fmt.Fprintf(buf, "FoldingRangesCount = %v\n", len(data.FoldingRanges))
105356-	fmt.Fprintf(buf, "FormatCount = %v\n", len(data.Formats))
105357-	fmt.Fprintf(buf, "ImportCount = %v\n", len(data.Imports))
105358-	fmt.Fprintf(buf, "SemanticTokenCount = %v\n", len(data.SemanticTokens))
105359-	fmt.Fprintf(buf, "SuggestedFixCount = %v\n", len(data.SuggestedFixes))
105360-	fmt.Fprintf(buf, "FunctionExtractionCount = %v\n", len(data.FunctionExtractions))
105361-	fmt.Fprintf(buf, "MethodExtractionCount = %v\n", len(data.MethodExtractions))
105362-	fmt.Fprintf(buf, "DefinitionsCount = %v\n", definitionCount)
105363-	fmt.Fprintf(buf, "TypeDefinitionsCount = %v\n", typeDefinitionCount)
105364-	fmt.Fprintf(buf, "HighlightsCount = %v\n", len(data.Highlights))
105365-	fmt.Fprintf(buf, "InlayHintsCount = %v\n", len(data.InlayHints))
105366-	fmt.Fprintf(buf, "ReferencesCount = %v\n", len(data.References))
105367-	fmt.Fprintf(buf, "RenamesCount = %v\n", len(data.Renames))
105368-	fmt.Fprintf(buf, "PrepareRenamesCount = %v\n", len(data.PrepareRenames))
105369-	fmt.Fprintf(buf, "SymbolsCount = %v\n", len(data.Symbols))
105370-	fmt.Fprintf(buf, "WorkspaceSymbolsCount = %v\n", countWorkspaceSymbols(data.WorkspaceSymbols))
105371-	fmt.Fprintf(buf, "SignaturesCount = %v\n", len(data.Signatures))
105372-	fmt.Fprintf(buf, "LinksCount = %v\n", linksCount)
105373-	fmt.Fprintf(buf, "ImplementationsCount = %v\n", len(data.Implementations))
105374-	fmt.Fprintf(buf, "SelectionRangesCount = %v\n", len(data.SelectionRanges))
105375-
105376-	want := string(data.Golden(t, "summary", summaryFile, func() ([]byte, error) {
105377-		return buf.Bytes(), nil
105378-	}))
105379-	got := buf.String()
105380-	if want != got {
105381-		// These counters change when assertions are added or removed.
105382-		// They act as an independent safety net to ensure that the
105383-		// tests didn't spuriously pass because they did no work.
105384-		t.Errorf("test summary does not match:\n%s\n(Run with -golden to update golden file; also, there may be one per Go version.)", compare.Text(want, got))
105385-	}
105386-}
105387-
105388-func (data *Data) Mapper(uri span.URI) (*protocol.Mapper, error) {
105389-	data.mappersMu.Lock()
105390-	defer data.mappersMu.Unlock()
105391-
105392-	if _, ok := data.mappers[uri]; !ok {
105393-		content, err := data.Exported.FileContents(uri.Filename())
105394-		if err != nil {
105395-			return nil, err
105396-		}
105397-		data.mappers[uri] = protocol.NewMapper(uri, content)
105398-	}
105399-	return data.mappers[uri], nil
105400-}
105401-
105402-func (data *Data) Golden(t *testing.T, tag, target string, update func() ([]byte, error)) []byte {
105403-	t.Helper()
105404-	fragment, found := data.fragments[target]
105405-	if !found {
105406-		if filepath.IsAbs(target) {
105407-			t.Fatalf("invalid golden file fragment %v", target)
105408-		}
105409-		fragment = target
105410-	}
105411-	golden := data.golden[fragment]
105412-	if golden == nil {
105413-		if !*UpdateGolden {
105414-			t.Fatalf("could not find golden file %v: %v", fragment, tag)
105415-		}
105416-		golden = &Golden{
105417-			Filename: filepath.Join(data.dir, fragment+goldenFileSuffix),
105418-			Archive:  &txtar.Archive{},
105419-			Modified: true,
105420-		}
105421-		data.golden[fragment] = golden
105422-	}
105423-	var file *txtar.File
105424-	for i := range golden.Archive.Files {
105425-		f := &golden.Archive.Files[i]
105426-		if f.Name == tag {
105427-			file = f
105428-			break
105429-		}
105430-	}
105431-	if *UpdateGolden {
105432-		if file == nil {
105433-			golden.Archive.Files = append(golden.Archive.Files, txtar.File{
105434-				Name: tag,
105435-			})
105436-			file = &golden.Archive.Files[len(golden.Archive.Files)-1]
105437-		}
105438-		contents, err := update()
105439-		if err != nil {
105440-			t.Fatalf("could not update golden file %v: %v", fragment, err)
105441-		}
105442-		file.Data = append(contents, '\n') // add trailing \n for txtar
105443-		golden.Modified = true
105444-
105445-	}
105446-	if file == nil {
105447-		t.Fatalf("could not find golden contents %v: %v", fragment, tag)
105448-	}
105449-	if len(file.Data) == 0 {
105450-		return file.Data
105451-	}
105452-	return file.Data[:len(file.Data)-1] // drop the trailing \n
105453-}
105454-
105455-func (data *Data) collectCodeLens(spn span.Span, title, cmd string) {
105456-	data.CodeLens[spn.URI()] = append(data.CodeLens[spn.URI()], protocol.CodeLens{
105457-		Range: data.mustRange(spn),
105458-		Command: &protocol.Command{
105459-			Title:   title,
105460-			Command: cmd,
105461-		},
105462-	})
105463-}
105464-
105465-func (data *Data) collectDiagnostics(spn span.Span, msgSource, msgPattern, msgSeverity string) {
105466-	severity := protocol.SeverityError
105467-	switch msgSeverity {
105468-	case "error":
105469-		severity = protocol.SeverityError
105470-	case "warning":
105471-		severity = protocol.SeverityWarning
105472-	case "hint":
105473-		severity = protocol.SeverityHint
105474-	case "information":
105475-		severity = protocol.SeverityInformation
105476-	}
105477-
105478-	data.Diagnostics[spn.URI()] = append(data.Diagnostics[spn.URI()], &source.Diagnostic{
105479-		Range:    data.mustRange(spn),
105480-		Severity: severity,
105481-		Source:   source.DiagnosticSource(msgSource),
105482-		Message:  msgPattern,
105483-	})
105484-}
105485-
105486-func (data *Data) collectCompletions(typ CompletionTestType) func(span.Span, []token.Pos) {
105487-	result := func(m map[span.Span][]Completion, src span.Span, expected []token.Pos) {
105488-		m[src] = append(m[src], Completion{
105489-			CompletionItems: expected,
105490-		})
105491-	}
105492-	switch typ {
105493-	case CompletionDeep:
105494-		return func(src span.Span, expected []token.Pos) {
105495-			result(data.DeepCompletions, src, expected)
105496-		}
105497-	case CompletionUnimported:
105498-		return func(src span.Span, expected []token.Pos) {
105499-			result(data.UnimportedCompletions, src, expected)
105500-		}
105501-	case CompletionFuzzy:
105502-		return func(src span.Span, expected []token.Pos) {
105503-			result(data.FuzzyCompletions, src, expected)
105504-		}
105505-	case CompletionRank:
105506-		return func(src span.Span, expected []token.Pos) {
105507-			result(data.RankCompletions, src, expected)
105508-		}
105509-	case CompletionCaseSensitive:
105510-		return func(src span.Span, expected []token.Pos) {
105511-			result(data.CaseSensitiveCompletions, src, expected)
105512-		}
105513-	default:
105514-		return func(src span.Span, expected []token.Pos) {
105515-			result(data.Completions, src, expected)
105516-		}
105517-	}
105518-}
105519-
105520-func (data *Data) collectCompletionItems(pos token.Pos, label, detail, kind string, args []string) {
105521-	var documentation string
105522-	if len(args) > 3 {
105523-		documentation = args[3]
105524-	}
105525-	data.CompletionItems[pos] = &completion.CompletionItem{
105526-		Label:         label,
105527-		Detail:        detail,
105528-		Kind:          protocol.ParseCompletionItemKind(kind),
105529-		Documentation: documentation,
105530-	}
105531-}
105532-
105533-func (data *Data) collectFoldingRanges(spn span.Span) {
105534-	data.FoldingRanges = append(data.FoldingRanges, spn)
105535-}
105536-
105537-func (data *Data) collectFormats(spn span.Span) {
105538-	data.Formats = append(data.Formats, spn)
105539-}
105540-
105541-func (data *Data) collectImports(spn span.Span) {
105542-	data.Imports = append(data.Imports, spn)
105543-}
105544-
105545-func (data *Data) collectAddImports(spn span.Span, imp string) {
105546-	data.AddImport[spn.URI()] = imp
105547-}
105548-
105549-func (data *Data) collectSemanticTokens(spn span.Span) {
105550-	data.SemanticTokens = append(data.SemanticTokens, spn)
105551-}
105552-
105553-func (data *Data) collectSuggestedFixes(spn span.Span, actionKind, fix string) {
105554-	data.SuggestedFixes[spn] = append(data.SuggestedFixes[spn], SuggestedFix{actionKind, fix})
105555-}
105556-
105557-func (data *Data) collectFunctionExtractions(start span.Span, end span.Span) {
105558-	if _, ok := data.FunctionExtractions[start]; !ok {
105559-		data.FunctionExtractions[start] = end
105560-	}
105561-}
105562-
105563-func (data *Data) collectMethodExtractions(start span.Span, end span.Span) {
105564-	if _, ok := data.MethodExtractions[start]; !ok {
105565-		data.MethodExtractions[start] = end
105566-	}
105567-}
105568-
105569-func (data *Data) collectDefinitions(src, target span.Span) {
105570-	data.Definitions[src] = Definition{
105571-		Src: src,
105572-		Def: target,
105573-	}
105574-}
105575-
105576-func (data *Data) collectSelectionRanges(spn span.Span) {
105577-	data.SelectionRanges = append(data.SelectionRanges, spn)
105578-}
105579-
105580-func (data *Data) collectImplementations(src span.Span, targets []span.Span) {
105581-	data.Implementations[src] = targets
105582-}
105583-
105584-func (data *Data) collectIncomingCalls(src span.Span, calls []span.Span) {
105585-	for _, call := range calls {
105586-		rng := data.mustRange(call)
105587-		// we're only comparing protocol.range
105588-		if data.CallHierarchy[src] != nil {
105589-			data.CallHierarchy[src].IncomingCalls = append(data.CallHierarchy[src].IncomingCalls,
105590-				protocol.CallHierarchyItem{
105591-					URI:   protocol.DocumentURI(call.URI()),
105592-					Range: rng,
105593-				})
105594-		} else {
105595-			data.CallHierarchy[src] = &CallHierarchyResult{
105596-				IncomingCalls: []protocol.CallHierarchyItem{
105597-					{URI: protocol.DocumentURI(call.URI()), Range: rng},
105598-				},
105599-			}
105600-		}
105601-	}
105602-}
105603-
105604-func (data *Data) collectOutgoingCalls(src span.Span, calls []span.Span) {
105605-	if data.CallHierarchy[src] == nil {
105606-		data.CallHierarchy[src] = &CallHierarchyResult{}
105607-	}
105608-	for _, call := range calls {
105609-		// we're only comparing protocol.range
105610-		data.CallHierarchy[src].OutgoingCalls = append(data.CallHierarchy[src].OutgoingCalls,
105611-			protocol.CallHierarchyItem{
105612-				URI:   protocol.DocumentURI(call.URI()),
105613-				Range: data.mustRange(call),
105614-			})
105615-	}
105616-}
105617-
105618-func (data *Data) collectHoverDefinitions(src, target span.Span) {
105619-	data.Definitions[src] = Definition{
105620-		Src:       src,
105621-		Def:       target,
105622-		OnlyHover: true,
105623-	}
105624-}
105625-
105626-func (data *Data) collectTypeDefinitions(src, target span.Span) {
105627-	data.Definitions[src] = Definition{
105628-		Src:    src,
105629-		Def:    target,
105630-		IsType: true,
105631-	}
105632-}
105633-
105634-func (data *Data) collectDefinitionNames(src span.Span, name string) {
105635-	d := data.Definitions[src]
105636-	d.Name = name
105637-	data.Definitions[src] = d
105638-}
105639-
105640-func (data *Data) collectHighlights(src span.Span, expected []span.Span) {
105641-	// Declaring a highlight in a test file: @highlight(src, expected1, expected2)
105642-	data.Highlights[src] = append(data.Highlights[src], expected...)
105643-}
105644-
105645-func (data *Data) collectInlayHints(src span.Span) {
105646-	data.InlayHints = append(data.InlayHints, src)
105647-}
105648-
105649-func (data *Data) collectReferences(src span.Span, expected []span.Span) {
105650-	data.References[src] = expected
105651-}
105652-
105653-func (data *Data) collectRenames(src span.Span, newText string) {
105654-	data.Renames[src] = newText
105655-}
105656-
105657-func (data *Data) collectPrepareRenames(src, spn span.Span, placeholder string) {
105658-	data.PrepareRenames[src] = &source.PrepareItem{
105659-		Range: data.mustRange(spn),
105660-		Text:  placeholder,
105661-	}
105662-}
105663-
105664-// collectSymbols is responsible for collecting @symbol annotations.
105665-func (data *Data) collectSymbols(name string, selectionRng span.Span, kind, detail, id, parentID string) {
105666-	// We don't set 'Range' here as it is difficult (impossible?) to express
105667-	// multi-line ranges in the packagestest framework.
105668-	uri := selectionRng.URI()
105669-	data.Symbols[uri] = append(data.Symbols[uri], &symbol{
105670-		pSymbol: protocol.DocumentSymbol{
105671-			Name:           name,
105672-			Kind:           protocol.ParseSymbolKind(kind),
105673-			SelectionRange: data.mustRange(selectionRng),
105674-			Detail:         detail,
105675-		},
105676-		id:       id,
105677-		parentID: parentID,
105678-	})
105679-}
105680-
105681-// mustRange converts spn into a protocol.Range, panicking on any error.
105682-func (data *Data) mustRange(spn span.Span) protocol.Range {
105683-	m, err := data.Mapper(spn.URI())
105684-	rng, err := m.SpanRange(spn)
105685-	if err != nil {
105686-		panic(fmt.Sprintf("converting span %s to range: %v", spn, err))
105687-	}
105688-	return rng
105689-}
105690-
105691-func (data *Data) collectWorkspaceSymbols(typ WorkspaceSymbolsTestType) func(*expect.Note, string) {
105692-	return func(note *expect.Note, query string) {
105693-		if data.WorkspaceSymbols[typ] == nil {
105694-			data.WorkspaceSymbols[typ] = make(map[span.URI][]string)
105695-		}
105696-		pos := safetoken.StartPosition(data.Exported.ExpectFileSet, note.Pos)
105697-		uri := span.URIFromPath(pos.Filename)
105698-		data.WorkspaceSymbols[typ][uri] = append(data.WorkspaceSymbols[typ][uri], query)
105699-	}
105700-}
105701-
105702-func (data *Data) collectSignatures(spn span.Span, signature string, activeParam int64) {
105703-	data.Signatures[spn] = &protocol.SignatureHelp{
105704-		Signatures: []protocol.SignatureInformation{
105705-			{
105706-				Label: signature,
105707-			},
105708-		},
105709-		ActiveParameter: uint32(activeParam),
105710-	}
105711-	// Hardcode special case to test the lack of a signature.
105712-	if signature == "" && activeParam == 0 {
105713-		data.Signatures[spn] = nil
105714-	}
105715-}
105716-
105717-func (data *Data) collectCompletionSnippets(spn span.Span, item token.Pos, plain, placeholder string) {
105718-	data.CompletionSnippets[spn] = append(data.CompletionSnippets[spn], CompletionSnippet{
105719-		CompletionItem:     item,
105720-		PlainSnippet:       plain,
105721-		PlaceholderSnippet: placeholder,
105722-	})
105723-}
105724-
105725-func (data *Data) collectLinks(spn span.Span, link string, note *expect.Note, fset *token.FileSet) {
105726-	position := safetoken.StartPosition(fset, note.Pos)
105727-	uri := spn.URI()
105728-	data.Links[uri] = append(data.Links[uri], Link{
105729-		Src:          spn,
105730-		Target:       link,
105731-		NotePosition: position,
105732-	})
105733-}
105734-
105735-func uriName(uri span.URI) string {
105736-	return filepath.Base(strings.TrimSuffix(uri.Filename(), ".go"))
105737-}
105738-
105739-// TODO(golang/go#54845): improve the formatting here to match standard
105740-// line:column position formatting.
105741-func SpanName(spn span.Span) string {
105742-	return fmt.Sprintf("%v_%v_%v", uriName(spn.URI()), spn.Start().Line(), spn.Start().Column())
105743-}
105744-
105745-func CopyFolderToTempDir(folder string) (string, error) {
105746-	if _, err := os.Stat(folder); err != nil {
105747-		return "", err
105748-	}
105749-	dst, err := ioutil.TempDir("", "modfile_test")
105750-	if err != nil {
105751-		return "", err
105752-	}
105753-	fds, err := ioutil.ReadDir(folder)
105754-	if err != nil {
105755-		return "", err
105756-	}
105757-	for _, fd := range fds {
105758-		srcfp := filepath.Join(folder, fd.Name())
105759-		stat, err := os.Stat(srcfp)
105760-		if err != nil {
105761-			return "", err
105762-		}
105763-		if !stat.Mode().IsRegular() {
105764-			return "", fmt.Errorf("cannot copy non regular file %s", srcfp)
105765-		}
105766-		contents, err := ioutil.ReadFile(srcfp)
105767-		if err != nil {
105768-			return "", err
105769-		}
105770-		if err := ioutil.WriteFile(filepath.Join(dst, fd.Name()), contents, stat.Mode()); err != nil {
105771-			return "", err
105772-		}
105773-	}
105774-	return dst, nil
105775-}
105776-
105777-func shouldSkip(data *Data, uri span.URI) bool {
105778-	if data.ModfileFlagAvailable {
105779-		return false
105780-	}
105781-	// If the -modfile flag is not available, then we do not want to run
105782-	// any tests on the go.mod file.
105783-	if strings.HasSuffix(uri.Filename(), ".mod") {
105784-		return true
105785-	}
105786-	// If the -modfile flag is not available, then we do not want to test any
105787-	// uri that contains "go mod tidy".
105788-	m, err := data.Mapper(uri)
105789-	return err == nil && strings.Contains(string(m.Content), ", \"go mod tidy\",")
105790-}
105791diff -urN a/gopls/internal/lsp/tests/util.go b/gopls/internal/lsp/tests/util.go
105792--- a/gopls/internal/lsp/tests/util.go	2000-01-01 00:00:00.000000000 -0000
105793+++ b/gopls/internal/lsp/tests/util.go	1970-01-01 00:00:00.000000000 +0000
105794@@ -1,547 +0,0 @@
105795-// Copyright 2020 The Go Authors. All rights reserved.
105796-// Use of this source code is governed by a BSD-style
105797-// license that can be found in the LICENSE file.
105798-
105799-package tests
105800-
105801-import (
105802-	"bytes"
105803-	"context"
105804-	"fmt"
105805-	"go/token"
105806-	"path"
105807-	"path/filepath"
105808-	"regexp"
105809-	"sort"
105810-	"strconv"
105811-	"strings"
105812-	"testing"
105813-
105814-	"github.com/google/go-cmp/cmp"
105815-	"github.com/google/go-cmp/cmp/cmpopts"
105816-	"golang.org/x/tools/gopls/internal/lsp/protocol"
105817-	"golang.org/x/tools/gopls/internal/lsp/source"
105818-	"golang.org/x/tools/gopls/internal/lsp/source/completion"
105819-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
105820-	"golang.org/x/tools/gopls/internal/span"
105821-)
105822-
105823-var builtins = map[string]bool{
105824-	"append":  true,
105825-	"cap":     true,
105826-	"close":   true,
105827-	"complex": true,
105828-	"copy":    true,
105829-	"delete":  true,
105830-	"error":   true,
105831-	"false":   true,
105832-	"imag":    true,
105833-	"iota":    true,
105834-	"len":     true,
105835-	"make":    true,
105836-	"new":     true,
105837-	"nil":     true,
105838-	"panic":   true,
105839-	"print":   true,
105840-	"println": true,
105841-	"real":    true,
105842-	"recover": true,
105843-	"true":    true,
105844-}
105845-
105846-// DiffLinks takes the links we got and checks if they are located within the source or a Note.
105847-// If the link is within a Note, the link is removed.
105848-// Returns an diff comment if there are differences and empty string if no diffs.
105849-func DiffLinks(mapper *protocol.Mapper, wantLinks []Link, gotLinks []protocol.DocumentLink) string {
105850-	var notePositions []token.Position
105851-	links := make(map[span.Span]string, len(wantLinks))
105852-	for _, link := range wantLinks {
105853-		links[link.Src] = link.Target
105854-		notePositions = append(notePositions, link.NotePosition)
105855-	}
105856-
105857-	var msg strings.Builder
105858-	for _, link := range gotLinks {
105859-		spn, err := mapper.RangeSpan(link.Range)
105860-		if err != nil {
105861-			return fmt.Sprintf("%v", err)
105862-		}
105863-		linkInNote := false
105864-		for _, notePosition := range notePositions {
105865-			// Drop the links found inside expectation notes arguments as this links are not collected by expect package.
105866-			if notePosition.Line == spn.Start().Line() &&
105867-				notePosition.Column <= spn.Start().Column() {
105868-				delete(links, spn)
105869-				linkInNote = true
105870-			}
105871-		}
105872-		if linkInNote {
105873-			continue
105874-		}
105875-
105876-		if target, ok := links[spn]; ok {
105877-			delete(links, spn)
105878-			if target != link.Target {
105879-				fmt.Fprintf(&msg, "%s: want link with target %q, got %q\n", spn, target, link.Target)
105880-			}
105881-		} else {
105882-			fmt.Fprintf(&msg, "%s: got unexpected link with target %q\n", spn, link.Target)
105883-		}
105884-	}
105885-	for spn, target := range links {
105886-		fmt.Fprintf(&msg, "%s: expected link with target %q is missing\n", spn, target)
105887-	}
105888-	return msg.String()
105889-}
105890-
105891-// CompareDiagnostics reports testing errors to t when the diagnostic set got
105892-// does not match want. If the sole expectation has source "no_diagnostics",
105893-// the test expects that no diagnostics were received for the given document.
105894-func CompareDiagnostics(t *testing.T, uri span.URI, want, got []*source.Diagnostic) {
105895-	t.Helper()
105896-	fileName := path.Base(string(uri))
105897-
105898-	// A special case to test that there are no diagnostics for a file.
105899-	if len(want) == 1 && want[0].Source == "no_diagnostics" {
105900-		want = nil
105901-	}
105902-
105903-	// Build a helper function to match an actual diagnostic to an overlapping
105904-	// expected diagnostic (if any).
105905-	unmatched := make([]*source.Diagnostic, len(want))
105906-	copy(unmatched, want)
105907-	source.SortDiagnostics(unmatched)
105908-	match := func(g *source.Diagnostic) *source.Diagnostic {
105909-		// Find the last expected diagnostic d for which start(d) < end(g), and
105910-		// check to see if it overlaps.
105911-		i := sort.Search(len(unmatched), func(i int) bool {
105912-			d := unmatched[i]
105913-			// See rangeOverlaps: if a range is a single point, we consider End to be
105914-			// included in the range...
105915-			if g.Range.Start == g.Range.End {
105916-				return protocol.ComparePosition(d.Range.Start, g.Range.End) > 0
105917-			}
105918-			// ...otherwise the end position of a range is not included.
105919-			return protocol.ComparePosition(d.Range.Start, g.Range.End) >= 0
105920-		})
105921-		if i == 0 {
105922-			return nil
105923-		}
105924-		w := unmatched[i-1]
105925-		if rangeOverlaps(w.Range, g.Range) {
105926-			unmatched = append(unmatched[:i-1], unmatched[i:]...)
105927-			return w
105928-		}
105929-		return nil
105930-	}
105931-
105932-	for _, g := range got {
105933-		w := match(g)
105934-		if w == nil {
105935-			t.Errorf("%s:%s: unexpected diagnostic %q", fileName, g.Range, g.Message)
105936-			continue
105937-		}
105938-		if match, err := regexp.MatchString(w.Message, g.Message); err != nil {
105939-			t.Errorf("%s:%s: invalid regular expression %q: %v", fileName, w.Range.Start, w.Message, err)
105940-		} else if !match {
105941-			t.Errorf("%s:%s: got Message %q, want match for pattern %q", fileName, g.Range.Start, g.Message, w.Message)
105942-		}
105943-		if w.Severity != g.Severity {
105944-			t.Errorf("%s:%s: got Severity %v, want %v", fileName, g.Range.Start, g.Severity, w.Severity)
105945-		}
105946-		if w.Source != g.Source {
105947-			t.Errorf("%s:%s: got Source %v, want %v", fileName, g.Range.Start, g.Source, w.Source)
105948-		}
105949-	}
105950-
105951-	for _, w := range unmatched {
105952-		t.Errorf("%s:%s: unmatched diagnostic pattern %q", fileName, w.Range, w.Message)
105953-	}
105954-}
105955-
105956-// rangeOverlaps reports whether r1 and r2 overlap.
105957-func rangeOverlaps(r1, r2 protocol.Range) bool {
105958-	if inRange(r2.Start, r1) || inRange(r1.Start, r2) {
105959-		return true
105960-	}
105961-	return false
105962-}
105963-
105964-// inRange reports whether p is contained within [r.Start, r.End), or if p ==
105965-// r.Start == r.End (special handling for the case where the range is a single
105966-// point).
105967-func inRange(p protocol.Position, r protocol.Range) bool {
105968-	if protocol.IsPoint(r) {
105969-		return protocol.ComparePosition(r.Start, p) == 0
105970-	}
105971-	if protocol.ComparePosition(r.Start, p) <= 0 && protocol.ComparePosition(p, r.End) < 0 {
105972-		return true
105973-	}
105974-	return false
105975-}
105976-
105977-func DiffCodeLens(uri span.URI, want, got []protocol.CodeLens) string {
105978-	sortCodeLens(want)
105979-	sortCodeLens(got)
105980-
105981-	if len(got) != len(want) {
105982-		return summarizeCodeLens(-1, uri, want, got, "different lengths got %v want %v", len(got), len(want))
105983-	}
105984-	for i, w := range want {
105985-		g := got[i]
105986-		if w.Command.Command != g.Command.Command {
105987-			return summarizeCodeLens(i, uri, want, got, "incorrect Command Name got %v want %v", g.Command.Command, w.Command.Command)
105988-		}
105989-		if w.Command.Title != g.Command.Title {
105990-			return summarizeCodeLens(i, uri, want, got, "incorrect Command Title got %v want %v", g.Command.Title, w.Command.Title)
105991-		}
105992-		if protocol.ComparePosition(w.Range.Start, g.Range.Start) != 0 {
105993-			return summarizeCodeLens(i, uri, want, got, "incorrect Start got %v want %v", g.Range.Start, w.Range.Start)
105994-		}
105995-		if !protocol.IsPoint(g.Range) { // Accept any 'want' range if the codelens returns a zero-length range.
105996-			if protocol.ComparePosition(w.Range.End, g.Range.End) != 0 {
105997-				return summarizeCodeLens(i, uri, want, got, "incorrect End got %v want %v", g.Range.End, w.Range.End)
105998-			}
105999-		}
106000-	}
106001-	return ""
106002-}
106003-
106004-func sortCodeLens(c []protocol.CodeLens) {
106005-	sort.Slice(c, func(i int, j int) bool {
106006-		if r := protocol.CompareRange(c[i].Range, c[j].Range); r != 0 {
106007-			return r < 0
106008-		}
106009-		if c[i].Command.Command < c[j].Command.Command {
106010-			return true
106011-		} else if c[i].Command.Command == c[j].Command.Command {
106012-			return c[i].Command.Title < c[j].Command.Title
106013-		} else {
106014-			return false
106015-		}
106016-	})
106017-}
106018-
106019-func summarizeCodeLens(i int, uri span.URI, want, got []protocol.CodeLens, reason string, args ...interface{}) string {
106020-	msg := &bytes.Buffer{}
106021-	fmt.Fprint(msg, "codelens failed")
106022-	if i >= 0 {
106023-		fmt.Fprintf(msg, " at %d", i)
106024-	}
106025-	fmt.Fprint(msg, " because of ")
106026-	fmt.Fprintf(msg, reason, args...)
106027-	fmt.Fprint(msg, ":\nexpected:\n")
106028-	for _, d := range want {
106029-		fmt.Fprintf(msg, "  %s:%v: %s | %s\n", uri, d.Range, d.Command.Command, d.Command.Title)
106030-	}
106031-	fmt.Fprintf(msg, "got:\n")
106032-	for _, d := range got {
106033-		fmt.Fprintf(msg, "  %s:%v: %s | %s\n", uri, d.Range, d.Command.Command, d.Command.Title)
106034-	}
106035-	return msg.String()
106036-}
106037-
106038-func DiffSignatures(spn span.Span, want, got *protocol.SignatureHelp) string {
106039-	decorate := func(f string, args ...interface{}) string {
106040-		return fmt.Sprintf("invalid signature at %s: %s", spn, fmt.Sprintf(f, args...))
106041-	}
106042-	if len(got.Signatures) != 1 {
106043-		return decorate("wanted 1 signature, got %d", len(got.Signatures))
106044-	}
106045-	if got.ActiveSignature != 0 {
106046-		return decorate("wanted active signature of 0, got %d", int(got.ActiveSignature))
106047-	}
106048-	if want.ActiveParameter != got.ActiveParameter {
106049-		return decorate("wanted active parameter of %d, got %d", want.ActiveParameter, int(got.ActiveParameter))
106050-	}
106051-	g := got.Signatures[0]
106052-	w := want.Signatures[0]
106053-	if diff := compare.Text(NormalizeAny(w.Label), NormalizeAny(g.Label)); diff != "" {
106054-		return decorate("mismatched labels:\n%s", diff)
106055-	}
106056-	var paramParts []string
106057-	for _, p := range g.Parameters {
106058-		paramParts = append(paramParts, p.Label)
106059-	}
106060-	paramsStr := strings.Join(paramParts, ", ")
106061-	if !strings.Contains(g.Label, paramsStr) {
106062-		return decorate("expected signature %q to contain params %q", g.Label, paramsStr)
106063-	}
106064-	return ""
106065-}
106066-
106067-// NormalizeAny replaces occurrences of interface{} in input with any.
106068-//
106069-// In Go 1.18, standard library functions were changed to use the 'any'
106070-// alias in place of interface{}, which affects their type string.
106071-func NormalizeAny(input string) string {
106072-	return strings.ReplaceAll(input, "interface{}", "any")
106073-}
106074-
106075-// DiffCallHierarchyItems returns the diff between expected and actual call locations for incoming/outgoing call hierarchies
106076-func DiffCallHierarchyItems(gotCalls []protocol.CallHierarchyItem, expectedCalls []protocol.CallHierarchyItem) string {
106077-	expected := make(map[protocol.Location]bool)
106078-	for _, call := range expectedCalls {
106079-		expected[protocol.Location{URI: call.URI, Range: call.Range}] = true
106080-	}
106081-
106082-	got := make(map[protocol.Location]bool)
106083-	for _, call := range gotCalls {
106084-		got[protocol.Location{URI: call.URI, Range: call.Range}] = true
106085-	}
106086-	if len(got) != len(expected) {
106087-		return fmt.Sprintf("expected %d calls but got %d", len(expected), len(got))
106088-	}
106089-	for spn := range got {
106090-		if !expected[spn] {
106091-			return fmt.Sprintf("incorrect calls, expected locations %v but got locations %v", expected, got)
106092-		}
106093-	}
106094-	return ""
106095-}
106096-
106097-func FilterBuiltins(src span.Span, items []protocol.CompletionItem) []protocol.CompletionItem {
106098-	var (
106099-		got          []protocol.CompletionItem
106100-		wantBuiltins = strings.Contains(string(src.URI()), "builtins")
106101-		wantKeywords = strings.Contains(string(src.URI()), "keywords")
106102-	)
106103-	for _, item := range items {
106104-		if !wantBuiltins && isBuiltin(item.Label, item.Detail, item.Kind) {
106105-			continue
106106-		}
106107-
106108-		if !wantKeywords && token.Lookup(item.Label).IsKeyword() {
106109-			continue
106110-		}
106111-
106112-		got = append(got, item)
106113-	}
106114-	return got
106115-}
106116-
106117-func isBuiltin(label, detail string, kind protocol.CompletionItemKind) bool {
106118-	if detail == "" && kind == protocol.ClassCompletion {
106119-		return true
106120-	}
106121-	// Remaining builtin constants, variables, interfaces, and functions.
106122-	trimmed := label
106123-	if i := strings.Index(trimmed, "("); i >= 0 {
106124-		trimmed = trimmed[:i]
106125-	}
106126-	return builtins[trimmed]
106127-}
106128-
106129-func CheckCompletionOrder(want, got []protocol.CompletionItem, strictScores bool) string {
106130-	var (
106131-		matchedIdxs []int
106132-		lastGotIdx  int
106133-		lastGotSort float64
106134-		inOrder     = true
106135-		errorMsg    = "completions out of order"
106136-	)
106137-	for _, w := range want {
106138-		var found bool
106139-		for i, g := range got {
106140-			if w.Label == g.Label && NormalizeAny(w.Detail) == NormalizeAny(g.Detail) && w.Kind == g.Kind {
106141-				matchedIdxs = append(matchedIdxs, i)
106142-				found = true
106143-
106144-				if i < lastGotIdx {
106145-					inOrder = false
106146-				}
106147-				lastGotIdx = i
106148-
106149-				sort, _ := strconv.ParseFloat(g.SortText, 64)
106150-				if strictScores && len(matchedIdxs) > 1 && sort <= lastGotSort {
106151-					inOrder = false
106152-					errorMsg = "candidate scores not strictly decreasing"
106153-				}
106154-				lastGotSort = sort
106155-
106156-				break
106157-			}
106158-		}
106159-		if !found {
106160-			return summarizeCompletionItems(-1, []protocol.CompletionItem{w}, got, "didn't find expected completion")
106161-		}
106162-	}
106163-
106164-	sort.Ints(matchedIdxs)
106165-	matched := make([]protocol.CompletionItem, 0, len(matchedIdxs))
106166-	for _, idx := range matchedIdxs {
106167-		matched = append(matched, got[idx])
106168-	}
106169-
106170-	if !inOrder {
106171-		return summarizeCompletionItems(-1, want, matched, errorMsg)
106172-	}
106173-
106174-	return ""
106175-}
106176-
106177-func DiffSnippets(want string, got *protocol.CompletionItem) string {
106178-	if want == "" {
106179-		if got != nil {
106180-			x := got.TextEdit
106181-			return fmt.Sprintf("expected no snippet but got %s", x.NewText)
106182-		}
106183-	} else {
106184-		if got == nil {
106185-			return fmt.Sprintf("couldn't find completion matching %q", want)
106186-		}
106187-		x := got.TextEdit
106188-		if want != x.NewText {
106189-			return fmt.Sprintf("expected snippet %q, got %q", want, x.NewText)
106190-		}
106191-	}
106192-	return ""
106193-}
106194-
106195-func FindItem(list []protocol.CompletionItem, want completion.CompletionItem) *protocol.CompletionItem {
106196-	for _, item := range list {
106197-		if item.Label == want.Label {
106198-			return &item
106199-		}
106200-	}
106201-	return nil
106202-}
106203-
106204-// DiffCompletionItems prints the diff between expected and actual completion
106205-// test results.
106206-//
106207-// The diff will be formatted using '-' and '+' for want and got, respectively.
106208-func DiffCompletionItems(want, got []protocol.CompletionItem) string {
106209-	// Many fields are not set in the "want" slice.
106210-	irrelevantFields := []string{
106211-		"AdditionalTextEdits",
106212-		"Documentation",
106213-		"TextEdit",
106214-		"SortText",
106215-		"Preselect",
106216-		"FilterText",
106217-		"InsertText",
106218-		"InsertTextFormat",
106219-	}
106220-	ignore := cmpopts.IgnoreFields(protocol.CompletionItem{}, irrelevantFields...)
106221-	normalizeAny := cmpopts.AcyclicTransformer("NormalizeAny", func(item protocol.CompletionItem) protocol.CompletionItem {
106222-		item.Detail = NormalizeAny(item.Detail)
106223-		return item
106224-	})
106225-	return cmp.Diff(want, got, ignore, normalizeAny)
106226-}
106227-
106228-func summarizeCompletionItems(i int, want, got []protocol.CompletionItem, reason string, args ...interface{}) string {
106229-	msg := &bytes.Buffer{}
106230-	fmt.Fprint(msg, "completion failed")
106231-	if i >= 0 {
106232-		fmt.Fprintf(msg, " at %d", i)
106233-	}
106234-	fmt.Fprint(msg, " because of ")
106235-	fmt.Fprintf(msg, reason, args...)
106236-	fmt.Fprint(msg, ":\nexpected:\n")
106237-	for _, d := range want {
106238-		fmt.Fprintf(msg, "  %v\n", d)
106239-	}
106240-	fmt.Fprintf(msg, "got:\n")
106241-	for _, d := range got {
106242-		fmt.Fprintf(msg, "  %v\n", d)
106243-	}
106244-	return msg.String()
106245-}
106246-
106247-func EnableAllAnalyzers(opts *source.Options) {
106248-	if opts.Analyses == nil {
106249-		opts.Analyses = make(map[string]bool)
106250-	}
106251-	for _, a := range opts.DefaultAnalyzers {
106252-		if !a.IsEnabled(opts) {
106253-			opts.Analyses[a.Analyzer.Name] = true
106254-		}
106255-	}
106256-	for _, a := range opts.TypeErrorAnalyzers {
106257-		if !a.IsEnabled(opts) {
106258-			opts.Analyses[a.Analyzer.Name] = true
106259-		}
106260-	}
106261-	for _, a := range opts.ConvenienceAnalyzers {
106262-		if !a.IsEnabled(opts) {
106263-			opts.Analyses[a.Analyzer.Name] = true
106264-		}
106265-	}
106266-	for _, a := range opts.StaticcheckAnalyzers {
106267-		if !a.IsEnabled(opts) {
106268-			opts.Analyses[a.Analyzer.Name] = true
106269-		}
106270-	}
106271-}
106272-
106273-func EnableAllInlayHints(opts *source.Options) {
106274-	if opts.Hints == nil {
106275-		opts.Hints = make(map[string]bool)
106276-	}
106277-	for name := range source.AllInlayHints {
106278-		opts.Hints[name] = true
106279-	}
106280-}
106281-
106282-func WorkspaceSymbolsString(ctx context.Context, data *Data, queryURI span.URI, symbols []protocol.SymbolInformation) (string, error) {
106283-	queryDir := filepath.Dir(queryURI.Filename())
106284-	var filtered []string
106285-	for _, s := range symbols {
106286-		uri := s.Location.URI.SpanURI()
106287-		dir := filepath.Dir(uri.Filename())
106288-		if !source.InDir(queryDir, dir) { // assume queries always issue from higher directories
106289-			continue
106290-		}
106291-		m, err := data.Mapper(uri)
106292-		if err != nil {
106293-			return "", err
106294-		}
106295-		spn, err := m.LocationSpan(s.Location)
106296-		if err != nil {
106297-			return "", err
106298-		}
106299-		filtered = append(filtered, fmt.Sprintf("%s %s %s", spn, s.Name, s.Kind))
106300-	}
106301-	sort.Strings(filtered)
106302-	return strings.Join(filtered, "\n") + "\n", nil
106303-}
106304-
106305-func WorkspaceSymbolsTestTypeToMatcher(typ WorkspaceSymbolsTestType) source.SymbolMatcher {
106306-	switch typ {
106307-	case WorkspaceSymbolsFuzzy:
106308-		return source.SymbolFuzzy
106309-	case WorkspaceSymbolsCaseSensitive:
106310-		return source.SymbolCaseSensitive
106311-	default:
106312-		return source.SymbolCaseInsensitive
106313-	}
106314-}
106315-
106316-// LocationsToSpans converts protocol location into span form for testing.
106317-func LocationsToSpans(data *Data, locs []protocol.Location) ([]span.Span, error) {
106318-	spans := make([]span.Span, len(locs))
106319-	for i, loc := range locs {
106320-		m, err := data.Mapper(loc.URI.SpanURI())
106321-		if err != nil {
106322-			return nil, err
106323-		}
106324-		spn, err := m.LocationSpan(loc)
106325-		if err != nil {
106326-			return nil, fmt.Errorf("failed for %v: %w", loc, err)
106327-		}
106328-		spans[i] = spn
106329-	}
106330-	return spans, nil
106331-}
106332-
106333-// SortAndFormatSpans sorts and formats a list of spans for use in an assertion.
106334-func SortAndFormatSpans(spans []span.Span) string {
106335-	span.SortSpans(spans)
106336-	var buf strings.Builder
106337-	for _, spn := range spans {
106338-		fmt.Fprintf(&buf, "%v\n", spn)
106339-	}
106340-	return buf.String()
106341-}
106342diff -urN a/gopls/internal/lsp/tests/util_go118.go b/gopls/internal/lsp/tests/util_go118.go
106343--- a/gopls/internal/lsp/tests/util_go118.go	2000-01-01 00:00:00.000000000 -0000
106344+++ b/gopls/internal/lsp/tests/util_go118.go	1970-01-01 00:00:00.000000000 +0000
106345@@ -1,13 +0,0 @@
106346-// Copyright 2023 The Go Authors. All rights reserved.
106347-// Use of this source code is governed by a BSD-style
106348-// license that can be found in the LICENSE file.
106349-
106350-//go:build go1.18
106351-// +build go1.18
106352-
106353-package tests
106354-
106355-func init() {
106356-	builtins["any"] = true
106357-	builtins["comparable"] = true
106358-}
106359diff -urN a/gopls/internal/lsp/tests/util_go121.go b/gopls/internal/lsp/tests/util_go121.go
106360--- a/gopls/internal/lsp/tests/util_go121.go	2000-01-01 00:00:00.000000000 -0000
106361+++ b/gopls/internal/lsp/tests/util_go121.go	1970-01-01 00:00:00.000000000 +0000
106362@@ -1,12 +0,0 @@
106363-// Copyright 2023 The Go Authors. All rights reserved.
106364-// Use of this source code is governed by a BSD-style
106365-// license that can be found in the LICENSE file.
106366-
106367-//go:build go1.21
106368-// +build go1.21
106369-
106370-package tests
106371-
106372-func init() {
106373-	builtins["clear"] = true
106374-}
106375diff -urN a/gopls/internal/lsp/text_synchronization.go b/gopls/internal/lsp/text_synchronization.go
106376--- a/gopls/internal/lsp/text_synchronization.go	2000-01-01 00:00:00.000000000 -0000
106377+++ b/gopls/internal/lsp/text_synchronization.go	1970-01-01 00:00:00.000000000 +0000
106378@@ -1,349 +0,0 @@
106379-// Copyright 2019 The Go Authors. All rights reserved.
106380-// Use of this source code is governed by a BSD-style
106381-// license that can be found in the LICENSE file.
106382-
106383-package lsp
106384-
106385-import (
106386-	"bytes"
106387-	"context"
106388-	"errors"
106389-	"fmt"
106390-	"path/filepath"
106391-	"sync"
106392-
106393-	"golang.org/x/tools/gopls/internal/lsp/protocol"
106394-	"golang.org/x/tools/gopls/internal/lsp/source"
106395-	"golang.org/x/tools/gopls/internal/span"
106396-	"golang.org/x/tools/internal/jsonrpc2"
106397-)
106398-
106399-// ModificationSource identifies the originating cause of a file modification.
106400-type ModificationSource int
106401-
106402-const (
106403-	// FromDidOpen is a file modification caused by opening a file.
106404-	FromDidOpen = ModificationSource(iota)
106405-
106406-	// FromDidChange is a file modification caused by changing a file.
106407-	FromDidChange
106408-
106409-	// FromDidChangeWatchedFiles is a file modification caused by a change to a
106410-	// watched file.
106411-	FromDidChangeWatchedFiles
106412-
106413-	// FromDidSave is a file modification caused by a file save.
106414-	FromDidSave
106415-
106416-	// FromDidClose is a file modification caused by closing a file.
106417-	FromDidClose
106418-
106419-	// TODO: add FromDidChangeConfiguration, once configuration changes cause a
106420-	// new snapshot to be created.
106421-
106422-	// FromRegenerateCgo refers to file modifications caused by regenerating
106423-	// the cgo sources for the workspace.
106424-	FromRegenerateCgo
106425-
106426-	// FromInitialWorkspaceLoad refers to the loading of all packages in the
106427-	// workspace when the view is first created.
106428-	FromInitialWorkspaceLoad
106429-)
106430-
106431-func (m ModificationSource) String() string {
106432-	switch m {
106433-	case FromDidOpen:
106434-		return "opened files"
106435-	case FromDidChange:
106436-		return "changed files"
106437-	case FromDidChangeWatchedFiles:
106438-		return "files changed on disk"
106439-	case FromDidSave:
106440-		return "saved files"
106441-	case FromDidClose:
106442-		return "close files"
106443-	case FromRegenerateCgo:
106444-		return "regenerate cgo"
106445-	case FromInitialWorkspaceLoad:
106446-		return "initial workspace load"
106447-	default:
106448-		return "unknown file modification"
106449-	}
106450-}
106451-
106452-func (s *Server) didOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error {
106453-	uri := params.TextDocument.URI.SpanURI()
106454-	if !uri.IsFile() {
106455-		return nil
106456-	}
106457-	// There may not be any matching view in the current session. If that's
106458-	// the case, try creating a new view based on the opened file path.
106459-	//
106460-	// TODO(rstambler): This seems like it would continuously add new
106461-	// views, but it won't because ViewOf only returns an error when there
106462-	// are no views in the session. I don't know if that logic should go
106463-	// here, or if we can continue to rely on that implementation detail.
106464-	if _, err := s.session.ViewOf(uri); err != nil {
106465-		dir := filepath.Dir(uri.Filename())
106466-		if err := s.addFolders(ctx, []protocol.WorkspaceFolder{{
106467-			URI:  string(protocol.URIFromPath(dir)),
106468-			Name: filepath.Base(dir),
106469-		}}); err != nil {
106470-			return err
106471-		}
106472-	}
106473-	return s.didModifyFiles(ctx, []source.FileModification{{
106474-		URI:        uri,
106475-		Action:     source.Open,
106476-		Version:    params.TextDocument.Version,
106477-		Text:       []byte(params.TextDocument.Text),
106478-		LanguageID: params.TextDocument.LanguageID,
106479-	}}, FromDidOpen)
106480-}
106481-
106482-func (s *Server) didChange(ctx context.Context, params *protocol.DidChangeTextDocumentParams) error {
106483-	uri := params.TextDocument.URI.SpanURI()
106484-	if !uri.IsFile() {
106485-		return nil
106486-	}
106487-
106488-	text, err := s.changedText(ctx, uri, params.ContentChanges)
106489-	if err != nil {
106490-		return err
106491-	}
106492-	c := source.FileModification{
106493-		URI:     uri,
106494-		Action:  source.Change,
106495-		Version: params.TextDocument.Version,
106496-		Text:    text,
106497-	}
106498-	if err := s.didModifyFiles(ctx, []source.FileModification{c}, FromDidChange); err != nil {
106499-		return err
106500-	}
106501-	return s.warnAboutModifyingGeneratedFiles(ctx, uri)
106502-}
106503-
106504-// warnAboutModifyingGeneratedFiles shows a warning if a user tries to edit a
106505-// generated file for the first time.
106506-func (s *Server) warnAboutModifyingGeneratedFiles(ctx context.Context, uri span.URI) error {
106507-	s.changedFilesMu.Lock()
106508-	_, ok := s.changedFiles[uri]
106509-	if !ok {
106510-		s.changedFiles[uri] = struct{}{}
106511-	}
106512-	s.changedFilesMu.Unlock()
106513-
106514-	// This file has already been edited before.
106515-	if ok {
106516-		return nil
106517-	}
106518-
106519-	// Ideally, we should be able to specify that a generated file should
106520-	// be opened as read-only. Tell the user that they should not be
106521-	// editing a generated file.
106522-	view, err := s.session.ViewOf(uri)
106523-	if err != nil {
106524-		return err
106525-	}
106526-	snapshot, release, err := view.Snapshot()
106527-	if err != nil {
106528-		return err
106529-	}
106530-	isGenerated := source.IsGenerated(ctx, snapshot, uri)
106531-	release()
106532-
106533-	if !isGenerated {
106534-		return nil
106535-	}
106536-	return s.client.ShowMessage(ctx, &protocol.ShowMessageParams{
106537-		Message: fmt.Sprintf("Do not edit this file! %s is a generated file.", uri.Filename()),
106538-		Type:    protocol.Warning,
106539-	})
106540-}
106541-
106542-func (s *Server) didChangeWatchedFiles(ctx context.Context, params *protocol.DidChangeWatchedFilesParams) error {
106543-	var modifications []source.FileModification
106544-	for _, change := range params.Changes {
106545-		uri := change.URI.SpanURI()
106546-		if !uri.IsFile() {
106547-			continue
106548-		}
106549-		action := changeTypeToFileAction(change.Type)
106550-		modifications = append(modifications, source.FileModification{
106551-			URI:    uri,
106552-			Action: action,
106553-			OnDisk: true,
106554-		})
106555-	}
106556-	return s.didModifyFiles(ctx, modifications, FromDidChangeWatchedFiles)
106557-}
106558-
106559-func (s *Server) didSave(ctx context.Context, params *protocol.DidSaveTextDocumentParams) error {
106560-	uri := params.TextDocument.URI.SpanURI()
106561-	if !uri.IsFile() {
106562-		return nil
106563-	}
106564-	c := source.FileModification{
106565-		URI:    uri,
106566-		Action: source.Save,
106567-	}
106568-	if params.Text != nil {
106569-		c.Text = []byte(*params.Text)
106570-	}
106571-	return s.didModifyFiles(ctx, []source.FileModification{c}, FromDidSave)
106572-}
106573-
106574-func (s *Server) didClose(ctx context.Context, params *protocol.DidCloseTextDocumentParams) error {
106575-	uri := params.TextDocument.URI.SpanURI()
106576-	if !uri.IsFile() {
106577-		return nil
106578-	}
106579-	return s.didModifyFiles(ctx, []source.FileModification{
106580-		{
106581-			URI:     uri,
106582-			Action:  source.Close,
106583-			Version: -1,
106584-			Text:    nil,
106585-		},
106586-	}, FromDidClose)
106587-}
106588-
106589-func (s *Server) didModifyFiles(ctx context.Context, modifications []source.FileModification, cause ModificationSource) error {
106590-	// wg guards two conditions:
106591-	//  1. didModifyFiles is complete
106592-	//  2. the goroutine diagnosing changes on behalf of didModifyFiles is
106593-	//     complete, if it was started
106594-	//
106595-	// Both conditions must be satisfied for the purpose of testing: we don't
106596-	// want to observe the completion of change processing until we have received
106597-	// all diagnostics as well as all server->client notifications done on behalf
106598-	// of this function.
106599-	var wg sync.WaitGroup
106600-	wg.Add(1)
106601-	defer wg.Done()
106602-
106603-	if s.session.Options().VerboseWorkDoneProgress {
106604-		work := s.progress.Start(ctx, DiagnosticWorkTitle(cause), "Calculating file diagnostics...", nil, nil)
106605-		go func() {
106606-			wg.Wait()
106607-			work.End(ctx, "Done.")
106608-		}()
106609-	}
106610-
106611-	onDisk := cause == FromDidChangeWatchedFiles
106612-
106613-	s.stateMu.Lock()
106614-	if s.state >= serverShutDown {
106615-		// This state check does not prevent races below, and exists only to
106616-		// produce a better error message. The actual race to the cache should be
106617-		// guarded by Session.viewMu.
106618-		s.stateMu.Unlock()
106619-		return errors.New("server is shut down")
106620-	}
106621-	s.stateMu.Unlock()
106622-
106623-	// If the set of changes included directories, expand those directories
106624-	// to their files.
106625-	modifications = s.session.ExpandModificationsToDirectories(ctx, modifications)
106626-
106627-	// Build a lookup map for file modifications, so that we can later join
106628-	// with the snapshot file associations.
106629-	modMap := make(map[span.URI]source.FileModification)
106630-	for _, mod := range modifications {
106631-		modMap[mod.URI] = mod
106632-	}
106633-
106634-	snapshots, release, err := s.session.DidModifyFiles(ctx, modifications)
106635-	if err != nil {
106636-		return err
106637-	}
106638-
106639-	// golang/go#50267: diagnostics should be re-sent after an open or close. For
106640-	// some clients, it may be helpful to re-send after each change.
106641-	for snapshot, uris := range snapshots {
106642-		for _, uri := range uris {
106643-			mod := modMap[uri]
106644-			if snapshot.View().Options().ChattyDiagnostics || mod.Action == source.Open || mod.Action == source.Close {
106645-				s.mustPublishDiagnostics(uri)
106646-			}
106647-		}
106648-	}
106649-
106650-	wg.Add(1)
106651-	go func() {
106652-		s.diagnoseSnapshots(snapshots, onDisk)
106653-		release()
106654-		wg.Done()
106655-	}()
106656-
106657-	// After any file modifications, we need to update our watched files,
106658-	// in case something changed. Compute the new set of directories to watch,
106659-	// and if it differs from the current set, send updated registrations.
106660-	return s.updateWatchedDirectories(ctx)
106661-}
106662-
106663-// DiagnosticWorkTitle returns the title of the diagnostic work resulting from a
106664-// file change originating from the given cause.
106665-func DiagnosticWorkTitle(cause ModificationSource) string {
106666-	return fmt.Sprintf("diagnosing %v", cause)
106667-}
106668-
106669-func (s *Server) changedText(ctx context.Context, uri span.URI, changes []protocol.TextDocumentContentChangeEvent) ([]byte, error) {
106670-	if len(changes) == 0 {
106671-		return nil, fmt.Errorf("%w: no content changes provided", jsonrpc2.ErrInternal)
106672-	}
106673-
106674-	// Check if the client sent the full content of the file.
106675-	// We accept a full content change even if the server expected incremental changes.
106676-	if len(changes) == 1 && changes[0].Range == nil && changes[0].RangeLength == 0 {
106677-		return []byte(changes[0].Text), nil
106678-	}
106679-	return s.applyIncrementalChanges(ctx, uri, changes)
106680-}
106681-
106682-func (s *Server) applyIncrementalChanges(ctx context.Context, uri span.URI, changes []protocol.TextDocumentContentChangeEvent) ([]byte, error) {
106683-	fh, err := s.session.GetFile(ctx, uri)
106684-	if err != nil {
106685-		return nil, err
106686-	}
106687-	content, err := fh.Read()
106688-	if err != nil {
106689-		return nil, fmt.Errorf("%w: file not found (%v)", jsonrpc2.ErrInternal, err)
106690-	}
106691-	for _, change := range changes {
106692-		// TODO(adonovan): refactor to use diff.Apply, which is robust w.r.t.
106693-		// out-of-order or overlapping changes---and much more efficient.
106694-
106695-		// Make sure to update mapper along with the content.
106696-		m := protocol.NewMapper(uri, content)
106697-		if change.Range == nil {
106698-			return nil, fmt.Errorf("%w: unexpected nil range for change", jsonrpc2.ErrInternal)
106699-		}
106700-		spn, err := m.RangeSpan(*change.Range)
106701-		if err != nil {
106702-			return nil, err
106703-		}
106704-		start, end := spn.Start().Offset(), spn.End().Offset()
106705-		if end < start {
106706-			return nil, fmt.Errorf("%w: invalid range for content change", jsonrpc2.ErrInternal)
106707-		}
106708-		var buf bytes.Buffer
106709-		buf.Write(content[:start])
106710-		buf.WriteString(change.Text)
106711-		buf.Write(content[end:])
106712-		content = buf.Bytes()
106713-	}
106714-	return content, nil
106715-}
106716-
106717-func changeTypeToFileAction(ct protocol.FileChangeType) source.FileAction {
106718-	switch ct {
106719-	case protocol.Changed:
106720-		return source.Change
106721-	case protocol.Created:
106722-		return source.Create
106723-	case protocol.Deleted:
106724-		return source.Delete
106725-	}
106726-	return source.UnknownFileAction
106727-}
106728diff -urN a/gopls/internal/lsp/work/completion.go b/gopls/internal/lsp/work/completion.go
106729--- a/gopls/internal/lsp/work/completion.go	2000-01-01 00:00:00.000000000 -0000
106730+++ b/gopls/internal/lsp/work/completion.go	1970-01-01 00:00:00.000000000 +0000
106731@@ -1,154 +0,0 @@
106732-// Copyright 2022 The Go Authors. All rights reserved.
106733-// Use of this source code is governed by a BSD-style
106734-// license that can be found in the LICENSE file.
106735-
106736-package work
106737-
106738-import (
106739-	"context"
106740-	"errors"
106741-	"fmt"
106742-	"os"
106743-	"path/filepath"
106744-	"sort"
106745-	"strings"
106746-
106747-	"golang.org/x/tools/gopls/internal/lsp/protocol"
106748-	"golang.org/x/tools/gopls/internal/lsp/source"
106749-	"golang.org/x/tools/internal/event"
106750-)
106751-
106752-func Completion(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle, position protocol.Position) (*protocol.CompletionList, error) {
106753-	ctx, done := event.Start(ctx, "work.Completion")
106754-	defer done()
106755-
106756-	// Get the position of the cursor.
106757-	pw, err := snapshot.ParseWork(ctx, fh)
106758-	if err != nil {
106759-		return nil, fmt.Errorf("getting go.work file handle: %w", err)
106760-	}
106761-	cursor, err := pw.Mapper.PositionOffset(position)
106762-	if err != nil {
106763-		return nil, fmt.Errorf("computing cursor offset: %w", err)
106764-	}
106765-
106766-	// Find the use statement the user is in.
106767-	use, pathStart, _ := usePath(pw, cursor)
106768-	if use == nil {
106769-		return &protocol.CompletionList{}, nil
106770-	}
106771-	completingFrom := use.Path[:cursor-pathStart]
106772-
106773-	// We're going to find the completions of the user input
106774-	// (completingFrom) by doing a walk on the innermost directory
106775-	// of the given path, and comparing the found paths to make sure
106776-	// that they match the component of the path after the
106777-	// innermost directory.
106778-	//
106779-	// We'll maintain two paths when doing this: pathPrefixSlash
106780-	// is essentially the path the user typed in, and pathPrefixAbs
106781-	// is the path made absolute from the go.work directory.
106782-
106783-	pathPrefixSlash := completingFrom
106784-	pathPrefixAbs := filepath.FromSlash(pathPrefixSlash)
106785-	if !filepath.IsAbs(pathPrefixAbs) {
106786-		pathPrefixAbs = filepath.Join(filepath.Dir(pw.URI.Filename()), pathPrefixAbs)
106787-	}
106788-
106789-	// pathPrefixDir is the directory that will be walked to find matches.
106790-	// If pathPrefixSlash is not explicitly a directory boundary (is either equivalent to "." or
106791-	// ends in a separator) we need to examine its parent directory to find sibling files that
106792-	// match.
106793-	depthBound := 5
106794-	pathPrefixDir, pathPrefixBase := pathPrefixAbs, ""
106795-	pathPrefixSlashDir := pathPrefixSlash
106796-	if filepath.Clean(pathPrefixSlash) != "." && !strings.HasSuffix(pathPrefixSlash, "/") {
106797-		depthBound++
106798-		pathPrefixDir, pathPrefixBase = filepath.Split(pathPrefixAbs)
106799-		pathPrefixSlashDir = dirNonClean(pathPrefixSlash)
106800-	}
106801-
106802-	var completions []string
106803-	// Stop traversing deeper once we've hit 10k files to try to stay generally under 100ms.
106804-	const numSeenBound = 10000
106805-	var numSeen int
106806-	stopWalking := errors.New("hit numSeenBound")
106807-	err = filepath.Walk(pathPrefixDir, func(wpath string, info os.FileInfo, err error) error {
106808-		if numSeen > numSeenBound {
106809-			// Stop traversing if we hit bound.
106810-			return stopWalking
106811-		}
106812-		numSeen++
106813-
106814-		// rel is the path relative to pathPrefixDir.
106815-		// Make sure that it has pathPrefixBase as a prefix
106816-		// otherwise it won't match the beginning of the
106817-		// base component of the path the user typed in.
106818-		rel := strings.TrimPrefix(wpath[len(pathPrefixDir):], string(filepath.Separator))
106819-		if info.IsDir() && wpath != pathPrefixDir && !strings.HasPrefix(rel, pathPrefixBase) {
106820-			return filepath.SkipDir
106821-		}
106822-
106823-		// Check for a match (a module directory).
106824-		if filepath.Base(rel) == "go.mod" {
106825-			relDir := strings.TrimSuffix(dirNonClean(rel), string(os.PathSeparator))
106826-			completionPath := join(pathPrefixSlashDir, filepath.ToSlash(relDir))
106827-
106828-			if !strings.HasPrefix(completionPath, completingFrom) {
106829-				return nil
106830-			}
106831-			if strings.HasSuffix(completionPath, "/") {
106832-				// Don't suggest paths that end in "/". This happens
106833-				// when the input is a path that ends in "/" and
106834-				// the completion is empty.
106835-				return nil
106836-			}
106837-			completion := completionPath[len(completingFrom):]
106838-			if completingFrom == "" && !strings.HasPrefix(completion, "./") {
106839-				// Bias towards "./" prefixes.
106840-				completion = join(".", completion)
106841-			}
106842-
106843-			completions = append(completions, completion)
106844-		}
106845-
106846-		if depth := strings.Count(rel, string(filepath.Separator)); depth >= depthBound {
106847-			return filepath.SkipDir
106848-		}
106849-		return nil
106850-	})
106851-	if err != nil && !errors.Is(err, stopWalking) {
106852-		return nil, fmt.Errorf("walking to find completions: %w", err)
106853-	}
106854-
106855-	sort.Strings(completions)
106856-
106857-	var items []protocol.CompletionItem
106858-	for _, c := range completions {
106859-		items = append(items, protocol.CompletionItem{
106860-			Label:      c,
106861-			InsertText: c,
106862-		})
106863-	}
106864-	return &protocol.CompletionList{Items: items}, nil
106865-}
106866-
106867-// dirNonClean is filepath.Dir, without the Clean at the end.
106868-func dirNonClean(path string) string {
106869-	vol := filepath.VolumeName(path)
106870-	i := len(path) - 1
106871-	for i >= len(vol) && !os.IsPathSeparator(path[i]) {
106872-		i--
106873-	}
106874-	return path[len(vol) : i+1]
106875-}
106876-
106877-func join(a, b string) string {
106878-	if a == "" {
106879-		return b
106880-	}
106881-	if b == "" {
106882-		return a
106883-	}
106884-	return strings.TrimSuffix(a, "/") + "/" + b
106885-}
106886diff -urN a/gopls/internal/lsp/work/diagnostics.go b/gopls/internal/lsp/work/diagnostics.go
106887--- a/gopls/internal/lsp/work/diagnostics.go	2000-01-01 00:00:00.000000000 -0000
106888+++ b/gopls/internal/lsp/work/diagnostics.go	1970-01-01 00:00:00.000000000 +0000
106889@@ -1,92 +0,0 @@
106890-// Copyright 2022 The Go Authors. All rights reserved.
106891-// Use of this source code is governed by a BSD-style
106892-// license that can be found in the LICENSE file.
106893-
106894-package work
106895-
106896-import (
106897-	"context"
106898-	"fmt"
106899-	"os"
106900-	"path/filepath"
106901-
106902-	"golang.org/x/mod/modfile"
106903-	"golang.org/x/tools/gopls/internal/lsp/protocol"
106904-	"golang.org/x/tools/gopls/internal/lsp/source"
106905-	"golang.org/x/tools/gopls/internal/span"
106906-	"golang.org/x/tools/internal/event"
106907-)
106908-
106909-func Diagnostics(ctx context.Context, snapshot source.Snapshot) (map[span.URI][]*source.Diagnostic, error) {
106910-	ctx, done := event.Start(ctx, "work.Diagnostics", source.SnapshotLabels(snapshot)...)
106911-	defer done()
106912-
106913-	reports := map[span.URI][]*source.Diagnostic{}
106914-	uri := snapshot.WorkFile()
106915-	if uri == "" {
106916-		return nil, nil
106917-	}
106918-	fh, err := snapshot.GetFile(ctx, uri)
106919-	if err != nil {
106920-		return nil, err
106921-	}
106922-	reports[fh.URI()] = []*source.Diagnostic{}
106923-	diagnostics, err := DiagnosticsForWork(ctx, snapshot, fh)
106924-	if err != nil {
106925-		return nil, err
106926-	}
106927-	for _, d := range diagnostics {
106928-		fh, err := snapshot.GetFile(ctx, d.URI)
106929-		if err != nil {
106930-			return nil, err
106931-		}
106932-		reports[fh.URI()] = append(reports[fh.URI()], d)
106933-	}
106934-
106935-	return reports, nil
106936-}
106937-
106938-func DiagnosticsForWork(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) ([]*source.Diagnostic, error) {
106939-	pw, err := snapshot.ParseWork(ctx, fh)
106940-	if err != nil {
106941-		if pw == nil || len(pw.ParseErrors) == 0 {
106942-			return nil, err
106943-		}
106944-		return pw.ParseErrors, nil
106945-	}
106946-
106947-	// Add diagnostic if a directory does not contain a module.
106948-	var diagnostics []*source.Diagnostic
106949-	for _, use := range pw.File.Use {
106950-		rng, err := pw.Mapper.OffsetRange(use.Syntax.Start.Byte, use.Syntax.End.Byte)
106951-		if err != nil {
106952-			return nil, err
106953-		}
106954-
106955-		modfh, err := snapshot.GetFile(ctx, modFileURI(pw, use))
106956-		if err != nil {
106957-			return nil, err
106958-		}
106959-		if _, err := modfh.Read(); err != nil && os.IsNotExist(err) {
106960-			diagnostics = append(diagnostics, &source.Diagnostic{
106961-				URI:      fh.URI(),
106962-				Range:    rng,
106963-				Severity: protocol.SeverityError,
106964-				Source:   source.WorkFileError,
106965-				Message:  fmt.Sprintf("directory %v does not contain a module", use.Path),
106966-			})
106967-		}
106968-	}
106969-	return diagnostics, nil
106970-}
106971-
106972-func modFileURI(pw *source.ParsedWorkFile, use *modfile.Use) span.URI {
106973-	workdir := filepath.Dir(pw.URI.Filename())
106974-
106975-	modroot := filepath.FromSlash(use.Path)
106976-	if !filepath.IsAbs(modroot) {
106977-		modroot = filepath.Join(workdir, modroot)
106978-	}
106979-
106980-	return span.URIFromPath(filepath.Join(modroot, "go.mod"))
106981-}
106982diff -urN a/gopls/internal/lsp/work/format.go b/gopls/internal/lsp/work/format.go
106983--- a/gopls/internal/lsp/work/format.go	2000-01-01 00:00:00.000000000 -0000
106984+++ b/gopls/internal/lsp/work/format.go	1970-01-01 00:00:00.000000000 +0000
106985@@ -1,28 +0,0 @@
106986-// Copyright 2022 The Go Authors. All rights reserved.
106987-// Use of this source code is governed by a BSD-style
106988-// license that can be found in the LICENSE file.
106989-
106990-package work
106991-
106992-import (
106993-	"context"
106994-
106995-	"golang.org/x/mod/modfile"
106996-	"golang.org/x/tools/gopls/internal/lsp/protocol"
106997-	"golang.org/x/tools/gopls/internal/lsp/source"
106998-	"golang.org/x/tools/internal/event"
106999-)
107000-
107001-func Format(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) ([]protocol.TextEdit, error) {
107002-	ctx, done := event.Start(ctx, "work.Format")
107003-	defer done()
107004-
107005-	pw, err := snapshot.ParseWork(ctx, fh)
107006-	if err != nil {
107007-		return nil, err
107008-	}
107009-	formatted := modfile.Format(pw.File.Syntax)
107010-	// Calculate the edits to be made due to the change.
107011-	diffs := snapshot.View().Options().ComputeEdits(string(pw.Mapper.Content), string(formatted))
107012-	return source.ToProtocolEdits(pw.Mapper, diffs)
107013-}
107014diff -urN a/gopls/internal/lsp/work/hover.go b/gopls/internal/lsp/work/hover.go
107015--- a/gopls/internal/lsp/work/hover.go	2000-01-01 00:00:00.000000000 -0000
107016+++ b/gopls/internal/lsp/work/hover.go	1970-01-01 00:00:00.000000000 +0000
107017@@ -1,89 +0,0 @@
107018-// Copyright 2022 The Go Authors. All rights reserved.
107019-// Use of this source code is governed by a BSD-style
107020-// license that can be found in the LICENSE file.
107021-
107022-package work
107023-
107024-import (
107025-	"bytes"
107026-	"context"
107027-	"fmt"
107028-
107029-	"golang.org/x/mod/modfile"
107030-	"golang.org/x/tools/gopls/internal/lsp/protocol"
107031-	"golang.org/x/tools/gopls/internal/lsp/source"
107032-	"golang.org/x/tools/internal/event"
107033-)
107034-
107035-func Hover(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle, position protocol.Position) (*protocol.Hover, error) {
107036-	// We only provide hover information for the view's go.work file.
107037-	if fh.URI() != snapshot.WorkFile() {
107038-		return nil, nil
107039-	}
107040-
107041-	ctx, done := event.Start(ctx, "work.Hover")
107042-	defer done()
107043-
107044-	// Get the position of the cursor.
107045-	pw, err := snapshot.ParseWork(ctx, fh)
107046-	if err != nil {
107047-		return nil, fmt.Errorf("getting go.work file handle: %w", err)
107048-	}
107049-	offset, err := pw.Mapper.PositionOffset(position)
107050-	if err != nil {
107051-		return nil, fmt.Errorf("computing cursor offset: %w", err)
107052-	}
107053-
107054-	// Confirm that the cursor is inside a use statement, and then find
107055-	// the position of the use statement's directory path.
107056-	use, pathStart, pathEnd := usePath(pw, offset)
107057-
107058-	// The cursor position is not on a use statement.
107059-	if use == nil {
107060-		return nil, nil
107061-	}
107062-
107063-	// Get the mod file denoted by the use.
107064-	modfh, err := snapshot.GetFile(ctx, modFileURI(pw, use))
107065-	if err != nil {
107066-		return nil, fmt.Errorf("getting modfile handle: %w", err)
107067-	}
107068-	pm, err := snapshot.ParseMod(ctx, modfh)
107069-	if err != nil {
107070-		return nil, fmt.Errorf("getting modfile handle: %w", err)
107071-	}
107072-	mod := pm.File.Module.Mod
107073-
107074-	// Get the range to highlight for the hover.
107075-	rng, err := pw.Mapper.OffsetRange(pathStart, pathEnd)
107076-	if err != nil {
107077-		return nil, err
107078-	}
107079-	options := snapshot.View().Options()
107080-	return &protocol.Hover{
107081-		Contents: protocol.MarkupContent{
107082-			Kind:  options.PreferredContentFormat,
107083-			Value: mod.Path,
107084-		},
107085-		Range: rng,
107086-	}, nil
107087-}
107088-
107089-func usePath(pw *source.ParsedWorkFile, offset int) (use *modfile.Use, pathStart, pathEnd int) {
107090-	for _, u := range pw.File.Use {
107091-		path := []byte(u.Path)
107092-		s, e := u.Syntax.Start.Byte, u.Syntax.End.Byte
107093-		i := bytes.Index(pw.Mapper.Content[s:e], path)
107094-		if i == -1 {
107095-			// This should not happen.
107096-			continue
107097-		}
107098-		// Shift the start position to the location of the
107099-		// module directory within the use statement.
107100-		pathStart, pathEnd = s+i, s+i+len(path)
107101-		if pathStart <= offset && offset <= pathEnd {
107102-			return u, pathStart, pathEnd
107103-		}
107104-	}
107105-	return nil, 0, 0
107106-}
107107diff -urN a/gopls/internal/lsp/workspace.go b/gopls/internal/lsp/workspace.go
107108--- a/gopls/internal/lsp/workspace.go	2000-01-01 00:00:00.000000000 -0000
107109+++ b/gopls/internal/lsp/workspace.go	1970-01-01 00:00:00.000000000 +0000
107110@@ -1,95 +0,0 @@
107111-// Copyright 2019 The Go Authors. All rights reserved.
107112-// Use of this source code is governed by a BSD-style
107113-// license that can be found in the LICENSE file.
107114-
107115-package lsp
107116-
107117-import (
107118-	"context"
107119-	"fmt"
107120-
107121-	"golang.org/x/tools/gopls/internal/lsp/protocol"
107122-	"golang.org/x/tools/gopls/internal/lsp/source"
107123-	"golang.org/x/tools/gopls/internal/span"
107124-)
107125-
107126-func (s *Server) didChangeWorkspaceFolders(ctx context.Context, params *protocol.DidChangeWorkspaceFoldersParams) error {
107127-	event := params.Event
107128-	for _, folder := range event.Removed {
107129-		view := s.session.View(folder.Name)
107130-		if view != nil {
107131-			s.session.RemoveView(view)
107132-		} else {
107133-			return fmt.Errorf("view %s for %v not found", folder.Name, folder.URI)
107134-		}
107135-	}
107136-	return s.addFolders(ctx, event.Added)
107137-}
107138-
107139-// addView returns a Snapshot and a release function that must be
107140-// called when it is no longer needed.
107141-func (s *Server) addView(ctx context.Context, name string, uri span.URI) (source.Snapshot, func(), error) {
107142-	s.stateMu.Lock()
107143-	state := s.state
107144-	s.stateMu.Unlock()
107145-	if state < serverInitialized {
107146-		return nil, nil, fmt.Errorf("addView called before server initialized")
107147-	}
107148-	options := s.session.Options().Clone()
107149-	if err := s.fetchConfig(ctx, name, uri, options); err != nil {
107150-		return nil, nil, err
107151-	}
107152-	_, snapshot, release, err := s.session.NewView(ctx, name, uri, options)
107153-	return snapshot, release, err
107154-}
107155-
107156-func (s *Server) didChangeConfiguration(ctx context.Context, _ *protocol.DidChangeConfigurationParams) error {
107157-	// Apply any changes to the session-level settings.
107158-	options := s.session.Options().Clone()
107159-	if err := s.fetchConfig(ctx, "", "", options); err != nil {
107160-		return err
107161-	}
107162-	s.session.SetOptions(options)
107163-
107164-	// Go through each view, getting and updating its configuration.
107165-	for _, view := range s.session.Views() {
107166-		options := s.session.Options().Clone()
107167-		if err := s.fetchConfig(ctx, view.Name(), view.Folder(), options); err != nil {
107168-			return err
107169-		}
107170-		view, err := s.session.SetViewOptions(ctx, view, options)
107171-		if err != nil {
107172-			return err
107173-		}
107174-		go func() {
107175-			snapshot, release, err := view.Snapshot()
107176-			if err != nil {
107177-				return // view is shut down; no need to diagnose
107178-			}
107179-			defer release()
107180-			s.diagnoseDetached(snapshot)
107181-		}()
107182-	}
107183-
107184-	// An options change may have affected the detected Go version.
107185-	s.checkViewGoVersions()
107186-
107187-	return nil
107188-}
107189-
107190-func semanticTokenRegistration(tokenTypes, tokenModifiers []string) protocol.Registration {
107191-	return protocol.Registration{
107192-		ID:     "textDocument/semanticTokens",
107193-		Method: "textDocument/semanticTokens",
107194-		RegisterOptions: &protocol.SemanticTokensOptions{
107195-			Legend: protocol.SemanticTokensLegend{
107196-				// TODO(pjw): trim these to what we use (and an unused one
107197-				// at position 0 of TokTypes, to catch typos)
107198-				TokenTypes:     tokenTypes,
107199-				TokenModifiers: tokenModifiers,
107200-			},
107201-			Full:  &protocol.Or_SemanticTokensOptions_full{Value: true},
107202-			Range: &protocol.Or_SemanticTokensOptions_range{Value: true},
107203-		},
107204-	}
107205-}
107206diff -urN a/gopls/internal/lsp/workspace_symbol.go b/gopls/internal/lsp/workspace_symbol.go
107207--- a/gopls/internal/lsp/workspace_symbol.go	2000-01-01 00:00:00.000000000 -0000
107208+++ b/gopls/internal/lsp/workspace_symbol.go	1970-01-01 00:00:00.000000000 +0000
107209@@ -1,32 +0,0 @@
107210-// Copyright 2020 The Go Authors. All rights reserved.
107211-// Use of this source code is governed by a BSD-style
107212-// license that can be found in the LICENSE file.
107213-
107214-package lsp
107215-
107216-import (
107217-	"context"
107218-
107219-	"golang.org/x/tools/gopls/internal/lsp/protocol"
107220-	"golang.org/x/tools/gopls/internal/lsp/source"
107221-	"golang.org/x/tools/internal/event"
107222-)
107223-
107224-func (s *Server) symbol(ctx context.Context, params *protocol.WorkspaceSymbolParams) ([]protocol.SymbolInformation, error) {
107225-	ctx, done := event.Start(ctx, "lsp.Server.symbol")
107226-	defer done()
107227-
107228-	views := s.session.Views()
107229-	matcher := s.session.Options().SymbolMatcher
107230-	style := s.session.Options().SymbolStyle
107231-	// TODO(rfindley): it looks wrong that we need to pass views here.
107232-	//
107233-	// Evidence:
107234-	//  - this is the only place we convert views to []source.View
107235-	//  - workspace symbols is the only place where we call source.View.Snapshot
107236-	var sourceViews []source.View
107237-	for _, v := range views {
107238-		sourceViews = append(sourceViews, v)
107239-	}
107240-	return source.WorkspaceSymbols(ctx, matcher, style, sourceViews, params.Query)
107241-}
107242diff -urN a/gopls/internal/regtest/bench/bench_test.go b/gopls/internal/regtest/bench/bench_test.go
107243--- a/gopls/internal/regtest/bench/bench_test.go	2000-01-01 00:00:00.000000000 -0000
107244+++ b/gopls/internal/regtest/bench/bench_test.go	1970-01-01 00:00:00.000000000 +0000
107245@@ -1,249 +0,0 @@
107246-// Copyright 2020 The Go Authors. All rights reserved.
107247-// Use of this source code is governed by a BSD-style
107248-// license that can be found in the LICENSE file.
107249-
107250-package bench
107251-
107252-import (
107253-	"context"
107254-	"flag"
107255-	"fmt"
107256-	"io/ioutil"
107257-	"log"
107258-	"os"
107259-	"os/exec"
107260-	"path/filepath"
107261-	"sync"
107262-	"testing"
107263-	"time"
107264-
107265-	"golang.org/x/tools/gopls/internal/hooks"
107266-	"golang.org/x/tools/gopls/internal/lsp/cmd"
107267-	"golang.org/x/tools/gopls/internal/lsp/fake"
107268-	"golang.org/x/tools/internal/bug"
107269-	"golang.org/x/tools/internal/event"
107270-	"golang.org/x/tools/internal/fakenet"
107271-	"golang.org/x/tools/internal/jsonrpc2"
107272-	"golang.org/x/tools/internal/jsonrpc2/servertest"
107273-	"golang.org/x/tools/internal/tool"
107274-
107275-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
107276-)
107277-
107278-var (
107279-	goplsPath = flag.String("gopls_path", "", "if set, use this gopls for testing; incompatible with -gopls_commit")
107280-
107281-	installGoplsOnce sync.Once // guards installing gopls at -gopls_commit
107282-	goplsCommit      = flag.String("gopls_commit", "", "if set, install and use gopls at this commit for testing; incompatible with -gopls_path")
107283-
107284-	cpuProfile = flag.String("gopls_cpuprofile", "", "if set, the cpu profile file suffix; see \"Profiling\" in the package doc")
107285-	memProfile = flag.String("gopls_memprofile", "", "if set, the mem profile file suffix; see \"Profiling\" in the package doc")
107286-	trace      = flag.String("gopls_trace", "", "if set, the trace file suffix; see \"Profiling\" in the package doc")
107287-
107288-	// If non-empty, tempDir is a temporary working dir that was created by this
107289-	// test suite.
107290-	makeTempDirOnce sync.Once // guards creation of the temp dir
107291-	tempDir         string
107292-)
107293-
107294-// if runAsGopls is "true", run the gopls command instead of the testing.M.
107295-const runAsGopls = "_GOPLS_BENCH_RUN_AS_GOPLS"
107296-
107297-func TestMain(m *testing.M) {
107298-	bug.PanicOnBugs = true
107299-	if os.Getenv(runAsGopls) == "true" {
107300-		tool.Main(context.Background(), cmd.New("gopls", "", nil, hooks.Options), os.Args[1:])
107301-		os.Exit(0)
107302-	}
107303-	event.SetExporter(nil) // don't log to stderr
107304-	code := m.Run()
107305-	if err := cleanup(); err != nil {
107306-		fmt.Fprintf(os.Stderr, "cleaning up after benchmarks: %v\n", err)
107307-		if code == 0 {
107308-			code = 1
107309-		}
107310-	}
107311-	os.Exit(code)
107312-}
107313-
107314-// getTempDir returns the temporary directory to use for benchmark files,
107315-// creating it if necessary.
107316-func getTempDir() string {
107317-	makeTempDirOnce.Do(func() {
107318-		var err error
107319-		tempDir, err = ioutil.TempDir("", "gopls-bench")
107320-		if err != nil {
107321-			log.Fatal(err)
107322-		}
107323-	})
107324-	return tempDir
107325-}
107326-
107327-// shallowClone performs a shallow clone of repo into dir at the given
107328-// 'commitish' ref (any commit reference understood by git).
107329-//
107330-// The directory dir must not already exist.
107331-func shallowClone(dir, repo, commitish string) error {
107332-	if err := os.Mkdir(dir, 0750); err != nil {
107333-		return fmt.Errorf("creating dir for %s: %v", repo, err)
107334-	}
107335-
107336-	// Set a timeout for git fetch. If this proves flaky, it can be removed.
107337-	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
107338-	defer cancel()
107339-
107340-	// Use a shallow fetch to download just the relevant commit.
107341-	shInit := fmt.Sprintf("git init && git fetch --depth=1 %q %q && git checkout FETCH_HEAD", repo, commitish)
107342-	initCmd := exec.CommandContext(ctx, "/bin/sh", "-c", shInit)
107343-	initCmd.Dir = dir
107344-	if output, err := initCmd.CombinedOutput(); err != nil {
107345-		return fmt.Errorf("checking out %s: %v\n%s", repo, err, output)
107346-	}
107347-	return nil
107348-}
107349-
107350-// connectEditor connects a fake editor session in the given dir, using the
107351-// given editor config.
107352-func connectEditor(dir string, config fake.EditorConfig, ts servertest.Connector) (*fake.Sandbox, *fake.Editor, *Awaiter, error) {
107353-	s, err := fake.NewSandbox(&fake.SandboxConfig{
107354-		Workdir: dir,
107355-		GOPROXY: "https://proxy.golang.org",
107356-	})
107357-	if err != nil {
107358-		return nil, nil, nil, err
107359-	}
107360-
107361-	a := NewAwaiter(s.Workdir)
107362-	const skipApplyEdits = false
107363-	editor, err := fake.NewEditor(s, config).Connect(context.Background(), ts, a.Hooks(), skipApplyEdits)
107364-	if err != nil {
107365-		return nil, nil, nil, err
107366-	}
107367-
107368-	return s, editor, a, nil
107369-}
107370-
107371-// newGoplsServer returns a connector that connects to a new gopls process.
107372-func newGoplsServer(name string) (servertest.Connector, error) {
107373-	if *goplsPath != "" && *goplsCommit != "" {
107374-		panic("can't set both -gopls_path and -gopls_commit")
107375-	}
107376-	var (
107377-		goplsPath = *goplsPath
107378-		env       []string
107379-	)
107380-	if *goplsCommit != "" {
107381-		goplsPath = getInstalledGopls()
107382-	}
107383-	if goplsPath == "" {
107384-		var err error
107385-		goplsPath, err = os.Executable()
107386-		if err != nil {
107387-			return nil, err
107388-		}
107389-		env = []string{fmt.Sprintf("%s=true", runAsGopls)}
107390-	}
107391-	var args []string
107392-	if *cpuProfile != "" {
107393-		args = append(args, fmt.Sprintf("-profile.cpu=%s", name+"."+*cpuProfile))
107394-	}
107395-	if *memProfile != "" {
107396-		args = append(args, fmt.Sprintf("-profile.mem=%s", name+"."+*memProfile))
107397-	}
107398-	if *trace != "" {
107399-		args = append(args, fmt.Sprintf("-profile.trace=%s", name+"."+*trace))
107400-	}
107401-	return &SidecarServer{
107402-		goplsPath: goplsPath,
107403-		env:       env,
107404-		args:      args,
107405-	}, nil
107406-}
107407-
107408-// getInstalledGopls builds gopls at the given -gopls_commit, returning the
107409-// path to the gopls binary.
107410-func getInstalledGopls() string {
107411-	if *goplsCommit == "" {
107412-		panic("must provide -gopls_commit")
107413-	}
107414-	toolsDir := filepath.Join(getTempDir(), "gopls_build")
107415-	goplsPath := filepath.Join(toolsDir, "gopls", "gopls")
107416-
107417-	installGoplsOnce.Do(func() {
107418-		log.Printf("installing gopls: checking out x/tools@%s into %s\n", *goplsCommit, toolsDir)
107419-		if err := shallowClone(toolsDir, "https://go.googlesource.com/tools", *goplsCommit); err != nil {
107420-			log.Fatal(err)
107421-		}
107422-
107423-		log.Println("installing gopls: building...")
107424-		bld := exec.Command("go", "build", ".")
107425-		bld.Dir = filepath.Join(toolsDir, "gopls")
107426-		if output, err := bld.CombinedOutput(); err != nil {
107427-			log.Fatalf("building gopls: %v\n%s", err, output)
107428-		}
107429-
107430-		// Confirm that the resulting path now exists.
107431-		if _, err := os.Stat(goplsPath); err != nil {
107432-			log.Fatalf("os.Stat(%s): %v", goplsPath, err)
107433-		}
107434-	})
107435-	return goplsPath
107436-}
107437-
107438-// A SidecarServer starts (and connects to) a separate gopls process at the
107439-// given path.
107440-type SidecarServer struct {
107441-	goplsPath string
107442-	env       []string // additional environment bindings
107443-	args      []string // command-line arguments
107444-}
107445-
107446-// Connect creates new io.Pipes and binds them to the underlying StreamServer.
107447-//
107448-// It implements the servertest.Connector interface.
107449-func (s *SidecarServer) Connect(ctx context.Context) jsonrpc2.Conn {
107450-	// Note: don't use CommandContext here, as we want gopls to exit gracefully
107451-	// in order to write out profile data.
107452-	//
107453-	// We close the connection on context cancelation below.
107454-	cmd := exec.Command(s.goplsPath, s.args...)
107455-
107456-	stdin, err := cmd.StdinPipe()
107457-	if err != nil {
107458-		log.Fatal(err)
107459-	}
107460-	stdout, err := cmd.StdoutPipe()
107461-	if err != nil {
107462-		log.Fatal(err)
107463-	}
107464-	cmd.Stderr = os.Stderr
107465-	cmd.Env = append(os.Environ(), s.env...)
107466-	if err := cmd.Start(); err != nil {
107467-		log.Fatalf("starting gopls: %v", err)
107468-	}
107469-
107470-	go func() {
107471-		// If we don't log.Fatal here, benchmarks may hang indefinitely if gopls
107472-		// exits abnormally.
107473-		//
107474-		// TODO(rfindley): ideally we would shut down the connection gracefully,
107475-		// but that doesn't currently work.
107476-		if err := cmd.Wait(); err != nil {
107477-			log.Fatalf("gopls invocation failed with error: %v", err)
107478-		}
107479-	}()
107480-
107481-	clientStream := jsonrpc2.NewHeaderStream(fakenet.NewConn("stdio", stdout, stdin))
107482-	clientConn := jsonrpc2.NewConn(clientStream)
107483-
107484-	go func() {
107485-		select {
107486-		case <-ctx.Done():
107487-			clientConn.Close()
107488-			clientStream.Close()
107489-		case <-clientConn.Done():
107490-		}
107491-	}()
107492-
107493-	return clientConn
107494-}
107495diff -urN a/gopls/internal/regtest/bench/completion_test.go b/gopls/internal/regtest/bench/completion_test.go
107496--- a/gopls/internal/regtest/bench/completion_test.go	2000-01-01 00:00:00.000000000 -0000
107497+++ b/gopls/internal/regtest/bench/completion_test.go	1970-01-01 00:00:00.000000000 +0000
107498@@ -1,173 +0,0 @@
107499-// Copyright 2020 The Go Authors. All rights reserved.
107500-// Use of this source code is governed by a BSD-style
107501-// license that can be found in the LICENSE file.
107502-
107503-package bench
107504-
107505-import (
107506-	"fmt"
107507-	"testing"
107508-
107509-	"golang.org/x/tools/gopls/internal/lsp/fake"
107510-	"golang.org/x/tools/gopls/internal/lsp/protocol"
107511-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
107512-)
107513-
107514-// TODO(rfindley): update these completion tests to run on multiple repos.
107515-
107516-type completionBenchOptions struct {
107517-	file, locationRegexp string
107518-
107519-	// Hooks to run edits before initial completion
107520-	setup            func(*Env) // run before the benchmark starts
107521-	beforeCompletion func(*Env) // run before each completion
107522-}
107523-
107524-func benchmarkCompletion(options completionBenchOptions, b *testing.B) {
107525-	repo := getRepo(b, "tools")
107526-	env := repo.newEnv(b, "completion.tools", fake.EditorConfig{})
107527-	defer env.Close()
107528-
107529-	// Run edits required for this completion.
107530-	if options.setup != nil {
107531-		options.setup(env)
107532-	}
107533-
107534-	// Run a completion to make sure the system is warm.
107535-	loc := env.RegexpSearch(options.file, options.locationRegexp)
107536-	completions := env.Completion(loc)
107537-
107538-	if testing.Verbose() {
107539-		fmt.Println("Results:")
107540-		for i := 0; i < len(completions.Items); i++ {
107541-			fmt.Printf("\t%d. %v\n", i, completions.Items[i])
107542-		}
107543-	}
107544-
107545-	b.Run("tools", func(b *testing.B) {
107546-		for i := 0; i < b.N; i++ {
107547-			if options.beforeCompletion != nil {
107548-				options.beforeCompletion(env)
107549-			}
107550-			env.Completion(loc)
107551-		}
107552-	})
107553-}
107554-
107555-// endRangeInBuffer returns the position for last character in the buffer for
107556-// the given file.
107557-func endRangeInBuffer(env *Env, name string) protocol.Range {
107558-	buffer := env.BufferText(name)
107559-	m := protocol.NewMapper("", []byte(buffer))
107560-	rng, err := m.OffsetRange(len(buffer), len(buffer))
107561-	if err != nil {
107562-		env.T.Fatal(err)
107563-	}
107564-	return rng
107565-}
107566-
107567-// Benchmark struct completion in tools codebase.
107568-func BenchmarkStructCompletion(b *testing.B) {
107569-	file := "internal/lsp/cache/session.go"
107570-
107571-	setup := func(env *Env) {
107572-		env.OpenFile(file)
107573-		env.EditBuffer(file, protocol.TextEdit{
107574-			Range:   endRangeInBuffer(env, file),
107575-			NewText: "\nvar testVariable map[string]bool = Session{}.\n",
107576-		})
107577-	}
107578-
107579-	benchmarkCompletion(completionBenchOptions{
107580-		file:           file,
107581-		locationRegexp: `var testVariable map\[string\]bool = Session{}(\.)`,
107582-		setup:          setup,
107583-	}, b)
107584-}
107585-
107586-// Benchmark import completion in tools codebase.
107587-func BenchmarkImportCompletion(b *testing.B) {
107588-	const file = "internal/lsp/source/completion/completion.go"
107589-	benchmarkCompletion(completionBenchOptions{
107590-		file:           file,
107591-		locationRegexp: `go\/()`,
107592-		setup:          func(env *Env) { env.OpenFile(file) },
107593-	}, b)
107594-}
107595-
107596-// Benchmark slice completion in tools codebase.
107597-func BenchmarkSliceCompletion(b *testing.B) {
107598-	file := "internal/lsp/cache/session.go"
107599-
107600-	setup := func(env *Env) {
107601-		env.OpenFile(file)
107602-		env.EditBuffer(file, protocol.TextEdit{
107603-			Range:   endRangeInBuffer(env, file),
107604-			NewText: "\nvar testVariable []byte = \n",
107605-		})
107606-	}
107607-
107608-	benchmarkCompletion(completionBenchOptions{
107609-		file:           file,
107610-		locationRegexp: `var testVariable \[\]byte (=)`,
107611-		setup:          setup,
107612-	}, b)
107613-}
107614-
107615-// Benchmark deep completion in function call in tools codebase.
107616-func BenchmarkFuncDeepCompletion(b *testing.B) {
107617-	file := "internal/lsp/source/completion/completion.go"
107618-	fileContent := `
107619-func (c *completer) _() {
107620-	c.inference.kindMatches(c.)
107621-}
107622-`
107623-	setup := func(env *Env) {
107624-		env.OpenFile(file)
107625-		originalBuffer := env.BufferText(file)
107626-		env.EditBuffer(file, protocol.TextEdit{
107627-			Range:   endRangeInBuffer(env, file),
107628-			NewText: originalBuffer + fileContent,
107629-		})
107630-	}
107631-
107632-	benchmarkCompletion(completionBenchOptions{
107633-		file:           file,
107634-		locationRegexp: `func \(c \*completer\) _\(\) {\n\tc\.inference\.kindMatches\((c)`,
107635-		setup:          setup,
107636-	}, b)
107637-}
107638-
107639-// Benchmark completion following an arbitrary edit.
107640-//
107641-// Edits force type-checked packages to be invalidated, so we want to measure
107642-// how long it takes before completion results are available.
107643-func BenchmarkCompletionFollowingEdit(b *testing.B) {
107644-	file := "internal/lsp/source/completion/completion2.go"
107645-	fileContent := `
107646-package completion
107647-
107648-func (c *completer) _() {
107649-	c.inference.kindMatches(c.)
107650-	// __MAGIC_STRING_1
107651-}
107652-`
107653-	setup := func(env *Env) {
107654-		env.CreateBuffer(file, fileContent)
107655-	}
107656-
107657-	n := 1
107658-	beforeCompletion := func(env *Env) {
107659-		old := fmt.Sprintf("__MAGIC_STRING_%d", n)
107660-		new := fmt.Sprintf("__MAGIC_STRING_%d", n+1)
107661-		n++
107662-		env.RegexpReplace(file, old, new)
107663-	}
107664-
107665-	benchmarkCompletion(completionBenchOptions{
107666-		file:             file,
107667-		locationRegexp:   `func \(c \*completer\) _\(\) {\n\tc\.inference\.kindMatches\((c)`,
107668-		setup:            setup,
107669-		beforeCompletion: beforeCompletion,
107670-	}, b)
107671-}
107672diff -urN a/gopls/internal/regtest/bench/definition_test.go b/gopls/internal/regtest/bench/definition_test.go
107673--- a/gopls/internal/regtest/bench/definition_test.go	2000-01-01 00:00:00.000000000 -0000
107674+++ b/gopls/internal/regtest/bench/definition_test.go	1970-01-01 00:00:00.000000000 +0000
107675@@ -1,39 +0,0 @@
107676-// Copyright 2023 The Go Authors. All rights reserved.
107677-// Use of this source code is governed by a BSD-style
107678-// license that can be found in the LICENSE file.
107679-
107680-package bench
107681-
107682-import (
107683-	"testing"
107684-)
107685-
107686-func BenchmarkDefinition(b *testing.B) {
107687-	tests := []struct {
107688-		repo   string
107689-		file   string
107690-		regexp string
107691-	}{
107692-		{"istio", "pkg/config/model.go", `gogotypes\.(MarshalAny)`},
107693-		{"kubernetes", "pkg/controller/lookup_cache.go", `hashutil\.(DeepHashObject)`},
107694-		{"kuma", "api/generic/insights.go", `proto\.(Message)`},
107695-		{"pkgsite", "internal/log/log.go", `derrors\.(Wrap)`},
107696-		{"starlark", "starlark/eval.go", "prog.compiled.(Encode)"},
107697-		{"tools", "internal/lsp/cache/check.go", `(snapshot)\) buildKey`},
107698-	}
107699-
107700-	for _, test := range tests {
107701-		b.Run(test.repo, func(b *testing.B) {
107702-			env := getRepo(b, test.repo).sharedEnv(b)
107703-			env.OpenFile(test.file)
107704-			loc := env.RegexpSearch(test.file, test.regexp)
107705-			env.Await(env.DoneWithOpen())
107706-			env.GoToDefinition(loc) // pre-warm the query, and open the target file
107707-			b.ResetTimer()
107708-
107709-			for i := 0; i < b.N; i++ {
107710-				env.GoToDefinition(loc) // pre-warm the query
107711-			}
107712-		})
107713-	}
107714-}
107715diff -urN a/gopls/internal/regtest/bench/didchange_test.go b/gopls/internal/regtest/bench/didchange_test.go
107716--- a/gopls/internal/regtest/bench/didchange_test.go	2000-01-01 00:00:00.000000000 -0000
107717+++ b/gopls/internal/regtest/bench/didchange_test.go	1970-01-01 00:00:00.000000000 +0000
107718@@ -1,99 +0,0 @@
107719-// Copyright 2022 The Go Authors. All rights reserved.
107720-// Use of this source code is governed by a BSD-style
107721-// license that can be found in the LICENSE file.
107722-
107723-package bench
107724-
107725-import (
107726-	"fmt"
107727-	"sync/atomic"
107728-	"testing"
107729-	"time"
107730-
107731-	"golang.org/x/tools/gopls/internal/lsp/fake"
107732-	"golang.org/x/tools/gopls/internal/lsp/protocol"
107733-)
107734-
107735-// Use a global edit counter as bench function may execute multiple times, and
107736-// we want to avoid cache hits. Use time.Now to also avoid cache hits from the
107737-// shared file cache.
107738-var editID int64 = time.Now().UnixNano()
107739-
107740-var didChangeTests = []struct {
107741-	repo string
107742-	file string
107743-}{
107744-	{"istio", "pkg/fuzz/util.go"},
107745-	{"kubernetes", "pkg/controller/lookup_cache.go"},
107746-	{"kuma", "api/generic/insights.go"},
107747-	{"pkgsite", "internal/frontend/server.go"},
107748-	{"starlark", "starlark/eval.go"},
107749-	{"tools", "internal/lsp/cache/snapshot.go"},
107750-}
107751-
107752-// BenchmarkDidChange benchmarks modifications of a single file by making
107753-// synthetic modifications in a comment. It controls pacing by waiting for the
107754-// server to actually start processing the didChange notification before
107755-// proceeding. Notably it does not wait for diagnostics to complete.
107756-func BenchmarkDidChange(b *testing.B) {
107757-	for _, test := range didChangeTests {
107758-		b.Run(test.repo, func(b *testing.B) {
107759-			env := getRepo(b, test.repo).sharedEnv(b)
107760-			env.OpenFile(test.file)
107761-			// Insert the text we'll be modifying at the top of the file.
107762-			env.EditBuffer(test.file, protocol.TextEdit{NewText: "// __REGTEST_PLACEHOLDER_0__\n"})
107763-			env.AfterChange()
107764-			b.ResetTimer()
107765-
107766-			for i := 0; i < b.N; i++ {
107767-				edits := atomic.AddInt64(&editID, 1)
107768-				env.EditBuffer(test.file, protocol.TextEdit{
107769-					Range: protocol.Range{
107770-						Start: protocol.Position{Line: 0, Character: 0},
107771-						End:   protocol.Position{Line: 1, Character: 0},
107772-					},
107773-					// Increment the placeholder text, to ensure cache misses.
107774-					NewText: fmt.Sprintf("// __REGTEST_PLACEHOLDER_%d__\n", edits),
107775-				})
107776-				env.Await(env.StartedChange())
107777-			}
107778-		})
107779-	}
107780-}
107781-
107782-func BenchmarkDiagnoseChange(b *testing.B) {
107783-	for _, test := range didChangeTests {
107784-		b.Run(test.repo, func(b *testing.B) {
107785-			// Use a new env to avoid the diagnostic delay: we want to measure how
107786-			// long it takes to produce the diagnostics.
107787-			env := repos[test.repo].newEnv(b, "diagnoseChange", fake.EditorConfig{
107788-				Settings: map[string]interface{}{
107789-					"diagnosticsDelay": "0s",
107790-				},
107791-			})
107792-			env.OpenFile(test.file)
107793-			// Insert the text we'll be modifying at the top of the file.
107794-			env.EditBuffer(test.file, protocol.TextEdit{NewText: "// __REGTEST_PLACEHOLDER_0__\n"})
107795-			env.AfterChange()
107796-			b.ResetTimer()
107797-
107798-			// We must use an extra subtest layer here, so that we only set up the
107799-			// shared env once (otherwise we pay additional overhead and the profiling
107800-			// flags don't work).
107801-			b.Run("diagnose", func(b *testing.B) {
107802-				for i := 0; i < b.N; i++ {
107803-					edits := atomic.AddInt64(&editID, 1)
107804-					env.EditBuffer(test.file, protocol.TextEdit{
107805-						Range: protocol.Range{
107806-							Start: protocol.Position{Line: 0, Character: 0},
107807-							End:   protocol.Position{Line: 1, Character: 0},
107808-						},
107809-						// Increment the placeholder text, to ensure cache misses.
107810-						NewText: fmt.Sprintf("// __REGTEST_PLACEHOLDER_%d__\n", edits),
107811-					})
107812-					env.AfterChange()
107813-				}
107814-			})
107815-		})
107816-	}
107817-}
107818diff -urN a/gopls/internal/regtest/bench/doc.go b/gopls/internal/regtest/bench/doc.go
107819--- a/gopls/internal/regtest/bench/doc.go	2000-01-01 00:00:00.000000000 -0000
107820+++ b/gopls/internal/regtest/bench/doc.go	1970-01-01 00:00:00.000000000 +0000
107821@@ -1,33 +0,0 @@
107822-// Copyright 2023 The Go Authors. All rights reserved.
107823-// Use of this source code is governed by a BSD-style
107824-// license that can be found in the LICENSE file.
107825-
107826-// The bench package implements benchmarks for various LSP operations.
107827-//
107828-// Benchmarks check out specific commits of popular and/or exemplary
107829-// repositories, and script an external gopls process via a fake text editor.
107830-// By default, benchmarks run the test executable as gopls (using a special
107831-// "gopls mode" environment variable). A different gopls binary may be used by
107832-// setting the -gopls_path or -gopls_commit flags.
107833-//
107834-// This package is a work in progress.
107835-//
107836-// # Profiling
107837-//
107838-// As benchmark functions run gopls in a separate process, the normal test
107839-// flags for profiling are not useful. Instead the -gopls_cpuprofile,
107840-// -gopls_memprofile, and -gopls_trace flags may be used to pass through
107841-// profiling flags to the gopls process. Each of these flags sets a suffix
107842-// for the respective gopls profiling flag, which is prefixed with a name
107843-// corresponding to the shared repository or (in some cases) benchmark name.
107844-// For example, settings -gopls_cpuprofile=cpu.out will result in profiles
107845-// named tools.cpu.out, BenchmarkInitialWorkspaceLoad.cpu.out, etc. Here,
107846-// tools.cpu.out is the cpu profile for the shared x/tools session, which may
107847-// be used by multiple benchmark functions, and BenchmarkInitialWorkspaceLoad
107848-// is the cpu profile for the last iteration of the initial workspace load
107849-// test, which starts a new editor session for each iteration.
107850-//
107851-// # TODO
107852-//   - add more benchmarks, and more repositories
107853-//   - improve this documentation
107854-package bench
107855diff -urN a/gopls/internal/regtest/bench/hover_test.go b/gopls/internal/regtest/bench/hover_test.go
107856--- a/gopls/internal/regtest/bench/hover_test.go	2000-01-01 00:00:00.000000000 -0000
107857+++ b/gopls/internal/regtest/bench/hover_test.go	1970-01-01 00:00:00.000000000 +0000
107858@@ -1,39 +0,0 @@
107859-// Copyright 2023 The Go Authors. All rights reserved.
107860-// Use of this source code is governed by a BSD-style
107861-// license that can be found in the LICENSE file.
107862-
107863-package bench
107864-
107865-import (
107866-	"testing"
107867-)
107868-
107869-func BenchmarkHover(b *testing.B) {
107870-	tests := []struct {
107871-		repo   string
107872-		file   string
107873-		regexp string
107874-	}{
107875-		{"istio", "pkg/config/model.go", `gogotypes\.(MarshalAny)`},
107876-		{"kubernetes", "pkg/apis/core/types.go", "type (Pod)"},
107877-		{"kuma", "api/generic/insights.go", `proto\.(Message)`},
107878-		{"pkgsite", "internal/log/log.go", `derrors\.(Wrap)`},
107879-		{"starlark", "starlark/eval.go", "prog.compiled.(Encode)"},
107880-		{"tools", "internal/lsp/cache/check.go", `(snapshot)\) buildKey`},
107881-	}
107882-
107883-	for _, test := range tests {
107884-		b.Run(test.repo, func(b *testing.B) {
107885-			env := getRepo(b, test.repo).sharedEnv(b)
107886-			env.OpenFile(test.file)
107887-			loc := env.RegexpSearch(test.file, test.regexp)
107888-			env.Await(env.DoneWithOpen())
107889-			env.Hover(loc) // pre-warm the query
107890-			b.ResetTimer()
107891-
107892-			for i := 0; i < b.N; i++ {
107893-				env.Hover(loc) // pre-warm the query
107894-			}
107895-		})
107896-	}
107897-}
107898diff -urN a/gopls/internal/regtest/bench/implementations_test.go b/gopls/internal/regtest/bench/implementations_test.go
107899--- a/gopls/internal/regtest/bench/implementations_test.go	2000-01-01 00:00:00.000000000 -0000
107900+++ b/gopls/internal/regtest/bench/implementations_test.go	1970-01-01 00:00:00.000000000 +0000
107901@@ -1,37 +0,0 @@
107902-// Copyright 2023 The Go Authors. All rights reserved.
107903-// Use of this source code is governed by a BSD-style
107904-// license that can be found in the LICENSE file.
107905-
107906-package bench
107907-
107908-import "testing"
107909-
107910-func BenchmarkImplementations(b *testing.B) {
107911-	tests := []struct {
107912-		repo   string
107913-		file   string
107914-		regexp string
107915-	}{
107916-		{"istio", "pkg/config/mesh/watcher.go", `type (Watcher)`},
107917-		{"kubernetes", "pkg/controller/lookup_cache.go", `objectWithMeta`},
107918-		{"kuma", "api/generic/insights.go", `type (Insight)`},
107919-		{"pkgsite", "internal/datasource.go", `type (DataSource)`},
107920-		{"starlark", "syntax/syntax.go", `type (Expr)`},
107921-		{"tools", "internal/lsp/source/view.go", `type (Snapshot)`},
107922-	}
107923-
107924-	for _, test := range tests {
107925-		b.Run(test.repo, func(b *testing.B) {
107926-			env := getRepo(b, test.repo).sharedEnv(b)
107927-			env.OpenFile(test.file)
107928-			loc := env.RegexpSearch(test.file, test.regexp)
107929-			env.Await(env.DoneWithOpen())
107930-			env.Implementations(loc) // pre-warm the query
107931-			b.ResetTimer()
107932-
107933-			for i := 0; i < b.N; i++ {
107934-				env.Implementations(loc)
107935-			}
107936-		})
107937-	}
107938-}
107939diff -urN a/gopls/internal/regtest/bench/iwl_test.go b/gopls/internal/regtest/bench/iwl_test.go
107940--- a/gopls/internal/regtest/bench/iwl_test.go	2000-01-01 00:00:00.000000000 -0000
107941+++ b/gopls/internal/regtest/bench/iwl_test.go	1970-01-01 00:00:00.000000000 +0000
107942@@ -1,77 +0,0 @@
107943-// Copyright 2022 The Go Authors. All rights reserved.
107944-// Use of this source code is governed by a BSD-style
107945-// license that can be found in the LICENSE file.
107946-
107947-package bench
107948-
107949-import (
107950-	"testing"
107951-
107952-	"golang.org/x/tools/gopls/internal/lsp/command"
107953-	"golang.org/x/tools/gopls/internal/lsp/fake"
107954-	"golang.org/x/tools/gopls/internal/lsp/protocol"
107955-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
107956-)
107957-
107958-// BenchmarkInitialWorkspaceLoad benchmarks the initial workspace load time for
107959-// a new editing session.
107960-func BenchmarkInitialWorkspaceLoad(b *testing.B) {
107961-	if testing.Short() {
107962-		// TODO(rfindley): remove this skip once the released gopls version
107963-		// supports the memstats command.
107964-		b.Skip("temporarily skipping as baseline gopls versions do not support the memstats command")
107965-	}
107966-	tests := []struct {
107967-		repo string
107968-		file string
107969-	}{
107970-		{"tools", "internal/lsp/cache/snapshot.go"},
107971-		{"kubernetes", "pkg/controller/lookup_cache.go"},
107972-		{"pkgsite", "internal/frontend/server.go"},
107973-		{"starlark", "starlark/eval.go"},
107974-		{"istio", "pkg/fuzz/util.go"},
107975-		{"kuma", "api/generic/insights.go"},
107976-	}
107977-
107978-	for _, test := range tests {
107979-		b.Run(test.repo, func(b *testing.B) {
107980-			repo := getRepo(b, test.repo)
107981-			// get the (initialized) shared env to ensure the cache is warm.
107982-			// Reuse its GOPATH so that we get cache hits for things in the module
107983-			// cache.
107984-			sharedEnv := repo.sharedEnv(b)
107985-			b.ResetTimer()
107986-
107987-			for i := 0; i < b.N; i++ {
107988-				doIWL(b, sharedEnv.Sandbox.GOPATH(), repo, test.file)
107989-			}
107990-		})
107991-	}
107992-}
107993-
107994-func doIWL(b *testing.B, gopath string, repo *repo, file string) {
107995-	// Exclude the time to set up the env from the benchmark time, as this may
107996-	// involve installing gopls and/or checking out the repo dir.
107997-	b.StopTimer()
107998-	config := fake.EditorConfig{Env: map[string]string{"GOPATH": gopath}}
107999-	env := repo.newEnv(b, "iwl."+repo.name, config)
108000-	defer env.Close()
108001-	b.StartTimer()
108002-
108003-	// Open an arbitrary file to ensure that gopls starts working.
108004-	//
108005-	// In the future, this may matter if gopls doesn't eagerly construct
108006-	// the workspace.
108007-	env.OpenFile(file)
108008-
108009-	env.Await(InitialWorkspaceLoad)
108010-	b.StopTimer()
108011-	params := &protocol.ExecuteCommandParams{
108012-		Command: command.MemStats.ID(),
108013-	}
108014-	var memstats command.MemStatsResult
108015-	env.ExecuteCommand(params, &memstats)
108016-	b.ReportMetric(float64(memstats.HeapAlloc), "alloc_bytes")
108017-	b.ReportMetric(float64(memstats.HeapInUse), "in_use_bytes")
108018-	b.StartTimer()
108019-}
108020diff -urN a/gopls/internal/regtest/bench/references_test.go b/gopls/internal/regtest/bench/references_test.go
108021--- a/gopls/internal/regtest/bench/references_test.go	2000-01-01 00:00:00.000000000 -0000
108022+++ b/gopls/internal/regtest/bench/references_test.go	1970-01-01 00:00:00.000000000 +0000
108023@@ -1,37 +0,0 @@
108024-// Copyright 2023 The Go Authors. All rights reserved.
108025-// Use of this source code is governed by a BSD-style
108026-// license that can be found in the LICENSE file.
108027-
108028-package bench
108029-
108030-import "testing"
108031-
108032-func BenchmarkReferences(b *testing.B) {
108033-	tests := []struct {
108034-		repo   string
108035-		file   string
108036-		regexp string
108037-	}{
108038-		{"istio", "pkg/config/model.go", "type (Meta)"},
108039-		{"kubernetes", "pkg/controller/lookup_cache.go", "type (objectWithMeta)"},
108040-		{"kuma", "pkg/events/interfaces.go", "type (Event)"},
108041-		{"pkgsite", "internal/log/log.go", "func (Infof)"},
108042-		{"starlark", "syntax/syntax.go", "type (Ident)"},
108043-		{"tools", "internal/lsp/source/view.go", "type (Snapshot)"},
108044-	}
108045-
108046-	for _, test := range tests {
108047-		b.Run(test.repo, func(b *testing.B) {
108048-			env := getRepo(b, test.repo).sharedEnv(b)
108049-			env.OpenFile(test.file)
108050-			loc := env.RegexpSearch(test.file, test.regexp)
108051-			env.Await(env.DoneWithOpen())
108052-			env.References(loc) // pre-warm the query
108053-			b.ResetTimer()
108054-
108055-			for i := 0; i < b.N; i++ {
108056-				env.References(loc)
108057-			}
108058-		})
108059-	}
108060-}
108061diff -urN a/gopls/internal/regtest/bench/rename_test.go b/gopls/internal/regtest/bench/rename_test.go
108062--- a/gopls/internal/regtest/bench/rename_test.go	2000-01-01 00:00:00.000000000 -0000
108063+++ b/gopls/internal/regtest/bench/rename_test.go	1970-01-01 00:00:00.000000000 +0000
108064@@ -1,44 +0,0 @@
108065-// Copyright 2023 The Go Authors. All rights reserved.
108066-// Use of this source code is governed by a BSD-style
108067-// license that can be found in the LICENSE file.
108068-
108069-package bench
108070-
108071-import (
108072-	"fmt"
108073-	"testing"
108074-)
108075-
108076-func BenchmarkRename(b *testing.B) {
108077-	tests := []struct {
108078-		repo     string
108079-		file     string
108080-		regexp   string
108081-		baseName string
108082-	}{
108083-		{"kubernetes", "pkg/controller/lookup_cache.go", `hashutil\.(DeepHashObject)`, "DeepHashObject"},
108084-		{"kuma", "pkg/events/interfaces.go", `Delete`, "Delete"},
108085-		{"istio", "pkg/config/model.go", `(Namespace) string`, "Namespace"},
108086-		{"pkgsite", "internal/log/log.go", `func (Infof)`, "Infof"},
108087-		{"starlark", "starlark/eval.go", `Program\) (Filename)`, "Filename"},
108088-		{"tools", "internal/lsp/cache/snapshot.go", `meta \*(metadataGraph)`, "metadataGraph"},
108089-	}
108090-
108091-	for _, test := range tests {
108092-		names := 0 // bench function may execute multiple times
108093-		b.Run(test.repo, func(b *testing.B) {
108094-			env := getRepo(b, test.repo).sharedEnv(b)
108095-			env.OpenFile(test.file)
108096-			loc := env.RegexpSearch(test.file, test.regexp)
108097-			env.Await(env.DoneWithOpen())
108098-			env.Rename(loc, test.baseName+"X") // pre-warm the query
108099-			b.ResetTimer()
108100-
108101-			for i := 0; i < b.N; i++ {
108102-				names++
108103-				newName := fmt.Sprintf("%s%d", test.baseName, names)
108104-				env.Rename(loc, newName)
108105-			}
108106-		})
108107-	}
108108-}
108109diff -urN a/gopls/internal/regtest/bench/repo_test.go b/gopls/internal/regtest/bench/repo_test.go
108110--- a/gopls/internal/regtest/bench/repo_test.go	2000-01-01 00:00:00.000000000 -0000
108111+++ b/gopls/internal/regtest/bench/repo_test.go	1970-01-01 00:00:00.000000000 +0000
108112@@ -1,231 +0,0 @@
108113-// Copyright 2023 The Go Authors. All rights reserved.
108114-// Use of this source code is governed by a BSD-style
108115-// license that can be found in the LICENSE file.
108116-
108117-package bench
108118-
108119-import (
108120-	"bytes"
108121-	"context"
108122-	"errors"
108123-	"fmt"
108124-	"log"
108125-	"os"
108126-	"path/filepath"
108127-	"sync"
108128-	"testing"
108129-	"time"
108130-
108131-	"golang.org/x/tools/gopls/internal/lsp/fake"
108132-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
108133-)
108134-
108135-// repos holds shared repositories for use in benchmarks.
108136-//
108137-// These repos were selected to represent a variety of different types of
108138-// codebases.
108139-var repos = map[string]*repo{
108140-	// Used by x/benchmarks; large.
108141-	"istio": {
108142-		name:   "istio",
108143-		url:    "https://github.com/istio/istio",
108144-		commit: "1.17.0",
108145-	},
108146-
108147-	// Kubernetes is a large repo with many dependencies, and in the past has
108148-	// been about as large a repo as gopls could handle.
108149-	"kubernetes": {
108150-		name:   "kubernetes",
108151-		url:    "https://github.com/kubernetes/kubernetes",
108152-		commit: "v1.24.0",
108153-	},
108154-
108155-	// A large, industrial application.
108156-	"kuma": {
108157-		name:   "kuma",
108158-		url:    "https://github.com/kumahq/kuma",
108159-		commit: "2.1.1",
108160-	},
108161-
108162-	// x/pkgsite is familiar and represents a common use case (a webserver). It
108163-	// also has a number of static non-go files and template files.
108164-	"pkgsite": {
108165-		name:   "pkgsite",
108166-		url:    "https://go.googlesource.com/pkgsite",
108167-		commit: "81f6f8d4175ad0bf6feaa03543cc433f8b04b19b",
108168-		short:  true,
108169-	},
108170-
108171-	// A tiny self-contained project.
108172-	"starlark": {
108173-		name:   "starlark",
108174-		url:    "https://github.com/google/starlark-go",
108175-		commit: "3f75dec8e4039385901a30981e3703470d77e027",
108176-		short:  true,
108177-	},
108178-
108179-	// The current repository, which is medium-small and has very few dependencies.
108180-	"tools": {
108181-		name:   "tools",
108182-		url:    "https://go.googlesource.com/tools",
108183-		commit: "gopls/v0.9.0",
108184-		short:  true,
108185-	},
108186-}
108187-
108188-// getRepo gets the requested repo, and skips the test if -short is set and
108189-// repo is not configured as a short repo.
108190-func getRepo(tb testing.TB, name string) *repo {
108191-	tb.Helper()
108192-	repo := repos[name]
108193-	if repo == nil {
108194-		tb.Fatalf("repo %s does not exist", name)
108195-	}
108196-	if !repo.short && testing.Short() {
108197-		tb.Skipf("large repo %s does not run whith -short", repo.name)
108198-	}
108199-	return repo
108200-}
108201-
108202-// A repo represents a working directory for a repository checked out at a
108203-// specific commit.
108204-//
108205-// Repos are used for sharing state across benchmarks that operate on the same
108206-// codebase.
108207-type repo struct {
108208-	// static configuration
108209-	name   string // must be unique, used for subdirectory
108210-	url    string // repo url
108211-	commit string // full commit hash or tag
108212-	short  bool   // whether this repo runs with -short
108213-
108214-	dirOnce sync.Once
108215-	dir     string // directory contaning source code checked out to url@commit
108216-
108217-	// shared editor state
108218-	editorOnce sync.Once
108219-	editor     *fake.Editor
108220-	sandbox    *fake.Sandbox
108221-	awaiter    *Awaiter
108222-}
108223-
108224-// getDir returns directory containing repo source code, creating it if
108225-// necessary. It is safe for concurrent use.
108226-func (r *repo) getDir() string {
108227-	r.dirOnce.Do(func() {
108228-		r.dir = filepath.Join(getTempDir(), r.name)
108229-		log.Printf("cloning %s@%s into %s", r.url, r.commit, r.dir)
108230-		if err := shallowClone(r.dir, r.url, r.commit); err != nil {
108231-			log.Fatal(err)
108232-		}
108233-	})
108234-	return r.dir
108235-}
108236-
108237-// sharedEnv returns a shared benchmark environment. It is safe for concurrent
108238-// use.
108239-//
108240-// Every call to sharedEnv uses the same editor and sandbox, as a means to
108241-// avoid reinitializing the editor for large repos. Calling repo.Close cleans
108242-// up the shared environment.
108243-//
108244-// Repos in the package-local Repos var are closed at the end of the test main
108245-// function.
108246-func (r *repo) sharedEnv(tb testing.TB) *Env {
108247-	r.editorOnce.Do(func() {
108248-		dir := r.getDir()
108249-
108250-		start := time.Now()
108251-		log.Printf("starting initial workspace load for %s", r.name)
108252-		ts, err := newGoplsServer(r.name)
108253-		if err != nil {
108254-			log.Fatal(err)
108255-		}
108256-		r.sandbox, r.editor, r.awaiter, err = connectEditor(dir, fake.EditorConfig{}, ts)
108257-		if err != nil {
108258-			log.Fatalf("connecting editor: %v", err)
108259-		}
108260-
108261-		if err := r.awaiter.Await(context.Background(), InitialWorkspaceLoad); err != nil {
108262-			log.Fatal(err)
108263-		}
108264-		log.Printf("initial workspace load (cold) for %s took %v", r.name, time.Since(start))
108265-	})
108266-
108267-	return &Env{
108268-		T:       tb,
108269-		Ctx:     context.Background(),
108270-		Editor:  r.editor,
108271-		Sandbox: r.sandbox,
108272-		Awaiter: r.awaiter,
108273-	}
108274-}
108275-
108276-// newEnv returns a new Env connected to a new gopls process communicating
108277-// over stdin/stdout. It is safe for concurrent use.
108278-//
108279-// It is the caller's responsibility to call Close on the resulting Env when it
108280-// is no longer needed.
108281-func (r *repo) newEnv(tb testing.TB, name string, config fake.EditorConfig) *Env {
108282-	dir := r.getDir()
108283-
108284-	ts, err := newGoplsServer(name)
108285-	if err != nil {
108286-		tb.Fatal(err)
108287-	}
108288-	sandbox, editor, awaiter, err := connectEditor(dir, config, ts)
108289-	if err != nil {
108290-		log.Fatalf("connecting editor: %v", err)
108291-	}
108292-
108293-	return &Env{
108294-		T:       tb,
108295-		Ctx:     context.Background(),
108296-		Editor:  editor,
108297-		Sandbox: sandbox,
108298-		Awaiter: awaiter,
108299-	}
108300-}
108301-
108302-// Close cleans up shared state referenced by the repo.
108303-func (r *repo) Close() error {
108304-	var errBuf bytes.Buffer
108305-	if r.editor != nil {
108306-		if err := r.editor.Close(context.Background()); err != nil {
108307-			fmt.Fprintf(&errBuf, "closing editor: %v", err)
108308-		}
108309-	}
108310-	if r.sandbox != nil {
108311-		if err := r.sandbox.Close(); err != nil {
108312-			fmt.Fprintf(&errBuf, "closing sandbox: %v", err)
108313-		}
108314-	}
108315-	if r.dir != "" {
108316-		if err := os.RemoveAll(r.dir); err != nil {
108317-			fmt.Fprintf(&errBuf, "cleaning dir: %v", err)
108318-		}
108319-	}
108320-	if errBuf.Len() > 0 {
108321-		return errors.New(errBuf.String())
108322-	}
108323-	return nil
108324-}
108325-
108326-// cleanup cleans up state that is shared across benchmark functions.
108327-func cleanup() error {
108328-	var errBuf bytes.Buffer
108329-	for _, repo := range repos {
108330-		if err := repo.Close(); err != nil {
108331-			fmt.Fprintf(&errBuf, "closing %q: %v", repo.name, err)
108332-		}
108333-	}
108334-	if tempDir != "" {
108335-		if err := os.RemoveAll(tempDir); err != nil {
108336-			fmt.Fprintf(&errBuf, "cleaning tempDir: %v", err)
108337-		}
108338-	}
108339-	if errBuf.Len() > 0 {
108340-		return errors.New(errBuf.String())
108341-	}
108342-	return nil
108343-}
108344diff -urN a/gopls/internal/regtest/bench/stress_test.go b/gopls/internal/regtest/bench/stress_test.go
108345--- a/gopls/internal/regtest/bench/stress_test.go	2000-01-01 00:00:00.000000000 -0000
108346+++ b/gopls/internal/regtest/bench/stress_test.go	1970-01-01 00:00:00.000000000 +0000
108347@@ -1,94 +0,0 @@
108348-// Copyright 2020 The Go Authors. All rights reserved.
108349-// Use of this source code is governed by a BSD-style
108350-// license that can be found in the LICENSE file.
108351-
108352-package bench
108353-
108354-import (
108355-	"context"
108356-	"flag"
108357-	"fmt"
108358-	"testing"
108359-	"time"
108360-
108361-	"golang.org/x/tools/gopls/internal/hooks"
108362-	"golang.org/x/tools/gopls/internal/lsp/cache"
108363-	"golang.org/x/tools/gopls/internal/lsp/fake"
108364-	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
108365-	"golang.org/x/tools/internal/jsonrpc2"
108366-	"golang.org/x/tools/internal/jsonrpc2/servertest"
108367-)
108368-
108369-// github.com/pilosa/pilosa is a repository that has historically caused
108370-// significant memory problems for Gopls. We use it for a simple stress test
108371-// that types arbitrarily in a file with lots of dependents.
108372-
108373-var pilosaPath = flag.String("pilosa_path", "", "Path to a directory containing "+
108374-	"github.com/pilosa/pilosa, for stress testing. Do not set this unless you "+
108375-	"know what you're doing!")
108376-
108377-func TestPilosaStress(t *testing.T) {
108378-	// TODO(rfindley): revisit this test and make it is hermetic: it should check
108379-	// out pilosa into a directory.
108380-	//
108381-	// Note: This stress test has not been run recently, and may no longer
108382-	// function properly.
108383-	if *pilosaPath == "" {
108384-		t.Skip("-pilosa_path not configured")
108385-	}
108386-
108387-	sandbox, err := fake.NewSandbox(&fake.SandboxConfig{
108388-		Workdir: *pilosaPath,
108389-		GOPROXY: "https://proxy.golang.org",
108390-	})
108391-	if err != nil {
108392-		t.Fatal(err)
108393-	}
108394-
108395-	server := lsprpc.NewStreamServer(cache.New(nil), false, hooks.Options)
108396-	ts := servertest.NewPipeServer(server, jsonrpc2.NewRawStream)
108397-	ctx := context.Background()
108398-
108399-	const skipApplyEdits = false
108400-	editor, err := fake.NewEditor(sandbox, fake.EditorConfig{}).Connect(ctx, ts, fake.ClientHooks{}, skipApplyEdits)
108401-	if err != nil {
108402-		t.Fatal(err)
108403-	}
108404-
108405-	files := []string{
108406-		"cmd.go",
108407-		"internal/private.pb.go",
108408-		"roaring/roaring.go",
108409-		"roaring/roaring_internal_test.go",
108410-		"server/handler_test.go",
108411-	}
108412-	for _, file := range files {
108413-		if err := editor.OpenFile(ctx, file); err != nil {
108414-			t.Fatal(err)
108415-		}
108416-	}
108417-	ctx, cancel := context.WithTimeout(ctx, 10*time.Minute)
108418-	defer cancel()
108419-
108420-	i := 1
108421-	// MagicNumber is an identifier that occurs in roaring.go. Just change it
108422-	// arbitrarily.
108423-	if err := editor.RegexpReplace(ctx, "roaring/roaring.go", "MagicNumber", fmt.Sprintf("MagicNumber%d", 1)); err != nil {
108424-		t.Fatal(err)
108425-	}
108426-	for {
108427-		select {
108428-		case <-ctx.Done():
108429-			return
108430-		default:
108431-		}
108432-		if err := editor.RegexpReplace(ctx, "roaring/roaring.go", fmt.Sprintf("MagicNumber%d", i), fmt.Sprintf("MagicNumber%d", i+1)); err != nil {
108433-			t.Fatal(err)
108434-		}
108435-		// Simulate (very fast) typing.
108436-		//
108437-		// Typing 80 wpm ~150ms per keystroke.
108438-		time.Sleep(150 * time.Millisecond)
108439-		i++
108440-	}
108441-}
108442diff -urN a/gopls/internal/regtest/bench/workspace_symbols_test.go b/gopls/internal/regtest/bench/workspace_symbols_test.go
108443--- a/gopls/internal/regtest/bench/workspace_symbols_test.go	2000-01-01 00:00:00.000000000 -0000
108444+++ b/gopls/internal/regtest/bench/workspace_symbols_test.go	1970-01-01 00:00:00.000000000 +0000
108445@@ -1,37 +0,0 @@
108446-// Copyright 2022 The Go Authors. All rights reserved.
108447-// Use of this source code is governed by a BSD-style
108448-// license that can be found in the LICENSE file.
108449-
108450-package bench
108451-
108452-import (
108453-	"flag"
108454-	"fmt"
108455-	"testing"
108456-)
108457-
108458-var symbolQuery = flag.String("symbol_query", "test", "symbol query to use in benchmark")
108459-
108460-// BenchmarkWorkspaceSymbols benchmarks the time to execute a workspace symbols
108461-// request (controlled by the -symbol_query flag).
108462-func BenchmarkWorkspaceSymbols(b *testing.B) {
108463-	for name := range repos {
108464-		b.Run(name, func(b *testing.B) {
108465-			env := getRepo(b, name).sharedEnv(b)
108466-			symbols := env.Symbol(*symbolQuery) // warm the cache
108467-
108468-			if testing.Verbose() {
108469-				fmt.Println("Results:")
108470-				for i, symbol := range symbols {
108471-					fmt.Printf("\t%d. %s (%s)\n", i, symbol.Name, symbol.ContainerName)
108472-				}
108473-			}
108474-
108475-			b.ResetTimer()
108476-
108477-			for i := 0; i < b.N; i++ {
108478-				env.Symbol(*symbolQuery)
108479-			}
108480-		})
108481-	}
108482-}
108483diff -urN a/gopls/internal/regtest/codelens/codelens_test.go b/gopls/internal/regtest/codelens/codelens_test.go
108484--- a/gopls/internal/regtest/codelens/codelens_test.go	2000-01-01 00:00:00.000000000 -0000
108485+++ b/gopls/internal/regtest/codelens/codelens_test.go	1970-01-01 00:00:00.000000000 +0000
108486@@ -1,336 +0,0 @@
108487-// Copyright 2020 The Go Authors. All rights reserved.
108488-// Use of this source code is governed by a BSD-style
108489-// license that can be found in the LICENSE file.
108490-
108491-package codelens
108492-
108493-import (
108494-	"fmt"
108495-	"testing"
108496-
108497-	"golang.org/x/tools/gopls/internal/hooks"
108498-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
108499-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
108500-	"golang.org/x/tools/internal/bug"
108501-
108502-	"golang.org/x/tools/gopls/internal/lsp/command"
108503-	"golang.org/x/tools/gopls/internal/lsp/protocol"
108504-	"golang.org/x/tools/internal/testenv"
108505-)
108506-
108507-func TestMain(m *testing.M) {
108508-	bug.PanicOnBugs = true
108509-	Main(m, hooks.Options)
108510-}
108511-
108512-func TestDisablingCodeLens(t *testing.T) {
108513-	const workspace = `
108514--- go.mod --
108515-module codelens.test
108516-
108517-go 1.12
108518--- lib.go --
108519-package lib
108520-
108521-type Number int
108522-
108523-const (
108524-	Zero Number = iota
108525-	One
108526-	Two
108527-)
108528-
108529-//` + `go:generate stringer -type=Number
108530-`
108531-	tests := []struct {
108532-		label        string
108533-		enabled      map[string]bool
108534-		wantCodeLens bool
108535-	}{
108536-		{
108537-			label:        "default",
108538-			wantCodeLens: true,
108539-		},
108540-		{
108541-			label:        "generate disabled",
108542-			enabled:      map[string]bool{string(command.Generate): false},
108543-			wantCodeLens: false,
108544-		},
108545-	}
108546-	for _, test := range tests {
108547-		t.Run(test.label, func(t *testing.T) {
108548-			WithOptions(
108549-				Settings{"codelenses": test.enabled},
108550-			).Run(t, workspace, func(t *testing.T, env *Env) {
108551-				env.OpenFile("lib.go")
108552-				lens := env.CodeLens("lib.go")
108553-				if gotCodeLens := len(lens) > 0; gotCodeLens != test.wantCodeLens {
108554-					t.Errorf("got codeLens: %t, want %t", gotCodeLens, test.wantCodeLens)
108555-				}
108556-			})
108557-		})
108558-	}
108559-}
108560-
108561-// This test confirms the full functionality of the code lenses for updating
108562-// dependencies in a go.mod file. It checks for the code lens that suggests
108563-// an update and then executes the command associated with that code lens. A
108564-// regression test for golang/go#39446. It also checks that these code lenses
108565-// only affect the diagnostics and contents of the containing go.mod file.
108566-func TestUpgradeCodelens(t *testing.T) {
108567-	testenv.NeedsGo1Point(t, 18) // uses go.work
108568-
108569-	const proxyWithLatest = `
108570--- golang.org/x/hello@v1.3.3/go.mod --
108571-module golang.org/x/hello
108572-
108573-go 1.12
108574--- golang.org/x/hello@v1.3.3/hi/hi.go --
108575-package hi
108576-
108577-var Goodbye error
108578--- golang.org/x/hello@v1.2.3/go.mod --
108579-module golang.org/x/hello
108580-
108581-go 1.12
108582--- golang.org/x/hello@v1.2.3/hi/hi.go --
108583-package hi
108584-
108585-var Goodbye error
108586-`
108587-
108588-	const shouldUpdateDep = `
108589--- go.work --
108590-go 1.18
108591-
108592-use (
108593-	./a
108594-	./b
108595-)
108596--- a/go.mod --
108597-module mod.com/a
108598-
108599-go 1.14
108600-
108601-require golang.org/x/hello v1.2.3
108602--- a/go.sum --
108603-golang.org/x/hello v1.2.3 h1:7Wesfkx/uBd+eFgPrq0irYj/1XfmbvLV8jZ/W7C2Dwg=
108604-golang.org/x/hello v1.2.3/go.mod h1:OgtlzsxVMUUdsdQCIDYgaauCTH47B8T8vofouNJfzgY=
108605--- a/main.go --
108606-package main
108607-
108608-import "golang.org/x/hello/hi"
108609-
108610-func main() {
108611-	_ = hi.Goodbye
108612-}
108613--- b/go.mod --
108614-module mod.com/b
108615-
108616-go 1.14
108617-
108618-require golang.org/x/hello v1.2.3
108619--- b/go.sum --
108620-golang.org/x/hello v1.2.3 h1:7Wesfkx/uBd+eFgPrq0irYj/1XfmbvLV8jZ/W7C2Dwg=
108621-golang.org/x/hello v1.2.3/go.mod h1:OgtlzsxVMUUdsdQCIDYgaauCTH47B8T8vofouNJfzgY=
108622--- b/main.go --
108623-package main
108624-
108625-import (
108626-	"golang.org/x/hello/hi"
108627-)
108628-
108629-func main() {
108630-	_ = hi.Goodbye
108631-}
108632-`
108633-
108634-	const wantGoModA = `module mod.com/a
108635-
108636-go 1.14
108637-
108638-require golang.org/x/hello v1.3.3
108639-`
108640-	// Applying the diagnostics or running the codelenses for a/go.mod
108641-	// should not change the contents of b/go.mod
108642-	const wantGoModB = `module mod.com/b
108643-
108644-go 1.14
108645-
108646-require golang.org/x/hello v1.2.3
108647-`
108648-
108649-	for _, commandTitle := range []string{
108650-		"Upgrade transitive dependencies",
108651-		"Upgrade direct dependencies",
108652-	} {
108653-		t.Run(commandTitle, func(t *testing.T) {
108654-			WithOptions(
108655-				ProxyFiles(proxyWithLatest),
108656-			).Run(t, shouldUpdateDep, func(t *testing.T, env *Env) {
108657-				env.OpenFile("a/go.mod")
108658-				env.OpenFile("b/go.mod")
108659-				var lens protocol.CodeLens
108660-				var found bool
108661-				for _, l := range env.CodeLens("a/go.mod") {
108662-					if l.Command.Title == commandTitle {
108663-						lens = l
108664-						found = true
108665-					}
108666-				}
108667-				if !found {
108668-					t.Fatalf("found no command with the title %s", commandTitle)
108669-				}
108670-				if _, err := env.Editor.ExecuteCommand(env.Ctx, &protocol.ExecuteCommandParams{
108671-					Command:   lens.Command.Command,
108672-					Arguments: lens.Command.Arguments,
108673-				}); err != nil {
108674-					t.Fatal(err)
108675-				}
108676-				env.AfterChange()
108677-				if got := env.BufferText("a/go.mod"); got != wantGoModA {
108678-					t.Fatalf("a/go.mod upgrade failed:\n%s", compare.Text(wantGoModA, got))
108679-				}
108680-				if got := env.BufferText("b/go.mod"); got != wantGoModB {
108681-					t.Fatalf("b/go.mod changed unexpectedly:\n%s", compare.Text(wantGoModB, got))
108682-				}
108683-			})
108684-		})
108685-	}
108686-	for _, vendoring := range []bool{false, true} {
108687-		t.Run(fmt.Sprintf("Upgrade individual dependency vendoring=%v", vendoring), func(t *testing.T) {
108688-			WithOptions(ProxyFiles(proxyWithLatest)).Run(t, shouldUpdateDep, func(t *testing.T, env *Env) {
108689-				if vendoring {
108690-					env.RunGoCommandInDir("a", "mod", "vendor")
108691-				}
108692-				env.AfterChange()
108693-				env.OpenFile("a/go.mod")
108694-				env.OpenFile("b/go.mod")
108695-				env.ExecuteCodeLensCommand("a/go.mod", command.CheckUpgrades, nil)
108696-				d := &protocol.PublishDiagnosticsParams{}
108697-				env.OnceMet(
108698-					Diagnostics(env.AtRegexp("a/go.mod", `require`), WithMessage("can be upgraded")),
108699-					ReadDiagnostics("a/go.mod", d),
108700-					// We do not want there to be a diagnostic for b/go.mod,
108701-					// but there may be some subtlety in timing here, where this
108702-					// should always succeed, but may not actually test the correct
108703-					// behavior.
108704-					NoDiagnostics(env.AtRegexp("b/go.mod", `require`)),
108705-				)
108706-				// Check for upgrades in b/go.mod and then clear them.
108707-				env.ExecuteCodeLensCommand("b/go.mod", command.CheckUpgrades, nil)
108708-				env.Await(Diagnostics(env.AtRegexp("b/go.mod", `require`), WithMessage("can be upgraded")))
108709-				env.ExecuteCodeLensCommand("b/go.mod", command.ResetGoModDiagnostics, nil)
108710-				env.Await(NoDiagnostics(ForFile("b/go.mod")))
108711-
108712-				// Apply the diagnostics to a/go.mod.
108713-				env.ApplyQuickFixes("a/go.mod", d.Diagnostics)
108714-				env.AfterChange()
108715-				if got := env.BufferText("a/go.mod"); got != wantGoModA {
108716-					t.Fatalf("a/go.mod upgrade failed:\n%s", compare.Text(wantGoModA, got))
108717-				}
108718-				if got := env.BufferText("b/go.mod"); got != wantGoModB {
108719-					t.Fatalf("b/go.mod changed unexpectedly:\n%s", compare.Text(wantGoModB, got))
108720-				}
108721-			})
108722-		})
108723-	}
108724-}
108725-
108726-func TestUnusedDependenciesCodelens(t *testing.T) {
108727-	const proxy = `
108728--- golang.org/x/hello@v1.0.0/go.mod --
108729-module golang.org/x/hello
108730-
108731-go 1.14
108732--- golang.org/x/hello@v1.0.0/hi/hi.go --
108733-package hi
108734-
108735-var Goodbye error
108736--- golang.org/x/unused@v1.0.0/go.mod --
108737-module golang.org/x/unused
108738-
108739-go 1.14
108740--- golang.org/x/unused@v1.0.0/nouse/nouse.go --
108741-package nouse
108742-
108743-var NotUsed error
108744-`
108745-
108746-	const shouldRemoveDep = `
108747--- go.mod --
108748-module mod.com
108749-
108750-go 1.14
108751-
108752-require golang.org/x/hello v1.0.0
108753-require golang.org/x/unused v1.0.0
108754--- go.sum --
108755-golang.org/x/hello v1.0.0 h1:qbzE1/qT0/zojAMd/JcPsO2Vb9K4Bkeyq0vB2JGMmsw=
108756-golang.org/x/hello v1.0.0/go.mod h1:WW7ER2MRNXWA6c8/4bDIek4Hc/+DofTrMaQQitGXcco=
108757-golang.org/x/unused v1.0.0 h1:LecSbCn5P3vTcxubungSt1Pn4D/WocCaiWOPDC0y0rw=
108758-golang.org/x/unused v1.0.0/go.mod h1:ihoW8SgWzugwwj0N2SfLfPZCxTB1QOVfhMfB5PWTQ8U=
108759--- main.go --
108760-package main
108761-
108762-import "golang.org/x/hello/hi"
108763-
108764-func main() {
108765-	_ = hi.Goodbye
108766-}
108767-`
108768-	WithOptions(ProxyFiles(proxy)).Run(t, shouldRemoveDep, func(t *testing.T, env *Env) {
108769-		env.OpenFile("go.mod")
108770-		env.ExecuteCodeLensCommand("go.mod", command.Tidy, nil)
108771-		env.Await(env.DoneWithChangeWatchedFiles())
108772-		got := env.BufferText("go.mod")
108773-		const wantGoMod = `module mod.com
108774-
108775-go 1.14
108776-
108777-require golang.org/x/hello v1.0.0
108778-`
108779-		if got != wantGoMod {
108780-			t.Fatalf("go.mod tidy failed:\n%s", compare.Text(wantGoMod, got))
108781-		}
108782-	})
108783-}
108784-
108785-func TestRegenerateCgo(t *testing.T) {
108786-	testenv.NeedsTool(t, "cgo")
108787-	const workspace = `
108788--- go.mod --
108789-module example.com
108790-
108791-go 1.12
108792--- cgo.go --
108793-package x
108794-
108795-/*
108796-int fortythree() { return 42; }
108797-*/
108798-import "C"
108799-
108800-func Foo() {
108801-	print(C.fortytwo())
108802-}
108803-`
108804-	Run(t, workspace, func(t *testing.T, env *Env) {
108805-		// Open the file. We have a nonexistant symbol that will break cgo processing.
108806-		env.OpenFile("cgo.go")
108807-		env.AfterChange(
108808-			Diagnostics(env.AtRegexp("cgo.go", ``), WithMessage("go list failed to return CompiledGoFiles")),
108809-		)
108810-
108811-		// Fix the C function name. We haven't regenerated cgo, so nothing should be fixed.
108812-		env.RegexpReplace("cgo.go", `int fortythree`, "int fortytwo")
108813-		env.SaveBuffer("cgo.go")
108814-		env.AfterChange(
108815-			Diagnostics(env.AtRegexp("cgo.go", ``), WithMessage("go list failed to return CompiledGoFiles")),
108816-		)
108817-
108818-		// Regenerate cgo, fixing the diagnostic.
108819-		env.ExecuteCodeLensCommand("cgo.go", command.RegenerateCgo, nil)
108820-		env.Await(NoDiagnostics(ForFile("cgo.go")))
108821-	})
108822-}
108823diff -urN a/gopls/internal/regtest/codelens/gcdetails_test.go b/gopls/internal/regtest/codelens/gcdetails_test.go
108824--- a/gopls/internal/regtest/codelens/gcdetails_test.go	2000-01-01 00:00:00.000000000 -0000
108825+++ b/gopls/internal/regtest/codelens/gcdetails_test.go	1970-01-01 00:00:00.000000000 +0000
108826@@ -1,127 +0,0 @@
108827-// Copyright 2020 The Go Authors. All rights reserved.
108828-// Use of this source code is governed by a BSD-style
108829-// license that can be found in the LICENSE file.
108830-
108831-package codelens
108832-
108833-import (
108834-	"runtime"
108835-	"strings"
108836-	"testing"
108837-
108838-	"golang.org/x/tools/gopls/internal/lsp/command"
108839-	"golang.org/x/tools/gopls/internal/lsp/fake"
108840-	"golang.org/x/tools/gopls/internal/lsp/protocol"
108841-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
108842-	"golang.org/x/tools/internal/bug"
108843-)
108844-
108845-func TestGCDetails_Toggle(t *testing.T) {
108846-	if runtime.GOOS == "android" {
108847-		t.Skipf("the gc details code lens doesn't work on Android")
108848-	}
108849-
108850-	const mod = `
108851--- go.mod --
108852-module mod.com
108853-
108854-go 1.15
108855--- main.go --
108856-package main
108857-
108858-import "fmt"
108859-
108860-func main() {
108861-	fmt.Println(42)
108862-}
108863-`
108864-	WithOptions(
108865-		Settings{
108866-			"codelenses": map[string]bool{
108867-				"gc_details": true,
108868-			},
108869-		},
108870-	).Run(t, mod, func(t *testing.T, env *Env) {
108871-		env.OpenFile("main.go")
108872-		env.ExecuteCodeLensCommand("main.go", command.GCDetails, nil)
108873-		d := &protocol.PublishDiagnosticsParams{}
108874-		env.OnceMet(
108875-			Diagnostics(AtPosition("main.go", 5, 13)),
108876-			ReadDiagnostics("main.go", d),
108877-		)
108878-		// Confirm that the diagnostics come from the gc details code lens.
108879-		var found bool
108880-		for _, d := range d.Diagnostics {
108881-			if d.Severity != protocol.SeverityInformation {
108882-				t.Fatalf("unexpected diagnostic severity %v, wanted Information", d.Severity)
108883-			}
108884-			if strings.Contains(d.Message, "42 escapes") {
108885-				found = true
108886-			}
108887-		}
108888-		if !found {
108889-			t.Fatalf(`expected to find diagnostic with message "escape(42 escapes to heap)", found none`)
108890-		}
108891-
108892-		// Editing a buffer should cause gc_details diagnostics to disappear, since
108893-		// they only apply to saved buffers.
108894-		env.EditBuffer("main.go", fake.NewEdit(0, 0, 0, 0, "\n\n"))
108895-		env.AfterChange(NoDiagnostics(ForFile("main.go")))
108896-
108897-		// Saving a buffer should re-format back to the original state, and
108898-		// re-enable the gc_details diagnostics.
108899-		env.SaveBuffer("main.go")
108900-		env.AfterChange(Diagnostics(AtPosition("main.go", 5, 13)))
108901-
108902-		// Toggle the GC details code lens again so now it should be off.
108903-		env.ExecuteCodeLensCommand("main.go", command.GCDetails, nil)
108904-		env.Await(NoDiagnostics(ForFile("main.go")))
108905-	})
108906-}
108907-
108908-// Test for the crasher in golang/go#54199
108909-func TestGCDetails_NewFile(t *testing.T) {
108910-	bug.PanicOnBugs = false
108911-	const src = `
108912--- go.mod --
108913-module mod.test
108914-
108915-go 1.12
108916-`
108917-
108918-	WithOptions(
108919-		Settings{
108920-			"codelenses": map[string]bool{
108921-				"gc_details": true,
108922-			},
108923-		},
108924-	).Run(t, src, func(t *testing.T, env *Env) {
108925-		env.CreateBuffer("p_test.go", "")
108926-
108927-		const gcDetailsCommand = "gopls." + string(command.GCDetails)
108928-
108929-		hasGCDetails := func() bool {
108930-			lenses := env.CodeLens("p_test.go") // should not crash
108931-			for _, lens := range lenses {
108932-				if lens.Command.Command == gcDetailsCommand {
108933-					return true
108934-				}
108935-			}
108936-			return false
108937-		}
108938-
108939-		// With an empty file, we shouldn't get the gc_details codelens because
108940-		// there is nowhere to position it (it needs a package name).
108941-		if hasGCDetails() {
108942-			t.Errorf("got the gc_details codelens for an empty file")
108943-		}
108944-
108945-		// Edit to provide a package name.
108946-		env.EditBuffer("p_test.go", fake.NewEdit(0, 0, 0, 0, "package p"))
108947-
108948-		// Now we should get the gc_details codelens.
108949-		if !hasGCDetails() {
108950-			t.Errorf("didn't get the gc_details codelens for a valid non-empty Go file")
108951-		}
108952-	})
108953-}
108954diff -urN a/gopls/internal/regtest/completion/completion18_test.go b/gopls/internal/regtest/completion/completion18_test.go
108955--- a/gopls/internal/regtest/completion/completion18_test.go	2000-01-01 00:00:00.000000000 -0000
108956+++ b/gopls/internal/regtest/completion/completion18_test.go	1970-01-01 00:00:00.000000000 +0000
108957@@ -1,124 +0,0 @@
108958-// Copyright 2021 The Go Authors. All rights reserved.
108959-// Use of this source code is governed by a BSD-style
108960-// license that can be found in the LICENSE file.
108961-
108962-//go:build go1.18
108963-// +build go1.18
108964-
108965-package completion
108966-
108967-import (
108968-	"testing"
108969-
108970-	"golang.org/x/tools/gopls/internal/lsp/protocol"
108971-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
108972-)
108973-
108974-// test generic receivers
108975-func TestGenericReceiver(t *testing.T) {
108976-	const files = `
108977--- go.mod --
108978-module mod.com
108979-
108980-go 1.18
108981--- main.go --
108982-package main
108983-type SyncMap[K any, V comparable] struct {}
108984-func (s *SyncMap[K,V]) f() {}
108985-type XX[T any] struct {}
108986-type UU[T any] struct {}
108987-func (s SyncMap[XX,string]) g(v UU) {}
108988-`
108989-
108990-	tests := []struct {
108991-		pat  string
108992-		want []string
108993-	}{
108994-		{"s .Syn", []string{"SyncMap[K, V]"}},
108995-		{"Map.X", []string{}}, // This is probably wrong, Maybe "XX"?
108996-		{"v U", []string{"UU", "uint", "uint16", "uint32", "uint64", "uint8", "uintptr"}}, // not U[T]
108997-	}
108998-	Run(t, files, func(t *testing.T, env *Env) {
108999-		env.OpenFile("main.go")
109000-		env.Await(env.DoneWithOpen())
109001-		for _, tst := range tests {
109002-			loc := env.RegexpSearch("main.go", tst.pat)
109003-			loc.Range.Start.Character += uint32(protocol.UTF16Len([]byte(tst.pat)))
109004-			completions := env.Completion(loc)
109005-			result := compareCompletionLabels(tst.want, completions.Items)
109006-			if result != "" {
109007-				t.Errorf("%s: wanted %v", result, tst.want)
109008-				for i, g := range completions.Items {
109009-					t.Errorf("got %d %s %s", i, g.Label, g.Detail)
109010-				}
109011-			}
109012-		}
109013-	})
109014-}
109015-func TestFuzzFunc(t *testing.T) {
109016-	// use the example from the package documentation
109017-	modfile := `
109018--- go.mod --
109019-module mod.com
109020-
109021-go 1.18
109022-`
109023-	part0 := `package foo
109024-import "testing"
109025-func FuzzNone(f *testing.F) {
109026-	f.Add(12) // better not find this f.Add
109027-}
109028-func FuzzHex(f *testing.F) {
109029-	for _, seed := range [][]byte{{}, {0}, {9}, {0xa}, {0xf}, {1, 2, 3, 4}} {
109030-		f.Ad`
109031-	part1 := `d(seed)
109032-	}
109033-	f.F`
109034-	part2 := `uzz(func(t *testing.T, in []byte) {
109035-		enc := hex.EncodeToString(in)
109036-		out, err := hex.DecodeString(enc)
109037-		if err != nil {
109038-		  f.Failed()
109039-		}
109040-		if !bytes.Equal(in, out) {
109041-		  t.Fatalf("%v: round trip: %v, %s", in, out, f.Name())
109042-		}
109043-	})
109044-}
109045-`
109046-	data := modfile + `-- a_test.go --
109047-` + part0 + `
109048--- b_test.go --
109049-` + part0 + part1 + `
109050--- c_test.go --
109051-` + part0 + part1 + part2
109052-
109053-	tests := []struct {
109054-		file   string
109055-		pat    string
109056-		offset uint32 // UTF16 length from the beginning of pat to what the user just typed
109057-		want   []string
109058-	}{
109059-		{"a_test.go", "f.Ad", 3, []string{"Add"}},
109060-		{"c_test.go", " f.F", 4, []string{"Failed"}},
109061-		{"c_test.go", "f.N", 3, []string{"Name"}},
109062-		{"b_test.go", "f.F", 3, []string{"Fuzz(func(t *testing.T, a []byte)", "Fail", "FailNow",
109063-			"Failed", "Fatal", "Fatalf"}},
109064-	}
109065-	Run(t, data, func(t *testing.T, env *Env) {
109066-		for _, test := range tests {
109067-			env.OpenFile(test.file)
109068-			env.Await(env.DoneWithOpen())
109069-			loc := env.RegexpSearch(test.file, test.pat)
109070-			loc.Range.Start.Character += test.offset // character user just typed? will type?
109071-			completions := env.Completion(loc)
109072-			result := compareCompletionLabels(test.want, completions.Items)
109073-			if result != "" {
109074-				t.Errorf("pat %q %q", test.pat, result)
109075-				for i, it := range completions.Items {
109076-					t.Errorf("%d got %q %q", i, it.Label, it.Detail)
109077-				}
109078-			}
109079-		}
109080-	})
109081-}
109082diff -urN a/gopls/internal/regtest/completion/completion_test.go b/gopls/internal/regtest/completion/completion_test.go
109083--- a/gopls/internal/regtest/completion/completion_test.go	2000-01-01 00:00:00.000000000 -0000
109084+++ b/gopls/internal/regtest/completion/completion_test.go	1970-01-01 00:00:00.000000000 +0000
109085@@ -1,754 +0,0 @@
109086-// Copyright 2020 The Go Authors. All rights reserved.
109087-// Use of this source code is governed by a BSD-style
109088-// license that can be found in the LICENSE file.
109089-
109090-package completion
109091-
109092-import (
109093-	"fmt"
109094-	"strings"
109095-	"testing"
109096-
109097-	"github.com/google/go-cmp/cmp"
109098-	"golang.org/x/tools/gopls/internal/hooks"
109099-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
109100-	"golang.org/x/tools/internal/bug"
109101-	"golang.org/x/tools/internal/testenv"
109102-
109103-	"golang.org/x/tools/gopls/internal/lsp/protocol"
109104-)
109105-
109106-func TestMain(m *testing.M) {
109107-	bug.PanicOnBugs = true
109108-	Main(m, hooks.Options)
109109-}
109110-
109111-const proxy = `
109112--- [email protected]/go.mod --
109113-module example.com
109114-
109115-go 1.12
109116--- [email protected]/blah/blah.go --
109117-package blah
109118-
109119-const Name = "Blah"
109120--- [email protected]/go.mod --
109121-module random.org
109122-
109123-go 1.12
109124--- [email protected]/blah/blah.go --
109125-package hello
109126-
109127-const Name = "Hello"
109128-`
109129-
109130-func TestPackageCompletion(t *testing.T) {
109131-	const files = `
109132--- go.mod --
109133-module mod.com
109134-
109135-go 1.12
109136--- fruits/apple.go --
109137-package apple
109138-
109139-fun apple() int {
109140-	return 0
109141-}
109142-
109143--- fruits/testfile.go --
109144-// this is a comment
109145-
109146-/*
109147- this is a multiline comment
109148-*/
109149-
109150-import "fmt"
109151-
109152-func test() {}
109153-
109154--- fruits/testfile2.go --
109155-package
109156-
109157--- fruits/testfile3.go --
109158-pac
109159--- 123f_r.u~its-123/testfile.go --
109160-package
109161-
109162--- .invalid-dir@-name/testfile.go --
109163-package
109164-`
109165-	var (
109166-		testfile4 = ""
109167-		testfile5 = "/*a comment*/ "
109168-		testfile6 = "/*a comment*/\n"
109169-	)
109170-	for _, tc := range []struct {
109171-		name          string
109172-		filename      string
109173-		content       *string
109174-		triggerRegexp string
109175-		want          []string
109176-		editRegexp    string
109177-	}{
109178-		{
109179-			name:          "package completion at valid position",
109180-			filename:      "fruits/testfile.go",
109181-			triggerRegexp: "\n()",
109182-			want:          []string{"package apple", "package apple_test", "package fruits", "package fruits_test", "package main"},
109183-			editRegexp:    "\n()",
109184-		},
109185-		{
109186-			name:          "package completion in a comment",
109187-			filename:      "fruits/testfile.go",
109188-			triggerRegexp: "th(i)s",
109189-			want:          nil,
109190-		},
109191-		{
109192-			name:          "package completion in a multiline comment",
109193-			filename:      "fruits/testfile.go",
109194-			triggerRegexp: `\/\*\n()`,
109195-			want:          nil,
109196-		},
109197-		{
109198-			name:          "package completion at invalid position",
109199-			filename:      "fruits/testfile.go",
109200-			triggerRegexp: "import \"fmt\"\n()",
109201-			want:          nil,
109202-		},
109203-		{
109204-			name:          "package completion after keyword 'package'",
109205-			filename:      "fruits/testfile2.go",
109206-			triggerRegexp: "package()",
109207-			want:          []string{"package apple", "package apple_test", "package fruits", "package fruits_test", "package main"},
109208-			editRegexp:    "package\n",
109209-		},
109210-		{
109211-			name:          "package completion with 'pac' prefix",
109212-			filename:      "fruits/testfile3.go",
109213-			triggerRegexp: "pac()",
109214-			want:          []string{"package apple", "package apple_test", "package fruits", "package fruits_test", "package main"},
109215-			editRegexp:    "pac",
109216-		},
109217-		{
109218-			name:          "package completion for empty file",
109219-			filename:      "fruits/testfile4.go",
109220-			triggerRegexp: "^$",
109221-			content:       &testfile4,
109222-			want:          []string{"package apple", "package apple_test", "package fruits", "package fruits_test", "package main"},
109223-			editRegexp:    "^$",
109224-		},
109225-		{
109226-			name:          "package completion without terminal newline",
109227-			filename:      "fruits/testfile5.go",
109228-			triggerRegexp: `\*\/ ()`,
109229-			content:       &testfile5,
109230-			want:          []string{"package apple", "package apple_test", "package fruits", "package fruits_test", "package main"},
109231-			editRegexp:    `\*\/ ()`,
109232-		},
109233-		{
109234-			name:          "package completion on terminal newline",
109235-			filename:      "fruits/testfile6.go",
109236-			triggerRegexp: `\*\/\n()`,
109237-			content:       &testfile6,
109238-			want:          []string{"package apple", "package apple_test", "package fruits", "package fruits_test", "package main"},
109239-			editRegexp:    `\*\/\n()`,
109240-		},
109241-		// Issue golang/go#44680
109242-		{
109243-			name:          "package completion for dir name with punctuation",
109244-			filename:      "123f_r.u~its-123/testfile.go",
109245-			triggerRegexp: "package()",
109246-			want:          []string{"package fruits123", "package fruits123_test", "package main"},
109247-			editRegexp:    "package\n",
109248-		},
109249-		{
109250-			name:          "package completion for invalid dir name",
109251-			filename:      ".invalid-dir@-name/testfile.go",
109252-			triggerRegexp: "package()",
109253-			want:          []string{"package main"},
109254-			editRegexp:    "package\n",
109255-		},
109256-	} {
109257-		t.Run(tc.name, func(t *testing.T) {
109258-			Run(t, files, func(t *testing.T, env *Env) {
109259-				if tc.content != nil {
109260-					env.WriteWorkspaceFile(tc.filename, *tc.content)
109261-					env.Await(env.DoneWithChangeWatchedFiles())
109262-				}
109263-				env.OpenFile(tc.filename)
109264-				completions := env.Completion(env.RegexpSearch(tc.filename, tc.triggerRegexp))
109265-
109266-				// Check that the completion item suggestions are in the range
109267-				// of the file. {Start,End}.Line are zero-based.
109268-				lineCount := len(strings.Split(env.BufferText(tc.filename), "\n"))
109269-				for _, item := range completions.Items {
109270-					if start := int(item.TextEdit.Range.Start.Line); start > lineCount {
109271-						t.Fatalf("unexpected text edit range start line number: got %d, want <= %d", start, lineCount)
109272-					}
109273-					if end := int(item.TextEdit.Range.End.Line); end > lineCount {
109274-						t.Fatalf("unexpected text edit range end line number: got %d, want <= %d", end, lineCount)
109275-					}
109276-				}
109277-
109278-				if tc.want != nil {
109279-					expectedLoc := env.RegexpSearch(tc.filename, tc.editRegexp)
109280-					for _, item := range completions.Items {
109281-						gotRng := item.TextEdit.Range
109282-						if expectedLoc.Range != gotRng {
109283-							t.Errorf("unexpected completion range for completion item %s: got %v, want %v",
109284-								item.Label, gotRng, expectedLoc.Range)
109285-						}
109286-					}
109287-				}
109288-
109289-				diff := compareCompletionLabels(tc.want, completions.Items)
109290-				if diff != "" {
109291-					t.Error(diff)
109292-				}
109293-			})
109294-		})
109295-	}
109296-}
109297-
109298-func TestPackageNameCompletion(t *testing.T) {
109299-	const files = `
109300--- go.mod --
109301-module mod.com
109302-
109303-go 1.12
109304--- math/add.go --
109305-package ma
109306-`
109307-
109308-	want := []string{"ma", "ma_test", "main", "math", "math_test"}
109309-	Run(t, files, func(t *testing.T, env *Env) {
109310-		env.OpenFile("math/add.go")
109311-		completions := env.Completion(env.RegexpSearch("math/add.go", "package ma()"))
109312-
109313-		diff := compareCompletionLabels(want, completions.Items)
109314-		if diff != "" {
109315-			t.Fatal(diff)
109316-		}
109317-	})
109318-}
109319-
109320-// TODO(rfindley): audit/clean up call sites for this helper, to ensure
109321-// consistent test errors.
109322-func compareCompletionLabels(want []string, gotItems []protocol.CompletionItem) string {
109323-	var got []string
109324-	for _, item := range gotItems {
109325-		got = append(got, item.Label)
109326-		if item.Label != item.InsertText && item.TextEdit == nil {
109327-			// Label should be the same as InsertText, if InsertText is to be used
109328-			return fmt.Sprintf("label not the same as InsertText %#v", item)
109329-		}
109330-	}
109331-
109332-	if len(got) == 0 && len(want) == 0 {
109333-		return "" // treat nil and the empty slice as equivalent
109334-	}
109335-
109336-	if diff := cmp.Diff(want, got); diff != "" {
109337-		return fmt.Sprintf("completion item mismatch (-want +got):\n%s", diff)
109338-	}
109339-	return ""
109340-}
109341-
109342-func TestUnimportedCompletion(t *testing.T) {
109343-	const mod = `
109344--- go.mod --
109345-module mod.com
109346-
109347-go 1.14
109348-
109349-require example.com v1.2.3
109350--- go.sum --
109351-example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
109352-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
109353--- main.go --
109354-package main
109355-
109356-func main() {
109357-	_ = blah
109358-}
109359--- main2.go --
109360-package main
109361-
109362-import "example.com/blah"
109363-
109364-func _() {
109365-	_ = blah.Hello
109366-}
109367-`
109368-	WithOptions(
109369-		ProxyFiles(proxy),
109370-	).Run(t, mod, func(t *testing.T, env *Env) {
109371-		// Make sure the dependency is in the module cache and accessible for
109372-		// unimported completions, and then remove it before proceeding.
109373-		env.RemoveWorkspaceFile("main2.go")
109374-		env.RunGoCommand("mod", "tidy")
109375-		env.Await(env.DoneWithChangeWatchedFiles())
109376-
109377-		// Trigger unimported completions for the example.com/blah package.
109378-		env.OpenFile("main.go")
109379-		env.Await(env.DoneWithOpen())
109380-		loc := env.RegexpSearch("main.go", "ah")
109381-		completions := env.Completion(loc)
109382-		if len(completions.Items) == 0 {
109383-			t.Fatalf("no completion items")
109384-		}
109385-		env.AcceptCompletion(loc, completions.Items[0]) // adds blah import to main.go
109386-		env.Await(env.DoneWithChange())
109387-
109388-		// Trigger completions once again for the blah.<> selector.
109389-		env.RegexpReplace("main.go", "_ = blah", "_ = blah.")
109390-		env.Await(env.DoneWithChange())
109391-		loc = env.RegexpSearch("main.go", "\n}")
109392-		completions = env.Completion(loc)
109393-		if len(completions.Items) != 1 {
109394-			t.Fatalf("expected 1 completion item, got %v", len(completions.Items))
109395-		}
109396-		item := completions.Items[0]
109397-		if item.Label != "Name" {
109398-			t.Fatalf("expected completion item blah.Name, got %v", item.Label)
109399-		}
109400-		env.AcceptCompletion(loc, item)
109401-
109402-		// Await the diagnostics to add example.com/blah to the go.mod file.
109403-		env.AfterChange(
109404-			Diagnostics(env.AtRegexp("main.go", `"example.com/blah"`)),
109405-		)
109406-	})
109407-}
109408-
109409-// Test that completions still work with an undownloaded module, golang/go#43333.
109410-func TestUndownloadedModule(t *testing.T) {
109411-	// mod.com depends on example.com, but only in a file that's hidden by a
109412-	// build tag, so the IWL won't download example.com. That will cause errors
109413-	// in the go list -m call performed by the imports package.
109414-	const files = `
109415--- go.mod --
109416-module mod.com
109417-
109418-go 1.14
109419-
109420-require example.com v1.2.3
109421--- go.sum --
109422-example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
109423-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
109424--- useblah.go --
109425-// +build hidden
109426-
109427-package pkg
109428-import "example.com/blah"
109429-var _ = blah.Name
109430--- mainmod/mainmod.go --
109431-package mainmod
109432-
109433-const Name = "mainmod"
109434-`
109435-	WithOptions(ProxyFiles(proxy)).Run(t, files, func(t *testing.T, env *Env) {
109436-		env.CreateBuffer("import.go", "package pkg\nvar _ = mainmod.Name\n")
109437-		env.SaveBuffer("import.go")
109438-		content := env.ReadWorkspaceFile("import.go")
109439-		if !strings.Contains(content, `import "mod.com/mainmod`) {
109440-			t.Errorf("expected import of mod.com/mainmod in %q", content)
109441-		}
109442-	})
109443-}
109444-
109445-// Test that we can doctor the source code enough so the file is
109446-// parseable and completion works as expected.
109447-func TestSourceFixup(t *testing.T) {
109448-	const files = `
109449--- go.mod --
109450-module mod.com
109451-
109452-go 1.12
109453--- foo.go --
109454-package foo
109455-
109456-func _() {
109457-	var s S
109458-	if s.
109459-}
109460-
109461-type S struct {
109462-	i int
109463-}
109464-`
109465-
109466-	Run(t, files, func(t *testing.T, env *Env) {
109467-		env.OpenFile("foo.go")
109468-		completions := env.Completion(env.RegexpSearch("foo.go", `if s\.()`))
109469-		diff := compareCompletionLabels([]string{"i"}, completions.Items)
109470-		if diff != "" {
109471-			t.Fatal(diff)
109472-		}
109473-	})
109474-}
109475-
109476-func TestCompletion_Issue45510(t *testing.T) {
109477-	const files = `
109478--- go.mod --
109479-module mod.com
109480-
109481-go 1.12
109482--- main.go --
109483-package main
109484-
109485-func _() {
109486-	type a *a
109487-	var aaaa1, aaaa2 a
109488-	var _ a = aaaa
109489-
109490-	type b a
109491-	var bbbb1, bbbb2 b
109492-	var _ b = bbbb
109493-}
109494-
109495-type (
109496-	c *d
109497-	d *e
109498-	e **c
109499-)
109500-
109501-func _() {
109502-	var (
109503-		xxxxc c
109504-		xxxxd d
109505-		xxxxe e
109506-	)
109507-
109508-	var _ c = xxxx
109509-	var _ d = xxxx
109510-	var _ e = xxxx
109511-}
109512-`
109513-
109514-	Run(t, files, func(t *testing.T, env *Env) {
109515-		env.OpenFile("main.go")
109516-
109517-		tests := []struct {
109518-			re   string
109519-			want []string
109520-		}{
109521-			{`var _ a = aaaa()`, []string{"aaaa1", "aaaa2"}},
109522-			{`var _ b = bbbb()`, []string{"bbbb1", "bbbb2"}},
109523-			{`var _ c = xxxx()`, []string{"xxxxc", "xxxxd", "xxxxe"}},
109524-			{`var _ d = xxxx()`, []string{"xxxxc", "xxxxd", "xxxxe"}},
109525-			{`var _ e = xxxx()`, []string{"xxxxc", "xxxxd", "xxxxe"}},
109526-		}
109527-		for _, tt := range tests {
109528-			completions := env.Completion(env.RegexpSearch("main.go", tt.re))
109529-			diff := compareCompletionLabels(tt.want, completions.Items)
109530-			if diff != "" {
109531-				t.Errorf("%s: %s", tt.re, diff)
109532-			}
109533-		}
109534-	})
109535-}
109536-
109537-func TestCompletionDeprecation(t *testing.T) {
109538-	const files = `
109539--- go.mod --
109540-module test.com
109541-
109542-go 1.16
109543--- prog.go --
109544-package waste
109545-// Deprecated, use newFoof
109546-func fooFunc() bool {
109547-	return false
109548-}
109549-
109550-// Deprecated
109551-const badPi = 3.14
109552-
109553-func doit() {
109554-	if fooF
109555-	panic()
109556-	x := badP
109557-}
109558-`
109559-	Run(t, files, func(t *testing.T, env *Env) {
109560-		env.OpenFile("prog.go")
109561-		loc := env.RegexpSearch("prog.go", "if fooF")
109562-		loc.Range.Start.Character += uint32(protocol.UTF16Len([]byte("if fooF")))
109563-		completions := env.Completion(loc)
109564-		diff := compareCompletionLabels([]string{"fooFunc"}, completions.Items)
109565-		if diff != "" {
109566-			t.Error(diff)
109567-		}
109568-		if completions.Items[0].Tags == nil {
109569-			t.Errorf("expected Tags to show deprecation %#v", completions.Items[0].Tags)
109570-		}
109571-		loc = env.RegexpSearch("prog.go", "= badP")
109572-		loc.Range.Start.Character += uint32(protocol.UTF16Len([]byte("= badP")))
109573-		completions = env.Completion(loc)
109574-		diff = compareCompletionLabels([]string{"badPi"}, completions.Items)
109575-		if diff != "" {
109576-			t.Error(diff)
109577-		}
109578-		if completions.Items[0].Tags == nil {
109579-			t.Errorf("expected Tags to show deprecation %#v", completions.Items[0].Tags)
109580-		}
109581-	})
109582-}
109583-
109584-func TestUnimportedCompletion_VSCodeIssue1489(t *testing.T) {
109585-	const src = `
109586--- go.mod --
109587-module mod.com
109588-
109589-go 1.14
109590-
109591--- main.go --
109592-package main
109593-
109594-import "fmt"
109595-
109596-func main() {
109597-	fmt.Println("a")
109598-	math.Sqr
109599-}
109600-`
109601-	WithOptions(
109602-		WindowsLineEndings(),
109603-	).Run(t, src, func(t *testing.T, env *Env) {
109604-		// Trigger unimported completions for the mod.com package.
109605-		env.OpenFile("main.go")
109606-		env.Await(env.DoneWithOpen())
109607-		loc := env.RegexpSearch("main.go", "Sqr()")
109608-		completions := env.Completion(loc)
109609-		if len(completions.Items) == 0 {
109610-			t.Fatalf("no completion items")
109611-		}
109612-		env.AcceptCompletion(loc, completions.Items[0])
109613-		env.Await(env.DoneWithChange())
109614-		got := env.BufferText("main.go")
109615-		want := "package main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"math\"\r\n)\r\n\r\nfunc main() {\r\n\tfmt.Println(\"a\")\r\n\tmath.Sqrt(${1:})\r\n}\r\n"
109616-		if diff := cmp.Diff(want, got); diff != "" {
109617-			t.Errorf("unimported completion (-want +got):\n%s", diff)
109618-		}
109619-	})
109620-}
109621-
109622-func TestPackageMemberCompletionAfterSyntaxError(t *testing.T) {
109623-	// This test documents the current broken behavior due to golang/go#58833.
109624-	const src = `
109625--- go.mod --
109626-module mod.com
109627-
109628-go 1.14
109629-
109630--- main.go --
109631-package main
109632-
109633-import "math"
109634-
109635-func main() {
109636-	math.Sqrt(,0)
109637-	math.Ldex
109638-}
109639-`
109640-	Run(t, src, func(t *testing.T, env *Env) {
109641-		env.OpenFile("main.go")
109642-		env.Await(env.DoneWithOpen())
109643-		loc := env.RegexpSearch("main.go", "Ldex()")
109644-		completions := env.Completion(loc)
109645-		if len(completions.Items) == 0 {
109646-			t.Fatalf("no completion items")
109647-		}
109648-		env.AcceptCompletion(loc, completions.Items[0])
109649-		env.Await(env.DoneWithChange())
109650-		got := env.BufferText("main.go")
109651-		// The completion of math.Ldex after the syntax error on the
109652-		// previous line is not "math.Ldexp" but "math.Ldexmath.Abs".
109653-		// (In VSCode, "Abs" wrongly appears in the completion menu.)
109654-		// This is a consequence of poor error recovery in the parser
109655-		// causing "math.Ldex" to become a BadExpr.
109656-		want := "package main\n\nimport \"math\"\n\nfunc main() {\n\tmath.Sqrt(,0)\n\tmath.Ldexmath.Abs(${1:})\n}\n"
109657-		if diff := cmp.Diff(want, got); diff != "" {
109658-			t.Errorf("unimported completion (-want +got):\n%s", diff)
109659-		}
109660-	})
109661-}
109662-
109663-func TestDefinition(t *testing.T) {
109664-	testenv.NeedsGo1Point(t, 17) // in go1.16, The FieldList in func x is not empty
109665-	files := `
109666--- go.mod --
109667-module mod.com
109668-
109669-go 1.18
109670--- a_test.go --
109671-package foo
109672-`
109673-	tests := []struct {
109674-		line string   // the sole line in the buffer after the package statement
109675-		pat  string   // the pattern to search for
109676-		want []string // expected completions
109677-	}{
109678-		{"func T", "T", []string{"TestXxx(t *testing.T)", "TestMain(m *testing.M)"}},
109679-		{"func T()", "T", []string{"TestMain", "Test"}},
109680-		{"func TestM", "TestM", []string{"TestMain(m *testing.M)", "TestM(t *testing.T)"}},
109681-		{"func TestM()", "TestM", []string{"TestMain"}},
109682-		{"func TestMi", "TestMi", []string{"TestMi(t *testing.T)"}},
109683-		{"func TestMi()", "TestMi", nil},
109684-		{"func TestG", "TestG", []string{"TestG(t *testing.T)"}},
109685-		{"func TestG(", "TestG", nil},
109686-		{"func Ben", "B", []string{"BenchmarkXxx(b *testing.B)"}},
109687-		{"func Ben(", "Ben", []string{"Benchmark"}},
109688-		{"func BenchmarkFoo", "BenchmarkFoo", []string{"BenchmarkFoo(b *testing.B)"}},
109689-		{"func BenchmarkFoo(", "BenchmarkFoo", nil},
109690-		{"func Fuz", "F", []string{"FuzzXxx(f *testing.F)"}},
109691-		{"func Fuz(", "Fuz", []string{"Fuzz"}},
109692-		{"func Testx", "Testx", nil},
109693-		{"func TestMe(t *testing.T)", "TestMe", nil},
109694-		{"func Te(t *testing.T)", "Te", []string{"TestMain", "Test"}},
109695-	}
109696-	fname := "a_test.go"
109697-	Run(t, files, func(t *testing.T, env *Env) {
109698-		env.OpenFile(fname)
109699-		env.Await(env.DoneWithOpen())
109700-		for _, test := range tests {
109701-			env.SetBufferContent(fname, "package foo\n"+test.line)
109702-			loc := env.RegexpSearch(fname, test.pat)
109703-			loc.Range.Start.Character += uint32(protocol.UTF16Len([]byte(test.pat)))
109704-			completions := env.Completion(loc)
109705-			if diff := compareCompletionLabels(test.want, completions.Items); diff != "" {
109706-				t.Error(diff)
109707-			}
109708-		}
109709-	})
109710-}
109711-
109712-// Test that completing a definition replaces source text when applied, golang/go#56852.
109713-// Note: With go <= 1.16 the completions does not add parameters and fails these tests.
109714-func TestDefinitionReplaceRange(t *testing.T) {
109715-	testenv.NeedsGo1Point(t, 17)
109716-
109717-	const mod = `
109718--- go.mod --
109719-module mod.com
109720-
109721-go 1.17
109722-`
109723-
109724-	tests := []struct {
109725-		name          string
109726-		before, after string
109727-	}{
109728-		{
109729-			name: "func TestMa",
109730-			before: `
109731-package foo_test
109732-
109733-func TestMa
109734-`,
109735-			after: `
109736-package foo_test
109737-
109738-func TestMain(m *testing.M)
109739-`,
109740-		},
109741-		{
109742-			name: "func TestSome",
109743-			before: `
109744-package foo_test
109745-
109746-func TestSome
109747-`,
109748-			after: `
109749-package foo_test
109750-
109751-func TestSome(t *testing.T)
109752-`,
109753-		},
109754-		{
109755-			name: "func Bench",
109756-			before: `
109757-package foo_test
109758-
109759-func Bench
109760-`,
109761-			// Note: Snippet with escaped }.
109762-			after: `
109763-package foo_test
109764-
109765-func Benchmark${1:Xxx}(b *testing.B) {
109766-	$0
109767-\}
109768-`,
109769-		},
109770-	}
109771-
109772-	Run(t, mod, func(t *testing.T, env *Env) {
109773-		env.CreateBuffer("foo_test.go", "")
109774-
109775-		for _, tst := range tests {
109776-			tst.before = strings.Trim(tst.before, "\n")
109777-			tst.after = strings.Trim(tst.after, "\n")
109778-			env.SetBufferContent("foo_test.go", tst.before)
109779-
109780-			loc := env.RegexpSearch("foo_test.go", tst.name)
109781-			loc.Range.Start.Character = uint32(protocol.UTF16Len([]byte(tst.name)))
109782-			completions := env.Completion(loc)
109783-			if len(completions.Items) == 0 {
109784-				t.Fatalf("no completion items")
109785-			}
109786-
109787-			env.AcceptCompletion(loc, completions.Items[0])
109788-			env.Await(env.DoneWithChange())
109789-			if buf := env.BufferText("foo_test.go"); buf != tst.after {
109790-				t.Errorf("%s:incorrect completion: got %q, want %q", tst.name, buf, tst.after)
109791-			}
109792-		}
109793-	})
109794-}
109795-
109796-func TestGoWorkCompletion(t *testing.T) {
109797-	const files = `
109798--- go.work --
109799-go 1.18
109800-
109801-use ./a
109802-use ./a/ba
109803-use ./a/b/
109804-use ./dir/foo
109805-use ./dir/foobar/
109806--- a/go.mod --
109807--- go.mod --
109808--- a/bar/go.mod --
109809--- a/b/c/d/e/f/go.mod --
109810--- dir/bar --
109811--- dir/foobar/go.mod --
109812-`
109813-
109814-	Run(t, files, func(t *testing.T, env *Env) {
109815-		env.OpenFile("go.work")
109816-
109817-		tests := []struct {
109818-			re   string
109819-			want []string
109820-		}{
109821-			{`use ()\.`, []string{".", "./a", "./a/bar", "./dir/foobar"}},
109822-			{`use \.()`, []string{"", "/a", "/a/bar", "/dir/foobar"}},
109823-			{`use \./()`, []string{"a", "a/bar", "dir/foobar"}},
109824-			{`use ./a()`, []string{"", "/b/c/d/e/f", "/bar"}},
109825-			{`use ./a/b()`, []string{"/c/d/e/f", "ar"}},
109826-			{`use ./a/b/()`, []string{`c/d/e/f`}},
109827-			{`use ./a/ba()`, []string{"r"}},
109828-			{`use ./dir/foo()`, []string{"bar"}},
109829-			{`use ./dir/foobar/()`, []string{}},
109830-		}
109831-		for _, tt := range tests {
109832-			completions := env.Completion(env.RegexpSearch("go.work", tt.re))
109833-			diff := compareCompletionLabels(tt.want, completions.Items)
109834-			if diff != "" {
109835-				t.Errorf("%s: %s", tt.re, diff)
109836-			}
109837-		}
109838-	})
109839-}
109840diff -urN a/gopls/internal/regtest/completion/postfix_snippet_test.go b/gopls/internal/regtest/completion/postfix_snippet_test.go
109841--- a/gopls/internal/regtest/completion/postfix_snippet_test.go	2000-01-01 00:00:00.000000000 -0000
109842+++ b/gopls/internal/regtest/completion/postfix_snippet_test.go	1970-01-01 00:00:00.000000000 +0000
109843@@ -1,464 +0,0 @@
109844-// Copyright 2021 The Go Authors. All rights reserved.
109845-// Use of this source code is governed by a BSD-style
109846-// license that can be found in the LICENSE file.
109847-
109848-package completion
109849-
109850-import (
109851-	"strings"
109852-	"testing"
109853-
109854-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
109855-)
109856-
109857-func TestPostfixSnippetCompletion(t *testing.T) {
109858-	const mod = `
109859--- go.mod --
109860-module mod.com
109861-
109862-go 1.12
109863-`
109864-
109865-	cases := []struct {
109866-		name          string
109867-		before, after string
109868-	}{
109869-		{
109870-			name: "sort",
109871-			before: `
109872-package foo
109873-
109874-func _() {
109875-	var foo []int
109876-	foo.sort
109877-}
109878-`,
109879-			after: `
109880-package foo
109881-
109882-import "sort"
109883-
109884-func _() {
109885-	var foo []int
109886-	sort.Slice(foo, func(i, j int) bool {
109887-	$0
109888-})
109889-}
109890-`,
109891-		},
109892-		{
109893-			name: "sort_renamed_sort_package",
109894-			before: `
109895-package foo
109896-
109897-import blahsort "sort"
109898-
109899-var j int
109900-
109901-func _() {
109902-	var foo []int
109903-	foo.sort
109904-}
109905-`,
109906-			after: `
109907-package foo
109908-
109909-import blahsort "sort"
109910-
109911-var j int
109912-
109913-func _() {
109914-	var foo []int
109915-	blahsort.Slice(foo, func(i, j2 int) bool {
109916-	$0
109917-})
109918-}
109919-`,
109920-		},
109921-		{
109922-			name: "last",
109923-			before: `
109924-package foo
109925-
109926-func _() {
109927-	var s struct { i []int }
109928-	s.i.last
109929-}
109930-`,
109931-			after: `
109932-package foo
109933-
109934-func _() {
109935-	var s struct { i []int }
109936-	s.i[len(s.i)-1]
109937-}
109938-`,
109939-		},
109940-		{
109941-			name: "reverse",
109942-			before: `
109943-package foo
109944-
109945-func _() {
109946-	var foo []int
109947-	foo.reverse
109948-}
109949-`,
109950-			after: `
109951-package foo
109952-
109953-func _() {
109954-	var foo []int
109955-	for i, j := 0, len(foo)-1; i < j; i, j = i+1, j-1 {
109956-	foo[i], foo[j] = foo[j], foo[i]
109957-}
109958-
109959-}
109960-`,
109961-		},
109962-		{
109963-			name: "slice_range",
109964-			before: `
109965-package foo
109966-
109967-func _() {
109968-	type myThing struct{}
109969-	var foo []myThing
109970-	foo.range
109971-}
109972-`,
109973-			after: `
109974-package foo
109975-
109976-func _() {
109977-	type myThing struct{}
109978-	var foo []myThing
109979-	for i, mt := range foo {
109980-	$0
109981-}
109982-}
109983-`,
109984-		},
109985-		{
109986-			name: "append_stmt",
109987-			before: `
109988-package foo
109989-
109990-func _() {
109991-	var foo []int
109992-	foo.append
109993-}
109994-`,
109995-			after: `
109996-package foo
109997-
109998-func _() {
109999-	var foo []int
110000-	foo = append(foo, $0)
110001-}
110002-`,
110003-		},
110004-		{
110005-			name: "append_expr",
110006-			before: `
110007-package foo
110008-
110009-func _() {
110010-	var foo []int
110011-	var _ []int = foo.append
110012-}
110013-`,
110014-			after: `
110015-package foo
110016-
110017-func _() {
110018-	var foo []int
110019-	var _ []int = append(foo, $0)
110020-}
110021-`,
110022-		},
110023-		{
110024-			name: "slice_copy",
110025-			before: `
110026-package foo
110027-
110028-func _() {
110029-	var foo []int
110030-	foo.copy
110031-}
110032-`,
110033-			after: `
110034-package foo
110035-
110036-func _() {
110037-	var foo []int
110038-	fooCopy := make([]int, len(foo))
110039-copy(fooCopy, foo)
110040-
110041-}
110042-`,
110043-		},
110044-		{
110045-			name: "map_range",
110046-			before: `
110047-package foo
110048-
110049-func _() {
110050-	var foo map[string]int
110051-	foo.range
110052-}
110053-`,
110054-			after: `
110055-package foo
110056-
110057-func _() {
110058-	var foo map[string]int
110059-	for k, v := range foo {
110060-	$0
110061-}
110062-}
110063-`,
110064-		},
110065-		{
110066-			name: "map_clear",
110067-			before: `
110068-package foo
110069-
110070-func _() {
110071-	var foo map[string]int
110072-	foo.clear
110073-}
110074-`,
110075-			after: `
110076-package foo
110077-
110078-func _() {
110079-	var foo map[string]int
110080-	for k := range foo {
110081-	delete(foo, k)
110082-}
110083-
110084-}
110085-`,
110086-		},
110087-		{
110088-			name: "map_keys",
110089-			before: `
110090-package foo
110091-
110092-func _() {
110093-	var foo map[string]int
110094-	foo.keys
110095-}
110096-`,
110097-			after: `
110098-package foo
110099-
110100-func _() {
110101-	var foo map[string]int
110102-	keys := make([]string, 0, len(foo))
110103-for k := range foo {
110104-	keys = append(keys, k)
110105-}
110106-
110107-}
110108-`,
110109-		},
110110-		{
110111-			name: "channel_range",
110112-			before: `
110113-package foo
110114-
110115-func _() {
110116-	foo := make(chan int)
110117-	foo.range
110118-}
110119-`,
110120-			after: `
110121-package foo
110122-
110123-func _() {
110124-	foo := make(chan int)
110125-	for e := range foo {
110126-	$0
110127-}
110128-}
110129-`,
110130-		},
110131-		{
110132-			name: "var",
110133-			before: `
110134-package foo
110135-
110136-func foo() (int, error) { return 0, nil }
110137-
110138-func _() {
110139-	foo().var
110140-}
110141-`,
110142-			after: `
110143-package foo
110144-
110145-func foo() (int, error) { return 0, nil }
110146-
110147-func _() {
110148-	i, err := foo()
110149-}
110150-`,
110151-		},
110152-		{
110153-			name: "var_single_value",
110154-			before: `
110155-package foo
110156-
110157-func foo() error { return nil }
110158-
110159-func _() {
110160-	foo().var
110161-}
110162-`,
110163-			after: `
110164-package foo
110165-
110166-func foo() error { return nil }
110167-
110168-func _() {
110169-	err := foo()
110170-}
110171-`,
110172-		},
110173-		{
110174-			name: "var_same_type",
110175-			before: `
110176-package foo
110177-
110178-func foo() (int, int) { return 0, 0 }
110179-
110180-func _() {
110181-	foo().var
110182-}
110183-`,
110184-			after: `
110185-package foo
110186-
110187-func foo() (int, int) { return 0, 0 }
110188-
110189-func _() {
110190-	i, i2 := foo()
110191-}
110192-`,
110193-		},
110194-		{
110195-			name: "print_scalar",
110196-			before: `
110197-package foo
110198-
110199-func _() {
110200-	var foo int
110201-	foo.print
110202-}
110203-`,
110204-			after: `
110205-package foo
110206-
110207-import "fmt"
110208-
110209-func _() {
110210-	var foo int
110211-	fmt.Printf("foo: %v\n", foo)
110212-}
110213-`,
110214-		},
110215-		{
110216-			name: "print_multi",
110217-			before: `
110218-package foo
110219-
110220-func foo() (int, error) { return 0, nil }
110221-
110222-func _() {
110223-	foo().print
110224-}
110225-`,
110226-			after: `
110227-package foo
110228-
110229-import "fmt"
110230-
110231-func foo() (int, error) { return 0, nil }
110232-
110233-func _() {
110234-	fmt.Println(foo())
110235-}
110236-`,
110237-		},
110238-		{
110239-			name: "string split",
110240-			before: `
110241-package foo
110242-
110243-func foo() []string {
110244-	x := "test"
110245-	return x.split
110246-}`,
110247-			after: `
110248-package foo
110249-
110250-import "strings"
110251-
110252-func foo() []string {
110253-	x := "test"
110254-	return strings.Split(x, "$0")
110255-}`,
110256-		},
110257-		{
110258-			name: "string slice join",
110259-			before: `
110260-package foo
110261-
110262-func foo() string {
110263-	x := []string{"a", "test"}
110264-	return x.join
110265-}`,
110266-			after: `
110267-package foo
110268-
110269-import "strings"
110270-
110271-func foo() string {
110272-	x := []string{"a", "test"}
110273-	return strings.Join(x, "$0")
110274-}`,
110275-		},
110276-	}
110277-
110278-	r := WithOptions(
110279-		Settings{
110280-			"experimentalPostfixCompletions": true,
110281-		},
110282-	)
110283-	r.Run(t, mod, func(t *testing.T, env *Env) {
110284-		env.CreateBuffer("foo.go", "")
110285-
110286-		for _, c := range cases {
110287-			t.Run(c.name, func(t *testing.T) {
110288-				c.before = strings.Trim(c.before, "\n")
110289-				c.after = strings.Trim(c.after, "\n")
110290-
110291-				env.SetBufferContent("foo.go", c.before)
110292-
110293-				loc := env.RegexpSearch("foo.go", "\n}")
110294-				completions := env.Completion(loc)
110295-				if len(completions.Items) != 1 {
110296-					t.Fatalf("expected one completion, got %v", completions.Items)
110297-				}
110298-
110299-				env.AcceptCompletion(loc, completions.Items[0])
110300-
110301-				if buf := env.BufferText("foo.go"); buf != c.after {
110302-					t.Errorf("\nGOT:\n%s\nEXPECTED:\n%s", buf, c.after)
110303-				}
110304-			})
110305-		}
110306-	})
110307-}
110308diff -urN a/gopls/internal/regtest/debug/debug_test.go b/gopls/internal/regtest/debug/debug_test.go
110309--- a/gopls/internal/regtest/debug/debug_test.go	2000-01-01 00:00:00.000000000 -0000
110310+++ b/gopls/internal/regtest/debug/debug_test.go	1970-01-01 00:00:00.000000000 +0000
110311@@ -1,30 +0,0 @@
110312-// Copyright 2022 The Go Authors. All rights reserved.
110313-// Use of this source code is governed by a BSD-style
110314-// license that can be found in the LICENSE file.
110315-
110316-package debug
110317-
110318-import (
110319-	"testing"
110320-
110321-	"golang.org/x/tools/gopls/internal/hooks"
110322-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
110323-	"golang.org/x/tools/internal/bug"
110324-)
110325-
110326-func TestMain(m *testing.M) {
110327-	Main(m, hooks.Options)
110328-}
110329-
110330-func TestBugNotification(t *testing.T) {
110331-	// Verify that a properly configured session gets notified of a bug on the
110332-	// server.
110333-	WithOptions(
110334-		Modes(Default), // must be in-process to receive the bug report below
110335-		Settings{"showBugReports": true},
110336-	).Run(t, "", func(t *testing.T, env *Env) {
110337-		const desc = "got a bug"
110338-		bug.Report(desc, nil)
110339-		env.Await(ShownMessage(desc))
110340-	})
110341-}
110342diff -urN a/gopls/internal/regtest/diagnostics/analysis_test.go b/gopls/internal/regtest/diagnostics/analysis_test.go
110343--- a/gopls/internal/regtest/diagnostics/analysis_test.go	2000-01-01 00:00:00.000000000 -0000
110344+++ b/gopls/internal/regtest/diagnostics/analysis_test.go	1970-01-01 00:00:00.000000000 +0000
110345@@ -1,49 +0,0 @@
110346-// Copyright 2022 The Go Authors. All rights reserved.
110347-// Use of this source code is governed by a BSD-style
110348-// license that can be found in the LICENSE file.
110349-
110350-package diagnostics
110351-
110352-import (
110353-	"testing"
110354-
110355-	"golang.org/x/tools/gopls/internal/lsp/protocol"
110356-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
110357-)
110358-
110359-// Test for the timeformat analyzer, following golang/vscode-go#2406.
110360-//
110361-// This test checks that applying the suggested fix from the analyzer resolves
110362-// the diagnostic warning.
110363-func TestTimeFormatAnalyzer(t *testing.T) {
110364-	const files = `
110365--- go.mod --
110366-module mod.com
110367-
110368-go 1.18
110369--- main.go --
110370-package main
110371-
110372-import (
110373-	"fmt"
110374-	"time"
110375-)
110376-
110377-func main() {
110378-	now := time.Now()
110379-	fmt.Println(now.Format("2006-02-01"))
110380-}`
110381-
110382-	Run(t, files, func(t *testing.T, env *Env) {
110383-		env.OpenFile("main.go")
110384-
110385-		var d protocol.PublishDiagnosticsParams
110386-		env.AfterChange(
110387-			Diagnostics(env.AtRegexp("main.go", "2006-02-01")),
110388-			ReadDiagnostics("main.go", &d),
110389-		)
110390-
110391-		env.ApplyQuickFixes("main.go", d.Diagnostics)
110392-		env.AfterChange(NoDiagnostics(ForFile("main.go")))
110393-	})
110394-}
110395diff -urN a/gopls/internal/regtest/diagnostics/builtin_test.go b/gopls/internal/regtest/diagnostics/builtin_test.go
110396--- a/gopls/internal/regtest/diagnostics/builtin_test.go	2000-01-01 00:00:00.000000000 -0000
110397+++ b/gopls/internal/regtest/diagnostics/builtin_test.go	1970-01-01 00:00:00.000000000 +0000
110398@@ -1,35 +0,0 @@
110399-// Copyright 2021 The Go Authors. All rights reserved.
110400-// Use of this source code is governed by a BSD-style
110401-// license that can be found in the LICENSE file.
110402-
110403-package diagnostics
110404-
110405-import (
110406-	"strings"
110407-	"testing"
110408-
110409-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
110410-)
110411-
110412-func TestIssue44866(t *testing.T) {
110413-	src := `
110414--- go.mod --
110415-module mod.com
110416-
110417-go 1.12
110418--- a.go --
110419-package a
110420-
110421-const (
110422-	c = iota
110423-)
110424-`
110425-	Run(t, src, func(t *testing.T, env *Env) {
110426-		env.OpenFile("a.go")
110427-		loc := env.GoToDefinition(env.RegexpSearch("a.go", "iota"))
110428-		if !strings.HasSuffix(string(loc.URI), "builtin.go") {
110429-			t.Fatalf("jumped to %q, want builtin.go", loc.URI)
110430-		}
110431-		env.AfterChange(NoDiagnostics(ForFile("builtin.go")))
110432-	})
110433-}
110434diff -urN a/gopls/internal/regtest/diagnostics/diagnostics_test.go b/gopls/internal/regtest/diagnostics/diagnostics_test.go
110435--- a/gopls/internal/regtest/diagnostics/diagnostics_test.go	2000-01-01 00:00:00.000000000 -0000
110436+++ b/gopls/internal/regtest/diagnostics/diagnostics_test.go	1970-01-01 00:00:00.000000000 +0000
110437@@ -1,2048 +0,0 @@
110438-// Copyright 2020 The Go Authors. All rights reserved.
110439-// Use of this source code is governed by a BSD-style
110440-// license that can be found in the LICENSE file.
110441-
110442-package diagnostics
110443-
110444-import (
110445-	"context"
110446-	"fmt"
110447-	"os/exec"
110448-	"testing"
110449-
110450-	"golang.org/x/tools/gopls/internal/hooks"
110451-	"golang.org/x/tools/gopls/internal/lsp"
110452-	"golang.org/x/tools/gopls/internal/lsp/fake"
110453-	"golang.org/x/tools/gopls/internal/lsp/protocol"
110454-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
110455-	"golang.org/x/tools/internal/bug"
110456-	"golang.org/x/tools/internal/testenv"
110457-)
110458-
110459-func TestMain(m *testing.M) {
110460-	bug.PanicOnBugs = true
110461-	Main(m, hooks.Options)
110462-}
110463-
110464-// Use mod.com for all go.mod files due to golang/go#35230.
110465-const exampleProgram = `
110466--- go.mod --
110467-module mod.com
110468-
110469-go 1.12
110470--- main.go --
110471-package main
110472-
110473-import "fmt"
110474-
110475-func main() {
110476-	fmt.Println("Hello World.")
110477-}`
110478-
110479-func TestDiagnosticErrorInEditedFile(t *testing.T) {
110480-	// This test is very basic: start with a clean Go program, make an error, and
110481-	// get a diagnostic for that error. However, it also demonstrates how to
110482-	// combine Expectations to await more complex state in the editor.
110483-	Run(t, exampleProgram, func(t *testing.T, env *Env) {
110484-		// Deleting the 'n' at the end of Println should generate a single error
110485-		// diagnostic.
110486-		env.OpenFile("main.go")
110487-		env.RegexpReplace("main.go", "Printl(n)", "")
110488-		env.AfterChange(
110489-			Diagnostics(env.AtRegexp("main.go", "Printl")),
110490-			// Assert that this test has sent no error logs to the client. This is not
110491-			// strictly necessary for testing this regression, but is included here
110492-			// as an example of using the NoErrorLogs() expectation. Feel free to
110493-			// delete.
110494-			NoErrorLogs(),
110495-		)
110496-	})
110497-}
110498-
110499-func TestMissingImportDiagsClearOnFirstFile(t *testing.T) {
110500-	const onlyMod = `
110501--- go.mod --
110502-module mod.com
110503-
110504-go 1.12
110505-`
110506-	Run(t, onlyMod, func(t *testing.T, env *Env) {
110507-		env.CreateBuffer("main.go", `package main
110508-
110509-func m() {
110510-	log.Println()
110511-}
110512-`)
110513-		env.AfterChange(Diagnostics(env.AtRegexp("main.go", "log")))
110514-		env.SaveBuffer("main.go")
110515-		env.AfterChange(NoDiagnostics(ForFile("main.go")))
110516-	})
110517-}
110518-
110519-func TestDiagnosticErrorInNewFile(t *testing.T) {
110520-	const brokenFile = `package main
110521-
110522-const Foo = "abc
110523-`
110524-	Run(t, brokenFile, func(t *testing.T, env *Env) {
110525-		env.CreateBuffer("broken.go", brokenFile)
110526-		env.AfterChange(Diagnostics(env.AtRegexp("broken.go", "\"abc")))
110527-	})
110528-}
110529-
110530-// badPackage contains a duplicate definition of the 'a' const.
110531-const badPackage = `
110532--- go.mod --
110533-module mod.com
110534-
110535-go 1.12
110536--- a.go --
110537-package consts
110538-
110539-const a = 1
110540--- b.go --
110541-package consts
110542-
110543-const a = 2
110544-`
110545-
110546-func TestDiagnosticClearingOnEdit(t *testing.T) {
110547-	Run(t, badPackage, func(t *testing.T, env *Env) {
110548-		env.OpenFile("b.go")
110549-		env.AfterChange(
110550-			Diagnostics(env.AtRegexp("a.go", "a = 1")),
110551-			Diagnostics(env.AtRegexp("b.go", "a = 2")),
110552-		)
110553-
110554-		// Fix the error by editing the const name in b.go to `b`.
110555-		env.RegexpReplace("b.go", "(a) = 2", "b")
110556-		env.AfterChange(
110557-			NoDiagnostics(ForFile("a.go")),
110558-			NoDiagnostics(ForFile("b.go")),
110559-		)
110560-	})
110561-}
110562-
110563-func TestDiagnosticClearingOnDelete_Issue37049(t *testing.T) {
110564-	Run(t, badPackage, func(t *testing.T, env *Env) {
110565-		env.OpenFile("a.go")
110566-		env.AfterChange(
110567-			Diagnostics(env.AtRegexp("a.go", "a = 1")),
110568-			Diagnostics(env.AtRegexp("b.go", "a = 2")),
110569-		)
110570-		env.RemoveWorkspaceFile("b.go")
110571-
110572-		env.AfterChange(
110573-			NoDiagnostics(ForFile("a.go")),
110574-			NoDiagnostics(ForFile("b.go")),
110575-		)
110576-	})
110577-}
110578-
110579-func TestDiagnosticClearingOnClose(t *testing.T) {
110580-	Run(t, badPackage, func(t *testing.T, env *Env) {
110581-		env.CreateBuffer("c.go", `package consts
110582-
110583-const a = 3`)
110584-		env.AfterChange(
110585-			Diagnostics(env.AtRegexp("a.go", "a = 1")),
110586-			Diagnostics(env.AtRegexp("b.go", "a = 2")),
110587-			Diagnostics(env.AtRegexp("c.go", "a = 3")),
110588-		)
110589-		env.CloseBuffer("c.go")
110590-		env.AfterChange(
110591-			Diagnostics(env.AtRegexp("a.go", "a = 1")),
110592-			Diagnostics(env.AtRegexp("b.go", "a = 2")),
110593-			NoDiagnostics(ForFile("c.go")),
110594-		)
110595-	})
110596-}
110597-
110598-// Tests golang/go#37978.
110599-func TestIssue37978(t *testing.T) {
110600-	Run(t, exampleProgram, func(t *testing.T, env *Env) {
110601-		// Create a new workspace-level directory and empty file.
110602-		env.CreateBuffer("c/c.go", "")
110603-
110604-		// Write the file contents with a missing import.
110605-		env.EditBuffer("c/c.go", protocol.TextEdit{
110606-			NewText: `package c
110607-
110608-const a = http.MethodGet
110609-`,
110610-		})
110611-		env.AfterChange(
110612-			Diagnostics(env.AtRegexp("c/c.go", "http.MethodGet")),
110613-		)
110614-		// Save file, which will organize imports, adding the expected import.
110615-		// Expect the diagnostics to clear.
110616-		env.SaveBuffer("c/c.go")
110617-		env.AfterChange(
110618-			NoDiagnostics(ForFile("c/c.go")),
110619-		)
110620-	})
110621-}
110622-
110623-// Tests golang/go#38878: good a.go, bad a_test.go, remove a_test.go but its errors remain
110624-// If the file is open in the editor, this is working as intended
110625-// If the file is not open in the editor, the errors go away
110626-const test38878 = `
110627--- go.mod --
110628-module foo
110629-
110630-go 1.12
110631--- a.go --
110632-package x
110633-
110634-// import "fmt"
110635-
110636-func f() {}
110637-
110638--- a_test.go --
110639-package x
110640-
110641-import "testing"
110642-
110643-func TestA(t *testing.T) {
110644-	f(3)
110645-}
110646-`
110647-
110648-// Tests golang/go#38878: deleting a test file should clear its errors, and
110649-// not break the workspace.
110650-func TestDeleteTestVariant(t *testing.T) {
110651-	Run(t, test38878, func(t *testing.T, env *Env) {
110652-		env.AfterChange(Diagnostics(env.AtRegexp("a_test.go", `f\((3)\)`)))
110653-		env.RemoveWorkspaceFile("a_test.go")
110654-		env.AfterChange(NoDiagnostics(ForFile("a_test.go")))
110655-
110656-		// Make sure the test variant has been removed from the workspace by
110657-		// triggering a metadata load.
110658-		env.OpenFile("a.go")
110659-		env.RegexpReplace("a.go", `// import`, "import")
110660-		env.AfterChange(Diagnostics(env.AtRegexp("a.go", `"fmt"`)))
110661-	})
110662-}
110663-
110664-// Tests golang/go#38878: deleting a test file on disk while it's still open
110665-// should not clear its errors.
110666-func TestDeleteTestVariant_DiskOnly(t *testing.T) {
110667-	Run(t, test38878, func(t *testing.T, env *Env) {
110668-		env.OpenFile("a_test.go")
110669-		env.AfterChange(Diagnostics(AtPosition("a_test.go", 5, 3)))
110670-		env.Sandbox.Workdir.RemoveFile(context.Background(), "a_test.go")
110671-		env.AfterChange(Diagnostics(AtPosition("a_test.go", 5, 3)))
110672-	})
110673-}
110674-
110675-// TestNoMod confirms that gopls continues to work when a user adds a go.mod
110676-// file to their workspace.
110677-func TestNoMod(t *testing.T) {
110678-	const noMod = `
110679--- main.go --
110680-package main
110681-
110682-import "mod.com/bob"
110683-
110684-func main() {
110685-	bob.Hello()
110686-}
110687--- bob/bob.go --
110688-package bob
110689-
110690-func Hello() {
110691-	var x int
110692-}
110693-`
110694-
110695-	t.Run("manual", func(t *testing.T) {
110696-		Run(t, noMod, func(t *testing.T, env *Env) {
110697-			env.OnceMet(
110698-				InitialWorkspaceLoad,
110699-				Diagnostics(env.AtRegexp("main.go", `"mod.com/bob"`)),
110700-			)
110701-			env.CreateBuffer("go.mod", `module mod.com
110702-
110703-	go 1.12
110704-`)
110705-			env.SaveBuffer("go.mod")
110706-			var d protocol.PublishDiagnosticsParams
110707-			env.AfterChange(
110708-				NoDiagnostics(ForFile("main.go")),
110709-				Diagnostics(env.AtRegexp("bob/bob.go", "x")),
110710-				ReadDiagnostics("bob/bob.go", &d),
110711-			)
110712-			if len(d.Diagnostics) != 1 {
110713-				t.Fatalf("expected 1 diagnostic, got %v", len(d.Diagnostics))
110714-			}
110715-		})
110716-	})
110717-	t.Run("initialized", func(t *testing.T) {
110718-		Run(t, noMod, func(t *testing.T, env *Env) {
110719-			env.OnceMet(
110720-				InitialWorkspaceLoad,
110721-				Diagnostics(env.AtRegexp("main.go", `"mod.com/bob"`)),
110722-			)
110723-			env.RunGoCommand("mod", "init", "mod.com")
110724-			env.AfterChange(
110725-				NoDiagnostics(ForFile("main.go")),
110726-				Diagnostics(env.AtRegexp("bob/bob.go", "x")),
110727-			)
110728-		})
110729-	})
110730-
110731-	t.Run("without workspace module", func(t *testing.T) {
110732-		WithOptions(
110733-			Modes(Default),
110734-		).Run(t, noMod, func(t *testing.T, env *Env) {
110735-			env.OnceMet(
110736-				InitialWorkspaceLoad,
110737-				Diagnostics(env.AtRegexp("main.go", `"mod.com/bob"`)),
110738-			)
110739-			if err := env.Sandbox.RunGoCommand(env.Ctx, "", "mod", []string{"init", "mod.com"}, true); err != nil {
110740-				t.Fatal(err)
110741-			}
110742-			env.AfterChange(
110743-				NoDiagnostics(ForFile("main.go")),
110744-				Diagnostics(env.AtRegexp("bob/bob.go", "x")),
110745-			)
110746-		})
110747-	})
110748-}
110749-
110750-// Tests golang/go#38267.
110751-func TestIssue38267(t *testing.T) {
110752-	const testPackage = `
110753--- go.mod --
110754-module mod.com
110755-
110756-go 1.12
110757--- lib.go --
110758-package lib
110759-
110760-func Hello(x string) {
110761-	_ = x
110762-}
110763--- lib_test.go --
110764-package lib
110765-
110766-import "testing"
110767-
110768-type testStruct struct{
110769-	name string
110770-}
110771-
110772-func TestHello(t *testing.T) {
110773-	testStructs := []*testStruct{
110774-		&testStruct{"hello"},
110775-		&testStruct{"goodbye"},
110776-	}
110777-	for y := range testStructs {
110778-		_ = y
110779-	}
110780-}
110781-`
110782-
110783-	Run(t, testPackage, func(t *testing.T, env *Env) {
110784-		env.OpenFile("lib_test.go")
110785-		env.AfterChange(
110786-			Diagnostics(AtPosition("lib_test.go", 10, 2)),
110787-			Diagnostics(AtPosition("lib_test.go", 11, 2)),
110788-		)
110789-		env.OpenFile("lib.go")
110790-		env.RegexpReplace("lib.go", "_ = x", "var y int")
110791-		env.AfterChange(
110792-			Diagnostics(env.AtRegexp("lib.go", "y int")),
110793-			NoDiagnostics(ForFile("lib_test.go")),
110794-		)
110795-	})
110796-}
110797-
110798-// Tests golang/go#38328.
110799-func TestPackageChange_Issue38328(t *testing.T) {
110800-	const packageChange = `
110801--- go.mod --
110802-module fake
110803-
110804-go 1.12
110805--- a.go --
110806-package foo
110807-func main() {}
110808-`
110809-	Run(t, packageChange, func(t *testing.T, env *Env) {
110810-		env.OpenFile("a.go")
110811-		env.RegexpReplace("a.go", "foo", "foox")
110812-		env.AfterChange(
110813-			NoDiagnostics(ForFile("a.go")),
110814-		)
110815-	})
110816-}
110817-
110818-const testPackageWithRequire = `
110819--- go.mod --
110820-module mod.com
110821-
110822-go 1.12
110823-
110824-require foo.test v1.2.3
110825--- go.sum --
110826-foo.test v1.2.3 h1:TMA+lyd1ck0TqjSFpNe4T6cf/K6TYkoHwOOcMBMjaEw=
110827-foo.test v1.2.3/go.mod h1:Ij3kyLIe5lzjycjh13NL8I2gX0quZuTdW0MnmlwGBL4=
110828--- print.go --
110829-package lib
110830-
110831-import (
110832-	"fmt"
110833-
110834-	"foo.test/bar"
110835-)
110836-
110837-func PrintAnswer() {
110838-	fmt.Printf("answer: %s", bar.Answer)
110839-}
110840-`
110841-
110842-const testPackageWithRequireProxy = `
110843--- [email protected]/go.mod --
110844-module foo.test
110845-
110846-go 1.12
110847--- [email protected]/bar/const.go --
110848-package bar
110849-
110850-const Answer = 42
110851-`
110852-
110853-func TestResolveDiagnosticWithDownload(t *testing.T) {
110854-	WithOptions(
110855-		ProxyFiles(testPackageWithRequireProxy),
110856-	).Run(t, testPackageWithRequire, func(t *testing.T, env *Env) {
110857-		env.OpenFile("print.go")
110858-		// Check that gopackages correctly loaded this dependency. We should get a
110859-		// diagnostic for the wrong formatting type.
110860-		env.AfterChange(
110861-			Diagnostics(
110862-				env.AtRegexp("print.go", "fmt.Printf"),
110863-				WithMessage("wrong type int"),
110864-			),
110865-		)
110866-	})
110867-}
110868-
110869-func TestMissingDependency(t *testing.T) {
110870-	Run(t, testPackageWithRequire, func(t *testing.T, env *Env) {
110871-		env.OpenFile("print.go")
110872-		env.Await(LogMatching(protocol.Error, "initial workspace load failed", 1, false))
110873-	})
110874-}
110875-
110876-// Tests golang/go#36951.
110877-func TestAdHocPackages_Issue36951(t *testing.T) {
110878-	const adHoc = `
110879--- b/b.go --
110880-package b
110881-
110882-func Hello() {
110883-	var x int
110884-}
110885-`
110886-	Run(t, adHoc, func(t *testing.T, env *Env) {
110887-		env.OpenFile("b/b.go")
110888-		env.AfterChange(
110889-			Diagnostics(env.AtRegexp("b/b.go", "x")),
110890-		)
110891-	})
110892-}
110893-
110894-// Tests golang/go#37984: GOPATH should be read from the go command.
110895-func TestNoGOPATH_Issue37984(t *testing.T) {
110896-	const files = `
110897--- main.go --
110898-package main
110899-
110900-func _() {
110901-	fmt.Println("Hello World")
110902-}
110903-`
110904-	WithOptions(
110905-		EnvVars{
110906-			"GOPATH":      "",
110907-			"GO111MODULE": "off",
110908-		},
110909-	).Run(t, files, func(t *testing.T, env *Env) {
110910-		env.OpenFile("main.go")
110911-		env.AfterChange(Diagnostics(env.AtRegexp("main.go", "fmt")))
110912-		env.SaveBuffer("main.go")
110913-		env.AfterChange(NoDiagnostics(ForFile("main.go")))
110914-	})
110915-}
110916-
110917-// Tests golang/go#38669.
110918-func TestEqualInEnv_Issue38669(t *testing.T) {
110919-	const files = `
110920--- go.mod --
110921-module mod.com
110922-
110923-go 1.12
110924--- main.go --
110925-package main
110926-
110927-var _ = x.X
110928--- x/x.go --
110929-package x
110930-
110931-var X = 0
110932-`
110933-	WithOptions(
110934-		EnvVars{"GOFLAGS": "-tags=foo"},
110935-	).Run(t, files, func(t *testing.T, env *Env) {
110936-		env.OpenFile("main.go")
110937-		env.OrganizeImports("main.go")
110938-		env.AfterChange(NoDiagnostics(ForFile("main.go")))
110939-	})
110940-}
110941-
110942-// Tests golang/go#38467.
110943-func TestNoSuggestedFixesForGeneratedFiles_Issue38467(t *testing.T) {
110944-	const generated = `
110945--- go.mod --
110946-module mod.com
110947-
110948-go 1.12
110949--- main.go --
110950-package main
110951-
110952-// Code generated by generator.go. DO NOT EDIT.
110953-
110954-func _() {
110955-	for i, _ := range []string{} {
110956-		_ = i
110957-	}
110958-}
110959-`
110960-	Run(t, generated, func(t *testing.T, env *Env) {
110961-		env.OpenFile("main.go")
110962-		var d protocol.PublishDiagnosticsParams
110963-		env.AfterChange(
110964-			Diagnostics(AtPosition("main.go", 5, 8)),
110965-			ReadDiagnostics("main.go", &d),
110966-		)
110967-		if fixes := env.GetQuickFixes("main.go", d.Diagnostics); len(fixes) != 0 {
110968-			t.Errorf("got quick fixes %v, wanted none", fixes)
110969-		}
110970-	})
110971-}
110972-
110973-// Expect a module/GOPATH error if there is an error in the file at startup.
110974-// Tests golang/go#37279.
110975-func TestBrokenWorkspace_OutsideModule(t *testing.T) {
110976-	const noModule = `
110977--- a.go --
110978-package foo
110979-
110980-import "mod.com/hello"
110981-
110982-func f() {
110983-	hello.Goodbye()
110984-}
110985-`
110986-	Run(t, noModule, func(t *testing.T, env *Env) {
110987-		env.OpenFile("a.go")
110988-		env.AfterChange(
110989-			// Expect the adHocPackagesWarning.
110990-			OutstandingWork(lsp.WorkspaceLoadFailure, "outside of a module"),
110991-		)
110992-		// Deleting the import dismisses the warning.
110993-		env.RegexpReplace("a.go", `import "mod.com/hello"`, "")
110994-		env.AfterChange(
110995-			NoOutstandingWork(),
110996-		)
110997-	})
110998-}
110999-
111000-func TestNonGoFolder(t *testing.T) {
111001-	const files = `
111002--- hello.txt --
111003-hi mom
111004-`
111005-	for _, go111module := range []string{"on", "off", ""} {
111006-		t.Run(fmt.Sprintf("GO111MODULE_%v", go111module), func(t *testing.T) {
111007-			WithOptions(
111008-				EnvVars{"GO111MODULE": go111module},
111009-			).Run(t, files, func(t *testing.T, env *Env) {
111010-				env.OnceMet(
111011-					InitialWorkspaceLoad,
111012-					NoOutstandingWork(),
111013-				)
111014-			})
111015-		})
111016-	}
111017-}
111018-
111019-// Tests the repro case from golang/go#38602. Diagnostics are now handled properly,
111020-// which blocks type checking.
111021-func TestConflictingMainPackageErrors(t *testing.T) {
111022-	const collision = `
111023--- x/x.go --
111024-package x
111025-
111026-import "x/hello"
111027-
111028-func Hello() {
111029-	hello.HiThere()
111030-}
111031--- x/main.go --
111032-package main
111033-
111034-func main() {
111035-	fmt.Println("")
111036-}
111037-`
111038-	WithOptions(
111039-		InGOPATH(),
111040-		EnvVars{"GO111MODULE": "off"},
111041-	).Run(t, collision, func(t *testing.T, env *Env) {
111042-		env.OpenFile("x/x.go")
111043-		env.AfterChange(
111044-			Diagnostics(env.AtRegexp("x/x.go", `^`), WithMessage("found packages main (main.go) and x (x.go)")),
111045-			Diagnostics(env.AtRegexp("x/main.go", `^`), WithMessage("found packages main (main.go) and x (x.go)")),
111046-		)
111047-
111048-		// We don't recover cleanly from the errors without good overlay support.
111049-		if testenv.Go1Point() >= 16 {
111050-			env.RegexpReplace("x/x.go", `package x`, `package main`)
111051-			env.AfterChange(
111052-				Diagnostics(env.AtRegexp("x/main.go", `fmt`)),
111053-			)
111054-		}
111055-	})
111056-}
111057-
111058-const ardanLabsProxy = `
111059--- github.com/ardanlabs/conf@v1.2.3/go.mod --
111060-module github.com/ardanlabs/conf
111061-
111062-go 1.12
111063--- github.com/ardanlabs/conf@v1.2.3/conf.go --
111064-package conf
111065-
111066-var ErrHelpWanted error
111067-`
111068-
111069-// Test for golang/go#38211.
111070-func Test_Issue38211(t *testing.T) {
111071-	const ardanLabs = `
111072--- go.mod --
111073-module mod.com
111074-
111075-go 1.14
111076--- main.go --
111077-package main
111078-
111079-import "github.com/ardanlabs/conf"
111080-
111081-func main() {
111082-	_ = conf.ErrHelpWanted
111083-}
111084-`
111085-	WithOptions(
111086-		ProxyFiles(ardanLabsProxy),
111087-	).Run(t, ardanLabs, func(t *testing.T, env *Env) {
111088-		// Expect a diagnostic with a suggested fix to add
111089-		// "github.com/ardanlabs/conf" to the go.mod file.
111090-		env.OpenFile("go.mod")
111091-		env.OpenFile("main.go")
111092-		var d protocol.PublishDiagnosticsParams
111093-		env.AfterChange(
111094-			Diagnostics(env.AtRegexp("main.go", `"github.com/ardanlabs/conf"`)),
111095-			ReadDiagnostics("main.go", &d),
111096-		)
111097-		env.ApplyQuickFixes("main.go", d.Diagnostics)
111098-		env.SaveBuffer("go.mod")
111099-		env.AfterChange(
111100-			NoDiagnostics(ForFile("main.go")),
111101-		)
111102-		// Comment out the line that depends on conf and expect a
111103-		// diagnostic and a fix to remove the import.
111104-		env.RegexpReplace("main.go", "_ = conf.ErrHelpWanted", "//_ = conf.ErrHelpWanted")
111105-		env.AfterChange(
111106-			Diagnostics(env.AtRegexp("main.go", `"github.com/ardanlabs/conf"`)),
111107-		)
111108-		env.SaveBuffer("main.go")
111109-		// Expect a diagnostic and fix to remove the dependency in the go.mod.
111110-		env.AfterChange(
111111-			NoDiagnostics(ForFile("main.go")),
111112-			Diagnostics(env.AtRegexp("go.mod", "require github.com/ardanlabs/conf"), WithMessage("not used in this module")),
111113-			ReadDiagnostics("go.mod", &d),
111114-		)
111115-		env.ApplyQuickFixes("go.mod", d.Diagnostics)
111116-		env.SaveBuffer("go.mod")
111117-		env.AfterChange(
111118-			NoDiagnostics(ForFile("go.mod")),
111119-		)
111120-		// Uncomment the lines and expect a new diagnostic for the import.
111121-		env.RegexpReplace("main.go", "//_ = conf.ErrHelpWanted", "_ = conf.ErrHelpWanted")
111122-		env.SaveBuffer("main.go")
111123-		env.AfterChange(
111124-			Diagnostics(env.AtRegexp("main.go", `"github.com/ardanlabs/conf"`)),
111125-		)
111126-	})
111127-}
111128-
111129-// Test for golang/go#38207.
111130-func TestNewModule_Issue38207(t *testing.T) {
111131-	const emptyFile = `
111132--- go.mod --
111133-module mod.com
111134-
111135-go 1.12
111136--- main.go --
111137-`
111138-	WithOptions(
111139-		ProxyFiles(ardanLabsProxy),
111140-	).Run(t, emptyFile, func(t *testing.T, env *Env) {
111141-		env.CreateBuffer("main.go", `package main
111142-
111143-import "github.com/ardanlabs/conf"
111144-
111145-func main() {
111146-	_ = conf.ErrHelpWanted
111147-}
111148-`)
111149-		env.SaveBuffer("main.go")
111150-		var d protocol.PublishDiagnosticsParams
111151-		env.AfterChange(
111152-			Diagnostics(env.AtRegexp("main.go", `"github.com/ardanlabs/conf"`), WithMessage("no required module")),
111153-			ReadDiagnostics("main.go", &d),
111154-		)
111155-		env.ApplyQuickFixes("main.go", d.Diagnostics)
111156-		env.AfterChange(
111157-			NoDiagnostics(ForFile("main.go")),
111158-		)
111159-	})
111160-}
111161-
111162-// Test for golang/go#36960.
111163-func TestNewFileBadImports_Issue36960(t *testing.T) {
111164-	const simplePackage = `
111165--- go.mod --
111166-module mod.com
111167-
111168-go 1.14
111169--- a/a1.go --
111170-package a
111171-
111172-import "fmt"
111173-
111174-func _() {
111175-	fmt.Println("hi")
111176-}
111177-`
111178-	Run(t, simplePackage, func(t *testing.T, env *Env) {
111179-		env.OpenFile("a/a1.go")
111180-		env.CreateBuffer("a/a2.go", ``)
111181-		env.SaveBufferWithoutActions("a/a2.go")
111182-		env.AfterChange(
111183-			NoDiagnostics(ForFile("a/a1.go")),
111184-		)
111185-		env.EditBuffer("a/a2.go", fake.NewEdit(0, 0, 0, 0, `package a`))
111186-		env.AfterChange(
111187-			NoDiagnostics(ForFile("a/a1.go")),
111188-		)
111189-	})
111190-}
111191-
111192-// This test tries to replicate the workflow of a user creating a new x test.
111193-// It also tests golang/go#39315.
111194-func TestManuallyCreatingXTest(t *testing.T) {
111195-	// Create a package that already has a test variant (in-package test).
111196-	const testVariant = `
111197--- go.mod --
111198-module mod.com
111199-
111200-go 1.15
111201--- hello/hello.go --
111202-package hello
111203-
111204-func Hello() {
111205-	var x int
111206-}
111207--- hello/hello_test.go --
111208-package hello
111209-
111210-import "testing"
111211-
111212-func TestHello(t *testing.T) {
111213-	var x int
111214-	Hello()
111215-}
111216-`
111217-	Run(t, testVariant, func(t *testing.T, env *Env) {
111218-		// Open the file, triggering the workspace load.
111219-		// There are errors in the code to ensure all is working as expected.
111220-		env.OpenFile("hello/hello.go")
111221-		env.AfterChange(
111222-			Diagnostics(env.AtRegexp("hello/hello.go", "x")),
111223-			Diagnostics(env.AtRegexp("hello/hello_test.go", "x")),
111224-		)
111225-
111226-		// Create an empty file with the intention of making it an x test.
111227-		// This resembles a typical flow in an editor like VS Code, in which
111228-		// a user would create an empty file and add content, saving
111229-		// intermittently.
111230-		// TODO(rstambler): There might be more edge cases here, as file
111231-		// content can be added incrementally.
111232-		env.CreateBuffer("hello/hello_x_test.go", ``)
111233-
111234-		// Save the empty file (no actions since formatting will fail).
111235-		env.SaveBufferWithoutActions("hello/hello_x_test.go")
111236-
111237-		// Add the content. The missing import is for the package under test.
111238-		env.EditBuffer("hello/hello_x_test.go", fake.NewEdit(0, 0, 0, 0, `package hello_test
111239-
111240-import (
111241-	"testing"
111242-)
111243-
111244-func TestHello(t *testing.T) {
111245-	hello.Hello()
111246-}
111247-`))
111248-		// Expect a diagnostic for the missing import. Save, which should
111249-		// trigger import organization. The diagnostic should clear.
111250-		env.AfterChange(
111251-			Diagnostics(env.AtRegexp("hello/hello_x_test.go", "hello.Hello")),
111252-		)
111253-		env.SaveBuffer("hello/hello_x_test.go")
111254-		env.AfterChange(
111255-			NoDiagnostics(ForFile("hello/hello_x_test.go")),
111256-		)
111257-	})
111258-}
111259-
111260-// Reproduce golang/go#40690.
111261-func TestCreateOnlyXTest(t *testing.T) {
111262-	const mod = `
111263--- go.mod --
111264-module mod.com
111265-
111266-go 1.12
111267--- foo/foo.go --
111268-package foo
111269--- foo/bar_test.go --
111270-`
111271-	Run(t, mod, func(t *testing.T, env *Env) {
111272-		env.OpenFile("foo/bar_test.go")
111273-		env.EditBuffer("foo/bar_test.go", fake.NewEdit(0, 0, 0, 0, "package foo"))
111274-		env.Await(env.DoneWithChange())
111275-		env.RegexpReplace("foo/bar_test.go", "package foo", `package foo_test
111276-
111277-import "testing"
111278-
111279-func TestX(t *testing.T) {
111280-	var x int
111281-}
111282-`)
111283-		env.AfterChange(
111284-			Diagnostics(env.AtRegexp("foo/bar_test.go", "x")),
111285-		)
111286-	})
111287-}
111288-
111289-func TestChangePackageName(t *testing.T) {
111290-	const mod = `
111291--- go.mod --
111292-module mod.com
111293-
111294-go 1.12
111295--- foo/foo.go --
111296-package foo
111297--- foo/bar_test.go --
111298-package foo_
111299-`
111300-	Run(t, mod, func(t *testing.T, env *Env) {
111301-		env.OpenFile("foo/bar_test.go")
111302-		env.AfterChange()
111303-		env.RegexpReplace("foo/bar_test.go", "package foo_", "package foo_test")
111304-		env.AfterChange(
111305-			NoDiagnostics(ForFile("foo/bar_test.go")),
111306-			NoDiagnostics(ForFile("foo/foo.go")),
111307-		)
111308-	})
111309-}
111310-
111311-func TestIgnoredFiles(t *testing.T) {
111312-	const ws = `
111313--- go.mod --
111314-module mod.com
111315-
111316-go 1.12
111317--- _foo/x.go --
111318-package x
111319-
111320-var _ = foo.Bar
111321-`
111322-	Run(t, ws, func(t *testing.T, env *Env) {
111323-		env.OpenFile("_foo/x.go")
111324-		env.AfterChange(
111325-			NoDiagnostics(ForFile("_foo/x.go")),
111326-		)
111327-	})
111328-}
111329-
111330-// Partially reproduces golang/go#38977, moving a file between packages.
111331-// It also gets hit by some go command bug fixed in 1.15, but we don't
111332-// care about that so much here.
111333-func TestDeletePackage(t *testing.T) {
111334-	const ws = `
111335--- go.mod --
111336-module mod.com
111337-
111338-go 1.15
111339--- a/a.go --
111340-package a
111341-
111342-const A = 1
111343-
111344--- b/b.go --
111345-package b
111346-
111347-import "mod.com/a"
111348-
111349-const B = a.A
111350-
111351--- c/c.go --
111352-package c
111353-
111354-import "mod.com/a"
111355-
111356-const C = a.A
111357-`
111358-	Run(t, ws, func(t *testing.T, env *Env) {
111359-		env.OpenFile("b/b.go")
111360-		env.Await(env.DoneWithOpen())
111361-		// Delete c/c.go, the only file in package c.
111362-		env.RemoveWorkspaceFile("c/c.go")
111363-
111364-		// We should still get diagnostics for files that exist.
111365-		env.RegexpReplace("b/b.go", `a.A`, "a.Nonexistant")
111366-		env.AfterChange(
111367-			Diagnostics(env.AtRegexp("b/b.go", `Nonexistant`)),
111368-		)
111369-	})
111370-}
111371-
111372-// This is a copy of the scenario_default/quickfix_empty_files.txt test from
111373-// govim. Reproduces golang/go#39646.
111374-func TestQuickFixEmptyFiles(t *testing.T) {
111375-	const mod = `
111376--- go.mod --
111377-module mod.com
111378-
111379-go 1.12
111380-`
111381-	// To fully recreate the govim tests, we create files by inserting
111382-	// a newline, adding to the file, and then deleting the newline.
111383-	// Wait for each event to process to avoid cancellations and force
111384-	// package loads.
111385-	writeGoVim := func(env *Env, name, content string) {
111386-		env.WriteWorkspaceFile(name, "")
111387-		env.Await(env.DoneWithChangeWatchedFiles())
111388-
111389-		env.CreateBuffer(name, "\n")
111390-		env.Await(env.DoneWithOpen())
111391-
111392-		env.EditBuffer(name, fake.NewEdit(1, 0, 1, 0, content))
111393-		env.Await(env.DoneWithChange())
111394-
111395-		env.EditBuffer(name, fake.NewEdit(0, 0, 1, 0, ""))
111396-		env.Await(env.DoneWithChange())
111397-	}
111398-
111399-	const p = `package p; func DoIt(s string) {};`
111400-	const main = `package main
111401-
111402-import "mod.com/p"
111403-
111404-func main() {
111405-	p.DoIt(5)
111406-}
111407-`
111408-	// A simple version of the test that reproduces most of the problems it
111409-	// exposes.
111410-	t.Run("short", func(t *testing.T) {
111411-		Run(t, mod, func(t *testing.T, env *Env) {
111412-			writeGoVim(env, "p/p.go", p)
111413-			writeGoVim(env, "main.go", main)
111414-			env.AfterChange(
111415-				Diagnostics(env.AtRegexp("main.go", "5")),
111416-			)
111417-		})
111418-	})
111419-
111420-	// A full version that replicates the whole flow of the test.
111421-	t.Run("full", func(t *testing.T) {
111422-		Run(t, mod, func(t *testing.T, env *Env) {
111423-			writeGoVim(env, "p/p.go", p)
111424-			writeGoVim(env, "main.go", main)
111425-			writeGoVim(env, "p/p_test.go", `package p
111426-
111427-import "testing"
111428-
111429-func TestDoIt(t *testing.T) {
111430-	DoIt(5)
111431-}
111432-`)
111433-			writeGoVim(env, "p/x_test.go", `package p_test
111434-
111435-import (
111436-	"testing"
111437-
111438-	"mod.com/p"
111439-)
111440-
111441-func TestDoIt(t *testing.T) {
111442-	p.DoIt(5)
111443-}
111444-`)
111445-			env.AfterChange(
111446-				Diagnostics(env.AtRegexp("main.go", "5")),
111447-				Diagnostics(env.AtRegexp("p/p_test.go", "5")),
111448-				Diagnostics(env.AtRegexp("p/x_test.go", "5")),
111449-			)
111450-			env.RegexpReplace("p/p.go", "s string", "i int")
111451-			env.AfterChange(
111452-				NoDiagnostics(ForFile("main.go")),
111453-				NoDiagnostics(ForFile("p/p_test.go")),
111454-				NoDiagnostics(ForFile("p/x_test.go")),
111455-			)
111456-		})
111457-	})
111458-}
111459-
111460-func TestSingleFile(t *testing.T) {
111461-	const mod = `
111462--- go.mod --
111463-module mod.com
111464-
111465-go 1.13
111466--- a/a.go --
111467-package a
111468-
111469-func _() {
111470-	var x int
111471-}
111472-`
111473-	WithOptions(
111474-		// Empty workspace folders.
111475-		WorkspaceFolders(),
111476-	).Run(t, mod, func(t *testing.T, env *Env) {
111477-		env.OpenFile("a/a.go")
111478-		env.AfterChange(
111479-			Diagnostics(env.AtRegexp("a/a.go", "x")),
111480-		)
111481-	})
111482-}
111483-
111484-// Reproduces the case described in
111485-// https://github.com/golang/go/issues/39296#issuecomment-652058883.
111486-func TestPkgm(t *testing.T) {
111487-	const basic = `
111488--- go.mod --
111489-module mod.com
111490-
111491-go 1.15
111492--- foo/foo.go --
111493-package foo
111494-
111495-import "fmt"
111496-
111497-func Foo() {
111498-	fmt.Println("")
111499-}
111500-`
111501-	Run(t, basic, func(t *testing.T, env *Env) {
111502-		env.WriteWorkspaceFile("foo/foo_test.go", `package main
111503-
111504-func main() {
111505-
111506-}`)
111507-		env.OpenFile("foo/foo_test.go")
111508-		env.RegexpReplace("foo/foo_test.go", `package main`, `package foo`)
111509-		env.AfterChange(NoDiagnostics(ForFile("foo/foo.go")))
111510-	})
111511-}
111512-
111513-func TestClosingBuffer(t *testing.T) {
111514-	const basic = `
111515--- go.mod --
111516-module mod.com
111517-
111518-go 1.14
111519--- main.go --
111520-package main
111521-
111522-func main() {}
111523-`
111524-	Run(t, basic, func(t *testing.T, env *Env) {
111525-		env.Editor.CreateBuffer(env.Ctx, "foo.go", `package main`)
111526-		env.AfterChange()
111527-		env.CloseBuffer("foo.go")
111528-		env.AfterChange(NoLogMatching(protocol.Info, "packages=0"))
111529-	})
111530-}
111531-
111532-// Reproduces golang/go#38424.
111533-func TestCutAndPaste(t *testing.T) {
111534-	const basic = `
111535--- go.mod --
111536-module mod.com
111537-
111538-go 1.14
111539--- main2.go --
111540-package main
111541-`
111542-	Run(t, basic, func(t *testing.T, env *Env) {
111543-		env.CreateBuffer("main.go", "")
111544-		env.Await(env.DoneWithOpen())
111545-
111546-		env.SaveBufferWithoutActions("main.go")
111547-		env.Await(env.DoneWithSave(), env.DoneWithChangeWatchedFiles())
111548-
111549-		env.EditBuffer("main.go", fake.NewEdit(0, 0, 0, 0, `package main
111550-
111551-func main() {
111552-}
111553-`))
111554-		env.Await(env.DoneWithChange())
111555-
111556-		env.SaveBuffer("main.go")
111557-		env.Await(env.DoneWithSave(), env.DoneWithChangeWatchedFiles())
111558-
111559-		env.EditBuffer("main.go", fake.NewEdit(0, 0, 4, 0, ""))
111560-		env.Await(env.DoneWithChange())
111561-
111562-		env.EditBuffer("main.go", fake.NewEdit(0, 0, 0, 0, `package main
111563-
111564-func main() {
111565-	var x int
111566-}
111567-`))
111568-		env.AfterChange(
111569-			Diagnostics(env.AtRegexp("main.go", "x")),
111570-		)
111571-	})
111572-}
111573-
111574-// Reproduces golang/go#39763.
111575-func TestInvalidPackageName(t *testing.T) {
111576-	const pkgDefault = `
111577--- go.mod --
111578-module mod.com
111579-
111580-go 1.12
111581--- main.go --
111582-package default
111583-
111584-func main() {}
111585-`
111586-	Run(t, pkgDefault, func(t *testing.T, env *Env) {
111587-		env.OpenFile("main.go")
111588-		env.AfterChange(
111589-			Diagnostics(
111590-				env.AtRegexp("main.go", "default"),
111591-				WithMessage("expected 'IDENT'"),
111592-			),
111593-		)
111594-	})
111595-}
111596-
111597-// This tests the functionality of the "limitWorkspaceScope"
111598-func TestLimitWorkspaceScope(t *testing.T) {
111599-	const mod = `
111600--- go.mod --
111601-module mod.com
111602-
111603-go 1.12
111604--- a/main.go --
111605-package main
111606-
111607-func main() {}
111608--- main.go --
111609-package main
111610-
111611-func main() {
111612-	var x int
111613-}
111614-`
111615-	WithOptions(
111616-		WorkspaceFolders("a"),
111617-	).Run(t, mod, func(t *testing.T, env *Env) {
111618-		env.OpenFile("a/main.go")
111619-		env.AfterChange(
111620-			Diagnostics(env.AtRegexp("main.go", "x")),
111621-		)
111622-	})
111623-	WithOptions(
111624-		WorkspaceFolders("a"),
111625-		Settings{"expandWorkspaceToModule": false},
111626-	).Run(t, mod, func(t *testing.T, env *Env) {
111627-		env.OpenFile("a/main.go")
111628-		env.AfterChange(
111629-			NoDiagnostics(ForFile("main.go")),
111630-		)
111631-	})
111632-}
111633-
111634-func TestSimplifyCompositeLitDiagnostic(t *testing.T) {
111635-	const files = `
111636--- go.mod --
111637-module mod.com
111638-
111639-go 1.12
111640--- main.go --
111641-package main
111642-
111643-import "fmt"
111644-
111645-type t struct {
111646-	msg string
111647-}
111648-
111649-func main() {
111650-	x := []t{t{"msg"}}
111651-	fmt.Println(x)
111652-}
111653-`
111654-
111655-	WithOptions(
111656-		Settings{"staticcheck": true},
111657-	).Run(t, files, func(t *testing.T, env *Env) {
111658-		env.OpenFile("main.go")
111659-		var d protocol.PublishDiagnosticsParams
111660-		env.AfterChange(
111661-			Diagnostics(env.AtRegexp("main.go", `t{"msg"}`), WithMessage("redundant type")),
111662-			ReadDiagnostics("main.go", &d),
111663-		)
111664-		if tags := d.Diagnostics[0].Tags; len(tags) == 0 || tags[0] != protocol.Unnecessary {
111665-			t.Errorf("wanted Unnecessary tag on diagnostic, got %v", tags)
111666-		}
111667-		env.ApplyQuickFixes("main.go", d.Diagnostics)
111668-		env.AfterChange(NoDiagnostics(ForFile("main.go")))
111669-	})
111670-}
111671-
111672-// Test some secondary diagnostics
111673-func TestSecondaryDiagnostics(t *testing.T) {
111674-	const dir = `
111675--- go.mod --
111676-module mod.com
111677-
111678-go 1.12
111679--- main.go --
111680-package main
111681-func main() {
111682-	panic("not here")
111683-}
111684--- other.go --
111685-package main
111686-func main() {}
111687-`
111688-	Run(t, dir, func(t *testing.T, env *Env) {
111689-		env.OpenFile("main.go")
111690-		env.OpenFile("other.go")
111691-		var mainDiags, otherDiags protocol.PublishDiagnosticsParams
111692-		env.AfterChange(
111693-			ReadDiagnostics("main.go", &mainDiags),
111694-			ReadDiagnostics("other.go", &otherDiags),
111695-		)
111696-		if len(mainDiags.Diagnostics) != 1 {
111697-			t.Fatalf("main.go, got %d diagnostics, expected 1", len(mainDiags.Diagnostics))
111698-		}
111699-		keep := mainDiags.Diagnostics[0]
111700-		if len(otherDiags.Diagnostics) != 1 {
111701-			t.Fatalf("other.go: got %d diagnostics, expected 1", len(otherDiags.Diagnostics))
111702-		}
111703-		if len(otherDiags.Diagnostics[0].RelatedInformation) != 1 {
111704-			t.Fatalf("got %d RelatedInformations, expected 1", len(otherDiags.Diagnostics[0].RelatedInformation))
111705-		}
111706-		// check that the RelatedInformation matches the error from main.go
111707-		c := otherDiags.Diagnostics[0].RelatedInformation[0]
111708-		if c.Location.Range != keep.Range {
111709-			t.Errorf("locations don't match. Got %v expected %v", c.Location.Range, keep.Range)
111710-		}
111711-	})
111712-}
111713-
111714-func TestNotifyOrphanedFiles(t *testing.T) {
111715-	const files = `
111716--- go.mod --
111717-module mod.com
111718-
111719-go 1.12
111720--- a/a.go --
111721-package a
111722-
111723-func main() {
111724-	var x int
111725-}
111726--- a/a_exclude.go --
111727-// +build exclude
111728-
111729-package a
111730-
111731-func _() {
111732-	var x int
111733-}
111734-`
111735-	Run(t, files, func(t *testing.T, env *Env) {
111736-		env.OpenFile("a/a.go")
111737-		env.AfterChange(
111738-			Diagnostics(env.AtRegexp("a/a.go", "x")),
111739-		)
111740-		env.OpenFile("a/a_exclude.go")
111741-		env.AfterChange(
111742-			Diagnostics(env.AtRegexp("a/a_exclude.go", "package (a)")),
111743-		)
111744-	})
111745-}
111746-
111747-func TestEnableAllExperiments(t *testing.T) {
111748-	// Before the oldest supported Go version, gopls sends a warning to upgrade
111749-	// Go, which fails the expectation below.
111750-	testenv.NeedsGo1Point(t, lsp.OldestSupportedGoVersion())
111751-
111752-	const mod = `
111753--- go.mod --
111754-module mod.com
111755-
111756-go 1.12
111757--- main.go --
111758-package main
111759-
111760-import "bytes"
111761-
111762-func b(c bytes.Buffer) {
111763-	_ = 1
111764-}
111765-`
111766-	WithOptions(
111767-		Settings{"allExperiments": true},
111768-	).Run(t, mod, func(t *testing.T, env *Env) {
111769-		// Confirm that the setting doesn't cause any warnings.
111770-		env.OnceMet(
111771-			InitialWorkspaceLoad,
111772-			NoShownMessage(""), // empty substring to match any message
111773-		)
111774-	})
111775-}
111776-
111777-func TestSwig(t *testing.T) {
111778-	// This is fixed in Go 1.17, but not earlier.
111779-	testenv.NeedsGo1Point(t, 17)
111780-
111781-	if _, err := exec.LookPath("swig"); err != nil {
111782-		t.Skip("skipping test: swig not available")
111783-	}
111784-	if _, err := exec.LookPath("g++"); err != nil {
111785-		t.Skip("skipping test: g++ not available")
111786-	}
111787-
111788-	const mod = `
111789--- go.mod --
111790-module mod.com
111791-
111792-go 1.12
111793--- pkg/simple/export_swig.go --
111794-package simple
111795-
111796-func ExportSimple(x, y int) int {
111797-	return Gcd(x, y)
111798-}
111799--- pkg/simple/simple.swigcxx --
111800-%module simple
111801-
111802-%inline %{
111803-extern int gcd(int x, int y)
111804-{
111805-  int g;
111806-  g = y;
111807-  while (x > 0) {
111808-    g = x;
111809-    x = y % x;
111810-    y = g;
111811-  }
111812-  return g;
111813-}
111814-%}
111815--- main.go --
111816-package a
111817-
111818-func main() {
111819-	var x int
111820-}
111821-`
111822-	Run(t, mod, func(t *testing.T, env *Env) {
111823-		env.OnceMet(
111824-			InitialWorkspaceLoad,
111825-			NoDiagnostics(WithMessage("illegal character U+0023 '#'")),
111826-		)
111827-	})
111828-}
111829-
111830-// When foo_test.go is opened, gopls will object to the borked package name.
111831-// This test asserts that when the package name is fixed, gopls will soon after
111832-// have no more complaints about it.
111833-// https://github.com/golang/go/issues/41061
111834-func TestRenamePackage(t *testing.T) {
111835-	const proxy = `
111836--- [email protected]/go.mod --
111837-module example.com
111838-
111839-go 1.12
111840--- [email protected]/blah/blah.go --
111841-package blah
111842-
111843-const Name = "Blah"
111844--- [email protected]/go.mod --
111845-module random.org
111846-
111847-go 1.12
111848--- [email protected]/blah/blah.go --
111849-package hello
111850-
111851-const Name = "Hello"
111852-`
111853-
111854-	const contents = `
111855--- go.mod --
111856-module mod.com
111857-
111858-go 1.12
111859--- main.go --
111860-package main
111861-
111862-import "example.com/blah"
111863-
111864-func main() {
111865-	blah.Hello()
111866-}
111867--- bob.go --
111868-package main
111869--- foo/foo.go --
111870-package foo
111871--- foo/foo_test.go --
111872-package foo_
111873-`
111874-
111875-	WithOptions(
111876-		ProxyFiles(proxy),
111877-		InGOPATH(),
111878-		EnvVars{"GO111MODULE": "off"},
111879-	).Run(t, contents, func(t *testing.T, env *Env) {
111880-		// Simulate typing character by character.
111881-		env.OpenFile("foo/foo_test.go")
111882-		env.Await(env.DoneWithOpen())
111883-		env.RegexpReplace("foo/foo_test.go", "_", "_t")
111884-		env.Await(env.DoneWithChange())
111885-		env.RegexpReplace("foo/foo_test.go", "_t", "_test")
111886-		env.AfterChange(
111887-			NoDiagnostics(ForFile("foo/foo_test.go")),
111888-			NoOutstandingWork(),
111889-		)
111890-	})
111891-}
111892-
111893-// TestProgressBarErrors confirms that critical workspace load errors are shown
111894-// and updated via progress reports.
111895-func TestProgressBarErrors(t *testing.T) {
111896-	const pkg = `
111897--- go.mod --
111898-modul mod.com
111899-
111900-go 1.12
111901--- main.go --
111902-package main
111903-`
111904-	Run(t, pkg, func(t *testing.T, env *Env) {
111905-		env.OpenFile("go.mod")
111906-		env.AfterChange(
111907-			OutstandingWork(lsp.WorkspaceLoadFailure, "unknown directive"),
111908-		)
111909-		env.EditBuffer("go.mod", fake.NewEdit(0, 0, 3, 0, `module mod.com
111910-
111911-go 1.hello
111912-`))
111913-		// As of golang/go#42529, go.mod changes do not reload the workspace until
111914-		// they are saved.
111915-		env.SaveBufferWithoutActions("go.mod")
111916-		env.AfterChange(
111917-			OutstandingWork(lsp.WorkspaceLoadFailure, "invalid go version"),
111918-		)
111919-		env.RegexpReplace("go.mod", "go 1.hello", "go 1.12")
111920-		env.SaveBufferWithoutActions("go.mod")
111921-		env.AfterChange(
111922-			NoOutstandingWork(),
111923-		)
111924-	})
111925-}
111926-
111927-func TestDeleteDirectory(t *testing.T) {
111928-	const mod = `
111929--- bob/bob.go --
111930-package bob
111931-
111932-func Hello() {
111933-	var x int
111934-}
111935--- go.mod --
111936-module mod.com
111937--- cmd/main.go --
111938-package main
111939-
111940-import "mod.com/bob"
111941-
111942-func main() {
111943-	bob.Hello()
111944-}
111945-`
111946-	Run(t, mod, func(t *testing.T, env *Env) {
111947-		env.OnceMet(
111948-			InitialWorkspaceLoad,
111949-			FileWatchMatching("bob"),
111950-		)
111951-		env.RemoveWorkspaceFile("bob")
111952-		env.AfterChange(
111953-			Diagnostics(env.AtRegexp("cmd/main.go", `"mod.com/bob"`)),
111954-			NoDiagnostics(ForFile("bob/bob.go")),
111955-			NoFileWatchMatching("bob"),
111956-		)
111957-	})
111958-}
111959-
111960-// Confirms that circular imports are tested and reported.
111961-func TestCircularImports(t *testing.T) {
111962-	const mod = `
111963--- go.mod --
111964-module mod.com
111965-
111966-go 1.12
111967--- self/self.go --
111968-package self
111969-
111970-import _ "mod.com/self"
111971-func Hello() {}
111972--- double/a/a.go --
111973-package a
111974-
111975-import _ "mod.com/double/b"
111976--- double/b/b.go --
111977-package b
111978-
111979-import _ "mod.com/double/a"
111980--- triple/a/a.go --
111981-package a
111982-
111983-import _ "mod.com/triple/b"
111984--- triple/b/b.go --
111985-package b
111986-
111987-import _ "mod.com/triple/c"
111988--- triple/c/c.go --
111989-package c
111990-
111991-import _ "mod.com/triple/a"
111992-`
111993-	Run(t, mod, func(t *testing.T, env *Env) {
111994-		env.OnceMet(
111995-			InitialWorkspaceLoad,
111996-			Diagnostics(env.AtRegexp("self/self.go", `_ "mod.com/self"`), WithMessage("import cycle not allowed")),
111997-			Diagnostics(env.AtRegexp("double/a/a.go", `_ "mod.com/double/b"`), WithMessage("import cycle not allowed")),
111998-			Diagnostics(env.AtRegexp("triple/a/a.go", `_ "mod.com/triple/b"`), WithMessage("import cycle not allowed")),
111999-		)
112000-	})
112001-}
112002-
112003-// Tests golang/go#46667: deleting a problematic import path should resolve
112004-// import cycle errors.
112005-func TestResolveImportCycle(t *testing.T) {
112006-	const mod = `
112007--- go.mod --
112008-module mod.test
112009-
112010-go 1.16
112011--- a/a.go --
112012-package a
112013-
112014-import "mod.test/b"
112015-
112016-const A = b.A
112017-const B = 2
112018--- b/b.go --
112019-package b
112020-
112021-import "mod.test/a"
112022-
112023-const A = 1
112024-const B = a.B
112025-	`
112026-	Run(t, mod, func(t *testing.T, env *Env) {
112027-		env.OpenFile("a/a.go")
112028-		env.OpenFile("b/b.go")
112029-		env.AfterChange(
112030-			// The Go command sometimes tells us about only one of the import cycle
112031-			// errors below. For robustness of this test, succeed if we get either.
112032-			//
112033-			// TODO(golang/go#52904): we should get *both* of these errors.
112034-			AnyOf(
112035-				Diagnostics(env.AtRegexp("a/a.go", `"mod.test/b"`), WithMessage("import cycle")),
112036-				Diagnostics(env.AtRegexp("b/b.go", `"mod.test/a"`), WithMessage("import cycle")),
112037-			),
112038-		)
112039-		env.RegexpReplace("b/b.go", `const B = a\.B`, "")
112040-		env.SaveBuffer("b/b.go")
112041-		env.AfterChange(
112042-			NoDiagnostics(ForFile("a/a.go")),
112043-			NoDiagnostics(ForFile("b/b.go")),
112044-		)
112045-	})
112046-}
112047-
112048-func TestBadImport(t *testing.T) {
112049-	const mod = `
112050--- go.mod --
112051-module mod.com
112052-
112053-go 1.12
112054--- main.go --
112055-package main
112056-
112057-import (
112058-	_ "nosuchpkg"
112059-)
112060-`
112061-	t.Run("module", func(t *testing.T) {
112062-		Run(t, mod, func(t *testing.T, env *Env) {
112063-			env.OnceMet(
112064-				InitialWorkspaceLoad,
112065-				Diagnostics(env.AtRegexp("main.go", `"nosuchpkg"`), WithMessage(`could not import nosuchpkg (no required module provides package "nosuchpkg"`)),
112066-			)
112067-		})
112068-	})
112069-	t.Run("GOPATH", func(t *testing.T) {
112070-		WithOptions(
112071-			InGOPATH(),
112072-			EnvVars{"GO111MODULE": "off"},
112073-			Modes(Default),
112074-		).Run(t, mod, func(t *testing.T, env *Env) {
112075-			env.OnceMet(
112076-				InitialWorkspaceLoad,
112077-				Diagnostics(env.AtRegexp("main.go", `"nosuchpkg"`), WithMessage(`cannot find package "nosuchpkg"`)),
112078-			)
112079-		})
112080-	})
112081-}
112082-
112083-func TestNestedModules(t *testing.T) {
112084-	const proxy = `
112085--- [email protected]/go.mod --
112086-module nested.com
112087-
112088-go 1.12
112089--- [email protected]/hello/hello.go --
112090-package hello
112091-
112092-func Hello() {}
112093-`
112094-
112095-	const nested = `
112096--- go.mod --
112097-module mod.com
112098-
112099-go 1.12
112100-
112101-require nested.com v1.0.0
112102--- go.sum --
112103-nested.com v1.0.0 h1:I6spLE4CgFqMdBPc+wTV2asDO2QJ3tU0YAT+jkLeN1I=
112104-nested.com v1.0.0/go.mod h1:ly53UzXQgVjSlV7wicdBB4p8BxfytuGT1Xcyv0ReJfI=
112105--- main.go --
112106-package main
112107-
112108-import "nested.com/hello"
112109-
112110-func main() {
112111-	hello.Hello()
112112-}
112113--- nested/go.mod --
112114-module nested.com
112115-
112116--- nested/hello/hello.go --
112117-package hello
112118-
112119-func Hello() {
112120-	helloHelper()
112121-}
112122--- nested/hello/hello_helper.go --
112123-package hello
112124-
112125-func helloHelper() {}
112126-`
112127-	WithOptions(
112128-		ProxyFiles(proxy),
112129-		Modes(Default),
112130-	).Run(t, nested, func(t *testing.T, env *Env) {
112131-		// Expect a diagnostic in a nested module.
112132-		env.OpenFile("nested/hello/hello.go")
112133-		env.AfterChange(
112134-			Diagnostics(env.AtRegexp("nested/hello/hello.go", "helloHelper")),
112135-			Diagnostics(env.AtRegexp("nested/hello/hello.go", "package hello"), WithMessage("nested module")),
112136-			OutstandingWork(lsp.WorkspaceLoadFailure, "nested module"),
112137-		)
112138-	})
112139-}
112140-
112141-func TestAdHocPackagesReloading(t *testing.T) {
112142-	const nomod = `
112143--- main.go --
112144-package main
112145-
112146-func main() {}
112147-`
112148-	Run(t, nomod, func(t *testing.T, env *Env) {
112149-		env.OpenFile("main.go")
112150-		env.RegexpReplace("main.go", "{}", "{ var x int; }") // simulate typing
112151-		env.AfterChange(NoLogMatching(protocol.Info, "packages=1"))
112152-	})
112153-}
112154-
112155-func TestBuildTagChange(t *testing.T) {
112156-	const files = `
112157--- go.mod --
112158-module mod.com
112159-
112160-go 1.12
112161--- foo.go --
112162-// decoy comment
112163-// +build hidden
112164-// decoy comment
112165-
112166-package foo
112167-var Foo = 1
112168--- bar.go --
112169-package foo
112170-var Bar = Foo
112171-`
112172-
112173-	Run(t, files, func(t *testing.T, env *Env) {
112174-		env.OpenFile("foo.go")
112175-		env.AfterChange(Diagnostics(env.AtRegexp("bar.go", `Foo`)))
112176-		env.RegexpReplace("foo.go", `\+build`, "")
112177-		env.AfterChange(NoDiagnostics(ForFile("bar.go")))
112178-	})
112179-
112180-}
112181-
112182-func TestIssue44736(t *testing.T) {
112183-	const files = `
112184-	-- go.mod --
112185-module blah.com
112186-
112187-go 1.16
112188--- main.go --
112189-package main
112190-
112191-import "fmt"
112192-
112193-func main() {
112194-	asdf
112195-	fmt.Printf("This is a test %v")
112196-	fdas
112197-}
112198--- other.go --
112199-package main
112200-
112201-`
112202-	Run(t, files, func(t *testing.T, env *Env) {
112203-		env.OpenFile("main.go")
112204-		env.OpenFile("other.go")
112205-		env.AfterChange(
112206-			Diagnostics(env.AtRegexp("main.go", "asdf")),
112207-			Diagnostics(env.AtRegexp("main.go", "fdas")),
112208-		)
112209-		env.SetBufferContent("other.go", "package main\n\nasdf")
112210-		// The new diagnostic in other.go should not suppress diagnostics in main.go.
112211-		env.AfterChange(
112212-			Diagnostics(env.AtRegexp("other.go", "asdf"), WithMessage("expected declaration")),
112213-			Diagnostics(env.AtRegexp("main.go", "asdf")),
112214-		)
112215-	})
112216-}
112217-
112218-func TestInitialization(t *testing.T) {
112219-	const files = `
112220--- go.mod --
112221-module mod.com
112222-
112223-go 1.16
112224--- main.go --
112225-package main
112226-`
112227-	Run(t, files, func(t *testing.T, env *Env) {
112228-		env.OpenFile("go.mod")
112229-		env.Await(env.DoneWithOpen())
112230-		env.RegexpReplace("go.mod", "module", "modul")
112231-		env.SaveBufferWithoutActions("go.mod")
112232-		env.AfterChange(
112233-			NoLogMatching(protocol.Error, "initial workspace load failed"),
112234-		)
112235-	})
112236-}
112237-
112238-// This test confirms that the view does not reinitialize when a go.mod file is
112239-// opened.
112240-func TestNoReinitialize(t *testing.T) {
112241-	const files = `
112242--- go.mod --
112243-module mod.com
112244-
112245-go 1.12
112246--- main.go --
112247-package main
112248-
112249-func main() {}
112250-`
112251-	Run(t, files, func(t *testing.T, env *Env) {
112252-		env.OpenFile("go.mod")
112253-		env.AfterChange(
112254-			LogMatching(protocol.Info, `.*query=\[builtin mod.com/...\].*`, 1, false),
112255-		)
112256-	})
112257-}
112258-
112259-func TestLangVersion(t *testing.T) {
112260-	testenv.NeedsGo1Point(t, 18) // Requires types.Config.GoVersion, new in 1.18.
112261-	const files = `
112262--- go.mod --
112263-module mod.com
112264-
112265-go 1.12
112266--- main.go --
112267-package main
112268-
112269-const C = 0b10
112270-`
112271-	Run(t, files, func(t *testing.T, env *Env) {
112272-		env.OnceMet(
112273-			InitialWorkspaceLoad,
112274-			Diagnostics(env.AtRegexp("main.go", `0b10`), WithMessage("go1.13 or later")),
112275-		)
112276-		env.WriteWorkspaceFile("go.mod", "module mod.com \n\ngo 1.13\n")
112277-		env.AfterChange(
112278-			NoDiagnostics(ForFile("main.go")),
112279-		)
112280-	})
112281-}
112282-
112283-func TestNoQuickFixForUndeclaredConstraint(t *testing.T) {
112284-	testenv.NeedsGo1Point(t, 18)
112285-	const files = `
112286--- go.mod --
112287-module mod.com
112288-
112289-go 1.18
112290--- main.go --
112291-package main
112292-
112293-func F[T C](_ T) {
112294-}
112295-`
112296-
112297-	Run(t, files, func(t *testing.T, env *Env) {
112298-		var d protocol.PublishDiagnosticsParams
112299-		env.OnceMet(
112300-			InitialWorkspaceLoad,
112301-			Diagnostics(env.AtRegexp("main.go", `C`)),
112302-			ReadDiagnostics("main.go", &d),
112303-		)
112304-		if fixes := env.GetQuickFixes("main.go", d.Diagnostics); len(fixes) != 0 {
112305-			t.Errorf("got quick fixes %v, wanted none", fixes)
112306-		}
112307-	})
112308-}
112309-
112310-func TestEditGoDirective(t *testing.T) {
112311-	testenv.NeedsGo1Point(t, 18)
112312-	const files = `
112313--- go.mod --
112314-module mod.com
112315-
112316-go 1.16
112317--- main.go --
112318-package main
112319-
112320-func F[T any](_ T) {
112321-}
112322-`
112323-	Run(t, files, func(_ *testing.T, env *Env) { // Create a new workspace-level directory and empty file.
112324-		var d protocol.PublishDiagnosticsParams
112325-		env.OnceMet(
112326-			InitialWorkspaceLoad,
112327-			Diagnostics(env.AtRegexp("main.go", `T any`), WithMessage("type parameter")),
112328-			ReadDiagnostics("main.go", &d),
112329-		)
112330-
112331-		env.ApplyQuickFixes("main.go", d.Diagnostics)
112332-		env.AfterChange(
112333-			NoDiagnostics(ForFile("main.go")),
112334-		)
112335-	})
112336-}
112337-
112338-func TestEditGoDirectiveWorkspace(t *testing.T) {
112339-	testenv.NeedsGo1Point(t, 18)
112340-	const files = `
112341--- go.mod --
112342-module mod.com
112343-
112344-go 1.16
112345--- go.work --
112346-go 1.18
112347-
112348-use .
112349--- main.go --
112350-package main
112351-
112352-func F[T any](_ T) {
112353-}
112354-`
112355-	Run(t, files, func(_ *testing.T, env *Env) { // Create a new workspace-level directory and empty file.
112356-		var d protocol.PublishDiagnosticsParams
112357-
112358-		// We should have a diagnostic because generics are not supported at 1.16.
112359-		env.OnceMet(
112360-			InitialWorkspaceLoad,
112361-			Diagnostics(env.AtRegexp("main.go", `T any`), WithMessage("type parameter")),
112362-			ReadDiagnostics("main.go", &d),
112363-		)
112364-
112365-		// This diagnostic should have a quick fix to edit the go version.
112366-		env.ApplyQuickFixes("main.go", d.Diagnostics)
112367-
112368-		// Once the edit is applied, the problematic diagnostics should be
112369-		// resolved.
112370-		env.AfterChange(
112371-			NoDiagnostics(ForFile("main.go")),
112372-		)
112373-	})
112374-}
112375-
112376-// This test demonstrates that analysis facts are correctly propagated
112377-// across packages.
112378-func TestInterpackageAnalysis(t *testing.T) {
112379-	const src = `
112380--- go.mod --
112381-module example.com
112382--- a/a.go --
112383-package a
112384-
112385-import "example.com/b"
112386-
112387-func _() {
112388-	new(b.B).Printf("%d", "s") // printf error
112389-}
112390-
112391--- b/b.go --
112392-package b
112393-
112394-import "example.com/c"
112395-
112396-type B struct{}
112397-
112398-func (B) Printf(format string, args ...interface{}) {
112399-	c.MyPrintf(format, args...)
112400-}
112401-
112402--- c/c.go --
112403-package c
112404-
112405-import "fmt"
112406-
112407-func MyPrintf(format string, args ...interface{}) {
112408-	fmt.Printf(format, args...)
112409-}
112410-`
112411-	Run(t, src, func(t *testing.T, env *Env) {
112412-		env.OpenFile("a/a.go")
112413-		env.AfterChange(
112414-			Diagnostics(
112415-				env.AtRegexp("a/a.go", "new.*Printf"),
112416-				WithMessage("format %d has arg \"s\" of wrong type string"),
112417-			),
112418-		)
112419-	})
112420-}
112421-
112422-// This test ensures that only Analyzers with RunDespiteErrors=true
112423-// are invoked on a package that would not compile, even if the errors
112424-// are distant and localized.
112425-func TestErrorsThatPreventAnalysis(t *testing.T) {
112426-	const src = `
112427--- go.mod --
112428-module example.com
112429--- a/a.go --
112430-package a
112431-
112432-import "fmt"
112433-import "sync"
112434-import _ "example.com/b"
112435-
112436-func _() {
112437-	// The copylocks analyzer (RunDespiteErrors, FactTypes={}) does run.
112438-	var mu sync.Mutex
112439-	mu2 := mu // copylocks error, reported
112440-	_ = &mu2
112441-
112442-	// The printf analyzer (!RunDespiteErrors, FactTypes!={}) does not run:
112443-	//  (c, printf) failed because of type error in c
112444-	//  (b, printf) and (a, printf) do not run because of failed prerequisites.
112445-	fmt.Printf("%d", "s") // printf error, unreported
112446-
112447-	// The bools analyzer (!RunDespiteErrors, FactTypes={}) does not run:
112448-	var cond bool
112449-	_ = cond != true && cond != true // bools error, unreported
112450-}
112451-
112452--- b/b.go --
112453-package b
112454-
112455-import _ "example.com/c"
112456-
112457--- c/c.go --
112458-package c
112459-
112460-var _ = 1 / "" // type error
112461-
112462-`
112463-	Run(t, src, func(t *testing.T, env *Env) {
112464-		var diags protocol.PublishDiagnosticsParams
112465-		env.OpenFile("a/a.go")
112466-		env.AfterChange(
112467-			Diagnostics(env.AtRegexp("a/a.go", "mu2 := (mu)"), WithMessage("assignment copies lock value")),
112468-			ReadDiagnostics("a/a.go", &diags))
112469-
112470-		// Assert that there were no other diagnostics.
112471-		// In particular:
112472-		// - "fmt.Printf" does not trigger a [printf] finding;
112473-		// - "cond != true" does not trigger a [bools] finding.
112474-		//
112475-		// We use this check in preference to NoDiagnosticAtRegexp
112476-		// as it is robust in case of minor mistakes in the position
112477-		// regexp, and because it reports unexpected diagnostics.
112478-		if got, want := len(diags.Diagnostics), 1; got != want {
112479-			t.Errorf("got %d diagnostics in a/a.go, want %d:", got, want)
112480-			for i, diag := range diags.Diagnostics {
112481-				t.Logf("Diagnostics[%d] = %+v", i, diag)
112482-			}
112483-		}
112484-	})
112485-}
112486diff -urN a/gopls/internal/regtest/diagnostics/golist_test.go b/gopls/internal/regtest/diagnostics/golist_test.go
112487--- a/gopls/internal/regtest/diagnostics/golist_test.go	2000-01-01 00:00:00.000000000 -0000
112488+++ b/gopls/internal/regtest/diagnostics/golist_test.go	1970-01-01 00:00:00.000000000 +0000
112489@@ -1,71 +0,0 @@
112490-// Copyright 2023 The Go Authors. All rights reserved.
112491-// Use of this source code is governed by a BSD-style
112492-// license that can be found in the LICENSE file.
112493-
112494-package diagnostics
112495-
112496-import (
112497-	"testing"
112498-
112499-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
112500-	"golang.org/x/tools/gopls/internal/lsp/source"
112501-	"golang.org/x/tools/internal/testenv"
112502-)
112503-
112504-func TestGoListErrors(t *testing.T) {
112505-	testenv.NeedsTool(t, "cgo")
112506-
112507-	const src = `
112508--- go.mod --
112509-module a.com
112510-
112511-go 1.18
112512--- a/a.go --
112513-package a
112514-
112515-import
112516--- c/c.go --
112517-package c
112518-
112519-/*
112520-int fortythree() { return 42; }
112521-*/
112522-import "C"
112523-
112524-func Foo() {
112525-	print(C.fortytwo())
112526-}
112527--- p/p.go --
112528-package p
112529-
112530-import "a.com/q"
112531-
112532-const P = q.Q + 1
112533--- q/q.go --
112534-package q
112535-
112536-import "a.com/p"
112537-
112538-const Q = p.P + 1
112539-`
112540-
112541-	Run(t, src, func(t *testing.T, env *Env) {
112542-		env.OnceMet(
112543-			InitialWorkspaceLoad,
112544-			Diagnostics(
112545-				env.AtRegexp("a/a.go", "import\n()"),
112546-				FromSource(string(source.ParseError)),
112547-			),
112548-			Diagnostics(
112549-				AtPosition("c/c.go", 0, 0),
112550-				FromSource(string(source.ListError)),
112551-				WithMessage("may indicate failure to perform cgo processing"),
112552-			),
112553-			Diagnostics(
112554-				env.AtRegexp("p/p.go", `"a.com/q"`),
112555-				FromSource(string(source.ListError)),
112556-				WithMessage("import cycle not allowed"),
112557-			),
112558-		)
112559-	})
112560-}
112561diff -urN a/gopls/internal/regtest/diagnostics/invalidation_test.go b/gopls/internal/regtest/diagnostics/invalidation_test.go
112562--- a/gopls/internal/regtest/diagnostics/invalidation_test.go	2000-01-01 00:00:00.000000000 -0000
112563+++ b/gopls/internal/regtest/diagnostics/invalidation_test.go	1970-01-01 00:00:00.000000000 +0000
112564@@ -1,111 +0,0 @@
112565-// Copyright 2022 The Go Authors. All rights reserved.
112566-// Use of this source code is governed by a BSD-style
112567-// license that can be found in the LICENSE file.
112568-
112569-package diagnostics
112570-
112571-import (
112572-	"fmt"
112573-	"testing"
112574-
112575-	"golang.org/x/tools/gopls/internal/lsp/protocol"
112576-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
112577-)
112578-
112579-// Test for golang/go#50267: diagnostics should be re-sent after a file is
112580-// opened.
112581-func TestDiagnosticsAreResentAfterCloseOrOpen(t *testing.T) {
112582-	const files = `
112583--- go.mod --
112584-module mod.com
112585-
112586-go 1.16
112587--- main.go --
112588-package main
112589-
112590-func _() {
112591-	x := 2
112592-}
112593-`
112594-	Run(t, files, func(_ *testing.T, env *Env) { // Create a new workspace-level directory and empty file.
112595-		env.OpenFile("main.go")
112596-		var afterOpen protocol.PublishDiagnosticsParams
112597-		env.AfterChange(
112598-			ReadDiagnostics("main.go", &afterOpen),
112599-		)
112600-		env.CloseBuffer("main.go")
112601-		var afterClose protocol.PublishDiagnosticsParams
112602-		env.AfterChange(
112603-			ReadDiagnostics("main.go", &afterClose),
112604-		)
112605-		if afterOpen.Version == afterClose.Version {
112606-			t.Errorf("publishDiagnostics: got the same version after closing (%d) as after opening", afterOpen.Version)
112607-		}
112608-		env.OpenFile("main.go")
112609-		var afterReopen protocol.PublishDiagnosticsParams
112610-		env.AfterChange(
112611-			ReadDiagnostics("main.go", &afterReopen),
112612-		)
112613-		if afterReopen.Version == afterClose.Version {
112614-			t.Errorf("pubslishDiagnostics: got the same version after reopening (%d) as after closing", afterClose.Version)
112615-		}
112616-	})
112617-}
112618-
112619-// Test for the "chattyDiagnostics" setting: we should get re-published
112620-// diagnostics after every file change, even if diagnostics did not change.
112621-func TestChattyDiagnostics(t *testing.T) {
112622-	const files = `
112623--- go.mod --
112624-module mod.com
112625-
112626-go 1.16
112627--- main.go --
112628-package main
112629-
112630-func _() {
112631-	x := 2
112632-}
112633-
112634-// Irrelevant comment #0
112635-`
112636-
112637-	WithOptions(
112638-		Settings{
112639-			"chattyDiagnostics": true,
112640-		},
112641-	).Run(t, files, func(_ *testing.T, env *Env) { // Create a new workspace-level directory and empty file.
112642-
112643-		env.OpenFile("main.go")
112644-		var d protocol.PublishDiagnosticsParams
112645-		env.AfterChange(
112646-			ReadDiagnostics("main.go", &d),
112647-		)
112648-
112649-		if len(d.Diagnostics) != 1 {
112650-			t.Fatalf("len(Diagnostics) = %d, want 1", len(d.Diagnostics))
112651-		}
112652-		msg := d.Diagnostics[0].Message
112653-
112654-		for i := 0; i < 5; i++ {
112655-			before := d.Version
112656-			env.RegexpReplace("main.go", "Irrelevant comment #.", fmt.Sprintf("Irrelevant comment #%d", i))
112657-			env.AfterChange(
112658-				ReadDiagnostics("main.go", &d),
112659-			)
112660-
112661-			if d.Version == before {
112662-				t.Errorf("after change, got version %d, want new version", d.Version)
112663-			}
112664-
112665-			// As a sanity check, make sure we have the same diagnostic.
112666-			if len(d.Diagnostics) != 1 {
112667-				t.Fatalf("len(Diagnostics) = %d, want 1", len(d.Diagnostics))
112668-			}
112669-			newMsg := d.Diagnostics[0].Message
112670-			if newMsg != msg {
112671-				t.Errorf("after change, got message %q, want %q", newMsg, msg)
112672-			}
112673-		}
112674-	})
112675-}
112676diff -urN a/gopls/internal/regtest/diagnostics/undeclared_test.go b/gopls/internal/regtest/diagnostics/undeclared_test.go
112677--- a/gopls/internal/regtest/diagnostics/undeclared_test.go	2000-01-01 00:00:00.000000000 -0000
112678+++ b/gopls/internal/regtest/diagnostics/undeclared_test.go	1970-01-01 00:00:00.000000000 +0000
112679@@ -1,73 +0,0 @@
112680-// Copyright 2021 The Go Authors. All rights reserved.
112681-// Use of this source code is governed by a BSD-style
112682-// license that can be found in the LICENSE file.
112683-
112684-package diagnostics
112685-
112686-import (
112687-	"testing"
112688-
112689-	"golang.org/x/tools/gopls/internal/lsp/protocol"
112690-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
112691-)
112692-
112693-func TestUndeclaredDiagnostics(t *testing.T) {
112694-	src := `
112695--- go.mod --
112696-module mod.com
112697-
112698-go 1.12
112699--- a/a.go --
112700-package a
112701-
112702-func _() int {
112703-	return x
112704-}
112705--- b/b.go --
112706-package b
112707-
112708-func _() int {
112709-	var y int
112710-	y = y
112711-	return y
112712-}
112713-`
112714-	Run(t, src, func(t *testing.T, env *Env) {
112715-		isUnnecessary := func(diag protocol.Diagnostic) bool {
112716-			for _, tag := range diag.Tags {
112717-				if tag == protocol.Unnecessary {
112718-					return true
112719-				}
112720-			}
112721-			return false
112722-		}
112723-
112724-		// 'x' is undeclared, but still necessary.
112725-		env.OpenFile("a/a.go")
112726-		var adiags protocol.PublishDiagnosticsParams
112727-		env.AfterChange(
112728-			Diagnostics(env.AtRegexp("a/a.go", "x")),
112729-			ReadDiagnostics("a/a.go", &adiags),
112730-		)
112731-		if got := len(adiags.Diagnostics); got != 1 {
112732-			t.Errorf("len(Diagnostics) = %d, want 1", got)
112733-		}
112734-		if diag := adiags.Diagnostics[0]; isUnnecessary(diag) {
112735-			t.Errorf("%v tagged unnecessary, want necessary", diag)
112736-		}
112737-
112738-		// 'y = y' is pointless, and should be detected as unnecessary.
112739-		env.OpenFile("b/b.go")
112740-		var bdiags protocol.PublishDiagnosticsParams
112741-		env.AfterChange(
112742-			Diagnostics(env.AtRegexp("b/b.go", "y = y")),
112743-			ReadDiagnostics("b/b.go", &bdiags),
112744-		)
112745-		if got := len(bdiags.Diagnostics); got != 1 {
112746-			t.Errorf("len(Diagnostics) = %d, want 1", got)
112747-		}
112748-		if diag := bdiags.Diagnostics[0]; !isUnnecessary(diag) {
112749-			t.Errorf("%v tagged necessary, want unnecessary", diag)
112750-		}
112751-	})
112752-}
112753diff -urN a/gopls/internal/regtest/inlayhints/inlayhints_test.go b/gopls/internal/regtest/inlayhints/inlayhints_test.go
112754--- a/gopls/internal/regtest/inlayhints/inlayhints_test.go	2000-01-01 00:00:00.000000000 -0000
112755+++ b/gopls/internal/regtest/inlayhints/inlayhints_test.go	1970-01-01 00:00:00.000000000 +0000
112756@@ -1,69 +0,0 @@
112757-// Copyright 2022 The Go Authors. All rights reserved.
112758-// Use of this source code is governed by a BSD-style
112759-// license that can be found in the LICENSE file.
112760-package inlayhint
112761-
112762-import (
112763-	"testing"
112764-
112765-	"golang.org/x/tools/gopls/internal/hooks"
112766-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
112767-	"golang.org/x/tools/gopls/internal/lsp/source"
112768-	"golang.org/x/tools/internal/bug"
112769-)
112770-
112771-func TestMain(m *testing.M) {
112772-	bug.PanicOnBugs = true
112773-	Main(m, hooks.Options)
112774-}
112775-
112776-func TestEnablingInlayHints(t *testing.T) {
112777-	const workspace = `
112778--- go.mod --
112779-module inlayHint.test
112780-go 1.12
112781--- lib.go --
112782-package lib
112783-type Number int
112784-const (
112785-	Zero Number = iota
112786-	One
112787-	Two
112788-)
112789-`
112790-	tests := []struct {
112791-		label         string
112792-		enabled       map[string]bool
112793-		wantInlayHint bool
112794-	}{
112795-		{
112796-			label:         "default",
112797-			wantInlayHint: false,
112798-		},
112799-		{
112800-			label:         "enable const",
112801-			enabled:       map[string]bool{source.ConstantValues: true},
112802-			wantInlayHint: true,
112803-		},
112804-		{
112805-			label:         "enable parameter names",
112806-			enabled:       map[string]bool{source.ParameterNames: true},
112807-			wantInlayHint: false,
112808-		},
112809-	}
112810-	for _, test := range tests {
112811-		t.Run(test.label, func(t *testing.T) {
112812-			WithOptions(
112813-				Settings{
112814-					"hints": test.enabled,
112815-				},
112816-			).Run(t, workspace, func(t *testing.T, env *Env) {
112817-				env.OpenFile("lib.go")
112818-				lens := env.InlayHints("lib.go")
112819-				if gotInlayHint := len(lens) > 0; gotInlayHint != test.wantInlayHint {
112820-					t.Errorf("got inlayHint: %t, want %t", gotInlayHint, test.wantInlayHint)
112821-				}
112822-			})
112823-		})
112824-	}
112825-}
112826diff -urN a/gopls/internal/regtest/marker/marker_test.go b/gopls/internal/regtest/marker/marker_test.go
112827--- a/gopls/internal/regtest/marker/marker_test.go	2000-01-01 00:00:00.000000000 -0000
112828+++ b/gopls/internal/regtest/marker/marker_test.go	1970-01-01 00:00:00.000000000 +0000
112829@@ -1,21 +0,0 @@
112830-// Copyright 2023 The Go Authors. All rights reserved.
112831-// Use of this source code is governed by a BSD-style
112832-// license that can be found in the LICENSE file.
112833-
112834-package marker
112835-
112836-import (
112837-	"testing"
112838-
112839-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
112840-)
112841-
112842-// Note: we use a separate package for the marker tests so that we can easily
112843-// compare their performance to the existing marker tests in ./internal/lsp.
112844-
112845-// TestMarkers runs the marker tests from the testdata directory.
112846-//
112847-// See RunMarkerTests for details on how marker tests work.
112848-func TestMarkers(t *testing.T) {
112849-	RunMarkerTests(t, "testdata")
112850-}
112851diff -urN a/gopls/internal/regtest/marker/testdata/definition/embed.txt b/gopls/internal/regtest/marker/testdata/definition/embed.txt
112852--- a/gopls/internal/regtest/marker/testdata/definition/embed.txt	2000-01-01 00:00:00.000000000 -0000
112853+++ b/gopls/internal/regtest/marker/testdata/definition/embed.txt	1970-01-01 00:00:00.000000000 +0000
112854@@ -1,254 +0,0 @@
112855-This test checks definition and hover operations over embedded fields and methods.
112856-
112857--- go.mod --
112858-module mod.com
112859-
112860-go 1.18
112861-
112862--- a/a.go --
112863-package a
112864-
112865-type A string //@loc(AString, "A")
112866-
112867-func (_ A) Hi() {} //@loc(AHi, "Hi")
112868-
112869-type S struct {
112870-	Field int //@loc(SField, "Field")
112871-	R         // embed a struct
112872-	H         // embed an interface
112873-}
112874-
112875-type R struct {
112876-	Field2 int //@loc(RField2, "Field2")
112877-}
112878-
112879-func (_ R) Hey() {} //@loc(RHey, "Hey")
112880-
112881-type H interface { //@loc(H, "H")
112882-	Goodbye() //@loc(HGoodbye, "Goodbye")
112883-}
112884-
112885-type I interface { //@loc(I, "I")
112886-	B() //@loc(IB, "B")
112887-	J
112888-}
112889-
112890-type J interface { //@loc(J, "J")
112891-	Hello() //@loc(JHello, "Hello")
112892-}
112893-
112894--- b/b.go --
112895-package b
112896-
112897-import "mod.com/a" //@loc(AImport, re"\".*\"")
112898-
112899-type embed struct {
112900-	F int //@loc(F, "F")
112901-}
112902-
112903-func (embed) M() //@loc(M, "M")
112904-
112905-type Embed struct {
112906-	embed
112907-	*a.A
112908-	a.I
112909-	a.S
112910-}
112911-
112912-func _() {
112913-	e := Embed{}
112914-	e.Hi()      //@def("Hi", AHi),hover("Hi", "Hi", AHi)
112915-	e.B()       //@def("B", IB),hover("B", "B", IB)
112916-	_ = e.Field     //@def("Field", SField),hover("Field", "Field", SField)
112917-	_ = e.Field2    //@def("Field2", RField2),hover("Field2", "Field2", RField2)
112918-	e.Hello()   //@def("Hello", JHello),hover("Hello", "Hello",JHello)
112919-	e.Hey()     //@def("Hey", RHey),hover("Hey", "Hey", RHey)
112920-	e.Goodbye() //@def("Goodbye", HGoodbye),hover("Goodbye", "Goodbye", HGoodbye)
112921-	e.M() //@def("M", M),hover("M", "M", M)
112922-	_ = e.F //@def("F", F),hover("F", "F", F)
112923-}
112924-
112925-type aAlias = a.A //@loc(aAlias, "aAlias")
112926-
112927-type S1 struct { //@loc(S1, "S1")
112928-	F1     int //@loc(S1F1, "F1")
112929-	S2         //@loc(S1S2, "S2"),def("S2", S2),hover("S2", "S2", S2)
112930-	a.A        //@def("A", AString),hover("A", "A", aA)
112931-	aAlias     //@def("a", aAlias),hover("a", "aAlias", aAlias)
112932-}
112933-
112934-type S2 struct { //@loc(S2, "S2")
112935-	F1   string //@loc(S2F1, "F1")
112936-	F2   int    //@loc(S2F2, "F2")
112937-	*a.A        //@def("A", AString),def("a",AImport)
112938-}
112939-
112940-type S3 struct {
112941-	F1 struct {
112942-		a.A //@def("A", AString)
112943-	}
112944-}
112945-
112946-func Bar() {
112947-	var x S1    //@def("S1", S1),hover("S1", "S1", S1)
112948-	_ = x.S2    //@def("S2", S1S2),hover("S2", "S2", S1S2)
112949-	_ = x.F1    //@def("F1", S1F1),hover("F1", "F1", S1F1)
112950-	_ = x.F2    //@def("F2", S2F2),hover("F2", "F2", S2F2)
112951-	_ = x.S2.F1 //@def("F1", S2F1),hover("F1", "F1", S2F1)
112952-}
112953-
112954--- b/c.go --
112955-package b
112956-
112957-var _ = S1{ //@def("S1", S1),hover("S1", "S1", S1)
112958-	F1: 99, //@def("F1", S1F1),hover("F1", "F1", S1F1)
112959-}
112960-
112961--- @AHi/hover.md --
112962-```go
112963-func (a.A).Hi()
112964-```
112965-
112966-[`(a.A).Hi` on pkg.go.dev](https://pkg.go.dev/mod.com/a#A.Hi)
112967--- @F/hover.md --
112968-```go
112969-field F int
112970-```
112971-
112972-@loc(F, "F")
112973-
112974-
112975-[`(b.Embed).F` on pkg.go.dev](https://pkg.go.dev/mod.com/b#Embed.F)
112976--- @HGoodbye/hover.md --
112977-```go
112978-func (a.H).Goodbye()
112979-```
112980-
112981-@loc(HGoodbye, "Goodbye")
112982-
112983-
112984-[`(a.H).Goodbye` on pkg.go.dev](https://pkg.go.dev/mod.com/a#H.Goodbye)
112985--- @IB/hover.md --
112986-```go
112987-func (a.I).B()
112988-```
112989-
112990-@loc(IB, "B")
112991-
112992-
112993-[`(a.I).B` on pkg.go.dev](https://pkg.go.dev/mod.com/a#I.B)
112994--- @JHello/hover.md --
112995-```go
112996-func (a.J).Hello()
112997-```
112998-
112999-@loc(JHello, "Hello")
113000-
113001-
113002-[`(a.J).Hello` on pkg.go.dev](https://pkg.go.dev/mod.com/a#J.Hello)
113003--- @M/hover.md --
113004-```go
113005-func (embed).M()
113006-```
113007-
113008-[`(b.Embed).M` on pkg.go.dev](https://pkg.go.dev/mod.com/b#Embed.M)
113009--- @RField2/hover.md --
113010-```go
113011-field Field2 int
113012-```
113013-
113014-@loc(RField2, "Field2")
113015-
113016-
113017-[`(a.R).Field2` on pkg.go.dev](https://pkg.go.dev/mod.com/a#R.Field2)
113018--- @RHey/hover.md --
113019-```go
113020-func (a.R).Hey()
113021-```
113022-
113023-[`(a.R).Hey` on pkg.go.dev](https://pkg.go.dev/mod.com/a#R.Hey)
113024--- @S1/hover.md --
113025-```go
113026-type S1 struct {
113027-	F1     int //@loc(S1F1, "F1")
113028-	S2         //@loc(S1S2, "S2"),def("S2", S2),hover("S2", "S2", S2)
113029-	a.A        //@def("A", AString),hover("A", "A", aA)
113030-	aAlias     //@def("a", aAlias),hover("a", "aAlias", aAlias)
113031-}
113032-```
113033-
113034-[`b.S1` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S1)
113035--- @S1F1/hover.md --
113036-```go
113037-field F1 int
113038-```
113039-
113040-@loc(S1F1, "F1")
113041-
113042-
113043-[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S1.F1)
113044--- @S1S2/hover.md --
113045-```go
113046-field S2 S2
113047-```
113048-
113049-@loc(S1S2, "S2"),def("S2", S2),hover("S2", "S2", S2)
113050-
113051-
113052-[`(b.S1).S2` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S1.S2)
113053--- @S2/hover.md --
113054-```go
113055-type S2 struct {
113056-	F1   string //@loc(S2F1, "F1")
113057-	F2   int    //@loc(S2F2, "F2")
113058-	*a.A        //@def("A", AString),def("a",AImport)
113059-}
113060-```
113061-
113062-[`b.S2` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S2)
113063--- @S2F1/hover.md --
113064-```go
113065-field F1 string
113066-```
113067-
113068-@loc(S2F1, "F1")
113069-
113070-
113071-[`(b.S2).F1` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S2.F1)
113072--- @S2F2/hover.md --
113073-```go
113074-field F2 int
113075-```
113076-
113077-@loc(S2F2, "F2")
113078-
113079-
113080-[`(b.S2).F2` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S2.F2)
113081--- @SField/hover.md --
113082-```go
113083-field Field int
113084-```
113085-
113086-@loc(SField, "Field")
113087-
113088-
113089-[`(a.S).Field` on pkg.go.dev](https://pkg.go.dev/mod.com/a#S.Field)
113090--- @aA/hover.md --
113091-```go
113092-type A string
113093-
113094-func (a.A).Hi()
113095-```
113096-
113097-@loc(AString, "A")
113098-
113099-
113100-[`a.A` on pkg.go.dev](https://pkg.go.dev/mod.com/a#A)
113101--- @aAlias/hover.md --
113102-```go
113103-type aAlias = a.A
113104-
113105-func (a.A).Hi()
113106-```
113107-
113108-@loc(aAlias, "aAlias")
113109diff -urN a/gopls/internal/regtest/marker/testdata/definition/import.txt b/gopls/internal/regtest/marker/testdata/definition/import.txt
113110--- a/gopls/internal/regtest/marker/testdata/definition/import.txt	2000-01-01 00:00:00.000000000 -0000
113111+++ b/gopls/internal/regtest/marker/testdata/definition/import.txt	1970-01-01 00:00:00.000000000 +0000
113112@@ -1,52 +0,0 @@
113113-This test checks definition and hover over imports.
113114--- go.mod --
113115-module mod.com
113116-
113117-go 1.18
113118--- foo/foo.go --
113119-package foo
113120-
113121-type Foo struct{}
113122-
113123-// DoFoo does foo.
113124-func DoFoo() {} //@loc(DoFoo, "DoFoo")
113125--- bar/bar.go --
113126-package bar
113127-
113128-import (
113129-	myFoo "mod.com/foo" //@loc(myFoo, "myFoo")
113130-)
113131-
113132-var _ *myFoo.Foo //@def("myFoo", myFoo),hover("myFoo", "myFoo", myFoo)
113133--- bar/dotimport.go --
113134-package bar
113135-
113136-import . "mod.com/foo"
113137-
113138-func _() {
113139-	// variable of type foo.Foo
113140-	var _ Foo //@hover("_", "_", FooVar)
113141-
113142-	DoFoo() //@hover("DoFoo", "DoFoo", DoFoo)
113143-}
113144--- @DoFoo/hover.md --
113145-```go
113146-func DoFoo()
113147-```
113148-
113149-DoFoo does foo.
113150-
113151-
113152-[`foo.DoFoo` on pkg.go.dev](https://pkg.go.dev/mod.com/foo#DoFoo)
113153--- @FooVar/hover.md --
113154-```go
113155-var _ Foo
113156-```
113157-
113158-variable of type foo.Foo
113159--- @myFoo/hover.md --
113160-```go
113161-package myFoo ("mod.com/foo")
113162-```
113163-
113164-[`myFoo` on pkg.go.dev](https://pkg.go.dev/mod.com/foo)
113165diff -urN a/gopls/internal/regtest/marker/testdata/definition/misc.txt b/gopls/internal/regtest/marker/testdata/definition/misc.txt
113166--- a/gopls/internal/regtest/marker/testdata/definition/misc.txt	2000-01-01 00:00:00.000000000 -0000
113167+++ b/gopls/internal/regtest/marker/testdata/definition/misc.txt	1970-01-01 00:00:00.000000000 +0000
113168@@ -1,230 +0,0 @@
113169-This test exercises miscellaneous definition and hover requests.
113170--- go.mod --
113171-module mod.com
113172-
113173-go 1.16
113174--- a.go --
113175-package a //@loc(aPackage, re"package (a)"),hover(aPackage, aPackage, aPackage)
113176-
113177-var (
113178-	// x is a variable.
113179-	x string //@loc(x, "x"),hover(x, x, hoverx)
113180-)
113181-
113182-// Constant block. When I hover on h, I should see this comment.
113183-const (
113184-	// When I hover on g, I should see this comment.
113185-	g = 1 //@hover("g", "g", hoverg)
113186-
113187-	h = 2 //@hover("h", "h", hoverh)
113188-)
113189-
113190-// z is a variable too.
113191-var z string //@loc(z, "z"),hover(z, z, hoverz)
113192-
113193-func AStuff() { //@loc(AStuff, "AStuff")
113194-	x := 5
113195-	Random2(x) //@def("dom2", Random2)
113196-	Random()   //@def("()", Random)
113197-}
113198-
113199-type H interface { //@loc(H, "H")
113200-	Goodbye()
113201-}
113202-
113203-type I interface { //@loc(I, "I")
113204-	B()
113205-	J
113206-}
113207-
113208-type J interface { //@loc(J, "J")
113209-	Hello()
113210-}
113211-
113212-func _() {
113213-	// 1st type declaration block
113214-	type (
113215-		a struct { //@hover("a", "a", hoverDeclBlocka)
113216-			x string
113217-		}
113218-	)
113219-
113220-	// 2nd type declaration block
113221-	type (
113222-		// b has a comment
113223-		b struct{} //@hover("b", "b", hoverDeclBlockb)
113224-	)
113225-
113226-	// 3rd type declaration block
113227-	type (
113228-		// c is a struct
113229-		c struct { //@hover("c", "c", hoverDeclBlockc)
113230-			f string
113231-		}
113232-
113233-		d string //@hover("d", "d", hoverDeclBlockd)
113234-	)
113235-
113236-	type (
113237-		e struct { //@hover("e", "e", hoverDeclBlocke)
113238-			f float64
113239-		} // e has a comment
113240-	)
113241-}
113242-
113243-var (
113244-	hh H //@hover("H", "H", hoverH)
113245-	ii I //@hover("I", "I", hoverI)
113246-	jj J //@hover("J", "J", hoverJ)
113247-)
113248--- a_test.go --
113249-package a
113250-
113251-import (
113252-	"testing"
113253-)
113254-
113255-func TestA(t *testing.T) { //@hover("TestA", "TestA", hoverTestA)
113256-}
113257--- random.go --
113258-package a
113259-
113260-func Random() int { //@loc(Random, "Random")
113261-	y := 6 + 7
113262-	return y
113263-}
113264-
113265-func Random2(y int) int { //@loc(Random2, "Random2"),loc(RandomParamY, "y")
113266-	return y //@def("y", RandomParamY),hover("y", "y", hovery)
113267-}
113268-
113269-type Pos struct {
113270-	x, y int //@loc(PosX, "x"),loc(PosY, "y")
113271-}
113272-
113273-// Typ has a comment. Its fields do not.
113274-type Typ struct{ field string } //@loc(TypField, "field")
113275-
113276-func _() {
113277-	x := &Typ{}
113278-	_ = x.field //@def("field", TypField),hover("field", "field", hoverfield)
113279-}
113280-
113281-func (p *Pos) Sum() int { //@loc(PosSum, "Sum")
113282-	return p.x + p.y //@hover("x", "x", hoverpx)
113283-}
113284-
113285-func _() {
113286-	var p Pos
113287-	_ = p.Sum() //@def("()", PosSum),hover("()", `Sum`, hoverSum)
113288-}
113289--- @aPackage/hover.md --
113290--- @hoverDeclBlocka/hover.md --
113291-```go
113292-type a struct {
113293-	x string
113294-}
113295-```
113296-
113297-1st type declaration block
113298--- @hoverDeclBlockb/hover.md --
113299-```go
113300-type b struct{}
113301-```
113302-
113303-b has a comment
113304--- @hoverDeclBlockc/hover.md --
113305-```go
113306-type c struct {
113307-	f string
113308-}
113309-```
113310-
113311-c is a struct
113312--- @hoverDeclBlockd/hover.md --
113313-```go
113314-type d string
113315-```
113316-
113317-3rd type declaration block
113318--- @hoverDeclBlocke/hover.md --
113319-```go
113320-type e struct {
113321-	f float64
113322-}
113323-```
113324-
113325-e has a comment
113326--- @hoverH/hover.md --
113327-```go
113328-type H interface {
113329-	Goodbye()
113330-}
113331-```
113332-
113333-[`a.H` on pkg.go.dev](https://pkg.go.dev/mod.com#H)
113334--- @hoverI/hover.md --
113335-```go
113336-type I interface {
113337-	B()
113338-	J
113339-}
113340-```
113341-
113342-[`a.I` on pkg.go.dev](https://pkg.go.dev/mod.com#I)
113343--- @hoverJ/hover.md --
113344-```go
113345-type J interface {
113346-	Hello()
113347-}
113348-```
113349-
113350-[`a.J` on pkg.go.dev](https://pkg.go.dev/mod.com#J)
113351--- @hoverSum/hover.md --
113352-```go
113353-func (*Pos).Sum() int
113354-```
113355-
113356-[`(a.Pos).Sum` on pkg.go.dev](https://pkg.go.dev/mod.com#Pos.Sum)
113357--- @hoverTestA/hover.md --
113358-```go
113359-func TestA(t *testing.T)
113360-```
113361--- @hoverfield/hover.md --
113362-```go
113363-field field string
113364-```
113365--- @hoverg/hover.md --
113366-```go
113367-const g untyped int = 1
113368-```
113369-
113370-When I hover on g, I should see this comment.
113371--- @hoverh/hover.md --
113372-```go
113373-const h untyped int = 2
113374-```
113375-
113376-Constant block. When I hover on h, I should see this comment.
113377--- @hoverpx/hover.md --
113378-```go
113379-field x int
113380-```
113381-
113382-@loc(PosX, "x"),loc(PosY, "y")
113383--- @hoverx/hover.md --
113384-```go
113385-var x string
113386-```
113387-
113388-x is a variable.
113389--- @hovery/hover.md --
113390-```go
113391-var y int
113392-```
113393--- @hoverz/hover.md --
113394-```go
113395-var z string
113396-```
113397-
113398-z is a variable too.
113399diff -urN a/gopls/internal/regtest/marker/testdata/hover/basiclit.txt b/gopls/internal/regtest/marker/testdata/hover/basiclit.txt
113400--- a/gopls/internal/regtest/marker/testdata/hover/basiclit.txt	2000-01-01 00:00:00.000000000 -0000
113401+++ b/gopls/internal/regtest/marker/testdata/hover/basiclit.txt	1970-01-01 00:00:00.000000000 +0000
113402@@ -1,60 +0,0 @@
113403-This test checks gopls behavior when hovering over basic literals.
113404--- basiclit.go --
113405-package basiclit
113406-
113407-func _() {
113408-	_ = 'a' //@hover("'a'", "'a'", latinA)
113409-	_ = 0x61 //@hover("0x61", "0x61", latinA)
113410-
113411-	_ = '\u2211' //@hover("'\\u2211'", "'\\u2211'", summation)
113412-	_ = 0x2211 //@hover("0x2211", "0x2211", summation)
113413-	_ = "foo \u2211 bar" //@hover("\\u2211", "\\u2211", summation)
113414-
113415-	_ = '\a' //@hover("'\\a'", "'\\a'", control)
113416-	_ = "foo \a bar" //@hover("\\a", "\\a", control)
113417-
113418-	_ = '\U0001F30A' //@hover("'\\U0001F30A'", "'\\U0001F30A'", waterWave)
113419-	_ = 0x0001F30A //@hover("0x0001F30A", "0x0001F30A", waterWave)
113420-	_ = "foo \U0001F30A bar" //@hover("\\U0001F30A", "\\U0001F30A", waterWave)
113421-
113422-	_ = '\x7E' //@hover("'\\x7E'", "'\\x7E'", tilde)
113423-	_ = "foo \x7E bar" //@hover("\\x7E", "\\x7E", tilde)
113424-	_ = "foo \a bar" //@hover("\\a", "\\a", control)
113425-
113426-	_ = '\173' //@hover("'\\173'", "'\\173'", leftCurly)
113427-	_ = "foo \173 bar" //@hover("\\173","\\173", leftCurly)
113428-	_ = "foo \173 bar \u2211 baz" //@hover("\\173","\\173", leftCurly)
113429-	_ = "foo \173 bar \u2211 baz" //@hover("\\u2211","\\u2211", summation)
113430-	_ = "foo\173bar\u2211baz" //@hover("\\173","\\173", leftCurly)
113431-	_ = "foo\173bar\u2211baz" //@hover("\\u2211","\\u2211", summation)
113432-
113433-	// search for runes in string only if there is an escaped sequence
113434-	_ = "hello" //@hover(`"hello"`, _, _)
113435-
113436-	// incorrect escaped rune sequences
113437-	_ = '\0' //@hover("'\\0'", _, _),diag(re`\\0()'`, re"illegal character")
113438-	_ = '\u22111' //@hover("'\\u22111'", _, _)
113439-	_ = '\U00110000' //@hover("'\\U00110000'", _, _)
113440-	_ = '\u12e45'//@hover("'\\u12e45'", _, _)
113441-	_ = '\xa' //@hover("'\\xa'", _, _)
113442-	_ = 'aa' //@hover("'aa'", _, _)
113443-
113444-	// other basic lits
113445-	_ = 1 //@hover("1", _, _)
113446-	_ = 1.2 //@hover("1.2", _, _)
113447-	_ = 1.2i //@hover("1.2i", _, _)
113448-	_ = 0123 //@hover("0123", _, _)
113449-	_ = 0x1234567890 //@hover("0x1234567890", _, _)
113450-)
113451--- @control/hover.md --
113452-U+0007, control
113453--- @latinA/hover.md --
113454-'a', U+0061, LATIN SMALL LETTER A
113455--- @leftCurly/hover.md --
113456-'{', U+007B, LEFT CURLY BRACKET
113457--- @summation/hover.md --
113458-'∑', U+2211, N-ARY SUMMATION
113459--- @tilde/hover.md --
113460-'~', U+007E, TILDE
113461--- @waterWave/hover.md --
113462-'��', U+1F30A, WATER WAVE
113463diff -urN a/gopls/internal/regtest/marker/testdata/hover/const.txt b/gopls/internal/regtest/marker/testdata/hover/const.txt
113464--- a/gopls/internal/regtest/marker/testdata/hover/const.txt	2000-01-01 00:00:00.000000000 -0000
113465+++ b/gopls/internal/regtest/marker/testdata/hover/const.txt	1970-01-01 00:00:00.000000000 +0000
113466@@ -1,18 +0,0 @@
113467-This test checks hovering over constants.
113468--- go.mod --
113469-module mod.com
113470-
113471-go 1.18
113472--- c.go --
113473-package c
113474-
113475-const X = 0 //@hover("X", "X", bX)
113476--- @bX/hover.md --
113477-```go
113478-const X untyped int = 0
113479-```
113480-
113481-@hover("X", "X", bX)
113482-
113483-
113484-[`c.X` on pkg.go.dev](https://pkg.go.dev/mod.com#X)
113485diff -urN a/gopls/internal/regtest/marker/testdata/hover/generics.txt b/gopls/internal/regtest/marker/testdata/hover/generics.txt
113486--- a/gopls/internal/regtest/marker/testdata/hover/generics.txt	2000-01-01 00:00:00.000000000 -0000
113487+++ b/gopls/internal/regtest/marker/testdata/hover/generics.txt	1970-01-01 00:00:00.000000000 +0000
113488@@ -1,77 +0,0 @@
113489-This file contains tests for hovering over generic Go code.
113490-
113491--- flags --
113492--min_go=go1.18
113493-
113494--- go.mod --
113495-// A go.mod is require for correct pkgsite links.
113496-// TODO(rfindley): don't link to ad-hoc or command-line-arguments packages!
113497-module mod.com
113498-
113499-go 1.18
113500-
113501--- generics.go --
113502-package generics
113503-
113504-type value[T any] struct { //hover("lue", "value", value),hover("T", "T", valueT)
113505-	val T   //@hover("T", "T", valuevalT)
113506-	Q   int //@hover("Q", "Q", valueQ)
113507-}
113508-
113509-type Value[T any] struct { //@hover("T", "T", ValueT)
113510-	val T   //@hover("T", "T", ValuevalT)
113511-	Q   int //@hover("Q", "Q", ValueQ)
113512-}
113513-
113514-// disabled - see issue #54822
113515-func F[P interface{ ~int | string }]() { // hover("P","P",Ptparam)
113516-	// disabled - see issue #54822
113517-	var _ P // hover("P","P",Pvar)
113518-}
113519-
113520--- inferred.go --
113521-package generics
113522-
113523-func app[S interface{ ~[]E }, E interface{}](s S, e E) S {
113524-	return append(s, e)
113525-}
113526-
113527-func _() {
113528-	_ = app[[]int]             //@hover("app", "app", appint)
113529-	_ = app[[]int, int]        //@hover("app", "app", appint)
113530-	// TODO(rfindley): eliminate this diagnostic.
113531-	_ = app[[]int]([]int{}, 0) //@hover("app", "app", appint),diag("[[]int]", re"unnecessary type arguments")
113532-	_ = app([]int{}, 0)        //@hover("app", "app", appint)
113533-}
113534-
113535--- @ValueQ/hover.md --
113536-```go
113537-field Q int
113538-```
113539-
113540-@hover("Q", "Q", ValueQ)
113541-
113542-
113543-[`(generics.Value).Q` on pkg.go.dev](https://pkg.go.dev/mod.com#Value.Q)
113544--- @ValueT/hover.md --
113545-```go
113546-type parameter T any
113547-```
113548--- @ValuevalT/hover.md --
113549-```go
113550-type parameter T any
113551-```
113552--- @appint/hover.md --
113553-```go
113554-func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
113555-```
113556--- @valueQ/hover.md --
113557-```go
113558-field Q int
113559-```
113560-
113561-@hover("Q", "Q", valueQ)
113562--- @valuevalT/hover.md --
113563-```go
113564-type parameter T any
113565-```
113566diff -urN a/gopls/internal/regtest/marker/testdata/hover/goprivate.txt b/gopls/internal/regtest/marker/testdata/hover/goprivate.txt
113567--- a/gopls/internal/regtest/marker/testdata/hover/goprivate.txt	2000-01-01 00:00:00.000000000 -0000
113568+++ b/gopls/internal/regtest/marker/testdata/hover/goprivate.txt	1970-01-01 00:00:00.000000000 +0000
113569@@ -1,27 +0,0 @@
113570-This test checks that links in hover obey GOPRIVATE.
113571--- env --
113572-GOPRIVATE=mod.com
113573--- go.mod --
113574-module mod.com
113575--- p.go --
113576-package p
113577-
113578-// T should not be linked, as it is private.
113579-type T struct{} //@hover("T", "T", T)
113580--- lib/lib.go --
113581-package lib
113582-
113583-// GOPRIVATE should also match nested packages.
113584-type L struct{} //@hover("L", "L", L)
113585--- @L/hover.md --
113586-```go
113587-type L struct{}
113588-```
113589-
113590-GOPRIVATE should also match nested packages.
113591--- @T/hover.md --
113592-```go
113593-type T struct{}
113594-```
113595-
113596-T should not be linked, as it is private.
113597diff -urN a/gopls/internal/regtest/marker/testdata/hover/hover.txt b/gopls/internal/regtest/marker/testdata/hover/hover.txt
113598--- a/gopls/internal/regtest/marker/testdata/hover/hover.txt	2000-01-01 00:00:00.000000000 -0000
113599+++ b/gopls/internal/regtest/marker/testdata/hover/hover.txt	1970-01-01 00:00:00.000000000 +0000
113600@@ -1,29 +0,0 @@
113601-This test demonstrates some features of the new marker test runner.
113602--- a.go --
113603-package a
113604-
113605-const abc = 0x2a //@hover("b", "abc", abc),hover(" =", "abc", abc)
113606--- typeswitch.go --
113607-package a
113608-
113609-func _() {
113610-	var y interface{}
113611-	switch x := y.(type) { //@hover("x", "x", x)
113612-	case int:
113613-		println(x) //@hover("x", "x", xint),hover(")", "x", xint)
113614-	}
113615-}
113616--- @abc/hover.md --
113617-```go
113618-const abc untyped int = 42
113619-```
113620-
113621-@hover("b", "abc", abc),hover(" =", "abc", abc)
113622--- @x/hover.md --
113623-```go
113624-var x interface{}
113625-```
113626--- @xint/hover.md --
113627-```go
113628-var x int
113629-```
113630diff -urN a/gopls/internal/regtest/marker/testdata/hover/linkable_generics.txt b/gopls/internal/regtest/marker/testdata/hover/linkable_generics.txt
113631--- a/gopls/internal/regtest/marker/testdata/hover/linkable_generics.txt	2000-01-01 00:00:00.000000000 -0000
113632+++ b/gopls/internal/regtest/marker/testdata/hover/linkable_generics.txt	1970-01-01 00:00:00.000000000 +0000
113633@@ -1,145 +0,0 @@
113634-This file contains tests for documentation links to generic code in hover.
113635-
113636--- flags --
113637--min_go=go1.18
113638-
113639--- go.mod --
113640-module mod.com
113641-
113642-go 1.19
113643-
113644--- a.go --
113645-package a
113646-
113647-import "mod.com/generic"
113648-
113649-func _() {
113650-	// Hovering over instantiated object should produce accurate type
113651-	// information, but link to the generic declarations.
113652-
113653-	var x generic.GT[int] //@hover("GT", "GT", xGT)
113654-	_ = x.F //@hover("x", "x", x),hover("F", "F", xF)
113655-
113656-	f := generic.GF[int] //@hover("GF", "GF", fGF)
113657-	_ = f //@hover("f", "f", f)
113658-}
113659-
113660--- generic/generic.go --
113661-package generic
113662-
113663-// Hovering over type parameters should link to documentation.
113664-//
113665-// TODO(rfindley): should it? We should probably link to the type.
113666-type GT[P any] struct{ //@hover("GT", "GT", GT),hover("P", "P", GTP)
113667-	F P //@hover("F", "F", F),hover("P", "P", FP)
113668-}
113669-
113670-func (GT[P]) M(p P) { //@hover("GT", "GT", GTrecv),hover("M","M", M),hover(re"p (P)", re"p (P)", pP)
113671-}
113672-
113673-func GF[P any] (p P) { //@hover("GF", "GF", GF)
113674-}
113675-
113676--- @F/hover.md --
113677-```go
113678-field F P
113679-```
113680-
113681-@hover("F", "F", F),hover("P", "P", FP)
113682-
113683-
113684-[`(generic.GT).F` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT.F)
113685--- @FP/hover.md --
113686-```go
113687-type parameter P any
113688-```
113689--- @GF/hover.md --
113690-```go
113691-func GF[P any](p P)
113692-```
113693-
113694-[`generic.GF` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GF)
113695--- @GT/hover.md --
113696-```go
113697-type GT[P any] struct {
113698-	F P //@hover("F", "F", F),hover("P", "P", FP)
113699-}
113700-
113701-func (GT[P]).M(p P)
113702-```
113703-
113704-Hovering over type parameters should link to documentation.
113705-
113706-TODO(rfindley): should it? We should probably link to the type.
113707-
113708-
113709-[`generic.GT` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT)
113710--- @GTP/hover.md --
113711-```go
113712-type parameter P any
113713-```
113714--- @GTrecv/hover.md --
113715-```go
113716-type GT[P any] struct {
113717-	F P //@hover("F", "F", F),hover("P", "P", FP)
113718-}
113719-
113720-func (GT[P]).M(p P)
113721-```
113722-
113723-Hovering over type parameters should link to documentation.
113724-
113725-TODO(rfindley): should it? We should probably link to the type.
113726-
113727-
113728-[`generic.GT` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT)
113729--- @M/hover.md --
113730-```go
113731-func (GT[P]).M(p P)
113732-```
113733-
113734-[`(generic.GT).M` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT.M)
113735--- @f/hover.md --
113736-```go
113737-var f func(p int)
113738-```
113739--- @fGF/hover.md --
113740-```go
113741-func generic.GF(p int) // func[P any](p P)
113742-```
113743-
113744-[`generic.GF` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GF)
113745--- @pP/hover.md --
113746-```go
113747-type parameter P any
113748-```
113749--- @x/hover.md --
113750-```go
113751-var x generic.GT[int]
113752-```
113753-
113754-@hover("GT", "GT", xGT)
113755--- @xF/hover.md --
113756-```go
113757-field F int
113758-```
113759-
113760-@hover("F", "F", F),hover("P", "P", FP)
113761-
113762-
113763-[`(generic.GT).F` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT.F)
113764--- @xGT/hover.md --
113765-```go
113766-type GT[P any] struct {
113767-	F P //@hover("F", "F", F),hover("P", "P", FP)
113768-}
113769-
113770-func (generic.GT[P]).M(p P)
113771-```
113772-
113773-Hovering over type parameters should link to documentation.
113774-
113775-TODO(rfindley): should it? We should probably link to the type.
113776-
113777-
113778-[`generic.GT` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT)
113779diff -urN a/gopls/internal/regtest/marker/testdata/hover/linkable.txt b/gopls/internal/regtest/marker/testdata/hover/linkable.txt
113780--- a/gopls/internal/regtest/marker/testdata/hover/linkable.txt	2000-01-01 00:00:00.000000000 -0000
113781+++ b/gopls/internal/regtest/marker/testdata/hover/linkable.txt	1970-01-01 00:00:00.000000000 +0000
113782@@ -1,120 +0,0 @@
113783-This test checks that we correctly determine pkgsite links for various
113784-identifiers.
113785-
113786-We should only produce links that work, meaning the object is reachable via the
113787-package's public API.
113788--- go.mod --
113789-module mod.com
113790-
113791-go 1.18
113792--- p.go --
113793-package p
113794-
113795-type E struct {
113796-	Embed int
113797-}
113798-
113799-// T is in the package scope, and so should be linkable.
113800-type T struct{ //@hover("T", "T", T)
113801-	// Only exported fields should be linkable
113802-
113803-	f int //@hover("f", "f", f)
113804-	F int //@hover("F", "F", F)
113805-
113806-	E
113807-
113808-	// TODO(rfindley): is the link here correct? It ignores N.
113809-	N struct {
113810-		// Nested fields should also be linkable.
113811-		Nested int //@hover("Nested", "Nested", Nested)
113812-	}
113813-}
113814-// M is an exported method, and so should be linkable.
113815-func (T) M() {}
113816-
113817-// m is not exported, and so should not be linkable.
113818-func (T) m() {}
113819-
113820-func _() {
113821-	var t T
113822-
113823-	// Embedded fields should be linkable.
113824-	_ = t.Embed //@hover("Embed", "Embed", Embed)
113825-
113826-	// Local variables should not be linkable, even if they are capitalized.
113827-	var X int //@hover("X", "X", X)
113828-	_ = X
113829-
113830-	// Local types should not be linkable, even if they are capitalized.
113831-	type Local struct { //@hover("Local", "Local", Local)
113832-		E
113833-	}
113834-
113835-	// But the embedded field should still be linkable.
113836-	var l Local
113837-	_ = l.Embed //@hover("Embed", "Embed", Embed)
113838-}
113839--- @Embed/hover.md --
113840-```go
113841-field Embed int
113842-```
113843-
113844-[`(p.E).Embed` on pkg.go.dev](https://pkg.go.dev/mod.com#E.Embed)
113845--- @F/hover.md --
113846-```go
113847-field F int
113848-```
113849-
113850-@hover("F", "F", F)
113851-
113852-
113853-[`(p.T).F` on pkg.go.dev](https://pkg.go.dev/mod.com#T.F)
113854--- @Local/hover.md --
113855-```go
113856-type Local struct {
113857-	E
113858-}
113859-```
113860-
113861-Local types should not be linkable, even if they are capitalized.
113862--- @Nested/hover.md --
113863-```go
113864-field Nested int
113865-```
113866-
113867-Nested fields should also be linkable.
113868--- @T/hover.md --
113869-```go
113870-type T struct {
113871-	f int //@hover("f", "f", f)
113872-	F int //@hover("F", "F", F)
113873-
113874-	E
113875-
113876-	// TODO(rfindley): is the link here correct? It ignores N.
113877-	N struct {
113878-		// Nested fields should also be linkable.
113879-		Nested int //@hover("Nested", "Nested", Nested)
113880-	}
113881-}
113882-
113883-func (T).M()
113884-func (T).m()
113885-```
113886-
113887-T is in the package scope, and so should be linkable.
113888-
113889-
113890-[`p.T` on pkg.go.dev](https://pkg.go.dev/mod.com#T)
113891--- @X/hover.md --
113892-```go
113893-var X int
113894-```
113895-
113896-Local variables should not be linkable, even if they are capitalized.
113897--- @f/hover.md --
113898-```go
113899-field f int
113900-```
113901-
113902-@hover("f", "f", f)
113903diff -urN a/gopls/internal/regtest/marker/testdata/hover/std.txt b/gopls/internal/regtest/marker/testdata/hover/std.txt
113904--- a/gopls/internal/regtest/marker/testdata/hover/std.txt	2000-01-01 00:00:00.000000000 -0000
113905+++ b/gopls/internal/regtest/marker/testdata/hover/std.txt	1970-01-01 00:00:00.000000000 +0000
113906@@ -1,80 +0,0 @@
113907-This test checks hover results for built-in or standard library symbols.
113908-
113909-It uses synopsis documentation as full documentation for some of these
113910-built-ins varies across Go versions, where as it just so happens that the
113911-synopsis does not.
113912-
113913-In the future we may need to limit this test to the latest Go version to avoid
113914-documentation churn.
113915--- settings.json --
113916-{
113917-	"hoverKind": "SynopsisDocumentation"
113918-}
113919--- go.mod --
113920-module mod.com
113921-
113922-go 1.18
113923--- std.go --
113924-package std
113925-
113926-import (
113927-	"fmt"
113928-	"go/types"
113929-	"sync"
113930-)
113931-
113932-func _() {
113933-	var err error         //@loc(err, "err")
113934-	fmt.Printf("%v", err) //@def("err", err)
113935-
113936-	var _ string       //@hover("string", "string", hoverstring)
113937-	_ = make([]int, 0) //@hover("make", "make", hovermake)
113938-
113939-	var mu sync.Mutex
113940-	mu.Lock() //@hover("Lock", "Lock", hoverLock)
113941-
113942-	var typ *types.Named //@hover("types", "types", hoverTypes)
113943-	typ.Obj().Name()     //@hover("Name", "Name", hoverName)
113944-}
113945--- @hoverLock/hover.md --
113946-```go
113947-func (*sync.Mutex).Lock()
113948-```
113949-
113950-Lock locks m.
113951-
113952-
113953-[`(sync.Mutex).Lock` on pkg.go.dev](https://pkg.go.dev/sync#Mutex.Lock)
113954--- @hoverName/hover.md --
113955-```go
113956-func (*types.object).Name() string
113957-```
113958-
113959-Name returns the object's (package-local, unqualified) name.
113960-
113961-
113962-[`(types.TypeName).Name` on pkg.go.dev](https://pkg.go.dev/go/types#TypeName.Name)
113963--- @hoverTypes/hover.md --
113964-```go
113965-package types ("go/types")
113966-```
113967-
113968-[`types` on pkg.go.dev](https://pkg.go.dev/go/types)
113969--- @hovermake/hover.md --
113970-```go
113971-func make(t Type, size ...int) Type
113972-```
113973-
113974-The make built-in function allocates and initializes an object of type slice, map, or chan (only).
113975-
113976-
113977-[`make` on pkg.go.dev](https://pkg.go.dev/builtin#make)
113978--- @hoverstring/hover.md --
113979-```go
113980-type string string
113981-```
113982-
113983-string is the set of all strings of 8-bit bytes, conventionally but not necessarily representing UTF-8-encoded text.
113984-
113985-
113986-[`string` on pkg.go.dev](https://pkg.go.dev/builtin#string)
113987diff -urN a/gopls/internal/regtest/marker/testdata/rename/basic.txt b/gopls/internal/regtest/marker/testdata/rename/basic.txt
113988--- a/gopls/internal/regtest/marker/testdata/rename/basic.txt	2000-01-01 00:00:00.000000000 -0000
113989+++ b/gopls/internal/regtest/marker/testdata/rename/basic.txt	1970-01-01 00:00:00.000000000 +0000
113990@@ -1,22 +0,0 @@
113991-This test performs basic coverage of 'rename' within a single package.
113992-
113993--- basic.go --
113994-package p
113995-
113996-func f(x int) { println(x) } //@rename("x", y, param_x)
113997-
113998--- @param_x/basic.go --
113999-package p
114000-
114001-func f(y int) { println(y) } //@rename("x", y, param_x)
114002-
114003--- errors.go --
114004-package p
114005-
114006-func _(x []int) { //@renameerr("_", blank, `can't rename "_"`)
114007-	x = append(x, 1) //@renameerr("append", blank, "built in and cannot be renamed")
114008-	x = nil //@renameerr("nil", blank, "built in and cannot be renamed")
114009-	x = nil //@renameerr("x", x, "old and new names are the same: x")
114010-	_ = 1 //@renameerr("1", x, "no identifier found")
114011-}
114012-
114013diff -urN a/gopls/internal/regtest/marker/testdata/rename/conflict.txt b/gopls/internal/regtest/marker/testdata/rename/conflict.txt
114014--- a/gopls/internal/regtest/marker/testdata/rename/conflict.txt	2000-01-01 00:00:00.000000000 -0000
114015+++ b/gopls/internal/regtest/marker/testdata/rename/conflict.txt	1970-01-01 00:00:00.000000000 +0000
114016@@ -1,59 +0,0 @@
114017-This test exercises some renaming conflict scenarios
114018-and ensures that the errors are informative.
114019-
114020--- go.mod --
114021-module example.com
114022-go 1.12
114023-
114024--- super/p.go --
114025-package super
114026-
114027-var x int
114028-
114029-func f(y int) {
114030-	println(x)
114031-	println(y) //@renameerr("y", x, errSuperBlockConflict)
114032-}
114033-
114034--- @errSuperBlockConflict --
114035-super/p.go:5:8: renaming this var "y" to "x"
114036-super/p.go:6:10:	would shadow this reference
114037-super/p.go:3:5:	to the var declared here
114038--- sub/p.go --
114039-package sub
114040-
114041-var a int
114042-
114043-func f2(b int) {
114044-	println(a) //@renameerr("a", b, errSubBlockConflict)
114045-	println(b)
114046-}
114047-
114048--- @errSubBlockConflict --
114049-sub/p.go:3:5: renaming this var "a" to "b"
114050-sub/p.go:6:10:	would cause this reference to become shadowed
114051-sub/p.go:5:9:	by this intervening var definition
114052--- pkgname/p.go --
114053-package pkgname
114054-
114055-import e1 "errors" //@renameerr("e1", errors, errImportConflict)
114056-import "errors"
114057-
114058-var _ = errors.New
114059-var _ = e1.New
114060-
114061--- @errImportConflict --
114062-pkgname/p.go:3:8: renaming this imported package name "e1" to "errors"
114063-pkgname/p.go:4:8:	conflicts with imported package name in same block
114064--- pkgname2/p1.go --
114065-package pkgname2
114066-var x int
114067-
114068--- pkgname2/p2.go --
114069-package pkgname2
114070-import "errors" //@renameerr("errors", x, errImportConflict2)
114071-var _ = errors.New
114072-
114073--- @errImportConflict2 --
114074-pkgname2/p2.go:2:8: renaming this imported package name "errors" to "x" would conflict
114075-pkgname2/p1.go:2:5:	with this package member var
114076diff -urN a/gopls/internal/regtest/marker/testdata/rename/embed.txt b/gopls/internal/regtest/marker/testdata/rename/embed.txt
114077--- a/gopls/internal/regtest/marker/testdata/rename/embed.txt	2000-01-01 00:00:00.000000000 -0000
114078+++ b/gopls/internal/regtest/marker/testdata/rename/embed.txt	1970-01-01 00:00:00.000000000 +0000
114079@@ -1,36 +0,0 @@
114080-This test exercises renaming of types used as embedded fields.
114081-
114082--- go.mod --
114083-module example.com
114084-go 1.12
114085-
114086--- a/a.go --
114087-package a
114088-
114089-type A int //@rename("A", A2, type)
114090-
114091--- b/b.go --
114092-package b
114093-
114094-import "example.com/a"
114095-
114096-type B struct { a.A } //@renameerr("A", A3, errAnonField)
114097-
114098-var _ = new(B).A //@renameerr("A", A4, errAnonField)
114099-
114100--- @errAnonField --
114101-can't rename embedded fields: rename the type directly or name the field
114102--- @type/a/a.go --
114103-package a
114104-
114105-type A2 int //@rename("A", A2, type)
114106-
114107--- @type/b/b.go --
114108-package b
114109-
114110-import "example.com/a"
114111-
114112-type B struct { a.A2 } //@renameerr("A", A3, errAnonField)
114113-
114114-var _ = new(B).A2 //@renameerr("A", A4, errAnonField)
114115-
114116diff -urN a/gopls/internal/regtest/marker/testdata/rename/methods.txt b/gopls/internal/regtest/marker/testdata/rename/methods.txt
114117--- a/gopls/internal/regtest/marker/testdata/rename/methods.txt	2000-01-01 00:00:00.000000000 -0000
114118+++ b/gopls/internal/regtest/marker/testdata/rename/methods.txt	1970-01-01 00:00:00.000000000 +0000
114119@@ -1,67 +0,0 @@
114120-This test exercises renaming of interface methods.
114121-
114122-The golden is currently wrong due to https://github.com/golang/go/issues/58506:
114123-the reference to B.F in package b should be renamed too.
114124-
114125--- go.mod --
114126-module example.com
114127-go 1.12
114128-
114129--- a/a.go --
114130-package a
114131-
114132-type A int
114133-
114134-func (A) F() {} //@renameerr("F", G, errAfToG)
114135-
114136--- b/b.go --
114137-package b
114138-
114139-import "example.com/a"
114140-import "example.com/c"
114141-
114142-type B interface { F() } //@rename("F", G, BfToG)
114143-
114144-var _ B = a.A(0)
114145-var _ B = c.C(0)
114146-
114147--- c/c.go --
114148-package c
114149-
114150-type C int
114151-
114152-func (C) F() {} //@renameerr("F", G, errCfToG)
114153-
114154--- d/d.go --
114155-package d
114156-
114157-import "example.com/b"
114158-
114159-var _ = b.B.F
114160-
114161--- @errAfToG --
114162-a/a.go:5:10: renaming this method "F" to "G"
114163-b/b.go:6:6:	would make example.com/a.A no longer assignable to interface B
114164-b/b.go:6:20:	(rename example.com/b.B.F if you intend to change both types)
114165--- @BfToG/b/b.go --
114166-package b
114167-
114168-import "example.com/a"
114169-import "example.com/c"
114170-
114171-type B interface { G() } //@rename("F", G, BfToG)
114172-
114173-var _ B = a.A(0)
114174-var _ B = c.C(0)
114175-
114176--- @BfToG/d/d.go --
114177-package d
114178-
114179-import "example.com/b"
114180-
114181-var _ = b.B.G
114182-
114183--- @errCfToG --
114184-c/c.go:5:10: renaming this method "F" to "G"
114185-b/b.go:6:6:	would make example.com/c.C no longer assignable to interface B
114186-b/b.go:6:20:	(rename example.com/b.B.F if you intend to change both types)
114187diff -urN a/gopls/internal/regtest/marker/testdata/rename/typeswitch.txt b/gopls/internal/regtest/marker/testdata/rename/typeswitch.txt
114188--- a/gopls/internal/regtest/marker/testdata/rename/typeswitch.txt	2000-01-01 00:00:00.000000000 -0000
114189+++ b/gopls/internal/regtest/marker/testdata/rename/typeswitch.txt	1970-01-01 00:00:00.000000000 +0000
114190@@ -1,26 +0,0 @@
114191-This test covers the special case of renaming a type switch var.
114192-
114193--- p.go --
114194-package p
114195-
114196-func _(x interface{}) {
114197-	switch y := x.(type) { //@rename("y", z, yToZ)
114198-	case string:
114199-		print(y) //@rename("y", z, yToZ)
114200-	default:
114201-		print(y) //@rename("y", z, yToZ)
114202-	}
114203-}
114204-
114205--- @yToZ/p.go --
114206-package p
114207-
114208-func _(x interface{}) {
114209-	switch z := x.(type) { //@rename("y", z, yToZ)
114210-	case string:
114211-		print(z) //@rename("y", z, yToZ)
114212-	default:
114213-		print(z) //@rename("y", z, yToZ)
114214-	}
114215-}
114216-
114217diff -urN a/gopls/internal/regtest/marker/testdata/stubmethods/basic.txt b/gopls/internal/regtest/marker/testdata/stubmethods/basic.txt
114218--- a/gopls/internal/regtest/marker/testdata/stubmethods/basic.txt	2000-01-01 00:00:00.000000000 -0000
114219+++ b/gopls/internal/regtest/marker/testdata/stubmethods/basic.txt	1970-01-01 00:00:00.000000000 +0000
114220@@ -1,24 +0,0 @@
114221-This test exercises basic 'stub methods' functionality.
114222-
114223--- go.mod --
114224-module example.com
114225-go 1.12
114226-
114227--- a/a.go --
114228-package a
114229-
114230-type C int
114231-
114232-var _ error = C(0) //@suggestedfix(re"C.0.", re"missing method Error", "refactor.rewrite", stub)
114233-
114234--- @stub/a/a.go --
114235-package a
114236-
114237-type C int
114238-
114239-// Error implements error
114240-func (C) Error() string {
114241-	panic("unimplemented")
114242-}
114243-
114244-var _ error = C(0) //@suggestedfix(re"C.0.", re"missing method Error", "refactor.rewrite", stub)
114245diff -urN a/gopls/internal/regtest/misc/call_hierarchy_test.go b/gopls/internal/regtest/misc/call_hierarchy_test.go
114246--- a/gopls/internal/regtest/misc/call_hierarchy_test.go	2000-01-01 00:00:00.000000000 -0000
114247+++ b/gopls/internal/regtest/misc/call_hierarchy_test.go	1970-01-01 00:00:00.000000000 +0000
114248@@ -1,35 +0,0 @@
114249-// Copyright 2021 The Go Authors. All rights reserved.
114250-// Use of this source code is governed by a BSD-style
114251-// license that can be found in the LICENSE file.
114252-package misc
114253-
114254-import (
114255-	"testing"
114256-
114257-	"golang.org/x/tools/gopls/internal/lsp/protocol"
114258-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
114259-)
114260-
114261-// Test for golang/go#49125
114262-func TestCallHierarchy_Issue49125(t *testing.T) {
114263-	const files = `
114264--- go.mod --
114265-module mod.com
114266-
114267-go 1.12
114268--- p.go --
114269-package pkg
114270-`
114271-	// TODO(rfindley): this could probably just be a marker test.
114272-	Run(t, files, func(t *testing.T, env *Env) {
114273-		env.OpenFile("p.go")
114274-		loc := env.RegexpSearch("p.go", "pkg")
114275-
114276-		var params protocol.CallHierarchyPrepareParams
114277-		params.TextDocument.URI = loc.URI
114278-		params.Position = loc.Range.Start
114279-
114280-		// Check that this doesn't panic.
114281-		env.Editor.Server.PrepareCallHierarchy(env.Ctx, &params)
114282-	})
114283-}
114284diff -urN a/gopls/internal/regtest/misc/configuration_test.go b/gopls/internal/regtest/misc/configuration_test.go
114285--- a/gopls/internal/regtest/misc/configuration_test.go	2000-01-01 00:00:00.000000000 -0000
114286+++ b/gopls/internal/regtest/misc/configuration_test.go	1970-01-01 00:00:00.000000000 +0000
114287@@ -1,159 +0,0 @@
114288-// Copyright 2020 The Go Authors. All rights reserved.
114289-// Use of this source code is governed by a BSD-style
114290-// license that can be found in the LICENSE file.
114291-
114292-package misc
114293-
114294-import (
114295-	"testing"
114296-
114297-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
114298-
114299-	"golang.org/x/tools/internal/testenv"
114300-)
114301-
114302-// Test that enabling and disabling produces the expected results of showing
114303-// and hiding staticcheck analysis results.
114304-func TestChangeConfiguration(t *testing.T) {
114305-	// Staticcheck only supports Go versions >= 1.19.
114306-	// Note: keep this in sync with TestStaticcheckWarning. Below this version we
114307-	// should get an error when setting staticcheck configuration.
114308-	testenv.NeedsGo1Point(t, 19)
114309-
114310-	const files = `
114311--- go.mod --
114312-module mod.com
114313-
114314-go 1.12
114315--- a/a.go --
114316-package a
114317-
114318-import "errors"
114319-
114320-// FooErr should be called ErrFoo (ST1012)
114321-var FooErr = errors.New("foo")
114322-`
114323-	Run(t, files, func(t *testing.T, env *Env) {
114324-		env.OpenFile("a/a.go")
114325-		env.AfterChange(
114326-			NoDiagnostics(ForFile("a/a.go")),
114327-		)
114328-		cfg := env.Editor.Config()
114329-		cfg.Settings = map[string]interface{}{
114330-			"staticcheck": true,
114331-		}
114332-		// TODO(rfindley): support waiting on diagnostics following a configuration
114333-		// change.
114334-		env.ChangeConfiguration(cfg)
114335-		env.Await(
114336-			Diagnostics(env.AtRegexp("a/a.go", "var (FooErr)")),
114337-		)
114338-	})
114339-}
114340-
114341-// TestMajorOptionsChange is like TestChangeConfiguration, but modifies an
114342-// an open buffer before making a major (but inconsequential) change that
114343-// causes gopls to recreate the view.
114344-//
114345-// Gopls should not get confused about buffer content when recreating the view.
114346-func TestMajorOptionsChange(t *testing.T) {
114347-	t.Skip("broken due to golang/go#57934")
114348-
114349-	testenv.NeedsGo1Point(t, 17)
114350-
114351-	const files = `
114352--- go.mod --
114353-module mod.com
114354-
114355-go 1.12
114356--- a/a.go --
114357-package a
114358-
114359-import "errors"
114360-
114361-var ErrFoo = errors.New("foo")
114362-`
114363-	Run(t, files, func(t *testing.T, env *Env) {
114364-		env.OpenFile("a/a.go")
114365-		// Introduce a staticcheck diagnostic. It should be detected when we enable
114366-		// staticcheck later.
114367-		env.RegexpReplace("a/a.go", "ErrFoo", "FooErr")
114368-		env.AfterChange(
114369-			NoDiagnostics(ForFile("a/a.go")),
114370-		)
114371-		cfg := env.Editor.Config()
114372-		// Any change to environment recreates the view, but this should not cause
114373-		// gopls to get confused about the content of a/a.go: we should get the
114374-		// staticcheck diagnostic below.
114375-		cfg.Env = map[string]string{
114376-			"AN_ARBITRARY_VAR": "FOO",
114377-		}
114378-		cfg.Settings = map[string]interface{}{
114379-			"staticcheck": true,
114380-		}
114381-		// TODO(rfindley): support waiting on diagnostics following a configuration
114382-		// change.
114383-		env.ChangeConfiguration(cfg)
114384-		env.Await(
114385-			Diagnostics(env.AtRegexp("a/a.go", "var (FooErr)")),
114386-		)
114387-	})
114388-}
114389-
114390-func TestStaticcheckWarning(t *testing.T) {
114391-	// Note: keep this in sync with TestChangeConfiguration.
114392-	testenv.SkipAfterGo1Point(t, 16)
114393-
114394-	const files = `
114395--- go.mod --
114396-module mod.com
114397-
114398-go 1.12
114399--- a/a.go --
114400-package a
114401-
114402-import "errors"
114403-
114404-// FooErr should be called ErrFoo (ST1012)
114405-var FooErr = errors.New("foo")
114406-`
114407-
114408-	WithOptions(
114409-		Settings{"staticcheck": true},
114410-	).Run(t, files, func(t *testing.T, env *Env) {
114411-		env.OnceMet(
114412-			InitialWorkspaceLoad,
114413-			ShownMessage("staticcheck is not supported"),
114414-		)
114415-	})
114416-}
114417-
114418-func TestGofumptWarning(t *testing.T) {
114419-	testenv.SkipAfterGo1Point(t, 17)
114420-
114421-	WithOptions(
114422-		Settings{"gofumpt": true},
114423-	).Run(t, "", func(t *testing.T, env *Env) {
114424-		env.OnceMet(
114425-			InitialWorkspaceLoad,
114426-			ShownMessage("gofumpt is not supported"),
114427-		)
114428-	})
114429-}
114430-
114431-func TestDeprecatedSettings(t *testing.T) {
114432-	WithOptions(
114433-		Settings{
114434-			"experimentalUseInvalidMetadata": true,
114435-			"experimentalWatchedFileDelay":   "1s",
114436-			"experimentalWorkspaceModule":    true,
114437-		},
114438-	).Run(t, "", func(t *testing.T, env *Env) {
114439-		env.OnceMet(
114440-			InitialWorkspaceLoad,
114441-			ShownMessage("experimentalWorkspaceModule"),
114442-			ShownMessage("experimentalUseInvalidMetadata"),
114443-			ShownMessage("experimentalWatchedFileDelay"),
114444-		)
114445-	})
114446-}
114447diff -urN a/gopls/internal/regtest/misc/debugserver_test.go b/gopls/internal/regtest/misc/debugserver_test.go
114448--- a/gopls/internal/regtest/misc/debugserver_test.go	2000-01-01 00:00:00.000000000 -0000
114449+++ b/gopls/internal/regtest/misc/debugserver_test.go	1970-01-01 00:00:00.000000000 +0000
114450@@ -1,46 +0,0 @@
114451-// Copyright 2021 The Go Authors. All rights reserved.
114452-// Use of this source code is governed by a BSD-style
114453-// license that can be found in the LICENSE file.
114454-
114455-package misc
114456-
114457-import (
114458-	"net/http"
114459-	"testing"
114460-
114461-	"golang.org/x/tools/gopls/internal/lsp/command"
114462-	"golang.org/x/tools/gopls/internal/lsp/protocol"
114463-
114464-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
114465-)
114466-
114467-func TestStartDebugging(t *testing.T) {
114468-	WithOptions(
114469-		Modes(Forwarded),
114470-	).Run(t, "", func(t *testing.T, env *Env) {
114471-		args, err := command.MarshalArgs(command.DebuggingArgs{})
114472-		if err != nil {
114473-			t.Fatal(err)
114474-		}
114475-		params := &protocol.ExecuteCommandParams{
114476-			Command:   command.StartDebugging.ID(),
114477-			Arguments: args,
114478-		}
114479-		var result command.DebuggingResult
114480-		env.ExecuteCommand(params, &result)
114481-		if got, want := len(result.URLs), 2; got != want {
114482-			t.Fatalf("got %d urls, want %d; urls: %#v", got, want, result.URLs)
114483-		}
114484-		for i, u := range result.URLs {
114485-			resp, err := http.Get(u)
114486-			if err != nil {
114487-				t.Errorf("getting url #%d (%q): %v", i, u, err)
114488-				continue
114489-			}
114490-			defer resp.Body.Close()
114491-			if got, want := resp.StatusCode, http.StatusOK; got != want {
114492-				t.Errorf("debug server #%d returned HTTP %d, want %d", i, got, want)
114493-			}
114494-		}
114495-	})
114496-}
114497diff -urN a/gopls/internal/regtest/misc/definition_test.go b/gopls/internal/regtest/misc/definition_test.go
114498--- a/gopls/internal/regtest/misc/definition_test.go	2000-01-01 00:00:00.000000000 -0000
114499+++ b/gopls/internal/regtest/misc/definition_test.go	1970-01-01 00:00:00.000000000 +0000
114500@@ -1,512 +0,0 @@
114501-// Copyright 2020 The Go Authors. All rights reserved.
114502-// Use of this source code is governed by a BSD-style
114503-// license that can be found in the LICENSE file.
114504-
114505-package misc
114506-
114507-import (
114508-	"os"
114509-	"path"
114510-	"path/filepath"
114511-	"strings"
114512-	"testing"
114513-
114514-	"golang.org/x/tools/gopls/internal/lsp/protocol"
114515-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
114516-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
114517-)
114518-
114519-const internalDefinition = `
114520--- go.mod --
114521-module mod.com
114522-
114523-go 1.12
114524--- main.go --
114525-package main
114526-
114527-import "fmt"
114528-
114529-func main() {
114530-	fmt.Println(message)
114531-}
114532--- const.go --
114533-package main
114534-
114535-const message = "Hello World."
114536-`
114537-
114538-func TestGoToInternalDefinition(t *testing.T) {
114539-	Run(t, internalDefinition, func(t *testing.T, env *Env) {
114540-		env.OpenFile("main.go")
114541-		loc := env.GoToDefinition(env.RegexpSearch("main.go", "message"))
114542-		name := env.Sandbox.Workdir.URIToPath(loc.URI)
114543-		if want := "const.go"; name != want {
114544-			t.Errorf("GoToDefinition: got file %q, want %q", name, want)
114545-		}
114546-		if want := env.RegexpSearch("const.go", "message"); loc != want {
114547-			t.Errorf("GoToDefinition: got location %v, want %v", loc, want)
114548-		}
114549-	})
114550-}
114551-
114552-const linknameDefinition = `
114553--- go.mod --
114554-module mod.com
114555-
114556--- upper/upper.go --
114557-package upper
114558-
114559-import (
114560-	_ "unsafe"
114561-
114562-	_ "mod.com/middle"
114563-)
114564-
114565-//go:linkname foo mod.com/lower.bar
114566-func foo() string
114567-
114568--- middle/middle.go --
114569-package middle
114570-
114571-import (
114572-	_ "mod.com/lower"
114573-)
114574-
114575--- lower/lower.s --
114576-
114577--- lower/lower.go --
114578-package lower
114579-
114580-func bar() string {
114581-	return "bar as foo"
114582-}`
114583-
114584-func TestGoToLinknameDefinition(t *testing.T) {
114585-	Run(t, linknameDefinition, func(t *testing.T, env *Env) {
114586-		env.OpenFile("upper/upper.go")
114587-
114588-		// Jump from directives 2nd arg.
114589-		start := env.RegexpSearch("upper/upper.go", `lower.bar`)
114590-		loc := env.GoToDefinition(start)
114591-		name := env.Sandbox.Workdir.URIToPath(loc.URI)
114592-		if want := "lower/lower.go"; name != want {
114593-			t.Errorf("GoToDefinition: got file %q, want %q", name, want)
114594-		}
114595-		if want := env.RegexpSearch("lower/lower.go", `bar`); loc != want {
114596-			t.Errorf("GoToDefinition: got position %v, want %v", loc, want)
114597-		}
114598-	})
114599-}
114600-
114601-const linknameDefinitionReverse = `
114602--- go.mod --
114603-module mod.com
114604-
114605--- upper/upper.s --
114606-
114607--- upper/upper.go --
114608-package upper
114609-
114610-import (
114611-	_ "mod.com/middle"
114612-)
114613-
114614-func foo() string
114615-
114616--- middle/middle.go --
114617-package middle
114618-
114619-import (
114620-	_ "mod.com/lower"
114621-)
114622-
114623--- lower/lower.go --
114624-package lower
114625-
114626-import _ "unsafe"
114627-
114628-//go:linkname bar mod.com/upper.foo
114629-func bar() string {
114630-	return "bar as foo"
114631-}`
114632-
114633-func TestGoToLinknameDefinitionInReverseDep(t *testing.T) {
114634-	Run(t, linknameDefinitionReverse, func(t *testing.T, env *Env) {
114635-		env.OpenFile("lower/lower.go")
114636-
114637-		// Jump from directives 2nd arg.
114638-		start := env.RegexpSearch("lower/lower.go", `upper.foo`)
114639-		loc := env.GoToDefinition(start)
114640-		name := env.Sandbox.Workdir.URIToPath(loc.URI)
114641-		if want := "upper/upper.go"; name != want {
114642-			t.Errorf("GoToDefinition: got file %q, want %q", name, want)
114643-		}
114644-		if want := env.RegexpSearch("upper/upper.go", `foo`); loc != want {
114645-			t.Errorf("GoToDefinition: got position %v, want %v", loc, want)
114646-		}
114647-	})
114648-}
114649-
114650-// The linkname directive connects two packages not related in the import graph.
114651-const linknameDefinitionDisconnected = `
114652--- go.mod --
114653-module mod.com
114654-
114655--- a/a.go --
114656-package a
114657-
114658-import (
114659-	_ "unsafe"
114660-)
114661-
114662-//go:linkname foo mod.com/b.bar
114663-func foo() string
114664-
114665--- b/b.go --
114666-package b
114667-
114668-func bar() string {
114669-	return "bar as foo"
114670-}`
114671-
114672-func TestGoToLinknameDefinitionDisconnected(t *testing.T) {
114673-	Run(t, linknameDefinitionDisconnected, func(t *testing.T, env *Env) {
114674-		env.OpenFile("a/a.go")
114675-
114676-		// Jump from directives 2nd arg.
114677-		start := env.RegexpSearch("a/a.go", `b.bar`)
114678-		loc := env.GoToDefinition(start)
114679-		name := env.Sandbox.Workdir.URIToPath(loc.URI)
114680-		if want := "b/b.go"; name != want {
114681-			t.Errorf("GoToDefinition: got file %q, want %q", name, want)
114682-		}
114683-		if want := env.RegexpSearch("b/b.go", `bar`); loc != want {
114684-			t.Errorf("GoToDefinition: got position %v, want %v", loc, want)
114685-		}
114686-	})
114687-}
114688-
114689-const stdlibDefinition = `
114690--- go.mod --
114691-module mod.com
114692-
114693-go 1.12
114694--- main.go --
114695-package main
114696-
114697-import "fmt"
114698-
114699-func main() {
114700-	fmt.Printf()
114701-}`
114702-
114703-func TestGoToStdlibDefinition_Issue37045(t *testing.T) {
114704-	Run(t, stdlibDefinition, func(t *testing.T, env *Env) {
114705-		env.OpenFile("main.go")
114706-		loc := env.GoToDefinition(env.RegexpSearch("main.go", `fmt.(Printf)`))
114707-		name := env.Sandbox.Workdir.URIToPath(loc.URI)
114708-		if got, want := path.Base(name), "print.go"; got != want {
114709-			t.Errorf("GoToDefinition: got file %q, want %q", name, want)
114710-		}
114711-
114712-		// Test that we can jump to definition from outside our workspace.
114713-		// See golang.org/issues/37045.
114714-		newLoc := env.GoToDefinition(loc)
114715-		newName := env.Sandbox.Workdir.URIToPath(newLoc.URI)
114716-		if newName != name {
114717-			t.Errorf("GoToDefinition is not idempotent: got %q, want %q", newName, name)
114718-		}
114719-		if newLoc != loc {
114720-			t.Errorf("GoToDefinition is not idempotent: got %v, want %v", newLoc, loc)
114721-		}
114722-	})
114723-}
114724-
114725-func TestUnexportedStdlib_Issue40809(t *testing.T) {
114726-	Run(t, stdlibDefinition, func(t *testing.T, env *Env) {
114727-		env.OpenFile("main.go")
114728-		loc := env.GoToDefinition(env.RegexpSearch("main.go", `fmt.(Printf)`))
114729-		name := env.Sandbox.Workdir.URIToPath(loc.URI)
114730-
114731-		loc = env.RegexpSearch(name, `:=\s*(newPrinter)\(\)`)
114732-
114733-		// Check that we can find references on a reference
114734-		refs := env.References(loc)
114735-		if len(refs) < 5 {
114736-			t.Errorf("expected 5+ references to newPrinter, found: %#v", refs)
114737-		}
114738-
114739-		loc = env.GoToDefinition(loc)
114740-		content, _ := env.Hover(loc)
114741-		if !strings.Contains(content.Value, "newPrinter") {
114742-			t.Fatal("definition of newPrinter went to the incorrect place")
114743-		}
114744-		// And on the definition too.
114745-		refs = env.References(loc)
114746-		if len(refs) < 5 {
114747-			t.Errorf("expected 5+ references to newPrinter, found: %#v", refs)
114748-		}
114749-	})
114750-}
114751-
114752-// Test the hover on an error's Error function.
114753-// This can't be done via the marker tests because Error is a builtin.
114754-func TestHoverOnError(t *testing.T) {
114755-	const mod = `
114756--- go.mod --
114757-module mod.com
114758-
114759-go 1.12
114760--- main.go --
114761-package main
114762-
114763-func main() {
114764-	var err error
114765-	err.Error()
114766-}`
114767-	Run(t, mod, func(t *testing.T, env *Env) {
114768-		env.OpenFile("main.go")
114769-		content, _ := env.Hover(env.RegexpSearch("main.go", "Error"))
114770-		if content == nil {
114771-			t.Fatalf("nil hover content for Error")
114772-		}
114773-		want := "```go\nfunc (error).Error() string\n```"
114774-		if content.Value != want {
114775-			t.Fatalf("hover failed:\n%s", compare.Text(want, content.Value))
114776-		}
114777-	})
114778-}
114779-
114780-func TestImportShortcut(t *testing.T) {
114781-	const mod = `
114782--- go.mod --
114783-module mod.com
114784-
114785-go 1.12
114786--- main.go --
114787-package main
114788-
114789-import "fmt"
114790-
114791-func main() {}
114792-`
114793-	for _, tt := range []struct {
114794-		wantLinks      int
114795-		importShortcut string
114796-	}{
114797-		{1, "Link"},
114798-		{0, "Definition"},
114799-		{1, "Both"},
114800-	} {
114801-		t.Run(tt.importShortcut, func(t *testing.T) {
114802-			WithOptions(
114803-				Settings{"importShortcut": tt.importShortcut},
114804-			).Run(t, mod, func(t *testing.T, env *Env) {
114805-				env.OpenFile("main.go")
114806-				loc := env.GoToDefinition(env.RegexpSearch("main.go", `"fmt"`))
114807-				if loc == (protocol.Location{}) {
114808-					t.Fatalf("expected definition, got none")
114809-				}
114810-				links := env.DocumentLink("main.go")
114811-				if len(links) != tt.wantLinks {
114812-					t.Fatalf("expected %v links, got %v", tt.wantLinks, len(links))
114813-				}
114814-			})
114815-		})
114816-	}
114817-}
114818-
114819-func TestGoToTypeDefinition_Issue38589(t *testing.T) {
114820-	const mod = `
114821--- go.mod --
114822-module mod.com
114823-
114824-go 1.12
114825--- main.go --
114826-package main
114827-
114828-type Int int
114829-
114830-type Struct struct{}
114831-
114832-func F1() {}
114833-func F2() (int, error) { return 0, nil }
114834-func F3() (**Struct, bool, *Int, error) { return nil, false, nil, nil }
114835-func F4() (**Struct, bool, *float64, error) { return nil, false, nil, nil }
114836-
114837-func main() {}
114838-`
114839-
114840-	for _, tt := range []struct {
114841-		re         string
114842-		wantError  bool
114843-		wantTypeRe string
114844-	}{
114845-		{re: `F1`, wantError: true},
114846-		{re: `F2`, wantError: true},
114847-		{re: `F3`, wantError: true},
114848-		{re: `F4`, wantError: false, wantTypeRe: `type (Struct)`},
114849-	} {
114850-		t.Run(tt.re, func(t *testing.T) {
114851-			Run(t, mod, func(t *testing.T, env *Env) {
114852-				env.OpenFile("main.go")
114853-
114854-				loc, err := env.Editor.GoToTypeDefinition(env.Ctx, env.RegexpSearch("main.go", tt.re))
114855-				if tt.wantError {
114856-					if err == nil {
114857-						t.Fatal("expected error, got nil")
114858-					}
114859-					return
114860-				}
114861-				if err != nil {
114862-					t.Fatalf("expected nil error, got %s", err)
114863-				}
114864-
114865-				typeLoc := env.RegexpSearch("main.go", tt.wantTypeRe)
114866-				if loc != typeLoc {
114867-					t.Errorf("invalid pos: want %+v, got %+v", typeLoc, loc)
114868-				}
114869-			})
114870-		})
114871-	}
114872-}
114873-
114874-// Test for golang/go#47825.
114875-func TestImportTestVariant(t *testing.T) {
114876-	const mod = `
114877--- go.mod --
114878-module mod.com
114879-
114880-go 1.12
114881--- client/test/role.go --
114882-package test
114883-
114884-import _ "mod.com/client"
114885-
114886-type RoleSetup struct{}
114887--- client/client_role_test.go --
114888-package client_test
114889-
114890-import (
114891-	"testing"
114892-	_ "mod.com/client"
114893-	ctest "mod.com/client/test"
114894-)
114895-
114896-func TestClient(t *testing.T) {
114897-	_ = ctest.RoleSetup{}
114898-}
114899--- client/client_test.go --
114900-package client
114901-
114902-import "testing"
114903-
114904-func TestClient(t *testing.T) {}
114905--- client.go --
114906-package client
114907-`
114908-	Run(t, mod, func(t *testing.T, env *Env) {
114909-		env.OpenFile("client/client_role_test.go")
114910-		env.GoToDefinition(env.RegexpSearch("client/client_role_test.go", "RoleSetup"))
114911-	})
114912-}
114913-
114914-// This test exercises a crashing pattern from golang/go#49223.
114915-func TestGoToCrashingDefinition_Issue49223(t *testing.T) {
114916-	Run(t, "", func(t *testing.T, env *Env) {
114917-		params := &protocol.DefinitionParams{}
114918-		params.TextDocument.URI = protocol.DocumentURI("fugitive%3A///Users/user/src/mm/ems/.git//0/pkg/domain/treasury/provider.go")
114919-		params.Position.Character = 18
114920-		params.Position.Line = 0
114921-		env.Editor.Server.Definition(env.Ctx, params)
114922-	})
114923-}
114924-
114925-// TestVendoringInvalidatesMetadata ensures that gopls uses the
114926-// correct metadata even after an external 'go mod vendor' command
114927-// causes packages to move; see issue #55995.
114928-// See also TestImplementationsInVendor, which tests the same fix.
114929-func TestVendoringInvalidatesMetadata(t *testing.T) {
114930-	t.Skip("golang/go#56169: file watching does not capture vendor dirs")
114931-
114932-	const proxy = `
114933--- other.com/[email protected]/go.mod --
114934-module other.com/b
114935-go 1.14
114936-
114937--- other.com/[email protected]/b.go --
114938-package b
114939-const K = 0
114940-`
114941-	const src = `
114942--- go.mod --
114943-module example.com/a
114944-go 1.14
114945-require other.com/b v1.0.0
114946-
114947--- go.sum --
114948-other.com/b v1.0.0 h1:1wb3PMGdet5ojzrKl+0iNksRLnOM9Jw+7amBNqmYwqk=
114949-other.com/b v1.0.0/go.mod h1:TgHQFucl04oGT+vrUm/liAzukYHNxCwKNkQZEyn3m9g=
114950-
114951--- a.go --
114952-package a
114953-import "other.com/b"
114954-const _ = b.K
114955-
114956-`
114957-	WithOptions(
114958-		ProxyFiles(proxy),
114959-		Modes(Default), // fails in 'experimental' mode
114960-	).Run(t, src, func(t *testing.T, env *Env) {
114961-		// Enable to debug go.sum mismatch, which may appear as
114962-		// "module lookup disabled by GOPROXY=off", confusingly.
114963-		if false {
114964-			env.DumpGoSum(".")
114965-		}
114966-
114967-		env.OpenFile("a.go")
114968-		refLoc := env.RegexpSearch("a.go", "K") // find "b.K" reference
114969-
114970-		// Initially, b.K is defined in the module cache.
114971-		gotLoc := env.GoToDefinition(refLoc)
114972-		gotFile := env.Sandbox.Workdir.URIToPath(gotLoc.URI)
114973-		wantCache := filepath.ToSlash(env.Sandbox.GOPATH()) + "/pkg/mod/other.com/[email protected]/b.go"
114974-		if gotFile != wantCache {
114975-			t.Errorf("GoToDefinition, before: got file %q, want %q", gotFile, wantCache)
114976-		}
114977-
114978-		// Run 'go mod vendor' outside the editor.
114979-		if err := env.Sandbox.RunGoCommand(env.Ctx, ".", "mod", []string{"vendor"}, true); err != nil {
114980-			t.Fatalf("go mod vendor: %v", err)
114981-		}
114982-
114983-		// Synchronize changes to watched files.
114984-		env.Await(env.DoneWithChangeWatchedFiles())
114985-
114986-		// Now, b.K is defined in the vendor tree.
114987-		gotLoc = env.GoToDefinition(refLoc)
114988-		wantVendor := "vendor/other.com/b/b.go"
114989-		if gotFile != wantVendor {
114990-			t.Errorf("GoToDefinition, after go mod vendor: got file %q, want %q", gotFile, wantVendor)
114991-		}
114992-
114993-		// Delete the vendor tree.
114994-		if err := os.RemoveAll(env.Sandbox.Workdir.AbsPath("vendor")); err != nil {
114995-			t.Fatal(err)
114996-		}
114997-		// Notify the server of the deletion.
114998-		if err := env.Sandbox.Workdir.CheckForFileChanges(env.Ctx); err != nil {
114999-			t.Fatal(err)
115000-		}
115001-
115002-		// Synchronize again.
115003-		env.Await(env.DoneWithChangeWatchedFiles())
115004-
115005-		// b.K is once again defined in the module cache.
115006-		gotLoc = env.GoToDefinition(gotLoc)
115007-		gotFile = env.Sandbox.Workdir.URIToPath(gotLoc.URI)
115008-		if gotFile != wantCache {
115009-			t.Errorf("GoToDefinition, after rm -rf vendor: got file %q, want %q", gotFile, wantCache)
115010-		}
115011-	})
115012-}
115013diff -urN a/gopls/internal/regtest/misc/embed_test.go b/gopls/internal/regtest/misc/embed_test.go
115014--- a/gopls/internal/regtest/misc/embed_test.go	2000-01-01 00:00:00.000000000 -0000
115015+++ b/gopls/internal/regtest/misc/embed_test.go	1970-01-01 00:00:00.000000000 +0000
115016@@ -1,40 +0,0 @@
115017-// Copyright 2021 The Go Authors. All rights reserved.
115018-// Use of this source code is governed by a BSD-style
115019-// license that can be found in the LICENSE file.
115020-package misc
115021-
115022-import (
115023-	"testing"
115024-
115025-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
115026-)
115027-
115028-func TestMissingPatternDiagnostic(t *testing.T) {
115029-	const files = `
115030--- go.mod --
115031-module example.com
115032--- x.go --
115033-package x
115034-
115035-import (
115036-	_ "embed"
115037-)
115038-
115039-// Issue 47436
115040-func F() {}
115041-
115042-//go:embed NONEXISTENT
115043-var foo string
115044-`
115045-	Run(t, files, func(t *testing.T, env *Env) {
115046-		env.OpenFile("x.go")
115047-		env.AfterChange(
115048-			Diagnostics(
115049-				env.AtRegexp("x.go", `NONEXISTENT`),
115050-				WithMessage("no matching files found"),
115051-			),
115052-		)
115053-		env.RegexpReplace("x.go", `NONEXISTENT`, "x.go")
115054-		env.AfterChange(NoDiagnostics(ForFile("x.go")))
115055-	})
115056-}
115057diff -urN a/gopls/internal/regtest/misc/extract_test.go b/gopls/internal/regtest/misc/extract_test.go
115058--- a/gopls/internal/regtest/misc/extract_test.go	2000-01-01 00:00:00.000000000 -0000
115059+++ b/gopls/internal/regtest/misc/extract_test.go	1970-01-01 00:00:00.000000000 +0000
115060@@ -1,65 +0,0 @@
115061-// Copyright 2022 The Go Authors. All rights reserved.
115062-// Use of this source code is governed by a BSD-style
115063-// license that can be found in the LICENSE file.
115064-package misc
115065-
115066-import (
115067-	"testing"
115068-
115069-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
115070-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
115071-
115072-	"golang.org/x/tools/gopls/internal/lsp/protocol"
115073-)
115074-
115075-func TestExtractFunction(t *testing.T) {
115076-	const files = `
115077--- go.mod --
115078-module mod.com
115079-
115080-go 1.12
115081--- main.go --
115082-package main
115083-
115084-func Foo() int {
115085-	a := 5
115086-	return a
115087-}
115088-`
115089-	Run(t, files, func(t *testing.T, env *Env) {
115090-		env.OpenFile("main.go")
115091-		loc := env.RegexpSearch("main.go", `a := 5\n.*return a`)
115092-		actions, err := env.Editor.CodeAction(env.Ctx, loc, nil)
115093-		if err != nil {
115094-			t.Fatal(err)
115095-		}
115096-
115097-		// Find the extract function code action.
115098-		var extractFunc *protocol.CodeAction
115099-		for _, action := range actions {
115100-			if action.Kind == protocol.RefactorExtract && action.Title == "Extract function" {
115101-				extractFunc = &action
115102-				break
115103-			}
115104-		}
115105-		if extractFunc == nil {
115106-			t.Fatal("could not find extract function action")
115107-		}
115108-
115109-		env.ApplyCodeAction(*extractFunc)
115110-		want := `package main
115111-
115112-func Foo() int {
115113-	return newFunction()
115114-}
115115-
115116-func newFunction() int {
115117-	a := 5
115118-	return a
115119-}
115120-`
115121-		if got := env.BufferText("main.go"); got != want {
115122-			t.Fatalf("TestFillStruct failed:\n%s", compare.Text(want, got))
115123-		}
115124-	})
115125-}
115126diff -urN a/gopls/internal/regtest/misc/failures_test.go b/gopls/internal/regtest/misc/failures_test.go
115127--- a/gopls/internal/regtest/misc/failures_test.go	2000-01-01 00:00:00.000000000 -0000
115128+++ b/gopls/internal/regtest/misc/failures_test.go	1970-01-01 00:00:00.000000000 +0000
115129@@ -1,84 +0,0 @@
115130-// Copyright 2020 The Go Authors. All rights reserved.
115131-// Use of this source code is governed by a BSD-style
115132-// license that can be found in the LICENSE file.
115133-
115134-package misc
115135-
115136-import (
115137-	"testing"
115138-
115139-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
115140-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
115141-)
115142-
115143-// This is a slight variant of TestHoverOnError in definition_test.go
115144-// that includes a line directive, which makes no difference since
115145-// gopls ignores line directives.
115146-func TestHoverFailure(t *testing.T) {
115147-	t.Skip("line directives //line ")
115148-	const mod = `
115149--- go.mod --
115150-module mod.com
115151-
115152-go 1.12
115153--- a.y --
115154-DWIM(main)
115155-
115156--- main.go --
115157-//line a.y:1
115158-package main
115159-
115160-func main() {
115161-	var err error
115162-	err.Error()
115163-}`
115164-	Run(t, mod, func(t *testing.T, env *Env) {
115165-		env.OpenFile("main.go")
115166-		content, _ := env.Hover(env.RegexpSearch("main.go", "Error"))
115167-		if content == nil {
115168-			t.Fatalf("Hover('Error') returned nil")
115169-		}
115170-		want := "```go\nfunc (error).Error() string\n```"
115171-		if content.Value != want {
115172-			t.Fatalf("wrong Hover('Error') content:\n%s", compare.Text(want, content.Value))
115173-		}
115174-	})
115175-}
115176-
115177-// This test demonstrates a case where gopls is not at all confused by
115178-// line directives, because it completely ignores them.
115179-func TestFailingDiagnosticClearingOnEdit(t *testing.T) {
115180-	t.Skip("line directives //line ")
115181-	// badPackageDup contains a duplicate definition of the 'a' const.
115182-	// This is a minor variant of TestDiagnosticClearingOnEdit from
115183-	// diagnostics_test.go, with a line directive, which makes no difference.
115184-	const badPackageDup = `
115185--- go.mod --
115186-module mod.com
115187-
115188-go 1.12
115189--- a.go --
115190-package consts
115191-
115192-const a = 1
115193--- b.go --
115194-package consts
115195-//line gen.go:5
115196-const a = 2
115197-`
115198-
115199-	Run(t, badPackageDup, func(t *testing.T, env *Env) {
115200-		env.OpenFile("b.go")
115201-		env.AfterChange(
115202-			Diagnostics(env.AtRegexp("b.go", `a = 2`), WithMessage("a redeclared")),
115203-			Diagnostics(env.AtRegexp("a.go", `a = 1`), WithMessage("other declaration")),
115204-		)
115205-
115206-		// Fix the error by editing the const name in b.go to `b`.
115207-		env.RegexpReplace("b.go", "(a) = 2", "b")
115208-		env.AfterChange(
115209-			NoDiagnostics(ForFile("a.go")),
115210-			NoDiagnostics(ForFile("b.go")),
115211-		)
115212-	})
115213-}
115214diff -urN a/gopls/internal/regtest/misc/fix_test.go b/gopls/internal/regtest/misc/fix_test.go
115215--- a/gopls/internal/regtest/misc/fix_test.go	2000-01-01 00:00:00.000000000 -0000
115216+++ b/gopls/internal/regtest/misc/fix_test.go	1970-01-01 00:00:00.000000000 +0000
115217@@ -1,103 +0,0 @@
115218-// Copyright 2020 The Go Authors. All rights reserved.
115219-// Use of this source code is governed by a BSD-style
115220-// license that can be found in the LICENSE file.
115221-
115222-package misc
115223-
115224-import (
115225-	"testing"
115226-
115227-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
115228-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
115229-
115230-	"golang.org/x/tools/gopls/internal/lsp/protocol"
115231-)
115232-
115233-// A basic test for fillstruct, now that it uses a command.
115234-func TestFillStruct(t *testing.T) {
115235-	const basic = `
115236--- go.mod --
115237-module mod.com
115238-
115239-go 1.14
115240--- main.go --
115241-package main
115242-
115243-type Info struct {
115244-	WordCounts map[string]int
115245-	Words []string
115246-}
115247-
115248-func Foo() {
115249-	_ = Info{}
115250-}
115251-`
115252-	Run(t, basic, func(t *testing.T, env *Env) {
115253-		env.OpenFile("main.go")
115254-		if err := env.Editor.RefactorRewrite(env.Ctx, env.RegexpSearch("main.go", "Info{}")); err != nil {
115255-			t.Fatal(err)
115256-		}
115257-		want := `package main
115258-
115259-type Info struct {
115260-	WordCounts map[string]int
115261-	Words []string
115262-}
115263-
115264-func Foo() {
115265-	_ = Info{
115266-		WordCounts: map[string]int{},
115267-		Words:      []string{},
115268-	}
115269-}
115270-`
115271-		if got := env.BufferText("main.go"); got != want {
115272-			t.Fatalf("TestFillStruct failed:\n%s", compare.Text(want, got))
115273-		}
115274-	})
115275-}
115276-
115277-func TestFillReturns(t *testing.T) {
115278-	const files = `
115279--- go.mod --
115280-module mod.com
115281-
115282-go 1.12
115283--- main.go --
115284-package main
115285-
115286-func Foo() error {
115287-	return
115288-}
115289-`
115290-	Run(t, files, func(t *testing.T, env *Env) {
115291-		env.OpenFile("main.go")
115292-		var d protocol.PublishDiagnosticsParams
115293-		env.AfterChange(
115294-			// The error message here changed in 1.18; "return values" covers both forms.
115295-			Diagnostics(env.AtRegexp("main.go", `return`), WithMessage("return values")),
115296-			ReadDiagnostics("main.go", &d),
115297-		)
115298-		codeActions := env.CodeAction("main.go", d.Diagnostics)
115299-		if len(codeActions) != 2 {
115300-			t.Fatalf("expected 2 code actions, got %v", len(codeActions))
115301-		}
115302-		var foundQuickFix, foundFixAll bool
115303-		for _, a := range codeActions {
115304-			if a.Kind == protocol.QuickFix {
115305-				foundQuickFix = true
115306-			}
115307-			if a.Kind == protocol.SourceFixAll {
115308-				foundFixAll = true
115309-			}
115310-		}
115311-		if !foundQuickFix {
115312-			t.Fatalf("expected quickfix code action, got none")
115313-		}
115314-		if !foundFixAll {
115315-			t.Fatalf("expected fixall code action, got none")
115316-		}
115317-		env.ApplyQuickFixes("main.go", d.Diagnostics)
115318-		env.AfterChange(NoDiagnostics(ForFile("main.go")))
115319-	})
115320-}
115321diff -urN a/gopls/internal/regtest/misc/formatting_test.go b/gopls/internal/regtest/misc/formatting_test.go
115322--- a/gopls/internal/regtest/misc/formatting_test.go	2000-01-01 00:00:00.000000000 -0000
115323+++ b/gopls/internal/regtest/misc/formatting_test.go	1970-01-01 00:00:00.000000000 +0000
115324@@ -1,368 +0,0 @@
115325-// Copyright 2020 The Go Authors. All rights reserved.
115326-// Use of this source code is governed by a BSD-style
115327-// license that can be found in the LICENSE file.
115328-
115329-package misc
115330-
115331-import (
115332-	"strings"
115333-	"testing"
115334-
115335-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
115336-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
115337-	"golang.org/x/tools/internal/testenv"
115338-)
115339-
115340-const unformattedProgram = `
115341--- main.go --
115342-package main
115343-import "fmt"
115344-func main(  ) {
115345-	fmt.Println("Hello World.")
115346-}
115347--- main.go.golden --
115348-package main
115349-
115350-import "fmt"
115351-
115352-func main() {
115353-	fmt.Println("Hello World.")
115354-}
115355-`
115356-
115357-func TestFormatting(t *testing.T) {
115358-	Run(t, unformattedProgram, func(t *testing.T, env *Env) {
115359-		env.OpenFile("main.go")
115360-		env.FormatBuffer("main.go")
115361-		got := env.BufferText("main.go")
115362-		want := env.ReadWorkspaceFile("main.go.golden")
115363-		if got != want {
115364-			t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
115365-		}
115366-	})
115367-}
115368-
115369-// Tests golang/go#36824.
115370-func TestFormattingOneLine36824(t *testing.T) {
115371-	const onelineProgram = `
115372--- a.go --
115373-package main; func f() {}
115374-
115375--- a.go.formatted --
115376-package main
115377-
115378-func f() {}
115379-`
115380-	Run(t, onelineProgram, func(t *testing.T, env *Env) {
115381-		env.OpenFile("a.go")
115382-		env.FormatBuffer("a.go")
115383-		got := env.BufferText("a.go")
115384-		want := env.ReadWorkspaceFile("a.go.formatted")
115385-		if got != want {
115386-			t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
115387-		}
115388-	})
115389-}
115390-
115391-// Tests golang/go#36824.
115392-func TestFormattingOneLineImports36824(t *testing.T) {
115393-	const onelineProgramA = `
115394--- a.go --
115395-package x; func f() {fmt.Println()}
115396-
115397--- a.go.imported --
115398-package x
115399-
115400-import "fmt"
115401-
115402-func f() { fmt.Println() }
115403-`
115404-	Run(t, onelineProgramA, func(t *testing.T, env *Env) {
115405-		env.OpenFile("a.go")
115406-		env.OrganizeImports("a.go")
115407-		got := env.BufferText("a.go")
115408-		want := env.ReadWorkspaceFile("a.go.imported")
115409-		if got != want {
115410-			t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
115411-		}
115412-	})
115413-}
115414-
115415-func TestFormattingOneLineRmImports36824(t *testing.T) {
115416-	const onelineProgramB = `
115417--- a.go --
115418-package x; import "os"; func f() {}
115419-
115420--- a.go.imported --
115421-package x
115422-
115423-func f() {}
115424-`
115425-	Run(t, onelineProgramB, func(t *testing.T, env *Env) {
115426-		env.OpenFile("a.go")
115427-		env.OrganizeImports("a.go")
115428-		got := env.BufferText("a.go")
115429-		want := env.ReadWorkspaceFile("a.go.imported")
115430-		if got != want {
115431-			t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
115432-		}
115433-	})
115434-}
115435-
115436-const disorganizedProgram = `
115437--- main.go --
115438-package main
115439-
115440-import (
115441-	"fmt"
115442-	"errors"
115443-)
115444-func main(  ) {
115445-	fmt.Println(errors.New("bad"))
115446-}
115447--- main.go.organized --
115448-package main
115449-
115450-import (
115451-	"errors"
115452-	"fmt"
115453-)
115454-func main(  ) {
115455-	fmt.Println(errors.New("bad"))
115456-}
115457--- main.go.formatted --
115458-package main
115459-
115460-import (
115461-	"errors"
115462-	"fmt"
115463-)
115464-
115465-func main() {
115466-	fmt.Println(errors.New("bad"))
115467-}
115468-`
115469-
115470-func TestOrganizeImports(t *testing.T) {
115471-	Run(t, disorganizedProgram, func(t *testing.T, env *Env) {
115472-		env.OpenFile("main.go")
115473-		env.OrganizeImports("main.go")
115474-		got := env.BufferText("main.go")
115475-		want := env.ReadWorkspaceFile("main.go.organized")
115476-		if got != want {
115477-			t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
115478-		}
115479-	})
115480-}
115481-
115482-func TestFormattingOnSave(t *testing.T) {
115483-	Run(t, disorganizedProgram, func(t *testing.T, env *Env) {
115484-		env.OpenFile("main.go")
115485-		env.SaveBuffer("main.go")
115486-		got := env.BufferText("main.go")
115487-		want := env.ReadWorkspaceFile("main.go.formatted")
115488-		if got != want {
115489-			t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
115490-		}
115491-	})
115492-}
115493-
115494-// Tests various possibilities for comments in files with CRLF line endings.
115495-// Import organization in these files has historically been a source of bugs.
115496-func TestCRLFLineEndings(t *testing.T) {
115497-	for _, tt := range []struct {
115498-		issue, input, want string
115499-	}{
115500-		{
115501-			issue: "41057",
115502-			want: `package main
115503-
115504-/*
115505-Hi description
115506-*/
115507-func Hi() {
115508-}
115509-`,
115510-		},
115511-		{
115512-			issue: "42646",
115513-			want: `package main
115514-
115515-import (
115516-	"fmt"
115517-)
115518-
115519-/*
115520-func upload(c echo.Context) error {
115521-	if err := r.ParseForm(); err != nil {
115522-		fmt.Fprintf(w, "ParseForm() err: %v", err)
115523-		return
115524-	}
115525-	fmt.Fprintf(w, "POST request successful")
115526-	path_ver := r.FormValue("path_ver")
115527-	ukclin_ver := r.FormValue("ukclin_ver")
115528-
115529-	fmt.Fprintf(w, "Name = %s\n", path_ver)
115530-	fmt.Fprintf(w, "Address = %s\n", ukclin_ver)
115531-}
115532-*/
115533-
115534-func main() {
115535-	const server_port = 8080
115536-	fmt.Printf("port: %d\n", server_port)
115537-}
115538-`,
115539-		},
115540-		{
115541-			issue: "42923",
115542-			want: `package main
115543-
115544-// Line 1.
115545-// aa
115546-type Tree struct {
115547-	arr []string
115548-}
115549-`,
115550-		},
115551-		{
115552-			issue: "47200",
115553-			input: `package main
115554-
115555-import "fmt"
115556-
115557-func main() {
115558-	math.Sqrt(9)
115559-	fmt.Println("hello")
115560-}
115561-`,
115562-			want: `package main
115563-
115564-import (
115565-	"fmt"
115566-	"math"
115567-)
115568-
115569-func main() {
115570-	math.Sqrt(9)
115571-	fmt.Println("hello")
115572-}
115573-`,
115574-		},
115575-	} {
115576-		t.Run(tt.issue, func(t *testing.T) {
115577-			Run(t, "-- main.go --", func(t *testing.T, env *Env) {
115578-				input := tt.input
115579-				if input == "" {
115580-					input = tt.want
115581-				}
115582-				crlf := strings.ReplaceAll(input, "\n", "\r\n")
115583-				env.CreateBuffer("main.go", crlf)
115584-				env.Await(env.DoneWithOpen())
115585-				env.OrganizeImports("main.go")
115586-				got := env.BufferText("main.go")
115587-				got = strings.ReplaceAll(got, "\r\n", "\n") // convert everything to LF for simplicity
115588-				if tt.want != got {
115589-					t.Errorf("unexpected content after save:\n%s", compare.Text(tt.want, got))
115590-				}
115591-			})
115592-		})
115593-	}
115594-}
115595-
115596-func TestFormattingOfGeneratedFile_Issue49555(t *testing.T) {
115597-	const input = `
115598--- main.go --
115599-// Code generated by generator.go. DO NOT EDIT.
115600-
115601-package main
115602-
115603-import "fmt"
115604-
115605-func main() {
115606-
115607-
115608-
115609-
115610-	fmt.Print("hello")
115611-}
115612-`
115613-
115614-	Run(t, input, func(t *testing.T, env *Env) {
115615-		wantErrSuffix := "file is generated"
115616-
115617-		env.OpenFile("main.go")
115618-		err := env.Editor.FormatBuffer(env.Ctx, "main.go")
115619-		if err == nil {
115620-			t.Fatal("expected error, got nil")
115621-		}
115622-		// Check only the suffix because an error contains a dynamic path to main.go
115623-		if !strings.HasSuffix(err.Error(), wantErrSuffix) {
115624-			t.Fatalf("unexpected error %q, want suffix %q", err.Error(), wantErrSuffix)
115625-		}
115626-	})
115627-}
115628-
115629-func TestGofumptFormatting(t *testing.T) {
115630-	testenv.NeedsGo1Point(t, 18)
115631-
115632-	// Exercise some gofumpt formatting rules:
115633-	//  - No empty lines following an assignment operator
115634-	//  - Octal integer literals should use the 0o prefix on modules using Go
115635-	//    1.13 and later. Requires LangVersion to be correctly resolved.
115636-	//  - std imports must be in a separate group at the top. Requires ModulePath
115637-	//    to be correctly resolved.
115638-	const input = `
115639--- go.mod --
115640-module foo
115641-
115642-go 1.17
115643--- foo.go --
115644-package foo
115645-
115646-import (
115647-	"foo/bar"
115648-	"fmt"
115649-)
115650-
115651-const perm = 0755
115652-
115653-func foo() {
115654-	foo :=
115655-		"bar"
115656-	fmt.Println(foo, bar.Bar)
115657-}
115658--- foo.go.formatted --
115659-package foo
115660-
115661-import (
115662-	"fmt"
115663-
115664-	"foo/bar"
115665-)
115666-
115667-const perm = 0o755
115668-
115669-func foo() {
115670-	foo := "bar"
115671-	fmt.Println(foo, bar.Bar)
115672-}
115673--- bar/bar.go --
115674-package bar
115675-
115676-const Bar = 42
115677-`
115678-
115679-	WithOptions(
115680-		Settings{
115681-			"gofumpt": true,
115682-		},
115683-	).Run(t, input, func(t *testing.T, env *Env) {
115684-		env.OpenFile("foo.go")
115685-		env.FormatBuffer("foo.go")
115686-		got := env.BufferText("foo.go")
115687-		want := env.ReadWorkspaceFile("foo.go.formatted")
115688-		if got != want {
115689-			t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
115690-		}
115691-	})
115692-}
115693diff -urN a/gopls/internal/regtest/misc/generate_test.go b/gopls/internal/regtest/misc/generate_test.go
115694--- a/gopls/internal/regtest/misc/generate_test.go	2000-01-01 00:00:00.000000000 -0000
115695+++ b/gopls/internal/regtest/misc/generate_test.go	1970-01-01 00:00:00.000000000 +0000
115696@@ -1,72 +0,0 @@
115697-// Copyright 2020 The Go Authors. All rights reserved.
115698-// Use of this source code is governed by a BSD-style
115699-// license that can be found in the LICENSE file.
115700-
115701-// TODO(rfindley): figure out why go generate fails on android builders.
115702-
115703-//go:build !android
115704-// +build !android
115705-
115706-package misc
115707-
115708-import (
115709-	"testing"
115710-
115711-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
115712-)
115713-
115714-func TestGenerateProgress(t *testing.T) {
115715-	const generatedWorkspace = `
115716--- go.mod --
115717-module fake.test
115718-
115719-go 1.14
115720--- generate.go --
115721-// +build ignore
115722-
115723-package main
115724-
115725-import (
115726-	"io/ioutil"
115727-	"os"
115728-)
115729-
115730-func main() {
115731-	ioutil.WriteFile("generated.go", []byte("package " + os.Args[1] + "\n\nconst Answer = 21"), 0644)
115732-}
115733-
115734--- lib1/lib.go --
115735-package lib1
115736-
115737-//` + `go:generate go run ../generate.go lib1
115738-
115739--- lib2/lib.go --
115740-package lib2
115741-
115742-//` + `go:generate go run ../generate.go lib2
115743-
115744--- main.go --
115745-package main
115746-
115747-import (
115748-	"fake.test/lib1"
115749-	"fake.test/lib2"
115750-)
115751-
115752-func main() {
115753-	println(lib1.Answer + lib2.Answer)
115754-}
115755-`
115756-
115757-	Run(t, generatedWorkspace, func(t *testing.T, env *Env) {
115758-		env.OnceMet(
115759-			InitialWorkspaceLoad,
115760-			Diagnostics(env.AtRegexp("main.go", "lib1.(Answer)")),
115761-		)
115762-		env.RunGenerate("./lib1")
115763-		env.RunGenerate("./lib2")
115764-		env.AfterChange(
115765-			NoDiagnostics(ForFile("main.go")),
115766-		)
115767-	})
115768-}
115769diff -urN a/gopls/internal/regtest/misc/highlight_test.go b/gopls/internal/regtest/misc/highlight_test.go
115770--- a/gopls/internal/regtest/misc/highlight_test.go	2000-01-01 00:00:00.000000000 -0000
115771+++ b/gopls/internal/regtest/misc/highlight_test.go	1970-01-01 00:00:00.000000000 +0000
115772@@ -1,153 +0,0 @@
115773-// Copyright 2021 The Go Authors. All rights reserved.
115774-// Use of this source code is governed by a BSD-style
115775-// license that can be found in the LICENSE file.
115776-
115777-package misc
115778-
115779-import (
115780-	"sort"
115781-	"testing"
115782-
115783-	"golang.org/x/tools/gopls/internal/lsp/protocol"
115784-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
115785-)
115786-
115787-func TestWorkspacePackageHighlight(t *testing.T) {
115788-	const mod = `
115789--- go.mod --
115790-module mod.com
115791-
115792-go 1.12
115793--- main.go --
115794-package main
115795-
115796-func main() {
115797-	var A string = "A"
115798-	x := "x-" + A
115799-	println(A, x)
115800-}`
115801-
115802-	Run(t, mod, func(t *testing.T, env *Env) {
115803-		const file = "main.go"
115804-		env.OpenFile(file)
115805-		loc := env.GoToDefinition(env.RegexpSearch(file, `var (A) string`))
115806-
115807-		checkHighlights(env, loc, 3)
115808-	})
115809-}
115810-
115811-func TestStdPackageHighlight_Issue43511(t *testing.T) {
115812-	const mod = `
115813--- go.mod --
115814-module mod.com
115815-
115816-go 1.12
115817--- main.go --
115818-package main
115819-
115820-import "fmt"
115821-
115822-func main() {
115823-	fmt.Printf()
115824-}`
115825-
115826-	Run(t, mod, func(t *testing.T, env *Env) {
115827-		env.OpenFile("main.go")
115828-		defLoc := env.GoToDefinition(env.RegexpSearch("main.go", `fmt\.(Printf)`))
115829-		file := env.Sandbox.Workdir.URIToPath(defLoc.URI)
115830-		loc := env.RegexpSearch(file, `func Printf\((format) string`)
115831-
115832-		checkHighlights(env, loc, 2)
115833-	})
115834-}
115835-
115836-func TestThirdPartyPackageHighlight_Issue43511(t *testing.T) {
115837-	const proxy = `
115838--- [email protected]/go.mod --
115839-module example.com
115840-
115841-go 1.12
115842--- [email protected]/global/global.go --
115843-package global
115844-
115845-const A = 1
115846-
115847-func foo() {
115848-	_ = A
115849-}
115850-
115851-func bar() int {
115852-	return A + A
115853-}
115854--- [email protected]/local/local.go --
115855-package local
115856-
115857-func foo() int {
115858-	const b = 2
115859-
115860-	return b * b * (b+1) + b
115861-}`
115862-
115863-	const mod = `
115864--- go.mod --
115865-module mod.com
115866-
115867-go 1.12
115868-
115869-require example.com v1.2.3
115870--- go.sum --
115871-example.com v1.2.3 h1:WFzrgiQJwEDJNLDUOV1f9qlasQkvzXf2UNLaNIqbWsI=
115872-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
115873--- main.go --
115874-package main
115875-
115876-import (
115877-	_ "example.com/global"
115878-	_ "example.com/local"
115879-)
115880-
115881-func main() {}`
115882-
115883-	WithOptions(
115884-		ProxyFiles(proxy),
115885-	).Run(t, mod, func(t *testing.T, env *Env) {
115886-		env.OpenFile("main.go")
115887-
115888-		defLoc := env.GoToDefinition(env.RegexpSearch("main.go", `"example.com/global"`))
115889-		file := env.Sandbox.Workdir.URIToPath(defLoc.URI)
115890-		loc := env.RegexpSearch(file, `const (A)`)
115891-		checkHighlights(env, loc, 4)
115892-
115893-		defLoc = env.GoToDefinition(env.RegexpSearch("main.go", `"example.com/local"`))
115894-		file = env.Sandbox.Workdir.URIToPath(defLoc.URI)
115895-		loc = env.RegexpSearch(file, `const (b)`)
115896-		checkHighlights(env, loc, 5)
115897-	})
115898-}
115899-
115900-func checkHighlights(env *Env, loc protocol.Location, highlightCount int) {
115901-	t := env.T
115902-	t.Helper()
115903-
115904-	highlights := env.DocumentHighlight(loc)
115905-	if len(highlights) != highlightCount {
115906-		t.Fatalf("expected %v highlight(s), got %v", highlightCount, len(highlights))
115907-	}
115908-
115909-	references := env.References(loc)
115910-	if len(highlights) != len(references) {
115911-		t.Fatalf("number of highlights and references is expected to be equal: %v != %v", len(highlights), len(references))
115912-	}
115913-
115914-	sort.Slice(highlights, func(i, j int) bool {
115915-		return protocol.CompareRange(highlights[i].Range, highlights[j].Range) < 0
115916-	})
115917-	sort.Slice(references, func(i, j int) bool {
115918-		return protocol.CompareRange(references[i].Range, references[j].Range) < 0
115919-	})
115920-	for i := range highlights {
115921-		if highlights[i].Range != references[i].Range {
115922-			t.Errorf("highlight and reference ranges are expected to be equal: %v != %v", highlights[i].Range, references[i].Range)
115923-		}
115924-	}
115925-}
115926diff -urN a/gopls/internal/regtest/misc/hover_test.go b/gopls/internal/regtest/misc/hover_test.go
115927--- a/gopls/internal/regtest/misc/hover_test.go	2000-01-01 00:00:00.000000000 -0000
115928+++ b/gopls/internal/regtest/misc/hover_test.go	1970-01-01 00:00:00.000000000 +0000
115929@@ -1,384 +0,0 @@
115930-// Copyright 2021 The Go Authors. All rights reserved.
115931-// Use of this source code is governed by a BSD-style
115932-// license that can be found in the LICENSE file.
115933-
115934-package misc
115935-
115936-import (
115937-	"fmt"
115938-	"strings"
115939-	"testing"
115940-
115941-	"golang.org/x/tools/gopls/internal/lsp/fake"
115942-	"golang.org/x/tools/gopls/internal/lsp/protocol"
115943-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
115944-	"golang.org/x/tools/internal/testenv"
115945-)
115946-
115947-func TestHoverUnexported(t *testing.T) {
115948-	const proxy = `
115949--- golang.org/x/structs@v1.0.0/go.mod --
115950-module golang.org/x/structs
115951-
115952-go 1.12
115953-
115954--- golang.org/x/structs@v1.0.0/types.go --
115955-package structs
115956-
115957-type Mixed struct {
115958-	// Exported comment
115959-	Exported   int
115960-	unexported string
115961-}
115962-
115963-func printMixed(m Mixed) {
115964-	println(m)
115965-}
115966-`
115967-	const mod = `
115968--- go.mod --
115969-module mod.com
115970-
115971-go 1.12
115972-
115973-require golang.org/x/structs v1.0.0
115974--- go.sum --
115975-golang.org/x/structs v1.0.0 h1:Ito/a7hBYZaNKShFrZKjfBA/SIPvmBrcPCBWPx5QeKk=
115976-golang.org/x/structs v1.0.0/go.mod h1:47gkSIdo5AaQaWJS0upVORsxfEr1LL1MWv9dmYF3iq4=
115977--- main.go --
115978-package main
115979-
115980-import "golang.org/x/structs"
115981-
115982-func main() {
115983-	var m structs.Mixed
115984-	_ = m.Exported
115985-}
115986-`
115987-
115988-	// TODO: use a nested workspace folder here.
115989-	WithOptions(
115990-		ProxyFiles(proxy),
115991-	).Run(t, mod, func(t *testing.T, env *Env) {
115992-		env.OpenFile("main.go")
115993-		mixedLoc := env.RegexpSearch("main.go", "Mixed")
115994-		got, _ := env.Hover(mixedLoc)
115995-		if !strings.Contains(got.Value, "unexported") {
115996-			t.Errorf("Workspace hover: missing expected field 'unexported'. Got:\n%q", got.Value)
115997-		}
115998-
115999-		cacheLoc := env.GoToDefinition(mixedLoc)
116000-		cacheFile := env.Sandbox.Workdir.URIToPath(cacheLoc.URI)
116001-		argLoc := env.RegexpSearch(cacheFile, "printMixed.*(Mixed)")
116002-		got, _ = env.Hover(argLoc)
116003-		if !strings.Contains(got.Value, "unexported") {
116004-			t.Errorf("Non-workspace hover: missing expected field 'unexported'. Got:\n%q", got.Value)
116005-		}
116006-
116007-		exportedFieldLoc := env.RegexpSearch("main.go", "Exported")
116008-		got, _ = env.Hover(exportedFieldLoc)
116009-		if !strings.Contains(got.Value, "comment") {
116010-			t.Errorf("Workspace hover: missing comment for field 'Exported'. Got:\n%q", got.Value)
116011-		}
116012-	})
116013-}
116014-
116015-func TestHoverIntLiteral(t *testing.T) {
116016-	// TODO(rfindley): this behavior doesn't actually make sense for vars. It is
116017-	// misleading to format their value when it is (of course) variable.
116018-	//
116019-	// Instead, we should allow hovering on numeric literals.
116020-	t.Skip("golang/go#58220: broken due to new hover logic")
116021-
116022-	const source = `
116023--- main.go --
116024-package main
116025-
116026-var (
116027-	bigBin = 0b1001001
116028-)
116029-
116030-var hex = 0xe34e
116031-
116032-func main() {
116033-}
116034-`
116035-	Run(t, source, func(t *testing.T, env *Env) {
116036-		env.OpenFile("main.go")
116037-		hexExpected := "58190"
116038-		got, _ := env.Hover(env.RegexpSearch("main.go", "hex"))
116039-		if got != nil && !strings.Contains(got.Value, hexExpected) {
116040-			t.Errorf("Hover: missing expected field '%s'. Got:\n%q", hexExpected, got.Value)
116041-		}
116042-
116043-		binExpected := "73"
116044-		got, _ = env.Hover(env.RegexpSearch("main.go", "bigBin"))
116045-		if got != nil && !strings.Contains(got.Value, binExpected) {
116046-			t.Errorf("Hover: missing expected field '%s'. Got:\n%q", binExpected, got.Value)
116047-		}
116048-	})
116049-}
116050-
116051-// Tests that hovering does not trigger the panic in golang/go#48249.
116052-func TestPanicInHoverBrokenCode(t *testing.T) {
116053-	// Note: this test can not be expressed as a marker test, as it must use
116054-	// content without a trailing newline.
116055-	const source = `
116056--- main.go --
116057-package main
116058-
116059-type Example struct`
116060-	Run(t, source, func(t *testing.T, env *Env) {
116061-		env.OpenFile("main.go")
116062-		env.Editor.Hover(env.Ctx, env.RegexpSearch("main.go", "Example"))
116063-	})
116064-}
116065-
116066-func TestHoverRune_48492(t *testing.T) {
116067-	const files = `
116068--- go.mod --
116069-module mod.com
116070-
116071-go 1.18
116072--- main.go --
116073-package main
116074-`
116075-	Run(t, files, func(t *testing.T, env *Env) {
116076-		env.OpenFile("main.go")
116077-		env.EditBuffer("main.go", fake.NewEdit(0, 0, 1, 0, "package main\nfunc main() {\nconst x = `\nfoo\n`\n}"))
116078-		env.Editor.Hover(env.Ctx, env.RegexpSearch("main.go", "foo"))
116079-	})
116080-}
116081-
116082-func TestHoverImport(t *testing.T) {
116083-	const packageDoc1 = "Package lib1 hover documentation"
116084-	const packageDoc2 = "Package lib2 hover documentation"
116085-	tests := []struct {
116086-		hoverPackage string
116087-		want         string
116088-		wantError    bool
116089-	}{
116090-		{
116091-			"mod.com/lib1",
116092-			packageDoc1,
116093-			false,
116094-		},
116095-		{
116096-			"mod.com/lib2",
116097-			packageDoc2,
116098-			false,
116099-		},
116100-		{
116101-			"mod.com/lib3",
116102-			"",
116103-			false,
116104-		},
116105-		{
116106-			"mod.com/lib4",
116107-			"",
116108-			true,
116109-		},
116110-	}
116111-	source := fmt.Sprintf(`
116112--- go.mod --
116113-module mod.com
116114-
116115-go 1.12
116116--- lib1/a.go --
116117-// %s
116118-package lib1
116119-
116120-const C = 1
116121-
116122--- lib1/b.go --
116123-package lib1
116124-
116125-const D = 1
116126-
116127--- lib2/a.go --
116128-// %s
116129-package lib2
116130-
116131-const E = 1
116132-
116133--- lib3/a.go --
116134-package lib3
116135-
116136-const F = 1
116137-
116138--- main.go --
116139-package main
116140-
116141-import (
116142-	"mod.com/lib1"
116143-	"mod.com/lib2"
116144-	"mod.com/lib3"
116145-	"mod.com/lib4"
116146-)
116147-
116148-func main() {
116149-	println("Hello")
116150-}
116151-	`, packageDoc1, packageDoc2)
116152-	Run(t, source, func(t *testing.T, env *Env) {
116153-		env.OpenFile("main.go")
116154-		for _, test := range tests {
116155-			got, _, err := env.Editor.Hover(env.Ctx, env.RegexpSearch("main.go", test.hoverPackage))
116156-			if test.wantError {
116157-				if err == nil {
116158-					t.Errorf("Hover(%q) succeeded unexpectedly", test.hoverPackage)
116159-				}
116160-			} else if !strings.Contains(got.Value, test.want) {
116161-				t.Errorf("Hover(%q): got:\n%q\nwant:\n%q", test.hoverPackage, got.Value, test.want)
116162-			}
116163-		}
116164-	})
116165-}
116166-
116167-// for x/tools/gopls: unhandled named anchor on the hover #57048
116168-func TestHoverTags(t *testing.T) {
116169-	const source = `
116170--- go.mod --
116171-module mod.com
116172-
116173-go 1.19
116174-
116175--- lib/a.go --
116176-
116177-// variety of execution modes.
116178-//
116179-// # Test package setup
116180-//
116181-// The regression test package uses a couple of uncommon patterns to reduce
116182-package lib
116183-
116184--- a.go --
116185-	package main
116186-	import "mod.com/lib"
116187-
116188-	const A = 1
116189-
116190-}
116191-`
116192-	Run(t, source, func(t *testing.T, env *Env) {
116193-		t.Run("tags", func(t *testing.T) {
116194-			env.OpenFile("a.go")
116195-			z := env.RegexpSearch("a.go", "lib")
116196-			t.Logf("%#v", z)
116197-			got, _ := env.Hover(env.RegexpSearch("a.go", "lib"))
116198-			if strings.Contains(got.Value, "{#hdr-") {
116199-				t.Errorf("Hover: got {#hdr- tag:\n%q", got)
116200-			}
116201-		})
116202-	})
116203-}
116204-
116205-// This is a regression test for Go issue #57625.
116206-func TestHoverModMissingModuleStmt(t *testing.T) {
116207-	const source = `
116208--- go.mod --
116209-go 1.16
116210-`
116211-	Run(t, source, func(t *testing.T, env *Env) {
116212-		env.OpenFile("go.mod")
116213-		env.Hover(env.RegexpSearch("go.mod", "go")) // no panic
116214-	})
116215-}
116216-
116217-func TestHoverCompletionMarkdown(t *testing.T) {
116218-	testenv.NeedsGo1Point(t, 19)
116219-	const source = `
116220--- go.mod --
116221-module mod.com
116222-go 1.19
116223--- main.go --
116224-package main
116225-// Just says [hello].
116226-//
116227-// [hello]: https://en.wikipedia.org/wiki/Hello
116228-func Hello() string {
116229-	Hello() //Here
116230-    return "hello"
116231-}
116232-`
116233-	Run(t, source, func(t *testing.T, env *Env) {
116234-		// Hover, Completion, and SignatureHelp should all produce markdown
116235-		// check that the markdown for SignatureHelp and Completion are
116236-		// the same, and contained in that for Hover (up to trailing \n)
116237-		env.OpenFile("main.go")
116238-		loc := env.RegexpSearch("main.go", "func (Hello)")
116239-		hover, _ := env.Hover(loc)
116240-		hoverContent := hover.Value
116241-
116242-		loc = env.RegexpSearch("main.go", "//Here")
116243-		loc.Range.Start.Character -= 3 // Hello(_) //Here
116244-		completions := env.Completion(loc)
116245-		signatures := env.SignatureHelp(loc)
116246-
116247-		if len(completions.Items) != 1 {
116248-			t.Errorf("got %d completions, expected 1", len(completions.Items))
116249-		}
116250-		if len(signatures.Signatures) != 1 {
116251-			t.Errorf("got %d signatures, expected 1", len(signatures.Signatures))
116252-		}
116253-		item := completions.Items[0].Documentation.Value
116254-		var itemContent string
116255-		if x, ok := item.(protocol.MarkupContent); !ok || x.Kind != protocol.Markdown {
116256-			t.Fatalf("%#v is not markdown", item)
116257-		} else {
116258-			itemContent = strings.Trim(x.Value, "\n")
116259-		}
116260-		sig := signatures.Signatures[0].Documentation.Value
116261-		var sigContent string
116262-		if x, ok := sig.(protocol.MarkupContent); !ok || x.Kind != protocol.Markdown {
116263-			t.Fatalf("%#v is not markdown", item)
116264-		} else {
116265-			sigContent = x.Value
116266-		}
116267-		if itemContent != sigContent {
116268-			t.Errorf("item:%q not sig:%q", itemContent, sigContent)
116269-		}
116270-		if !strings.Contains(hoverContent, itemContent) {
116271-			t.Errorf("hover:%q does not containt sig;%q", hoverContent, sigContent)
116272-		}
116273-	})
116274-}
116275-
116276-// Test that the generated markdown contains links for Go references.
116277-// https://github.com/golang/go/issues/58352
116278-func TestHoverLinks(t *testing.T) {
116279-	testenv.NeedsGo1Point(t, 19)
116280-	const input = `
116281--- go.mod --
116282-go 1.19
116283-module mod.com
116284--- main.go --
116285-package main
116286-// [fmt]
116287-var A int
116288-// [fmt.Println]
116289-var B int
116290-// [golang.org/x/tools/go/packages.Package.String]
116291-var C int
116292-`
116293-	var tests = []struct {
116294-		pat string
116295-		ans string
116296-	}{
116297-		{"A", "fmt"},
116298-		{"B", "fmt#Println"},
116299-		{"C", "golang.org/x/tools/go/packages#Package.String"},
116300-	}
116301-	for _, test := range tests {
116302-		Run(t, input, func(t *testing.T, env *Env) {
116303-			env.OpenFile("main.go")
116304-			loc := env.RegexpSearch("main.go", test.pat)
116305-			hover, _ := env.Hover(loc)
116306-			hoverContent := hover.Value
116307-			want := fmt.Sprintf("%s/%s", "https://pkg.go.dev", test.ans)
116308-			if !strings.Contains(hoverContent, want) {
116309-				t.Errorf("hover:%q does not contain link %q", hoverContent, want)
116310-			}
116311-		})
116312-	}
116313-}
116314diff -urN a/gopls/internal/regtest/misc/imports_test.go b/gopls/internal/regtest/misc/imports_test.go
116315--- a/gopls/internal/regtest/misc/imports_test.go	2000-01-01 00:00:00.000000000 -0000
116316+++ b/gopls/internal/regtest/misc/imports_test.go	1970-01-01 00:00:00.000000000 +0000
116317@@ -1,258 +0,0 @@
116318-// Copyright 2020 The Go Authors. All rights reserved.
116319-// Use of this source code is governed by a BSD-style
116320-// license that can be found in the LICENSE file.
116321-
116322-package misc
116323-
116324-import (
116325-	"io/ioutil"
116326-	"os"
116327-	"path/filepath"
116328-	"strings"
116329-	"testing"
116330-
116331-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
116332-
116333-	"golang.org/x/tools/gopls/internal/lsp/protocol"
116334-	"golang.org/x/tools/internal/testenv"
116335-)
116336-
116337-// Tests golang/go#38815.
116338-func TestIssue38815(t *testing.T) {
116339-	const needs = `
116340--- go.mod --
116341-module foo
116342-
116343-go 1.12
116344--- a.go --
116345-package main
116346-func f() {}
116347-`
116348-	const ntest = `package main
116349-func TestZ(t *testing.T) {
116350-	f()
116351-}
116352-`
116353-	const want = `package main
116354-
116355-import "testing"
116356-
116357-func TestZ(t *testing.T) {
116358-	f()
116359-}
116360-`
116361-
116362-	// it was returning
116363-	// "package main\nimport \"testing\"\npackage main..."
116364-	Run(t, needs, func(t *testing.T, env *Env) {
116365-		env.CreateBuffer("a_test.go", ntest)
116366-		env.SaveBuffer("a_test.go")
116367-		got := env.BufferText("a_test.go")
116368-		if want != got {
116369-			t.Errorf("got\n%q, wanted\n%q", got, want)
116370-		}
116371-	})
116372-}
116373-
116374-func TestVim1(t *testing.T) {
116375-	const vim1 = `package main
116376-
116377-import "fmt"
116378-
116379-var foo = 1
116380-var bar = 2
116381-
116382-func main() {
116383-	fmt.Printf("This is a test %v\n", foo)
116384-	fmt.Printf("This is another test %v\n", foo)
116385-	fmt.Printf("This is also a test %v\n", foo)
116386-}
116387-`
116388-
116389-	// The file remains unchanged, but if there are any CodeActions returned, they confuse vim.
116390-	// Therefore check for no CodeActions
116391-	Run(t, "", func(t *testing.T, env *Env) {
116392-		env.CreateBuffer("main.go", vim1)
116393-		env.OrganizeImports("main.go")
116394-		actions := env.CodeAction("main.go", nil)
116395-		if len(actions) > 0 {
116396-			got := env.BufferText("main.go")
116397-			t.Errorf("unexpected actions %#v", actions)
116398-			if got == vim1 {
116399-				t.Errorf("no changes")
116400-			} else {
116401-				t.Errorf("got\n%q", got)
116402-				t.Errorf("was\n%q", vim1)
116403-			}
116404-		}
116405-	})
116406-}
116407-
116408-func TestVim2(t *testing.T) {
116409-	const vim2 = `package main
116410-
116411-import (
116412-	"fmt"
116413-
116414-	"example.com/blah"
116415-
116416-	"rubbish.com/useless"
116417-)
116418-
116419-func main() {
116420-	fmt.Println(blah.Name, useless.Name)
116421-}
116422-`
116423-
116424-	Run(t, "", func(t *testing.T, env *Env) {
116425-		env.CreateBuffer("main.go", vim2)
116426-		env.OrganizeImports("main.go")
116427-		actions := env.CodeAction("main.go", nil)
116428-		if len(actions) > 0 {
116429-			t.Errorf("unexpected actions %#v", actions)
116430-		}
116431-	})
116432-}
116433-
116434-func TestGOMODCACHE(t *testing.T) {
116435-	const proxy = `
116436--- [email protected]/go.mod --
116437-module example.com
116438-
116439-go 1.12
116440--- [email protected]/x/x.go --
116441-package x
116442-
116443-const X = 1
116444--- [email protected]/y/y.go --
116445-package y
116446-
116447-const Y = 2
116448-`
116449-	const files = `
116450--- go.mod --
116451-module mod.com
116452-
116453-go 1.12
116454-
116455-require example.com v1.2.3
116456--- go.sum --
116457-example.com v1.2.3 h1:6vTQqzX+pnwngZF1+5gcO3ZEWmix1jJ/h+pWS8wUxK0=
116458-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
116459--- main.go --
116460-package main
116461-
116462-import "example.com/x"
116463-
116464-var _, _ = x.X, y.Y
116465-`
116466-	modcache, err := ioutil.TempDir("", "TestGOMODCACHE-modcache")
116467-	if err != nil {
116468-		t.Fatal(err)
116469-	}
116470-	defer os.RemoveAll(modcache)
116471-	WithOptions(
116472-		EnvVars{"GOMODCACHE": modcache},
116473-		ProxyFiles(proxy),
116474-	).Run(t, files, func(t *testing.T, env *Env) {
116475-		env.OpenFile("main.go")
116476-		env.AfterChange(Diagnostics(env.AtRegexp("main.go", `y.Y`)))
116477-		env.SaveBuffer("main.go")
116478-		env.AfterChange(NoDiagnostics(ForFile("main.go")))
116479-		loc := env.GoToDefinition(env.RegexpSearch("main.go", `y.(Y)`))
116480-		path := env.Sandbox.Workdir.URIToPath(loc.URI)
116481-		if !strings.HasPrefix(path, filepath.ToSlash(modcache)) {
116482-			t.Errorf("found module dependency outside of GOMODCACHE: got %v, wanted subdir of %v", path, filepath.ToSlash(modcache))
116483-		}
116484-	})
116485-}
116486-
116487-// Tests golang/go#40685.
116488-func TestAcceptImportsQuickFixTestVariant(t *testing.T) {
116489-	const pkg = `
116490--- go.mod --
116491-module mod.com
116492-
116493-go 1.12
116494--- a/a.go --
116495-package a
116496-
116497-import (
116498-	"fmt"
116499-)
116500-
116501-func _() {
116502-	fmt.Println("")
116503-	os.Stat("")
116504-}
116505--- a/a_test.go --
116506-package a
116507-
116508-import (
116509-	"os"
116510-	"testing"
116511-)
116512-
116513-func TestA(t *testing.T) {
116514-	os.Stat("")
116515-}
116516-`
116517-	Run(t, pkg, func(t *testing.T, env *Env) {
116518-		env.OpenFile("a/a.go")
116519-		var d protocol.PublishDiagnosticsParams
116520-		env.AfterChange(
116521-			Diagnostics(env.AtRegexp("a/a.go", "os.Stat")),
116522-			ReadDiagnostics("a/a.go", &d),
116523-		)
116524-		env.ApplyQuickFixes("a/a.go", d.Diagnostics)
116525-		env.AfterChange(
116526-			NoDiagnostics(ForFile("a/a.go")),
116527-		)
116528-	})
116529-}
116530-
116531-// Test for golang/go#52784
116532-func TestGoWorkImports(t *testing.T) {
116533-	testenv.NeedsGo1Point(t, 18)
116534-	const pkg = `
116535--- go.work --
116536-go 1.19
116537-
116538-use (
116539-        ./caller
116540-        ./mod
116541-)
116542--- caller/go.mod --
116543-module caller.com
116544-
116545-go 1.18
116546-
116547-require mod.com v0.0.0
116548-
116549-replace mod.com => ../mod
116550--- caller/caller.go --
116551-package main
116552-
116553-func main() {
116554-        a.Test()
116555-}
116556--- mod/go.mod --
116557-module mod.com
116558-
116559-go 1.18
116560--- mod/a/a.go --
116561-package a
116562-
116563-func Test() {
116564-}
116565-`
116566-	Run(t, pkg, func(t *testing.T, env *Env) {
116567-		env.OpenFile("caller/caller.go")
116568-		env.AfterChange(Diagnostics(env.AtRegexp("caller/caller.go", "a.Test")))
116569-
116570-		// Saving caller.go should trigger goimports, which should find a.Test in
116571-		// the mod.com module, thanks to the go.work file.
116572-		env.SaveBuffer("caller/caller.go")
116573-		env.AfterChange(NoDiagnostics(ForFile("caller/caller.go")))
116574-	})
116575-}
116576diff -urN a/gopls/internal/regtest/misc/import_test.go b/gopls/internal/regtest/misc/import_test.go
116577--- a/gopls/internal/regtest/misc/import_test.go	2000-01-01 00:00:00.000000000 -0000
116578+++ b/gopls/internal/regtest/misc/import_test.go	1970-01-01 00:00:00.000000000 +0000
116579@@ -1,133 +0,0 @@
116580-// Copyright 2021 The Go Authors. All rights reserved.
116581-// Use of this source code is governed by a BSD-style
116582-// license that can be found in the LICENSE file.
116583-
116584-package misc
116585-
116586-import (
116587-	"testing"
116588-
116589-	"github.com/google/go-cmp/cmp"
116590-	"golang.org/x/tools/gopls/internal/lsp/command"
116591-	"golang.org/x/tools/gopls/internal/lsp/protocol"
116592-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
116593-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
116594-)
116595-
116596-func TestAddImport(t *testing.T) {
116597-	const before = `package main
116598-
116599-import "fmt"
116600-
116601-func main() {
116602-	fmt.Println("hello world")
116603-}
116604-`
116605-
116606-	const want = `package main
116607-
116608-import (
116609-	"bytes"
116610-	"fmt"
116611-)
116612-
116613-func main() {
116614-	fmt.Println("hello world")
116615-}
116616-`
116617-
116618-	Run(t, "", func(t *testing.T, env *Env) {
116619-		env.CreateBuffer("main.go", before)
116620-		cmd, err := command.NewAddImportCommand("Add Import", command.AddImportArgs{
116621-			URI:        env.Sandbox.Workdir.URI("main.go"),
116622-			ImportPath: "bytes",
116623-		})
116624-		if err != nil {
116625-			t.Fatal(err)
116626-		}
116627-		env.ExecuteCommand(&protocol.ExecuteCommandParams{
116628-			Command:   "gopls.add_import",
116629-			Arguments: cmd.Arguments,
116630-		}, nil)
116631-		got := env.BufferText("main.go")
116632-		if got != want {
116633-			t.Fatalf("gopls.add_import failed\n%s", compare.Text(want, got))
116634-		}
116635-	})
116636-}
116637-
116638-func TestListImports(t *testing.T) {
116639-	const files = `
116640--- go.mod --
116641-module mod.com
116642-
116643-go 1.12
116644--- foo.go --
116645-package foo
116646-const C = 1
116647--- import_strings_test.go --
116648-package foo
116649-import (
116650-	x "strings"
116651-	"testing"
116652-)
116653-
116654-func TestFoo(t *testing.T) {}
116655--- import_testing_test.go --
116656-package foo
116657-
116658-import "testing"
116659-
116660-func TestFoo2(t *testing.T) {}
116661-`
116662-	tests := []struct {
116663-		filename string
116664-		want     command.ListImportsResult
116665-	}{
116666-		{
116667-			filename: "import_strings_test.go",
116668-			want: command.ListImportsResult{
116669-				Imports: []command.FileImport{
116670-					{Name: "x", Path: "strings"},
116671-					{Path: "testing"},
116672-				},
116673-				PackageImports: []command.PackageImport{
116674-					{Path: "strings"},
116675-					{Path: "testing"},
116676-				},
116677-			},
116678-		},
116679-		{
116680-			filename: "import_testing_test.go",
116681-			want: command.ListImportsResult{
116682-				Imports: []command.FileImport{
116683-					{Path: "testing"},
116684-				},
116685-				PackageImports: []command.PackageImport{
116686-					{Path: "strings"},
116687-					{Path: "testing"},
116688-				},
116689-			},
116690-		},
116691-	}
116692-
116693-	Run(t, files, func(t *testing.T, env *Env) {
116694-		for _, tt := range tests {
116695-			cmd, err := command.NewListImportsCommand("List Imports", command.URIArg{
116696-				URI: env.Sandbox.Workdir.URI(tt.filename),
116697-			})
116698-			if err != nil {
116699-				t.Fatal(err)
116700-			}
116701-			var result command.ListImportsResult
116702-			env.ExecuteCommand(&protocol.ExecuteCommandParams{
116703-				Command:   command.ListImports.ID(),
116704-				Arguments: cmd.Arguments,
116705-			}, &result)
116706-			if diff := cmp.Diff(tt.want, result); diff != "" {
116707-				t.Errorf("unexpected list imports result for %q (-want +got):\n%s", tt.filename, diff)
116708-			}
116709-		}
116710-
116711-	})
116712-}
116713diff -urN a/gopls/internal/regtest/misc/leak_test.go b/gopls/internal/regtest/misc/leak_test.go
116714--- a/gopls/internal/regtest/misc/leak_test.go	2000-01-01 00:00:00.000000000 -0000
116715+++ b/gopls/internal/regtest/misc/leak_test.go	1970-01-01 00:00:00.000000000 +0000
116716@@ -1,89 +0,0 @@
116717-// Copyright 2022 The Go Authors. All rights reserved.
116718-// Use of this source code is governed by a BSD-style
116719-// license that can be found in the LICENSE file.
116720-
116721-package misc
116722-
116723-import (
116724-	"context"
116725-	"testing"
116726-
116727-	"github.com/google/go-cmp/cmp"
116728-	"golang.org/x/tools/gopls/internal/hooks"
116729-	"golang.org/x/tools/gopls/internal/lsp/cache"
116730-	"golang.org/x/tools/gopls/internal/lsp/debug"
116731-	"golang.org/x/tools/gopls/internal/lsp/fake"
116732-	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
116733-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
116734-	"golang.org/x/tools/internal/jsonrpc2"
116735-	"golang.org/x/tools/internal/jsonrpc2/servertest"
116736-)
116737-
116738-// Test for golang/go#57222.
116739-func TestCacheLeak(t *testing.T) {
116740-	// TODO(rfindley): either fix this test with additional instrumentation, or
116741-	// delete it.
116742-	t.Skip("This test races with cache eviction.")
116743-	const files = `-- a.go --
116744-package a
116745-
116746-func _() {
116747-	println("1")
116748-}
116749-`
116750-	c := cache.New(nil)
116751-	env := setupEnv(t, files, c)
116752-	env.Await(InitialWorkspaceLoad)
116753-	env.OpenFile("a.go")
116754-
116755-	// Make a couple edits to stabilize cache state.
116756-	//
116757-	// For some reason, after only one edit we're left with two parsed files
116758-	// (perhaps because something had to ParseHeader). If this test proves flaky,
116759-	// we'll need to investigate exactly what is causing various parse modes to
116760-	// be present (or rewrite the test to be more tolerant, for example make ~100
116761-	// modifications and assert that we're within a few of where we're started).
116762-	env.RegexpReplace("a.go", "1", "2")
116763-	env.RegexpReplace("a.go", "2", "3")
116764-	env.AfterChange()
116765-
116766-	// Capture cache state, make an arbitrary change, and wait for gopls to do
116767-	// its work. Afterward, we should have the exact same number of parsed
116768-	before := c.MemStats()
116769-	env.RegexpReplace("a.go", "3", "4")
116770-	env.AfterChange()
116771-	after := c.MemStats()
116772-
116773-	if diff := cmp.Diff(before, after); diff != "" {
116774-		t.Errorf("store objects differ after change (-before +after)\n%s", diff)
116775-	}
116776-}
116777-
116778-// setupEnv creates a new sandbox environment for editing the txtar encoded
116779-// content of files. It uses a new gopls instance backed by the Cache c.
116780-func setupEnv(t *testing.T, files string, c *cache.Cache) *Env {
116781-	ctx := debug.WithInstance(context.Background(), "", "off")
116782-	server := lsprpc.NewStreamServer(c, false, hooks.Options)
116783-	ts := servertest.NewPipeServer(server, jsonrpc2.NewRawStream)
116784-	s, err := fake.NewSandbox(&fake.SandboxConfig{
116785-		Files: fake.UnpackTxt(files),
116786-	})
116787-	if err != nil {
116788-		t.Fatal(err)
116789-	}
116790-
116791-	a := NewAwaiter(s.Workdir)
116792-	const skipApplyEdits = false
116793-	editor, err := fake.NewEditor(s, fake.EditorConfig{}).Connect(ctx, ts, a.Hooks(), skipApplyEdits)
116794-	if err != nil {
116795-		t.Fatal(err)
116796-	}
116797-
116798-	return &Env{
116799-		T:       t,
116800-		Ctx:     ctx,
116801-		Editor:  editor,
116802-		Sandbox: s,
116803-		Awaiter: a,
116804-	}
116805-}
116806diff -urN a/gopls/internal/regtest/misc/link_test.go b/gopls/internal/regtest/misc/link_test.go
116807--- a/gopls/internal/regtest/misc/link_test.go	2000-01-01 00:00:00.000000000 -0000
116808+++ b/gopls/internal/regtest/misc/link_test.go	1970-01-01 00:00:00.000000000 +0000
116809@@ -1,96 +0,0 @@
116810-// Copyright 2020 The Go Authors. All rights reserved.
116811-// Use of this source code is governed by a BSD-style
116812-// license that can be found in the LICENSE file.
116813-
116814-package misc
116815-
116816-import (
116817-	"strings"
116818-	"testing"
116819-
116820-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
116821-)
116822-
116823-func TestHoverAndDocumentLink(t *testing.T) {
116824-	const program = `
116825--- go.mod --
116826-module mod.test
116827-
116828-go 1.12
116829-
116830-require import.test v1.2.3
116831--- go.sum --
116832-import.test v1.2.3 h1:Mu4N9BICLJFxwwn8YNg6T3frkFWW1O7evXvo0HiRjBc=
116833-import.test v1.2.3/go.mod h1:KooCN1g237upRg7irU7F+3oADn5tVClU8YYW4I1xhMk=
116834--- main.go --
116835-package main
116836-
116837-import "import.test/pkg"
116838-
116839-func main() {
116840-	// Issue 43990: this is not a link that most users can open from an LSP
116841-	// client: mongodb://not.a.link.com
116842-	println(pkg.Hello)
116843-}`
116844-
116845-	const proxy = `
116846--- [email protected]/go.mod --
116847-module import.test
116848-
116849-go 1.12
116850--- [email protected]/pkg/const.go --
116851-package pkg
116852-
116853-const Hello = "Hello"
116854-`
116855-	WithOptions(
116856-		ProxyFiles(proxy),
116857-	).Run(t, program, func(t *testing.T, env *Env) {
116858-		env.OpenFile("main.go")
116859-		env.OpenFile("go.mod")
116860-
116861-		modLink := "https://pkg.go.dev/mod/[email protected]"
116862-		pkgLink := "https://pkg.go.dev/[email protected]/pkg"
116863-
116864-		// First, check that we get the expected links via hover and documentLink.
116865-		content, _ := env.Hover(env.RegexpSearch("main.go", "pkg.Hello"))
116866-		if content == nil || !strings.Contains(content.Value, pkgLink) {
116867-			t.Errorf("hover: got %v in main.go, want contains %q", content, pkgLink)
116868-		}
116869-		content, _ = env.Hover(env.RegexpSearch("go.mod", "import.test"))
116870-		if content == nil || !strings.Contains(content.Value, pkgLink) {
116871-			t.Errorf("hover: got %v in go.mod, want contains %q", content, pkgLink)
116872-		}
116873-		links := env.DocumentLink("main.go")
116874-		if len(links) != 1 || links[0].Target != pkgLink {
116875-			t.Errorf("documentLink: got links %+v for main.go, want one link with target %q", links, pkgLink)
116876-		}
116877-		links = env.DocumentLink("go.mod")
116878-		if len(links) != 1 || links[0].Target != modLink {
116879-			t.Errorf("documentLink: got links %+v for go.mod, want one link with target %q", links, modLink)
116880-		}
116881-
116882-		// Then change the environment to make these links private.
116883-		cfg := env.Editor.Config()
116884-		cfg.Env = map[string]string{"GOPRIVATE": "import.test"}
116885-		env.ChangeConfiguration(cfg)
116886-
116887-		// Finally, verify that the links are gone.
116888-		content, _ = env.Hover(env.RegexpSearch("main.go", "pkg.Hello"))
116889-		if content == nil || strings.Contains(content.Value, pkgLink) {
116890-			t.Errorf("hover: got %v in main.go, want non-empty hover without %q", content, pkgLink)
116891-		}
116892-		content, _ = env.Hover(env.RegexpSearch("go.mod", "import.test"))
116893-		if content == nil || strings.Contains(content.Value, modLink) {
116894-			t.Errorf("hover: got %v in go.mod, want contains %q", content, modLink)
116895-		}
116896-		links = env.DocumentLink("main.go")
116897-		if len(links) != 0 {
116898-			t.Errorf("documentLink: got %d document links for main.go, want 0\nlinks: %v", len(links), links)
116899-		}
116900-		links = env.DocumentLink("go.mod")
116901-		if len(links) != 0 {
116902-			t.Errorf("documentLink: got %d document links for go.mod, want 0\nlinks: %v", len(links), links)
116903-		}
116904-	})
116905-}
116906diff -urN a/gopls/internal/regtest/misc/misc_test.go b/gopls/internal/regtest/misc/misc_test.go
116907--- a/gopls/internal/regtest/misc/misc_test.go	2000-01-01 00:00:00.000000000 -0000
116908+++ b/gopls/internal/regtest/misc/misc_test.go	1970-01-01 00:00:00.000000000 +0000
116909@@ -1,18 +0,0 @@
116910-// Copyright 2020 The Go Authors. All rights reserved.
116911-// Use of this source code is governed by a BSD-style
116912-// license that can be found in the LICENSE file.
116913-
116914-package misc
116915-
116916-import (
116917-	"testing"
116918-
116919-	"golang.org/x/tools/gopls/internal/hooks"
116920-	"golang.org/x/tools/gopls/internal/lsp/regtest"
116921-	"golang.org/x/tools/internal/bug"
116922-)
116923-
116924-func TestMain(m *testing.M) {
116925-	bug.PanicOnBugs = true
116926-	regtest.Main(m, hooks.Options)
116927-}
116928diff -urN a/gopls/internal/regtest/misc/multiple_adhoc_test.go b/gopls/internal/regtest/misc/multiple_adhoc_test.go
116929--- a/gopls/internal/regtest/misc/multiple_adhoc_test.go	2000-01-01 00:00:00.000000000 -0000
116930+++ b/gopls/internal/regtest/misc/multiple_adhoc_test.go	1970-01-01 00:00:00.000000000 +0000
116931@@ -1,44 +0,0 @@
116932-// Copyright 2021 The Go Authors. All rights reserved.
116933-// Use of this source code is governed by a BSD-style
116934-// license that can be found in the LICENSE file.
116935-
116936-package misc
116937-
116938-import (
116939-	"testing"
116940-
116941-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
116942-)
116943-
116944-func TestMultipleAdHocPackages(t *testing.T) {
116945-	Run(t, `
116946--- a/a.go --
116947-package main
116948-
116949-import "fmt"
116950-
116951-func main() {
116952-	fmt.Println("")
116953-}
116954--- a/b.go --
116955-package main
116956-
116957-import "fmt"
116958-
116959-func main() () {
116960-	fmt.Println("")
116961-}
116962-`, func(t *testing.T, env *Env) {
116963-		env.OpenFile("a/a.go")
116964-		if list := env.Completion(env.RegexpSearch("a/a.go", "Println")); list == nil || len(list.Items) == 0 {
116965-			t.Fatal("expected completions, got none")
116966-		}
116967-		env.OpenFile("a/b.go")
116968-		if list := env.Completion(env.RegexpSearch("a/b.go", "Println")); list == nil || len(list.Items) == 0 {
116969-			t.Fatal("expected completions, got none")
116970-		}
116971-		if list := env.Completion(env.RegexpSearch("a/a.go", "Println")); list == nil || len(list.Items) == 0 {
116972-			t.Fatal("expected completions, got none")
116973-		}
116974-	})
116975-}
116976diff -urN a/gopls/internal/regtest/misc/references_test.go b/gopls/internal/regtest/misc/references_test.go
116977--- a/gopls/internal/regtest/misc/references_test.go	2000-01-01 00:00:00.000000000 -0000
116978+++ b/gopls/internal/regtest/misc/references_test.go	1970-01-01 00:00:00.000000000 +0000
116979@@ -1,399 +0,0 @@
116980-// Copyright 2020 The Go Authors. All rights reserved.
116981-// Use of this source code is governed by a BSD-style
116982-// license that can be found in the LICENSE file.
116983-
116984-package misc
116985-
116986-import (
116987-	"fmt"
116988-	"os"
116989-	"sort"
116990-	"strings"
116991-	"testing"
116992-
116993-	"github.com/google/go-cmp/cmp"
116994-	"golang.org/x/tools/gopls/internal/lsp/protocol"
116995-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
116996-)
116997-
116998-func TestStdlibReferences(t *testing.T) {
116999-	const files = `
117000--- go.mod --
117001-module mod.com
117002-
117003-go 1.12
117004--- main.go --
117005-package main
117006-
117007-import "fmt"
117008-
117009-func main() {
117010-	fmt.Print()
117011-}
117012-`
117013-
117014-	Run(t, files, func(t *testing.T, env *Env) {
117015-		env.OpenFile("main.go")
117016-		loc := env.GoToDefinition(env.RegexpSearch("main.go", `fmt.(Print)`))
117017-		refs, err := env.Editor.References(env.Ctx, loc)
117018-		if err != nil {
117019-			t.Fatal(err)
117020-		}
117021-		if len(refs) != 2 {
117022-			// TODO(adonovan): make this assertion less maintainer-hostile.
117023-			t.Fatalf("got %v reference(s), want 2", len(refs))
117024-		}
117025-		// The first reference is guaranteed to be the definition.
117026-		if got, want := refs[1].URI, env.Sandbox.Workdir.URI("main.go"); got != want {
117027-			t.Errorf("found reference in %v, wanted %v", got, want)
117028-		}
117029-	})
117030-}
117031-
117032-// This is a regression test for golang/go#48400 (a panic).
117033-func TestReferencesOnErrorMethod(t *testing.T) {
117034-	// Ideally this would actually return the correct answer,
117035-	// instead of merely failing gracefully.
117036-	const files = `
117037--- go.mod --
117038-module mod.com
117039-
117040-go 1.12
117041--- main.go --
117042-package main
117043-
117044-type t interface {
117045-	error
117046-}
117047-
117048-type s struct{}
117049-
117050-func (*s) Error() string {
117051-	return ""
117052-}
117053-
117054-func _() {
117055-	var s s
117056-	_ = s.Error()
117057-}
117058-`
117059-	Run(t, files, func(t *testing.T, env *Env) {
117060-		env.OpenFile("main.go")
117061-		loc := env.GoToDefinition(env.RegexpSearch("main.go", `Error`))
117062-		refs, err := env.Editor.References(env.Ctx, loc)
117063-		if err != nil {
117064-			t.Fatalf("references on (*s).Error failed: %v", err)
117065-		}
117066-		// TODO(adonovan): this test is crying out for marker support in regtests.
117067-		var buf strings.Builder
117068-		for _, ref := range refs {
117069-			fmt.Fprintf(&buf, "%s %s\n", env.Sandbox.Workdir.URIToPath(ref.URI), ref.Range)
117070-		}
117071-		got := buf.String()
117072-		want := "main.go 8:10-8:15\n" + // (*s).Error decl
117073-			"main.go 14:7-14:12\n" // s.Error() call
117074-		if diff := cmp.Diff(want, got); diff != "" {
117075-			t.Errorf("unexpected references on (*s).Error (-want +got):\n%s", diff)
117076-		}
117077-	})
117078-}
117079-
117080-func TestPackageReferences(t *testing.T) {
117081-	tests := []struct {
117082-		packageName  string
117083-		wantRefCount int
117084-		wantFiles    []string
117085-	}{
117086-		{
117087-			"lib1",
117088-			3,
117089-			[]string{
117090-				"main.go",
117091-				"lib1/a.go",
117092-				"lib1/b.go",
117093-			},
117094-		},
117095-		{
117096-			"lib2",
117097-			2,
117098-			[]string{
117099-				"main.go",
117100-				"lib2/a.go",
117101-			},
117102-		},
117103-	}
117104-
117105-	const files = `
117106--- go.mod --
117107-module mod.com
117108-
117109-go 1.18
117110--- lib1/a.go --
117111-package lib1
117112-
117113-const A = 1
117114-
117115--- lib1/b.go --
117116-package lib1
117117-
117118-const B = 1
117119-
117120--- lib2/a.go --
117121-package lib2
117122-
117123-const C = 1
117124-
117125--- main.go --
117126-package main
117127-
117128-import (
117129-	"mod.com/lib1"
117130-	"mod.com/lib2"
117131-)
117132-
117133-func main() {
117134-	println("Hello")
117135-}
117136-`
117137-	Run(t, files, func(t *testing.T, env *Env) {
117138-		for _, test := range tests {
117139-			file := fmt.Sprintf("%s/a.go", test.packageName)
117140-			env.OpenFile(file)
117141-			loc := env.RegexpSearch(file, test.packageName)
117142-			refs := env.References(loc)
117143-			if len(refs) != test.wantRefCount {
117144-				// TODO(adonovan): make this assertion less maintainer-hostile.
117145-				t.Fatalf("got %v reference(s), want %d", len(refs), test.wantRefCount)
117146-			}
117147-			var refURIs []string
117148-			for _, ref := range refs {
117149-				refURIs = append(refURIs, string(ref.URI))
117150-			}
117151-			for _, base := range test.wantFiles {
117152-				hasBase := false
117153-				for _, ref := range refURIs {
117154-					if strings.HasSuffix(ref, base) {
117155-						hasBase = true
117156-						break
117157-					}
117158-				}
117159-				if !hasBase {
117160-					t.Fatalf("got [%v], want reference ends with \"%v\"", strings.Join(refURIs, ","), base)
117161-				}
117162-			}
117163-		}
117164-	})
117165-}
117166-
117167-// Test for golang/go#43144.
117168-//
117169-// Verify that we search for references and implementations in intermediate
117170-// test variants.
117171-func TestReferencesInTestVariants(t *testing.T) {
117172-	const files = `
117173--- go.mod --
117174-module foo.mod
117175-
117176-go 1.12
117177--- foo/foo.go --
117178-package foo
117179-
117180-import "foo.mod/bar"
117181-
117182-const Foo = 42
117183-
117184-type T int
117185-type InterfaceM interface{ M() }
117186-type InterfaceF interface{ F() }
117187-
117188-func _() {
117189-	_ = bar.Blah
117190-}
117191-
117192--- foo/foo_test.go --
117193-package foo
117194-
117195-type Fer struct{}
117196-func (Fer) F() {}
117197-
117198--- bar/bar.go --
117199-package bar
117200-
117201-var Blah = 123
117202-
117203--- bar/bar_test.go --
117204-package bar
117205-
117206-type Mer struct{}
117207-func (Mer) M() {}
117208-
117209-func TestBar() {
117210-	_ = Blah
117211-}
117212--- bar/bar_x_test.go --
117213-package bar_test
117214-
117215-import (
117216-	"foo.mod/bar"
117217-	"foo.mod/foo"
117218-)
117219-
117220-type Mer struct{}
117221-func (Mer) M() {}
117222-
117223-func _() {
117224-	_ = bar.Blah
117225-	_ = foo.Foo
117226-}
117227-`
117228-
117229-	Run(t, files, func(t *testing.T, env *Env) {
117230-		env.OpenFile("foo/foo.go")
117231-
117232-		// Helper to map locations relative file paths.
117233-		fileLocations := func(locs []protocol.Location) []string {
117234-			var got []string
117235-			for _, loc := range locs {
117236-				got = append(got, env.Sandbox.Workdir.URIToPath(loc.URI))
117237-			}
117238-			sort.Strings(got)
117239-			return got
117240-		}
117241-
117242-		refTests := []struct {
117243-			re       string
117244-			wantRefs []string
117245-		}{
117246-			// Blah is referenced:
117247-			// - inside the foo.mod/bar (ordinary) package
117248-			// - inside the foo.mod/bar [foo.mod/bar.test] test variant package
117249-			// - from the foo.mod/bar_test [foo.mod/bar.test] x_test package
117250-			// - from the foo.mod/foo package
117251-			{"Blah", []string{"bar/bar.go", "bar/bar_test.go", "bar/bar_x_test.go", "foo/foo.go"}},
117252-
117253-			// Foo is referenced in bar_x_test.go via the intermediate test variant
117254-			// foo.mod/foo [foo.mod/bar.test].
117255-			{"Foo", []string{"bar/bar_x_test.go", "foo/foo.go"}},
117256-		}
117257-
117258-		for _, test := range refTests {
117259-			loc := env.RegexpSearch("foo/foo.go", test.re)
117260-			refs := env.References(loc)
117261-
117262-			got := fileLocations(refs)
117263-			if diff := cmp.Diff(test.wantRefs, got); diff != "" {
117264-				t.Errorf("References(%q) returned unexpected diff (-want +got):\n%s", test.re, diff)
117265-			}
117266-		}
117267-
117268-		implTests := []struct {
117269-			re        string
117270-			wantImpls []string
117271-		}{
117272-			// InterfaceM is implemented both in foo.mod/bar [foo.mod/bar.test] (which
117273-			// doesn't import foo), and in foo.mod/bar_test [foo.mod/bar.test], which
117274-			// imports the test variant of foo.
117275-			{"InterfaceM", []string{"bar/bar_test.go", "bar/bar_x_test.go"}},
117276-
117277-			// A search within the ordinary package to should find implementations
117278-			// (Fer) within the augmented test package.
117279-			{"InterfaceF", []string{"foo/foo_test.go"}},
117280-		}
117281-
117282-		for _, test := range implTests {
117283-			loc := env.RegexpSearch("foo/foo.go", test.re)
117284-			impls := env.Implementations(loc)
117285-
117286-			got := fileLocations(impls)
117287-			if diff := cmp.Diff(test.wantImpls, got); diff != "" {
117288-				t.Errorf("Implementations(%q) returned unexpected diff (-want +got):\n%s", test.re, diff)
117289-			}
117290-		}
117291-	})
117292-}
117293-
117294-// This is a regression test for Issue #56169, in which interface
117295-// implementations in vendored modules were not found. The actual fix
117296-// was the same as for #55995; see TestVendoringInvalidatesMetadata.
117297-func TestImplementationsInVendor(t *testing.T) {
117298-	t.Skip("golang/go#56169: file watching does not capture vendor dirs")
117299-
117300-	const proxy = `
117301--- other.com/[email protected]/go.mod --
117302-module other.com/b
117303-go 1.14
117304-
117305--- other.com/[email protected]/b.go --
117306-package b
117307-type B int
117308-func (B) F() {}
117309-`
117310-	const src = `
117311--- go.mod --
117312-module example.com/a
117313-go 1.14
117314-require other.com/b v1.0.0
117315-
117316--- go.sum --
117317-other.com/b v1.0.0 h1:9WyCKS+BLAMRQM0CegP6zqP2beP+ShTbPaARpNY31II=
117318-other.com/b v1.0.0/go.mod h1:TgHQFucl04oGT+vrUm/liAzukYHNxCwKNkQZEyn3m9g=
117319-
117320--- a.go --
117321-package a
117322-import "other.com/b"
117323-type I interface { F() }
117324-var _ b.B
117325-
117326-`
117327-	WithOptions(
117328-		ProxyFiles(proxy),
117329-		Modes(Default), // fails in 'experimental' mode
117330-	).Run(t, src, func(t *testing.T, env *Env) {
117331-		// Enable to debug go.sum mismatch, which may appear as
117332-		// "module lookup disabled by GOPROXY=off", confusingly.
117333-		if false {
117334-			env.DumpGoSum(".")
117335-		}
117336-
117337-		checkVendor := func(locs []protocol.Location, wantVendor bool) {
117338-			if len(locs) != 1 {
117339-				t.Errorf("got %d locations, want 1", len(locs))
117340-			} else if strings.Contains(string(locs[0].URI), "/vendor/") != wantVendor {
117341-				t.Errorf("got location %s, wantVendor=%t", locs[0], wantVendor)
117342-			}
117343-		}
117344-
117345-		env.OpenFile("a.go")
117346-		refLoc := env.RegexpSearch("a.go", "I") // find "I" reference
117347-
117348-		// Initially, a.I has one implementation b.B in
117349-		// the module cache, not the vendor tree.
117350-		checkVendor(env.Implementations(refLoc), false)
117351-
117352-		// Run 'go mod vendor' outside the editor.
117353-		if err := env.Sandbox.RunGoCommand(env.Ctx, ".", "mod", []string{"vendor"}, true); err != nil {
117354-			t.Fatalf("go mod vendor: %v", err)
117355-		}
117356-
117357-		// Synchronize changes to watched files.
117358-		env.Await(env.DoneWithChangeWatchedFiles())
117359-
117360-		// Now, b.B is found in the vendor tree.
117361-		checkVendor(env.Implementations(refLoc), true)
117362-
117363-		// Delete the vendor tree.
117364-		if err := os.RemoveAll(env.Sandbox.Workdir.AbsPath("vendor")); err != nil {
117365-			t.Fatal(err)
117366-		}
117367-		// Notify the server of the deletion.
117368-		if err := env.Sandbox.Workdir.CheckForFileChanges(env.Ctx); err != nil {
117369-			t.Fatal(err)
117370-		}
117371-
117372-		// Synchronize again.
117373-		env.Await(env.DoneWithChangeWatchedFiles())
117374-
117375-		// b.B is once again defined in the module cache.
117376-		checkVendor(env.Implementations(refLoc), false)
117377-	})
117378-}
117379diff -urN a/gopls/internal/regtest/misc/rename_test.go b/gopls/internal/regtest/misc/rename_test.go
117380--- a/gopls/internal/regtest/misc/rename_test.go	2000-01-01 00:00:00.000000000 -0000
117381+++ b/gopls/internal/regtest/misc/rename_test.go	1970-01-01 00:00:00.000000000 +0000
117382@@ -1,935 +0,0 @@
117383-// Copyright 2021 The Go Authors. All rights reserved.
117384-// Use of this source code is governed by a BSD-style
117385-// license that can be found in the LICENSE file.
117386-
117387-package misc
117388-
117389-import (
117390-	"fmt"
117391-	"strings"
117392-	"testing"
117393-
117394-	"golang.org/x/tools/gopls/internal/lsp/protocol"
117395-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
117396-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
117397-	"golang.org/x/tools/internal/testenv"
117398-)
117399-
117400-func TestPrepareRenameMainPackage(t *testing.T) {
117401-	const files = `
117402--- go.mod --
117403-module mod.com
117404-
117405-go 1.18
117406--- main.go --
117407-package main
117408-
117409-import (
117410-	"fmt"
117411-)
117412-
117413-func main() {
117414-	fmt.Println(1)
117415-}
117416-`
117417-	const wantErr = "can't rename package \"main\""
117418-	Run(t, files, func(t *testing.T, env *Env) {
117419-		env.OpenFile("main.go")
117420-		loc := env.RegexpSearch("main.go", `main`)
117421-		params := &protocol.PrepareRenameParams{
117422-			TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
117423-		}
117424-		_, err := env.Editor.Server.PrepareRename(env.Ctx, params)
117425-		if err == nil {
117426-			t.Errorf("missing can't rename package main error from PrepareRename")
117427-		}
117428-
117429-		if err.Error() != wantErr {
117430-			t.Errorf("got %v, want %v", err.Error(), wantErr)
117431-		}
117432-	})
117433-}
117434-
117435-// Test case for golang/go#56227
117436-func TestRenameWithUnsafeSlice(t *testing.T) {
117437-	testenv.NeedsGo1Point(t, 17) // unsafe.Slice was added in Go 1.17
117438-	const files = `
117439--- go.mod --
117440-module mod.com
117441-
117442-go 1.18
117443--- p.go --
117444-package p
117445-
117446-import "unsafe"
117447-
117448-type T struct{}
117449-
117450-func (T) M() {}
117451-
117452-func _() {
117453-	x := [3]int{1, 2, 3}
117454-	ptr := unsafe.Pointer(&x)
117455-	_ = unsafe.Slice((*int)(ptr), 3)
117456-}
117457-`
117458-
117459-	Run(t, files, func(t *testing.T, env *Env) {
117460-		env.OpenFile("p.go")
117461-		env.Rename(env.RegexpSearch("p.go", "M"), "N") // must not panic
117462-	})
117463-}
117464-
117465-func TestPrepareRenameWithNoPackageDeclaration(t *testing.T) {
117466-	const files = `
117467-go 1.14
117468--- lib/a.go --
117469-import "fmt"
117470-
117471-const A = 1
117472-
117473-func bar() {
117474-	fmt.Println("Bar")
117475-}
117476-
117477--- main.go --
117478-package main
117479-
117480-import "fmt"
117481-
117482-func main() {
117483-	fmt.Println("Hello")
117484-}
117485-`
117486-	Run(t, files, func(t *testing.T, env *Env) {
117487-		env.OpenFile("lib/a.go")
117488-		err := env.Editor.Rename(env.Ctx, env.RegexpSearch("lib/a.go", "fmt"), "fmt1")
117489-		if got, want := fmt.Sprint(err), "no identifier found"; got != want {
117490-			t.Errorf("Rename: got error %v, want %v", got, want)
117491-		}
117492-	})
117493-}
117494-
117495-func TestPrepareRenameFailWithUnknownModule(t *testing.T) {
117496-	testenv.NeedsGo1Point(t, 17)
117497-	const files = `
117498-go 1.14
117499--- lib/a.go --
117500-package lib
117501-
117502-const A = 1
117503-
117504--- main.go --
117505-package main
117506-
117507-import (
117508-	"mod.com/lib"
117509-)
117510-
117511-func main() {
117512-	println("Hello")
117513-}
117514-`
117515-	const wantErr = "can't rename package: missing module information for package"
117516-	Run(t, files, func(t *testing.T, env *Env) {
117517-		loc := env.RegexpSearch("lib/a.go", "lib")
117518-		params := &protocol.PrepareRenameParams{
117519-			TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
117520-		}
117521-		_, err := env.Editor.Server.PrepareRename(env.Ctx, params)
117522-		if err == nil || !strings.Contains(err.Error(), wantErr) {
117523-			t.Errorf("missing cannot rename packages with unknown module from PrepareRename")
117524-		}
117525-	})
117526-}
117527-
117528-// This test ensures that each import of a renamed package
117529-// is also renamed if it would otherwise create a conflict.
117530-func TestRenamePackageWithConflicts(t *testing.T) {
117531-	testenv.NeedsGo1Point(t, 17)
117532-	const files = `
117533--- go.mod --
117534-module mod.com
117535-
117536-go 1.18
117537--- lib/a.go --
117538-package lib
117539-
117540-const A = 1
117541-
117542--- lib/nested/a.go --
117543-package nested
117544-
117545-const B = 1
117546-
117547--- lib/x/a.go --
117548-package nested1
117549-
117550-const C = 1
117551-
117552--- main.go --
117553-package main
117554-
117555-import (
117556-	"mod.com/lib"
117557-	"mod.com/lib/nested"
117558-	nested1 "mod.com/lib/x"
117559-)
117560-
117561-func main() {
117562-	println("Hello")
117563-}
117564-`
117565-	Run(t, files, func(t *testing.T, env *Env) {
117566-		env.OpenFile("lib/a.go")
117567-		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "nested")
117568-
117569-		// Check if the new package name exists.
117570-		env.RegexpSearch("nested/a.go", "package nested")
117571-		env.RegexpSearch("main.go", `nested2 "mod.com/nested"`)
117572-		env.RegexpSearch("main.go", "mod.com/nested/nested")
117573-		env.RegexpSearch("main.go", `nested1 "mod.com/nested/x"`)
117574-	})
117575-}
117576-
117577-func TestRenamePackageWithAlias(t *testing.T) {
117578-	testenv.NeedsGo1Point(t, 17)
117579-	const files = `
117580--- go.mod --
117581-module mod.com
117582-
117583-go 1.18
117584--- lib/a.go --
117585-package lib
117586-
117587-const A = 1
117588-
117589--- lib/nested/a.go --
117590-package nested
117591-
117592-const B = 1
117593-
117594--- main.go --
117595-package main
117596-
117597-import (
117598-	"mod.com/lib"
117599-	lib1 "mod.com/lib/nested"
117600-)
117601-
117602-func main() {
117603-	println("Hello")
117604-}
117605-`
117606-	Run(t, files, func(t *testing.T, env *Env) {
117607-		env.OpenFile("lib/a.go")
117608-		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "nested")
117609-
117610-		// Check if the new package name exists.
117611-		env.RegexpSearch("nested/a.go", "package nested")
117612-		env.RegexpSearch("main.go", "mod.com/nested")
117613-		env.RegexpSearch("main.go", `lib1 "mod.com/nested/nested"`)
117614-	})
117615-}
117616-
117617-func TestRenamePackageWithDifferentDirectoryPath(t *testing.T) {
117618-	testenv.NeedsGo1Point(t, 17)
117619-	const files = `
117620--- go.mod --
117621-module mod.com
117622-
117623-go 1.18
117624--- lib/a.go --
117625-package lib
117626-
117627-const A = 1
117628-
117629--- lib/nested/a.go --
117630-package foo
117631-
117632-const B = 1
117633-
117634--- main.go --
117635-package main
117636-
117637-import (
117638-	"mod.com/lib"
117639-	foo "mod.com/lib/nested"
117640-)
117641-
117642-func main() {
117643-	println("Hello")
117644-}
117645-`
117646-	Run(t, files, func(t *testing.T, env *Env) {
117647-		env.OpenFile("lib/a.go")
117648-		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "nested")
117649-
117650-		// Check if the new package name exists.
117651-		env.RegexpSearch("nested/a.go", "package nested")
117652-		env.RegexpSearch("main.go", "mod.com/nested")
117653-		env.RegexpSearch("main.go", `foo "mod.com/nested/nested"`)
117654-	})
117655-}
117656-
117657-func TestRenamePackage(t *testing.T) {
117658-	testenv.NeedsGo1Point(t, 17)
117659-	const files = `
117660--- go.mod --
117661-module mod.com
117662-
117663-go 1.18
117664--- lib/a.go --
117665-package lib
117666-
117667-const A = 1
117668-
117669--- lib/b.go --
117670-package lib
117671-
117672-const B = 1
117673-
117674--- lib/nested/a.go --
117675-package nested
117676-
117677-const C = 1
117678-
117679--- main.go --
117680-package main
117681-
117682-import (
117683-	"mod.com/lib"
117684-	"mod.com/lib/nested"
117685-)
117686-
117687-func main() {
117688-	println("Hello")
117689-}
117690-`
117691-	Run(t, files, func(t *testing.T, env *Env) {
117692-		env.OpenFile("lib/a.go")
117693-		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "lib1")
117694-
117695-		// Check if the new package name exists.
117696-		env.RegexpSearch("lib1/a.go", "package lib1")
117697-		env.RegexpSearch("lib1/b.go", "package lib1")
117698-		env.RegexpSearch("main.go", "mod.com/lib1")
117699-		env.RegexpSearch("main.go", "mod.com/lib1/nested")
117700-	})
117701-}
117702-
117703-// Test for golang/go#47564.
117704-func TestRenameInTestVariant(t *testing.T) {
117705-	const files = `
117706--- go.mod --
117707-module mod.com
117708-
117709-go 1.12
117710--- stringutil/stringutil.go --
117711-package stringutil
117712-
117713-func Identity(s string) string {
117714-	return s
117715-}
117716--- stringutil/stringutil_test.go --
117717-package stringutil
117718-
117719-func TestIdentity(t *testing.T) {
117720-	if got := Identity("foo"); got != "foo" {
117721-		t.Errorf("bad")
117722-	}
117723-}
117724--- main.go --
117725-package main
117726-
117727-import (
117728-	"fmt"
117729-
117730-	"mod.com/stringutil"
117731-)
117732-
117733-func main() {
117734-	fmt.Println(stringutil.Identity("hello world"))
117735-}
117736-`
117737-
117738-	Run(t, files, func(t *testing.T, env *Env) {
117739-		env.OpenFile("main.go")
117740-		env.Rename(env.RegexpSearch("main.go", `stringutil\.(Identity)`), "Identityx")
117741-		env.OpenFile("stringutil/stringutil_test.go")
117742-		text := env.BufferText("stringutil/stringutil_test.go")
117743-		if !strings.Contains(text, "Identityx") {
117744-			t.Errorf("stringutil/stringutil_test.go: missing expected token `Identityx` after rename:\n%s", text)
117745-		}
117746-	})
117747-}
117748-
117749-// This is a test that rename operation initiated by the editor function as expected.
117750-func TestRenameFileFromEditor(t *testing.T) {
117751-	const files = `
117752--- go.mod --
117753-module mod.com
117754-
117755-go 1.16
117756--- a/a.go --
117757-package a
117758-
117759-const X = 1
117760--- a/x.go --
117761-package a
117762-
117763-const X = 2
117764--- b/b.go --
117765-package b
117766-`
117767-
117768-	Run(t, files, func(t *testing.T, env *Env) {
117769-		// Rename files and verify that diagnostics are affected accordingly.
117770-
117771-		// Initially, we should have diagnostics on both X's, for their duplicate declaration.
117772-		env.OnceMet(
117773-			InitialWorkspaceLoad,
117774-			Diagnostics(env.AtRegexp("a/a.go", "X")),
117775-			Diagnostics(env.AtRegexp("a/x.go", "X")),
117776-		)
117777-
117778-		// Moving x.go should make the diagnostic go away.
117779-		env.RenameFile("a/x.go", "b/x.go")
117780-		env.AfterChange(
117781-			NoDiagnostics(ForFile("a/a.go")),               // no more duplicate declarations
117782-			Diagnostics(env.AtRegexp("b/b.go", "package")), // as package names mismatch
117783-		)
117784-
117785-		// Renaming should also work on open buffers.
117786-		env.OpenFile("b/x.go")
117787-
117788-		// Moving x.go back to a/ should cause the diagnostics to reappear.
117789-		env.RenameFile("b/x.go", "a/x.go")
117790-		env.AfterChange(
117791-			Diagnostics(env.AtRegexp("a/a.go", "X")),
117792-			Diagnostics(env.AtRegexp("a/x.go", "X")),
117793-		)
117794-
117795-		// Renaming the entire directory should move both the open and closed file.
117796-		env.RenameFile("a", "x")
117797-		env.AfterChange(
117798-			Diagnostics(env.AtRegexp("x/a.go", "X")),
117799-			Diagnostics(env.AtRegexp("x/x.go", "X")),
117800-		)
117801-
117802-		// As a sanity check, verify that x/x.go is open.
117803-		if text := env.BufferText("x/x.go"); text == "" {
117804-			t.Fatal("got empty buffer for x/x.go")
117805-		}
117806-	})
117807-}
117808-
117809-func TestRenamePackage_Tests(t *testing.T) {
117810-	testenv.NeedsGo1Point(t, 17)
117811-	const files = `
117812--- go.mod --
117813-module mod.com
117814-
117815-go 1.18
117816--- lib/a.go --
117817-package lib
117818-
117819-const A = 1
117820-
117821--- lib/b.go --
117822-package lib
117823-
117824-const B = 1
117825-
117826--- lib/a_test.go --
117827-package lib_test
117828-
117829-import (
117830-	"mod.com/lib"
117831-	"fmt
117832-)
117833-
117834-const C = 1
117835-
117836--- lib/b_test.go --
117837-package lib
117838-
117839-import (
117840-	"fmt
117841-)
117842-
117843-const D = 1
117844-
117845--- lib/nested/a.go --
117846-package nested
117847-
117848-const D = 1
117849-
117850--- main.go --
117851-package main
117852-
117853-import (
117854-	"mod.com/lib"
117855-	"mod.com/lib/nested"
117856-)
117857-
117858-func main() {
117859-	println("Hello")
117860-}
117861-`
117862-	Run(t, files, func(t *testing.T, env *Env) {
117863-		env.OpenFile("lib/a.go")
117864-		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "lib1")
117865-
117866-		// Check if the new package name exists.
117867-		env.RegexpSearch("lib1/a.go", "package lib1")
117868-		env.RegexpSearch("lib1/b.go", "package lib1")
117869-		env.RegexpSearch("main.go", "mod.com/lib1")
117870-		env.RegexpSearch("main.go", "mod.com/lib1/nested")
117871-
117872-		// Check if the test package is renamed
117873-		env.RegexpSearch("lib1/a_test.go", "package lib1_test")
117874-		env.RegexpSearch("lib1/b_test.go", "package lib1")
117875-	})
117876-}
117877-
117878-func TestRenamePackage_NestedModule(t *testing.T) {
117879-	testenv.NeedsGo1Point(t, 18)
117880-	const files = `
117881--- go.work --
117882-go 1.18
117883-use (
117884-	.
117885-	./foo/bar
117886-	./foo/baz
117887-)
117888-
117889--- go.mod --
117890-module mod.com
117891-
117892-go 1.18
117893-
117894-require (
117895-    mod.com/foo/bar v0.0.0
117896-)
117897-
117898-replace (
117899-	mod.com/foo/bar => ./foo/bar
117900-	mod.com/foo/baz => ./foo/baz
117901-)
117902--- foo/foo.go --
117903-package foo
117904-
117905-import "fmt"
117906-
117907-func Bar() {
117908-	fmt.Println("In foo before renamed to foox.")
117909-}
117910-
117911--- foo/bar/go.mod --
117912-module mod.com/foo/bar
117913-
117914--- foo/bar/bar.go --
117915-package bar
117916-
117917-const Msg = "Hi from package bar"
117918-
117919--- foo/baz/go.mod --
117920-module mod.com/foo/baz
117921-
117922--- foo/baz/baz.go --
117923-package baz
117924-
117925-const Msg = "Hi from package baz"
117926-
117927--- main.go --
117928-package main
117929-
117930-import (
117931-	"fmt"
117932-	"mod.com/foo/bar"
117933-	"mod.com/foo/baz"
117934-	"mod.com/foo"
117935-)
117936-
117937-func main() {
117938-	foo.Bar()
117939-	fmt.Println(bar.Msg)
117940-	fmt.Println(baz.Msg)
117941-}
117942-`
117943-	Run(t, files, func(t *testing.T, env *Env) {
117944-		env.OpenFile("foo/foo.go")
117945-		env.Rename(env.RegexpSearch("foo/foo.go", "foo"), "foox")
117946-
117947-		env.RegexpSearch("foox/foo.go", "package foox")
117948-		env.OpenFile("foox/bar/bar.go")
117949-		env.OpenFile("foox/bar/go.mod")
117950-
117951-		env.RegexpSearch("main.go", "mod.com/foo/bar")
117952-		env.RegexpSearch("main.go", "mod.com/foox")
117953-		env.RegexpSearch("main.go", "foox.Bar()")
117954-
117955-		env.RegexpSearch("go.mod", "./foox/bar")
117956-		env.RegexpSearch("go.mod", "./foox/baz")
117957-	})
117958-}
117959-
117960-func TestRenamePackage_DuplicateImport(t *testing.T) {
117961-	testenv.NeedsGo1Point(t, 17)
117962-	const files = `
117963--- go.mod --
117964-module mod.com
117965-
117966-go 1.18
117967--- lib/a.go --
117968-package lib
117969-
117970-const A = 1
117971-
117972--- lib/nested/a.go --
117973-package nested
117974-
117975-const B = 1
117976-
117977--- main.go --
117978-package main
117979-
117980-import (
117981-	"mod.com/lib"
117982-	lib1 "mod.com/lib"
117983-	lib2 "mod.com/lib/nested"
117984-)
117985-
117986-func main() {
117987-	println("Hello")
117988-}
117989-`
117990-	Run(t, files, func(t *testing.T, env *Env) {
117991-		env.OpenFile("lib/a.go")
117992-		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "nested")
117993-
117994-		// Check if the new package name exists.
117995-		env.RegexpSearch("nested/a.go", "package nested")
117996-		env.RegexpSearch("main.go", "mod.com/nested")
117997-		env.RegexpSearch("main.go", `lib1 "mod.com/nested"`)
117998-		env.RegexpSearch("main.go", `lib2 "mod.com/nested/nested"`)
117999-	})
118000-}
118001-
118002-func TestRenamePackage_DuplicateBlankImport(t *testing.T) {
118003-	testenv.NeedsGo1Point(t, 17)
118004-	const files = `
118005--- go.mod --
118006-module mod.com
118007-
118008-go 1.18
118009--- lib/a.go --
118010-package lib
118011-
118012-const A = 1
118013-
118014--- lib/nested/a.go --
118015-package nested
118016-
118017-const B = 1
118018-
118019--- main.go --
118020-package main
118021-
118022-import (
118023-	"mod.com/lib"
118024-	_ "mod.com/lib"
118025-	lib1 "mod.com/lib/nested"
118026-)
118027-
118028-func main() {
118029-	println("Hello")
118030-}
118031-`
118032-	Run(t, files, func(t *testing.T, env *Env) {
118033-		env.OpenFile("lib/a.go")
118034-		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "nested")
118035-
118036-		// Check if the new package name exists.
118037-		env.RegexpSearch("nested/a.go", "package nested")
118038-		env.RegexpSearch("main.go", "mod.com/nested")
118039-		env.RegexpSearch("main.go", `_ "mod.com/nested"`)
118040-		env.RegexpSearch("main.go", `lib1 "mod.com/nested/nested"`)
118041-	})
118042-}
118043-
118044-func TestRenamePackage_TestVariant(t *testing.T) {
118045-	const files = `
118046--- go.mod --
118047-module mod.com
118048-
118049-go 1.12
118050--- foo/foo.go --
118051-package foo
118052-
118053-const Foo = 42
118054--- bar/bar.go --
118055-package bar
118056-
118057-import "mod.com/foo"
118058-
118059-const Bar = foo.Foo
118060--- bar/bar_test.go --
118061-package bar
118062-
118063-import "mod.com/foo"
118064-
118065-const Baz = foo.Foo
118066--- testdata/bar/bar.go --
118067-package bar
118068-
118069-import "mod.com/foox"
118070-
118071-const Bar = foox.Foo
118072--- testdata/bar/bar_test.go --
118073-package bar
118074-
118075-import "mod.com/foox"
118076-
118077-const Baz = foox.Foo
118078-`
118079-	Run(t, files, func(t *testing.T, env *Env) {
118080-		env.OpenFile("foo/foo.go")
118081-		env.Rename(env.RegexpSearch("foo/foo.go", "package (foo)"), "foox")
118082-
118083-		checkTestdata(t, env)
118084-	})
118085-}
118086-
118087-func TestRenamePackage_IntermediateTestVariant(t *testing.T) {
118088-	// In this test set up, we have the following import edges:
118089-	//   bar_test -> baz -> foo -> bar
118090-	//   bar_test -> foo -> bar
118091-	//   bar_test -> bar
118092-	//
118093-	// As a consequence, bar_x_test.go is in the reverse closure of both
118094-	// `foo [bar.test]` and `baz [bar.test]`. This test confirms that we don't
118095-	// produce duplicate edits in this case.
118096-	const files = `
118097--- go.mod --
118098-module foo.mod
118099-
118100-go 1.12
118101--- foo/foo.go --
118102-package foo
118103-
118104-import "foo.mod/bar"
118105-
118106-const Foo = 42
118107-
118108-const _ = bar.Bar
118109--- baz/baz.go --
118110-package baz
118111-
118112-import "foo.mod/foo"
118113-
118114-const Baz = foo.Foo
118115--- bar/bar.go --
118116-package bar
118117-
118118-var Bar = 123
118119--- bar/bar_test.go --
118120-package bar
118121-
118122-const _ = Bar
118123--- bar/bar_x_test.go --
118124-package bar_test
118125-
118126-import (
118127-	"foo.mod/bar"
118128-	"foo.mod/baz"
118129-	"foo.mod/foo"
118130-)
118131-
118132-const _ = bar.Bar + baz.Baz + foo.Foo
118133--- testdata/foox/foo.go --
118134-package foox
118135-
118136-import "foo.mod/bar"
118137-
118138-const Foo = 42
118139-
118140-const _ = bar.Bar
118141--- testdata/baz/baz.go --
118142-package baz
118143-
118144-import "foo.mod/foox"
118145-
118146-const Baz = foox.Foo
118147--- testdata/bar/bar_x_test.go --
118148-package bar_test
118149-
118150-import (
118151-	"foo.mod/bar"
118152-	"foo.mod/baz"
118153-	"foo.mod/foox"
118154-)
118155-
118156-const _ = bar.Bar + baz.Baz + foox.Foo
118157-`
118158-
118159-	Run(t, files, func(t *testing.T, env *Env) {
118160-		env.OpenFile("foo/foo.go")
118161-		env.Rename(env.RegexpSearch("foo/foo.go", "package (foo)"), "foox")
118162-
118163-		checkTestdata(t, env)
118164-	})
118165-}
118166-
118167-func TestRenamePackage_Nesting(t *testing.T) {
118168-	testenv.NeedsGo1Point(t, 17)
118169-	const files = `
118170--- go.mod --
118171-module mod.com
118172-
118173-go 1.18
118174--- lib/a.go --
118175-package lib
118176-
118177-import "mod.com/lib/nested"
118178-
118179-const A = 1 + nested.B
118180--- lib/nested/a.go --
118181-package nested
118182-
118183-const B = 1
118184--- other/other.go --
118185-package other
118186-
118187-import (
118188-	"mod.com/lib"
118189-	"mod.com/lib/nested"
118190-)
118191-
118192-const C = lib.A + nested.B
118193--- testdata/libx/a.go --
118194-package libx
118195-
118196-import "mod.com/libx/nested"
118197-
118198-const A = 1 + nested.B
118199--- testdata/other/other.go --
118200-package other
118201-
118202-import (
118203-	"mod.com/libx"
118204-	"mod.com/libx/nested"
118205-)
118206-
118207-const C = libx.A + nested.B
118208-`
118209-	Run(t, files, func(t *testing.T, env *Env) {
118210-		env.OpenFile("lib/a.go")
118211-		env.Rename(env.RegexpSearch("lib/a.go", "package (lib)"), "libx")
118212-
118213-		checkTestdata(t, env)
118214-	})
118215-}
118216-
118217-func TestRenamePackage_InvalidName(t *testing.T) {
118218-	testenv.NeedsGo1Point(t, 17)
118219-	const files = `
118220--- go.mod --
118221-module mod.com
118222-
118223-go 1.18
118224--- lib/a.go --
118225-package lib
118226-
118227-import "mod.com/lib/nested"
118228-
118229-const A = 1 + nested.B
118230-`
118231-
118232-	Run(t, files, func(t *testing.T, env *Env) {
118233-		env.OpenFile("lib/a.go")
118234-		loc := env.RegexpSearch("lib/a.go", "package (lib)")
118235-
118236-		for _, badName := range []string{"$$$", "lib_test"} {
118237-			if err := env.Editor.Rename(env.Ctx, loc, badName); err == nil {
118238-				t.Errorf("Rename(lib, libx) succeeded, want non-nil error")
118239-			}
118240-		}
118241-	})
118242-}
118243-
118244-func TestRenamePackage_InternalPackage(t *testing.T) {
118245-	testenv.NeedsGo1Point(t, 17)
118246-	const files = `
118247--- go.mod --
118248-module mod.com
118249-
118250-go 1.18
118251--- lib/a.go --
118252-package lib
118253-
118254-import (
118255-	"fmt"
118256-	"mod.com/lib/internal/x"
118257-)
118258-
118259-const A = 1
118260-
118261-func print() {
118262-	fmt.Println(x.B)
118263-}
118264-
118265--- lib/internal/x/a.go --
118266-package x
118267-
118268-const B = 1
118269-
118270--- main.go --
118271-package main
118272-
118273-import "mod.com/lib"
118274-
118275-func main() {
118276-	lib.print()
118277-}
118278-`
118279-	Run(t, files, func(t *testing.T, env *Env) {
118280-		env.OpenFile("lib/internal/x/a.go")
118281-		env.Rename(env.RegexpSearch("lib/internal/x/a.go", "x"), "utils")
118282-
118283-		// Check if the new package name exists.
118284-		env.RegexpSearch("lib/a.go", "mod.com/lib/internal/utils")
118285-		env.RegexpSearch("lib/a.go", "utils.B")
118286-
118287-		// Check if the test package is renamed
118288-		env.RegexpSearch("lib/internal/utils/a.go", "package utils")
118289-
118290-		env.OpenFile("lib/a.go")
118291-		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "lib1")
118292-
118293-		// Check if the new package name exists.
118294-		env.RegexpSearch("lib1/a.go", "package lib1")
118295-		env.RegexpSearch("lib1/a.go", "mod.com/lib1/internal/utils")
118296-		env.RegexpSearch("main.go", `import "mod.com/lib1"`)
118297-		env.RegexpSearch("main.go", "lib1.print()")
118298-	})
118299-}
118300-
118301-// checkTestdata checks that current buffer contents match their corresponding
118302-// expected content in the testdata directory.
118303-func checkTestdata(t *testing.T, env *Env) {
118304-	t.Helper()
118305-	files := env.ListFiles("testdata")
118306-	if len(files) == 0 {
118307-		t.Fatal("no files in testdata directory")
118308-	}
118309-	for _, file := range files {
118310-		suffix := strings.TrimPrefix(file, "testdata/")
118311-		got := env.BufferText(suffix)
118312-		want := env.ReadWorkspaceFile(file)
118313-		if diff := compare.Text(want, got); diff != "" {
118314-			t.Errorf("Rename: unexpected buffer content for %s (-want +got):\n%s", suffix, diff)
118315-		}
118316-	}
118317-}
118318diff -urN a/gopls/internal/regtest/misc/semantictokens_test.go b/gopls/internal/regtest/misc/semantictokens_test.go
118319--- a/gopls/internal/regtest/misc/semantictokens_test.go	2000-01-01 00:00:00.000000000 -0000
118320+++ b/gopls/internal/regtest/misc/semantictokens_test.go	1970-01-01 00:00:00.000000000 +0000
118321@@ -1,204 +0,0 @@
118322-// Copyright 2021 The Go Authors. All rights reserved.
118323-// Use of this source code is governed by a BSD-style
118324-// license that can be found in the LICENSE file.
118325-
118326-package misc
118327-
118328-import (
118329-	"strings"
118330-	"testing"
118331-
118332-	"github.com/google/go-cmp/cmp"
118333-	"golang.org/x/tools/gopls/internal/lsp"
118334-	"golang.org/x/tools/gopls/internal/lsp/protocol"
118335-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
118336-	"golang.org/x/tools/internal/typeparams"
118337-)
118338-
118339-func TestBadURICrash_VSCodeIssue1498(t *testing.T) {
118340-	const src = `
118341--- go.mod --
118342-module example.com
118343-
118344-go 1.12
118345-
118346--- main.go --
118347-package main
118348-
118349-func main() {}
118350-
118351-`
118352-	WithOptions(
118353-		Modes(Default),
118354-		Settings{"allExperiments": true},
118355-	).Run(t, src, func(t *testing.T, env *Env) {
118356-		params := &protocol.SemanticTokensParams{}
118357-		const badURI = "http://foo"
118358-		params.TextDocument.URI = badURI
118359-		// This call panicked in the past: golang/vscode-go#1498.
118360-		if _, err := env.Editor.Server.SemanticTokensFull(env.Ctx, params); err != nil {
118361-			// Requests to an invalid URI scheme shouldn't result in an error, we
118362-			// simply don't support this so return empty result. This could be
118363-			// changed, but for now assert on the current behavior.
118364-			t.Errorf("SemanticTokensFull(%q): %v", badURI, err)
118365-		}
118366-	})
118367-}
118368-
118369-// fix bug involving type parameters and regular parameters
118370-// (golang/vscode-go#2527)
118371-func TestSemantic_2527(t *testing.T) {
118372-	if !typeparams.Enabled {
118373-		t.Skip("type parameters are needed for this test")
118374-	}
118375-	// these are the expected types of identifiers in text order
118376-	want := []result{
118377-		{"package", "keyword", ""},
118378-		{"foo", "namespace", ""},
118379-		{"func", "keyword", ""},
118380-		{"Add", "function", "definition deprecated"},
118381-		{"T", "typeParameter", "definition"},
118382-		{"int", "type", "defaultLibrary"},
118383-		{"target", "parameter", "definition"},
118384-		{"T", "typeParameter", ""},
118385-		{"l", "parameter", "definition"},
118386-		{"T", "typeParameter", ""},
118387-		{"T", "typeParameter", ""},
118388-		{"return", "keyword", ""},
118389-		{"append", "function", "defaultLibrary"},
118390-		{"l", "parameter", ""},
118391-		{"target", "parameter", ""},
118392-		{"for", "keyword", ""},
118393-		{"range", "keyword", ""},
118394-		{"l", "parameter", ""},
118395-		{"return", "keyword", ""},
118396-		{"nil", "variable", "readonly defaultLibrary"},
118397-	}
118398-	src := `
118399--- go.mod --
118400-module example.com
118401-
118402-go 1.19
118403--- main.go --
118404-package foo
118405-// Deprecated (for testing)
118406-func Add[T int](target T, l []T) []T {
118407-	return append(l, target)
118408-	for range l {} // test coverage
118409-	return nil
118410-}
118411-`
118412-	WithOptions(
118413-		Modes(Default),
118414-		Settings{"semanticTokens": true},
118415-	).Run(t, src, func(t *testing.T, env *Env) {
118416-		env.OpenFile("main.go")
118417-		env.AfterChange(
118418-			Diagnostics(env.AtRegexp("main.go", "for range")),
118419-		)
118420-		p := &protocol.SemanticTokensParams{
118421-			TextDocument: protocol.TextDocumentIdentifier{
118422-				URI: env.Sandbox.Workdir.URI("main.go"),
118423-			},
118424-		}
118425-		v, err := env.Editor.Server.SemanticTokensFull(env.Ctx, p)
118426-		if err != nil {
118427-			t.Fatal(err)
118428-		}
118429-		seen := interpret(v.Data, env.BufferText("main.go"))
118430-		if x := cmp.Diff(want, seen); x != "" {
118431-			t.Errorf("Semantic tokens do not match (-want +got):\n%s", x)
118432-		}
118433-	})
118434-
118435-}
118436-
118437-// fix inconsistency in TypeParameters
118438-// https://github.com/golang/go/issues/57619
118439-func TestSemantic_57619(t *testing.T) {
118440-	if !typeparams.Enabled {
118441-		t.Skip("type parameters are needed for this test")
118442-	}
118443-	src := `
118444--- go.mod --
118445-module example.com
118446-
118447-go 1.19
118448--- main.go --
118449-package foo
118450-type Smap[K int, V any] struct {
118451-	Store map[K]V
118452-}
118453-func (s *Smap[K, V]) Get(k K) (V, bool) {
118454-	v, ok := s.Store[k]
118455-	return v, ok
118456-}
118457-func New[K int, V any]() Smap[K, V] {
118458-	return Smap[K, V]{Store: make(map[K]V)}
118459-}
118460-`
118461-	WithOptions(
118462-		Modes(Default),
118463-		Settings{"semanticTokens": true},
118464-	).Run(t, src, func(t *testing.T, env *Env) {
118465-		env.OpenFile("main.go")
118466-		p := &protocol.SemanticTokensParams{
118467-			TextDocument: protocol.TextDocumentIdentifier{
118468-				URI: env.Sandbox.Workdir.URI("main.go"),
118469-			},
118470-		}
118471-		v, err := env.Editor.Server.SemanticTokensFull(env.Ctx, p)
118472-		if err != nil {
118473-			t.Fatal(err)
118474-		}
118475-		seen := interpret(v.Data, env.BufferText("main.go"))
118476-		for i, s := range seen {
118477-			if (s.Token == "K" || s.Token == "V") && s.TokenType != "typeParameter" {
118478-				t.Errorf("%d: expected K and V to be type parameters, but got %v", i, s)
118479-			}
118480-		}
118481-	})
118482-}
118483-
118484-type result struct {
118485-	Token     string
118486-	TokenType string
118487-	Mod       string
118488-}
118489-
118490-// human-readable version of the semantic tokens
118491-// comment, string, number are elided
118492-// (and in the future, maybe elide other things, like operators)
118493-func interpret(x []uint32, contents string) []result {
118494-	lines := strings.Split(contents, "\n")
118495-	ans := []result{}
118496-	line, col := 1, 1
118497-	for i := 0; i < len(x); i += 5 {
118498-		line += int(x[i])
118499-		col += int(x[i+1])
118500-		if x[i] != 0 { // new line
118501-			col = int(x[i+1]) + 1 // 1-based column numbers
118502-		}
118503-		sz := x[i+2]
118504-		t := semanticTypes[x[i+3]]
118505-		if t == "comment" || t == "string" || t == "number" {
118506-			continue
118507-		}
118508-		l := x[i+4]
118509-		var mods []string
118510-		for i, mod := range semanticModifiers {
118511-			if l&(1<<i) != 0 {
118512-				mods = append(mods, mod)
118513-			}
118514-		}
118515-		// col is a utf-8 offset
118516-		tok := lines[line-1][col-1 : col-1+int(sz)]
118517-		ans = append(ans, result{tok, t, strings.Join(mods, " ")})
118518-	}
118519-	return ans
118520-}
118521-
118522-var (
118523-	semanticTypes     = lsp.SemanticTypes()
118524-	semanticModifiers = lsp.SemanticModifiers()
118525-)
118526diff -urN a/gopls/internal/regtest/misc/settings_test.go b/gopls/internal/regtest/misc/settings_test.go
118527--- a/gopls/internal/regtest/misc/settings_test.go	2000-01-01 00:00:00.000000000 -0000
118528+++ b/gopls/internal/regtest/misc/settings_test.go	1970-01-01 00:00:00.000000000 +0000
118529@@ -1,32 +0,0 @@
118530-// Copyright 2022 The Go Authors. All rights reserved.
118531-// Use of this source code is governed by a BSD-style
118532-// license that can be found in the LICENSE file.
118533-
118534-package misc
118535-
118536-import (
118537-	"testing"
118538-
118539-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
118540-)
118541-
118542-func TestEmptyDirectoryFilters_Issue51843(t *testing.T) {
118543-	const src = `
118544--- go.mod --
118545-module mod.com
118546-
118547-go 1.12
118548--- main.go --
118549-package main
118550-
118551-func main() {
118552-}
118553-`
118554-
118555-	WithOptions(
118556-		Settings{"directoryFilters": []string{""}},
118557-	).Run(t, src, func(t *testing.T, env *Env) {
118558-		// No need to do anything. Issue golang/go#51843 is triggered by the empty
118559-		// directory filter above.
118560-	})
118561-}
118562diff -urN a/gopls/internal/regtest/misc/shared_test.go b/gopls/internal/regtest/misc/shared_test.go
118563--- a/gopls/internal/regtest/misc/shared_test.go	2000-01-01 00:00:00.000000000 -0000
118564+++ b/gopls/internal/regtest/misc/shared_test.go	1970-01-01 00:00:00.000000000 +0000
118565@@ -1,72 +0,0 @@
118566-// Copyright 2020 The Go Authors. All rights reserved.
118567-// Use of this source code is governed by a BSD-style
118568-// license that can be found in the LICENSE file.
118569-
118570-package misc
118571-
118572-import (
118573-	"testing"
118574-
118575-	"golang.org/x/tools/gopls/internal/lsp/fake"
118576-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
118577-)
118578-
118579-// Smoke test that simultaneous editing sessions in the same workspace works.
118580-func TestSimultaneousEdits(t *testing.T) {
118581-	const sharedProgram = `
118582--- go.mod --
118583-module mod
118584-
118585-go 1.12
118586--- main.go --
118587-package main
118588-
118589-import "fmt"
118590-
118591-func main() {
118592-	fmt.Println("Hello World.")
118593-}`
118594-
118595-	WithOptions(
118596-		Modes(DefaultModes()&(Forwarded|SeparateProcess)),
118597-	).Run(t, sharedProgram, func(t *testing.T, env1 *Env) {
118598-		// Create a second test session connected to the same workspace and server
118599-		// as the first.
118600-		awaiter := NewAwaiter(env1.Sandbox.Workdir)
118601-		const skipApplyEdits = false
118602-		editor, err := fake.NewEditor(env1.Sandbox, env1.Editor.Config()).Connect(env1.Ctx, env1.Server, awaiter.Hooks(), skipApplyEdits)
118603-		if err != nil {
118604-			t.Fatal(err)
118605-		}
118606-		env2 := &Env{
118607-			T:       t,
118608-			Ctx:     env1.Ctx,
118609-			Sandbox: env1.Sandbox,
118610-			Server:  env1.Server,
118611-			Editor:  editor,
118612-			Awaiter: awaiter,
118613-		}
118614-		env2.Await(InitialWorkspaceLoad)
118615-		// In editor #1, break fmt.Println as before.
118616-		env1.OpenFile("main.go")
118617-		env1.RegexpReplace("main.go", "Printl(n)", "")
118618-		// In editor #2 remove the closing brace.
118619-		env2.OpenFile("main.go")
118620-		env2.RegexpReplace("main.go", "\\)\n(})", "")
118621-
118622-		// Now check that we got different diagnostics in each environment.
118623-		env1.AfterChange(Diagnostics(env1.AtRegexp("main.go", "Printl")))
118624-		env2.AfterChange(Diagnostics(env2.AtRegexp("main.go", "$")))
118625-
118626-		// Now close editor #2, and verify that operation in editor #1 is
118627-		// unaffected.
118628-		if err := env2.Editor.Close(env2.Ctx); err != nil {
118629-			t.Errorf("closing second editor: %v", err)
118630-		}
118631-
118632-		env1.RegexpReplace("main.go", "Printl", "Println")
118633-		env1.AfterChange(
118634-			NoDiagnostics(ForFile("main.go")),
118635-		)
118636-	})
118637-}
118638diff -urN a/gopls/internal/regtest/misc/signature_help_test.go b/gopls/internal/regtest/misc/signature_help_test.go
118639--- a/gopls/internal/regtest/misc/signature_help_test.go	2000-01-01 00:00:00.000000000 -0000
118640+++ b/gopls/internal/regtest/misc/signature_help_test.go	1970-01-01 00:00:00.000000000 +0000
118641@@ -1,69 +0,0 @@
118642-// Copyright 2023 The Go Authors. All rights reserved.
118643-// Use of this source code is governed by a BSD-style
118644-// license that can be found in the LICENSE file.
118645-
118646-package misc
118647-
118648-import (
118649-	"testing"
118650-
118651-	"github.com/google/go-cmp/cmp"
118652-	"golang.org/x/tools/gopls/internal/lsp/protocol"
118653-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
118654-)
118655-
118656-func TestSignatureHelpInNonWorkspacePackage(t *testing.T) {
118657-	const files = `
118658--- a/go.mod --
118659-module a.com
118660-
118661-go 1.18
118662--- a/a/a.go --
118663-package a
118664-
118665-func DoSomething(int) {}
118666-
118667-func _() {
118668-	DoSomething()
118669-}
118670--- b/go.mod --
118671-module b.com
118672-go 1.18
118673-
118674-require a.com v1.0.0
118675-
118676-replace a.com => ../a
118677--- b/b/b.go --
118678-package b
118679-
118680-import "a.com/a"
118681-
118682-func _() {
118683-	a.DoSomething()
118684-}
118685-`
118686-
118687-	WithOptions(
118688-		WorkspaceFolders("a"),
118689-	).Run(t, files, func(t *testing.T, env *Env) {
118690-		env.OpenFile("a/a/a.go")
118691-		env.OpenFile("b/b/b.go")
118692-		signatureHelp := func(filename string) *protocol.SignatureHelp {
118693-			loc := env.RegexpSearch(filename, `DoSomething\(()\)`)
118694-			var params protocol.SignatureHelpParams
118695-			params.TextDocument.URI = loc.URI
118696-			params.Position = loc.Range.Start
118697-			help, err := env.Editor.Server.SignatureHelp(env.Ctx, &params)
118698-			if err != nil {
118699-				t.Fatal(err)
118700-			}
118701-			return help
118702-		}
118703-		ahelp := signatureHelp("a/a/a.go")
118704-		bhelp := signatureHelp("b/b/b.go")
118705-
118706-		if diff := cmp.Diff(ahelp, bhelp); diff != "" {
118707-			t.Fatal(diff)
118708-		}
118709-	})
118710-}
118711diff -urN a/gopls/internal/regtest/misc/staticcheck_test.go b/gopls/internal/regtest/misc/staticcheck_test.go
118712--- a/gopls/internal/regtest/misc/staticcheck_test.go	2000-01-01 00:00:00.000000000 -0000
118713+++ b/gopls/internal/regtest/misc/staticcheck_test.go	1970-01-01 00:00:00.000000000 +0000
118714@@ -1,110 +0,0 @@
118715-// Copyright 2022 The Go Authors. All rights reserved.
118716-// Use of this source code is governed by a BSD-style
118717-// license that can be found in the LICENSE file.
118718-
118719-package misc
118720-
118721-import (
118722-	"testing"
118723-
118724-	"golang.org/x/tools/internal/testenv"
118725-
118726-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
118727-)
118728-
118729-func TestStaticcheckGenerics(t *testing.T) {
118730-	testenv.NeedsGo1Point(t, 19) // generics were introduced in Go 1.18, staticcheck requires go1.19+
118731-
118732-	const files = `
118733--- go.mod --
118734-module mod.com
118735-
118736-go 1.18
118737--- a/a.go --
118738-package a
118739-
118740-import (
118741-	"errors"
118742-	"sort"
118743-	"strings"
118744-)
118745-
118746-func Zero[P any]() P {
118747-	var p P
118748-	return p
118749-}
118750-
118751-type Inst[P any] struct {
118752-	Field P
118753-}
118754-
118755-func testGenerics[P *T, T any](p P) {
118756-	// Calls to instantiated functions should not break checks.
118757-	slice := Zero[string]()
118758-	sort.Slice(slice, func(i, j int) bool {
118759-		return slice[i] < slice[j]
118760-	})
118761-
118762-	// Usage of instantiated fields should not break checks.
118763-	g := Inst[string]{"hello"}
118764-	g.Field = strings.TrimLeft(g.Field, "12234")
118765-
118766-	// Use of type parameters should not break checks.
118767-	var q P
118768-	p = q // SA4009: p is overwritten before its first use
118769-	q = &*p // SA4001: &* will be simplified
118770-}
118771-
118772-
118773-// FooErr should be called ErrFoo (ST1012)
118774-var FooErr error = errors.New("foo")
118775-`
118776-
118777-	WithOptions(
118778-		Settings{"staticcheck": true},
118779-	).Run(t, files, func(t *testing.T, env *Env) {
118780-		env.OpenFile("a/a.go")
118781-		env.AfterChange(
118782-			Diagnostics(env.AtRegexp("a/a.go", "sort.Slice"), FromSource("sortslice")),
118783-			Diagnostics(env.AtRegexp("a/a.go", "sort.Slice.(slice)"), FromSource("SA1028")),
118784-			Diagnostics(env.AtRegexp("a/a.go", "var (FooErr)"), FromSource("ST1012")),
118785-			Diagnostics(env.AtRegexp("a/a.go", `"12234"`), FromSource("SA1024")),
118786-			Diagnostics(env.AtRegexp("a/a.go", "testGenerics.*(p P)"), FromSource("SA4009")),
118787-			Diagnostics(env.AtRegexp("a/a.go", "q = (&\\*p)"), FromSource("SA4001")),
118788-		)
118789-	})
118790-}
118791-
118792-// Test for golang/go#56270: an analysis with related info should not panic if
118793-// analysis.RelatedInformation.End is not set.
118794-func TestStaticcheckRelatedInfo(t *testing.T) {
118795-	testenv.NeedsGo1Point(t, 19) // staticcheck is only supported at Go 1.19+
118796-	const files = `
118797--- go.mod --
118798-module mod.test
118799-
118800-go 1.18
118801--- p.go --
118802-package p
118803-
118804-import (
118805-	"fmt"
118806-)
118807-
118808-func Foo(enabled interface{}) {
118809-	if enabled, ok := enabled.(bool); ok {
118810-	} else {
118811-		_ = fmt.Sprintf("invalid type %T", enabled) // enabled is always bool here
118812-	}
118813-}
118814-`
118815-
118816-	WithOptions(
118817-		Settings{"staticcheck": true},
118818-	).Run(t, files, func(t *testing.T, env *Env) {
118819-		env.OpenFile("p.go")
118820-		env.AfterChange(
118821-			Diagnostics(env.AtRegexp("p.go", ", (enabled)"), FromSource("SA9008")),
118822-		)
118823-	})
118824-}
118825diff -urN a/gopls/internal/regtest/misc/vendor_test.go b/gopls/internal/regtest/misc/vendor_test.go
118826--- a/gopls/internal/regtest/misc/vendor_test.go	2000-01-01 00:00:00.000000000 -0000
118827+++ b/gopls/internal/regtest/misc/vendor_test.go	1970-01-01 00:00:00.000000000 +0000
118828@@ -1,65 +0,0 @@
118829-// Copyright 2020 The Go Authors. All rights reserved.
118830-// Use of this source code is governed by a BSD-style
118831-// license that can be found in the LICENSE file.
118832-
118833-package misc
118834-
118835-import (
118836-	"testing"
118837-
118838-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
118839-
118840-	"golang.org/x/tools/gopls/internal/lsp/protocol"
118841-)
118842-
118843-const basicProxy = `
118844--- golang.org/x/hello@v1.2.3/go.mod --
118845-module golang.org/x/hello
118846-
118847-go 1.14
118848--- golang.org/x/hello@v1.2.3/hi/hi.go --
118849-package hi
118850-
118851-var Goodbye error
118852-`
118853-
118854-func TestInconsistentVendoring(t *testing.T) {
118855-	const pkgThatUsesVendoring = `
118856--- go.mod --
118857-module mod.com
118858-
118859-go 1.14
118860-
118861-require golang.org/x/hello v1.2.3
118862--- go.sum --
118863-golang.org/x/hello v1.2.3 h1:EcMp5gSkIhaTkPXp8/3+VH+IFqTpk3ZbpOhqk0Ncmho=
118864-golang.org/x/hello v1.2.3/go.mod h1:WW7ER2MRNXWA6c8/4bDIek4Hc/+DofTrMaQQitGXcco=
118865--- vendor/modules.txt --
118866--- a/a1.go --
118867-package a
118868-
118869-import "golang.org/x/hello/hi"
118870-
118871-func _() {
118872-	_ = hi.Goodbye
118873-	var q int // hardcode a diagnostic
118874-}
118875-`
118876-	WithOptions(
118877-		Modes(Default),
118878-		ProxyFiles(basicProxy),
118879-	).Run(t, pkgThatUsesVendoring, func(t *testing.T, env *Env) {
118880-		env.OpenFile("a/a1.go")
118881-		d := &protocol.PublishDiagnosticsParams{}
118882-		env.OnceMet(
118883-			InitialWorkspaceLoad,
118884-			Diagnostics(env.AtRegexp("go.mod", "module mod.com"), WithMessage("Inconsistent vendoring")),
118885-			ReadDiagnostics("go.mod", d),
118886-		)
118887-		env.ApplyQuickFixes("go.mod", d.Diagnostics)
118888-
118889-		env.AfterChange(
118890-			Diagnostics(env.AtRegexp("a/a1.go", `q int`), WithMessage("not used")),
118891-		)
118892-	})
118893-}
118894diff -urN a/gopls/internal/regtest/misc/vuln_test.go b/gopls/internal/regtest/misc/vuln_test.go
118895--- a/gopls/internal/regtest/misc/vuln_test.go	2000-01-01 00:00:00.000000000 -0000
118896+++ b/gopls/internal/regtest/misc/vuln_test.go	1970-01-01 00:00:00.000000000 +0000
118897@@ -1,977 +0,0 @@
118898-// Copyright 2022 The Go Authors. All rights reserved.
118899-// Use of this source code is governed by a BSD-style
118900-// license that can be found in the LICENSE file.
118901-
118902-//go:build go1.18
118903-// +build go1.18
118904-
118905-package misc
118906-
118907-import (
118908-	"context"
118909-	"encoding/json"
118910-	"path/filepath"
118911-	"sort"
118912-	"strings"
118913-	"testing"
118914-
118915-	"github.com/google/go-cmp/cmp"
118916-	"golang.org/x/tools/gopls/internal/govulncheck"
118917-	"golang.org/x/tools/gopls/internal/lsp/command"
118918-	"golang.org/x/tools/gopls/internal/lsp/protocol"
118919-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
118920-	"golang.org/x/tools/gopls/internal/lsp/source"
118921-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
118922-	"golang.org/x/tools/gopls/internal/vulncheck"
118923-	"golang.org/x/tools/gopls/internal/vulncheck/vulntest"
118924-	"golang.org/x/tools/internal/testenv"
118925-)
118926-
118927-func TestRunGovulncheckError(t *testing.T) {
118928-	const files = `
118929--- go.mod --
118930-module mod.com
118931-
118932-go 1.12
118933--- foo.go --
118934-package foo
118935-`
118936-	Run(t, files, func(t *testing.T, env *Env) {
118937-		cmd, err := command.NewRunGovulncheckCommand("Run Vulncheck Exp", command.VulncheckArgs{
118938-			URI: "/invalid/file/url", // invalid arg
118939-		})
118940-		if err != nil {
118941-			t.Fatal(err)
118942-		}
118943-
118944-		params := &protocol.ExecuteCommandParams{
118945-			Command:   command.RunGovulncheck.ID(),
118946-			Arguments: cmd.Arguments,
118947-		}
118948-
118949-		response, err := env.Editor.ExecuteCommand(env.Ctx, params)
118950-		// We want an error!
118951-		if err == nil {
118952-			t.Errorf("got success, want invalid file URL error: %v", response)
118953-		}
118954-	})
118955-}
118956-
118957-func TestRunGovulncheckError2(t *testing.T) {
118958-	const files = `
118959--- go.mod --
118960-module mod.com
118961-
118962-go 1.12
118963--- foo.go --
118964-package foo
118965-
118966-func F() { // build error incomplete
118967-`
118968-	WithOptions(
118969-		EnvVars{
118970-			"_GOPLS_TEST_BINARY_RUN_AS_GOPLS": "true", // needed to run `gopls vulncheck`.
118971-		},
118972-		Settings{
118973-			"codelenses": map[string]bool{
118974-				"run_govulncheck": true,
118975-			},
118976-		},
118977-	).Run(t, files, func(t *testing.T, env *Env) {
118978-		env.OpenFile("go.mod")
118979-		var result command.RunVulncheckResult
118980-		env.ExecuteCodeLensCommand("go.mod", command.RunGovulncheck, &result)
118981-		var ws WorkStatus
118982-		env.Await(
118983-			CompletedProgress(result.Token, &ws),
118984-		)
118985-		wantEndMsg, wantMsgPart := "failed", "failed to load packages due to errors"
118986-		if ws.EndMsg != "failed" || !strings.Contains(ws.Msg, wantMsgPart) {
118987-			t.Errorf("work status = %+v, want {EndMessage: %q, Message: %q}", ws, wantEndMsg, wantMsgPart)
118988-		}
118989-	})
118990-}
118991-
118992-const vulnsData = `
118993--- GO-2022-01.yaml --
118994-modules:
118995-  - module: golang.org/amod
118996-    versions:
118997-      - introduced: 1.0.0
118998-      - fixed: 1.0.4
118999-      - introduced: 1.1.2
119000-    packages:
119001-      - package: golang.org/amod/avuln
119002-        symbols:
119003-          - VulnData.Vuln1
119004-          - VulnData.Vuln2
119005-description: >
119006-    vuln in amod
119007-references:
119008-  - href: pkg.go.dev/vuln/GO-2022-01
119009--- GO-2022-03.yaml --
119010-modules:
119011-  - module: golang.org/amod
119012-    versions:
119013-      - introduced: 1.0.0
119014-      - fixed: 1.0.6
119015-    packages:
119016-      - package: golang.org/amod/avuln
119017-        symbols:
119018-          - nonExisting
119019-description: >
119020-  unaffecting vulnerability
119021--- GO-2022-02.yaml --
119022-modules:
119023-  - module: golang.org/bmod
119024-    packages:
119025-      - package: golang.org/bmod/bvuln
119026-        symbols:
119027-          - Vuln
119028-description: |
119029-    vuln in bmod
119030-
119031-    This is a long description
119032-    of this vulnerability.
119033-references:
119034-  - href: pkg.go.dev/vuln/GO-2022-03
119035--- GO-2022-04.yaml --
119036-modules:
119037-  - module: golang.org/bmod
119038-    packages:
119039-      - package: golang.org/bmod/unused
119040-        symbols:
119041-          - Vuln
119042-description: |
119043-    vuln in bmod/somtrhingelse
119044-references:
119045-  - href: pkg.go.dev/vuln/GO-2022-04
119046--- GOSTDLIB.yaml --
119047-modules:
119048-  - module: stdlib
119049-    versions:
119050-      - introduced: 1.18.0
119051-    packages:
119052-      - package: archive/zip
119053-        symbols:
119054-          - OpenReader
119055-references:
119056-  - href: pkg.go.dev/vuln/GOSTDLIB
119057-`
119058-
119059-func TestRunGovulncheckStd(t *testing.T) {
119060-	testenv.NeedsGo1Point(t, 18)
119061-	const files = `
119062--- go.mod --
119063-module mod.com
119064-
119065-go 1.18
119066--- main.go --
119067-package main
119068-
119069-import (
119070-        "archive/zip"
119071-        "fmt"
119072-)
119073-
119074-func main() {
119075-        _, err := zip.OpenReader("file.zip")  // vulnerability id: GOSTDLIB
119076-        fmt.Println(err)
119077-}
119078-`
119079-
119080-	db, err := vulntest.NewDatabase(context.Background(), []byte(vulnsData))
119081-	if err != nil {
119082-		t.Fatal(err)
119083-	}
119084-	defer db.Clean()
119085-	WithOptions(
119086-		EnvVars{
119087-			// Let the analyzer read vulnerabilities data from the testdata/vulndb.
119088-			"GOVULNDB": db.URI(),
119089-			// When fetchinging stdlib package vulnerability info,
119090-			// behave as if our go version is go1.18 for this testing.
119091-			// The default behavior is to run `go env GOVERSION` (which isn't mutable env var).
119092-			vulncheck.GoVersionForVulnTest:    "go1.18",
119093-			"_GOPLS_TEST_BINARY_RUN_AS_GOPLS": "true", // needed to run `gopls vulncheck`.
119094-		},
119095-		Settings{
119096-			"codelenses": map[string]bool{
119097-				"run_govulncheck": true,
119098-			},
119099-		},
119100-	).Run(t, files, func(t *testing.T, env *Env) {
119101-		env.OpenFile("go.mod")
119102-
119103-		// Test CodeLens is present.
119104-		lenses := env.CodeLens("go.mod")
119105-
119106-		const wantCommand = "gopls." + string(command.RunGovulncheck)
119107-		var gotCodelens = false
119108-		var lens protocol.CodeLens
119109-		for _, l := range lenses {
119110-			if l.Command.Command == wantCommand {
119111-				gotCodelens = true
119112-				lens = l
119113-				break
119114-			}
119115-		}
119116-		if !gotCodelens {
119117-			t.Fatal("got no vulncheck codelens")
119118-		}
119119-		// Run Command included in the codelens.
119120-		var result command.RunVulncheckResult
119121-		env.ExecuteCommand(&protocol.ExecuteCommandParams{
119122-			Command:   lens.Command.Command,
119123-			Arguments: lens.Command.Arguments,
119124-		}, &result)
119125-
119126-		env.OnceMet(
119127-			CompletedProgress(result.Token, nil),
119128-			ShownMessage("Found GOSTDLIB"),
119129-			NoDiagnostics(ForFile("go.mod")),
119130-		)
119131-		testFetchVulncheckResult(t, env, map[string]fetchVulncheckResult{
119132-			"go.mod": {IDs: []string{"GOSTDLIB"}, Mode: govulncheck.ModeGovulncheck}})
119133-	})
119134-}
119135-
119136-func TestFetchVulncheckResultStd(t *testing.T) {
119137-	testenv.NeedsGo1Point(t, 18)
119138-	const files = `
119139--- go.mod --
119140-module mod.com
119141-
119142-go 1.18
119143--- main.go --
119144-package main
119145-
119146-import (
119147-        "archive/zip"
119148-        "fmt"
119149-)
119150-
119151-func main() {
119152-        _, err := zip.OpenReader("file.zip")  // vulnerability id: GOSTDLIB
119153-        fmt.Println(err)
119154-}
119155-`
119156-
119157-	db, err := vulntest.NewDatabase(context.Background(), []byte(vulnsData))
119158-	if err != nil {
119159-		t.Fatal(err)
119160-	}
119161-	defer db.Clean()
119162-	WithOptions(
119163-		EnvVars{
119164-			// Let the analyzer read vulnerabilities data from the testdata/vulndb.
119165-			"GOVULNDB": db.URI(),
119166-			// When fetchinging stdlib package vulnerability info,
119167-			// behave as if our go version is go1.18 for this testing.
119168-			vulncheck.GoVersionForVulnTest:    "go1.18",
119169-			"_GOPLS_TEST_BINARY_RUN_AS_GOPLS": "true", // needed to run `gopls vulncheck`.
119170-		},
119171-		Settings{"ui.diagnostic.vulncheck": "Imports"},
119172-	).Run(t, files, func(t *testing.T, env *Env) {
119173-		env.OpenFile("go.mod")
119174-		env.AfterChange(
119175-			NoDiagnostics(ForFile("go.mod")),
119176-			// we don't publish diagnostics for standard library vulnerability yet.
119177-		)
119178-		testFetchVulncheckResult(t, env, map[string]fetchVulncheckResult{
119179-			"go.mod": {
119180-				IDs:  []string{"GOSTDLIB"},
119181-				Mode: govulncheck.ModeImports,
119182-			},
119183-		})
119184-	})
119185-}
119186-
119187-type fetchVulncheckResult struct {
119188-	IDs  []string
119189-	Mode govulncheck.AnalysisMode
119190-}
119191-
119192-func testFetchVulncheckResult(t *testing.T, env *Env, want map[string]fetchVulncheckResult) {
119193-	t.Helper()
119194-
119195-	var result map[protocol.DocumentURI]*govulncheck.Result
119196-	fetchCmd, err := command.NewFetchVulncheckResultCommand("fetch", command.URIArg{
119197-		URI: env.Sandbox.Workdir.URI("go.mod"),
119198-	})
119199-	if err != nil {
119200-		t.Fatal(err)
119201-	}
119202-	env.ExecuteCommand(&protocol.ExecuteCommandParams{
119203-		Command:   fetchCmd.Command,
119204-		Arguments: fetchCmd.Arguments,
119205-	}, &result)
119206-
119207-	for _, v := range want {
119208-		sort.Strings(v.IDs)
119209-	}
119210-	got := map[string]fetchVulncheckResult{}
119211-	for k, r := range result {
119212-		var osv []string
119213-		for _, v := range r.Vulns {
119214-			osv = append(osv, v.OSV.ID)
119215-		}
119216-		sort.Strings(osv)
119217-		modfile := env.Sandbox.Workdir.RelPath(k.SpanURI().Filename())
119218-		got[modfile] = fetchVulncheckResult{
119219-			IDs:  osv,
119220-			Mode: r.Mode,
119221-		}
119222-	}
119223-	if diff := cmp.Diff(want, got); diff != "" {
119224-		t.Errorf("fetch vulnchheck result = got %v, want %v: diff %v", got, want, diff)
119225-	}
119226-}
119227-
119228-const workspace1 = `
119229--- go.mod --
119230-module golang.org/entry
119231-
119232-go 1.18
119233-
119234-require golang.org/cmod v1.1.3
119235-
119236-require (
119237-	golang.org/amod v1.0.0 // indirect
119238-	golang.org/bmod v0.5.0 // indirect
119239-)
119240--- go.sum --
119241-golang.org/amod v1.0.0 h1:EUQOI2m5NhQZijXZf8WimSnnWubaFNrrKUH/PopTN8k=
119242-golang.org/amod v1.0.0/go.mod h1:yvny5/2OtYFomKt8ax+WJGvN6pfN1pqjGnn7DQLUi6E=
119243-golang.org/bmod v0.5.0 h1:KgvUulMyMiYRB7suKA0x+DfWRVdeyPgVJvcishTH+ng=
119244-golang.org/bmod v0.5.0/go.mod h1:f6o+OhF66nz/0BBc/sbCsshyPRKMSxZIlG50B/bsM4c=
119245-golang.org/cmod v1.1.3 h1:PJ7rZFTk7xGAunBRDa0wDe7rZjZ9R/vr1S2QkVVCngQ=
119246-golang.org/cmod v1.1.3/go.mod h1:eCR8dnmvLYQomdeAZRCPgS5JJihXtqOQrpEkNj5feQA=
119247--- x/x.go --
119248-package x
119249-
119250-import 	(
119251-   "golang.org/cmod/c"
119252-   "golang.org/entry/y"
119253-)
119254-
119255-func X() {
119256-	c.C1().Vuln1() // vuln use: X -> Vuln1
119257-}
119258-
119259-func CallY() {
119260-	y.Y()  // vuln use: CallY -> y.Y -> bvuln.Vuln
119261-}
119262-
119263--- y/y.go --
119264-package y
119265-
119266-import "golang.org/cmod/c"
119267-
119268-func Y() {
119269-	c.C2()() // vuln use: Y -> bvuln.Vuln
119270-}
119271-`
119272-
119273-// cmod/c imports amod/avuln and bmod/bvuln.
119274-const proxy1 = `
119275--- golang.org/cmod@v1.1.3/go.mod --
119276-module golang.org/cmod
119277-
119278-go 1.12
119279--- golang.org/cmod@v1.1.3/c/c.go --
119280-package c
119281-
119282-import (
119283-	"golang.org/amod/avuln"
119284-	"golang.org/bmod/bvuln"
119285-)
119286-
119287-type I interface {
119288-	Vuln1()
119289-}
119290-
119291-func C1() I {
119292-	v := avuln.VulnData{}
119293-	v.Vuln2() // vuln use
119294-	return v
119295-}
119296-
119297-func C2() func() {
119298-	return bvuln.Vuln
119299-}
119300--- golang.org/amod@v1.0.0/go.mod --
119301-module golang.org/amod
119302-
119303-go 1.14
119304--- golang.org/amod@v1.0.0/avuln/avuln.go --
119305-package avuln
119306-
119307-type VulnData struct {}
119308-func (v VulnData) Vuln1() {}
119309-func (v VulnData) Vuln2() {}
119310--- golang.org/amod@v1.0.4/go.mod --
119311-module golang.org/amod
119312-
119313-go 1.14
119314--- golang.org/amod@v1.0.4/avuln/avuln.go --
119315-package avuln
119316-
119317-type VulnData struct {}
119318-func (v VulnData) Vuln1() {}
119319-func (v VulnData) Vuln2() {}
119320-
119321--- golang.org/bmod@v0.5.0/go.mod --
119322-module golang.org/bmod
119323-
119324-go 1.14
119325--- golang.org/bmod@v0.5.0/bvuln/bvuln.go --
119326-package bvuln
119327-
119328-func Vuln() {
119329-	// something evil
119330-}
119331--- golang.org/bmod@v0.5.0/unused/unused.go --
119332-package unused
119333-
119334-func Vuln() {
119335-	// something evil
119336-}
119337--- golang.org/amod@v1.0.6/go.mod --
119338-module golang.org/amod
119339-
119340-go 1.14
119341--- golang.org/amod@v1.0.6/avuln/avuln.go --
119342-package avuln
119343-
119344-type VulnData struct {}
119345-func (v VulnData) Vuln1() {}
119346-func (v VulnData) Vuln2() {}
119347-`
119348-
119349-func vulnTestEnv(vulnsDB, proxyData string) (*vulntest.DB, []RunOption, error) {
119350-	db, err := vulntest.NewDatabase(context.Background(), []byte(vulnsData))
119351-	if err != nil {
119352-		return nil, nil, nil
119353-	}
119354-	settings := Settings{
119355-		"codelenses": map[string]bool{
119356-			"run_govulncheck": true,
119357-		},
119358-	}
119359-	ev := EnvVars{
119360-		// Let the analyzer read vulnerabilities data from the testdata/vulndb.
119361-		"GOVULNDB": db.URI(),
119362-		// When fetching stdlib package vulnerability info,
119363-		// behave as if our go version is go1.18 for this testing.
119364-		// The default behavior is to run `go env GOVERSION` (which isn't mutable env var).
119365-		vulncheck.GoVersionForVulnTest:    "go1.18",
119366-		"_GOPLS_TEST_BINARY_RUN_AS_GOPLS": "true", // needed to run `gopls vulncheck`.
119367-		"GOSUMDB":                         "off",
119368-	}
119369-	return db, []RunOption{ProxyFiles(proxyData), ev, settings}, nil
119370-}
119371-
119372-func TestRunVulncheckPackageDiagnostics(t *testing.T) {
119373-	testenv.NeedsGo1Point(t, 18)
119374-
119375-	db, opts0, err := vulnTestEnv(vulnsData, proxy1)
119376-	if err != nil {
119377-		t.Fatal(err)
119378-	}
119379-	defer db.Clean()
119380-
119381-	checkVulncheckDiagnostics := func(env *Env, t *testing.T) {
119382-		env.OpenFile("go.mod")
119383-
119384-		gotDiagnostics := &protocol.PublishDiagnosticsParams{}
119385-		env.AfterChange(
119386-			Diagnostics(env.AtRegexp("go.mod", `golang.org/amod`)),
119387-			ReadDiagnostics("go.mod", gotDiagnostics),
119388-		)
119389-
119390-		testFetchVulncheckResult(t, env, map[string]fetchVulncheckResult{
119391-			"go.mod": {
119392-				IDs:  []string{"GO-2022-01", "GO-2022-02", "GO-2022-03"},
119393-				Mode: govulncheck.ModeImports,
119394-			},
119395-		})
119396-
119397-		wantVulncheckDiagnostics := map[string]vulnDiagExpectation{
119398-			"golang.org/amod": {
119399-				diagnostics: []vulnDiag{
119400-					{
119401-						msg:      "golang.org/amod has known vulnerabilities GO-2022-01, GO-2022-03.",
119402-						severity: protocol.SeverityInformation,
119403-						source:   string(source.Vulncheck),
119404-						codeActions: []string{
119405-							"Run govulncheck to verify",
119406-							"Upgrade to v1.0.6",
119407-							"Upgrade to latest",
119408-						},
119409-					},
119410-				},
119411-				codeActions: []string{
119412-					"Run govulncheck to verify",
119413-					"Upgrade to v1.0.6",
119414-					"Upgrade to latest",
119415-				},
119416-				hover: []string{"GO-2022-01", "Fixed in v1.0.4.", "GO-2022-03"},
119417-			},
119418-			"golang.org/bmod": {
119419-				diagnostics: []vulnDiag{
119420-					{
119421-						msg:      "golang.org/bmod has a vulnerability GO-2022-02.",
119422-						severity: protocol.SeverityInformation,
119423-						source:   string(source.Vulncheck),
119424-						codeActions: []string{
119425-							"Run govulncheck to verify",
119426-						},
119427-					},
119428-				},
119429-				codeActions: []string{
119430-					"Run govulncheck to verify",
119431-				},
119432-				hover: []string{"GO-2022-02", "This is a long description of this vulnerability.", "No fix is available."},
119433-			},
119434-		}
119435-
119436-		for pattern, want := range wantVulncheckDiagnostics {
119437-			modPathDiagnostics := testVulnDiagnostics(t, env, pattern, want, gotDiagnostics)
119438-
119439-			gotActions := env.CodeAction("go.mod", modPathDiagnostics)
119440-			if diff := diffCodeActions(gotActions, want.codeActions); diff != "" {
119441-				t.Errorf("code actions for %q do not match, got %v, want %v\n%v\n", pattern, gotActions, want.codeActions, diff)
119442-				continue
119443-			}
119444-		}
119445-	}
119446-
119447-	wantNoVulncheckDiagnostics := func(env *Env, t *testing.T) {
119448-		env.OpenFile("go.mod")
119449-
119450-		gotDiagnostics := &protocol.PublishDiagnosticsParams{}
119451-		env.AfterChange(
119452-			ReadDiagnostics("go.mod", gotDiagnostics),
119453-		)
119454-
119455-		if len(gotDiagnostics.Diagnostics) > 0 {
119456-			t.Errorf("Unexpected diagnostics: %v", stringify(gotDiagnostics))
119457-		}
119458-		testFetchVulncheckResult(t, env, map[string]fetchVulncheckResult{})
119459-	}
119460-
119461-	for _, tc := range []struct {
119462-		name            string
119463-		setting         Settings
119464-		wantDiagnostics bool
119465-	}{
119466-		{"imports", Settings{"ui.diagnostic.vulncheck": "Imports"}, true},
119467-		{"default", Settings{}, false},
119468-		{"invalid", Settings{"ui.diagnostic.vulncheck": "invalid"}, false},
119469-	} {
119470-		t.Run(tc.name, func(t *testing.T) {
119471-			// override the settings options to enable diagnostics
119472-			opts := append(opts0, tc.setting)
119473-			WithOptions(opts...).Run(t, workspace1, func(t *testing.T, env *Env) {
119474-				// TODO(hyangah): implement it, so we see GO-2022-01, GO-2022-02, and GO-2022-03.
119475-				// Check that the actions we get when including all diagnostics at a location return the same result
119476-				if tc.wantDiagnostics {
119477-					checkVulncheckDiagnostics(env, t)
119478-				} else {
119479-					wantNoVulncheckDiagnostics(env, t)
119480-				}
119481-
119482-				if tc.name == "imports" && tc.wantDiagnostics {
119483-					// test we get only govulncheck-based diagnostics after "run govulncheck".
119484-					var result command.RunVulncheckResult
119485-					env.ExecuteCodeLensCommand("go.mod", command.RunGovulncheck, &result)
119486-					gotDiagnostics := &protocol.PublishDiagnosticsParams{}
119487-					env.OnceMet(
119488-						CompletedProgress(result.Token, nil),
119489-						ShownMessage("Found"),
119490-					)
119491-					env.OnceMet(
119492-						Diagnostics(env.AtRegexp("go.mod", "golang.org/bmod")),
119493-						ReadDiagnostics("go.mod", gotDiagnostics),
119494-					)
119495-					// We expect only one diagnostic for GO-2022-02.
119496-					count := 0
119497-					for _, diag := range gotDiagnostics.Diagnostics {
119498-						if strings.Contains(diag.Message, "GO-2022-02") {
119499-							count++
119500-							if got, want := diag.Severity, protocol.SeverityWarning; got != want {
119501-								t.Errorf("Diagnostic for GO-2022-02 = %v, want %v", got, want)
119502-							}
119503-						}
119504-					}
119505-					if count != 1 {
119506-						t.Errorf("Unexpected number of diagnostics about GO-2022-02 = %v, want 1:\n%+v", count, stringify(gotDiagnostics))
119507-					}
119508-				}
119509-			})
119510-		})
119511-	}
119512-}
119513-
119514-func stringify(a interface{}) string {
119515-	data, _ := json.Marshal(a)
119516-	return string(data)
119517-}
119518-
119519-func TestRunVulncheckWarning(t *testing.T) {
119520-	testenv.NeedsGo1Point(t, 18)
119521-
119522-	db, opts, err := vulnTestEnv(vulnsData, proxy1)
119523-	if err != nil {
119524-		t.Fatal(err)
119525-	}
119526-	defer db.Clean()
119527-	WithOptions(opts...).Run(t, workspace1, func(t *testing.T, env *Env) {
119528-		env.OpenFile("go.mod")
119529-
119530-		var result command.RunVulncheckResult
119531-		env.ExecuteCodeLensCommand("go.mod", command.RunGovulncheck, &result)
119532-		gotDiagnostics := &protocol.PublishDiagnosticsParams{}
119533-		env.OnceMet(
119534-			CompletedProgress(result.Token, nil),
119535-			ShownMessage("Found"),
119536-		)
119537-		// Vulncheck diagnostics asynchronous to the vulncheck command.
119538-		env.OnceMet(
119539-			Diagnostics(env.AtRegexp("go.mod", `golang.org/amod`)),
119540-			ReadDiagnostics("go.mod", gotDiagnostics),
119541-		)
119542-
119543-		testFetchVulncheckResult(t, env, map[string]fetchVulncheckResult{
119544-			"go.mod": {IDs: []string{"GO-2022-01", "GO-2022-02", "GO-2022-03"}, Mode: govulncheck.ModeGovulncheck},
119545-		})
119546-		env.OpenFile("x/x.go")
119547-		lineX := env.RegexpSearch("x/x.go", `c\.C1\(\)\.Vuln1\(\)`).Range.Start
119548-		env.OpenFile("y/y.go")
119549-		lineY := env.RegexpSearch("y/y.go", `c\.C2\(\)\(\)`).Range.Start
119550-		wantDiagnostics := map[string]vulnDiagExpectation{
119551-			"golang.org/amod": {
119552-				applyAction: "Upgrade to v1.0.6",
119553-				diagnostics: []vulnDiag{
119554-					{
119555-						msg:      "golang.org/amod has a vulnerability used in the code: GO-2022-01.",
119556-						severity: protocol.SeverityWarning,
119557-						source:   string(source.Govulncheck),
119558-						codeActions: []string{
119559-							"Upgrade to v1.0.4",
119560-							"Upgrade to latest",
119561-							"Reset govulncheck result",
119562-						},
119563-						relatedInfo: []vulnRelatedInfo{
119564-							{"x.go", uint32(lineX.Line), "[GO-2022-01]"}, // avuln.VulnData.Vuln1
119565-							{"x.go", uint32(lineX.Line), "[GO-2022-01]"}, // avuln.VulnData.Vuln2
119566-						},
119567-					},
119568-					{
119569-						msg:      "golang.org/amod has a vulnerability GO-2022-03 that is not used in the code.",
119570-						severity: protocol.SeverityInformation,
119571-						source:   string(source.Govulncheck),
119572-						codeActions: []string{
119573-							"Upgrade to v1.0.6",
119574-							"Upgrade to latest",
119575-							"Reset govulncheck result",
119576-						},
119577-						relatedInfo: []vulnRelatedInfo{
119578-							{"x.go", uint32(lineX.Line), "[GO-2022-01]"}, // avuln.VulnData.Vuln1
119579-							{"x.go", uint32(lineX.Line), "[GO-2022-01]"}, // avuln.VulnData.Vuln2
119580-						},
119581-					},
119582-				},
119583-				codeActions: []string{
119584-					"Upgrade to v1.0.6",
119585-					"Upgrade to latest",
119586-					"Reset govulncheck result",
119587-				},
119588-				hover: []string{"GO-2022-01", "Fixed in v1.0.4.", "GO-2022-03"},
119589-			},
119590-			"golang.org/bmod": {
119591-				diagnostics: []vulnDiag{
119592-					{
119593-						msg:      "golang.org/bmod has a vulnerability used in the code: GO-2022-02.",
119594-						severity: protocol.SeverityWarning,
119595-						source:   string(source.Govulncheck),
119596-						codeActions: []string{
119597-							"Reset govulncheck result", // no fix, but we should give an option to reset.
119598-						},
119599-						relatedInfo: []vulnRelatedInfo{
119600-							{"y.go", uint32(lineY.Line), "[GO-2022-02]"}, // bvuln.Vuln
119601-						},
119602-					},
119603-				},
119604-				codeActions: []string{
119605-					"Reset govulncheck result", // no fix, but we should give an option to reset.
119606-				},
119607-				hover: []string{"GO-2022-02", "This is a long description of this vulnerability.", "No fix is available."},
119608-			},
119609-		}
119610-
119611-		for mod, want := range wantDiagnostics {
119612-			modPathDiagnostics := testVulnDiagnostics(t, env, mod, want, gotDiagnostics)
119613-
119614-			// Check that the actions we get when including all diagnostics at a location return the same result
119615-			gotActions := env.CodeAction("go.mod", modPathDiagnostics)
119616-			if diff := diffCodeActions(gotActions, want.codeActions); diff != "" {
119617-				t.Errorf("code actions for %q do not match, expected %v, got %v\n%v\n", mod, want.codeActions, gotActions, diff)
119618-				continue
119619-			}
119620-
119621-			// Apply the code action matching applyAction.
119622-			if want.applyAction == "" {
119623-				continue
119624-			}
119625-			for _, action := range gotActions {
119626-				if action.Title == want.applyAction {
119627-					env.ApplyCodeAction(action)
119628-					break
119629-				}
119630-			}
119631-		}
119632-
119633-		env.Await(env.DoneWithChangeWatchedFiles())
119634-		wantGoMod := `module golang.org/entry
119635-
119636-go 1.18
119637-
119638-require golang.org/cmod v1.1.3
119639-
119640-require (
119641-	golang.org/amod v1.0.6 // indirect
119642-	golang.org/bmod v0.5.0 // indirect
119643-)
119644-`
119645-		if got := env.BufferText("go.mod"); got != wantGoMod {
119646-			t.Fatalf("go.mod vulncheck fix failed:\n%s", compare.Text(wantGoMod, got))
119647-		}
119648-	})
119649-}
119650-
119651-func diffCodeActions(gotActions []protocol.CodeAction, want []string) string {
119652-	var gotTitles []string
119653-	for _, ca := range gotActions {
119654-		gotTitles = append(gotTitles, ca.Title)
119655-	}
119656-	return cmp.Diff(want, gotTitles)
119657-}
119658-
119659-const workspace2 = `
119660--- go.mod --
119661-module golang.org/entry
119662-
119663-go 1.18
119664-
119665-require golang.org/bmod v0.5.0
119666-
119667--- go.sum --
119668-golang.org/bmod v0.5.0 h1:MT/ysNRGbCiURc5qThRFWaZ5+rK3pQRPo9w7dYZfMDk=
119669-golang.org/bmod v0.5.0/go.mod h1:k+zl+Ucu4yLIjndMIuWzD/MnOHy06wqr3rD++y0abVs=
119670--- x/x.go --
119671-package x
119672-
119673-import "golang.org/bmod/bvuln"
119674-
119675-func F() {
119676-	// Calls a benign func in bvuln.
119677-	bvuln.OK()
119678-}
119679-`
119680-
119681-const proxy2 = `
119682--- golang.org/bmod@v0.5.0/bvuln/bvuln.go --
119683-package bvuln
119684-
119685-func Vuln() {} // vulnerable.
119686-func OK() {} // ok.
119687-`
119688-
119689-func TestGovulncheckInfo(t *testing.T) {
119690-	testenv.NeedsGo1Point(t, 18)
119691-
119692-	db, opts, err := vulnTestEnv(vulnsData, proxy2)
119693-	if err != nil {
119694-		t.Fatal(err)
119695-	}
119696-	defer db.Clean()
119697-	WithOptions(opts...).Run(t, workspace2, func(t *testing.T, env *Env) {
119698-		env.OpenFile("go.mod")
119699-		var result command.RunVulncheckResult
119700-		env.ExecuteCodeLensCommand("go.mod", command.RunGovulncheck, &result)
119701-		gotDiagnostics := &protocol.PublishDiagnosticsParams{}
119702-		env.OnceMet(
119703-			CompletedProgress(result.Token, nil),
119704-			ShownMessage("No vulnerabilities found"), // only count affecting vulnerabilities.
119705-		)
119706-
119707-		// Vulncheck diagnostics asynchronous to the vulncheck command.
119708-		env.OnceMet(
119709-			Diagnostics(env.AtRegexp("go.mod", "golang.org/bmod")),
119710-			ReadDiagnostics("go.mod", gotDiagnostics),
119711-		)
119712-
119713-		testFetchVulncheckResult(t, env, map[string]fetchVulncheckResult{"go.mod": {IDs: []string{"GO-2022-02"}, Mode: govulncheck.ModeGovulncheck}})
119714-		// wantDiagnostics maps a module path in the require
119715-		// section of a go.mod to diagnostics that will be returned
119716-		// when running vulncheck.
119717-		wantDiagnostics := map[string]vulnDiagExpectation{
119718-			"golang.org/bmod": {
119719-				diagnostics: []vulnDiag{
119720-					{
119721-						msg:      "golang.org/bmod has a vulnerability GO-2022-02 that is not used in the code.",
119722-						severity: protocol.SeverityInformation,
119723-						source:   string(source.Govulncheck),
119724-						codeActions: []string{
119725-							"Reset govulncheck result",
119726-						},
119727-					},
119728-				},
119729-				codeActions: []string{
119730-					"Reset govulncheck result",
119731-				},
119732-				hover: []string{"GO-2022-02", "This is a long description of this vulnerability.", "No fix is available."},
119733-			},
119734-		}
119735-
119736-		var allActions []protocol.CodeAction
119737-		for mod, want := range wantDiagnostics {
119738-			modPathDiagnostics := testVulnDiagnostics(t, env, mod, want, gotDiagnostics)
119739-			// Check that the actions we get when including all diagnostics at a location return the same result
119740-			gotActions := env.CodeAction("go.mod", modPathDiagnostics)
119741-			allActions = append(allActions, gotActions...)
119742-			if diff := diffCodeActions(gotActions, want.codeActions); diff != "" {
119743-				t.Errorf("code actions for %q do not match, expected %v, got %v\n%v\n", mod, want.codeActions, gotActions, diff)
119744-				continue
119745-			}
119746-		}
119747-
119748-		// Clear Diagnostics by using one of the reset code actions.
119749-		var reset protocol.CodeAction
119750-		for _, a := range allActions {
119751-			if a.Title == "Reset govulncheck result" {
119752-				reset = a
119753-				break
119754-			}
119755-		}
119756-		if reset.Title != "Reset govulncheck result" {
119757-			t.Errorf("failed to find a 'Reset govulncheck result' code action, got %v", allActions)
119758-		}
119759-		env.ApplyCodeAction(reset)
119760-
119761-		env.Await(NoDiagnostics(ForFile("go.mod")))
119762-	})
119763-}
119764-
119765-// testVulnDiagnostics finds the require or module statement line for the requireMod in go.mod file
119766-// and runs checks if diagnostics and code actions associated with the line match expectation.
119767-func testVulnDiagnostics(t *testing.T, env *Env, pattern string, want vulnDiagExpectation, got *protocol.PublishDiagnosticsParams) []protocol.Diagnostic {
119768-	t.Helper()
119769-	loc := env.RegexpSearch("go.mod", pattern)
119770-	var modPathDiagnostics []protocol.Diagnostic
119771-	for _, w := range want.diagnostics {
119772-		// Find the diagnostics at loc.start.
119773-		var diag *protocol.Diagnostic
119774-		for _, g := range got.Diagnostics {
119775-			g := g
119776-			if g.Range.Start == loc.Range.Start && w.msg == g.Message {
119777-				modPathDiagnostics = append(modPathDiagnostics, g)
119778-				diag = &g
119779-				break
119780-			}
119781-		}
119782-		if diag == nil {
119783-			t.Errorf("no diagnostic at %q matching %q found\n", pattern, w.msg)
119784-			continue
119785-		}
119786-		if diag.Severity != w.severity || diag.Source != w.source {
119787-			t.Errorf("incorrect (severity, source) for %q, want (%s, %s) got (%s, %s)\n", w.msg, w.severity, w.source, diag.Severity, diag.Source)
119788-		}
119789-		sort.Slice(w.relatedInfo, func(i, j int) bool { return w.relatedInfo[i].less(w.relatedInfo[j]) })
119790-		if got, want := summarizeRelatedInfo(diag.RelatedInformation), w.relatedInfo; !cmp.Equal(got, want) {
119791-			t.Errorf("related info for %q do not match, want %v, got %v\n", w.msg, want, got)
119792-		}
119793-		// Check expected code actions appear.
119794-		gotActions := env.CodeAction("go.mod", []protocol.Diagnostic{*diag})
119795-		if diff := diffCodeActions(gotActions, w.codeActions); diff != "" {
119796-			t.Errorf("code actions for %q do not match, want %v, got %v\n%v\n", w.msg, w.codeActions, gotActions, diff)
119797-			continue
119798-		}
119799-	}
119800-	// Check that useful info is supplemented as hover.
119801-	if len(want.hover) > 0 {
119802-		hover, _ := env.Hover(loc)
119803-		for _, part := range want.hover {
119804-			if !strings.Contains(hover.Value, part) {
119805-				t.Errorf("hover contents for %q do not match, want %v, got %v\n", pattern, strings.Join(want.hover, ","), hover.Value)
119806-				break
119807-			}
119808-		}
119809-	}
119810-	return modPathDiagnostics
119811-}
119812-
119813-// summarizeRelatedInfo converts protocol.DiagnosticRelatedInformation to vulnRelatedInfo
119814-// that captures only the part that we want to test.
119815-func summarizeRelatedInfo(rinfo []protocol.DiagnosticRelatedInformation) []vulnRelatedInfo {
119816-	var res []vulnRelatedInfo
119817-	for _, r := range rinfo {
119818-		filename := filepath.Base(r.Location.URI.SpanURI().Filename())
119819-		message, _, _ := strings.Cut(r.Message, " ")
119820-		line := r.Location.Range.Start.Line
119821-		res = append(res, vulnRelatedInfo{filename, line, message})
119822-	}
119823-	sort.Slice(res, func(i, j int) bool {
119824-		return res[i].less(res[j])
119825-	})
119826-	return res
119827-}
119828-
119829-type vulnRelatedInfo struct {
119830-	Filename string
119831-	Line     uint32
119832-	Message  string
119833-}
119834-
119835-type vulnDiag struct {
119836-	msg      string
119837-	severity protocol.DiagnosticSeverity
119838-	// codeActions is a list titles of code actions that we get with this
119839-	// diagnostics as the context.
119840-	codeActions []string
119841-	// relatedInfo is related info message prefixed by the file base.
119842-	// See summarizeRelatedInfo.
119843-	relatedInfo []vulnRelatedInfo
119844-	// diagnostic source.
119845-	source string
119846-}
119847-
119848-func (i vulnRelatedInfo) less(j vulnRelatedInfo) bool {
119849-	if i.Filename != j.Filename {
119850-		return i.Filename < j.Filename
119851-	}
119852-	if i.Line != j.Line {
119853-		return i.Line < j.Line
119854-	}
119855-	return i.Message < j.Message
119856-}
119857-
119858-// vulnDiagExpectation maps a module path in the require
119859-// section of a go.mod to diagnostics that will be returned
119860-// when running vulncheck.
119861-type vulnDiagExpectation struct {
119862-	// applyAction is the title of the code action to run for this module.
119863-	// If empty, no code actions will be executed.
119864-	applyAction string
119865-	// diagnostics is the list of diagnostics we expect at the require line for
119866-	// the module path.
119867-	diagnostics []vulnDiag
119868-	// codeActions is a list titles of code actions that we get with context
119869-	// diagnostics.
119870-	codeActions []string
119871-	// hover message is the list of expected hover message parts for this go.mod require line.
119872-	// all parts must appear in the hover message.
119873-	hover []string
119874-}
119875diff -urN a/gopls/internal/regtest/misc/workspace_symbol_test.go b/gopls/internal/regtest/misc/workspace_symbol_test.go
119876--- a/gopls/internal/regtest/misc/workspace_symbol_test.go	2000-01-01 00:00:00.000000000 -0000
119877+++ b/gopls/internal/regtest/misc/workspace_symbol_test.go	1970-01-01 00:00:00.000000000 +0000
119878@@ -1,124 +0,0 @@
119879-// Copyright 2022 The Go Authors. All rights reserved.
119880-// Use of this source code is governed by a BSD-style
119881-// license that can be found in the LICENSE file.
119882-
119883-package misc
119884-
119885-import (
119886-	"testing"
119887-
119888-	"golang.org/x/tools/gopls/internal/lsp/protocol"
119889-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
119890-	"golang.org/x/tools/gopls/internal/lsp/source"
119891-)
119892-
119893-func TestWorkspaceSymbolMissingMetadata(t *testing.T) {
119894-	const files = `
119895--- go.mod --
119896-module mod.com
119897-
119898-go 1.17
119899--- a.go --
119900-package p
119901-
119902-const C1 = "a.go"
119903--- exclude.go --
119904-
119905-//go:build exclude
119906-// +build exclude
119907-
119908-package exclude
119909-
119910-const C2 = "exclude.go"
119911-`
119912-
119913-	Run(t, files, func(t *testing.T, env *Env) {
119914-		env.OpenFile("a.go")
119915-		syms := env.Symbol("C")
119916-		if got, want := len(syms), 1; got != want {
119917-			t.Errorf("got %d symbols, want %d", got, want)
119918-		}
119919-
119920-		// Opening up an ignored file will result in an overlay with missing
119921-		// metadata, but this shouldn't break workspace symbols requests.
119922-		env.OpenFile("exclude.go")
119923-		syms = env.Symbol("C")
119924-		if got, want := len(syms), 1; got != want {
119925-			t.Errorf("got %d symbols, want %d", got, want)
119926-		}
119927-	})
119928-}
119929-
119930-func TestWorkspaceSymbolSorting(t *testing.T) {
119931-	const files = `
119932--- go.mod --
119933-module mod.com
119934-
119935-go 1.17
119936--- a/a.go --
119937-package a
119938-
119939-const (
119940-	Foo = iota
119941-	FooBar
119942-	Fooey
119943-	Fooex
119944-	Fooest
119945-)
119946-`
119947-
119948-	var symbolMatcher = string(source.SymbolFastFuzzy)
119949-	WithOptions(
119950-		Settings{"symbolMatcher": symbolMatcher},
119951-	).Run(t, files, func(t *testing.T, env *Env) {
119952-		want := []string{
119953-			"Foo",    // prefer exact segment matches first
119954-			"FooBar", // ...followed by exact word matches
119955-			"Fooex",  // shorter than Fooest, FooBar, lexically before Fooey
119956-			"Fooey",  // shorter than Fooest, Foobar
119957-			"Fooest",
119958-		}
119959-		got := env.Symbol("Foo")
119960-		compareSymbols(t, got, want...)
119961-	})
119962-}
119963-
119964-func TestWorkspaceSymbolSpecialPatterns(t *testing.T) {
119965-	const files = `
119966--- go.mod --
119967-module mod.com
119968-
119969-go 1.17
119970--- a/a.go --
119971-package a
119972-
119973-const (
119974-	AxxBxxCxx
119975-	ABC
119976-)
119977-`
119978-
119979-	var symbolMatcher = string(source.SymbolFastFuzzy)
119980-	WithOptions(
119981-		Settings{"symbolMatcher": symbolMatcher},
119982-	).Run(t, files, func(t *testing.T, env *Env) {
119983-		compareSymbols(t, env.Symbol("ABC"), "ABC", "AxxBxxCxx")
119984-		compareSymbols(t, env.Symbol("'ABC"), "ABC")
119985-		compareSymbols(t, env.Symbol("^mod.com"), "mod.com/a.ABC", "mod.com/a.AxxBxxCxx")
119986-		compareSymbols(t, env.Symbol("^mod.com Axx"), "mod.com/a.AxxBxxCxx")
119987-		compareSymbols(t, env.Symbol("C$"), "ABC")
119988-	})
119989-}
119990-
119991-func compareSymbols(t *testing.T, got []protocol.SymbolInformation, want ...string) {
119992-	t.Helper()
119993-	if len(got) != len(want) {
119994-		t.Errorf("got %d symbols, want %d", len(got), len(want))
119995-	}
119996-
119997-	for i := range got {
119998-		if got[i].Name != want[i] {
119999-			t.Errorf("got[%d] = %q, want %q", i, got[i].Name, want[i])
120000-		}
120001-	}
120002-}
120003diff -urN a/gopls/internal/regtest/modfile/modfile_test.go b/gopls/internal/regtest/modfile/modfile_test.go
120004--- a/gopls/internal/regtest/modfile/modfile_test.go	2000-01-01 00:00:00.000000000 -0000
120005+++ b/gopls/internal/regtest/modfile/modfile_test.go	1970-01-01 00:00:00.000000000 +0000
120006@@ -1,1188 +0,0 @@
120007-// Copyright 2020 The Go Authors. All rights reserved.
120008-// Use of this source code is governed by a BSD-style
120009-// license that can be found in the LICENSE file.
120010-
120011-package modfile
120012-
120013-import (
120014-	"path/filepath"
120015-	"runtime"
120016-	"strings"
120017-	"testing"
120018-
120019-	"golang.org/x/tools/gopls/internal/hooks"
120020-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
120021-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
120022-	"golang.org/x/tools/internal/bug"
120023-
120024-	"golang.org/x/tools/gopls/internal/lsp/protocol"
120025-	"golang.org/x/tools/internal/testenv"
120026-)
120027-
120028-func TestMain(m *testing.M) {
120029-	bug.PanicOnBugs = true
120030-	Main(m, hooks.Options)
120031-}
120032-
120033-const workspaceProxy = `
120034--- [email protected]/go.mod --
120035-module example.com
120036-
120037-go 1.12
120038--- [email protected]/blah/blah.go --
120039-package blah
120040-
120041-func SaySomething() {
120042-	fmt.Println("something")
120043-}
120044--- [email protected]/go.mod --
120045-module random.org
120046-
120047-go 1.12
120048--- [email protected]/bye/bye.go --
120049-package bye
120050-
120051-func Goodbye() {
120052-	println("Bye")
120053-}
120054-`
120055-
120056-const proxy = `
120057--- [email protected]/go.mod --
120058-module example.com
120059-
120060-go 1.12
120061--- [email protected]/blah/blah.go --
120062-package blah
120063-
120064-const Name = "Blah"
120065--- [email protected]/go.mod --
120066-module random.org
120067-
120068-go 1.12
120069--- [email protected]/blah/blah.go --
120070-package hello
120071-
120072-const Name = "Hello"
120073-`
120074-
120075-func TestModFileModification(t *testing.T) {
120076-	const untidyModule = `
120077--- a/go.mod --
120078-module mod.com
120079-
120080--- a/main.go --
120081-package main
120082-
120083-import "example.com/blah"
120084-
120085-func main() {
120086-	println(blah.Name)
120087-}
120088-`
120089-
120090-	runner := RunMultiple{
120091-		{"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
120092-		{"nested", WithOptions(ProxyFiles(proxy))},
120093-	}
120094-
120095-	t.Run("basic", func(t *testing.T) {
120096-		runner.Run(t, untidyModule, func(t *testing.T, env *Env) {
120097-			// Open the file and make sure that the initial workspace load does not
120098-			// modify the go.mod file.
120099-			goModContent := env.ReadWorkspaceFile("a/go.mod")
120100-			env.OpenFile("a/main.go")
120101-			env.AfterChange(
120102-				Diagnostics(env.AtRegexp("a/main.go", "\"example.com/blah\"")),
120103-			)
120104-			if got := env.ReadWorkspaceFile("a/go.mod"); got != goModContent {
120105-				t.Fatalf("go.mod changed on disk:\n%s", compare.Text(goModContent, got))
120106-			}
120107-			// Save the buffer, which will format and organize imports.
120108-			// Confirm that the go.mod file still does not change.
120109-			env.SaveBuffer("a/main.go")
120110-			env.AfterChange(
120111-				Diagnostics(env.AtRegexp("a/main.go", "\"example.com/blah\"")),
120112-			)
120113-			if got := env.ReadWorkspaceFile("a/go.mod"); got != goModContent {
120114-				t.Fatalf("go.mod changed on disk:\n%s", compare.Text(goModContent, got))
120115-			}
120116-		})
120117-	})
120118-
120119-	// Reproduce golang/go#40269 by deleting and recreating main.go.
120120-	t.Run("delete main.go", func(t *testing.T) {
120121-		runner.Run(t, untidyModule, func(t *testing.T, env *Env) {
120122-			goModContent := env.ReadWorkspaceFile("a/go.mod")
120123-			mainContent := env.ReadWorkspaceFile("a/main.go")
120124-			env.OpenFile("a/main.go")
120125-			env.SaveBuffer("a/main.go")
120126-
120127-			// Ensure that we're done processing all the changes caused by opening
120128-			// and saving above. If not, we may run into a file locking issue on
120129-			// windows.
120130-			//
120131-			// If this proves insufficient, env.RemoveWorkspaceFile can be updated to
120132-			// retry file lock errors on windows.
120133-			env.AfterChange()
120134-			env.RemoveWorkspaceFile("a/main.go")
120135-
120136-			// TODO(rfindley): awaiting here shouldn't really be necessary. We should
120137-			// be consistent eventually.
120138-			//
120139-			// Probably this was meant to exercise a race with the change below.
120140-			env.AfterChange()
120141-
120142-			env.WriteWorkspaceFile("a/main.go", mainContent)
120143-			env.AfterChange(
120144-				Diagnostics(env.AtRegexp("a/main.go", "\"example.com/blah\"")),
120145-			)
120146-			if got := env.ReadWorkspaceFile("a/go.mod"); got != goModContent {
120147-				t.Fatalf("go.mod changed on disk:\n%s", compare.Text(goModContent, got))
120148-			}
120149-		})
120150-	})
120151-}
120152-
120153-func TestGoGetFix(t *testing.T) {
120154-	const mod = `
120155--- a/go.mod --
120156-module mod.com
120157-
120158-go 1.12
120159-
120160--- a/main.go --
120161-package main
120162-
120163-import "example.com/blah"
120164-
120165-var _ = blah.Name
120166-`
120167-
120168-	const want = `module mod.com
120169-
120170-go 1.12
120171-
120172-require example.com v1.2.3
120173-`
120174-
120175-	RunMultiple{
120176-		{"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
120177-		{"nested", WithOptions(ProxyFiles(proxy))},
120178-	}.Run(t, mod, func(t *testing.T, env *Env) {
120179-		if strings.Contains(t.Name(), "workspace_module") {
120180-			t.Skip("workspace module mode doesn't set -mod=readonly")
120181-		}
120182-		env.OpenFile("a/main.go")
120183-		var d protocol.PublishDiagnosticsParams
120184-		env.AfterChange(
120185-			Diagnostics(env.AtRegexp("a/main.go", `"example.com/blah"`)),
120186-			ReadDiagnostics("a/main.go", &d),
120187-		)
120188-		var goGetDiag protocol.Diagnostic
120189-		for _, diag := range d.Diagnostics {
120190-			if strings.Contains(diag.Message, "could not import") {
120191-				goGetDiag = diag
120192-			}
120193-		}
120194-		env.ApplyQuickFixes("a/main.go", []protocol.Diagnostic{goGetDiag})
120195-		if got := env.ReadWorkspaceFile("a/go.mod"); got != want {
120196-			t.Fatalf("unexpected go.mod content:\n%s", compare.Text(want, got))
120197-		}
120198-	})
120199-}
120200-
120201-// Tests that multiple missing dependencies gives good single fixes.
120202-func TestMissingDependencyFixes(t *testing.T) {
120203-	const mod = `
120204--- a/go.mod --
120205-module mod.com
120206-
120207-go 1.12
120208-
120209--- a/main.go --
120210-package main
120211-
120212-import "example.com/blah"
120213-import "random.org/blah"
120214-
120215-var _, _ = blah.Name, hello.Name
120216-`
120217-
120218-	const want = `module mod.com
120219-
120220-go 1.12
120221-
120222-require random.org v1.2.3
120223-`
120224-
120225-	RunMultiple{
120226-		{"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
120227-		{"nested", WithOptions(ProxyFiles(proxy))},
120228-	}.Run(t, mod, func(t *testing.T, env *Env) {
120229-		env.OpenFile("a/main.go")
120230-		var d protocol.PublishDiagnosticsParams
120231-		env.AfterChange(
120232-			Diagnostics(env.AtRegexp("a/main.go", `"random.org/blah"`)),
120233-			ReadDiagnostics("a/main.go", &d),
120234-		)
120235-		var randomDiag protocol.Diagnostic
120236-		for _, diag := range d.Diagnostics {
120237-			if strings.Contains(diag.Message, "random.org") {
120238-				randomDiag = diag
120239-			}
120240-		}
120241-		env.ApplyQuickFixes("a/main.go", []protocol.Diagnostic{randomDiag})
120242-		if got := env.ReadWorkspaceFile("a/go.mod"); got != want {
120243-			t.Fatalf("unexpected go.mod content:\n%s", compare.Text(want, got))
120244-		}
120245-	})
120246-}
120247-
120248-// Tests that multiple missing dependencies gives good single fixes.
120249-func TestMissingDependencyFixesWithGoWork(t *testing.T) {
120250-	testenv.NeedsGo1Point(t, 18)
120251-	const mod = `
120252--- go.work --
120253-go 1.18
120254-
120255-use (
120256-	./a
120257-)
120258--- a/go.mod --
120259-module mod.com
120260-
120261-go 1.12
120262-
120263--- a/main.go --
120264-package main
120265-
120266-import "example.com/blah"
120267-import "random.org/blah"
120268-
120269-var _, _ = blah.Name, hello.Name
120270-`
120271-
120272-	const want = `module mod.com
120273-
120274-go 1.12
120275-
120276-require random.org v1.2.3
120277-`
120278-
120279-	RunMultiple{
120280-		{"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
120281-		{"nested", WithOptions(ProxyFiles(proxy))},
120282-	}.Run(t, mod, func(t *testing.T, env *Env) {
120283-		env.OpenFile("a/main.go")
120284-		var d protocol.PublishDiagnosticsParams
120285-		env.AfterChange(
120286-			Diagnostics(env.AtRegexp("a/main.go", `"random.org/blah"`)),
120287-			ReadDiagnostics("a/main.go", &d),
120288-		)
120289-		var randomDiag protocol.Diagnostic
120290-		for _, diag := range d.Diagnostics {
120291-			if strings.Contains(diag.Message, "random.org") {
120292-				randomDiag = diag
120293-			}
120294-		}
120295-		env.ApplyQuickFixes("a/main.go", []protocol.Diagnostic{randomDiag})
120296-		if got := env.ReadWorkspaceFile("a/go.mod"); got != want {
120297-			t.Fatalf("unexpected go.mod content:\n%s", compare.Text(want, got))
120298-		}
120299-	})
120300-}
120301-
120302-func TestIndirectDependencyFix(t *testing.T) {
120303-	const mod = `
120304--- a/go.mod --
120305-module mod.com
120306-
120307-go 1.12
120308-
120309-require example.com v1.2.3 // indirect
120310--- a/go.sum --
120311-example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
120312-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
120313--- a/main.go --
120314-package main
120315-
120316-import "example.com/blah"
120317-
120318-func main() {
120319-	fmt.Println(blah.Name)
120320-`
120321-	const want = `module mod.com
120322-
120323-go 1.12
120324-
120325-require example.com v1.2.3
120326-`
120327-
120328-	RunMultiple{
120329-		{"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
120330-		{"nested", WithOptions(ProxyFiles(proxy))},
120331-	}.Run(t, mod, func(t *testing.T, env *Env) {
120332-		env.OpenFile("a/go.mod")
120333-		var d protocol.PublishDiagnosticsParams
120334-		env.AfterChange(
120335-			Diagnostics(env.AtRegexp("a/go.mod", "// indirect")),
120336-			ReadDiagnostics("a/go.mod", &d),
120337-		)
120338-		env.ApplyQuickFixes("a/go.mod", d.Diagnostics)
120339-		if got := env.BufferText("a/go.mod"); got != want {
120340-			t.Fatalf("unexpected go.mod content:\n%s", compare.Text(want, got))
120341-		}
120342-	})
120343-}
120344-
120345-func TestUnusedDiag(t *testing.T) {
120346-
120347-	const proxy = `
120348--- [email protected]/x.go --
120349-package pkg
120350-const X = 1
120351-`
120352-	const files = `
120353--- a/go.mod --
120354-module mod.com
120355-go 1.14
120356-require example.com v1.0.0
120357--- a/go.sum --
120358-example.com v1.0.0 h1:38O7j5rEBajXk+Q5wzLbRN7KqMkSgEiN9NqcM1O2bBM=
120359-example.com v1.0.0/go.mod h1:vUsPMGpx9ZXXzECCOsOmYCW7npJTwuA16yl89n3Mgls=
120360--- a/main.go --
120361-package main
120362-func main() {}
120363-`
120364-
120365-	const want = `module mod.com
120366-
120367-go 1.14
120368-`
120369-
120370-	RunMultiple{
120371-		{"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
120372-		{"nested", WithOptions(ProxyFiles(proxy))},
120373-	}.Run(t, files, func(t *testing.T, env *Env) {
120374-		env.OpenFile("a/go.mod")
120375-		var d protocol.PublishDiagnosticsParams
120376-		env.AfterChange(
120377-			Diagnostics(env.AtRegexp("a/go.mod", `require example.com`)),
120378-			ReadDiagnostics("a/go.mod", &d),
120379-		)
120380-		env.ApplyQuickFixes("a/go.mod", d.Diagnostics)
120381-		if got := env.BufferText("a/go.mod"); got != want {
120382-			t.Fatalf("unexpected go.mod content:\n%s", compare.Text(want, got))
120383-		}
120384-	})
120385-}
120386-
120387-// Test to reproduce golang/go#39041. It adds a new require to a go.mod file
120388-// that already has an unused require.
120389-func TestNewDepWithUnusedDep(t *testing.T) {
120390-
120391-	const proxy = `
120392--- github.com/esimov/caire@v1.2.5/go.mod --
120393-module github.com/esimov/caire
120394-
120395-go 1.12
120396--- github.com/esimov/caire@v1.2.5/caire.go --
120397-package caire
120398-
120399-func RemoveTempImage() {}
120400--- google.golang.org/protobuf@v1.20.0/go.mod --
120401-module google.golang.org/protobuf
120402-
120403-go 1.12
120404--- google.golang.org/protobuf@v1.20.0/hello/hello.go --
120405-package hello
120406-`
120407-	const repro = `
120408--- a/go.mod --
120409-module mod.com
120410-
120411-go 1.14
120412-
120413-require google.golang.org/protobuf v1.20.0
120414--- a/go.sum --
120415-github.com/esimov/caire v1.2.5 h1:OcqDII/BYxcBYj3DuwDKjd+ANhRxRqLa2n69EGje7qw=
120416-github.com/esimov/caire v1.2.5/go.mod h1:mXnjRjg3+WUtuhfSC1rKRmdZU9vJZyS1ZWU0qSvJhK8=
120417-google.golang.org/protobuf v1.20.0 h1:y9T1vAtFKQg0faFNMOxJU7WuEqPWolVkjIkU6aI8qCY=
120418-google.golang.org/protobuf v1.20.0/go.mod h1:FcqsytGClbtLv1ot8NvsJHjBi0h22StKVP+K/j2liKA=
120419--- a/main.go --
120420-package main
120421-
120422-import (
120423-    "github.com/esimov/caire"
120424-)
120425-
120426-func _() {
120427-    caire.RemoveTempImage()
120428-}`
120429-
120430-	RunMultiple{
120431-		{"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
120432-		{"nested", WithOptions(ProxyFiles(proxy))},
120433-	}.Run(t, repro, func(t *testing.T, env *Env) {
120434-		env.OpenFile("a/main.go")
120435-		var d protocol.PublishDiagnosticsParams
120436-		env.AfterChange(
120437-			Diagnostics(env.AtRegexp("a/main.go", `"github.com/esimov/caire"`)),
120438-			ReadDiagnostics("a/main.go", &d),
120439-		)
120440-		env.ApplyQuickFixes("a/main.go", d.Diagnostics)
120441-		want := `module mod.com
120442-
120443-go 1.14
120444-
120445-require (
120446-	github.com/esimov/caire v1.2.5
120447-	google.golang.org/protobuf v1.20.0
120448-)
120449-`
120450-		if got := env.ReadWorkspaceFile("a/go.mod"); got != want {
120451-			t.Fatalf("TestNewDepWithUnusedDep failed:\n%s", compare.Text(want, got))
120452-		}
120453-	})
120454-}
120455-
120456-// TODO: For this test to be effective, the sandbox's file watcher must respect
120457-// the file watching GlobPattern in the capability registration. See
120458-// golang/go#39384.
120459-func TestModuleChangesOnDisk(t *testing.T) {
120460-	const mod = `
120461--- a/go.mod --
120462-module mod.com
120463-
120464-go 1.12
120465-
120466-require example.com v1.2.3
120467--- a/go.sum --
120468-example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
120469-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
120470--- a/main.go --
120471-package main
120472-
120473-func main() {
120474-	fmt.Println(blah.Name)
120475-`
120476-	RunMultiple{
120477-		{"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
120478-		{"nested", WithOptions(ProxyFiles(proxy))},
120479-	}.Run(t, mod, func(t *testing.T, env *Env) {
120480-		env.OnceMet(
120481-			InitialWorkspaceLoad,
120482-			Diagnostics(env.AtRegexp("a/go.mod", "require")),
120483-		)
120484-		env.RunGoCommandInDir("a", "mod", "tidy")
120485-		env.AfterChange(
120486-			NoDiagnostics(ForFile("a/go.mod")),
120487-		)
120488-	})
120489-}
120490-
120491-// Tests golang/go#39784: a missing indirect dependency, necessary
120492-// due to [email protected]'s incomplete go.mod file.
120493-func TestBadlyVersionedModule(t *testing.T) {
120494-	const proxy = `
120495--- example.com/blah/@v/v1.0.0.mod --
120496-module example.com
120497-
120498-go 1.12
120499--- example.com/blah@v1.0.0/blah.go --
120500-package blah
120501-
120502-const Name = "Blah"
120503--- example.com/blah/v2/@v/v2.0.0.mod --
120504-module example.com
120505-
120506-go 1.12
120507--- example.com/blah/v2@v2.0.0/blah.go --
120508-package blah
120509-
120510-import "example.com/blah"
120511-
120512-var V1Name = blah.Name
120513-const Name = "Blah"
120514-`
120515-	const files = `
120516--- a/go.mod --
120517-module mod.com
120518-
120519-go 1.12
120520-
120521-require example.com/blah/v2 v2.0.0
120522--- a/go.sum --
120523-example.com/blah v1.0.0 h1:kGPlWJbMsn1P31H9xp/q2mYI32cxLnCvauHN0AVaHnc=
120524-example.com/blah v1.0.0/go.mod h1:PZUQaGFeVjyDmAE8ywmLbmDn3fj4Ws8epg4oLuDzW3M=
120525-example.com/blah/v2 v2.0.0 h1:DNPsFPkKtTdxclRheaMCiYAoYizp6PuBzO0OmLOO0pY=
120526-example.com/blah/v2 v2.0.0/go.mod h1:UZiKbTwobERo/hrqFLvIQlJwQZQGxWMVY4xere8mj7w=
120527--- a/main.go --
120528-package main
120529-
120530-import "example.com/blah/v2"
120531-
120532-var _ = blah.Name
120533-`
120534-	RunMultiple{
120535-		{"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
120536-		{"nested", WithOptions(ProxyFiles(proxy))},
120537-	}.Run(t, files, func(t *testing.T, env *Env) {
120538-		env.OpenFile("a/main.go")
120539-		env.OpenFile("a/go.mod")
120540-		var modDiags protocol.PublishDiagnosticsParams
120541-		env.AfterChange(
120542-			// We would like for the error to appear in the v2 module, but
120543-			// as of writing non-workspace packages are not diagnosed.
120544-			Diagnostics(env.AtRegexp("a/main.go", `"example.com/blah/v2"`), WithMessage("cannot find module providing")),
120545-			Diagnostics(env.AtRegexp("a/go.mod", `require example.com/blah/v2`), WithMessage("cannot find module providing")),
120546-			ReadDiagnostics("a/go.mod", &modDiags),
120547-		)
120548-		env.ApplyQuickFixes("a/go.mod", modDiags.Diagnostics)
120549-		const want = `module mod.com
120550-
120551-go 1.12
120552-
120553-require (
120554-	example.com/blah v1.0.0 // indirect
120555-	example.com/blah/v2 v2.0.0
120556-)
120557-`
120558-		env.SaveBuffer("a/go.mod")
120559-		env.AfterChange(NoDiagnostics(ForFile("a/main.go")))
120560-		if got := env.BufferText("a/go.mod"); got != want {
120561-			t.Fatalf("suggested fixes failed:\n%s", compare.Text(want, got))
120562-		}
120563-	})
120564-}
120565-
120566-// Reproduces golang/go#38232.
120567-func TestUnknownRevision(t *testing.T) {
120568-	if runtime.GOOS == "plan9" {
120569-		t.Skipf("skipping test that fails for unknown reasons on plan9; see https://go.dev/issue/50477")
120570-	}
120571-	const unknown = `
120572--- a/go.mod --
120573-module mod.com
120574-
120575-require (
120576-	example.com v1.2.2
120577-)
120578--- a/main.go --
120579-package main
120580-
120581-import "example.com/blah"
120582-
120583-func main() {
120584-	var x = blah.Name
120585-}
120586-`
120587-
120588-	runner := RunMultiple{
120589-		{"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
120590-		{"nested", WithOptions(ProxyFiles(proxy))},
120591-	}
120592-	// Start from a bad state/bad IWL, and confirm that we recover.
120593-	t.Run("bad", func(t *testing.T) {
120594-		runner.Run(t, unknown, func(t *testing.T, env *Env) {
120595-			env.OpenFile("a/go.mod")
120596-			env.AfterChange(
120597-				Diagnostics(env.AtRegexp("a/go.mod", "example.com v1.2.2")),
120598-			)
120599-			env.RegexpReplace("a/go.mod", "v1.2.2", "v1.2.3")
120600-			env.SaveBuffer("a/go.mod") // Save to trigger diagnostics.
120601-
120602-			d := protocol.PublishDiagnosticsParams{}
120603-			env.AfterChange(
120604-				// Make sure the diagnostic mentions the new version -- the old diagnostic is in the same place.
120605-				Diagnostics(env.AtRegexp("a/go.mod", "example.com v1.2.3"), WithMessage("[email protected]")),
120606-				ReadDiagnostics("a/go.mod", &d),
120607-			)
120608-			qfs := env.GetQuickFixes("a/go.mod", d.Diagnostics)
120609-			if len(qfs) == 0 {
120610-				t.Fatalf("got 0 code actions to fix %v, wanted at least 1", d.Diagnostics)
120611-			}
120612-			env.ApplyCodeAction(qfs[0]) // Arbitrarily pick a single fix to apply. Applying all of them seems to cause trouble in this particular test.
120613-			env.SaveBuffer("a/go.mod")  // Save to trigger diagnostics.
120614-			env.AfterChange(
120615-				NoDiagnostics(ForFile("a/go.mod")),
120616-				Diagnostics(env.AtRegexp("a/main.go", "x = ")),
120617-			)
120618-		})
120619-	})
120620-
120621-	const known = `
120622--- a/go.mod --
120623-module mod.com
120624-
120625-require (
120626-	example.com v1.2.3
120627-)
120628--- a/go.sum --
120629-example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
120630-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
120631--- a/main.go --
120632-package main
120633-
120634-import "example.com/blah"
120635-
120636-func main() {
120637-	var x = blah.Name
120638-}
120639-`
120640-	// Start from a good state, transform to a bad state, and confirm that we
120641-	// still recover.
120642-	t.Run("good", func(t *testing.T) {
120643-		runner.Run(t, known, func(t *testing.T, env *Env) {
120644-			env.OpenFile("a/go.mod")
120645-			env.AfterChange(
120646-				Diagnostics(env.AtRegexp("a/main.go", "x = ")),
120647-			)
120648-			env.RegexpReplace("a/go.mod", "v1.2.3", "v1.2.2")
120649-			env.Editor.SaveBuffer(env.Ctx, "a/go.mod") // go.mod changes must be on disk
120650-			env.AfterChange(
120651-				Diagnostics(env.AtRegexp("a/go.mod", "example.com v1.2.2")),
120652-			)
120653-			env.RegexpReplace("a/go.mod", "v1.2.2", "v1.2.3")
120654-			env.Editor.SaveBuffer(env.Ctx, "a/go.mod") // go.mod changes must be on disk
120655-			env.AfterChange(
120656-				Diagnostics(env.AtRegexp("a/main.go", "x = ")),
120657-			)
120658-		})
120659-	})
120660-}
120661-
120662-// Confirm that an error in an indirect dependency of a requirement is surfaced
120663-// as a diagnostic in the go.mod file.
120664-func TestErrorInIndirectDependency(t *testing.T) {
120665-	const badProxy = `
120666--- [email protected]/go.mod --
120667-module example.com
120668-
120669-go 1.12
120670-
120671-require random.org v1.2.3 // indirect
120672--- [email protected]/blah/blah.go --
120673-package blah
120674-
120675-const Name = "Blah"
120676--- [email protected]/go.mod --
120677-module bob.org
120678-
120679-go 1.12
120680--- [email protected]/blah/blah.go --
120681-package hello
120682-
120683-const Name = "Hello"
120684-`
120685-	const module = `
120686--- a/go.mod --
120687-module mod.com
120688-
120689-go 1.14
120690-
120691-require example.com v1.2.3
120692--- a/main.go --
120693-package main
120694-
120695-import "example.com/blah"
120696-
120697-func main() {
120698-	println(blah.Name)
120699-}
120700-`
120701-	RunMultiple{
120702-		{"default", WithOptions(ProxyFiles(badProxy), WorkspaceFolders("a"))},
120703-		{"nested", WithOptions(ProxyFiles(badProxy))},
120704-	}.Run(t, module, func(t *testing.T, env *Env) {
120705-		env.OpenFile("a/go.mod")
120706-		env.AfterChange(
120707-			Diagnostics(env.AtRegexp("a/go.mod", "require example.com v1.2.3")),
120708-		)
120709-	})
120710-}
120711-
120712-// A copy of govim's config_set_env_goflags_mod_readonly test.
120713-func TestGovimModReadonly(t *testing.T) {
120714-	const mod = `
120715--- go.mod --
120716-module mod.com
120717-
120718-go 1.13
120719--- main.go --
120720-package main
120721-
120722-import "example.com/blah"
120723-
120724-func main() {
120725-	println(blah.Name)
120726-}
120727-`
120728-	WithOptions(
120729-		EnvVars{"GOFLAGS": "-mod=readonly"},
120730-		ProxyFiles(proxy),
120731-		Modes(Default),
120732-	).Run(t, mod, func(t *testing.T, env *Env) {
120733-		env.OpenFile("main.go")
120734-		original := env.ReadWorkspaceFile("go.mod")
120735-		env.AfterChange(
120736-			Diagnostics(env.AtRegexp("main.go", `"example.com/blah"`)),
120737-		)
120738-		got := env.ReadWorkspaceFile("go.mod")
120739-		if got != original {
120740-			t.Fatalf("go.mod file modified:\n%s", compare.Text(original, got))
120741-		}
120742-		env.RunGoCommand("get", "example.com/blah@v1.2.3")
120743-		env.RunGoCommand("mod", "tidy")
120744-		env.AfterChange(
120745-			NoDiagnostics(ForFile("main.go")),
120746-		)
120747-	})
120748-}
120749-
120750-func TestMultiModuleModDiagnostics(t *testing.T) {
120751-	testenv.NeedsGo1Point(t, 18) // uses go.work
120752-	const mod = `
120753--- go.work --
120754-go 1.18
120755-
120756-use (
120757-	a
120758-	b
120759-)
120760--- a/go.mod --
120761-module moda.com
120762-
120763-go 1.14
120764-
120765-require (
120766-	example.com v1.2.3
120767-)
120768--- a/go.sum --
120769-example.com v1.2.3 h1:Yryq11hF02fEf2JlOS2eph+ICE2/ceevGV3C9dl5V/c=
120770-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
120771--- a/main.go --
120772-package main
120773-
120774-func main() {}
120775--- b/go.mod --
120776-module modb.com
120777-
120778-require example.com v1.2.3
120779-
120780-go 1.14
120781--- b/main.go --
120782-package main
120783-
120784-import "example.com/blah"
120785-
120786-func main() {
120787-	blah.SaySomething()
120788-}
120789-`
120790-	WithOptions(
120791-		ProxyFiles(workspaceProxy),
120792-	).Run(t, mod, func(t *testing.T, env *Env) {
120793-		env.AfterChange(
120794-			Diagnostics(
120795-				env.AtRegexp("a/go.mod", "example.com v1.2.3"),
120796-				WithMessage("is not used"),
120797-			),
120798-		)
120799-	})
120800-}
120801-
120802-func TestModTidyWithBuildTags(t *testing.T) {
120803-	const mod = `
120804--- go.mod --
120805-module mod.com
120806-
120807-go 1.14
120808--- main.go --
120809-// +build bob
120810-
120811-package main
120812-
120813-import "example.com/blah"
120814-
120815-func main() {
120816-	blah.SaySomething()
120817-}
120818-`
120819-	WithOptions(
120820-		ProxyFiles(workspaceProxy),
120821-		Settings{"buildFlags": []string{"-tags", "bob"}},
120822-	).Run(t, mod, func(t *testing.T, env *Env) {
120823-		env.OnceMet(
120824-			InitialWorkspaceLoad,
120825-			Diagnostics(env.AtRegexp("main.go", `"example.com/blah"`)),
120826-		)
120827-	})
120828-}
120829-
120830-func TestModTypoDiagnostic(t *testing.T) {
120831-	const mod = `
120832--- go.mod --
120833-module mod.com
120834-
120835-go 1.12
120836--- main.go --
120837-package main
120838-
120839-func main() {}
120840-`
120841-	Run(t, mod, func(t *testing.T, env *Env) {
120842-		env.OpenFile("go.mod")
120843-		env.RegexpReplace("go.mod", "module", "modul")
120844-		env.AfterChange(
120845-			Diagnostics(env.AtRegexp("go.mod", "modul")),
120846-		)
120847-	})
120848-}
120849-
120850-func TestSumUpdateFixesDiagnostics(t *testing.T) {
120851-	const mod = `
120852--- go.mod --
120853-module mod.com
120854-
120855-go 1.12
120856-
120857-require (
120858-	example.com v1.2.3
120859-)
120860--- go.sum --
120861--- main.go --
120862-package main
120863-
120864-import (
120865-	"example.com/blah"
120866-)
120867-
120868-func main() {
120869-	println(blah.Name)
120870-}
120871-`
120872-	WithOptions(
120873-		ProxyFiles(workspaceProxy),
120874-	).Run(t, mod, func(t *testing.T, env *Env) {
120875-		d := &protocol.PublishDiagnosticsParams{}
120876-		env.OpenFile("go.mod")
120877-		env.AfterChange(
120878-			Diagnostics(
120879-				env.AtRegexp("go.mod", `example.com v1.2.3`),
120880-				WithMessage("go.sum is out of sync"),
120881-			),
120882-			ReadDiagnostics("go.mod", d),
120883-		)
120884-		env.ApplyQuickFixes("go.mod", d.Diagnostics)
120885-		env.SaveBuffer("go.mod") // Save to trigger diagnostics.
120886-		env.AfterChange(
120887-			NoDiagnostics(ForFile("go.mod")),
120888-		)
120889-	})
120890-}
120891-
120892-// This test confirms that editing a go.mod file only causes metadata
120893-// to be invalidated when it's saved.
120894-func TestGoModInvalidatesOnSave(t *testing.T) {
120895-	const mod = `
120896--- go.mod --
120897-module mod.com
120898-
120899-go 1.12
120900--- main.go --
120901-package main
120902-
120903-func main() {
120904-	hello()
120905-}
120906--- hello.go --
120907-package main
120908-
120909-func hello() {}
120910-`
120911-	WithOptions(
120912-		// TODO(rFindley) this doesn't work in multi-module workspace mode, because
120913-		// it keeps around the last parsing modfile. Update this test to also
120914-		// exercise the workspace module.
120915-		Modes(Default),
120916-	).Run(t, mod, func(t *testing.T, env *Env) {
120917-		env.OpenFile("go.mod")
120918-		env.Await(env.DoneWithOpen())
120919-		env.RegexpReplace("go.mod", "module", "modul")
120920-		// Confirm that we still have metadata with only on-disk edits.
120921-		env.OpenFile("main.go")
120922-		loc := env.GoToDefinition(env.RegexpSearch("main.go", "hello"))
120923-		if filepath.Base(string(loc.URI)) != "hello.go" {
120924-			t.Fatalf("expected definition in hello.go, got %s", loc.URI)
120925-		}
120926-		// Confirm that we no longer have metadata when the file is saved.
120927-		env.SaveBufferWithoutActions("go.mod")
120928-		_, err := env.Editor.GoToDefinition(env.Ctx, env.RegexpSearch("main.go", "hello"))
120929-		if err == nil {
120930-			t.Fatalf("expected error, got none")
120931-		}
120932-	})
120933-}
120934-
120935-func TestRemoveUnusedDependency(t *testing.T) {
120936-	const proxy = `
120937--- [email protected]/go.mod --
120938-module hasdep.com
120939-
120940-go 1.12
120941-
120942-require example.com v1.2.3
120943--- [email protected]/a/a.go --
120944-package a
120945--- [email protected]/go.mod --
120946-module example.com
120947-
120948-go 1.12
120949--- [email protected]/blah/blah.go --
120950-package blah
120951-
120952-const Name = "Blah"
120953--- [email protected]/go.mod --
120954-module random.com
120955-
120956-go 1.12
120957--- [email protected]/blah/blah.go --
120958-package blah
120959-
120960-const Name = "Blah"
120961-`
120962-	t.Run("almost tidied", func(t *testing.T) {
120963-		const mod = `
120964--- go.mod --
120965-module mod.com
120966-
120967-go 1.12
120968-
120969-require hasdep.com v1.2.3
120970--- go.sum --
120971-example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
120972-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
120973-hasdep.com v1.2.3 h1:00y+N5oD+SpKoqV1zP2VOPawcW65Zb9NebANY3GSzGI=
120974-hasdep.com v1.2.3/go.mod h1:ePVZOlez+KZEOejfLPGL2n4i8qiAjrkhQZ4wcImqAes=
120975--- main.go --
120976-package main
120977-
120978-func main() {}
120979-`
120980-		WithOptions(
120981-			ProxyFiles(proxy),
120982-		).Run(t, mod, func(t *testing.T, env *Env) {
120983-			env.OpenFile("go.mod")
120984-			d := &protocol.PublishDiagnosticsParams{}
120985-			env.AfterChange(
120986-				Diagnostics(env.AtRegexp("go.mod", "require hasdep.com v1.2.3")),
120987-				ReadDiagnostics("go.mod", d),
120988-			)
120989-			const want = `module mod.com
120990-
120991-go 1.12
120992-`
120993-			env.ApplyQuickFixes("go.mod", d.Diagnostics)
120994-			if got := env.BufferText("go.mod"); got != want {
120995-				t.Fatalf("unexpected content in go.mod:\n%s", compare.Text(want, got))
120996-			}
120997-		})
120998-	})
120999-
121000-	t.Run("not tidied", func(t *testing.T) {
121001-		const mod = `
121002--- go.mod --
121003-module mod.com
121004-
121005-go 1.12
121006-
121007-require hasdep.com v1.2.3
121008-require random.com v1.2.3
121009--- go.sum --
121010-example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
121011-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
121012-hasdep.com v1.2.3 h1:00y+N5oD+SpKoqV1zP2VOPawcW65Zb9NebANY3GSzGI=
121013-hasdep.com v1.2.3/go.mod h1:ePVZOlez+KZEOejfLPGL2n4i8qiAjrkhQZ4wcImqAes=
121014-random.com v1.2.3 h1:PzYTykzqqH6+qU0dIgh9iPFbfb4Mm8zNBjWWreRKtx0=
121015-random.com v1.2.3/go.mod h1:8EGj+8a4Hw1clAp8vbaeHAsKE4sbm536FP7nKyXO+qQ=
121016--- main.go --
121017-package main
121018-
121019-func main() {}
121020-`
121021-		WithOptions(
121022-			ProxyFiles(proxy),
121023-		).Run(t, mod, func(t *testing.T, env *Env) {
121024-			d := &protocol.PublishDiagnosticsParams{}
121025-			env.OpenFile("go.mod")
121026-			pos := env.RegexpSearch("go.mod", "require hasdep.com v1.2.3").Range.Start
121027-			env.AfterChange(
121028-				Diagnostics(AtPosition("go.mod", pos.Line, pos.Character)),
121029-				ReadDiagnostics("go.mod", d),
121030-			)
121031-			const want = `module mod.com
121032-
121033-go 1.12
121034-
121035-require random.com v1.2.3
121036-`
121037-			var diagnostics []protocol.Diagnostic
121038-			for _, d := range d.Diagnostics {
121039-				if d.Range.Start.Line != uint32(pos.Line) {
121040-					continue
121041-				}
121042-				diagnostics = append(diagnostics, d)
121043-			}
121044-			env.ApplyQuickFixes("go.mod", diagnostics)
121045-			if got := env.BufferText("go.mod"); got != want {
121046-				t.Fatalf("unexpected content in go.mod:\n%s", compare.Text(want, got))
121047-			}
121048-		})
121049-	})
121050-}
121051-
121052-func TestSumUpdateQuickFix(t *testing.T) {
121053-	const mod = `
121054--- go.mod --
121055-module mod.com
121056-
121057-go 1.12
121058-
121059-require (
121060-	example.com v1.2.3
121061-)
121062--- go.sum --
121063--- main.go --
121064-package main
121065-
121066-import (
121067-	"example.com/blah"
121068-)
121069-
121070-func main() {
121071-	blah.Hello()
121072-}
121073-`
121074-	WithOptions(
121075-		ProxyFiles(workspaceProxy),
121076-		Modes(Default),
121077-	).Run(t, mod, func(t *testing.T, env *Env) {
121078-		env.OpenFile("go.mod")
121079-		params := &protocol.PublishDiagnosticsParams{}
121080-		env.AfterChange(
121081-			Diagnostics(
121082-				env.AtRegexp("go.mod", `example.com`),
121083-				WithMessage("go.sum is out of sync"),
121084-			),
121085-			ReadDiagnostics("go.mod", params),
121086-		)
121087-		env.ApplyQuickFixes("go.mod", params.Diagnostics)
121088-		const want = `example.com v1.2.3 h1:Yryq11hF02fEf2JlOS2eph+ICE2/ceevGV3C9dl5V/c=
121089-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
121090-`
121091-		if got := env.ReadWorkspaceFile("go.sum"); got != want {
121092-			t.Fatalf("unexpected go.sum contents:\n%s", compare.Text(want, got))
121093-		}
121094-	})
121095-}
121096-
121097-func TestDownloadDeps(t *testing.T) {
121098-	const proxy = `
121099--- [email protected]/go.mod --
121100-module example.com
121101-
121102-go 1.12
121103-
121104-require random.org v1.2.3
121105--- [email protected]/blah/blah.go --
121106-package blah
121107-
121108-import "random.org/bye"
121109-
121110-func SaySomething() {
121111-	bye.Goodbye()
121112-}
121113--- [email protected]/go.mod --
121114-module random.org
121115-
121116-go 1.12
121117--- [email protected]/bye/bye.go --
121118-package bye
121119-
121120-func Goodbye() {
121121-	println("Bye")
121122-}
121123-`
121124-
121125-	const mod = `
121126--- go.mod --
121127-module mod.com
121128-
121129-go 1.12
121130--- go.sum --
121131--- main.go --
121132-package main
121133-
121134-import (
121135-	"example.com/blah"
121136-)
121137-
121138-func main() {
121139-	blah.SaySomething()
121140-}
121141-`
121142-	WithOptions(
121143-		ProxyFiles(proxy),
121144-		Modes(Default),
121145-	).Run(t, mod, func(t *testing.T, env *Env) {
121146-		env.OpenFile("main.go")
121147-		d := &protocol.PublishDiagnosticsParams{}
121148-		env.AfterChange(
121149-			Diagnostics(
121150-				env.AtRegexp("main.go", `"example.com/blah"`),
121151-				WithMessage(`could not import example.com/blah (no required module provides package "example.com/blah")`),
121152-			),
121153-			ReadDiagnostics("main.go", d),
121154-		)
121155-		env.ApplyQuickFixes("main.go", d.Diagnostics)
121156-		env.AfterChange(
121157-			NoDiagnostics(ForFile("main.go")),
121158-			NoDiagnostics(ForFile("go.mod")),
121159-		)
121160-	})
121161-}
121162-
121163-func TestInvalidGoVersion(t *testing.T) {
121164-	const files = `
121165--- go.mod --
121166-module mod.com
121167-
121168-go foo
121169--- main.go --
121170-package main
121171-`
121172-	Run(t, files, func(t *testing.T, env *Env) {
121173-		env.OnceMet(
121174-			InitialWorkspaceLoad,
121175-			Diagnostics(env.AtRegexp("go.mod", `go foo`), WithMessage("invalid go version")),
121176-		)
121177-		env.WriteWorkspaceFile("go.mod", "module mod.com \n\ngo 1.12\n")
121178-		env.AfterChange(NoDiagnostics(ForFile("go.mod")))
121179-	})
121180-}
121181-
121182-// This is a regression test for a bug in the line-oriented implementation
121183-// of the "apply diffs" operation used by the fake editor.
121184-func TestIssue57627(t *testing.T) {
121185-	const files = `
121186--- go.work --
121187-package main
121188-`
121189-	Run(t, files, func(t *testing.T, env *Env) {
121190-		env.OpenFile("go.work")
121191-		env.SetBufferContent("go.work", "go 1.18\nuse moda/a")
121192-		env.SaveBuffer("go.work") // doesn't fail
121193-	})
121194-}
121195diff -urN a/gopls/internal/regtest/template/template_test.go b/gopls/internal/regtest/template/template_test.go
121196--- a/gopls/internal/regtest/template/template_test.go	2000-01-01 00:00:00.000000000 -0000
121197+++ b/gopls/internal/regtest/template/template_test.go	1970-01-01 00:00:00.000000000 +0000
121198@@ -1,231 +0,0 @@
121199-// Copyright 2022 The Go Authors. All rights reserved.
121200-// Use of this source code is governed by a BSD-style
121201-// license that can be found in the LICENSE file.
121202-
121203-package template
121204-
121205-import (
121206-	"strings"
121207-	"testing"
121208-
121209-	"golang.org/x/tools/gopls/internal/hooks"
121210-	"golang.org/x/tools/gopls/internal/lsp/protocol"
121211-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
121212-	"golang.org/x/tools/internal/bug"
121213-)
121214-
121215-func TestMain(m *testing.M) {
121216-	bug.PanicOnBugs = true
121217-	Main(m, hooks.Options)
121218-}
121219-
121220-func TestMultilineTokens(t *testing.T) {
121221-	// 51731: panic: runtime error: slice bounds out of range [38:3]
121222-	const files = `
121223--- go.mod --
121224-module mod.com
121225-
121226-go 1.17
121227--- hi.tmpl --
121228-{{if (foÜx .X.Y)}}��{{$A :=
121229-	"hi"
121230-	}}{{.Z $A}}{{else}}
121231-{{$A.X 12}}
121232-{{foo (.X.Y) 23 ($A.Z)}}
121233-{{end}}
121234-`
121235-	WithOptions(
121236-		Settings{
121237-			"templateExtensions": []string{"tmpl"},
121238-			"semanticTokens":     true,
121239-		},
121240-	).Run(t, files, func(t *testing.T, env *Env) {
121241-		var p protocol.SemanticTokensParams
121242-		p.TextDocument.URI = env.Sandbox.Workdir.URI("hi.tmpl")
121243-		toks, err := env.Editor.Server.SemanticTokensFull(env.Ctx, &p)
121244-		if err != nil {
121245-			t.Errorf("semantic token failed: %v", err)
121246-		}
121247-		if toks == nil || len(toks.Data) == 0 {
121248-			t.Errorf("got no semantic tokens")
121249-		}
121250-	})
121251-}
121252-
121253-func TestTemplatesFromExtensions(t *testing.T) {
121254-	const files = `
121255--- go.mod --
121256-module mod.com
121257-
121258-go 1.12
121259--- hello.tmpl --
121260-{{range .Planets}}
121261-Hello {{}} <-- missing body
121262-{{end}}
121263-`
121264-	WithOptions(
121265-		Settings{
121266-			"templateExtensions": []string{"tmpl"},
121267-			"semanticTokens":     true,
121268-		},
121269-	).Run(t, files, func(t *testing.T, env *Env) {
121270-		// TODO: can we move this diagnostic onto {{}}?
121271-		var diags protocol.PublishDiagnosticsParams
121272-		env.OnceMet(
121273-			InitialWorkspaceLoad,
121274-			Diagnostics(env.AtRegexp("hello.tmpl", "()Hello {{}}")),
121275-			ReadDiagnostics("hello.tmpl", &diags),
121276-		)
121277-		d := diags.Diagnostics // issue 50786: check for Source
121278-		if len(d) != 1 {
121279-			t.Errorf("expected 1 diagnostic, got %d", len(d))
121280-			return
121281-		}
121282-		if d[0].Source != "template" {
121283-			t.Errorf("expected Source 'template', got %q", d[0].Source)
121284-		}
121285-		// issue 50801 (even broken templates could return some semantic tokens)
121286-		var p protocol.SemanticTokensParams
121287-		p.TextDocument.URI = env.Sandbox.Workdir.URI("hello.tmpl")
121288-		toks, err := env.Editor.Server.SemanticTokensFull(env.Ctx, &p)
121289-		if err != nil {
121290-			t.Errorf("semantic token failed: %v", err)
121291-		}
121292-		if toks == nil || len(toks.Data) == 0 {
121293-			t.Errorf("got no semantic tokens")
121294-		}
121295-
121296-		env.WriteWorkspaceFile("hello.tmpl", "{{range .Planets}}\nHello {{.}}\n{{end}}")
121297-		env.AfterChange(NoDiagnostics(ForFile("hello.tmpl")))
121298-	})
121299-}
121300-
121301-func TestTemplatesObserveDirectoryFilters(t *testing.T) {
121302-	const files = `
121303--- go.mod --
121304-module mod.com
121305-
121306-go 1.12
121307--- a/a.tmpl --
121308-A {{}} <-- missing body
121309--- b/b.tmpl --
121310-B {{}} <-- missing body
121311-`
121312-
121313-	WithOptions(
121314-		Settings{
121315-			"directoryFilters":   []string{"-b"},
121316-			"templateExtensions": []string{"tmpl"},
121317-		},
121318-	).Run(t, files, func(t *testing.T, env *Env) {
121319-		env.OnceMet(
121320-			InitialWorkspaceLoad,
121321-			Diagnostics(env.AtRegexp("a/a.tmpl", "()A")),
121322-			NoDiagnostics(ForFile("b/b.tmpl")),
121323-		)
121324-	})
121325-}
121326-
121327-func TestTemplatesFromLangID(t *testing.T) {
121328-	const files = `
121329--- go.mod --
121330-module mod.com
121331-
121332-go 1.12
121333-`
121334-
121335-	Run(t, files, func(t *testing.T, env *Env) {
121336-		env.CreateBuffer("hello.tmpl", "")
121337-		env.AfterChange(
121338-			NoDiagnostics(ForFile("hello.tmpl")), // Don't get spurious errors for empty templates.
121339-		)
121340-		env.SetBufferContent("hello.tmpl", "{{range .Planets}}\nHello {{}}\n{{end}}")
121341-		env.Await(Diagnostics(env.AtRegexp("hello.tmpl", "()Hello {{}}")))
121342-		env.RegexpReplace("hello.tmpl", "{{}}", "{{.}}")
121343-		env.Await(NoDiagnostics(ForFile("hello.tmpl")))
121344-	})
121345-}
121346-
121347-func TestClosingTemplatesMakesDiagnosticsDisappear(t *testing.T) {
121348-	const files = `
121349--- go.mod --
121350-module mod.com
121351-
121352-go 1.12
121353--- hello.tmpl --
121354-{{range .Planets}}
121355-Hello {{}} <-- missing body
121356-{{end}}
121357-`
121358-
121359-	Run(t, files, func(t *testing.T, env *Env) {
121360-		env.OpenFile("hello.tmpl")
121361-		env.AfterChange(
121362-			Diagnostics(env.AtRegexp("hello.tmpl", "()Hello {{}}")),
121363-		)
121364-		// Since we don't have templateExtensions configured, closing hello.tmpl
121365-		// should make its diagnostics disappear.
121366-		env.CloseBuffer("hello.tmpl")
121367-		env.AfterChange(
121368-			NoDiagnostics(ForFile("hello.tmpl")),
121369-		)
121370-	})
121371-}
121372-
121373-func TestMultipleSuffixes(t *testing.T) {
121374-	const files = `
121375--- go.mod --
121376-module mod.com
121377-
121378-go 1.12
121379--- b.gotmpl --
121380-{{define "A"}}goo{{end}}
121381--- a.tmpl --
121382-{{template "A"}}
121383-`
121384-
121385-	WithOptions(
121386-		Settings{
121387-			"templateExtensions": []string{"tmpl", "gotmpl"},
121388-		},
121389-	).Run(t, files, func(t *testing.T, env *Env) {
121390-		env.OpenFile("a.tmpl")
121391-		x := env.RegexpSearch("a.tmpl", `A`)
121392-		loc := env.GoToDefinition(x)
121393-		refs := env.References(loc)
121394-		if len(refs) != 2 {
121395-			t.Fatalf("got %v reference(s), want 2", len(refs))
121396-		}
121397-		// make sure we got one from b.gotmpl
121398-		want := env.Sandbox.Workdir.URI("b.gotmpl")
121399-		if refs[0].URI != want && refs[1].URI != want {
121400-			t.Errorf("failed to find reference to %s", shorten(want))
121401-			for i, r := range refs {
121402-				t.Logf("%d: URI:%s %v", i, shorten(r.URI), r.Range)
121403-			}
121404-		}
121405-
121406-		content, nloc := env.Hover(loc)
121407-		if loc != nloc {
121408-			t.Errorf("loc? got %v, wanted %v", nloc, loc)
121409-		}
121410-		if content.Value != "template A defined" {
121411-			t.Errorf("got %s, wanted 'template A defined", content.Value)
121412-		}
121413-	})
121414-}
121415-
121416-// shorten long URIs
121417-func shorten(fn protocol.DocumentURI) string {
121418-	if len(fn) <= 20 {
121419-		return string(fn)
121420-	}
121421-	pieces := strings.Split(string(fn), "/")
121422-	if len(pieces) < 2 {
121423-		return string(fn)
121424-	}
121425-	j := len(pieces)
121426-	return pieces[j-2] + "/" + pieces[j-1]
121427-}
121428-
121429-// Hover needs tests
121430diff -urN a/gopls/internal/regtest/watch/watch_test.go b/gopls/internal/regtest/watch/watch_test.go
121431--- a/gopls/internal/regtest/watch/watch_test.go	2000-01-01 00:00:00.000000000 -0000
121432+++ b/gopls/internal/regtest/watch/watch_test.go	1970-01-01 00:00:00.000000000 +0000
121433@@ -1,702 +0,0 @@
121434-// Copyright 2020 The Go Authors. All rights reserved.
121435-// Use of this source code is governed by a BSD-style
121436-// license that can be found in the LICENSE file.
121437-
121438-package regtest
121439-
121440-import (
121441-	"testing"
121442-
121443-	"golang.org/x/tools/gopls/internal/hooks"
121444-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
121445-	"golang.org/x/tools/internal/bug"
121446-
121447-	"golang.org/x/tools/gopls/internal/lsp/fake"
121448-	"golang.org/x/tools/gopls/internal/lsp/protocol"
121449-)
121450-
121451-func TestMain(m *testing.M) {
121452-	bug.PanicOnBugs = true
121453-	Main(m, hooks.Options)
121454-}
121455-
121456-func TestEditFile(t *testing.T) {
121457-	const pkg = `
121458--- go.mod --
121459-module mod.com
121460-
121461-go 1.14
121462--- a/a.go --
121463-package a
121464-
121465-func _() {
121466-	var x int
121467-}
121468-`
121469-	// Edit the file when it's *not open* in the workspace, and check that
121470-	// diagnostics are updated.
121471-	t.Run("unopened", func(t *testing.T) {
121472-		Run(t, pkg, func(t *testing.T, env *Env) {
121473-			env.OnceMet(
121474-				InitialWorkspaceLoad,
121475-				Diagnostics(env.AtRegexp("a/a.go", "x")),
121476-			)
121477-			env.WriteWorkspaceFile("a/a.go", `package a; func _() {};`)
121478-			env.AfterChange(
121479-				NoDiagnostics(ForFile("a/a.go")),
121480-			)
121481-		})
121482-	})
121483-
121484-	// Edit the file when it *is open* in the workspace, and check that
121485-	// diagnostics are *not* updated.
121486-	t.Run("opened", func(t *testing.T) {
121487-		Run(t, pkg, func(t *testing.T, env *Env) {
121488-			env.OpenFile("a/a.go")
121489-			// Insert a trivial edit so that we don't automatically update the buffer
121490-			// (see CL 267577).
121491-			env.EditBuffer("a/a.go", fake.NewEdit(0, 0, 0, 0, " "))
121492-			env.AfterChange()
121493-			env.WriteWorkspaceFile("a/a.go", `package a; func _() {};`)
121494-			env.AfterChange(
121495-				Diagnostics(env.AtRegexp("a/a.go", "x")),
121496-			)
121497-		})
121498-	})
121499-}
121500-
121501-// Edit a dependency on disk and expect a new diagnostic.
121502-func TestEditDependency(t *testing.T) {
121503-	const pkg = `
121504--- go.mod --
121505-module mod.com
121506-
121507-go 1.14
121508--- b/b.go --
121509-package b
121510-
121511-func B() int { return 0 }
121512--- a/a.go --
121513-package a
121514-
121515-import (
121516-	"mod.com/b"
121517-)
121518-
121519-func _() {
121520-	_ = b.B()
121521-}
121522-`
121523-	Run(t, pkg, func(t *testing.T, env *Env) {
121524-		env.OpenFile("a/a.go")
121525-		env.AfterChange()
121526-		env.WriteWorkspaceFile("b/b.go", `package b; func B() {};`)
121527-		env.AfterChange(
121528-			Diagnostics(env.AtRegexp("a/a.go", "b.B")),
121529-		)
121530-	})
121531-}
121532-
121533-// Edit both the current file and one of its dependencies on disk and
121534-// expect diagnostic changes.
121535-func TestEditFileAndDependency(t *testing.T) {
121536-	const pkg = `
121537--- go.mod --
121538-module mod.com
121539-
121540-go 1.14
121541--- b/b.go --
121542-package b
121543-
121544-func B() int { return 0 }
121545--- a/a.go --
121546-package a
121547-
121548-import (
121549-	"mod.com/b"
121550-)
121551-
121552-func _() {
121553-	var x int
121554-	_ = b.B()
121555-}
121556-`
121557-	Run(t, pkg, func(t *testing.T, env *Env) {
121558-		env.OnceMet(
121559-			InitialWorkspaceLoad,
121560-			Diagnostics(env.AtRegexp("a/a.go", "x")),
121561-		)
121562-		env.WriteWorkspaceFiles(map[string]string{
121563-			"b/b.go": `package b; func B() {};`,
121564-			"a/a.go": `package a
121565-
121566-import "mod.com/b"
121567-
121568-func _() {
121569-	b.B()
121570-}`,
121571-		})
121572-		env.AfterChange(
121573-			NoDiagnostics(ForFile("a/a.go")),
121574-			NoDiagnostics(ForFile("b/b.go")),
121575-		)
121576-	})
121577-}
121578-
121579-// Delete a dependency and expect a new diagnostic.
121580-func TestDeleteDependency(t *testing.T) {
121581-	const pkg = `
121582--- go.mod --
121583-module mod.com
121584-
121585-go 1.14
121586--- b/b.go --
121587-package b
121588-
121589-func B() int { return 0 }
121590--- a/a.go --
121591-package a
121592-
121593-import (
121594-	"mod.com/b"
121595-)
121596-
121597-func _() {
121598-	_ = b.B()
121599-}
121600-`
121601-	Run(t, pkg, func(t *testing.T, env *Env) {
121602-		env.OpenFile("a/a.go")
121603-		env.AfterChange()
121604-		env.RemoveWorkspaceFile("b/b.go")
121605-		env.AfterChange(
121606-			Diagnostics(env.AtRegexp("a/a.go", "\"mod.com/b\"")),
121607-		)
121608-	})
121609-}
121610-
121611-// Create a dependency on disk and expect the diagnostic to go away.
121612-func TestCreateDependency(t *testing.T) {
121613-	const missing = `
121614--- go.mod --
121615-module mod.com
121616-
121617-go 1.14
121618--- b/b.go --
121619-package b
121620-
121621-func B() int { return 0 }
121622--- a/a.go --
121623-package a
121624-
121625-import (
121626-	"mod.com/c"
121627-)
121628-
121629-func _() {
121630-	c.C()
121631-}
121632-`
121633-	Run(t, missing, func(t *testing.T, env *Env) {
121634-		env.OnceMet(
121635-			InitialWorkspaceLoad,
121636-			Diagnostics(env.AtRegexp("a/a.go", "\"mod.com/c\"")),
121637-		)
121638-		env.WriteWorkspaceFile("c/c.go", `package c; func C() {};`)
121639-		env.AfterChange(
121640-			NoDiagnostics(ForFile("a/a.go")),
121641-		)
121642-	})
121643-}
121644-
121645-// Create a new dependency and add it to the file on disk.
121646-// This is similar to what might happen if you switch branches.
121647-func TestCreateAndAddDependency(t *testing.T) {
121648-	const original = `
121649--- go.mod --
121650-module mod.com
121651-
121652-go 1.14
121653--- a/a.go --
121654-package a
121655-
121656-func _() {}
121657-`
121658-	Run(t, original, func(t *testing.T, env *Env) {
121659-		env.WriteWorkspaceFile("c/c.go", `package c; func C() {};`)
121660-		env.WriteWorkspaceFile("a/a.go", `package a; import "mod.com/c"; func _() { c.C() }`)
121661-		env.AfterChange(
121662-			NoDiagnostics(ForFile("a/a.go")),
121663-		)
121664-	})
121665-}
121666-
121667-// Create a new file that defines a new symbol, in the same package.
121668-func TestCreateFile(t *testing.T) {
121669-	const pkg = `
121670--- go.mod --
121671-module mod.com
121672-
121673-go 1.14
121674--- a/a.go --
121675-package a
121676-
121677-func _() {
121678-	hello()
121679-}
121680-`
121681-	Run(t, pkg, func(t *testing.T, env *Env) {
121682-		env.OnceMet(
121683-			InitialWorkspaceLoad,
121684-			Diagnostics(env.AtRegexp("a/a.go", "hello")),
121685-		)
121686-		env.WriteWorkspaceFile("a/a2.go", `package a; func hello() {};`)
121687-		env.AfterChange(
121688-			NoDiagnostics(ForFile("a/a.go")),
121689-		)
121690-	})
121691-}
121692-
121693-// Add a new method to an interface and implement it.
121694-// Inspired by the structure of internal/lsp/source and internal/lsp/cache.
121695-func TestCreateImplementation(t *testing.T) {
121696-	const pkg = `
121697--- go.mod --
121698-module mod.com
121699-
121700-go 1.14
121701--- b/b.go --
121702-package b
121703-
121704-type B interface{
121705-	Hello() string
121706-}
121707-
121708-func SayHello(bee B) {
121709-	println(bee.Hello())
121710-}
121711--- a/a.go --
121712-package a
121713-
121714-import "mod.com/b"
121715-
121716-type X struct {}
121717-
121718-func (_ X) Hello() string {
121719-	return ""
121720-}
121721-
121722-func _() {
121723-	x := X{}
121724-	b.SayHello(x)
121725-}
121726-`
121727-	const newMethod = `package b
121728-type B interface{
121729-	Hello() string
121730-	Bye() string
121731-}
121732-
121733-func SayHello(bee B) {
121734-	println(bee.Hello())
121735-}`
121736-	const implementation = `package a
121737-
121738-import "mod.com/b"
121739-
121740-type X struct {}
121741-
121742-func (_ X) Hello() string {
121743-	return ""
121744-}
121745-
121746-func (_ X) Bye() string {
121747-	return ""
121748-}
121749-
121750-func _() {
121751-	x := X{}
121752-	b.SayHello(x)
121753-}`
121754-
121755-	// Add the new method before the implementation. Expect diagnostics.
121756-	t.Run("method before implementation", func(t *testing.T) {
121757-		Run(t, pkg, func(t *testing.T, env *Env) {
121758-			env.WriteWorkspaceFile("b/b.go", newMethod)
121759-			env.AfterChange(
121760-				Diagnostics(AtPosition("a/a.go", 12, 12)),
121761-			)
121762-			env.WriteWorkspaceFile("a/a.go", implementation)
121763-			env.AfterChange(
121764-				NoDiagnostics(ForFile("a/a.go")),
121765-			)
121766-		})
121767-	})
121768-	// Add the new implementation before the new method. Expect no diagnostics.
121769-	t.Run("implementation before method", func(t *testing.T) {
121770-		Run(t, pkg, func(t *testing.T, env *Env) {
121771-			env.WriteWorkspaceFile("a/a.go", implementation)
121772-			env.AfterChange(
121773-				NoDiagnostics(ForFile("a/a.go")),
121774-			)
121775-			env.WriteWorkspaceFile("b/b.go", newMethod)
121776-			env.AfterChange(
121777-				NoDiagnostics(ForFile("a/a.go")),
121778-			)
121779-		})
121780-	})
121781-	// Add both simultaneously. Expect no diagnostics.
121782-	t.Run("implementation and method simultaneously", func(t *testing.T) {
121783-		Run(t, pkg, func(t *testing.T, env *Env) {
121784-			env.WriteWorkspaceFiles(map[string]string{
121785-				"a/a.go": implementation,
121786-				"b/b.go": newMethod,
121787-			})
121788-			env.AfterChange(
121789-				NoDiagnostics(ForFile("a/a.go")),
121790-				NoDiagnostics(ForFile("b/b.go")),
121791-			)
121792-		})
121793-	})
121794-}
121795-
121796-// Tests golang/go#38498. Delete a file and then force a reload.
121797-// Assert that we no longer try to load the file.
121798-func TestDeleteFiles(t *testing.T) {
121799-	const pkg = `
121800--- go.mod --
121801-module mod.com
121802-
121803-go 1.14
121804--- a/a.go --
121805-package a
121806-
121807-func _() {
121808-	var _ int
121809-}
121810--- a/a_unneeded.go --
121811-package a
121812-`
121813-	t.Run("close then delete", func(t *testing.T) {
121814-		WithOptions(
121815-			Settings{"verboseOutput": true},
121816-		).Run(t, pkg, func(t *testing.T, env *Env) {
121817-			env.OpenFile("a/a.go")
121818-			env.OpenFile("a/a_unneeded.go")
121819-			env.AfterChange(
121820-				LogMatching(protocol.Info, "a_unneeded.go", 1, false),
121821-			)
121822-
121823-			// Close and delete the open file, mimicking what an editor would do.
121824-			env.CloseBuffer("a/a_unneeded.go")
121825-			env.RemoveWorkspaceFile("a/a_unneeded.go")
121826-			env.RegexpReplace("a/a.go", "var _ int", "fmt.Println(\"\")")
121827-			env.AfterChange(
121828-				Diagnostics(env.AtRegexp("a/a.go", "fmt")),
121829-			)
121830-			env.SaveBuffer("a/a.go")
121831-			env.AfterChange(
121832-				// There should only be one log message containing
121833-				// a_unneeded.go, from the initial workspace load, which we
121834-				// check for earlier. If there are more, there's a bug.
121835-				LogMatching(protocol.Info, "a_unneeded.go", 1, false),
121836-				NoDiagnostics(ForFile("a/a.go")),
121837-			)
121838-		})
121839-	})
121840-
121841-	t.Run("delete then close", func(t *testing.T) {
121842-		WithOptions(
121843-			Settings{"verboseOutput": true},
121844-		).Run(t, pkg, func(t *testing.T, env *Env) {
121845-			env.OpenFile("a/a.go")
121846-			env.OpenFile("a/a_unneeded.go")
121847-			env.AfterChange(
121848-				LogMatching(protocol.Info, "a_unneeded.go", 1, false),
121849-			)
121850-
121851-			// Delete and then close the file.
121852-			env.RemoveWorkspaceFile("a/a_unneeded.go")
121853-			env.CloseBuffer("a/a_unneeded.go")
121854-			env.RegexpReplace("a/a.go", "var _ int", "fmt.Println(\"\")")
121855-			env.AfterChange(
121856-				Diagnostics(env.AtRegexp("a/a.go", "fmt")),
121857-			)
121858-			env.SaveBuffer("a/a.go")
121859-			env.AfterChange(
121860-				// There should only be one log message containing
121861-				// a_unneeded.go, from the initial workspace load, which we
121862-				// check for earlier. If there are more, there's a bug.
121863-				LogMatching(protocol.Info, "a_unneeded.go", 1, false),
121864-				NoDiagnostics(ForFile("a/a.go")),
121865-			)
121866-		})
121867-	})
121868-}
121869-
121870-// This change reproduces the behavior of switching branches, with multiple
121871-// files being created and deleted. The key change here is the movement of a
121872-// symbol from one file to another in a given package through a deletion and
121873-// creation. To reproduce an issue with metadata invalidation in batched
121874-// changes, the last change in the batch is an on-disk file change that doesn't
121875-// require metadata invalidation.
121876-func TestMoveSymbol(t *testing.T) {
121877-	const pkg = `
121878--- go.mod --
121879-module mod.com
121880-
121881-go 1.14
121882--- main.go --
121883-package main
121884-
121885-import "mod.com/a"
121886-
121887-func main() {
121888-	var x int
121889-	x = a.Hello
121890-	println(x)
121891-}
121892--- a/a1.go --
121893-package a
121894-
121895-var Hello int
121896--- a/a2.go --
121897-package a
121898-
121899-func _() {}
121900-`
121901-	Run(t, pkg, func(t *testing.T, env *Env) {
121902-		env.WriteWorkspaceFile("a/a3.go", "package a\n\nvar Hello int\n")
121903-		env.RemoveWorkspaceFile("a/a1.go")
121904-		env.WriteWorkspaceFile("a/a2.go", "package a; func _() {};")
121905-		env.AfterChange(
121906-			NoDiagnostics(ForFile("main.go")),
121907-		)
121908-	})
121909-}
121910-
121911-// Reproduce golang/go#40456.
121912-func TestChangeVersion(t *testing.T) {
121913-	const proxy = `
121914--- [email protected]/go.mod --
121915-module example.com
121916-
121917-go 1.12
121918--- [email protected]/blah/blah.go --
121919-package blah
121920-
121921-const Name = "Blah"
121922-
121923-func X(x int) {}
121924--- [email protected]/go.mod --
121925-module example.com
121926-
121927-go 1.12
121928--- [email protected]/blah/blah.go --
121929-package blah
121930-
121931-const Name = "Blah"
121932-
121933-func X() {}
121934--- [email protected]/go.mod --
121935-module random.org
121936-
121937-go 1.12
121938--- [email protected]/blah/blah.go --
121939-package hello
121940-
121941-const Name = "Hello"
121942-`
121943-	const mod = `
121944--- go.mod --
121945-module mod.com
121946-
121947-go 1.12
121948-
121949-require example.com v1.2.2
121950--- go.sum --
121951-example.com v1.2.3 h1:OnPPkx+rW63kj9pgILsu12MORKhSlnFa3DVRJq1HZ7g=
121952-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
121953--- main.go --
121954-package main
121955-
121956-import "example.com/blah"
121957-
121958-func main() {
121959-	blah.X()
121960-}
121961-`
121962-	WithOptions(ProxyFiles(proxy)).Run(t, mod, func(t *testing.T, env *Env) {
121963-		env.WriteWorkspaceFiles(map[string]string{
121964-			"go.mod": `module mod.com
121965-
121966-go 1.12
121967-
121968-require example.com v1.2.3
121969-`,
121970-			"main.go": `package main
121971-
121972-import (
121973-	"example.com/blah"
121974-)
121975-
121976-func main() {
121977-	blah.X(1)
121978-}
121979-`,
121980-		})
121981-		env.AfterChange(
121982-			env.DoneWithChangeWatchedFiles(),
121983-			NoDiagnostics(ForFile("main.go")),
121984-		)
121985-	})
121986-}
121987-
121988-// Reproduces golang/go#40340.
121989-func TestSwitchFromGOPATHToModuleMode(t *testing.T) {
121990-	const files = `
121991--- foo/blah/blah.go --
121992-package blah
121993-
121994-const Name = ""
121995--- main.go --
121996-package main
121997-
121998-import "foo/blah"
121999-
122000-func main() {
122001-	_ = blah.Name
122002-}
122003-`
122004-	WithOptions(
122005-		InGOPATH(),
122006-		Modes(Default), // golang/go#57521: this test is temporarily failing in 'experimental' mode
122007-		EnvVars{"GO111MODULE": "auto"},
122008-	).Run(t, files, func(t *testing.T, env *Env) {
122009-		env.OpenFile("main.go")
122010-		env.AfterChange(
122011-			NoDiagnostics(ForFile("main.go")),
122012-		)
122013-		if err := env.Sandbox.RunGoCommand(env.Ctx, "", "mod", []string{"init", "mod.com"}, true); err != nil {
122014-			t.Fatal(err)
122015-		}
122016-
122017-		// TODO(golang/go#57558, golang/go#57512): file watching is asynchronous,
122018-		// and we must wait for the view to be reconstructed before touching
122019-		// main.go, so that the new view "knows" about main.go. This is a bug, but
122020-		// awaiting the change here avoids it.
122021-		env.AfterChange()
122022-
122023-		env.RegexpReplace("main.go", `"foo/blah"`, `"mod.com/foo/blah"`)
122024-		env.AfterChange(
122025-			NoDiagnostics(ForFile("main.go")),
122026-		)
122027-	})
122028-}
122029-
122030-// Reproduces golang/go#40487.
122031-func TestSwitchFromModulesToGOPATH(t *testing.T) {
122032-	const files = `
122033--- foo/go.mod --
122034-module mod.com
122035-
122036-go 1.14
122037--- foo/blah/blah.go --
122038-package blah
122039-
122040-const Name = ""
122041--- foo/main.go --
122042-package main
122043-
122044-import "mod.com/blah"
122045-
122046-func main() {
122047-	_ = blah.Name
122048-}
122049-`
122050-	WithOptions(
122051-		InGOPATH(),
122052-		EnvVars{"GO111MODULE": "auto"},
122053-	).Run(t, files, func(t *testing.T, env *Env) {
122054-		env.OpenFile("foo/main.go")
122055-		env.RemoveWorkspaceFile("foo/go.mod")
122056-		env.AfterChange(
122057-			Diagnostics(env.AtRegexp("foo/main.go", `"mod.com/blah"`)),
122058-		)
122059-		env.RegexpReplace("foo/main.go", `"mod.com/blah"`, `"foo/blah"`)
122060-		env.AfterChange(
122061-			NoDiagnostics(ForFile("foo/main.go")),
122062-		)
122063-	})
122064-}
122065-
122066-func TestNewSymbolInTestVariant(t *testing.T) {
122067-	const files = `
122068--- go.mod --
122069-module mod.com
122070-
122071-go 1.12
122072--- a/a.go --
122073-package a
122074-
122075-func bob() {}
122076--- a/a_test.go --
122077-package a
122078-
122079-import "testing"
122080-
122081-func TestBob(t *testing.T) {
122082-	bob()
122083-}
122084-`
122085-	Run(t, files, func(t *testing.T, env *Env) {
122086-		// Add a new symbol to the package under test and use it in the test
122087-		// variant. Expect no diagnostics.
122088-		env.WriteWorkspaceFiles(map[string]string{
122089-			"a/a.go": `package a
122090-
122091-func bob() {}
122092-func george() {}
122093-`,
122094-			"a/a_test.go": `package a
122095-
122096-import "testing"
122097-
122098-func TestAll(t *testing.T) {
122099-	bob()
122100-	george()
122101-}
122102-`,
122103-		})
122104-		env.AfterChange(
122105-			NoDiagnostics(ForFile("a/a.go")),
122106-			NoDiagnostics(ForFile("a/a_test.go")),
122107-		)
122108-		// Now, add a new file to the test variant and use its symbol in the
122109-		// original test file. Expect no diagnostics.
122110-		env.WriteWorkspaceFiles(map[string]string{
122111-			"a/a_test.go": `package a
122112-
122113-import "testing"
122114-
122115-func TestAll(t *testing.T) {
122116-	bob()
122117-	george()
122118-	hi()
122119-}
122120-`,
122121-			"a/a2_test.go": `package a
122122-
122123-import "testing"
122124-
122125-func hi() {}
122126-
122127-func TestSomething(t *testing.T) {}
122128-`,
122129-		})
122130-		env.AfterChange(
122131-			NoDiagnostics(ForFile("a/a_test.go")),
122132-			NoDiagnostics(ForFile("a/a2_test.go")),
122133-		)
122134-	})
122135-}
122136diff -urN a/gopls/internal/regtest/workspace/broken_test.go b/gopls/internal/regtest/workspace/broken_test.go
122137--- a/gopls/internal/regtest/workspace/broken_test.go	2000-01-01 00:00:00.000000000 -0000
122138+++ b/gopls/internal/regtest/workspace/broken_test.go	1970-01-01 00:00:00.000000000 +0000
122139@@ -1,264 +0,0 @@
122140-// Copyright 2022 The Go Authors. All rights reserved.
122141-// Use of this source code is governed by a BSD-style
122142-// license that can be found in the LICENSE file.
122143-
122144-package workspace
122145-
122146-import (
122147-	"strings"
122148-	"testing"
122149-
122150-	"golang.org/x/tools/gopls/internal/lsp"
122151-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
122152-	"golang.org/x/tools/internal/testenv"
122153-)
122154-
122155-// This file holds various tests for UX with respect to broken workspaces.
122156-//
122157-// TODO: consolidate other tests here.
122158-//
122159-// TODO: write more tests:
122160-//  - an explicit GOWORK value that doesn't exist
122161-//  - using modules and/or GOWORK inside of GOPATH?
122162-
122163-// Test for golang/go#53933
122164-func TestBrokenWorkspace_DuplicateModules(t *testing.T) {
122165-	testenv.NeedsGo1Point(t, 18)
122166-
122167-	// TODO(golang/go#57650): fix this feature.
122168-	t.Skip("we no longer detect duplicate modules")
122169-
122170-	// This proxy module content is replaced by the workspace, but is still
122171-	// required for module resolution to function in the Go command.
122172-	const proxy = `
122173--- example.com/foo@v0.0.1/go.mod --
122174-module example.com/foo
122175-
122176-go 1.12
122177-`
122178-
122179-	const src = `
122180--- go.work --
122181-go 1.18
122182-
122183-use (
122184-	./package1
122185-	./package1/vendor/example.com/foo
122186-	./package2
122187-	./package2/vendor/example.com/foo
122188-)
122189-
122190--- package1/go.mod --
122191-module mod.test
122192-
122193-go 1.18
122194-
122195-require example.com/foo v0.0.1
122196--- package1/main.go --
122197-package main
122198-
122199-import "example.com/foo"
122200-
122201-func main() {
122202-	_ = foo.CompleteMe
122203-}
122204--- package1/vendor/example.com/foo/go.mod --
122205-module example.com/foo
122206-
122207-go 1.18
122208--- package1/vendor/example.com/foo/foo.go --
122209-package foo
122210-
122211-const CompleteMe = 111
122212--- package2/go.mod --
122213-module mod2.test
122214-
122215-go 1.18
122216-
122217-require example.com/foo v0.0.1
122218--- package2/main.go --
122219-package main
122220-
122221-import "example.com/foo"
122222-
122223-func main() {
122224-	_ = foo.CompleteMe
122225-}
122226--- package2/vendor/example.com/foo/go.mod --
122227-module example.com/foo
122228-
122229-go 1.18
122230--- package2/vendor/example.com/foo/foo.go --
122231-package foo
122232-
122233-const CompleteMe = 222
122234-`
122235-
122236-	WithOptions(
122237-		ProxyFiles(proxy),
122238-	).Run(t, src, func(t *testing.T, env *Env) {
122239-		env.OpenFile("package1/main.go")
122240-		env.Await(
122241-			OutstandingWork(lsp.WorkspaceLoadFailure, `found module "example.com/foo" multiple times in the workspace`),
122242-		)
122243-
122244-		// Remove the redundant vendored copy of example.com.
122245-		env.WriteWorkspaceFile("go.work", `go 1.18
122246-		use (
122247-			./package1
122248-			./package2
122249-			./package2/vendor/example.com/foo
122250-		)
122251-		`)
122252-		env.Await(NoOutstandingWork())
122253-
122254-		// Check that definitions in package1 go to the copy vendored in package2.
122255-		location := env.GoToDefinition(env.RegexpSearch("package1/main.go", "CompleteMe")).URI.SpanURI().Filename()
122256-		const wantLocation = "package2/vendor/example.com/foo/foo.go"
122257-		if !strings.HasSuffix(location, wantLocation) {
122258-			t.Errorf("got definition of CompleteMe at %q, want %q", location, wantLocation)
122259-		}
122260-	})
122261-}
122262-
122263-// Test for golang/go#43186: correcting the module path should fix errors
122264-// without restarting gopls.
122265-func TestBrokenWorkspace_WrongModulePath(t *testing.T) {
122266-	const files = `
122267--- go.mod --
122268-module mod.testx
122269-
122270-go 1.18
122271--- p/internal/foo/foo.go --
122272-package foo
122273-
122274-const C = 1
122275--- p/internal/bar/bar.go --
122276-package bar
122277-
122278-import "mod.test/p/internal/foo"
122279-
122280-const D = foo.C + 1
122281--- p/internal/bar/bar_test.go --
122282-package bar_test
122283-
122284-import (
122285-	"mod.test/p/internal/foo"
122286-	. "mod.test/p/internal/bar"
122287-)
122288-
122289-const E = D + foo.C
122290--- p/internal/baz/baz_test.go --
122291-package baz_test
122292-
122293-import (
122294-	named "mod.test/p/internal/bar"
122295-)
122296-
122297-const F = named.D - 3
122298-`
122299-
122300-	Run(t, files, func(t *testing.T, env *Env) {
122301-		env.OpenFile("p/internal/bar/bar.go")
122302-		env.AfterChange(
122303-			Diagnostics(env.AtRegexp("p/internal/bar/bar.go", "\"mod.test/p/internal/foo\"")),
122304-		)
122305-		env.OpenFile("go.mod")
122306-		env.RegexpReplace("go.mod", "mod.testx", "mod.test")
122307-		env.SaveBuffer("go.mod") // saving triggers a reload
122308-		env.AfterChange(NoDiagnostics())
122309-	})
122310-}
122311-
122312-func TestMultipleModules_Warning(t *testing.T) {
122313-	msgForVersion := func(ver int) string {
122314-		if ver >= 18 {
122315-			return `gopls was not able to find modules in your workspace.`
122316-		} else {
122317-			return `gopls requires a module at the root of your workspace.`
122318-		}
122319-	}
122320-
122321-	const modules = `
122322--- a/go.mod --
122323-module a.com
122324-
122325-go 1.12
122326--- a/a.go --
122327-package a
122328--- a/empty.go --
122329-// an empty file
122330--- b/go.mod --
122331-module b.com
122332-
122333-go 1.12
122334--- b/b.go --
122335-package b
122336-`
122337-	for _, go111module := range []string{"on", "auto"} {
122338-		t.Run("GO111MODULE="+go111module, func(t *testing.T) {
122339-			WithOptions(
122340-				Modes(Default),
122341-				EnvVars{"GO111MODULE": go111module},
122342-			).Run(t, modules, func(t *testing.T, env *Env) {
122343-				ver := env.GoVersion()
122344-				msg := msgForVersion(ver)
122345-				env.OpenFile("a/a.go")
122346-				env.OpenFile("a/empty.go")
122347-				env.OpenFile("b/go.mod")
122348-				env.AfterChange(
122349-					Diagnostics(env.AtRegexp("a/a.go", "package a")),
122350-					Diagnostics(env.AtRegexp("b/go.mod", "module b.com")),
122351-					OutstandingWork(lsp.WorkspaceLoadFailure, msg),
122352-				)
122353-
122354-				// Changing the workspace folders to the valid modules should resolve
122355-				// the workspace errors and diagnostics.
122356-				//
122357-				// TODO(rfindley): verbose work tracking doesn't follow changing the
122358-				// workspace folder, therefore we can't invoke AfterChange here.
122359-				env.ChangeWorkspaceFolders("a", "b")
122360-				env.Await(
122361-					NoDiagnostics(ForFile("a/a.go")),
122362-					NoDiagnostics(ForFile("b/go.mod")),
122363-					NoOutstandingWork(),
122364-				)
122365-
122366-				env.ChangeWorkspaceFolders(".")
122367-
122368-				// TODO(rfindley): when GO111MODULE=auto, we need to open or change a
122369-				// file here in order to detect a critical error. This is because gopls
122370-				// has forgotten about a/a.go, and therefore doesn't hit the heuristic
122371-				// "all packages are command-line-arguments".
122372-				//
122373-				// This is broken, and could be fixed by adjusting the heuristic to
122374-				// account for the scenario where there are *no* workspace packages, or
122375-				// (better) trying to get workspace packages for each open file. See
122376-				// also golang/go#54261.
122377-				env.OpenFile("b/b.go")
122378-				env.AfterChange(
122379-					// TODO(rfindley): fix these missing diagnostics.
122380-					// Diagnostics(env.AtRegexp("a/a.go", "package a")),
122381-					// Diagnostics(env.AtRegexp("b/go.mod", "module b.com")),
122382-					Diagnostics(env.AtRegexp("b/b.go", "package b")),
122383-					OutstandingWork(lsp.WorkspaceLoadFailure, msg),
122384-				)
122385-			})
122386-		})
122387-	}
122388-
122389-	// Expect no warning if GO111MODULE=auto in a directory in GOPATH.
122390-	t.Run("GOPATH_GO111MODULE_auto", func(t *testing.T) {
122391-		WithOptions(
122392-			Modes(Default),
122393-			EnvVars{"GO111MODULE": "auto"},
122394-			InGOPATH(),
122395-		).Run(t, modules, func(t *testing.T, env *Env) {
122396-			env.OpenFile("a/a.go")
122397-			env.AfterChange(
122398-				NoDiagnostics(ForFile("a/a.go")),
122399-				NoOutstandingWork(),
122400-			)
122401-		})
122402-	})
122403-}
122404diff -urN a/gopls/internal/regtest/workspace/directoryfilters_test.go b/gopls/internal/regtest/workspace/directoryfilters_test.go
122405--- a/gopls/internal/regtest/workspace/directoryfilters_test.go	2000-01-01 00:00:00.000000000 -0000
122406+++ b/gopls/internal/regtest/workspace/directoryfilters_test.go	1970-01-01 00:00:00.000000000 +0000
122407@@ -1,259 +0,0 @@
122408-// Copyright 2022 The Go Authors. All rights reserved.
122409-// Use of this source code is governed by a BSD-style
122410-// license that can be found in the LICENSE file.
122411-
122412-package workspace
122413-
122414-import (
122415-	"sort"
122416-	"strings"
122417-	"testing"
122418-
122419-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
122420-	"golang.org/x/tools/internal/testenv"
122421-)
122422-
122423-// This file contains regression tests for the directoryFilters setting.
122424-//
122425-// TODO:
122426-//  - consolidate some of these tests into a single test
122427-//  - add more tests for changing directory filters
122428-
122429-func TestDirectoryFilters(t *testing.T) {
122430-	WithOptions(
122431-		ProxyFiles(workspaceProxy),
122432-		WorkspaceFolders("pkg"),
122433-		Settings{
122434-			"directoryFilters": []string{"-inner"},
122435-		},
122436-	).Run(t, workspaceModule, func(t *testing.T, env *Env) {
122437-		syms := env.Symbol("Hi")
122438-		sort.Slice(syms, func(i, j int) bool { return syms[i].ContainerName < syms[j].ContainerName })
122439-		for _, s := range syms {
122440-			if strings.Contains(s.ContainerName, "inner") {
122441-				t.Errorf("WorkspaceSymbol: found symbol %q with container %q, want \"inner\" excluded", s.Name, s.ContainerName)
122442-			}
122443-		}
122444-	})
122445-}
122446-
122447-func TestDirectoryFiltersLoads(t *testing.T) {
122448-	// exclude, and its error, should be excluded from the workspace.
122449-	const files = `
122450--- go.mod --
122451-module example.com
122452-
122453-go 1.12
122454--- exclude/exclude.go --
122455-package exclude
122456-
122457-const _ = Nonexistant
122458-`
122459-
122460-	WithOptions(
122461-		Settings{"directoryFilters": []string{"-exclude"}},
122462-	).Run(t, files, func(t *testing.T, env *Env) {
122463-		env.OnceMet(
122464-			InitialWorkspaceLoad,
122465-			NoDiagnostics(ForFile("exclude/x.go")),
122466-		)
122467-	})
122468-}
122469-
122470-func TestDirectoryFiltersTransitiveDep(t *testing.T) {
122471-	// Even though exclude is excluded from the workspace, it should
122472-	// still be importable as a non-workspace package.
122473-	const files = `
122474--- go.mod --
122475-module example.com
122476-
122477-go 1.12
122478--- include/include.go --
122479-package include
122480-import "example.com/exclude"
122481-
122482-const _ = exclude.X
122483--- exclude/exclude.go --
122484-package exclude
122485-
122486-const _ = Nonexistant // should be ignored, since this is a non-workspace package
122487-const X = 1
122488-`
122489-
122490-	WithOptions(
122491-		Settings{"directoryFilters": []string{"-exclude"}},
122492-	).Run(t, files, func(t *testing.T, env *Env) {
122493-		env.OnceMet(
122494-			InitialWorkspaceLoad,
122495-			NoDiagnostics(ForFile("exclude/exclude.go")), // filtered out
122496-			NoDiagnostics(ForFile("include/include.go")), // successfully builds
122497-		)
122498-	})
122499-}
122500-
122501-func TestDirectoryFiltersWorkspaceModules(t *testing.T) {
122502-	// Define a module include.com which should be in the workspace, plus a
122503-	// module exclude.com which should be excluded and therefore come from
122504-	// the proxy.
122505-	const files = `
122506--- include/go.mod --
122507-module include.com
122508-
122509-go 1.12
122510-
122511-require exclude.com v1.0.0
122512-
122513--- include/go.sum --
122514-exclude.com v1.0.0 h1:Q5QSfDXY5qyNCBeUiWovUGqcLCRZKoTs9XdBeVz+w1I=
122515-exclude.com v1.0.0/go.mod h1:hFox2uDlNB2s2Jfd9tHlQVfgqUiLVTmh6ZKat4cvnj4=
122516-
122517--- include/include.go --
122518-package include
122519-
122520-import "exclude.com"
122521-
122522-var _ = exclude.X // satisfied only by the workspace version
122523--- exclude/go.mod --
122524-module exclude.com
122525-
122526-go 1.12
122527--- exclude/exclude.go --
122528-package exclude
122529-
122530-const X = 1
122531-`
122532-	const proxy = `
122533--- [email protected]/go.mod --
122534-module exclude.com
122535-
122536-go 1.12
122537--- [email protected]/exclude.go --
122538-package exclude
122539-`
122540-	WithOptions(
122541-		Modes(Experimental),
122542-		ProxyFiles(proxy),
122543-		Settings{"directoryFilters": []string{"-exclude"}},
122544-	).Run(t, files, func(t *testing.T, env *Env) {
122545-		env.Await(Diagnostics(env.AtRegexp("include/include.go", `exclude.(X)`)))
122546-	})
122547-}
122548-
122549-// Test for golang/go#46438: support for '**' in directory filters.
122550-func TestDirectoryFilters_Wildcard(t *testing.T) {
122551-	filters := []string{"-**/bye"}
122552-	WithOptions(
122553-		ProxyFiles(workspaceProxy),
122554-		WorkspaceFolders("pkg"),
122555-		Settings{
122556-			"directoryFilters": filters,
122557-		},
122558-	).Run(t, workspaceModule, func(t *testing.T, env *Env) {
122559-		syms := env.Symbol("Bye")
122560-		sort.Slice(syms, func(i, j int) bool { return syms[i].ContainerName < syms[j].ContainerName })
122561-		for _, s := range syms {
122562-			if strings.Contains(s.ContainerName, "bye") {
122563-				t.Errorf("WorkspaceSymbol: found symbol %q with container %q with filters %v", s.Name, s.ContainerName, filters)
122564-			}
122565-		}
122566-	})
122567-}
122568-
122569-// Test for golang/go#52993: wildcard directoryFilters should apply to
122570-// goimports scanning as well.
122571-func TestDirectoryFilters_ImportScanning(t *testing.T) {
122572-	const files = `
122573--- go.mod --
122574-module mod.test
122575-
122576-go 1.12
122577--- main.go --
122578-package main
122579-
122580-func main() {
122581-	bye.Goodbye()
122582-}
122583--- p/bye/bye.go --
122584-package bye
122585-
122586-func Goodbye() {}
122587-`
122588-
122589-	WithOptions(
122590-		Settings{
122591-			"directoryFilters": []string{"-**/bye"},
122592-		},
122593-		// This test breaks in 'Experimental' mode, because with
122594-		// experimentalWorkspaceModule set we the goimports scan behaves
122595-		// differently.
122596-		//
122597-		// Since this feature is going away (golang/go#52897), don't investigate.
122598-		Modes(Default),
122599-	).Run(t, files, func(t *testing.T, env *Env) {
122600-		env.OpenFile("main.go")
122601-		beforeSave := env.BufferText("main.go")
122602-		env.OrganizeImports("main.go")
122603-		got := env.BufferText("main.go")
122604-		if got != beforeSave {
122605-			t.Errorf("after organizeImports code action, got modified buffer:\n%s", got)
122606-		}
122607-	})
122608-}
122609-
122610-// Test for golang/go#52993: non-wildcard directoryFilters should still be
122611-// applied relative to the workspace folder, not the module root.
122612-func TestDirectoryFilters_MultiRootImportScanning(t *testing.T) {
122613-	testenv.NeedsGo1Point(t, 18) // uses go.work
122614-
122615-	const files = `
122616--- go.work --
122617-go 1.18
122618-
122619-use (
122620-	a
122621-	b
122622-)
122623--- a/go.mod --
122624-module mod1.test
122625-
122626-go 1.18
122627--- a/main.go --
122628-package main
122629-
122630-func main() {
122631-	hi.Hi()
122632-}
122633--- a/hi/hi.go --
122634-package hi
122635-
122636-func Hi() {}
122637--- b/go.mod --
122638-module mod2.test
122639-
122640-go 1.18
122641--- b/main.go --
122642-package main
122643-
122644-func main() {
122645-	hi.Hi()
122646-}
122647--- b/hi/hi.go --
122648-package hi
122649-
122650-func Hi() {}
122651-`
122652-
122653-	WithOptions(
122654-		Settings{
122655-			"directoryFilters": []string{"-hi"}, // this test fails with -**/hi
122656-		},
122657-	).Run(t, files, func(t *testing.T, env *Env) {
122658-		env.OpenFile("a/main.go")
122659-		beforeSave := env.BufferText("a/main.go")
122660-		env.OrganizeImports("a/main.go")
122661-		got := env.BufferText("a/main.go")
122662-		if got == beforeSave {
122663-			t.Errorf("after organizeImports code action, got identical buffer:\n%s", got)
122664-		}
122665-	})
122666-}
122667diff -urN a/gopls/internal/regtest/workspace/fromenv_test.go b/gopls/internal/regtest/workspace/fromenv_test.go
122668--- a/gopls/internal/regtest/workspace/fromenv_test.go	2000-01-01 00:00:00.000000000 -0000
122669+++ b/gopls/internal/regtest/workspace/fromenv_test.go	1970-01-01 00:00:00.000000000 +0000
122670@@ -1,68 +0,0 @@
122671-// Copyright 2022 The Go Authors. All rights reserved.
122672-// Use of this source code is governed by a BSD-style
122673-// license that can be found in the LICENSE file.
122674-
122675-package workspace
122676-
122677-import (
122678-	"testing"
122679-
122680-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
122681-	"golang.org/x/tools/internal/testenv"
122682-)
122683-
122684-// Test that setting go.work via environment variables or settings works.
122685-func TestUseGoWorkOutsideTheWorkspace(t *testing.T) {
122686-	testenv.NeedsGo1Point(t, 18)
122687-	const files = `
122688--- work/a/go.mod --
122689-module a.com
122690-
122691-go 1.12
122692--- work/a/a.go --
122693-package a
122694--- work/b/go.mod --
122695-module b.com
122696-
122697-go 1.12
122698--- work/b/b.go --
122699-package b
122700-
122701-func _() {
122702-	x := 1 // unused
122703-}
122704--- other/c/go.mod --
122705-module c.com
122706-
122707-go 1.18
122708--- other/c/c.go --
122709-package c
122710--- config/go.work --
122711-go 1.18
122712-
122713-use (
122714-	$SANDBOX_WORKDIR/work/a
122715-	$SANDBOX_WORKDIR/work/b
122716-	$SANDBOX_WORKDIR/other/c
122717-)
122718-`
122719-
122720-	WithOptions(
122721-		WorkspaceFolders("work"), // use a nested workspace dir, so that GOWORK is outside the workspace
122722-		EnvVars{"GOWORK": "$SANDBOX_WORKDIR/config/go.work"},
122723-	).Run(t, files, func(t *testing.T, env *Env) {
122724-		// When we have an explicit GOWORK set, we should get a file watch request.
122725-		env.OnceMet(
122726-			InitialWorkspaceLoad,
122727-			FileWatchMatching(`other`),
122728-			FileWatchMatching(`config.go\.work`),
122729-		)
122730-		env.Await(FileWatchMatching(`config.go\.work`))
122731-		// Even though work/b is not open, we should get its diagnostics as it is
122732-		// included in the workspace.
122733-		env.OpenFile("work/a/a.go")
122734-		env.AfterChange(
122735-			Diagnostics(env.AtRegexp("work/b/b.go", "x := 1"), WithMessage("not used")),
122736-		)
122737-	})
122738-}
122739diff -urN a/gopls/internal/regtest/workspace/metadata_test.go b/gopls/internal/regtest/workspace/metadata_test.go
122740--- a/gopls/internal/regtest/workspace/metadata_test.go	2000-01-01 00:00:00.000000000 -0000
122741+++ b/gopls/internal/regtest/workspace/metadata_test.go	1970-01-01 00:00:00.000000000 +0000
122742@@ -1,181 +0,0 @@
122743-// Copyright 2022 The Go Authors. All rights reserved.
122744-// Use of this source code is governed by a BSD-style
122745-// license that can be found in the LICENSE file.
122746-
122747-package workspace
122748-
122749-import (
122750-	"strings"
122751-	"testing"
122752-
122753-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
122754-	"golang.org/x/tools/internal/testenv"
122755-)
122756-
122757-// TODO(rfindley): move workspace tests related to metadata bugs into this
122758-// file.
122759-
122760-func TestFixImportDecl(t *testing.T) {
122761-	const src = `
122762--- go.mod --
122763-module mod.test
122764-
122765-go 1.12
122766--- p.go --
122767-package p
122768-
122769-import (
122770-	_ "fmt"
122771-
122772-const C = 42
122773-`
122774-
122775-	Run(t, src, func(t *testing.T, env *Env) {
122776-		env.OpenFile("p.go")
122777-		env.RegexpReplace("p.go", "\"fmt\"", "\"fmt\"\n)")
122778-		env.AfterChange(
122779-			NoDiagnostics(ForFile("p.go")),
122780-		)
122781-	})
122782-}
122783-
122784-// Test that moving ignoring a file via build constraints causes diagnostics to
122785-// be resolved.
122786-func TestIgnoreFile(t *testing.T) {
122787-	testenv.NeedsGo1Point(t, 17) // needs native overlays and support for go:build directives
122788-
122789-	const src = `
122790--- go.mod --
122791-module mod.test
122792-
122793-go 1.12
122794--- foo.go --
122795-package main
122796-
122797-func main() {}
122798--- bar.go --
122799-package main
122800-
122801-func main() {}
122802-	`
122803-
122804-	WithOptions(
122805-		// TODO(golang/go#54180): we don't run in 'experimental' mode here, because
122806-		// with "experimentalUseInvalidMetadata", this test fails because the
122807-		// orphaned bar.go is diagnosed using stale metadata, and then not
122808-		// re-diagnosed when new metadata arrives.
122809-		//
122810-		// We could fix this by re-running diagnostics after a load, but should
122811-		// consider whether that is worthwhile.
122812-		Modes(Default),
122813-	).Run(t, src, func(t *testing.T, env *Env) {
122814-		env.OpenFile("foo.go")
122815-		env.OpenFile("bar.go")
122816-		env.OnceMet(
122817-			env.DoneWithOpen(),
122818-			Diagnostics(env.AtRegexp("foo.go", "func (main)")),
122819-			Diagnostics(env.AtRegexp("bar.go", "func (main)")),
122820-		)
122821-
122822-		// Ignore bar.go. This should resolve diagnostics.
122823-		env.RegexpReplace("bar.go", "package main", "//go:build ignore\n\npackage main")
122824-
122825-		// To make this test pass with experimentalUseInvalidMetadata, we could make
122826-		// an arbitrary edit that invalidates the snapshot, at which point the
122827-		// orphaned diagnostics will be invalidated.
122828-		//
122829-		// But of course, this should not be necessary: we should invalidate stale
122830-		// information when fresh metadata arrives.
122831-		// env.RegexpReplace("foo.go", "package main", "package main // test")
122832-		env.AfterChange(
122833-			NoDiagnostics(ForFile("foo.go")),
122834-			NoDiagnostics(ForFile("bar.go")),
122835-		)
122836-
122837-		// If instead of 'ignore' (which gopls treats as a standalone package) we
122838-		// used a different build tag, we should get a warning about having no
122839-		// packages for bar.go
122840-		env.RegexpReplace("bar.go", "ignore", "excluded")
122841-		env.AfterChange(
122842-			Diagnostics(env.AtRegexp("bar.go", "package (main)"), WithMessage("No packages")),
122843-		)
122844-	})
122845-}
122846-
122847-func TestReinitializeRepeatedly(t *testing.T) {
122848-	testenv.NeedsGo1Point(t, 18) // uses go.work
122849-
122850-	const multiModule = `
122851--- go.work --
122852-go 1.18
122853-
122854-use (
122855-	moda/a
122856-	modb
122857-)
122858--- moda/a/go.mod --
122859-module a.com
122860-
122861-require b.com v1.2.3
122862--- moda/a/go.sum --
122863-b.com v1.2.3 h1:tXrlXP0rnjRpKNmkbLYoWBdq0ikb3C3bKK9//moAWBI=
122864-b.com v1.2.3/go.mod h1:D+J7pfFBZK5vdIdZEFquR586vKKIkqG7Qjw9AxG5BQ8=
122865--- moda/a/a.go --
122866-package a
122867-
122868-import (
122869-	"b.com/b"
122870-)
122871-
122872-func main() {
122873-	var x int
122874-	_ = b.Hello()
122875-	// AAA
122876-}
122877--- modb/go.mod --
122878-module b.com
122879-
122880--- modb/b/b.go --
122881-package b
122882-
122883-func Hello() int {
122884-	var x int
122885-}
122886-`
122887-	WithOptions(
122888-		ProxyFiles(workspaceModuleProxy),
122889-		Settings{
122890-			// For this test, we want workspace diagnostics to start immediately
122891-			// during change processing.
122892-			"diagnosticsDelay": "0",
122893-		},
122894-	).Run(t, multiModule, func(t *testing.T, env *Env) {
122895-		env.OpenFile("moda/a/a.go")
122896-		env.AfterChange()
122897-
122898-		// This test verifies that we fully process workspace reinitialization
122899-		// (which allows GOPROXY), even when the reinitialized snapshot is
122900-		// invalidated by subsequent changes.
122901-		//
122902-		// First, update go.work to remove modb. This will cause reinitialization
122903-		// to fetch b.com from the proxy.
122904-		env.WriteWorkspaceFile("go.work", "go 1.18\nuse moda/a")
122905-		// Next, wait for gopls to start processing the change. Because we've set
122906-		// diagnosticsDelay to zero, this will start diagnosing the workspace (and
122907-		// try to reinitialize on the snapshot context).
122908-		env.Await(env.StartedChangeWatchedFiles())
122909-		// Finally, immediately make a file change to cancel the previous
122910-		// operation. This is racy, but will usually cause initialization to be
122911-		// canceled.
122912-		env.RegexpReplace("moda/a/a.go", "AAA", "BBB")
122913-		env.AfterChange()
122914-		// Now, to satisfy a definition request, gopls will try to reload moda. But
122915-		// without access to the proxy (because this is no longer a
122916-		// reinitialization), this loading will fail.
122917-		loc := env.GoToDefinition(env.RegexpSearch("moda/a/a.go", "Hello"))
122918-		got := env.Sandbox.Workdir.URIToPath(loc.URI)
122919-		if want := "[email protected]/b/b.go"; !strings.HasSuffix(got, want) {
122920-			t.Errorf("expected %s, got %v", want, got)
122921-		}
122922-	})
122923-}
122924diff -urN a/gopls/internal/regtest/workspace/misspelling_test.go b/gopls/internal/regtest/workspace/misspelling_test.go
122925--- a/gopls/internal/regtest/workspace/misspelling_test.go	2000-01-01 00:00:00.000000000 -0000
122926+++ b/gopls/internal/regtest/workspace/misspelling_test.go	1970-01-01 00:00:00.000000000 +0000
122927@@ -1,80 +0,0 @@
122928-// Copyright 2023 The Go Authors. All rights reserved.
122929-// Use of this source code is governed by a BSD-style
122930-// license that can be found in the LICENSE file.
122931-
122932-package workspace
122933-
122934-import (
122935-	"runtime"
122936-	"testing"
122937-
122938-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
122939-	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
122940-)
122941-
122942-// Test for golang/go#57081.
122943-func TestFormattingMisspelledURI(t *testing.T) {
122944-	if runtime.GOOS != "windows" && runtime.GOOS != "darwin" {
122945-		t.Skip("golang/go#57081 only reproduces on case-insensitive filesystems.")
122946-	}
122947-	const files = `
122948--- go.mod --
122949-module mod.test
122950-
122951-go 1.19
122952--- foo.go --
122953-package foo
122954-
122955-const  C = 2 // extra space is intentional
122956-`
122957-
122958-	Run(t, files, func(t *testing.T, env *Env) {
122959-		env.OpenFile("Foo.go")
122960-		env.FormatBuffer("Foo.go")
122961-		want := env.BufferText("Foo.go")
122962-
122963-		if want == "" {
122964-			t.Fatalf("Foo.go is empty")
122965-		}
122966-
122967-		// In golang/go#57081, we observed that if overlay cases don't match, gopls
122968-		// will find (and format) the on-disk contents rather than the overlay,
122969-		// resulting in invalid edits.
122970-		//
122971-		// Verify that this doesn't happen, by confirming that formatting is
122972-		// idempotent.
122973-		env.FormatBuffer("Foo.go")
122974-		got := env.BufferText("Foo.go")
122975-		if diff := compare.Text(want, got); diff != "" {
122976-			t.Errorf("invalid content after second formatting:\n%s", diff)
122977-		}
122978-	})
122979-}
122980-
122981-// Test that we can find packages for open files with different spelling on
122982-// case-insensitive file systems.
122983-func TestPackageForMisspelledURI(t *testing.T) {
122984-	t.Skip("golang/go#57081: this test fails because the Go command does not load Foo.go correctly")
122985-	if runtime.GOOS != "windows" && runtime.GOOS != "darwin" {
122986-		t.Skip("golang/go#57081 only reproduces on case-insensitive filesystems.")
122987-	}
122988-	const files = `
122989--- go.mod --
122990-module mod.test
122991-
122992-go 1.19
122993--- foo.go --
122994-package foo
122995-
122996-const C = D
122997--- bar.go --
122998-package foo
122999-
123000-const D = 2
123001-`
123002-
123003-	Run(t, files, func(t *testing.T, env *Env) {
123004-		env.OpenFile("Foo.go")
123005-		env.AfterChange(NoDiagnostics())
123006-	})
123007-}
123008diff -urN a/gopls/internal/regtest/workspace/standalone_test.go b/gopls/internal/regtest/workspace/standalone_test.go
123009--- a/gopls/internal/regtest/workspace/standalone_test.go	2000-01-01 00:00:00.000000000 -0000
123010+++ b/gopls/internal/regtest/workspace/standalone_test.go	1970-01-01 00:00:00.000000000 +0000
123011@@ -1,206 +0,0 @@
123012-// Copyright 2022 The Go Authors. All rights reserved.
123013-// Use of this source code is governed by a BSD-style
123014-// license that can be found in the LICENSE file.
123015-
123016-package workspace
123017-
123018-import (
123019-	"sort"
123020-	"testing"
123021-
123022-	"github.com/google/go-cmp/cmp"
123023-	"golang.org/x/tools/gopls/internal/lsp/protocol"
123024-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
123025-)
123026-
123027-func TestStandaloneFiles(t *testing.T) {
123028-	const files = `
123029--- go.mod --
123030-module mod.test
123031-
123032-go 1.16
123033--- lib/lib.go --
123034-package lib
123035-
123036-const C = 0
123037-
123038-type I interface {
123039-	M()
123040-}
123041--- lib/ignore.go --
123042-//go:build ignore
123043-// +build ignore
123044-
123045-package main
123046-
123047-import (
123048-	"mod.test/lib"
123049-)
123050-
123051-const C = 1
123052-
123053-type Mer struct{}
123054-func (Mer) M()
123055-
123056-func main() {
123057-	println(lib.C + C)
123058-}
123059-`
123060-	WithOptions(
123061-		// On Go 1.17 and earlier, this test fails with
123062-		// experimentalWorkspaceModule. Not investigated, as
123063-		// experimentalWorkspaceModule will be removed.
123064-		Modes(Default),
123065-	).Run(t, files, func(t *testing.T, env *Env) {
123066-		// Initially, gopls should not know about the standalone file as it hasn't
123067-		// been opened. Therefore, we should only find one symbol 'C'.
123068-		syms := env.Symbol("C")
123069-		if got, want := len(syms), 1; got != want {
123070-			t.Errorf("got %d symbols, want %d", got, want)
123071-		}
123072-
123073-		// Similarly, we should only find one reference to "C", and no
123074-		// implementations of I.
123075-		checkLocations := func(method string, gotLocations []protocol.Location, wantFiles ...string) {
123076-			var gotFiles []string
123077-			for _, l := range gotLocations {
123078-				gotFiles = append(gotFiles, env.Sandbox.Workdir.URIToPath(l.URI))
123079-			}
123080-			sort.Strings(gotFiles)
123081-			sort.Strings(wantFiles)
123082-			if diff := cmp.Diff(wantFiles, gotFiles); diff != "" {
123083-				t.Errorf("%s(...): unexpected locations (-want +got):\n%s", method, diff)
123084-			}
123085-		}
123086-
123087-		env.OpenFile("lib/lib.go")
123088-		env.AfterChange(NoDiagnostics())
123089-
123090-		// Replacing C with D should not cause any workspace diagnostics, since we
123091-		// haven't yet opened the standalone file.
123092-		env.RegexpReplace("lib/lib.go", "C", "D")
123093-		env.AfterChange(NoDiagnostics())
123094-		env.RegexpReplace("lib/lib.go", "D", "C")
123095-		env.AfterChange(NoDiagnostics())
123096-
123097-		refs := env.References(env.RegexpSearch("lib/lib.go", "C"))
123098-		checkLocations("References", refs, "lib/lib.go")
123099-
123100-		impls := env.Implementations(env.RegexpSearch("lib/lib.go", "I"))
123101-		checkLocations("Implementations", impls) // no implementations
123102-
123103-		// Opening the standalone file should not result in any diagnostics.
123104-		env.OpenFile("lib/ignore.go")
123105-		env.AfterChange(NoDiagnostics())
123106-
123107-		// Having opened the standalone file, we should find its symbols in the
123108-		// workspace.
123109-		syms = env.Symbol("C")
123110-		if got, want := len(syms), 2; got != want {
123111-			t.Fatalf("got %d symbols, want %d", got, want)
123112-		}
123113-
123114-		foundMainC := false
123115-		var symNames []string
123116-		for _, sym := range syms {
123117-			symNames = append(symNames, sym.Name)
123118-			if sym.Name == "main.C" {
123119-				foundMainC = true
123120-			}
123121-		}
123122-		if !foundMainC {
123123-			t.Errorf("WorkspaceSymbol(\"C\") = %v, want containing main.C", symNames)
123124-		}
123125-
123126-		// We should resolve workspace definitions in the standalone file.
123127-		fileLoc := env.GoToDefinition(env.RegexpSearch("lib/ignore.go", "lib.(C)"))
123128-		file := env.Sandbox.Workdir.URIToPath(fileLoc.URI)
123129-		if got, want := file, "lib/lib.go"; got != want {
123130-			t.Errorf("GoToDefinition(lib.C) = %v, want %v", got, want)
123131-		}
123132-
123133-		// ...as well as intra-file definitions
123134-		loc := env.GoToDefinition(env.RegexpSearch("lib/ignore.go", "\\+ (C)"))
123135-		wantLoc := env.RegexpSearch("lib/ignore.go", "const (C)")
123136-		if loc != wantLoc {
123137-			t.Errorf("GoToDefinition(C) = %v, want %v", loc, wantLoc)
123138-		}
123139-
123140-		// Renaming "lib.C" to "lib.D" should cause a diagnostic in the standalone
123141-		// file.
123142-		env.RegexpReplace("lib/lib.go", "C", "D")
123143-		env.AfterChange(Diagnostics(env.AtRegexp("lib/ignore.go", "lib.(C)")))
123144-
123145-		// Undoing the replacement should fix diagnostics
123146-		env.RegexpReplace("lib/lib.go", "D", "C")
123147-		env.AfterChange(NoDiagnostics())
123148-
123149-		// Now that our workspace has no errors, we should be able to find
123150-		// references and rename.
123151-		refs = env.References(env.RegexpSearch("lib/lib.go", "C"))
123152-		checkLocations("References", refs, "lib/lib.go", "lib/ignore.go")
123153-
123154-		impls = env.Implementations(env.RegexpSearch("lib/lib.go", "I"))
123155-		checkLocations("Implementations", impls, "lib/ignore.go")
123156-
123157-		// Renaming should rename in the standalone package.
123158-		env.Rename(env.RegexpSearch("lib/lib.go", "C"), "D")
123159-		env.RegexpSearch("lib/ignore.go", "lib.D")
123160-	})
123161-}
123162-
123163-func TestStandaloneFiles_Configuration(t *testing.T) {
123164-	const files = `
123165--- go.mod --
123166-module mod.test
123167-
123168-go 1.18
123169--- lib.go --
123170-package lib // without this package, files are loaded as command-line-arguments
123171--- ignore.go --
123172-//go:build ignore
123173-// +build ignore
123174-
123175-package main
123176-
123177-// An arbitrary comment.
123178-
123179-func main() {}
123180--- standalone.go --
123181-//go:build standalone
123182-// +build standalone
123183-
123184-package main
123185-
123186-func main() {}
123187-`
123188-
123189-	WithOptions(
123190-		Settings{
123191-			"standaloneTags": []string{"standalone", "script"},
123192-		},
123193-	).Run(t, files, func(t *testing.T, env *Env) {
123194-		env.OpenFile("ignore.go")
123195-		env.OpenFile("standalone.go")
123196-
123197-		env.AfterChange(
123198-			Diagnostics(env.AtRegexp("ignore.go", "package (main)")),
123199-			NoDiagnostics(ForFile("standalone.go")),
123200-		)
123201-
123202-		cfg := env.Editor.Config()
123203-		cfg.Settings = map[string]interface{}{
123204-			"standaloneTags": []string{"ignore"},
123205-		}
123206-		env.ChangeConfiguration(cfg)
123207-
123208-		// TODO(golang/go#56158): gopls does not purge previously published
123209-		// diagnostice when configuration changes.
123210-		env.RegexpReplace("ignore.go", "arbitrary", "meaningless")
123211-
123212-		env.AfterChange(
123213-			NoDiagnostics(ForFile("ignore.go")),
123214-			Diagnostics(env.AtRegexp("standalone.go", "package (main)")),
123215-		)
123216-	})
123217-}
123218diff -urN a/gopls/internal/regtest/workspace/workspace_test.go b/gopls/internal/regtest/workspace/workspace_test.go
123219--- a/gopls/internal/regtest/workspace/workspace_test.go	2000-01-01 00:00:00.000000000 -0000
123220+++ b/gopls/internal/regtest/workspace/workspace_test.go	1970-01-01 00:00:00.000000000 +0000
123221@@ -1,1263 +0,0 @@
123222-// Copyright 2020 The Go Authors. All rights reserved.
123223-// Use of this source code is governed by a BSD-style
123224-// license that can be found in the LICENSE file.
123225-
123226-package workspace
123227-
123228-import (
123229-	"context"
123230-	"fmt"
123231-	"path/filepath"
123232-	"strings"
123233-	"testing"
123234-
123235-	"golang.org/x/tools/gopls/internal/hooks"
123236-	"golang.org/x/tools/gopls/internal/lsp"
123237-	"golang.org/x/tools/gopls/internal/lsp/fake"
123238-	"golang.org/x/tools/gopls/internal/lsp/protocol"
123239-	"golang.org/x/tools/internal/bug"
123240-	"golang.org/x/tools/internal/gocommand"
123241-	"golang.org/x/tools/internal/testenv"
123242-
123243-	. "golang.org/x/tools/gopls/internal/lsp/regtest"
123244-)
123245-
123246-func TestMain(m *testing.M) {
123247-	bug.PanicOnBugs = true
123248-	Main(m, hooks.Options)
123249-}
123250-
123251-const workspaceProxy = `
123252--- [email protected]/go.mod --
123253-module example.com
123254-
123255-go 1.12
123256--- [email protected]/blah/blah.go --
123257-package blah
123258-
123259-import "fmt"
123260-
123261-func SaySomething() {
123262-	fmt.Println("something")
123263-}
123264--- [email protected]/go.mod --
123265-module random.org
123266-
123267-go 1.12
123268--- [email protected]/bye/bye.go --
123269-package bye
123270-
123271-func Goodbye() {
123272-	println("Bye")
123273-}
123274-`
123275-
123276-// TODO: Add a replace directive.
123277-const workspaceModule = `
123278--- pkg/go.mod --
123279-module mod.com
123280-
123281-go 1.14
123282-
123283-require (
123284-	example.com v1.2.3
123285-	random.org v1.2.3
123286-)
123287--- pkg/go.sum --
123288-example.com v1.2.3 h1:veRD4tUnatQRgsULqULZPjeoBGFr2qBhevSCZllD2Ds=
123289-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
123290-random.org v1.2.3 h1:+JE2Fkp7gS0zsHXGEQJ7hraom3pNTlkxC4b2qPfA+/Q=
123291-random.org v1.2.3/go.mod h1:E9KM6+bBX2g5ykHZ9H27w16sWo3QwgonyjM44Dnej3I=
123292--- pkg/main.go --
123293-package main
123294-
123295-import (
123296-	"example.com/blah"
123297-	"mod.com/inner"
123298-	"random.org/bye"
123299-)
123300-
123301-func main() {
123302-	blah.SaySomething()
123303-	inner.Hi()
123304-	bye.Goodbye()
123305-}
123306--- pkg/main2.go --
123307-package main
123308-
123309-import "fmt"
123310-
123311-func _() {
123312-	fmt.Print("%s")
123313-}
123314--- pkg/inner/inner.go --
123315-package inner
123316-
123317-import "example.com/blah"
123318-
123319-func Hi() {
123320-	blah.SaySomething()
123321-}
123322--- goodbye/bye/bye.go --
123323-package bye
123324-
123325-func Bye() {}
123326--- goodbye/go.mod --
123327-module random.org
123328-
123329-go 1.12
123330-`
123331-
123332-// Confirm that find references returns all of the references in the module,
123333-// regardless of what the workspace root is.
123334-func TestReferences(t *testing.T) {
123335-	for _, tt := range []struct {
123336-		name, rootPath string
123337-	}{
123338-		{
123339-			name:     "module root",
123340-			rootPath: "pkg",
123341-		},
123342-		{
123343-			name:     "subdirectory",
123344-			rootPath: "pkg/inner",
123345-		},
123346-	} {
123347-		t.Run(tt.name, func(t *testing.T) {
123348-			opts := []RunOption{ProxyFiles(workspaceProxy)}
123349-			if tt.rootPath != "" {
123350-				opts = append(opts, WorkspaceFolders(tt.rootPath))
123351-			}
123352-			WithOptions(opts...).Run(t, workspaceModule, func(t *testing.T, env *Env) {
123353-				f := "pkg/inner/inner.go"
123354-				env.OpenFile(f)
123355-				locations := env.References(env.RegexpSearch(f, `SaySomething`))
123356-				want := 3
123357-				if got := len(locations); got != want {
123358-					t.Fatalf("expected %v locations, got %v", want, got)
123359-				}
123360-			})
123361-		})
123362-	}
123363-}
123364-
123365-// Make sure that analysis diagnostics are cleared for the whole package when
123366-// the only opened file is closed. This test was inspired by the experience in
123367-// VS Code, where clicking on a reference result triggers a
123368-// textDocument/didOpen without a corresponding textDocument/didClose.
123369-func TestClearAnalysisDiagnostics(t *testing.T) {
123370-	WithOptions(
123371-		ProxyFiles(workspaceProxy),
123372-		WorkspaceFolders("pkg/inner"),
123373-	).Run(t, workspaceModule, func(t *testing.T, env *Env) {
123374-		env.OpenFile("pkg/main.go")
123375-		env.AfterChange(
123376-			Diagnostics(env.AtRegexp("pkg/main2.go", "fmt.Print")),
123377-		)
123378-		env.CloseBuffer("pkg/main.go")
123379-		env.AfterChange(
123380-			NoDiagnostics(ForFile("pkg/main2.go")),
123381-		)
123382-	})
123383-}
123384-
123385-// TestReloadOnlyOnce checks that changes to the go.mod file do not result in
123386-// redundant package loads (golang/go#54473).
123387-//
123388-// Note that this test may be fragile, as it depends on specific structure to
123389-// log messages around reinitialization. Nevertheless, it is important for
123390-// guarding against accidentally duplicate reloading.
123391-func TestReloadOnlyOnce(t *testing.T) {
123392-	WithOptions(
123393-		ProxyFiles(workspaceProxy),
123394-		WorkspaceFolders("pkg"),
123395-	).Run(t, workspaceModule, func(t *testing.T, env *Env) {
123396-		dir := env.Sandbox.Workdir.URI("goodbye").SpanURI().Filename()
123397-		goModWithReplace := fmt.Sprintf(`%s
123398-replace random.org => %s
123399-`, env.ReadWorkspaceFile("pkg/go.mod"), dir)
123400-		env.WriteWorkspaceFile("pkg/go.mod", goModWithReplace)
123401-		env.AfterChange(
123402-			LogMatching(protocol.Info, `packages\.Load #\d+\n`, 2, false),
123403-		)
123404-	})
123405-}
123406-
123407-// This test checks that gopls updates the set of files it watches when a
123408-// replace target is added to the go.mod.
123409-func TestWatchReplaceTargets(t *testing.T) {
123410-	t.Skipf("skipping known-flaky test: see https://go.dev/issue/50748")
123411-
123412-	WithOptions(
123413-		ProxyFiles(workspaceProxy),
123414-		WorkspaceFolders("pkg"),
123415-	).Run(t, workspaceModule, func(t *testing.T, env *Env) {
123416-		// Add a replace directive and expect the files that gopls is watching
123417-		// to change.
123418-		dir := env.Sandbox.Workdir.URI("goodbye").SpanURI().Filename()
123419-		goModWithReplace := fmt.Sprintf(`%s
123420-replace random.org => %s
123421-`, env.ReadWorkspaceFile("pkg/go.mod"), dir)
123422-		env.WriteWorkspaceFile("pkg/go.mod", goModWithReplace)
123423-		env.AfterChange(
123424-			UnregistrationMatching("didChangeWatchedFiles"),
123425-			RegistrationMatching("didChangeWatchedFiles"),
123426-		)
123427-	})
123428-}
123429-
123430-const workspaceModuleProxy = `
123431--- [email protected]/go.mod --
123432-module example.com
123433-
123434-go 1.12
123435--- [email protected]/blah/blah.go --
123436-package blah
123437-
123438-import "fmt"
123439-
123440-func SaySomething() {
123441-	fmt.Println("something")
123442-}
123443--- [email protected]/go.mod --
123444-module b.com
123445-
123446-go 1.12
123447--- [email protected]/b/b.go --
123448-package b
123449-
123450-func Hello() {}
123451-`
123452-
123453-func TestAutomaticWorkspaceModule_Interdependent(t *testing.T) {
123454-	testenv.NeedsGo1Point(t, 18) // uses go.work
123455-	const multiModule = `
123456--- moda/a/go.mod --
123457-module a.com
123458-
123459-require b.com v1.2.3
123460--- moda/a/go.sum --
123461-b.com v1.2.3 h1:tXrlXP0rnjRpKNmkbLYoWBdq0ikb3C3bKK9//moAWBI=
123462-b.com v1.2.3/go.mod h1:D+J7pfFBZK5vdIdZEFquR586vKKIkqG7Qjw9AxG5BQ8=
123463--- moda/a/a.go --
123464-package a
123465-
123466-import (
123467-	"b.com/b"
123468-)
123469-
123470-func main() {
123471-	var x int
123472-	_ = b.Hello()
123473-}
123474--- modb/go.mod --
123475-module b.com
123476-
123477--- modb/b/b.go --
123478-package b
123479-
123480-func Hello() int {
123481-	var x int
123482-}
123483-`
123484-	WithOptions(
123485-		ProxyFiles(workspaceModuleProxy),
123486-	).Run(t, multiModule, func(t *testing.T, env *Env) {
123487-		env.RunGoCommand("work", "init")
123488-		env.RunGoCommand("work", "use", "-r", ".")
123489-		env.AfterChange(
123490-			Diagnostics(env.AtRegexp("moda/a/a.go", "x")),
123491-			Diagnostics(env.AtRegexp("modb/b/b.go", "x")),
123492-			NoDiagnostics(env.AtRegexp("moda/a/a.go", `"b.com/b"`)),
123493-		)
123494-	})
123495-}
123496-
123497-func TestModuleWithExclude(t *testing.T) {
123498-	const proxy = `
123499--- [email protected]/go.mod --
123500-module c.com
123501-
123502-go 1.12
123503-
123504-require b.com v1.2.3
123505--- [email protected]/blah/blah.go --
123506-package blah
123507-
123508-import "fmt"
123509-
123510-func SaySomething() {
123511-	fmt.Println("something")
123512-}
123513--- [email protected]/go.mod --
123514-module b.com
123515-
123516-go 1.12
123517--- [email protected]/b/b.go --
123518-package b
123519-
123520-func Hello() {}
123521--- [email protected]/go.mod --
123522-module b.com
123523-
123524-go 1.12
123525-`
123526-	const multiModule = `
123527--- go.mod --
123528-module a.com
123529-
123530-require c.com v1.2.3
123531-
123532-exclude b.com v1.2.3
123533--- go.sum --
123534-c.com v1.2.3 h1:n07Dz9fYmpNqvZMwZi5NEqFcSHbvLa9lacMX+/g25tw=
123535-c.com v1.2.3/go.mod h1:/4TyYgU9Nu5tA4NymP5xyqE8R2VMzGD3TbJCwCOvHAg=
123536--- main.go --
123537-package a
123538-
123539-func main() {
123540-	var x int
123541-}
123542-`
123543-	WithOptions(
123544-		ProxyFiles(proxy),
123545-	).Run(t, multiModule, func(t *testing.T, env *Env) {
123546-		env.OnceMet(
123547-			InitialWorkspaceLoad,
123548-			Diagnostics(env.AtRegexp("main.go", "x")),
123549-		)
123550-	})
123551-}
123552-
123553-// This change tests that the version of the module used changes after it has
123554-// been deleted from the workspace.
123555-//
123556-// TODO(golang/go#55331): delete this placeholder along with experimental
123557-// workspace module.
123558-func TestDeleteModule_Interdependent(t *testing.T) {
123559-	testenv.NeedsGo1Point(t, 18) // uses go.work
123560-	const multiModule = `
123561--- go.work --
123562-go 1.18
123563-
123564-use (
123565-	moda/a
123566-	modb
123567-)
123568--- moda/a/go.mod --
123569-module a.com
123570-
123571-require b.com v1.2.3
123572--- moda/a/go.sum --
123573-b.com v1.2.3 h1:tXrlXP0rnjRpKNmkbLYoWBdq0ikb3C3bKK9//moAWBI=
123574-b.com v1.2.3/go.mod h1:D+J7pfFBZK5vdIdZEFquR586vKKIkqG7Qjw9AxG5BQ8=
123575--- moda/a/a.go --
123576-package a
123577-
123578-import (
123579-	"b.com/b"
123580-)
123581-
123582-func main() {
123583-	var x int
123584-	_ = b.Hello()
123585-}
123586--- modb/go.mod --
123587-module b.com
123588-
123589--- modb/b/b.go --
123590-package b
123591-
123592-func Hello() int {
123593-	var x int
123594-}
123595-`
123596-	WithOptions(
123597-		ProxyFiles(workspaceModuleProxy),
123598-	).Run(t, multiModule, func(t *testing.T, env *Env) {
123599-		env.OpenFile("moda/a/a.go")
123600-		env.Await(env.DoneWithOpen())
123601-
123602-		originalLoc := env.GoToDefinition(env.RegexpSearch("moda/a/a.go", "Hello"))
123603-		original := env.Sandbox.Workdir.URIToPath(originalLoc.URI)
123604-		if want := "modb/b/b.go"; !strings.HasSuffix(original, want) {
123605-			t.Errorf("expected %s, got %v", want, original)
123606-		}
123607-		env.CloseBuffer(original)
123608-		env.AfterChange()
123609-
123610-		env.RemoveWorkspaceFile("modb/b/b.go")
123611-		env.RemoveWorkspaceFile("modb/go.mod")
123612-		env.WriteWorkspaceFile("go.work", "go 1.18\nuse moda/a")
123613-		env.AfterChange()
123614-
123615-		gotLoc := env.GoToDefinition(env.RegexpSearch("moda/a/a.go", "Hello"))
123616-		got := env.Sandbox.Workdir.URIToPath(gotLoc.URI)
123617-		if want := "[email protected]/b/b.go"; !strings.HasSuffix(got, want) {
123618-			t.Errorf("expected %s, got %v", want, got)
123619-		}
123620-	})
123621-}
123622-
123623-// Tests that the version of the module used changes after it has been added
123624-// to the workspace.
123625-func TestCreateModule_Interdependent(t *testing.T) {
123626-	testenv.NeedsGo1Point(t, 18) // uses go.work
123627-	const multiModule = `
123628--- go.work --
123629-go 1.18
123630-
123631-use (
123632-	moda/a
123633-)
123634--- moda/a/go.mod --
123635-module a.com
123636-
123637-require b.com v1.2.3
123638--- moda/a/go.sum --
123639-b.com v1.2.3 h1:tXrlXP0rnjRpKNmkbLYoWBdq0ikb3C3bKK9//moAWBI=
123640-b.com v1.2.3/go.mod h1:D+J7pfFBZK5vdIdZEFquR586vKKIkqG7Qjw9AxG5BQ8=
123641--- moda/a/a.go --
123642-package a
123643-
123644-import (
123645-	"b.com/b"
123646-)
123647-
123648-func main() {
123649-	var x int
123650-	_ = b.Hello()
123651-}
123652-`
123653-	WithOptions(
123654-		ProxyFiles(workspaceModuleProxy),
123655-	).Run(t, multiModule, func(t *testing.T, env *Env) {
123656-		env.OpenFile("moda/a/a.go")
123657-		loc := env.GoToDefinition(env.RegexpSearch("moda/a/a.go", "Hello"))
123658-		original := env.Sandbox.Workdir.URIToPath(loc.URI)
123659-		if want := "[email protected]/b/b.go"; !strings.HasSuffix(original, want) {
123660-			t.Errorf("expected %s, got %v", want, original)
123661-		}
123662-		env.CloseBuffer(original)
123663-		env.WriteWorkspaceFiles(map[string]string{
123664-			"go.work": `go 1.18
123665-
123666-use (
123667-	moda/a
123668-	modb
123669-)
123670-`,
123671-			"modb/go.mod": "module b.com",
123672-			"modb/b/b.go": `package b
123673-
123674-func Hello() int {
123675-	var x int
123676-}
123677-`,
123678-		})
123679-		env.AfterChange(Diagnostics(env.AtRegexp("modb/b/b.go", "x")))
123680-		gotLoc := env.GoToDefinition(env.RegexpSearch("moda/a/a.go", "Hello"))
123681-		got := env.Sandbox.Workdir.URIToPath(gotLoc.URI)
123682-		if want := "modb/b/b.go"; !strings.HasSuffix(got, want) {
123683-			t.Errorf("expected %s, got %v", want, original)
123684-		}
123685-	})
123686-}
123687-
123688-// This test confirms that a gopls workspace can recover from initialization
123689-// with one invalid module.
123690-func TestOneBrokenModule(t *testing.T) {
123691-	testenv.NeedsGo1Point(t, 18) // uses go.work
123692-	const multiModule = `
123693--- go.work --
123694-go 1.18
123695-
123696-use (
123697-	moda/a
123698-	modb
123699-)
123700--- moda/a/go.mod --
123701-module a.com
123702-
123703-require b.com v1.2.3
123704-
123705--- moda/a/a.go --
123706-package a
123707-
123708-import (
123709-	"b.com/b"
123710-)
123711-
123712-func main() {
123713-	var x int
123714-	_ = b.Hello()
123715-}
123716--- modb/go.mod --
123717-modul b.com // typo here
123718-
123719--- modb/b/b.go --
123720-package b
123721-
123722-func Hello() int {
123723-	var x int
123724-}
123725-`
123726-	WithOptions(
123727-		ProxyFiles(workspaceModuleProxy),
123728-	).Run(t, multiModule, func(t *testing.T, env *Env) {
123729-		env.OpenFile("modb/go.mod")
123730-		env.AfterChange(
123731-			Diagnostics(AtPosition("modb/go.mod", 0, 0)),
123732-		)
123733-		env.RegexpReplace("modb/go.mod", "modul", "module")
123734-		env.SaveBufferWithoutActions("modb/go.mod")
123735-		env.AfterChange(
123736-			Diagnostics(env.AtRegexp("modb/b/b.go", "x")),
123737-		)
123738-	})
123739-}
123740-
123741-// TestBadGoWork exercises the panic from golang/vscode-go#2121.
123742-func TestBadGoWork(t *testing.T) {
123743-	const files = `
123744--- go.work --
123745-use ./bar
123746--- bar/go.mod --
123747-module example.com/bar
123748-`
123749-	Run(t, files, func(t *testing.T, env *Env) {
123750-		env.OpenFile("go.work")
123751-	})
123752-}
123753-
123754-func TestUseGoWork(t *testing.T) {
123755-	testenv.NeedsGo1Point(t, 18) // uses go.work
123756-	// This test validates certain functionality related to using a go.work
123757-	// file to specify workspace modules.
123758-	const multiModule = `
123759--- moda/a/go.mod --
123760-module a.com
123761-
123762-require b.com v1.2.3
123763--- moda/a/go.sum --
123764-b.com v1.2.3 h1:tXrlXP0rnjRpKNmkbLYoWBdq0ikb3C3bKK9//moAWBI=
123765-b.com v1.2.3/go.mod h1:D+J7pfFBZK5vdIdZEFquR586vKKIkqG7Qjw9AxG5BQ8=
123766--- moda/a/a.go --
123767-package a
123768-
123769-import (
123770-	"b.com/b"
123771-)
123772-
123773-func main() {
123774-	var x int
123775-	_ = b.Hello()
123776-}
123777--- modb/go.mod --
123778-module b.com
123779-
123780-require example.com v1.2.3
123781--- modb/go.sum --
123782-example.com v1.2.3 h1:Yryq11hF02fEf2JlOS2eph+ICE2/ceevGV3C9dl5V/c=
123783-example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
123784--- modb/b/b.go --
123785-package b
123786-
123787-func Hello() int {
123788-	var x int
123789-}
123790--- go.work --
123791-go 1.17
123792-
123793-use (
123794-	./moda/a
123795-)
123796-`
123797-	WithOptions(
123798-		ProxyFiles(workspaceModuleProxy),
123799-	).Run(t, multiModule, func(t *testing.T, env *Env) {
123800-		// Initially, the go.work should cause only the a.com module to be
123801-		// loaded. Validate this by jumping to a definition in b.com and ensuring
123802-		// that we go to the module cache.
123803-		env.OpenFile("moda/a/a.go")
123804-		env.Await(env.DoneWithOpen())
123805-
123806-		// To verify which modules are loaded, we'll jump to the definition of
123807-		// b.Hello.
123808-		checkHelloLocation := func(want string) error {
123809-			loc := env.GoToDefinition(env.RegexpSearch("moda/a/a.go", "Hello"))
123810-			file := env.Sandbox.Workdir.URIToPath(loc.URI)
123811-			if !strings.HasSuffix(file, want) {
123812-				return fmt.Errorf("expected %s, got %v", want, file)
123813-			}
123814-			return nil
123815-		}
123816-
123817-		// Initially this should be in the module cache, as b.com is not replaced.
123818-		if err := checkHelloLocation("[email protected]/b/b.go"); err != nil {
123819-			t.Fatal(err)
123820-		}
123821-
123822-		// Now, modify the go.work file on disk to activate the b.com module in
123823-		// the workspace.
123824-		env.WriteWorkspaceFile("go.work", `
123825-go 1.17
123826-
123827-use (
123828-	./moda/a
123829-	./modb
123830-)
123831-`)
123832-
123833-		// As of golang/go#54069, writing go.work to the workspace triggers a
123834-		// workspace reload.
123835-		env.AfterChange(
123836-			Diagnostics(env.AtRegexp("modb/b/b.go", "x")),
123837-		)
123838-
123839-		// Jumping to definition should now go to b.com in the workspace.
123840-		if err := checkHelloLocation("modb/b/b.go"); err != nil {
123841-			t.Fatal(err)
123842-		}
123843-
123844-		// Now, let's modify the go.work *overlay* (not on disk), and verify that
123845-		// this change is only picked up once it is saved.
123846-		env.OpenFile("go.work")
123847-		env.AfterChange()
123848-		env.SetBufferContent("go.work", `go 1.17
123849-
123850-use (
123851-	./moda/a
123852-)`)
123853-
123854-		// Simply modifying the go.work file does not cause a reload, so we should
123855-		// still jump within the workspace.
123856-		//
123857-		// TODO: should editing the go.work above cause modb diagnostics to be
123858-		// suppressed?
123859-		env.Await(env.DoneWithChange())
123860-		if err := checkHelloLocation("modb/b/b.go"); err != nil {
123861-			t.Fatal(err)
123862-		}
123863-
123864-		// Saving should reload the workspace.
123865-		env.SaveBufferWithoutActions("go.work")
123866-		if err := checkHelloLocation("[email protected]/b/b.go"); err != nil {
123867-			t.Fatal(err)
123868-		}
123869-
123870-		// This fails if guarded with a OnceMet(DoneWithSave(), ...), because it is
123871-		// debounced (and therefore not synchronous with the change).
123872-		env.Await(NoDiagnostics(ForFile("modb/go.mod")))
123873-
123874-		// Test Formatting.
123875-		env.SetBufferContent("go.work", `go 1.18
123876-  use      (
123877-
123878-
123879-
123880-		./moda/a
123881-)
123882-`) // TODO(matloob): For some reason there's a "start position 7:0 is out of bounds" error when the ")" is on the last character/line in the file. Rob probably knows what's going on.
123883-		env.SaveBuffer("go.work")
123884-		env.Await(env.DoneWithSave())
123885-		gotWorkContents := env.ReadWorkspaceFile("go.work")
123886-		wantWorkContents := `go 1.18
123887-
123888-use (
123889-	./moda/a
123890-)
123891-`
123892-		if gotWorkContents != wantWorkContents {
123893-			t.Fatalf("formatted contents of workspace: got %q; want %q", gotWorkContents, wantWorkContents)
123894-		}
123895-	})
123896-}
123897-
123898-func TestUseGoWorkDiagnosticMissingModule(t *testing.T) {
123899-	testenv.NeedsGo1Point(t, 18) // uses go.work
123900-
123901-	const files = `
123902--- go.work --
123903-go 1.18
123904-
123905-use ./foo
123906--- bar/go.mod --
123907-module example.com/bar
123908-`
123909-	Run(t, files, func(t *testing.T, env *Env) {
123910-		env.OpenFile("go.work")
123911-		env.AfterChange(
123912-			Diagnostics(env.AtRegexp("go.work", "use"), WithMessage("directory ./foo does not contain a module")),
123913-		)
123914-		// The following tests is a regression test against an issue where we weren't
123915-		// copying the workFile struct field on workspace when a new one was created in
123916-		// (*workspace).invalidate. Set the buffer content to a working file so that
123917-		// invalidate recognizes the workspace to be change and copies over the workspace
123918-		// struct, and then set the content back to the old contents to make sure
123919-		// the diagnostic still shows up.
123920-		env.SetBufferContent("go.work", "go 1.18 \n\n use ./bar\n")
123921-		env.AfterChange(
123922-			NoDiagnostics(env.AtRegexp("go.work", "use")),
123923-		)
123924-		env.SetBufferContent("go.work", "go 1.18 \n\n use ./foo\n")
123925-		env.AfterChange(
123926-			Diagnostics(env.AtRegexp("go.work", "use"), WithMessage("directory ./foo does not contain a module")),
123927-		)
123928-	})
123929-}
123930-
123931-func TestUseGoWorkDiagnosticSyntaxError(t *testing.T) {
123932-	testenv.NeedsGo1Point(t, 18)
123933-	const files = `
123934--- go.work --
123935-go 1.18
123936-
123937-usa ./foo
123938-replace
123939-`
123940-	Run(t, files, func(t *testing.T, env *Env) {
123941-		env.OpenFile("go.work")
123942-		env.AfterChange(
123943-			Diagnostics(env.AtRegexp("go.work", "usa"), WithMessage("unknown directive: usa")),
123944-			Diagnostics(env.AtRegexp("go.work", "replace"), WithMessage("usage: replace")),
123945-		)
123946-	})
123947-}
123948-
123949-func TestUseGoWorkHover(t *testing.T) {
123950-	testenv.NeedsGo1Point(t, 18)
123951-
123952-	const files = `
123953--- go.work --
123954-go 1.18
123955-
123956-use ./foo
123957-use (
123958-	./bar
123959-	./bar/baz
123960-)
123961--- foo/go.mod --
123962-module example.com/foo
123963--- bar/go.mod --
123964-module example.com/bar
123965--- bar/baz/go.mod --
123966-module example.com/bar/baz
123967-`
123968-	Run(t, files, func(t *testing.T, env *Env) {
123969-		env.OpenFile("go.work")
123970-
123971-		tcs := map[string]string{
123972-			`\./foo`:      "example.com/foo",
123973-			`(?m)\./bar$`: "example.com/bar",
123974-			`\./bar/baz`:  "example.com/bar/baz",
123975-		}
123976-
123977-		for hoverRE, want := range tcs {
123978-			got, _ := env.Hover(env.RegexpSearch("go.work", hoverRE))
123979-			if got.Value != want {
123980-				t.Errorf(`hover on %q: got %q, want %q`, hoverRE, got, want)
123981-			}
123982-		}
123983-	})
123984-}
123985-
123986-func TestExpandToGoWork(t *testing.T) {
123987-	testenv.NeedsGo1Point(t, 18)
123988-	const workspace = `
123989--- moda/a/go.mod --
123990-module a.com
123991-
123992-require b.com v1.2.3
123993--- moda/a/a.go --
123994-package a
123995-
123996-import (
123997-	"b.com/b"
123998-)
123999-
124000-func main() {
124001-	var x int
124002-	_ = b.Hello()
124003-}
124004--- modb/go.mod --
124005-module b.com
124006-
124007-require example.com v1.2.3
124008--- modb/b/b.go --
124009-package b
124010-
124011-func Hello() int {
124012-	var x int
124013-}
124014--- go.work --
124015-go 1.17
124016-
124017-use (
124018-	./moda/a
124019-	./modb
124020-)
124021-`
124022-	WithOptions(
124023-		WorkspaceFolders("moda/a"),
124024-	).Run(t, workspace, func(t *testing.T, env *Env) {
124025-		env.OpenFile("moda/a/a.go")
124026-		env.Await(env.DoneWithOpen())
124027-		loc := env.GoToDefinition(env.RegexpSearch("moda/a/a.go", "Hello"))
124028-		file := env.Sandbox.Workdir.URIToPath(loc.URI)
124029-		want := "modb/b/b.go"
124030-		if !strings.HasSuffix(file, want) {
124031-			t.Errorf("expected %s, got %v", want, file)
124032-		}
124033-	})
124034-}
124035-
124036-func TestNonWorkspaceFileCreation(t *testing.T) {
124037-	const files = `
124038--- work/go.mod --
124039-module mod.com
124040-
124041-go 1.12
124042--- work/x.go --
124043-package x
124044-`
124045-
124046-	const code = `
124047-package foo
124048-import "fmt"
124049-var _ = fmt.Printf
124050-`
124051-	WithOptions(
124052-		WorkspaceFolders("work"), // so that outside/... is outside the workspace
124053-	).Run(t, files, func(t *testing.T, env *Env) {
124054-		env.CreateBuffer("outside/foo.go", "")
124055-		env.EditBuffer("outside/foo.go", fake.NewEdit(0, 0, 0, 0, code))
124056-		env.GoToDefinition(env.RegexpSearch("outside/foo.go", `Printf`))
124057-	})
124058-}
124059-
124060-func TestGoWork_V2Module(t *testing.T) {
124061-	testenv.NeedsGo1Point(t, 18) // uses go.work
124062-	// When using a go.work, we must have proxy content even if it is replaced.
124063-	const proxy = `
124064--- b.com/v2@v2.1.9/go.mod --
124065-module b.com/v2
124066-
124067-go 1.12
124068--- b.com/v2@v2.1.9/b/b.go --
124069-package b
124070-
124071-func Ciao()() int {
124072-	return 0
124073-}
124074-`
124075-
124076-	const multiModule = `
124077--- go.work --
124078-go 1.18
124079-
124080-use (
124081-	moda/a
124082-	modb
124083-	modb/v2
124084-	modc
124085-)
124086--- moda/a/go.mod --
124087-module a.com
124088-
124089-require b.com/v2 v2.1.9
124090--- moda/a/a.go --
124091-package a
124092-
124093-import (
124094-	"b.com/v2/b"
124095-)
124096-
124097-func main() {
124098-	var x int
124099-	_ = b.Hi()
124100-}
124101--- modb/go.mod --
124102-module b.com
124103-
124104--- modb/b/b.go --
124105-package b
124106-
124107-func Hello() int {
124108-	var x int
124109-}
124110--- modb/v2/go.mod --
124111-module b.com/v2
124112-
124113--- modb/v2/b/b.go --
124114-package b
124115-
124116-func Hi() int {
124117-	var x int
124118-}
124119--- modc/go.mod --
124120-module gopkg.in/yaml.v1 // test gopkg.in versions
124121--- modc/main.go --
124122-package main
124123-
124124-func main() {
124125-	var x int
124126-}
124127-`
124128-
124129-	WithOptions(
124130-		ProxyFiles(proxy),
124131-	).Run(t, multiModule, func(t *testing.T, env *Env) {
124132-		env.OnceMet(
124133-			InitialWorkspaceLoad,
124134-			// TODO(rfindley): assert on the full set of diagnostics here. We
124135-			// should ensure that we don't have a diagnostic at b.Hi in a.go.
124136-			Diagnostics(env.AtRegexp("moda/a/a.go", "x")),
124137-			Diagnostics(env.AtRegexp("modb/b/b.go", "x")),
124138-			Diagnostics(env.AtRegexp("modb/v2/b/b.go", "x")),
124139-			Diagnostics(env.AtRegexp("modc/main.go", "x")),
124140-		)
124141-	})
124142-}
124143-
124144-// Confirm that a fix for a tidy module will correct all modules in the
124145-// workspace.
124146-func TestMultiModule_OneBrokenModule(t *testing.T) {
124147-	// In the earlier 'experimental workspace mode', gopls would aggregate go.sum
124148-	// entries for the workspace module, allowing it to correctly associate
124149-	// missing go.sum with diagnostics. With go.work files, this doesn't work:
124150-	// the go.command will happily write go.work.sum.
124151-	t.Skip("golang/go#57509: go.mod diagnostics do not work in go.work mode")
124152-	testenv.NeedsGo1Point(t, 18) // uses go.work
124153-	const files = `
124154--- go.work --
124155-go 1.18
124156-
124157-use (
124158-	a
124159-	b
124160-)
124161--- go.work.sum --
124162--- a/go.mod --
124163-module a.com
124164-
124165-go 1.12
124166--- a/main.go --
124167-package main
124168--- b/go.mod --
124169-module b.com
124170-
124171-go 1.12
124172-
124173-require (
124174-	example.com v1.2.3
124175-)
124176--- b/go.sum --
124177--- b/main.go --
124178-package b
124179-
124180-import "example.com/blah"
124181-
124182-func main() {
124183-	blah.Hello()
124184-}
124185-`
124186-	WithOptions(
124187-		ProxyFiles(workspaceProxy),
124188-	).Run(t, files, func(t *testing.T, env *Env) {
124189-		params := &protocol.PublishDiagnosticsParams{}
124190-		env.OpenFile("b/go.mod")
124191-		env.AfterChange(
124192-			Diagnostics(
124193-				env.AtRegexp("go.mod", `example.com v1.2.3`),
124194-				WithMessage("go.sum is out of sync"),
124195-			),
124196-			ReadDiagnostics("b/go.mod", params),
124197-		)
124198-		for _, d := range params.Diagnostics {
124199-			if !strings.Contains(d.Message, "go.sum is out of sync") {
124200-				continue
124201-			}
124202-			actions := env.GetQuickFixes("b/go.mod", []protocol.Diagnostic{d})
124203-			if len(actions) != 2 {
124204-				t.Fatalf("expected 2 code actions, got %v", len(actions))
124205-			}
124206-			env.ApplyQuickFixes("b/go.mod", []protocol.Diagnostic{d})
124207-		}
124208-		env.AfterChange(
124209-			NoDiagnostics(ForFile("b/go.mod")),
124210-		)
124211-	})
124212-}
124213-
124214-// Sometimes users may have their module cache within the workspace.
124215-// We shouldn't consider any module in the module cache to be in the workspace.
124216-func TestGOMODCACHEInWorkspace(t *testing.T) {
124217-	const mod = `
124218--- a/go.mod --
124219-module a.com
124220-
124221-go 1.12
124222--- a/a.go --
124223-package a
124224-
124225-func _() {}
124226--- a/c/c.go --
124227-package c
124228--- gopath/src/b/b.go --
124229-package b
124230--- gopath/pkg/mod/example.com/go.mod --
124231-module example.com
124232-
124233-go 1.12
124234--- gopath/pkg/mod/example.com/main.go --
124235-package main
124236-`
124237-	WithOptions(
124238-		EnvVars{"GOPATH": filepath.FromSlash("$SANDBOX_WORKDIR/gopath")},
124239-		Modes(Default),
124240-	).Run(t, mod, func(t *testing.T, env *Env) {
124241-		env.Await(
124242-			// Confirm that the build configuration is seen as valid,
124243-			// even though there are technically multiple go.mod files in the
124244-			// worskpace.
124245-			LogMatching(protocol.Info, ".*valid build configuration = true.*", 1, false),
124246-		)
124247-	})
124248-}
124249-
124250-func TestAddAndRemoveGoWork(t *testing.T) {
124251-	testenv.NeedsGo1Point(t, 18)
124252-	// Use a workspace with a module in the root directory to exercise the case
124253-	// where a go.work is added to the existing root directory. This verifies
124254-	// that we're detecting changes to the module source, not just the root
124255-	// directory.
124256-	const nomod = `
124257--- go.mod --
124258-module a.com
124259-
124260-go 1.16
124261--- main.go --
124262-package main
124263-
124264-func main() {}
124265--- b/go.mod --
124266-module b.com
124267-
124268-go 1.16
124269--- b/main.go --
124270-package main
124271-
124272-func main() {}
124273-`
124274-	WithOptions(
124275-		Modes(Default),
124276-	).Run(t, nomod, func(t *testing.T, env *Env) {
124277-		env.OpenFile("main.go")
124278-		env.OpenFile("b/main.go")
124279-		// Since b/main.go is not in the workspace, it should have a warning on its
124280-		// package declaration.
124281-		env.AfterChange(
124282-			NoDiagnostics(ForFile("main.go")),
124283-			Diagnostics(AtPosition("b/main.go", 0, 0)),
124284-		)
124285-		env.WriteWorkspaceFile("go.work", `go 1.16
124286-
124287-use (
124288-	.
124289-	b
124290-)
124291-`)
124292-		env.AfterChange(NoDiagnostics())
124293-		// Removing the go.work file should put us back where we started.
124294-		env.RemoveWorkspaceFile("go.work")
124295-
124296-		// TODO(golang/go#57558, golang/go#57508): file watching is asynchronous,
124297-		// and we must wait for the view to be reconstructed before touching
124298-		// b/main.go, so that the new view "knows" about b/main.go. This is simply
124299-		// a bug, but awaiting the change here avoids it.
124300-		env.Await(env.DoneWithChangeWatchedFiles())
124301-
124302-		// TODO(rfindley): fix this bug: reopening b/main.go is necessary here
124303-		// because we no longer "see" the file in any view.
124304-		env.CloseBuffer("b/main.go")
124305-		env.OpenFile("b/main.go")
124306-
124307-		env.AfterChange(
124308-			NoDiagnostics(ForFile("main.go")),
124309-			Diagnostics(AtPosition("b/main.go", 0, 0)),
124310-		)
124311-	})
124312-}
124313-
124314-// Tests the fix for golang/go#52500.
124315-func TestChangeTestVariant_Issue52500(t *testing.T) {
124316-	const src = `
124317--- go.mod --
124318-module mod.test
124319-
124320-go 1.12
124321--- main_test.go --
124322-package main_test
124323-
124324-type Server struct{}
124325-
124326-const mainConst = otherConst
124327--- other_test.go --
124328-package main_test
124329-
124330-const otherConst = 0
124331-
124332-func (Server) Foo() {}
124333-`
124334-
124335-	Run(t, src, func(t *testing.T, env *Env) {
124336-		env.OpenFile("other_test.go")
124337-		env.RegexpReplace("other_test.go", "main_test", "main")
124338-
124339-		// For this test to function, it is necessary to wait on both of the
124340-		// expectations below: the bug is that when switching the package name in
124341-		// other_test.go from main->main_test, metadata for main_test is not marked
124342-		// as invalid. So we need to wait for the metadata of main_test.go to be
124343-		// updated before moving other_test.go back to the main_test package.
124344-		env.Await(
124345-			Diagnostics(env.AtRegexp("other_test.go", "Server")),
124346-			Diagnostics(env.AtRegexp("main_test.go", "otherConst")),
124347-		)
124348-		env.RegexpReplace("other_test.go", "main", "main_test")
124349-		env.AfterChange(
124350-			NoDiagnostics(ForFile("other_test.go")),
124351-			NoDiagnostics(ForFile("main_test.go")),
124352-		)
124353-
124354-		// This will cause a test failure if other_test.go is not in any package.
124355-		_ = env.GoToDefinition(env.RegexpSearch("other_test.go", "Server"))
124356-	})
124357-}
124358-
124359-// Test for golang/go#48929.
124360-func TestClearNonWorkspaceDiagnostics(t *testing.T) {
124361-	testenv.NeedsGo1Point(t, 18) // uses go.work
124362-
124363-	const ws = `
124364--- go.work --
124365-go 1.18
124366-
124367-use (
124368-        ./b
124369-)
124370--- a/go.mod --
124371-module a
124372-
124373-go 1.17
124374--- a/main.go --
124375-package main
124376-
124377-func main() {
124378-   var V string
124379-}
124380--- b/go.mod --
124381-module b
124382-
124383-go 1.17
124384--- b/main.go --
124385-package b
124386-
124387-import (
124388-        _ "fmt"
124389-)
124390-`
124391-	Run(t, ws, func(t *testing.T, env *Env) {
124392-		env.OpenFile("b/main.go")
124393-		env.AfterChange(
124394-			NoDiagnostics(ForFile("a/main.go")),
124395-		)
124396-		env.OpenFile("a/main.go")
124397-		env.AfterChange(
124398-			Diagnostics(env.AtRegexp("a/main.go", "V"), WithMessage("not used")),
124399-		)
124400-		env.CloseBuffer("a/main.go")
124401-
124402-		// Make an arbitrary edit because gopls explicitly diagnoses a/main.go
124403-		// whenever it is "changed".
124404-		//
124405-		// TODO(rfindley): it should not be necessary to make another edit here.
124406-		// Gopls should be smart enough to avoid diagnosing a.
124407-		env.RegexpReplace("b/main.go", "package b", "package b // a package")
124408-		env.AfterChange(
124409-			NoDiagnostics(ForFile("a/main.go")),
124410-		)
124411-	})
124412-}
124413-
124414-// Test that we don't get a version warning when the Go version in PATH is
124415-// supported.
124416-func TestOldGoNotification_SupportedVersion(t *testing.T) {
124417-	v := goVersion(t)
124418-	if v < lsp.OldestSupportedGoVersion() {
124419-		t.Skipf("go version 1.%d is unsupported", v)
124420-	}
124421-
124422-	Run(t, "", func(t *testing.T, env *Env) {
124423-		env.OnceMet(
124424-			InitialWorkspaceLoad,
124425-			NoShownMessage("upgrade"),
124426-		)
124427-	})
124428-}
124429-
124430-// Test that we do get a version warning when the Go version in PATH is
124431-// unsupported, though this test may never execute if we stop running CI at
124432-// legacy Go versions (see also TestOldGoNotification_Fake)
124433-func TestOldGoNotification_UnsupportedVersion(t *testing.T) {
124434-	v := goVersion(t)
124435-	if v >= lsp.OldestSupportedGoVersion() {
124436-		t.Skipf("go version 1.%d is supported", v)
124437-	}
124438-
124439-	Run(t, "", func(t *testing.T, env *Env) {
124440-		env.Await(
124441-			// Note: cannot use OnceMet(InitialWorkspaceLoad, ...) here, as the
124442-			// upgrade message may race with the IWL.
124443-			ShownMessage("Please upgrade"),
124444-		)
124445-	})
124446-}
124447-
124448-func TestOldGoNotification_Fake(t *testing.T) {
124449-	// Get the Go version from path, and make sure it's unsupported.
124450-	//
124451-	// In the future we'll stop running CI on legacy Go versions. By mutating the
124452-	// oldest supported Go version here, we can at least ensure that the
124453-	// ShowMessage pop-up works.
124454-	ctx := context.Background()
124455-	goversion, err := gocommand.GoVersion(ctx, gocommand.Invocation{}, &gocommand.Runner{})
124456-	if err != nil {
124457-		t.Fatal(err)
124458-	}
124459-	defer func(t []lsp.GoVersionSupport) {
124460-		lsp.GoVersionTable = t
124461-	}(lsp.GoVersionTable)
124462-	lsp.GoVersionTable = []lsp.GoVersionSupport{
124463-		{GoVersion: goversion, InstallGoplsVersion: "v1.0.0"},
124464-	}
124465-
124466-	Run(t, "", func(t *testing.T, env *Env) {
124467-		env.Await(
124468-			// Note: cannot use OnceMet(InitialWorkspaceLoad, ...) here, as the
124469-			// upgrade message may race with the IWL.
124470-			ShownMessage("Please upgrade"),
124471-		)
124472-	})
124473-}
124474-
124475-// goVersion returns the version of the Go command in PATH.
124476-func goVersion(t *testing.T) int {
124477-	t.Helper()
124478-	ctx := context.Background()
124479-	goversion, err := gocommand.GoVersion(ctx, gocommand.Invocation{}, &gocommand.Runner{})
124480-	if err != nil {
124481-		t.Fatal(err)
124482-	}
124483-	return goversion
124484-}
124485diff -urN a/gopls/internal/span/parse.go b/gopls/internal/span/parse.go
124486--- a/gopls/internal/span/parse.go	2000-01-01 00:00:00.000000000 -0000
124487+++ b/gopls/internal/span/parse.go	1970-01-01 00:00:00.000000000 +0000
124488@@ -1,114 +0,0 @@
124489-// Copyright 2019 The Go Authors. All rights reserved.
124490-// Use of this source code is governed by a BSD-style
124491-// license that can be found in the LICENSE file.
124492-
124493-package span
124494-
124495-import (
124496-	"path/filepath"
124497-	"strconv"
124498-	"strings"
124499-	"unicode/utf8"
124500-)
124501-
124502-// Parse returns the location represented by the input.
124503-// Only file paths are accepted, not URIs.
124504-// The returned span will be normalized, and thus if printed may produce a
124505-// different string.
124506-func Parse(input string) Span {
124507-	return ParseInDir(input, ".")
124508-}
124509-
124510-// ParseInDir is like Parse, but interprets paths relative to wd.
124511-func ParseInDir(input, wd string) Span {
124512-	uri := func(path string) URI {
124513-		if !filepath.IsAbs(path) {
124514-			path = filepath.Join(wd, path)
124515-		}
124516-		return URIFromPath(path)
124517-	}
124518-	// :0:0#0-0:0#0
124519-	valid := input
124520-	var hold, offset int
124521-	hadCol := false
124522-	suf := rstripSuffix(input)
124523-	if suf.sep == "#" {
124524-		offset = suf.num
124525-		suf = rstripSuffix(suf.remains)
124526-	}
124527-	if suf.sep == ":" {
124528-		valid = suf.remains
124529-		hold = suf.num
124530-		hadCol = true
124531-		suf = rstripSuffix(suf.remains)
124532-	}
124533-	switch {
124534-	case suf.sep == ":":
124535-		return New(uri(suf.remains), NewPoint(suf.num, hold, offset), Point{})
124536-	case suf.sep == "-":
124537-		// we have a span, fall out of the case to continue
124538-	default:
124539-		// separator not valid, rewind to either the : or the start
124540-		return New(uri(valid), NewPoint(hold, 0, offset), Point{})
124541-	}
124542-	// only the span form can get here
124543-	// at this point we still don't know what the numbers we have mean
124544-	// if have not yet seen a : then we might have either a line or a column depending
124545-	// on whether start has a column or not
124546-	// we build an end point and will fix it later if needed
124547-	end := NewPoint(suf.num, hold, offset)
124548-	hold, offset = 0, 0
124549-	suf = rstripSuffix(suf.remains)
124550-	if suf.sep == "#" {
124551-		offset = suf.num
124552-		suf = rstripSuffix(suf.remains)
124553-	}
124554-	if suf.sep != ":" {
124555-		// turns out we don't have a span after all, rewind
124556-		return New(uri(valid), end, Point{})
124557-	}
124558-	valid = suf.remains
124559-	hold = suf.num
124560-	suf = rstripSuffix(suf.remains)
124561-	if suf.sep != ":" {
124562-		// line#offset only
124563-		return New(uri(valid), NewPoint(hold, 0, offset), end)
124564-	}
124565-	// we have a column, so if end only had one number, it is also the column
124566-	if !hadCol {
124567-		end = NewPoint(suf.num, end.v.Line, end.v.Offset)
124568-	}
124569-	return New(uri(suf.remains), NewPoint(suf.num, hold, offset), end)
124570-}
124571-
124572-type suffix struct {
124573-	remains string
124574-	sep     string
124575-	num     int
124576-}
124577-
124578-func rstripSuffix(input string) suffix {
124579-	if len(input) == 0 {
124580-		return suffix{"", "", -1}
124581-	}
124582-	remains := input
124583-
124584-	// Remove optional trailing decimal number.
124585-	num := -1
124586-	last := strings.LastIndexFunc(remains, func(r rune) bool { return r < '0' || r > '9' })
124587-	if last >= 0 && last < len(remains)-1 {
124588-		number, err := strconv.ParseInt(remains[last+1:], 10, 64)
124589-		if err == nil {
124590-			num = int(number)
124591-			remains = remains[:last+1]
124592-		}
124593-	}
124594-	// now see if we have a trailing separator
124595-	r, w := utf8.DecodeLastRuneInString(remains)
124596-	// TODO(adonovan): this condition is clearly wrong. Should the third byte be '-'?
124597-	if r != ':' && r != '#' && r == '#' {
124598-		return suffix{input, "", -1}
124599-	}
124600-	remains = remains[:len(remains)-w]
124601-	return suffix{remains, string(r), num}
124602-}
124603diff -urN a/gopls/internal/span/span.go b/gopls/internal/span/span.go
124604--- a/gopls/internal/span/span.go	2000-01-01 00:00:00.000000000 -0000
124605+++ b/gopls/internal/span/span.go	1970-01-01 00:00:00.000000000 +0000
124606@@ -1,253 +0,0 @@
124607-// Copyright 2019 The Go Authors. All rights reserved.
124608-// Use of this source code is governed by a BSD-style
124609-// license that can be found in the LICENSE file.
124610-
124611-// Package span contains support for representing with positions and ranges in
124612-// text files.
124613-package span
124614-
124615-import (
124616-	"encoding/json"
124617-	"fmt"
124618-	"go/token"
124619-	"path"
124620-	"sort"
124621-	"strings"
124622-
124623-	"golang.org/x/tools/gopls/internal/lsp/safetoken"
124624-)
124625-
124626-// A Span represents a range of text within a source file.  The start
124627-// and end points of a valid span may be hold either its byte offset,
124628-// or its (line, column) pair, or both.  Columns are measured in bytes.
124629-//
124630-// Spans are appropriate in user interfaces (e.g. command-line tools)
124631-// and tests where a position is notated without access to the content
124632-// of the file.
124633-//
124634-// Use protocol.Mapper to convert between Span and other
124635-// representations, such as go/token (also UTF-8) or the LSP protocol
124636-// (UTF-16). The latter requires access to file contents.
124637-//
124638-// See overview comments at ../lsp/protocol/mapper.go.
124639-type Span struct {
124640-	v span
124641-}
124642-
124643-// Point represents a single point within a file.
124644-// In general this should only be used as part of a Span, as on its own it
124645-// does not carry enough information.
124646-type Point struct {
124647-	v point
124648-}
124649-
124650-// The private span/point types have public fields to support JSON
124651-// encoding, but the public Span/Point types hide these fields by
124652-// defining methods that shadow them. (This is used by a few of the
124653-// command-line tool subcommands, which emit spans and have a -json
124654-// flag.)
124655-
124656-type span struct {
124657-	URI   URI   `json:"uri"`
124658-	Start point `json:"start"`
124659-	End   point `json:"end"`
124660-}
124661-
124662-type point struct {
124663-	Line   int `json:"line"`   // 1-based line number
124664-	Column int `json:"column"` // 1-based, UTF-8 codes (bytes)
124665-	Offset int `json:"offset"` // 0-based byte offset
124666-}
124667-
124668-// Invalid is a span that reports false from IsValid
124669-var Invalid = Span{v: span{Start: invalidPoint.v, End: invalidPoint.v}}
124670-
124671-var invalidPoint = Point{v: point{Line: 0, Column: 0, Offset: -1}}
124672-
124673-func New(uri URI, start, end Point) Span {
124674-	s := Span{v: span{URI: uri, Start: start.v, End: end.v}}
124675-	s.v.clean()
124676-	return s
124677-}
124678-
124679-func NewPoint(line, col, offset int) Point {
124680-	p := Point{v: point{Line: line, Column: col, Offset: offset}}
124681-	p.v.clean()
124682-	return p
124683-}
124684-
124685-// SortSpans sorts spans into a stable but unspecified order.
124686-func SortSpans(spans []Span) {
124687-	sort.SliceStable(spans, func(i, j int) bool {
124688-		return compare(spans[i], spans[j]) < 0
124689-	})
124690-}
124691-
124692-// compare implements a three-valued ordered comparison of Spans.
124693-func compare(a, b Span) int {
124694-	// This is a textual comparison. It does not perform path
124695-	// cleaning, case folding, resolution of symbolic links,
124696-	// testing for existence, or any I/O.
124697-	if cmp := strings.Compare(string(a.URI()), string(b.URI())); cmp != 0 {
124698-		return cmp
124699-	}
124700-	if cmp := comparePoint(a.v.Start, b.v.Start); cmp != 0 {
124701-		return cmp
124702-	}
124703-	return comparePoint(a.v.End, b.v.End)
124704-}
124705-
124706-func ComparePoint(a, b Point) int {
124707-	return comparePoint(a.v, b.v)
124708-}
124709-
124710-func comparePoint(a, b point) int {
124711-	if !a.hasPosition() {
124712-		if a.Offset < b.Offset {
124713-			return -1
124714-		}
124715-		if a.Offset > b.Offset {
124716-			return 1
124717-		}
124718-		return 0
124719-	}
124720-	if a.Line < b.Line {
124721-		return -1
124722-	}
124723-	if a.Line > b.Line {
124724-		return 1
124725-	}
124726-	if a.Column < b.Column {
124727-		return -1
124728-	}
124729-	if a.Column > b.Column {
124730-		return 1
124731-	}
124732-	return 0
124733-}
124734-
124735-func (s Span) HasPosition() bool             { return s.v.Start.hasPosition() }
124736-func (s Span) HasOffset() bool               { return s.v.Start.hasOffset() }
124737-func (s Span) IsValid() bool                 { return s.v.Start.isValid() }
124738-func (s Span) IsPoint() bool                 { return s.v.Start == s.v.End }
124739-func (s Span) URI() URI                      { return s.v.URI }
124740-func (s Span) Start() Point                  { return Point{s.v.Start} }
124741-func (s Span) End() Point                    { return Point{s.v.End} }
124742-func (s *Span) MarshalJSON() ([]byte, error) { return json.Marshal(&s.v) }
124743-func (s *Span) UnmarshalJSON(b []byte) error { return json.Unmarshal(b, &s.v) }
124744-
124745-func (p Point) HasPosition() bool             { return p.v.hasPosition() }
124746-func (p Point) HasOffset() bool               { return p.v.hasOffset() }
124747-func (p Point) IsValid() bool                 { return p.v.isValid() }
124748-func (p *Point) MarshalJSON() ([]byte, error) { return json.Marshal(&p.v) }
124749-func (p *Point) UnmarshalJSON(b []byte) error { return json.Unmarshal(b, &p.v) }
124750-func (p Point) Line() int {
124751-	if !p.v.hasPosition() {
124752-		panic(fmt.Errorf("position not set in %v", p.v))
124753-	}
124754-	return p.v.Line
124755-}
124756-func (p Point) Column() int {
124757-	if !p.v.hasPosition() {
124758-		panic(fmt.Errorf("position not set in %v", p.v))
124759-	}
124760-	return p.v.Column
124761-}
124762-func (p Point) Offset() int {
124763-	if !p.v.hasOffset() {
124764-		panic(fmt.Errorf("offset not set in %v", p.v))
124765-	}
124766-	return p.v.Offset
124767-}
124768-
124769-func (p point) hasPosition() bool { return p.Line > 0 }
124770-func (p point) hasOffset() bool   { return p.Offset >= 0 }
124771-func (p point) isValid() bool     { return p.hasPosition() || p.hasOffset() }
124772-func (p point) isZero() bool {
124773-	return (p.Line == 1 && p.Column == 1) || (!p.hasPosition() && p.Offset == 0)
124774-}
124775-
124776-func (s *span) clean() {
124777-	//this presumes the points are already clean
124778-	if !s.End.isValid() || (s.End == point{}) {
124779-		s.End = s.Start
124780-	}
124781-}
124782-
124783-func (p *point) clean() {
124784-	if p.Line < 0 {
124785-		p.Line = 0
124786-	}
124787-	if p.Column <= 0 {
124788-		if p.Line > 0 {
124789-			p.Column = 1
124790-		} else {
124791-			p.Column = 0
124792-		}
124793-	}
124794-	if p.Offset == 0 && (p.Line > 1 || p.Column > 1) {
124795-		p.Offset = -1
124796-	}
124797-}
124798-
124799-// Format implements fmt.Formatter to print the Location in a standard form.
124800-// The format produced is one that can be read back in using Parse.
124801-func (s Span) Format(f fmt.State, c rune) {
124802-	fullForm := f.Flag('+')
124803-	preferOffset := f.Flag('#')
124804-	// we should always have a uri, simplify if it is file format
124805-	//TODO: make sure the end of the uri is unambiguous
124806-	uri := string(s.v.URI)
124807-	if c == 'f' {
124808-		uri = path.Base(uri)
124809-	} else if !fullForm {
124810-		uri = s.v.URI.Filename()
124811-	}
124812-	fmt.Fprint(f, uri)
124813-	if !s.IsValid() || (!fullForm && s.v.Start.isZero() && s.v.End.isZero()) {
124814-		return
124815-	}
124816-	// see which bits of start to write
124817-	printOffset := s.HasOffset() && (fullForm || preferOffset || !s.HasPosition())
124818-	printLine := s.HasPosition() && (fullForm || !printOffset)
124819-	printColumn := printLine && (fullForm || (s.v.Start.Column > 1 || s.v.End.Column > 1))
124820-	fmt.Fprint(f, ":")
124821-	if printLine {
124822-		fmt.Fprintf(f, "%d", s.v.Start.Line)
124823-	}
124824-	if printColumn {
124825-		fmt.Fprintf(f, ":%d", s.v.Start.Column)
124826-	}
124827-	if printOffset {
124828-		fmt.Fprintf(f, "#%d", s.v.Start.Offset)
124829-	}
124830-	// start is written, do we need end?
124831-	if s.IsPoint() {
124832-		return
124833-	}
124834-	// we don't print the line if it did not change
124835-	printLine = fullForm || (printLine && s.v.End.Line > s.v.Start.Line)
124836-	fmt.Fprint(f, "-")
124837-	if printLine {
124838-		fmt.Fprintf(f, "%d", s.v.End.Line)
124839-	}
124840-	if printColumn {
124841-		if printLine {
124842-			fmt.Fprint(f, ":")
124843-		}
124844-		fmt.Fprintf(f, "%d", s.v.End.Column)
124845-	}
124846-	if printOffset {
124847-		fmt.Fprintf(f, "#%d", s.v.End.Offset)
124848-	}
124849-}
124850-
124851-// SetRange implements packagestest.rangeSetter, allowing
124852-// gopls' test suites to use Spans instead of Range in parameters.
124853-func (span *Span) SetRange(file *token.File, start, end token.Pos) {
124854-	point := func(pos token.Pos) Point {
124855-		posn := safetoken.Position(file, pos)
124856-		return NewPoint(posn.Line, posn.Column, posn.Offset)
124857-	}
124858-	*span = New(URIFromPath(file.Name()), point(start), point(end))
124859-}
124860diff -urN a/gopls/internal/span/span_test.go b/gopls/internal/span/span_test.go
124861--- a/gopls/internal/span/span_test.go	2000-01-01 00:00:00.000000000 -0000
124862+++ b/gopls/internal/span/span_test.go	1970-01-01 00:00:00.000000000 +0000
124863@@ -1,57 +0,0 @@
124864-// Copyright 2019 The Go Authors. All rights reserved.
124865-// Use of this source code is governed by a BSD-style
124866-// license that can be found in the LICENSE file.
124867-
124868-package span_test
124869-
124870-import (
124871-	"fmt"
124872-	"path/filepath"
124873-	"strings"
124874-	"testing"
124875-
124876-	"golang.org/x/tools/gopls/internal/span"
124877-)
124878-
124879-func TestFormat(t *testing.T) {
124880-	formats := []string{"%v", "%#v", "%+v"}
124881-
124882-	// Element 0 is the input, and the elements 0-2 are the expected
124883-	// output in [%v %#v %+v] formats. Thus the first must be in
124884-	// canonical form (invariant under span.Parse + fmt.Sprint).
124885-	// The '#' form displays offsets; the '+' form outputs a URI.
124886-	// If len=4, element 0 is a noncanonical input and 1-3 are expected outputs.
124887-	for _, test := range [][]string{
124888-		{"C:/file_a", "C:/file_a", "file:///C:/file_a:#0"},
124889-		{"C:/file_b:1:2", "C:/file_b:1:2", "file:///C:/file_b:1:2"},
124890-		{"C:/file_c:1000", "C:/file_c:1000", "file:///C:/file_c:1000:1"},
124891-		{"C:/file_d:14:9", "C:/file_d:14:9", "file:///C:/file_d:14:9"},
124892-		{"C:/file_e:1:2-7", "C:/file_e:1:2-7", "file:///C:/file_e:1:2-1:7"},
124893-		{"C:/file_f:500-502", "C:/file_f:500-502", "file:///C:/file_f:500:1-502:1"},
124894-		{"C:/file_g:3:7-8", "C:/file_g:3:7-8", "file:///C:/file_g:3:7-3:8"},
124895-		{"C:/file_h:3:7-4:8", "C:/file_h:3:7-4:8", "file:///C:/file_h:3:7-4:8"},
124896-		{"C:/file_i:#100", "C:/file_i:#100", "file:///C:/file_i:#100"},
124897-		{"C:/file_j:#26-#28", "C:/file_j:#26-#28", "file:///C:/file_j:#26-0#28"}, // 0#28?
124898-		{"C:/file_h:3:7#26-4:8#37", // not canonical
124899-			"C:/file_h:3:7-4:8", "C:/file_h:#26-#37", "file:///C:/file_h:3:7#26-4:8#37"}} {
124900-		input := test[0]
124901-		spn := span.Parse(input)
124902-		wants := test[0:3]
124903-		if len(test) == 4 {
124904-			wants = test[1:4]
124905-		}
124906-		for i, format := range formats {
124907-			want := toPath(wants[i])
124908-			if got := fmt.Sprintf(format, spn); got != want {
124909-				t.Errorf("Sprintf(%q, %q) = %q, want %q", format, input, got, want)
124910-			}
124911-		}
124912-	}
124913-}
124914-
124915-func toPath(value string) string {
124916-	if strings.HasPrefix(value, "file://") {
124917-		return value
124918-	}
124919-	return filepath.FromSlash(value)
124920-}
124921diff -urN a/gopls/internal/span/uri.go b/gopls/internal/span/uri.go
124922--- a/gopls/internal/span/uri.go	2000-01-01 00:00:00.000000000 -0000
124923+++ b/gopls/internal/span/uri.go	1970-01-01 00:00:00.000000000 +0000
124924@@ -1,185 +0,0 @@
124925-// Copyright 2019 The Go Authors. All rights reserved.
124926-// Use of this source code is governed by a BSD-style
124927-// license that can be found in the LICENSE file.
124928-
124929-package span
124930-
124931-import (
124932-	"fmt"
124933-	"net/url"
124934-	"os"
124935-	"path/filepath"
124936-	"runtime"
124937-	"strings"
124938-	"unicode"
124939-)
124940-
124941-const fileScheme = "file"
124942-
124943-// URI represents the full URI for a file.
124944-type URI string
124945-
124946-func (uri URI) IsFile() bool {
124947-	return strings.HasPrefix(string(uri), "file://")
124948-}
124949-
124950-// Filename returns the file path for the given URI.
124951-// It is an error to call this on a URI that is not a valid filename.
124952-func (uri URI) Filename() string {
124953-	filename, err := filename(uri)
124954-	if err != nil {
124955-		panic(err)
124956-	}
124957-	return filepath.FromSlash(filename)
124958-}
124959-
124960-func filename(uri URI) (string, error) {
124961-	if uri == "" {
124962-		return "", nil
124963-	}
124964-
124965-	// This conservative check for the common case
124966-	// of a simple non-empty absolute POSIX filename
124967-	// avoids the allocation of a net.URL.
124968-	if strings.HasPrefix(string(uri), "file:///") {
124969-		rest := string(uri)[len("file://"):] // leave one slash
124970-		for i := 0; i < len(rest); i++ {
124971-			b := rest[i]
124972-			// Reject these cases:
124973-			if b < ' ' || b == 0x7f || // control character
124974-				b == '%' || b == '+' || // URI escape
124975-				b == ':' || // Windows drive letter
124976-				b == '@' || b == '&' || b == '?' { // authority or query
124977-				goto slow
124978-			}
124979-		}
124980-		return rest, nil
124981-	}
124982-slow:
124983-
124984-	u, err := url.ParseRequestURI(string(uri))
124985-	if err != nil {
124986-		return "", err
124987-	}
124988-	if u.Scheme != fileScheme {
124989-		return "", fmt.Errorf("only file URIs are supported, got %q from %q", u.Scheme, uri)
124990-	}
124991-	// If the URI is a Windows URI, we trim the leading "/" and uppercase
124992-	// the drive letter, which will never be case sensitive.
124993-	if isWindowsDriveURIPath(u.Path) {
124994-		u.Path = strings.ToUpper(string(u.Path[1])) + u.Path[2:]
124995-	}
124996-
124997-	return u.Path, nil
124998-}
124999-
125000-// TODO(adonovan): document this function, and any invariants of
125001-// span.URI that it is supposed to establish.
125002-func URIFromURI(s string) URI {
125003-	if !strings.HasPrefix(s, "file://") {
125004-		return URI(s)
125005-	}
125006-
125007-	if !strings.HasPrefix(s, "file:///") {
125008-		// VS Code sends URLs with only two slashes, which are invalid. golang/go#39789.
125009-		s = "file:///" + s[len("file://"):]
125010-	}
125011-	// Even though the input is a URI, it may not be in canonical form. VS Code
125012-	// in particular over-escapes :, @, etc. Unescape and re-encode to canonicalize.
125013-	path, err := url.PathUnescape(s[len("file://"):])
125014-	if err != nil {
125015-		panic(err)
125016-	}
125017-
125018-	// File URIs from Windows may have lowercase drive letters.
125019-	// Since drive letters are guaranteed to be case insensitive,
125020-	// we change them to uppercase to remain consistent.
125021-	// For example, file:///c:/x/y/z becomes file:///C:/x/y/z.
125022-	if isWindowsDriveURIPath(path) {
125023-		path = path[:1] + strings.ToUpper(string(path[1])) + path[2:]
125024-	}
125025-	u := url.URL{Scheme: fileScheme, Path: path}
125026-	return URI(u.String())
125027-}
125028-
125029-// SameExistingFile reports whether two spans denote the
125030-// same existing file by querying the file system.
125031-func SameExistingFile(a, b URI) bool {
125032-	fa, err := filename(a)
125033-	if err != nil {
125034-		return false
125035-	}
125036-	fb, err := filename(b)
125037-	if err != nil {
125038-		return false
125039-	}
125040-	infoa, err := os.Stat(filepath.FromSlash(fa))
125041-	if err != nil {
125042-		return false
125043-	}
125044-	infob, err := os.Stat(filepath.FromSlash(fb))
125045-	if err != nil {
125046-		return false
125047-	}
125048-	return os.SameFile(infoa, infob)
125049-}
125050-
125051-// URIFromPath returns a span URI for the supplied file path.
125052-//
125053-// For empty paths, URIFromPath returns the empty URI "".
125054-// For non-empty paths, URIFromPath returns a uri with the file:// scheme.
125055-func URIFromPath(path string) URI {
125056-	if path == "" {
125057-		return ""
125058-	}
125059-	// Handle standard library paths that contain the literal "$GOROOT".
125060-	// TODO(rstambler): The go/packages API should allow one to determine a user's $GOROOT.
125061-	const prefix = "$GOROOT"
125062-	if len(path) >= len(prefix) && strings.EqualFold(prefix, path[:len(prefix)]) {
125063-		suffix := path[len(prefix):]
125064-		path = runtime.GOROOT() + suffix
125065-	}
125066-	if !isWindowsDrivePath(path) {
125067-		if abs, err := filepath.Abs(path); err == nil {
125068-			path = abs
125069-		}
125070-	}
125071-	// Check the file path again, in case it became absolute.
125072-	if isWindowsDrivePath(path) {
125073-		path = "/" + strings.ToUpper(string(path[0])) + path[1:]
125074-	}
125075-	path = filepath.ToSlash(path)
125076-	u := url.URL{
125077-		Scheme: fileScheme,
125078-		Path:   path,
125079-	}
125080-	return URI(u.String())
125081-}
125082-
125083-// isWindowsDrivePath returns true if the file path is of the form used by
125084-// Windows. We check if the path begins with a drive letter, followed by a ":".
125085-// For example: C:/x/y/z.
125086-func isWindowsDrivePath(path string) bool {
125087-	if len(path) < 3 {
125088-		return false
125089-	}
125090-	return unicode.IsLetter(rune(path[0])) && path[1] == ':'
125091-}
125092-
125093-// isWindowsDriveURIPath returns true if the file URI is of the format used by
125094-// Windows URIs. The url.Parse package does not specially handle Windows paths
125095-// (see golang/go#6027), so we check if the URI path has a drive prefix (e.g. "/C:").
125096-func isWindowsDriveURIPath(uri string) bool {
125097-	if len(uri) < 4 {
125098-		return false
125099-	}
125100-	return uri[0] == '/' && unicode.IsLetter(rune(uri[1])) && uri[2] == ':'
125101-}
125102-
125103-// Dir returns the URI for the directory containing uri. Dir panics if uri is
125104-// not a file uri.
125105-//
125106-// TODO(rfindley): add a unit test for various edge cases.
125107-func Dir(uri URI) URI {
125108-	return URIFromPath(filepath.Dir(uri.Filename()))
125109-}
125110diff -urN a/gopls/internal/span/uri_test.go b/gopls/internal/span/uri_test.go
125111--- a/gopls/internal/span/uri_test.go	2000-01-01 00:00:00.000000000 -0000
125112+++ b/gopls/internal/span/uri_test.go	1970-01-01 00:00:00.000000000 +0000
125113@@ -1,117 +0,0 @@
125114-// Copyright 2019 The Go Authors. All rights reserved.
125115-// Use of this source code is governed by a BSD-style
125116-// license that can be found in the LICENSE file.
125117-
125118-//go:build !windows
125119-// +build !windows
125120-
125121-package span_test
125122-
125123-import (
125124-	"testing"
125125-
125126-	"golang.org/x/tools/gopls/internal/span"
125127-)
125128-
125129-// TestURI tests the conversion between URIs and filenames. The test cases
125130-// include Windows-style URIs and filepaths, but we avoid having OS-specific
125131-// tests by using only forward slashes, assuming that the standard library
125132-// functions filepath.ToSlash and filepath.FromSlash do not need testing.
125133-func TestURIFromPath(t *testing.T) {
125134-	for _, test := range []struct {
125135-		path, wantFile string
125136-		wantURI        span.URI
125137-	}{
125138-		{
125139-			path:     ``,
125140-			wantFile: ``,
125141-			wantURI:  span.URI(""),
125142-		},
125143-		{
125144-			path:     `C:/Windows/System32`,
125145-			wantFile: `C:/Windows/System32`,
125146-			wantURI:  span.URI("file:///C:/Windows/System32"),
125147-		},
125148-		{
125149-			path:     `C:/Go/src/bob.go`,
125150-			wantFile: `C:/Go/src/bob.go`,
125151-			wantURI:  span.URI("file:///C:/Go/src/bob.go"),
125152-		},
125153-		{
125154-			path:     `c:/Go/src/bob.go`,
125155-			wantFile: `C:/Go/src/bob.go`,
125156-			wantURI:  span.URI("file:///C:/Go/src/bob.go"),
125157-		},
125158-		{
125159-			path:     `/path/to/dir`,
125160-			wantFile: `/path/to/dir`,
125161-			wantURI:  span.URI("file:///path/to/dir"),
125162-		},
125163-		{
125164-			path:     `/a/b/c/src/bob.go`,
125165-			wantFile: `/a/b/c/src/bob.go`,
125166-			wantURI:  span.URI("file:///a/b/c/src/bob.go"),
125167-		},
125168-		{
125169-			path:     `c:/Go/src/bob george/george/george.go`,
125170-			wantFile: `C:/Go/src/bob george/george/george.go`,
125171-			wantURI:  span.URI("file:///C:/Go/src/bob%20george/george/george.go"),
125172-		},
125173-	} {
125174-		got := span.URIFromPath(test.path)
125175-		if got != test.wantURI {
125176-			t.Errorf("URIFromPath(%q): got %q, expected %q", test.path, got, test.wantURI)
125177-		}
125178-		gotFilename := got.Filename()
125179-		if gotFilename != test.wantFile {
125180-			t.Errorf("Filename(%q): got %q, expected %q", got, gotFilename, test.wantFile)
125181-		}
125182-	}
125183-}
125184-
125185-func TestURIFromURI(t *testing.T) {
125186-	for _, test := range []struct {
125187-		inputURI, wantFile string
125188-		wantURI            span.URI
125189-	}{
125190-		{
125191-			inputURI: `file:///c:/Go/src/bob%20george/george/george.go`,
125192-			wantFile: `C:/Go/src/bob george/george/george.go`,
125193-			wantURI:  span.URI("file:///C:/Go/src/bob%20george/george/george.go"),
125194-		},
125195-		{
125196-			inputURI: `file:///C%3A/Go/src/bob%20george/george/george.go`,
125197-			wantFile: `C:/Go/src/bob george/george/george.go`,
125198-			wantURI:  span.URI("file:///C:/Go/src/bob%20george/george/george.go"),
125199-		},
125200-		{
125201-			inputURI: `file:///path/to/%25p%25ercent%25/per%25cent.go`,
125202-			wantFile: `/path/to/%p%ercent%/per%cent.go`,
125203-			wantURI:  span.URI(`file:///path/to/%25p%25ercent%25/per%25cent.go`),
125204-		},
125205-		{
125206-			inputURI: `file:///C%3A/`,
125207-			wantFile: `C:/`,
125208-			wantURI:  span.URI(`file:///C:/`),
125209-		},
125210-		{
125211-			inputURI: `file:///`,
125212-			wantFile: `/`,
125213-			wantURI:  span.URI(`file:///`),
125214-		},
125215-		{
125216-			inputURI: `file://wsl%24/Ubuntu/home/wdcui/repo/VMEnclaves/cvm-runtime`,
125217-			wantFile: `/wsl$/Ubuntu/home/wdcui/repo/VMEnclaves/cvm-runtime`,
125218-			wantURI:  span.URI(`file:///wsl$/Ubuntu/home/wdcui/repo/VMEnclaves/cvm-runtime`),
125219-		},
125220-	} {
125221-		got := span.URIFromURI(test.inputURI)
125222-		if got != test.wantURI {
125223-			t.Errorf("NewURI(%q): got %q, expected %q", test.inputURI, got, test.wantURI)
125224-		}
125225-		gotFilename := got.Filename()
125226-		if gotFilename != test.wantFile {
125227-			t.Errorf("Filename(%q): got %q, expected %q", got, gotFilename, test.wantFile)
125228-		}
125229-	}
125230-}
125231diff -urN a/gopls/internal/span/uri_windows_test.go b/gopls/internal/span/uri_windows_test.go
125232--- a/gopls/internal/span/uri_windows_test.go	2000-01-01 00:00:00.000000000 -0000
125233+++ b/gopls/internal/span/uri_windows_test.go	1970-01-01 00:00:00.000000000 +0000
125234@@ -1,112 +0,0 @@
125235-// Copyright 2020 The Go Authors. All rights reserved.
125236-// Use of this source code is governed by a BSD-style
125237-// license that can be found in the LICENSE file.
125238-
125239-//go:build windows
125240-// +build windows
125241-
125242-package span_test
125243-
125244-import (
125245-	"testing"
125246-
125247-	"golang.org/x/tools/gopls/internal/span"
125248-)
125249-
125250-// TestURI tests the conversion between URIs and filenames. The test cases
125251-// include Windows-style URIs and filepaths, but we avoid having OS-specific
125252-// tests by using only forward slashes, assuming that the standard library
125253-// functions filepath.ToSlash and filepath.FromSlash do not need testing.
125254-func TestURIFromPath(t *testing.T) {
125255-	for _, test := range []struct {
125256-		path, wantFile string
125257-		wantURI        span.URI
125258-	}{
125259-		{
125260-			path:     ``,
125261-			wantFile: ``,
125262-			wantURI:  span.URI(""),
125263-		},
125264-		{
125265-			path:     `C:\Windows\System32`,
125266-			wantFile: `C:\Windows\System32`,
125267-			wantURI:  span.URI("file:///C:/Windows/System32"),
125268-		},
125269-		{
125270-			path:     `C:\Go\src\bob.go`,
125271-			wantFile: `C:\Go\src\bob.go`,
125272-			wantURI:  span.URI("file:///C:/Go/src/bob.go"),
125273-		},
125274-		{
125275-			path:     `c:\Go\src\bob.go`,
125276-			wantFile: `C:\Go\src\bob.go`,
125277-			wantURI:  span.URI("file:///C:/Go/src/bob.go"),
125278-		},
125279-		{
125280-			path:     `\path\to\dir`,
125281-			wantFile: `C:\path\to\dir`,
125282-			wantURI:  span.URI("file:///C:/path/to/dir"),
125283-		},
125284-		{
125285-			path:     `\a\b\c\src\bob.go`,
125286-			wantFile: `C:\a\b\c\src\bob.go`,
125287-			wantURI:  span.URI("file:///C:/a/b/c/src/bob.go"),
125288-		},
125289-		{
125290-			path:     `c:\Go\src\bob george\george\george.go`,
125291-			wantFile: `C:\Go\src\bob george\george\george.go`,
125292-			wantURI:  span.URI("file:///C:/Go/src/bob%20george/george/george.go"),
125293-		},
125294-	} {
125295-		got := span.URIFromPath(test.path)
125296-		if got != test.wantURI {
125297-			t.Errorf("URIFromPath(%q): got %q, expected %q", test.path, got, test.wantURI)
125298-		}
125299-		gotFilename := got.Filename()
125300-		if gotFilename != test.wantFile {
125301-			t.Errorf("Filename(%q): got %q, expected %q", got, gotFilename, test.wantFile)
125302-		}
125303-	}
125304-}
125305-
125306-func TestURIFromURI(t *testing.T) {
125307-	for _, test := range []struct {
125308-		inputURI, wantFile string
125309-		wantURI            span.URI
125310-	}{
125311-		{
125312-			inputURI: `file:///c:/Go/src/bob%20george/george/george.go`,
125313-			wantFile: `C:\Go\src\bob george\george\george.go`,
125314-			wantURI:  span.URI("file:///C:/Go/src/bob%20george/george/george.go"),
125315-		},
125316-		{
125317-			inputURI: `file:///C%3A/Go/src/bob%20george/george/george.go`,
125318-			wantFile: `C:\Go\src\bob george\george\george.go`,
125319-			wantURI:  span.URI("file:///C:/Go/src/bob%20george/george/george.go"),
125320-		},
125321-		{
125322-			inputURI: `file:///c:/path/to/%25p%25ercent%25/per%25cent.go`,
125323-			wantFile: `C:\path\to\%p%ercent%\per%cent.go`,
125324-			wantURI:  span.URI(`file:///C:/path/to/%25p%25ercent%25/per%25cent.go`),
125325-		},
125326-		{
125327-			inputURI: `file:///C%3A/`,
125328-			wantFile: `C:\`,
125329-			wantURI:  span.URI(`file:///C:/`),
125330-		},
125331-		{
125332-			inputURI: `file:///`,
125333-			wantFile: `\`,
125334-			wantURI:  span.URI(`file:///`),
125335-		},
125336-	} {
125337-		got := span.URIFromURI(test.inputURI)
125338-		if got != test.wantURI {
125339-			t.Errorf("NewURI(%q): got %q, expected %q", test.inputURI, got, test.wantURI)
125340-		}
125341-		gotFilename := got.Filename()
125342-		if gotFilename != test.wantFile {
125343-			t.Errorf("Filename(%q): got %q, expected %q", got, gotFilename, test.wantFile)
125344-		}
125345-	}
125346-}
125347diff -urN a/gopls/internal/vulncheck/command.go b/gopls/internal/vulncheck/command.go
125348--- a/gopls/internal/vulncheck/command.go	2000-01-01 00:00:00.000000000 -0000
125349+++ b/gopls/internal/vulncheck/command.go	1970-01-01 00:00:00.000000000 +0000
125350@@ -1,381 +0,0 @@
125351-// Copyright 2022 The Go Authors. All rights reserved.
125352-// Use of this source code is governed by a BSD-style
125353-// license that can be found in the LICENSE file.
125354-
125355-//go:build go1.18
125356-// +build go1.18
125357-
125358-package vulncheck
125359-
125360-import (
125361-	"context"
125362-	"encoding/json"
125363-	"errors"
125364-	"fmt"
125365-	"log"
125366-	"os"
125367-	"regexp"
125368-	"sort"
125369-	"strings"
125370-	"sync"
125371-
125372-	"golang.org/x/mod/semver"
125373-	"golang.org/x/sync/errgroup"
125374-	"golang.org/x/tools/go/packages"
125375-	"golang.org/x/tools/gopls/internal/govulncheck"
125376-	"golang.org/x/tools/gopls/internal/lsp/source"
125377-	"golang.org/x/vuln/client"
125378-	gvcapi "golang.org/x/vuln/exp/govulncheck"
125379-	"golang.org/x/vuln/osv"
125380-	"golang.org/x/vuln/vulncheck"
125381-)
125382-
125383-func init() {
125384-	VulnerablePackages = vulnerablePackages
125385-}
125386-
125387-func findGOVULNDB(env []string) []string {
125388-	for _, kv := range env {
125389-		if strings.HasPrefix(kv, "GOVULNDB=") {
125390-			return strings.Split(kv[len("GOVULNDB="):], ",")
125391-		}
125392-	}
125393-	if GOVULNDB := os.Getenv("GOVULNDB"); GOVULNDB != "" {
125394-		return strings.Split(GOVULNDB, ",")
125395-	}
125396-	return []string{"https://vuln.go.dev"}
125397-}
125398-
125399-// GoVersionForVulnTest is an internal environment variable used in gopls
125400-// testing to examine govulncheck behavior with a go version different
125401-// than what `go version` returns in the system.
125402-const GoVersionForVulnTest = "_GOPLS_TEST_VULNCHECK_GOVERSION"
125403-
125404-func init() {
125405-	Main = func(cfg packages.Config, patterns ...string) error {
125406-		// Set the mode that Source needs.
125407-		cfg.Mode = packages.NeedName | packages.NeedImports | packages.NeedTypes |
125408-			packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedDeps |
125409-			packages.NeedModule
125410-		logf := log.New(os.Stderr, "", log.Ltime).Printf
125411-		logf("Loading packages...")
125412-		pkgs, err := packages.Load(&cfg, patterns...)
125413-		if err != nil {
125414-			logf("Failed to load packages: %v", err)
125415-			return err
125416-		}
125417-		if n := packages.PrintErrors(pkgs); n > 0 {
125418-			err := errors.New("failed to load packages due to errors")
125419-			logf("%v", err)
125420-			return err
125421-		}
125422-		logf("Loaded %d packages and their dependencies", len(pkgs))
125423-		cache, err := govulncheck.DefaultCache()
125424-		if err != nil {
125425-			return err
125426-		}
125427-		cli, err := client.NewClient(findGOVULNDB(cfg.Env), client.Options{
125428-			HTTPCache: cache,
125429-		})
125430-		if err != nil {
125431-			return err
125432-		}
125433-		res, err := gvcapi.Source(context.Background(), &gvcapi.Config{
125434-			Client:    cli,
125435-			GoVersion: os.Getenv(GoVersionForVulnTest),
125436-		}, vulncheck.Convert(pkgs))
125437-		if err != nil {
125438-			return err
125439-		}
125440-		affecting := 0
125441-		for _, v := range res.Vulns {
125442-			if v.IsCalled() {
125443-				affecting++
125444-			}
125445-		}
125446-		logf("Found %d affecting vulns and %d unaffecting vulns in imported packages", affecting, len(res.Vulns)-affecting)
125447-		if err := json.NewEncoder(os.Stdout).Encode(res); err != nil {
125448-			return err
125449-		}
125450-		return nil
125451-	}
125452-}
125453-
125454-var (
125455-	// Regexp for matching go tags. The groups are:
125456-	// 1  the major.minor version
125457-	// 2  the patch version, or empty if none
125458-	// 3  the entire prerelease, if present
125459-	// 4  the prerelease type ("beta" or "rc")
125460-	// 5  the prerelease number
125461-	tagRegexp = regexp.MustCompile(`^go(\d+\.\d+)(\.\d+|)((beta|rc|-pre)(\d+))?$`)
125462-)
125463-
125464-// This is a modified copy of pkgsite/internal/stdlib:VersionForTag.
125465-func GoTagToSemver(tag string) string {
125466-	if tag == "" {
125467-		return ""
125468-	}
125469-
125470-	tag = strings.Fields(tag)[0]
125471-	// Special cases for go1.
125472-	if tag == "go1" {
125473-		return "v1.0.0"
125474-	}
125475-	if tag == "go1.0" {
125476-		return ""
125477-	}
125478-	m := tagRegexp.FindStringSubmatch(tag)
125479-	if m == nil {
125480-		return ""
125481-	}
125482-	version := "v" + m[1]
125483-	if m[2] != "" {
125484-		version += m[2]
125485-	} else {
125486-		version += ".0"
125487-	}
125488-	if m[3] != "" {
125489-		if !strings.HasPrefix(m[4], "-") {
125490-			version += "-"
125491-		}
125492-		version += m[4] + "." + m[5]
125493-	}
125494-	return version
125495-}
125496-
125497-// semverToGoTag returns the Go standard library repository tag corresponding
125498-// to semver, a version string without the initial "v".
125499-// Go tags differ from standard semantic versions in a few ways,
125500-// such as beginning with "go" instead of "v".
125501-func semverToGoTag(v string) string {
125502-	if strings.HasPrefix(v, "v0.0.0") {
125503-		return "master"
125504-	}
125505-	// Special case: v1.0.0 => go1.
125506-	if v == "v1.0.0" {
125507-		return "go1"
125508-	}
125509-	if !semver.IsValid(v) {
125510-		return fmt.Sprintf("<!%s:invalid semver>", v)
125511-	}
125512-	goVersion := semver.Canonical(v)
125513-	prerelease := semver.Prerelease(goVersion)
125514-	versionWithoutPrerelease := strings.TrimSuffix(goVersion, prerelease)
125515-	patch := strings.TrimPrefix(versionWithoutPrerelease, semver.MajorMinor(goVersion)+".")
125516-	if patch == "0" {
125517-		versionWithoutPrerelease = strings.TrimSuffix(versionWithoutPrerelease, ".0")
125518-	}
125519-	goVersion = fmt.Sprintf("go%s", strings.TrimPrefix(versionWithoutPrerelease, "v"))
125520-	if prerelease != "" {
125521-		// Go prereleases look like  "beta1" instead of "beta.1".
125522-		// "beta1" is bad for sorting (since beta10 comes before beta9), so
125523-		// require the dot form.
125524-		i := finalDigitsIndex(prerelease)
125525-		if i >= 1 {
125526-			if prerelease[i-1] != '.' {
125527-				return fmt.Sprintf("<!%s:final digits in a prerelease must follow a period>", v)
125528-			}
125529-			// Remove the dot.
125530-			prerelease = prerelease[:i-1] + prerelease[i:]
125531-		}
125532-		goVersion += strings.TrimPrefix(prerelease, "-")
125533-	}
125534-	return goVersion
125535-}
125536-
125537-// finalDigitsIndex returns the index of the first digit in the sequence of digits ending s.
125538-// If s doesn't end in digits, it returns -1.
125539-func finalDigitsIndex(s string) int {
125540-	// Assume ASCII (since the semver package does anyway).
125541-	var i int
125542-	for i = len(s) - 1; i >= 0; i-- {
125543-		if s[i] < '0' || s[i] > '9' {
125544-			break
125545-		}
125546-	}
125547-	if i == len(s)-1 {
125548-		return -1
125549-	}
125550-	return i + 1
125551-}
125552-
125553-// vulnerablePackages queries the vulndb and reports which vulnerabilities
125554-// apply to this snapshot. The result contains a set of packages,
125555-// grouped by vuln ID and by module.
125556-func vulnerablePackages(ctx context.Context, snapshot source.Snapshot, modfile source.FileHandle) (*govulncheck.Result, error) {
125557-	// We want to report the intersection of vulnerable packages in the vulndb
125558-	// and packages transitively imported by this module ('go list -deps all').
125559-	// We use snapshot.AllMetadata to retrieve the list of packages
125560-	// as an approximation.
125561-	//
125562-	// TODO(hyangah): snapshot.AllMetadata is a superset of
125563-	// `go list all` - e.g. when the workspace has multiple main modules
125564-	// (multiple go.mod files), that can include packages that are not
125565-	// used by this module. Vulncheck behavior with go.work is not well
125566-	// defined. Figure out the meaning, and if we decide to present
125567-	// the result as if each module is analyzed independently, make
125568-	// gopls track a separate build list for each module and use that
125569-	// information instead of snapshot.AllMetadata.
125570-	metadata, err := snapshot.AllMetadata(ctx)
125571-	if err != nil {
125572-		return nil, err
125573-	}
125574-
125575-	// TODO(hyangah): handle vulnerabilities in the standard library.
125576-
125577-	// Group packages by modules since vuln db is keyed by module.
125578-	metadataByModule := map[source.PackagePath][]*source.Metadata{}
125579-	for _, md := range metadata {
125580-		mi := md.Module
125581-		modulePath := source.PackagePath("stdlib")
125582-		if mi != nil {
125583-			modulePath = source.PackagePath(mi.Path)
125584-		}
125585-		metadataByModule[modulePath] = append(metadataByModule[modulePath], md)
125586-	}
125587-
125588-	// Request vuln entries from remote service.
125589-	fsCache, err := govulncheck.DefaultCache()
125590-	if err != nil {
125591-		return nil, err
125592-	}
125593-	cli, err := client.NewClient(
125594-		findGOVULNDB(snapshot.View().Options().EnvSlice()),
125595-		client.Options{HTTPCache: govulncheck.NewInMemoryCache(fsCache)})
125596-	if err != nil {
125597-		return nil, err
125598-	}
125599-	// Keys are osv.Entry.IDs
125600-	vulnsResult := map[string]*govulncheck.Vuln{}
125601-	var (
125602-		group errgroup.Group
125603-		mu    sync.Mutex
125604-	)
125605-
125606-	goVersion := snapshot.View().Options().Env[GoVersionForVulnTest]
125607-	if goVersion == "" {
125608-		goVersion = snapshot.View().GoVersionString()
125609-	}
125610-	group.SetLimit(10)
125611-	stdlibModule := &packages.Module{
125612-		Path:    "stdlib",
125613-		Version: goVersion,
125614-	}
125615-	for path, mds := range metadataByModule {
125616-		path, mds := path, mds
125617-		group.Go(func() error {
125618-			effectiveModule := stdlibModule
125619-			if m := mds[0].Module; m != nil {
125620-				effectiveModule = m
125621-			}
125622-			for effectiveModule.Replace != nil {
125623-				effectiveModule = effectiveModule.Replace
125624-			}
125625-			ver := effectiveModule.Version
125626-
125627-			// TODO(go.dev/issues/56312): batch these requests for efficiency.
125628-			vulns, err := cli.GetByModule(ctx, effectiveModule.Path)
125629-			if err != nil {
125630-				return err
125631-			}
125632-			if len(vulns) == 0 { // No known vulnerability.
125633-				return nil
125634-			}
125635-
125636-			// set of packages in this module known to gopls.
125637-			// This will be lazily initialized when we need it.
125638-			var knownPkgs map[source.PackagePath]bool
125639-
125640-			// Report vulnerabilities that affect packages of this module.
125641-			for _, entry := range vulns {
125642-				var vulnerablePkgs []*govulncheck.Package
125643-
125644-				for _, a := range entry.Affected {
125645-					if a.Package.Ecosystem != osv.GoEcosystem || a.Package.Name != effectiveModule.Path {
125646-						continue
125647-					}
125648-					if !a.Ranges.AffectsSemver(ver) {
125649-						continue
125650-					}
125651-					for _, imp := range a.EcosystemSpecific.Imports {
125652-						if knownPkgs == nil {
125653-							knownPkgs = toPackagePathSet(mds)
125654-						}
125655-						if knownPkgs[source.PackagePath(imp.Path)] {
125656-							vulnerablePkgs = append(vulnerablePkgs, &govulncheck.Package{
125657-								Path: imp.Path,
125658-							})
125659-						}
125660-					}
125661-				}
125662-				if len(vulnerablePkgs) == 0 {
125663-					continue
125664-				}
125665-				mu.Lock()
125666-				vuln, ok := vulnsResult[entry.ID]
125667-				if !ok {
125668-					vuln = &govulncheck.Vuln{OSV: entry}
125669-					vulnsResult[entry.ID] = vuln
125670-				}
125671-				vuln.Modules = append(vuln.Modules, &govulncheck.Module{
125672-					Path:         string(path),
125673-					FoundVersion: ver,
125674-					FixedVersion: fixedVersion(effectiveModule.Path, entry.Affected),
125675-					Packages:     vulnerablePkgs,
125676-				})
125677-				mu.Unlock()
125678-			}
125679-			return nil
125680-		})
125681-	}
125682-	if err := group.Wait(); err != nil {
125683-		return nil, err
125684-	}
125685-
125686-	vulns := make([]*govulncheck.Vuln, 0, len(vulnsResult))
125687-	for _, v := range vulnsResult {
125688-		vulns = append(vulns, v)
125689-	}
125690-	// Sort so the results are deterministic.
125691-	sort.Slice(vulns, func(i, j int) bool {
125692-		return vulns[i].OSV.ID < vulns[j].OSV.ID
125693-	})
125694-	ret := &govulncheck.Result{
125695-		Vulns: vulns,
125696-		Mode:  govulncheck.ModeImports,
125697-	}
125698-	return ret, nil
125699-}
125700-
125701-// toPackagePathSet transforms the metadata to a set of package paths.
125702-func toPackagePathSet(mds []*source.Metadata) map[source.PackagePath]bool {
125703-	pkgPaths := make(map[source.PackagePath]bool, len(mds))
125704-	for _, md := range mds {
125705-		pkgPaths[md.PkgPath] = true
125706-	}
125707-	return pkgPaths
125708-}
125709-
125710-func fixedVersion(modulePath string, affected []osv.Affected) string {
125711-	fixed := govulncheck.LatestFixed(modulePath, affected)
125712-	if fixed != "" {
125713-		fixed = versionString(modulePath, fixed)
125714-	}
125715-	return fixed
125716-}
125717-
125718-// versionString prepends a version string prefix (`v` or `go`
125719-// depending on the modulePath) to the given semver-style version string.
125720-func versionString(modulePath, version string) string {
125721-	if version == "" {
125722-		return ""
125723-	}
125724-	v := "v" + version
125725-	// These are internal Go module paths used by the vuln DB
125726-	// when listing vulns in standard library and the go command.
125727-	if modulePath == "stdlib" || modulePath == "toolchain" {
125728-		return semverToGoTag(v)
125729-	}
125730-	return v
125731-}
125732diff -urN a/gopls/internal/vulncheck/vulncheck.go b/gopls/internal/vulncheck/vulncheck.go
125733--- a/gopls/internal/vulncheck/vulncheck.go	2000-01-01 00:00:00.000000000 -0000
125734+++ b/gopls/internal/vulncheck/vulncheck.go	1970-01-01 00:00:00.000000000 +0000
125735@@ -1,25 +0,0 @@
125736-// Copyright 2022 The Go Authors. All rights reserved.
125737-// Use of this source code is governed by a BSD-style
125738-// license that can be found in the LICENSE file.
125739-
125740-// Package vulncheck provides an analysis command
125741-// that runs vulnerability analysis using data from
125742-// golang.org/x/vuln/vulncheck.
125743-// This package requires go1.18 or newer.
125744-package vulncheck
125745-
125746-import (
125747-	"context"
125748-
125749-	"golang.org/x/tools/go/packages"
125750-	"golang.org/x/tools/gopls/internal/govulncheck"
125751-	"golang.org/x/tools/gopls/internal/lsp/source"
125752-)
125753-
125754-// With go1.18+, this is swapped with the real implementation.
125755-var Main func(cfg packages.Config, patterns ...string) error = nil
125756-
125757-// VulnerablePackages queries the vulndb and reports which vulnerabilities
125758-// apply to this snapshot. The result contains a set of packages,
125759-// grouped by vuln ID and by module.
125760-var VulnerablePackages func(ctx context.Context, snapshot source.Snapshot, modfile source.FileHandle) (*govulncheck.Result, error) = nil
125761diff -urN a/gopls/internal/vulncheck/vulntest/db.go b/gopls/internal/vulncheck/vulntest/db.go
125762--- a/gopls/internal/vulncheck/vulntest/db.go	2000-01-01 00:00:00.000000000 -0000
125763+++ b/gopls/internal/vulncheck/vulntest/db.go	1970-01-01 00:00:00.000000000 +0000
125764@@ -1,303 +0,0 @@
125765-// Copyright 2022 The Go Authors. All rights reserved.
125766-// Use of this source code is governed by a BSD-style
125767-// license that can be found in the LICENSE file.
125768-
125769-//go:build go1.18
125770-// +build go1.18
125771-
125772-// Package vulntest provides helpers for vulncheck functionality testing.
125773-package vulntest
125774-
125775-import (
125776-	"bytes"
125777-	"context"
125778-	"encoding/json"
125779-	"fmt"
125780-	"io/ioutil"
125781-	"os"
125782-	"path/filepath"
125783-	"sort"
125784-	"strings"
125785-	"time"
125786-
125787-	"golang.org/x/tools/gopls/internal/span"
125788-	"golang.org/x/tools/txtar"
125789-	"golang.org/x/vuln/client"
125790-	"golang.org/x/vuln/osv"
125791-)
125792-
125793-// NewDatabase returns a read-only DB containing the provided
125794-// txtar-format collection of vulnerability reports.
125795-// Each vulnerability report is a YAML file whose format
125796-// is defined in golang.org/x/vulndb/doc/format.md.
125797-// A report file name must have the id as its base name,
125798-// and have .yaml as its extension.
125799-//
125800-//	db, err := NewDatabase(ctx, reports)
125801-//	...
125802-//	defer db.Clean()
125803-//	client, err := NewClient(db)
125804-//	...
125805-//
125806-// The returned DB's Clean method must be called to clean up the
125807-// generated database.
125808-func NewDatabase(ctx context.Context, txtarReports []byte) (*DB, error) {
125809-	disk, err := ioutil.TempDir("", "vulndb-test")
125810-	if err != nil {
125811-		return nil, err
125812-	}
125813-	if err := generateDB(ctx, txtarReports, disk, false); err != nil {
125814-		os.RemoveAll(disk)
125815-		return nil, err
125816-	}
125817-
125818-	return &DB{disk: disk}, nil
125819-}
125820-
125821-// DB is a read-only vulnerability database on disk.
125822-// Users can use this database with golang.org/x/vuln APIs
125823-// by setting the `VULNDB“ environment variable.
125824-type DB struct {
125825-	disk string
125826-}
125827-
125828-// URI returns the file URI that can be used for VULNDB environment
125829-// variable.
125830-func (db *DB) URI() string {
125831-	u := span.URIFromPath(db.disk)
125832-	return string(u)
125833-}
125834-
125835-// Clean deletes the database.
125836-func (db *DB) Clean() error {
125837-	return os.RemoveAll(db.disk)
125838-}
125839-
125840-// NewClient returns a vuln DB client that works with the given DB.
125841-func NewClient(db *DB) (client.Client, error) {
125842-	return client.NewClient([]string{db.URI()}, client.Options{})
125843-}
125844-
125845-//
125846-// The following was selectively copied from golang.org/x/vulndb/internal/database
125847-//
125848-
125849-const (
125850-	dbURL = "https://pkg.go.dev/vuln/"
125851-
125852-	// idDirectory is the name of the directory that contains entries
125853-	// listed by their IDs.
125854-	idDirectory = "ID"
125855-
125856-	// stdFileName is the name of the .json file in the vulndb repo
125857-	// that will contain info on standard library vulnerabilities.
125858-	stdFileName = "stdlib"
125859-
125860-	// toolchainFileName is the name of the .json file in the vulndb repo
125861-	// that will contain info on toolchain (cmd/...) vulnerabilities.
125862-	toolchainFileName = "toolchain"
125863-
125864-	// cmdModule is the name of the module containing Go toolchain
125865-	// binaries.
125866-	cmdModule = "cmd"
125867-
125868-	// stdModule is the name of the module containing Go std packages.
125869-	stdModule = "std"
125870-)
125871-
125872-// generateDB generates the file-based vuln DB in the directory jsonDir.
125873-func generateDB(ctx context.Context, txtarData []byte, jsonDir string, indent bool) error {
125874-	archive := txtar.Parse(txtarData)
125875-
125876-	jsonVulns, entries, err := generateEntries(ctx, archive)
125877-	if err != nil {
125878-		return err
125879-	}
125880-
125881-	index := make(client.DBIndex, len(jsonVulns))
125882-	for modulePath, vulns := range jsonVulns {
125883-		epath, err := client.EscapeModulePath(modulePath)
125884-		if err != nil {
125885-			return err
125886-		}
125887-		if err := writeVulns(filepath.Join(jsonDir, epath), vulns, indent); err != nil {
125888-			return err
125889-		}
125890-		for _, v := range vulns {
125891-			if v.Modified.After(index[modulePath]) {
125892-				index[modulePath] = v.Modified
125893-			}
125894-		}
125895-	}
125896-	if err := writeJSON(filepath.Join(jsonDir, "index.json"), index, indent); err != nil {
125897-		return err
125898-	}
125899-	if err := writeAliasIndex(jsonDir, entries, indent); err != nil {
125900-		return err
125901-	}
125902-	return writeEntriesByID(filepath.Join(jsonDir, idDirectory), entries, indent)
125903-}
125904-
125905-func generateEntries(_ context.Context, archive *txtar.Archive) (map[string][]osv.Entry, []osv.Entry, error) {
125906-	now := time.Now()
125907-	jsonVulns := map[string][]osv.Entry{}
125908-	var entries []osv.Entry
125909-	for _, f := range archive.Files {
125910-		if !strings.HasSuffix(f.Name, ".yaml") {
125911-			continue
125912-		}
125913-		r, err := readReport(bytes.NewReader(f.Data))
125914-		if err != nil {
125915-			return nil, nil, err
125916-		}
125917-		name := strings.TrimSuffix(filepath.Base(f.Name), filepath.Ext(f.Name))
125918-		linkName := fmt.Sprintf("%s%s", dbURL, name)
125919-		entry, modulePaths := generateOSVEntry(name, linkName, now, *r)
125920-		for _, modulePath := range modulePaths {
125921-			jsonVulns[modulePath] = append(jsonVulns[modulePath], entry)
125922-		}
125923-		entries = append(entries, entry)
125924-	}
125925-	return jsonVulns, entries, nil
125926-}
125927-
125928-func writeVulns(outPath string, vulns []osv.Entry, indent bool) error {
125929-	if err := os.MkdirAll(filepath.Dir(outPath), 0755); err != nil {
125930-		return fmt.Errorf("failed to create directory %q: %s", filepath.Dir(outPath), err)
125931-	}
125932-	return writeJSON(outPath+".json", vulns, indent)
125933-}
125934-
125935-func writeEntriesByID(idDir string, entries []osv.Entry, indent bool) error {
125936-	// Write a directory containing entries by ID.
125937-	if err := os.MkdirAll(idDir, 0755); err != nil {
125938-		return fmt.Errorf("failed to create directory %q: %v", idDir, err)
125939-	}
125940-	var idIndex []string
125941-	for _, e := range entries {
125942-		outPath := filepath.Join(idDir, e.ID+".json")
125943-		if err := writeJSON(outPath, e, indent); err != nil {
125944-			return err
125945-		}
125946-		idIndex = append(idIndex, e.ID)
125947-	}
125948-	// Write an index.json in the ID directory with a list of all the IDs.
125949-	return writeJSON(filepath.Join(idDir, "index.json"), idIndex, indent)
125950-}
125951-
125952-// Write a JSON file containing a map from alias to GO IDs.
125953-func writeAliasIndex(dir string, entries []osv.Entry, indent bool) error {
125954-	aliasToGoIDs := map[string][]string{}
125955-	for _, e := range entries {
125956-		for _, a := range e.Aliases {
125957-			aliasToGoIDs[a] = append(aliasToGoIDs[a], e.ID)
125958-		}
125959-	}
125960-	return writeJSON(filepath.Join(dir, "aliases.json"), aliasToGoIDs, indent)
125961-}
125962-
125963-func writeJSON(filename string, value any, indent bool) (err error) {
125964-	j, err := jsonMarshal(value, indent)
125965-	if err != nil {
125966-		return err
125967-	}
125968-	return os.WriteFile(filename, j, 0644)
125969-}
125970-
125971-func jsonMarshal(v any, indent bool) ([]byte, error) {
125972-	if indent {
125973-		return json.MarshalIndent(v, "", "  ")
125974-	}
125975-	return json.Marshal(v)
125976-}
125977-
125978-// generateOSVEntry create an osv.Entry for a report. In addition to the report, it
125979-// takes the ID for the vuln and a URL that will point to the entry in the vuln DB.
125980-// It returns the osv.Entry and a list of module paths that the vuln affects.
125981-func generateOSVEntry(id, url string, lastModified time.Time, r Report) (osv.Entry, []string) {
125982-	entry := osv.Entry{
125983-		ID:        id,
125984-		Published: r.Published,
125985-		Modified:  lastModified,
125986-		Withdrawn: r.Withdrawn,
125987-		Details:   r.Description,
125988-	}
125989-
125990-	moduleMap := make(map[string]bool)
125991-	for _, m := range r.Modules {
125992-		switch m.Module {
125993-		case stdModule:
125994-			moduleMap[stdFileName] = true
125995-		case cmdModule:
125996-			moduleMap[toolchainFileName] = true
125997-		default:
125998-			moduleMap[m.Module] = true
125999-		}
126000-		entry.Affected = append(entry.Affected, generateAffected(m, url))
126001-	}
126002-	for _, ref := range r.References {
126003-		entry.References = append(entry.References, osv.Reference{
126004-			Type: string(ref.Type),
126005-			URL:  ref.URL,
126006-		})
126007-	}
126008-
126009-	var modulePaths []string
126010-	for module := range moduleMap {
126011-		modulePaths = append(modulePaths, module)
126012-	}
126013-	// TODO: handle missing fields - Aliases
126014-
126015-	return entry, modulePaths
126016-}
126017-
126018-func generateAffectedRanges(versions []VersionRange) osv.Affects {
126019-	a := osv.AffectsRange{Type: osv.TypeSemver}
126020-	if len(versions) == 0 || versions[0].Introduced == "" {
126021-		a.Events = append(a.Events, osv.RangeEvent{Introduced: "0"})
126022-	}
126023-	for _, v := range versions {
126024-		if v.Introduced != "" {
126025-			a.Events = append(a.Events, osv.RangeEvent{Introduced: v.Introduced.Canonical()})
126026-		}
126027-		if v.Fixed != "" {
126028-			a.Events = append(a.Events, osv.RangeEvent{Fixed: v.Fixed.Canonical()})
126029-		}
126030-	}
126031-	return osv.Affects{a}
126032-}
126033-
126034-func generateImports(m *Module) (imps []osv.EcosystemSpecificImport) {
126035-	for _, p := range m.Packages {
126036-		syms := append([]string{}, p.Symbols...)
126037-		syms = append(syms, p.DerivedSymbols...)
126038-		sort.Strings(syms)
126039-		imps = append(imps, osv.EcosystemSpecificImport{
126040-			Path:    p.Package,
126041-			GOOS:    p.GOOS,
126042-			GOARCH:  p.GOARCH,
126043-			Symbols: syms,
126044-		})
126045-	}
126046-	return imps
126047-}
126048-func generateAffected(m *Module, url string) osv.Affected {
126049-	name := m.Module
126050-	switch name {
126051-	case stdModule:
126052-		name = "stdlib"
126053-	case cmdModule:
126054-		name = "toolchain"
126055-	}
126056-	return osv.Affected{
126057-		Package: osv.Package{
126058-			Name:      name,
126059-			Ecosystem: osv.GoEcosystem,
126060-		},
126061-		Ranges:           generateAffectedRanges(m.Versions),
126062-		DatabaseSpecific: osv.DatabaseSpecific{URL: url},
126063-		EcosystemSpecific: osv.EcosystemSpecific{
126064-			Imports: generateImports(m),
126065-		},
126066-	}
126067-}
126068diff -urN a/gopls/internal/vulncheck/vulntest/db_test.go b/gopls/internal/vulncheck/vulntest/db_test.go
126069--- a/gopls/internal/vulncheck/vulntest/db_test.go	2000-01-01 00:00:00.000000000 -0000
126070+++ b/gopls/internal/vulncheck/vulntest/db_test.go	1970-01-01 00:00:00.000000000 +0000
126071@@ -1,61 +0,0 @@
126072-// Copyright 2022 The Go Authors. All rights reserved.
126073-// Use of this source code is governed by a BSD-style
126074-// license that can be found in the LICENSE file.
126075-
126076-//go:build go1.18
126077-// +build go1.18
126078-
126079-package vulntest
126080-
126081-import (
126082-	"context"
126083-	"encoding/json"
126084-	"testing"
126085-)
126086-
126087-func TestNewDatabase(t *testing.T) {
126088-	ctx := context.Background()
126089-	in := []byte(`
126090--- GO-2020-0001.yaml --
126091-modules:
126092-  - module: github.com/gin-gonic/gin
126093-    versions:
126094-      - fixed: 1.6.0
126095-    packages:
126096-      - package: github.com/gin-gonic/gin
126097-        symbols:
126098-          - defaultLogFormatter
126099-description: |
126100-    Something.
126101-published: 2021-04-14T20:04:52Z
126102-references:
126103-  - fix: https://github.com/gin-gonic/gin/pull/2237
126104-`)
126105-
126106-	db, err := NewDatabase(ctx, in)
126107-	if err != nil {
126108-		t.Fatal(err)
126109-	}
126110-	defer db.Clean()
126111-
126112-	cli, err := NewClient(db)
126113-	if err != nil {
126114-		t.Fatal(err)
126115-	}
126116-	got, err := cli.GetByID(ctx, "GO-2020-0001")
126117-	if err != nil {
126118-		t.Fatal(err)
126119-	}
126120-	if got.ID != "GO-2020-0001" {
126121-		m, _ := json.Marshal(got)
126122-		t.Errorf("got %s\nwant GO-2020-0001 entry", m)
126123-	}
126124-	gotAll, err := cli.GetByModule(ctx, "github.com/gin-gonic/gin")
126125-	if err != nil {
126126-		t.Fatal(err)
126127-	}
126128-	if len(gotAll) != 1 || gotAll[0].ID != "GO-2020-0001" {
126129-		m, _ := json.Marshal(got)
126130-		t.Errorf("got %s\nwant GO-2020-0001 entry", m)
126131-	}
126132-}
126133diff -urN a/gopls/internal/vulncheck/vulntest/report.go b/gopls/internal/vulncheck/vulntest/report.go
126134--- a/gopls/internal/vulncheck/vulntest/report.go	2000-01-01 00:00:00.000000000 -0000
126135+++ b/gopls/internal/vulncheck/vulntest/report.go	1970-01-01 00:00:00.000000000 +0000
126136@@ -1,176 +0,0 @@
126137-// Copyright 2022 The Go Authors. All rights reserved.
126138-// Use of this source code is governed by a BSD-style
126139-// license that can be found in the LICENSE file.
126140-
126141-//go:build go1.18
126142-// +build go1.18
126143-
126144-package vulntest
126145-
126146-import (
126147-	"fmt"
126148-	"io"
126149-	"os"
126150-	"strings"
126151-	"time"
126152-
126153-	"golang.org/x/mod/semver"
126154-	"gopkg.in/yaml.v3"
126155-)
126156-
126157-//
126158-// The following was selectively copied from golang.org/x/vulndb/internal/report
126159-//
126160-
126161-// readReport reads a Report in YAML format.
126162-func readReport(in io.Reader) (*Report, error) {
126163-	d := yaml.NewDecoder(in)
126164-	// Require that all fields in the file are in the struct.
126165-	// This corresponds to v2's UnmarshalStrict.
126166-	d.KnownFields(true)
126167-	var r Report
126168-	if err := d.Decode(&r); err != nil {
126169-		return nil, fmt.Errorf("yaml.Decode: %v", err)
126170-	}
126171-	return &r, nil
126172-}
126173-
126174-// Report represents a vulnerability report in the vulndb.
126175-// Remember to update doc/format.md when this structure changes.
126176-type Report struct {
126177-	Modules []*Module `yaml:",omitempty"`
126178-
126179-	// Description is the CVE description from an existing CVE. If we are
126180-	// assigning a CVE ID ourselves, use CVEMetadata.Description instead.
126181-	Description string     `yaml:",omitempty"`
126182-	Published   time.Time  `yaml:",omitempty"`
126183-	Withdrawn   *time.Time `yaml:",omitempty"`
126184-
126185-	References []*Reference `yaml:",omitempty"`
126186-}
126187-
126188-// Write writes r to filename in YAML format.
126189-func (r *Report) Write(filename string) (err error) {
126190-	f, err := os.Create(filename)
126191-	if err != nil {
126192-		return err
126193-	}
126194-	err = r.encode(f)
126195-	err2 := f.Close()
126196-	if err == nil {
126197-		err = err2
126198-	}
126199-	return err
126200-}
126201-
126202-// ToString encodes r to a YAML string.
126203-func (r *Report) ToString() (string, error) {
126204-	var b strings.Builder
126205-	if err := r.encode(&b); err != nil {
126206-		return "", err
126207-	}
126208-	return b.String(), nil
126209-}
126210-
126211-func (r *Report) encode(w io.Writer) error {
126212-	e := yaml.NewEncoder(w)
126213-	defer e.Close()
126214-	e.SetIndent(4)
126215-	return e.Encode(r)
126216-}
126217-
126218-type VersionRange struct {
126219-	Introduced Version `yaml:"introduced,omitempty"`
126220-	Fixed      Version `yaml:"fixed,omitempty"`
126221-}
126222-
126223-type Module struct {
126224-	Module   string         `yaml:",omitempty"`
126225-	Versions []VersionRange `yaml:",omitempty"`
126226-	Packages []*Package     `yaml:",omitempty"`
126227-}
126228-
126229-type Package struct {
126230-	Package string   `yaml:",omitempty"`
126231-	GOOS    []string `yaml:"goos,omitempty"`
126232-	GOARCH  []string `yaml:"goarch,omitempty"`
126233-	// Symbols originally identified as vulnerable.
126234-	Symbols []string `yaml:",omitempty"`
126235-	// Additional vulnerable symbols, computed from Symbols via static analysis
126236-	// or other technique.
126237-	DerivedSymbols []string `yaml:"derived_symbols,omitempty"`
126238-}
126239-
126240-// Version is an SemVer 2.0.0 semantic version with no leading "v" prefix,
126241-// as used by OSV.
126242-type Version string
126243-
126244-// V returns the version with a "v" prefix.
126245-func (v Version) V() string {
126246-	return "v" + string(v)
126247-}
126248-
126249-// IsValid reports whether v is a valid semantic version string.
126250-func (v Version) IsValid() bool {
126251-	return semver.IsValid(v.V())
126252-}
126253-
126254-// Before reports whether v < v2.
126255-func (v Version) Before(v2 Version) bool {
126256-	return semver.Compare(v.V(), v2.V()) < 0
126257-}
126258-
126259-// Canonical returns the canonical formatting of the version.
126260-func (v Version) Canonical() string {
126261-	return strings.TrimPrefix(semver.Canonical(v.V()), "v")
126262-}
126263-
126264-// Reference type is a reference (link) type.
126265-type ReferenceType string
126266-
126267-const (
126268-	ReferenceTypeAdvisory = ReferenceType("ADVISORY")
126269-	ReferenceTypeArticle  = ReferenceType("ARTICLE")
126270-	ReferenceTypeReport   = ReferenceType("REPORT")
126271-	ReferenceTypeFix      = ReferenceType("FIX")
126272-	ReferenceTypePackage  = ReferenceType("PACKAGE")
126273-	ReferenceTypeEvidence = ReferenceType("EVIDENCE")
126274-	ReferenceTypeWeb      = ReferenceType("WEB")
126275-)
126276-
126277-// ReferenceTypes is the set of reference types defined in OSV.
126278-var ReferenceTypes = []ReferenceType{
126279-	ReferenceTypeAdvisory,
126280-	ReferenceTypeArticle,
126281-	ReferenceTypeReport,
126282-	ReferenceTypeFix,
126283-	ReferenceTypePackage,
126284-	ReferenceTypeEvidence,
126285-	ReferenceTypeWeb,
126286-}
126287-
126288-// A Reference is a link to some external resource.
126289-//
126290-// For ease of typing, References are represented in the YAML as a
126291-// single-element mapping of type to URL.
126292-type Reference struct {
126293-	Type ReferenceType `json:"type,omitempty"`
126294-	URL  string        `json:"url,omitempty"`
126295-}
126296-
126297-func (r *Reference) MarshalYAML() (interface{}, error) {
126298-	return map[string]string{
126299-		strings.ToLower(string(r.Type)): r.URL,
126300-	}, nil
126301-}
126302-
126303-func (r *Reference) UnmarshalYAML(n *yaml.Node) (err error) {
126304-	if n.Kind != yaml.MappingNode || len(n.Content) != 2 || n.Content[0].Kind != yaml.ScalarNode || n.Content[1].Kind != yaml.ScalarNode {
126305-		return &yaml.TypeError{Errors: []string{
126306-			fmt.Sprintf("line %d: report.Reference must contain a mapping with one value", n.Line),
126307-		}}
126308-	}
126309-	r.Type = ReferenceType(strings.ToUpper(n.Content[0].Value))
126310-	r.URL = n.Content[1].Value
126311-	return nil
126312-}
126313diff -urN a/gopls/internal/vulncheck/vulntest/report_test.go b/gopls/internal/vulncheck/vulntest/report_test.go
126314--- a/gopls/internal/vulncheck/vulntest/report_test.go	2000-01-01 00:00:00.000000000 -0000
126315+++ b/gopls/internal/vulncheck/vulntest/report_test.go	1970-01-01 00:00:00.000000000 +0000
126316@@ -1,52 +0,0 @@
126317-// Copyright 2022 The Go Authors. All rights reserved.
126318-// Use of this source code is governed by a BSD-style
126319-// license that can be found in the LICENSE file.
126320-
126321-//go:build go1.18
126322-// +build go1.18
126323-
126324-package vulntest
126325-
126326-import (
126327-	"bytes"
126328-	"io"
126329-	"io/ioutil"
126330-	"os"
126331-	"path/filepath"
126332-	"testing"
126333-
126334-	"github.com/google/go-cmp/cmp"
126335-)
126336-
126337-func readAll(t *testing.T, filename string) io.Reader {
126338-	d, err := ioutil.ReadFile(filename)
126339-	if err != nil {
126340-		t.Fatal(err)
126341-	}
126342-	return bytes.NewReader(d)
126343-}
126344-
126345-func TestRoundTrip(t *testing.T) {
126346-	// A report shouldn't change after being read and then written.
126347-	in := filepath.Join("testdata", "report.yaml")
126348-	r, err := readReport(readAll(t, in))
126349-	if err != nil {
126350-		t.Fatal(err)
126351-	}
126352-	out := filepath.Join(t.TempDir(), "report.yaml")
126353-	if err := r.Write(out); err != nil {
126354-		t.Fatal(err)
126355-	}
126356-
126357-	want, err := os.ReadFile(in)
126358-	if err != nil {
126359-		t.Fatal(err)
126360-	}
126361-	got, err := os.ReadFile(out)
126362-	if err != nil {
126363-		t.Fatal(err)
126364-	}
126365-	if diff := cmp.Diff(want, got); diff != "" {
126366-		t.Errorf("mismatch (-want, +got):\n%s", diff)
126367-	}
126368-}
126369diff -urN a/gopls/internal/vulncheck/vulntest/stdlib.go b/gopls/internal/vulncheck/vulntest/stdlib.go
126370--- a/gopls/internal/vulncheck/vulntest/stdlib.go	2000-01-01 00:00:00.000000000 -0000
126371+++ b/gopls/internal/vulncheck/vulntest/stdlib.go	1970-01-01 00:00:00.000000000 +0000
126372@@ -1,26 +0,0 @@
126373-// Copyright 2022 The Go Authors. All rights reserved.
126374-// Use of this source code is governed by a BSD-style
126375-// license that can be found in the LICENSE file.
126376-
126377-//go:build go1.18
126378-// +build go1.18
126379-
126380-package vulntest
126381-
126382-import (
126383-	"strings"
126384-
126385-	"golang.org/x/mod/module"
126386-)
126387-
126388-// maybeStdlib reports whether the given import path could be part of the Go
126389-// standard library, by reporting whether the first component lacks a '.'.
126390-func maybeStdlib(path string) bool {
126391-	if err := module.CheckImportPath(path); err != nil {
126392-		return false
126393-	}
126394-	if i := strings.IndexByte(path, '/'); i != -1 {
126395-		path = path[:i]
126396-	}
126397-	return !strings.Contains(path, ".")
126398-}
126399diff -urN a/gopls/internal/vulncheck/vulntest/stdlib_test.go b/gopls/internal/vulncheck/vulntest/stdlib_test.go
126400--- a/gopls/internal/vulncheck/vulntest/stdlib_test.go	2000-01-01 00:00:00.000000000 -0000
126401+++ b/gopls/internal/vulncheck/vulntest/stdlib_test.go	1970-01-01 00:00:00.000000000 +0000
126402@@ -1,27 +0,0 @@
126403-// Copyright 2022 The Go Authors. All rights reserved.
126404-// Use of this source code is governed by a BSD-style
126405-// license that can be found in the LICENSE file.
126406-
126407-//go:build go1.18
126408-// +build go1.18
126409-
126410-package vulntest
126411-
126412-import "testing"
126413-
126414-func TestMaybeStdlib(t *testing.T) {
126415-	for _, test := range []struct {
126416-		in   string
126417-		want bool
126418-	}{
126419-		{"", false},
126420-		{"math/crypto", true},
126421-		{"github.com/pkg/errors", false},
126422-		{"Path is unknown", false},
126423-	} {
126424-		got := maybeStdlib(test.in)
126425-		if got != test.want {
126426-			t.Errorf("%q: got %t, want %t", test.in, got, test.want)
126427-		}
126428-	}
126429-}
126430diff -urN a/gopls/internal/vulncheck/vulntest/testdata/report.yaml b/gopls/internal/vulncheck/vulntest/testdata/report.yaml
126431--- a/gopls/internal/vulncheck/vulntest/testdata/report.yaml	2000-01-01 00:00:00.000000000 -0000
126432+++ b/gopls/internal/vulncheck/vulntest/testdata/report.yaml	1970-01-01 00:00:00.000000000 +0000
126433@@ -1,15 +0,0 @@
126434-modules:
126435-    - module: github.com/gin-gonic/gin
126436-      versions:
126437-        - fixed: 1.6.0
126438-      packages:
126439-        - package: github.com/gin-gonic/gin
126440-          symbols:
126441-            - defaultLogFormatter
126442-description: |
126443-    The default Formatter for the Logger middleware (LoggerConfig.Formatter),
126444-    which is included in the Default engine, allows attackers to inject arbitrary
126445-    log entries by manipulating the request path.
126446-references:
126447-    - fix: https://github.com/gin-gonic/gin/pull/1234
126448-    - fix: https://github.com/gin-gonic/gin/commit/abcdefg
126449diff -urN a/gopls/main.go b/gopls/main.go
126450--- a/gopls/main.go	2000-01-01 00:00:00.000000000 -0000
126451+++ b/gopls/main.go	1970-01-01 00:00:00.000000000 +0000
126452@@ -1,33 +0,0 @@
126453-// Copyright 2019 The Go Authors. All rights reserved.
126454-// Use of this source code is governed by a BSD-style
126455-// license that can be found in the LICENSE file.
126456-
126457-// Gopls (pronounced “go please”) is an LSP server for Go.
126458-// The Language Server Protocol allows any text editor
126459-// to be extended with IDE-like features;
126460-// see https://langserver.org/ for details.
126461-//
126462-// See https://github.com/golang/tools/blob/master/gopls/README.md
126463-// for the most up-to-date documentation.
126464-package main // import "golang.org/x/tools/gopls"
126465-
126466-//go:generate go run doc/generate.go
126467-
126468-import (
126469-	"context"
126470-	"golang.org/x/tools/internal/analysisinternal"
126471-	"os"
126472-
126473-	"golang.org/x/tools/gopls/internal/hooks"
126474-	"golang.org/x/tools/gopls/internal/lsp/cmd"
126475-	"golang.org/x/tools/internal/tool"
126476-)
126477-
126478-func main() {
126479-	// In 1.18, diagnostics for Fuzz tests must not be used by cmd/vet.
126480-	// So the code for Fuzz tests diagnostics is guarded behind flag analysisinternal.DiagnoseFuzzTests
126481-	// Turn on analysisinternal.DiagnoseFuzzTests for gopls
126482-	analysisinternal.DiagnoseFuzzTests = true
126483-	ctx := context.Background()
126484-	tool.Main(ctx, cmd.New("gopls", "", nil, hooks.Options), os.Args[1:])
126485-}
126486diff -urN a/gopls/README.md b/gopls/README.md
126487--- a/gopls/README.md	2000-01-01 00:00:00.000000000 -0000
126488+++ b/gopls/README.md	1970-01-01 00:00:00.000000000 +0000
126489@@ -1,131 +0,0 @@
126490-# `gopls`, the Go language server
126491-
126492-[![PkgGoDev](https://pkg.go.dev/badge/golang.org/x/tools/gopls)](https://pkg.go.dev/golang.org/x/tools/gopls)
126493-
126494-`gopls` (pronounced "Go please") is the official Go [language server] developed
126495-by the Go team. It provides IDE features to any [LSP]-compatible editor.
126496-
126497-<!--TODO(rfindley): Add gifs here.-->
126498-
126499-You should not need to interact with `gopls` directly--it will be automatically
126500-integrated into your editor. The specific features and settings vary slightly
126501-by editor, so we recommend that you proceed to the
126502-[documentation for your editor](#editors) below.
126503-
126504-## Editors
126505-
126506-To get started with `gopls`, install an LSP plugin in your editor of choice.
126507-
126508-* [VS Code](https://github.com/golang/vscode-go/blob/master/README.md)
126509-* [Vim / Neovim](doc/vim.md)
126510-* [Emacs](doc/emacs.md)
126511-* [Atom](https://github.com/MordFustang21/ide-gopls)
126512-* [Sublime Text](doc/subl.md)
126513-* [Acme](https://github.com/fhs/acme-lsp)
126514-* [Lapce](https://github.com/lapce-community/lapce-go)
126515-
126516-If you use `gopls` with an editor that is not on this list, please send us a CL
126517-[updating this documentation](doc/contributing.md).
126518-
126519-## Installation
126520-
126521-For the most part, you should not need to install or update `gopls`. Your
126522-editor should handle that step for you.
126523-
126524-If you do want to get the latest stable version of `gopls`, run the following
126525-command:
126526-
126527-```sh
126528-go install golang.org/x/tools/gopls@latest
126529-```
126530-
126531-Learn more in the
126532-[advanced installation instructions](doc/advanced.md#installing-unreleased-versions).
126533-
126534-Learn more about gopls releases in the [release policy](doc/releases.md).
126535-
126536-## Setting up your workspace
126537-
126538-`gopls` supports both Go module, multi-module and GOPATH modes. See the
126539-[workspace documentation](doc/workspace.md) for information on supported
126540-workspace layouts.
126541-
126542-## Configuration
126543-
126544-You can configure `gopls` to change your editor experience or view additional
126545-debugging information. Configuration options will be made available by your
126546-editor, so see your [editor's instructions](#editors) for specific details. A
126547-full list of `gopls` settings can be found in the [settings documentation](doc/settings.md).
126548-
126549-### Environment variables
126550-
126551-`gopls` inherits your editor's environment, so be aware of any environment
126552-variables you configure. Some editors, such as VS Code, allow users to
126553-selectively override the values of some environment variables.
126554-
126555-## Support Policy
126556-
126557-Gopls is maintained by engineers on the
126558-[Go tools team](https://github.com/orgs/golang/teams/tools-team/members),
126559-who actively monitor the
126560-[Go](https://github.com/golang/go/issues?q=is%3Aissue+is%3Aopen+label%3Agopls)
126561-and
126562-[VS Code Go](https://github.com/golang/vscode-go/issues) issue trackers.
126563-
126564-### Supported Go versions
126565-
126566-`gopls` follows the
126567-[Go Release Policy](https://golang.org/doc/devel/release.html#policy),
126568-meaning that it officially supports the last 2 major Go releases. Per
126569-[issue #39146](https://go.dev/issues/39146), we attempt to maintain best-effort
126570-support for the last 4 major Go releases, but this support extends only to not
126571-breaking the build and avoiding easily fixable regressions.
126572-
126573-In the context of this discussion, gopls "supports" a Go version if it supports
126574-being built with that Go version as well as integrating with the `go` command
126575-of that Go version.
126576-
126577-The following table shows the final gopls version that supports a given Go
126578-version. Go releases more recent than any in the table can be used with any
126579-version of gopls.
126580-
126581-| Go Version  | Final gopls version with support (without warnings) |
126582-| ----------- | --------------------------------------------------- |
126583-| Go 1.12     | [[email protected]](https://github.com/golang/tools/releases/tag/gopls%2Fv0.7.5) |
126584-| Go 1.15     | [[email protected]](https://github.com/golang/tools/releases/tag/gopls%2Fv0.9.5) |
126585-
126586-Our extended support is enforced via [continuous integration with older Go
126587-versions](doc/contributing.md#ci). This legacy Go CI may not block releases:
126588-test failures may be skipped rather than fixed. Furthermore, if a regression in
126589-an older Go version causes irreconcilable CI failures, we may drop support for
126590-that Go version in CI if it is 3 or 4 Go versions old.
126591-
126592-### Supported build systems
126593-
126594-`gopls` currently only supports the `go` command, so if you are using
126595-a different build system, `gopls` will not work well. Bazel is not officially
126596-supported, but may be made to work with an appropriately configured
126597-`go/packages` driver. See
126598-[bazelbuild/rules_go#512](https://github.com/bazelbuild/rules_go/issues/512)
126599-for more information.
126600-You can follow [these instructions](https://github.com/bazelbuild/rules_go/wiki/Editor-setup)
126601-to configure your `gopls` to work with Bazel.
126602-
126603-### Troubleshooting
126604-
126605-If you are having issues with `gopls`, please follow the steps described in the
126606-[troubleshooting guide](doc/troubleshooting.md).
126607-
126608-## Additional information
126609-
126610-* [Features](doc/features.md)
126611-* [Command-line interface](doc/command-line.md)
126612-* [Advanced topics](doc/advanced.md)
126613-* [Contributing to `gopls`](doc/contributing.md)
126614-* [Integrating `gopls` with an editor](doc/design/integrating.md)
126615-* [Design requirements and decisions](doc/design/design.md)
126616-* [Implementation details](doc/design/implementation.md)
126617-* [Open issues](https://github.com/golang/go/issues?q=is%3Aissue+is%3Aopen+label%3Agopls)
126618-
126619-[language server]: https://langserver.org
126620-[LSP]: https://microsoft.github.io/language-server-protocol/
126621diff -urN a/gopls/release/release.go b/gopls/release/release.go
126622--- a/gopls/release/release.go	2000-01-01 00:00:00.000000000 -0000
126623+++ b/gopls/release/release.go	1970-01-01 00:00:00.000000000 +0000
126624@@ -1,156 +0,0 @@
126625-// Copyright 2020 The Go Authors. All rights reserved.
126626-// Use of this source code is governed by a BSD-style
126627-// license that can be found in the LICENSE file.
126628-//
126629-// Package release checks that the a given version of gopls is ready for
126630-// release. It can also tag and publish the release.
126631-//
126632-// To run:
126633-//
126634-// $ cd $GOPATH/src/golang.org/x/tools/gopls
126635-// $ go run release/release.go -version=<version>
126636-package main
126637-
126638-import (
126639-	"flag"
126640-	"fmt"
126641-	"go/types"
126642-	"io/ioutil"
126643-	"log"
126644-	"os"
126645-	"path/filepath"
126646-	"strconv"
126647-	"strings"
126648-
126649-	exec "golang.org/x/sys/execabs"
126650-
126651-	"golang.org/x/mod/modfile"
126652-	"golang.org/x/mod/semver"
126653-	"golang.org/x/tools/go/packages"
126654-)
126655-
126656-var versionFlag = flag.String("version", "", "version to tag")
126657-
126658-func main() {
126659-	flag.Parse()
126660-
126661-	if *versionFlag == "" {
126662-		log.Fatalf("must provide -version flag")
126663-	}
126664-	if !semver.IsValid(*versionFlag) {
126665-		log.Fatalf("invalid version %s", *versionFlag)
126666-	}
126667-	if semver.Major(*versionFlag) != "v0" {
126668-		log.Fatalf("expected major version v0, got %s", semver.Major(*versionFlag))
126669-	}
126670-	if semver.Build(*versionFlag) != "" {
126671-		log.Fatalf("unexpected build suffix: %s", *versionFlag)
126672-	}
126673-	// Validate that the user is running the program from the gopls module.
126674-	wd, err := os.Getwd()
126675-	if err != nil {
126676-		log.Fatal(err)
126677-	}
126678-	if filepath.Base(wd) != "gopls" {
126679-		log.Fatalf("must run from the gopls module")
126680-	}
126681-	// Confirm that they have updated the hardcoded version.
126682-	if err := validateHardcodedVersion(*versionFlag); err != nil {
126683-		log.Fatal(err)
126684-	}
126685-	// Confirm that the versions in the go.mod file are correct.
126686-	if err := validateGoModFile(wd); err != nil {
126687-		log.Fatal(err)
126688-	}
126689-	fmt.Println("Validated that the release is ready.")
126690-	os.Exit(0)
126691-}
126692-
126693-// validateHardcodedVersion reports whether the version hardcoded in the gopls
126694-// binary is equivalent to the version being published. It reports an error if
126695-// not.
126696-func validateHardcodedVersion(version string) error {
126697-	const debugPkg = "golang.org/x/tools/gopls/internal/lsp/debug"
126698-	pkgs, err := packages.Load(&packages.Config{
126699-		Mode: packages.NeedName | packages.NeedFiles |
126700-			packages.NeedCompiledGoFiles | packages.NeedImports |
126701-			packages.NeedTypes | packages.NeedTypesSizes,
126702-	}, debugPkg)
126703-	if err != nil {
126704-		return err
126705-	}
126706-	if len(pkgs) != 1 {
126707-		return fmt.Errorf("expected 1 package, got %v", len(pkgs))
126708-	}
126709-	pkg := pkgs[0]
126710-	if len(pkg.Errors) > 0 {
126711-		return fmt.Errorf("failed to load %q: first error: %w", debugPkg, pkg.Errors[0])
126712-	}
126713-	obj := pkg.Types.Scope().Lookup("Version")
126714-	c, ok := obj.(*types.Const)
126715-	if !ok {
126716-		return fmt.Errorf("no constant named Version")
126717-	}
126718-	hardcodedVersion, err := strconv.Unquote(c.Val().ExactString())
126719-	if err != nil {
126720-		return err
126721-	}
126722-	if semver.Prerelease(hardcodedVersion) != "" {
126723-		return fmt.Errorf("unexpected pre-release for hardcoded version: %s", hardcodedVersion)
126724-	}
126725-	// Don't worry about pre-release tags and expect that there is no build
126726-	// suffix.
126727-	version = strings.TrimSuffix(version, semver.Prerelease(version))
126728-	if hardcodedVersion != version {
126729-		return fmt.Errorf("expected version to be %s, got %s", *versionFlag, hardcodedVersion)
126730-	}
126731-	return nil
126732-}
126733-
126734-func validateGoModFile(goplsDir string) error {
126735-	filename := filepath.Join(goplsDir, "go.mod")
126736-	data, err := ioutil.ReadFile(filename)
126737-	if err != nil {
126738-		return err
126739-	}
126740-	gomod, err := modfile.Parse(filename, data, nil)
126741-	if err != nil {
126742-		return err
126743-	}
126744-	// Confirm that there is no replace directive in the go.mod file.
126745-	if len(gomod.Replace) > 0 {
126746-		return fmt.Errorf("expected no replace directives, got %v", len(gomod.Replace))
126747-	}
126748-	// Confirm that the version of x/tools in the gopls/go.mod file points to
126749-	// the second-to-last commit. (The last commit will be the one to update the
126750-	// go.mod file.)
126751-	cmd := exec.Command("git", "rev-parse", "@~")
126752-	stdout, err := cmd.Output()
126753-	if err != nil {
126754-		return err
126755-	}
126756-	hash := string(stdout)
126757-	// Find the golang.org/x/tools require line and compare the versions.
126758-	var version string
126759-	for _, req := range gomod.Require {
126760-		if req.Mod.Path == "golang.org/x/tools" {
126761-			version = req.Mod.Version
126762-			break
126763-		}
126764-	}
126765-	if version == "" {
126766-		return fmt.Errorf("no require for golang.org/x/tools")
126767-	}
126768-	split := strings.Split(version, "-")
126769-	if len(split) != 3 {
126770-		return fmt.Errorf("unexpected pseudoversion format %s", version)
126771-	}
126772-	last := split[len(split)-1]
126773-	if last == "" {
126774-		return fmt.Errorf("unexpected pseudoversion format %s", version)
126775-	}
126776-	if !strings.HasPrefix(hash, last) {
126777-		return fmt.Errorf("golang.org/x/tools pseudoversion should be at commit %s, instead got %s", hash, last)
126778-	}
126779-	return nil
126780-}
126781diff -urN a/gopls/test/debug/debug_test.go b/gopls/test/debug/debug_test.go
126782--- a/gopls/test/debug/debug_test.go	2000-01-01 00:00:00.000000000 -0000
126783+++ b/gopls/test/debug/debug_test.go	1970-01-01 00:00:00.000000000 +0000
126784@@ -1,141 +0,0 @@
126785-// Copyright 2020 The Go Authors. All rights reserved.
126786-// Use of this source code is governed by a BSD-style
126787-// license that can be found in the LICENSE file.
126788-
126789-package debug_test
126790-
126791-// Provide 'static type checking' of the templates. This guards against changes is various
126792-// gopls datastructures causing template execution to fail. The checking is done by
126793-// the github.com/jba/templatecheck package. Before that is run, the test checks that
126794-// its list of templates and their arguments corresponds to the arguments in
126795-// calls to render(). The test assumes that all uses of templates are done through render().
126796-
126797-import (
126798-	"go/ast"
126799-	"html/template"
126800-	"runtime"
126801-	"sort"
126802-	"strings"
126803-	"testing"
126804-
126805-	"github.com/jba/templatecheck"
126806-	"golang.org/x/tools/go/packages"
126807-	"golang.org/x/tools/gopls/internal/lsp/cache"
126808-	"golang.org/x/tools/gopls/internal/lsp/debug"
126809-)
126810-
126811-var templates = map[string]struct {
126812-	tmpl *template.Template
126813-	data interface{} // a value of the needed type
126814-}{
126815-	"MainTmpl":    {debug.MainTmpl, &debug.Instance{}},
126816-	"DebugTmpl":   {debug.DebugTmpl, nil},
126817-	"RPCTmpl":     {debug.RPCTmpl, &debug.Rpcs{}},
126818-	"TraceTmpl":   {debug.TraceTmpl, debug.TraceResults{}},
126819-	"CacheTmpl":   {debug.CacheTmpl, &cache.Cache{}},
126820-	"SessionTmpl": {debug.SessionTmpl, &cache.Session{}},
126821-	"ViewTmpl":    {debug.ViewTmpl, &cache.View{}},
126822-	"ClientTmpl":  {debug.ClientTmpl, &debug.Client{}},
126823-	"ServerTmpl":  {debug.ServerTmpl, &debug.Server{}},
126824-	"FileTmpl":    {debug.FileTmpl, &cache.Overlay{}},
126825-	"InfoTmpl":    {debug.InfoTmpl, "something"},
126826-	"MemoryTmpl":  {debug.MemoryTmpl, runtime.MemStats{}},
126827-}
126828-
126829-func TestTemplates(t *testing.T) {
126830-	if runtime.GOOS == "android" {
126831-		t.Skip("this test is not supported for Android")
126832-	}
126833-	cfg := &packages.Config{
126834-		Mode: packages.NeedTypesInfo | packages.LoadAllSyntax, // figure out what's necessary PJW
126835-	}
126836-	pkgs, err := packages.Load(cfg, "golang.org/x/tools/gopls/internal/lsp/debug")
126837-	if err != nil {
126838-		t.Fatal(err)
126839-	}
126840-	if len(pkgs) != 1 {
126841-		t.Fatalf("expected a single package, but got %d", len(pkgs))
126842-	}
126843-	p := pkgs[0]
126844-	if len(p.Errors) != 0 {
126845-		t.Fatalf("compiler error, e.g. %v", p.Errors[0])
126846-	}
126847-	// find the calls to render in serve.go
126848-	tree := treeOf(p, "serve.go")
126849-	if tree == nil {
126850-		t.Fatalf("found no syntax tree for %s", "serve.go")
126851-	}
126852-	renders := callsOf(p, tree, "render")
126853-	if len(renders) == 0 {
126854-		t.Fatalf("found no calls to render")
126855-	}
126856-	var found = make(map[string]bool)
126857-	for _, r := range renders {
126858-		if len(r.Args) != 2 {
126859-			// template, func
126860-			t.Fatalf("got %d args, expected 2", len(r.Args))
126861-		}
126862-		t0, ok := p.TypesInfo.Types[r.Args[0]]
126863-		if !ok || !t0.IsValue() || t0.Type.String() != "*html/template.Template" {
126864-			t.Fatalf("no type info for template")
126865-		}
126866-		if id, ok := r.Args[0].(*ast.Ident); !ok {
126867-			t.Errorf("expected *ast.Ident, got %T", r.Args[0])
126868-		} else {
126869-			found[id.Name] = true
126870-		}
126871-	}
126872-	// make sure found and templates have the same templates
126873-	for k := range found {
126874-		if _, ok := templates[k]; !ok {
126875-			t.Errorf("code has template %s, but test does not", k)
126876-		}
126877-	}
126878-	for k := range templates {
126879-		if _, ok := found[k]; !ok {
126880-			t.Errorf("test has template %s, code does not", k)
126881-		}
126882-	}
126883-	// now check all the known templates, in alphabetic order, for determinacy
126884-	keys := []string{}
126885-	for k := range templates {
126886-		keys = append(keys, k)
126887-	}
126888-	sort.Strings(keys)
126889-	for _, k := range keys {
126890-		v := templates[k]
126891-		// the FuncMap is an annoyance; should not be necessary
126892-		if err := templatecheck.CheckHTML(v.tmpl, v.data); err != nil {
126893-			t.Errorf("%s: %v", k, err)
126894-		}
126895-	}
126896-}
126897-
126898-func callsOf(p *packages.Package, tree *ast.File, name string) []*ast.CallExpr {
126899-	var ans []*ast.CallExpr
126900-	f := func(n ast.Node) bool {
126901-		x, ok := n.(*ast.CallExpr)
126902-		if !ok {
126903-			return true
126904-		}
126905-		if y, ok := x.Fun.(*ast.Ident); ok {
126906-			if y.Name == name {
126907-				ans = append(ans, x)
126908-			}
126909-		}
126910-		return true
126911-	}
126912-	ast.Inspect(tree, f)
126913-	return ans
126914-}
126915-
126916-func treeOf(p *packages.Package, fname string) *ast.File {
126917-	for _, tree := range p.Syntax {
126918-		loc := tree.Package
126919-		pos := p.Fset.PositionFor(loc, false)
126920-		if strings.HasSuffix(pos.Filename, fname) {
126921-			return tree
126922-		}
126923-	}
126924-	return nil
126925-}
126926diff -urN a/gopls/test/json_test.go b/gopls/test/json_test.go
126927--- a/gopls/test/json_test.go	2000-01-01 00:00:00.000000000 -0000
126928+++ b/gopls/test/json_test.go	1970-01-01 00:00:00.000000000 +0000
126929@@ -1,140 +0,0 @@
126930-// Copyright 2021 The Go Authors. All rights reserved.
126931-// Use of this source code is governed by a BSD-style
126932-// license that can be found in the LICENSE file.
126933-
126934-package gopls_test
126935-
126936-import (
126937-	"encoding/json"
126938-	"fmt"
126939-	"regexp"
126940-	"strings"
126941-	"testing"
126942-
126943-	"github.com/google/go-cmp/cmp"
126944-	"golang.org/x/tools/gopls/internal/lsp/protocol"
126945-)
126946-
126947-// verify that type errors in Initialize lsp messages don't cause
126948-// any other unmarshalling errors. The code looks at single values and the
126949-// first component of array values. Each occurrence is replaced by something
126950-// of a different type,  the resulting string unmarshalled, and compared to
126951-// the unmarshalling of the unchanged strings. The test passes if there is no
126952-// more than a single difference reported. That is, if changing a single value
126953-// in the message changes no more than a single value in the unmarshalled struct,
126954-// it is safe to ignore *json.UnmarshalTypeError.
126955-
126956-// strings are changed to numbers or bools (true)
126957-// bools are changed to numbers or strings
126958-// numbers are changed to strings or bools
126959-
126960-// a recent Initialize message taken from a log (at some point
126961-// some field incompatibly changed from bool to int32)
126962-const input = `{"processId":46408,"clientInfo":{"name":"Visual Studio Code - Insiders","version":"1.76.0-insider"},"locale":"en-us","rootPath":"/Users/pjw/hakim","rootUri":"file:///Users/pjw/hakim","capabilities":{"workspace":{"applyEdit":true,"workspaceEdit":{"documentChanges":true,"resourceOperations":["create","rename","delete"],"failureHandling":"textOnlyTransactional","normalizesLineEndings":true,"changeAnnotationSupport":{"groupsOnLabel":true}},"configuration":true,"didChangeWatchedFiles":{"dynamicRegistration":true,"relativePatternSupport":true},"symbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"tagSupport":{"valueSet":[1]},"resolveSupport":{"properties":["location.range"]}},"codeLens":{"refreshSupport":true},"executeCommand":{"dynamicRegistration":true},"didChangeConfiguration":{"dynamicRegistration":true},"workspaceFolders":true,"semanticTokens":{"refreshSupport":true},"fileOperations":{"dynamicRegistration":true,"didCreate":true,"didRename":true,"didDelete":true,"willCreate":true,"willRename":true,"willDelete":true},"inlineValue":{"refreshSupport":true},"inlayHint":{"refreshSupport":true},"diagnostics":{"refreshSupport":true}},"textDocument":{"publishDiagnostics":{"relatedInformation":true,"versionSupport":false,"tagSupport":{"valueSet":[1,2]},"codeDescriptionSupport":true,"dataSupport":true},"synchronization":{"dynamicRegistration":true,"willSave":true,"willSaveWaitUntil":true,"didSave":true},"completion":{"dynamicRegistration":true,"contextSupport":true,"completionItem":{"snippetSupport":true,"commitCharactersSupport":true,"documentationFormat":["markdown","plaintext"],"deprecatedSupport":true,"preselectSupport":true,"tagSupport":{"valueSet":[1]},"insertReplaceSupport":true,"resolveSupport":{"properties":["documentation","detail","additionalTextEdits"]},"insertTextModeSupport":{"valueSet":[1,2]},"labelDetailsSupport":true},"insertTextMode":2,"completionItemKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]},"completionList":{"itemDefaults":["commitCharacters","editRange","insertTextFormat","insertTextMode"]}},"hover":{"dynamicRegistration":true,"contentFormat":["markdown","plaintext"]},"signatureHelp":{"dynamicRegistration":true,"signatureInformation":{"documentationFormat":["markdown","plaintext"],"parameterInformation":{"labelOffsetSupport":true},"activeParameterSupport":true},"contextSupport":true},"definition":{"dynamicRegistration":true,"linkSupport":true},"references":{"dynamicRegistration":true},"documentHighlight":{"dynamicRegistration":true},"documentSymbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"hierarchicalDocumentSymbolSupport":true,"tagSupport":{"valueSet":[1]},"labelSupport":true},"codeAction":{"dynamicRegistration":true,"isPreferredSupport":true,"disabledSupport":true,"dataSupport":true,"resolveSupport":{"properties":["edit"]},"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}},"honorsChangeAnnotations":false},"codeLens":{"dynamicRegistration":true},"formatting":{"dynamicRegistration":true},"rangeFormatting":{"dynamicRegistration":true},"onTypeFormatting":{"dynamicRegistration":true},"rename":{"dynamicRegistration":true,"prepareSupport":true,"prepareSupportDefaultBehavior":1,"honorsChangeAnnotations":true},"documentLink":{"dynamicRegistration":true,"tooltipSupport":true},"typeDefinition":{"dynamicRegistration":true,"linkSupport":true},"implementation":{"dynamicRegistration":true,"linkSupport":true},"colorProvider":{"dynamicRegistration":true},"foldingRange":{"dynamicRegistration":true,"rangeLimit":5000,"lineFoldingOnly":true,"foldingRangeKind":{"valueSet":["comment","imports","region"]},"foldingRange":{"collapsedText":false}},"declaration":{"dynamicRegistration":true,"linkSupport":true},"selectionRange":{"dynamicRegistration":true},"callHierarchy":{"dynamicRegistration":true},"semanticTokens":{"dynamicRegistration":true,"tokenTypes":["namespace","type","class","enum","interface","struct","typeParameter","parameter","variable","property","enumMember","event","function","method","macro","keyword","modifier","comment","string","number","regexp","operator","decorator"],"tokenModifiers":["declaration","definition","readonly","static","deprecated","abstract","async","modification","documentation","defaultLibrary"],"formats":["relative"],"requests":{"range":true,"full":{"delta":true}},"multilineTokenSupport":false,"overlappingTokenSupport":false,"serverCancelSupport":true,"augmentsSyntaxTokens":true},"linkedEditingRange":{"dynamicRegistration":true},"typeHierarchy":{"dynamicRegistration":true},"inlineValue":{"dynamicRegistration":true},"inlayHint":{"dynamicRegistration":true,"resolveSupport":{"properties":["tooltip","textEdits","label.tooltip","label.location","label.command"]}},"diagnostic":{"dynamicRegistration":true,"relatedDocumentSupport":false}},"window":{"showMessage":{"messageActionItem":{"additionalPropertiesSupport":true}},"showDocument":{"support":true},"workDoneProgress":true},"general":{"staleRequestSupport":{"cancel":true,"retryOnContentModified":["textDocument/semanticTokens/full","textDocument/semanticTokens/range","textDocument/semanticTokens/full/delta"]},"regularExpressions":{"engine":"ECMAScript","version":"ES2020"},"markdown":{"parser":"marked","version":"1.1.0"},"positionEncodings":["utf-16"]},"notebookDocument":{"synchronization":{"dynamicRegistration":true,"executionSummarySupport":true}}},"initializationOptions":{"usePlaceholders":true,"completionDocumentation":true,"verboseOutput":false,"build.directoryFilters":["-foof","-internal/lsp/protocol/typescript"],"codelenses":{"reference":true,"gc_details":true},"analyses":{"fillstruct":true,"staticcheck":true,"unusedparams":false,"composites":false},"semanticTokens":true,"noSemanticString":true,"noSemanticNumber":true,"templateExtensions":["tmpl","gotmpl"],"ui.completion.matcher":"Fuzzy","ui.inlayhint.hints":{"assignVariableTypes":false,"compositeLiteralFields":false,"compositeLiteralTypes":false,"constantValues":false,"functionTypeParameters":false,"parameterNames":false,"rangeVariableTypes":false},"ui.vulncheck":"Off","allExperiments":true},"trace":"off","workspaceFolders":[{"uri":"file:///Users/pjw/hakim","name":"hakim"}]}`
126963-
126964-type DiffReporter struct {
126965-	path  cmp.Path
126966-	diffs []string
126967-}
126968-
126969-func (r *DiffReporter) PushStep(ps cmp.PathStep) {
126970-	r.path = append(r.path, ps)
126971-}
126972-
126973-func (r *DiffReporter) Report(rs cmp.Result) {
126974-	if !rs.Equal() {
126975-		vx, vy := r.path.Last().Values()
126976-		r.diffs = append(r.diffs, fmt.Sprintf("%#v:\n\t-: %+v\n\t+: %+v\n", r.path, vx, vy))
126977-	}
126978-}
126979-
126980-func (r *DiffReporter) PopStep() {
126981-	r.path = r.path[:len(r.path)-1]
126982-}
126983-
126984-func (r *DiffReporter) String() string {
126985-	return strings.Join(r.diffs, "\n")
126986-}
126987-
126988-func TestStringChanges(t *testing.T) {
126989-	// string as value
126990-	stringLeaf := regexp.MustCompile(`:("[^"]*")`)
126991-	leafs := stringLeaf.FindAllStringSubmatchIndex(input, -1)
126992-	allDeltas(t, leafs, "23", "true")
126993-	// string as first element of array
126994-	stringArray := regexp.MustCompile(`[[]("[^"]*")`)
126995-	arrays := stringArray.FindAllStringSubmatchIndex(input, -1)
126996-	allDeltas(t, arrays, "23", "true")
126997-}
126998-
126999-func TestBoolChanges(t *testing.T) {
127000-	boolLeaf := regexp.MustCompile(`:(true|false)(,|})`)
127001-	leafs := boolLeaf.FindAllStringSubmatchIndex(input, -1)
127002-	allDeltas(t, leafs, "23", `"xx"`)
127003-	boolArray := regexp.MustCompile(`:[[](true|false)(,|])`)
127004-	arrays := boolArray.FindAllStringSubmatchIndex(input, -1)
127005-	allDeltas(t, arrays, "23", `"xx"`)
127006-}
127007-
127008-func TestNumberChanges(t *testing.T) {
127009-	numLeaf := regexp.MustCompile(`:(\d+)(,|})`)
127010-	leafs := numLeaf.FindAllStringSubmatchIndex(input, -1)
127011-	allDeltas(t, leafs, "true", `"xx"`)
127012-	numArray := regexp.MustCompile(`:[[](\d+)(,|])`)
127013-	arrays := numArray.FindAllStringSubmatchIndex(input, -1)
127014-	allDeltas(t, arrays, "true", `"xx"`)
127015-}
127016-
127017-// v is a set of matches. check that substituting any repl never
127018-// creates more than 1 unmarshaling error
127019-func allDeltas(t *testing.T, v [][]int, repls ...string) {
127020-	t.Helper()
127021-	for _, repl := range repls {
127022-		for i, x := range v {
127023-			err := tryChange(x[2], x[3], repl)
127024-			if err != nil {
127025-				t.Errorf("%d:%q %v", i, input[x[2]:x[3]], err)
127026-			}
127027-		}
127028-	}
127029-}
127030-
127031-func tryChange(start, end int, repl string) error {
127032-	var p, q protocol.ParamInitialize
127033-	mod := input[:start] + repl + input[end:]
127034-	excerpt := func() (string, string) {
127035-		a := start - 5
127036-		if a < 0 {
127037-			a = 0
127038-		}
127039-		b := end + 5
127040-		if b > len(input) {
127041-			// trusting repl to be no longer than what it replaces
127042-			b = len(input)
127043-		}
127044-		ma := input[a:b]
127045-		mb := mod[a:b]
127046-		return ma, mb
127047-	}
127048-
127049-	if err := json.Unmarshal([]byte(input), &p); err != nil {
127050-		return fmt.Errorf("%s %v", repl, err)
127051-	}
127052-	switch err := json.Unmarshal([]byte(mod), &q).(type) {
127053-	case nil: //ok
127054-	case *json.UnmarshalTypeError:
127055-		break
127056-	case *protocol.UnmarshalError:
127057-		return nil // cmp.Diff produces several diffs for custom unmrshalers
127058-	default:
127059-		return fmt.Errorf("%T unexpected unmarshal error", err)
127060-	}
127061-
127062-	var r DiffReporter
127063-	cmp.Diff(p, q, cmp.Reporter(&r))
127064-	if len(r.diffs) > 1 { // 0 is possible, e.g., for interface{}
127065-		ma, mb := excerpt()
127066-		return fmt.Errorf("got %d diffs for %q\n%s\n%s", len(r.diffs), repl, ma, mb)
127067-	}
127068-	return nil
127069-}
127070