all: merge master (a297bfd) into gopls-release-branch.0.15

For golang/go#64973

Conflicts:

- gopls/go.mod
- gopls/go.sum

Merge List:

+ 2024-02-06 a297bfd98 go/callgraph/rta: audit for types.Alias safety
+ 2024-02-06 08393e066 cmd/deadcode: audit for types.Alias safety
+ 2024-02-06 37586e4e3 internal/apidiff: audit for types.Alias safety
+ 2024-02-06 6d4ccf2ad gopls/internal/cache: prime goimports cache asynchronously
+ 2024-02-06 8b6359d83 gopls/internal/cache: share goimports state for GOMODCACHE
+ 2024-02-06 2bb7f1c0c gopls/internal/test/integration/bench: improve completion benchmarks
+ 2024-02-06 f6dc1e9b7 internal/imports: merge init and newModuleResolver
+ 2024-02-06 4f6024ea3 internal/gopathwalk: walk directories concurrently
+ 2024-02-06 8fcb5f023 gopls/internal/test/marker: skip on LUCI solaris builders
+ 2024-02-06 08bd7281e gopls/internal/test/integration: add a test for an inner go.work file
+ 2024-02-06 aee2e7643 gopls/internal/settings: deprecate "allowModfileModifications"
+ 2024-02-05 ddb71b012 gopls/internal/cache: remove findWorkspaceModFile
+ 2024-02-05 365517a55 gopls/internal/cache: detect and reinit on workspace vendor changes
+ 2024-02-05 0be034b1e internal/aliases: Adds an internal alias package.
+ 2024-02-05 8efa10c95 internal/imports: add a benchmark for the initial mod cache scan
+ 2024-02-05 df03d7d47 gopls/internal/golang: add missing check for nil funcBody
+ 2024-02-03 a1fbc781c gopls/internal/golang: move Go semantic tokens out of server
+ 2024-02-03 51e3724fe gopls: remove unused parameters
+ 2024-02-03 d6bd2d74f gopls/internal/cache: add assertions for export data inconsistency
+ 2024-02-02 3403ce104 go/internal/gccgoimporter: recognize "any" as a builtin type
+ 2024-02-02 aecdb2d3f gopls/internal/cache: support workspace vendoring
+ 2024-02-02 e80085c40 gopls/internal/golang: downgrade bug.Reportf for missing builtin
+ 2024-02-02 9c4380303 gopls/internal/cache: allow command-line-package >1 CompileGoFiles
+ 2024-02-02 efce0f596 gopls/internal/cache/metadata: assert graph is acyclic
+ 2024-02-02 c3f60b787 gopls/internal/golang: hover: show embedded fields
+ 2024-02-02 85146f5b4 gopls/internal/lsp/source: highlight returns correctly
+ 2024-02-02 e211e0f09 gopls: enable crashmonitor for unexpected crashes
+ 2024-02-01 d07788857 gopls: update third party dependencies
+ 2024-02-01 2e15dc7cd gopls/internal/test/marker: reject "module testdata"
+ 2024-02-01 c07f92765 cmd/deadcode: enable crash reporting
+ 2024-02-01 44aed241f gopls/internal/analysis/undeclaredname: improve fix name
+ 2024-02-01 afe526599 go/packages: wait for sizes goroutine on all control paths
+ 2024-02-01 425078335 refactor/eg: don't use cgo in Test
+ 2024-02-01 1efbdde36 cmd/stringer, go/loader: use testenv.NeedsTool(t, "cgo")
+ 2024-01-31 5f9069195 go/buildutil: permit comma delimiters in build tags
+ 2024-01-31 0c80ba376 internal/imports: remove the unused ProcessEnv.ModFile field
+ 2024-01-31 c046c5b69 gopls/internal/test/marker/testdata: move test to correct location
+ 2024-01-31 da7ed6494 gopls/internal/cache/imports: simplify importsState invalidation
+ 2024-01-30 7ec8ac08d gopls/internal/golang: hover: show type's methods after doc comment
+ 2024-01-29 0e1f5be92 gopls: update x/telemetry dependency
+ 2024-01-29 341c0434d gopls/internal/test/integration/bench: fix broken benchmarks
+ 2024-01-29 b048cf126 cmd/callgraph: unskip TestCallgraph on windows/arm64
+ 2024-01-29 14d7f7b65 gopls/internal/cache: memoize the view filter func
+ 2024-01-29 5e1643725 gopls/internal/cache: skip TestZeroConfigAlgorithm on wasm
+ 2024-01-29 dd0f88f02 gopls/doc/emacs.md: explain how to organize imports automatically
+ 2024-01-25 3d49bd525 internal/lsp: publish protocol.UnmarshalJSON
+ 2024-01-24 35d8b1b59 gopls/internal/golang: don't bug.Report repaired ASTs in hover
+ 2024-01-24 8174727b3 gopls/internal/test: await quiescence in TestInconsistentVendoring
+ 2024-01-24 df2fa1e99 gopls/doc: s/source/golang/ in the SVG file
+ 2024-01-24 238800b70 gopls: manual tweaks after the lsp/ -> . rename
+ 2024-01-24 95c6ac4a5 gopls/internal/protocol/command: move from ../lsp
+ 2024-01-24 6d109d113 gopls/internal/protocol: move out of lsp/
+ 2024-01-24 f872b3d6f gopls/internal/cache: move out of lsp/
+ 2024-01-24 6823da4bc gopls/internal/golang: move from lsp/source
+ 2024-01-23 129144e6c gopls/internal/lsprpc: move out of lsp/
+ 2024-01-23 eed199759 gopls: use relative watched file patterns if supported
+ 2024-01-23 fa791ac34 gopls/internal/progress: simplify API
+ 2024-01-23 816dcdfba go/packages: add test for flake observed on Android
+ 2024-01-23 d5e76f13c gopls/internal/progress: move from lsp/
+ 2024-01-23 6fe9326ff gopls/internal/telemetry/cmd/stacks: include client name in report
+ 2024-01-23 6a58b9848 gopls/internal/lsp/lsprpc: radically reduce API
+ 2024-01-23 0ffb1d053 gopls/doc: add Helix editor documentation for gopls
+ 2024-01-23 c16e22246 gopls/internal/test/integration: add regtest for hover crash
+ 2024-01-23 bd547e596 gopls/internal/lsp/cache: clean up public API
+ 2024-01-22 4c532679b gopls/internal/lsp/cache: don't report a bug for standalone test files
+ 2024-01-22 a49867fe1 internal/imports: don't add imports that shadow predeclared names
+ 2024-01-22 e2ca5942a gopls/internal/lsp/source: address problems detected by staticcheck
+ 2024-01-22 94d99e340 gopls/internal/test/marker: re-enable some tests
+ 2024-01-22 060c748a2 gopls: consolidate analyzers, eliminating "convenience" analyzers
+ 2024-01-22 7f6ec23c6 go/ssa: suppress go/packages-based test on android
+ 2024-01-22 a987ef7ae go/packages: publish Driver{Request,Response}
+ 2024-01-19 e1555a36d go/ssa: add Function.DomPostorder
+ 2024-01-19 cd7b5109b gopls/internal/lsp/cache: allow versions of form "go1.2.3"
+ 2024-01-19 d0930dbc1 gopls/internal/lsp/cache: fix bug reports from toGobDiagnostics
+ 2024-01-19 1871a2e93 gopls/internal/lsp/source: move Go CodeActions logic from server
+ 2024-01-19 afcd676c5 gopls/internal/lsp/source: show promoted methods in hover
+ 2024-01-19 525acd127 go/analysis/internal/analysisflags: add RelatedInformation JSON
+ 2024-01-19 c7ccb5172 gopls/doc/design: rewrite the architecture overview
+ 2024-01-19 39a254580 gopls/internal/version: amend the year in a recent copyright header
+ 2024-01-19 186fcf30e gopls/internal/lsp/source: factor edit conversion utils
+ 2024-01-19 83c6c25d3 gopls/internal/server: analyze widest packages for open files
+ 2024-01-19 c467be361 gopls: add a main.version variable to override the version at linktime
+ 2024-01-19 6673e7a46 gopls/internal/lsp/source/completion: infer parameter types
+ 2024-01-18 3458e0c56 gopls/internal/lsp/source: fix Fix titles
+ 2024-01-18 72a36a788 gopls/internal/test/marker: fix test breakage due to semantic conflict
+ 2024-01-18 470afdaa8 gopls/internal/analysis/unusedparams: eliminate false positives
+ 2024-01-18 592d9e1e8 internal/lsp: convert refactor code actions to use codeAction/resolve
+ 2024-01-17 f2d3f78aa gopls/internal/lsp/protocol: fix TestURIFromPath on windows
+ 2024-01-17 d2200d1bd gopls/internal/test/marker: update skip comment for addgowork.txt
+ 2024-01-17 c0db45fb1 gopls/internal/server: simplify DiagnoseFiles to avoid a race
+ 2024-01-17 0d1b47829 gopls/internal/test/integration: fix flakiness of TestResolveImportCycle
+ 2024-01-17 d51711299 gopls/internal/lsp/protocol: deliver log messages in order
+ 2024-01-12 9164f2aed gopls/internal/test/marker: skip on solaris-amd64-oraclerel
+ 2024-01-12 dbc9d3e95 internal/analysisinternal: TypeExpr: don't forget Variadic
+ 2024-01-12 54cf5bc0a internal/debug: show new View information in the debug page
+ 2024-01-12 b37fde9dc gopls: simplify gopls command configuration
+ 2024-01-12 6a0605d4e gopls/internal/test/marker: regenerate golden data
+ 2024-01-11 f572b7efa gopls/internal/lsp/source/stub: trim version suffix from module path
+ 2024-01-11 0b1f1d4bc gopls/internal/lsp/cache: (re-)ensure clean shutdown
+ 2024-01-10 706525de5 gopls/internal/lsp/source/completion: support postfix completion (iferr,
+ 2024-01-09 581c0b357 gopls/internal/lsp/source: add receiver name to stubbed methods
+ 2024-01-08 c95fa0ff4 gopls/internal/test: skip marker tests on darwin builders if -short
+ 2024-01-08 25a0e9d3e go.mod: update golang.org/x dependencies
+ 2024-01-05 c9c95f97f internal/refactor/inline: improve a confusing error message
+ 2024-01-05 ba8672b53 go/analysis/passes/unusedresult: add functions from slices package

Change-Id: I428339a4a66ce849c3a3f8827da47125218bb121
diff --git a/cmd/callgraph/main_test.go b/cmd/callgraph/main_test.go
index afcb7a9..ce63413 100644
--- a/cmd/callgraph/main_test.go
+++ b/cmd/callgraph/main_test.go
@@ -15,7 +15,6 @@
 	"log"
 	"os"
 	"path/filepath"
-	"runtime"
 	"strings"
 	"testing"
 
@@ -35,10 +34,6 @@
 }
 
 func TestCallgraph(t *testing.T) {
-	if runtime.GOOS == "windows" && runtime.GOARCH == "arm64" {
-		t.Skipf("skipping due to suspected file corruption bug on windows/arm64 (https://go.dev/issue/50706)")
-	}
-
 	testenv.NeedsTool(t, "go")
 
 	gopath, err := filepath.Abs("testdata")
diff --git a/cmd/deadcode/deadcode.go b/cmd/deadcode/deadcode.go
index da1c204..8ee439b 100644
--- a/cmd/deadcode/deadcode.go
+++ b/cmd/deadcode/deadcode.go
@@ -26,11 +26,14 @@
 	"strings"
 	"text/template"
 
+	"golang.org/x/telemetry/counter"
+	"golang.org/x/telemetry/crashmonitor"
 	"golang.org/x/tools/go/callgraph"
 	"golang.org/x/tools/go/callgraph/rta"
 	"golang.org/x/tools/go/packages"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/internal/aliases"
 )
 
 //go:embed doc.go
@@ -62,6 +65,9 @@
 }
 
 func main() {
+	counter.Open()       // Enable telemetry counter writing.
+	crashmonitor.Start() // Enable crash reporting watchdog.
+
 	log.SetPrefix("deadcode: ")
 	log.SetFlags(0) // no time prefix
 
@@ -380,10 +386,10 @@
 		// method receiver?
 		if recv := fn.Signature.Recv(); recv != nil {
 			t := recv.Type()
-			if ptr, ok := t.(*types.Pointer); ok {
+			if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok {
 				t = ptr.Elem()
 			}
-			buf.WriteString(t.(*types.Named).Obj().Name())
+			buf.WriteString(aliases.Unalias(t).(*types.Named).Obj().Name())
 			buf.WriteByte('.')
 		}
 
diff --git a/cmd/deadcode/doc.go b/cmd/deadcode/doc.go
index edc8dfd..66a150d 100644
--- a/cmd/deadcode/doc.go
+++ b/cmd/deadcode/doc.go
@@ -63,7 +63,7 @@
 function in the form of a typical compiler diagnostic, for example:
 
 	$ deadcode -f='{{range .Funcs}}{{println .Position}}{{end}}' -test ./gopls/...
-	gopls/internal/lsp/command.go:1206:6: unreachable func: openClientEditor
+	gopls/internal/protocol/command.go:1206:6: unreachable func: openClientEditor
 	gopls/internal/template/parse.go:414:18: unreachable func: Parsed.WriteNode
 	gopls/internal/template/parse.go:419:18: unreachable func: wrNode.writeNode
 
diff --git a/cmd/stringer/endtoend_test.go b/cmd/stringer/endtoend_test.go
index e68b612..2b9afa3 100644
--- a/cmd/stringer/endtoend_test.go
+++ b/cmd/stringer/endtoend_test.go
@@ -13,7 +13,6 @@
 	"bytes"
 	"flag"
 	"fmt"
-	"go/build"
 	"io"
 	"os"
 	"path"
@@ -50,6 +49,8 @@
 }
 
 func TestEndToEnd(t *testing.T) {
+	testenv.NeedsTool(t, "go")
+
 	stringer := stringerPath(t)
 	// Read the testdata directory.
 	fd, err := os.Open("testdata")
@@ -76,8 +77,8 @@
 			continue
 		}
 		t.Run(name, func(t *testing.T) {
-			if name == "cgo.go" && !build.Default.CgoEnabled {
-				t.Skipf("cgo is not enabled for %s", name)
+			if name == "cgo.go" {
+				testenv.NeedsTool(t, "cgo")
 			}
 			stringerCompileAndRun(t, t.TempDir(), stringer, typeName(name), name)
 		})
@@ -155,6 +156,8 @@
 // TestConstValueChange verifies that if a constant value changes and
 // the stringer code is not regenerated, we'll get a compiler error.
 func TestConstValueChange(t *testing.T) {
+	testenv.NeedsTool(t, "go")
+
 	stringer := stringerPath(t)
 	dir := t.TempDir()
 	source := filepath.Join(dir, "day.go")
diff --git a/copyright/copyright.go b/copyright/copyright.go
index c084bd0..b13b56e 100644
--- a/copyright/copyright.go
+++ b/copyright/copyright.go
@@ -94,7 +94,7 @@
 	return shouldAddCopyright, nil
 }
 
-// Copied from golang.org/x/tools/gopls/internal/lsp/source/util.go.
+// Copied from golang.org/x/tools/gopls/internal/golang/util.go.
 // Matches cgo generated comment as well as the proposed standard:
 //
 //	https://golang.org/s/generatedcode
diff --git a/go.mod b/go.mod
index 0f57d67..fb7bcfc 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,12 @@
 require (
 	github.com/yuin/goldmark v1.4.13
 	golang.org/x/mod v0.14.0
-	golang.org/x/net v0.19.0
+	golang.org/x/net v0.20.0
 )
 
-require golang.org/x/sync v0.5.0
+require golang.org/x/sync v0.6.0
+
+require (
+	golang.org/x/sys v0.16.0 // indirect
+	golang.org/x/telemetry v0.0.0-20240201224847-0a1d30dda509
+)
diff --git a/go.sum b/go.sum
index cb917ea..f30cef7 100644
--- a/go.sum
+++ b/go.sum
@@ -2,7 +2,11 @@
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
 golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
-golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
-golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
-golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
+golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
+golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
+golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/telemetry v0.0.0-20240201224847-0a1d30dda509 h1:Nr7eTQpQZ/ytesxDJpQgaf0t4sdLnnDtAbmtViTrSUo=
+golang.org/x/telemetry v0.0.0-20240201224847-0a1d30dda509/go.mod h1:ZthVHHkOi8rlMEsfFr3Ie42Ym1NonbFNNRKW3ci0UrU=
diff --git a/go/analysis/diagnostic.go b/go/analysis/diagnostic.go
index f67c972..c638f27 100644
--- a/go/analysis/diagnostic.go
+++ b/go/analysis/diagnostic.go
@@ -31,14 +31,14 @@
 	// see https://pkg.go.dev/net/url#URL.ResolveReference.
 	URL string
 
-	// SuggestedFixes contains suggested fixes for a diagnostic
-	// which can be used to perform edits to a file that address
-	// the diagnostic.
-	//
-	// Diagnostics should not contain SuggestedFixes that overlap.
-	SuggestedFixes []SuggestedFix // optional
+	// SuggestedFixes is an optional list of fixes to address the
+	// problem described by the diagnostic, each one representing
+	// an alternative strategy; at most one may be applied.
+	SuggestedFixes []SuggestedFix
 
-	Related []RelatedInformation // optional
+	// Related contains optional secondary positions and messages
+	// related to the primary diagnostic.
+	Related []RelatedInformation
 }
 
 // RelatedInformation contains information related to a diagnostic.
@@ -55,8 +55,7 @@
 // user can choose to apply to their code. Usually the SuggestedFix is
 // meant to fix the issue flagged by the diagnostic.
 //
-// TextEdits for a SuggestedFix should not overlap,
-// nor contain edits for other packages.
+// The TextEdits must not overlap, nor contain edits for other packages.
 type SuggestedFix struct {
 	// A description for this suggested fix to be shown to a user deciding
 	// whether to accept it.
diff --git a/go/analysis/internal/analysisflags/flags.go b/go/analysis/internal/analysisflags/flags.go
index 9e3fde7..ff14ff5 100644
--- a/go/analysis/internal/analysisflags/flags.go
+++ b/go/analysis/internal/analysisflags/flags.go
@@ -362,15 +362,24 @@
 	Edits   []JSONTextEdit `json:"edits"`
 }
 
-// A JSONDiagnostic can be used to encode and decode analysis.Diagnostics to and
-// from JSON.
-// TODO(matloob): Should the JSON diagnostics contain ranges?
-// If so, how should they be formatted?
+// A JSONDiagnostic describes the JSON schema of an analysis.Diagnostic.
+//
+// TODO(matloob): include End position if present.
 type JSONDiagnostic struct {
-	Category       string             `json:"category,omitempty"`
-	Posn           string             `json:"posn"`
-	Message        string             `json:"message"`
-	SuggestedFixes []JSONSuggestedFix `json:"suggested_fixes,omitempty"`
+	Category       string                   `json:"category,omitempty"`
+	Posn           string                   `json:"posn"` // e.g. "file.go:line:column"
+	Message        string                   `json:"message"`
+	SuggestedFixes []JSONSuggestedFix       `json:"suggested_fixes,omitempty"`
+	Related        []JSONRelatedInformation `json:"related,omitempty"`
+}
+
+// A JSONRelated describes a secondary position and message related to
+// a primary diagnostic.
+//
+// TODO(adonovan): include End position if present.
+type JSONRelatedInformation struct {
+	Posn    string `json:"posn"` // e.g. "file.go:line:column"
+	Message string `json:"message"`
 }
 
 // Add adds the result of analysis 'name' on package 'id'.
@@ -401,11 +410,19 @@
 					Edits:   edits,
 				})
 			}
+			var related []JSONRelatedInformation
+			for _, r := range f.Related {
+				related = append(related, JSONRelatedInformation{
+					Posn:    fset.Position(r.Pos).String(),
+					Message: r.Message,
+				})
+			}
 			jdiag := JSONDiagnostic{
 				Category:       f.Category,
 				Posn:           fset.Position(f.Pos).String(),
 				Message:        f.Message,
 				SuggestedFixes: fixes,
+				Related:        related,
 			}
 			diagnostics = append(diagnostics, jdiag)
 		}
diff --git a/go/analysis/passes/lostcancel/lostcancel.go b/go/analysis/passes/lostcancel/lostcancel.go
index 2bccb67..bf56a5c 100644
--- a/go/analysis/passes/lostcancel/lostcancel.go
+++ b/go/analysis/passes/lostcancel/lostcancel.go
@@ -172,7 +172,18 @@
 		if ret := lostCancelPath(pass, g, v, stmt, sig); ret != nil {
 			lineno := pass.Fset.Position(stmt.Pos()).Line
 			pass.ReportRangef(stmt, "the %s function is not used on all paths (possible context leak)", v.Name())
-			pass.ReportRangef(ret, "this return statement may be reached without using the %s var defined on line %d", v.Name(), lineno)
+
+			pos, end := ret.Pos(), ret.End()
+			// golang/go#64547: cfg.Block.Return may return a synthetic
+			// ReturnStmt that overflows the file.
+			if pass.Fset.File(pos) != pass.Fset.File(end) {
+				end = pos
+			}
+			pass.Report(analysis.Diagnostic{
+				Pos:     pos,
+				End:     end,
+				Message: fmt.Sprintf("this return statement may be reached without using the %s var defined on line %d", v.Name(), lineno),
+			})
 		}
 	}
 }
diff --git a/go/analysis/passes/unusedresult/unusedresult.go b/go/analysis/passes/unusedresult/unusedresult.go
index 7f79b4a..76f42b0 100644
--- a/go/analysis/passes/unusedresult/unusedresult.go
+++ b/go/analysis/passes/unusedresult/unusedresult.go
@@ -59,7 +59,25 @@
 	// List standard library functions here.
 	// The context.With{Cancel,Deadline,Timeout} entries are
 	// effectively redundant wrt the lostcancel analyzer.
-	funcs.Set("errors.New,fmt.Errorf,fmt.Sprintf,fmt.Sprint,sort.Reverse,context.WithValue,context.WithCancel,context.WithDeadline,context.WithTimeout")
+	funcs = stringSetFlag{
+		"context.WithCancel":   true,
+		"context.WithDeadline": true,
+		"context.WithTimeout":  true,
+		"context.WithValue":    true,
+		"errors.New":           true,
+		"fmt.Errorf":           true,
+		"fmt.Sprint":           true,
+		"fmt.Sprintf":          true,
+		"slices.Clip":          true,
+		"slices.Compact":       true,
+		"slices.CompactFunc":   true,
+		"slices.Delete":        true,
+		"slices.DeleteFunc":    true,
+		"slices.Grow":          true,
+		"slices.Insert":        true,
+		"slices.Replace":       true,
+		"sort.Reverse":         true,
+	}
 	Analyzer.Flags.Var(&funcs, "funcs",
 		"comma-separated list of functions whose results must be used")
 
diff --git a/go/buildutil/tags.go b/go/buildutil/tags.go
index 7cf523b..32c8d14 100644
--- a/go/buildutil/tags.go
+++ b/go/buildutil/tags.go
@@ -4,17 +4,22 @@
 
 package buildutil
 
-// This logic was copied from stringsFlag from $GOROOT/src/cmd/go/build.go.
+// This duplicated logic must be kept in sync with that from go build:
+//   $GOROOT/src/cmd/go/internal/work/build.go (tagsFlag.Set)
+//   $GOROOT/src/cmd/go/internal/base/flag.go (StringsFlag.Set)
+//   $GOROOT/src/cmd/internal/quoted/quoted.go (isSpaceByte, Split)
 
-import "fmt"
+import (
+	"fmt"
+	"strings"
+)
 
 const TagsFlagDoc = "a list of `build tags` to consider satisfied during the build. " +
 	"For more information about build tags, see the description of " +
 	"build constraints in the documentation for the go/build package"
 
 // TagsFlag is an implementation of the flag.Value and flag.Getter interfaces that parses
-// a flag value in the same manner as go build's -tags flag and
-// populates a []string slice.
+// a flag value the same as go build's -tags flag and populates a []string slice.
 //
 // See $GOROOT/src/go/build/doc.go for description of build tags.
 // See $GOROOT/src/cmd/go/doc.go for description of 'go build -tags' flag.
@@ -25,19 +30,32 @@
 type TagsFlag []string
 
 func (v *TagsFlag) Set(s string) error {
-	var err error
-	*v, err = splitQuotedFields(s)
-	if *v == nil {
-		*v = []string{}
+	// See $GOROOT/src/cmd/go/internal/work/build.go (tagsFlag.Set)
+	// For compatibility with Go 1.12 and earlier, allow "-tags='a b c'" or even just "-tags='a'".
+	if strings.Contains(s, " ") || strings.Contains(s, "'") {
+		var err error
+		*v, err = splitQuotedFields(s)
+		if *v == nil {
+			*v = []string{}
+		}
+		return err
 	}
-	return err
+
+	// Starting in Go 1.13, the -tags flag is a comma-separated list of build tags.
+	*v = []string{}
+	for _, s := range strings.Split(s, ",") {
+		if s != "" {
+			*v = append(*v, s)
+		}
+	}
+	return nil
 }
 
 func (v *TagsFlag) Get() interface{} { return *v }
 
 func splitQuotedFields(s string) ([]string, error) {
-	// Split fields allowing '' or "" around elements.
-	// Quotes further inside the string do not count.
+	// See $GOROOT/src/cmd/internal/quoted/quoted.go (Split)
+	// This must remain in sync with that logic.
 	var f []string
 	for len(s) > 0 {
 		for len(s) > 0 && isSpaceByte(s[0]) {
@@ -76,5 +94,7 @@
 }
 
 func isSpaceByte(c byte) bool {
+	// See $GOROOT/src/cmd/internal/quoted/quoted.go (isSpaceByte, Split)
+	// This list must remain in sync with that.
 	return c == ' ' || c == '\t' || c == '\n' || c == '\r'
 }
diff --git a/go/buildutil/tags_test.go b/go/buildutil/tags_test.go
index f823431..fb3afbc 100644
--- a/go/buildutil/tags_test.go
+++ b/go/buildutil/tags_test.go
@@ -5,28 +5,124 @@
 package buildutil_test
 
 import (
+	"bytes"
 	"flag"
 	"go/build"
+	"os/exec"
 	"reflect"
+	"strings"
 	"testing"
 
 	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/internal/testenv"
 )
 
 func TestTags(t *testing.T) {
-	f := flag.NewFlagSet("TestTags", flag.PanicOnError)
-	var ctxt build.Context
-	f.Var((*buildutil.TagsFlag)(&ctxt.BuildTags), "tags", buildutil.TagsFlagDoc)
-	f.Parse([]string{"-tags", ` 'one'"two"	'three "four"'`, "rest"})
 
-	// BuildTags
-	want := []string{"one", "two", "three \"four\""}
-	if !reflect.DeepEqual(ctxt.BuildTags, want) {
-		t.Errorf("BuildTags = %q, want %q", ctxt.BuildTags, want)
+	type tagTestCase struct {
+		tags    string
+		want    []string
+		wantErr bool
 	}
 
-	// Args()
-	if want := []string{"rest"}; !reflect.DeepEqual(f.Args(), want) {
-		t.Errorf("f.Args() = %q, want %q", f.Args(), want)
+	for name, tc := range map[string]tagTestCase{
+		// Normal valid cases
+		"empty": {
+			tags: "",
+			want: []string{},
+		},
+		"commas": {
+			tags: "tag1,tag_2,🐹,tag/3,tag-4",
+			want: []string{"tag1", "tag_2", "🐹", "tag/3", "tag-4"},
+		},
+		"delimiters are spaces": {
+			tags: "a b\tc\rd\ne",
+			want: []string{"a", "b", "c", "d", "e"},
+		},
+		"old quote and space form": {
+			tags: "'a' 'b' 'c'",
+			want: []string{"a", "b", "c"},
+		},
+
+		// Normal error cases
+		"unterminated": {
+			tags:    `"missing closing quote`,
+			want:    []string{},
+			wantErr: true,
+		},
+		"unterminated single": {
+			tags:    `'missing closing quote`,
+			want:    []string{},
+			wantErr: true,
+		},
+
+		// Maybe surprising difference for unterminated quotes, no spaces
+		"unterminated no spaces": {
+			tags: `"missing_closing_quote`,
+			want: []string{"\"missing_closing_quote"},
+		},
+		"unterminated no spaces single": {
+			tags:    `'missing_closing_quote`,
+			want:    []string{},
+			wantErr: true,
+		},
+
+		// Permitted but not recommended
+		"delimiters contiguous spaces": {
+			tags: "a \t\r\n, b \t\r\nc,d\te\tf",
+			want: []string{"a", ",", "b", "c,d", "e", "f"},
+		},
+		"quotes and spaces": {
+			tags: ` 'one'"two"	'three "four"'`,
+			want: []string{"one", "two", "three \"four\""},
+		},
+		"quotes single no spaces": {
+			tags: `'t1','t2',"t3"`,
+			want: []string{"t1", ",'t2',\"t3\""},
+		},
+		"quotes double no spaces": {
+			tags: `"t1","t2","t3"`,
+			want: []string{`"t1"`, `"t2"`, `"t3"`},
+		},
+	} {
+		t.Run(name, func(t *testing.T) {
+			f := flag.NewFlagSet("TestTags", flag.ContinueOnError)
+			var ctxt build.Context
+			f.Var((*buildutil.TagsFlag)(&ctxt.BuildTags), "tags", buildutil.TagsFlagDoc)
+
+			// Normal case valid parsed tags
+			f.Parse([]string{"-tags", tc.tags, "rest"})
+
+			// BuildTags
+			if !reflect.DeepEqual(ctxt.BuildTags, tc.want) {
+				t.Errorf("Case = %s, BuildTags = %q, want %q", name, ctxt.BuildTags, tc.want)
+			}
+
+			// Args()
+			if want := []string{"rest"}; !reflect.DeepEqual(f.Args(), want) {
+				t.Errorf("Case = %s, f.Args() = %q, want %q", name, f.Args(), want)
+			}
+
+			// Regression check against base go tooling
+			cmd := testenv.Command(t, "go", "list", "-f", "{{context.BuildTags}}", "-tags", tc.tags, ".")
+			var out bytes.Buffer
+			cmd.Stdout = &out
+			if err := cmd.Run(); err != nil {
+				if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
+					t.Logf("stderr:\n%s", ee.Stderr)
+				}
+				if !tc.wantErr {
+					t.Errorf("%v: %v", cmd, err)
+				}
+			} else if tc.wantErr {
+				t.Errorf("Expected failure for %v", cmd)
+			} else {
+				wantDescription := strings.Join(tc.want, " ")
+				output := strings.Trim(strings.TrimSuffix(out.String(), "\n"), "[]")
+				if output != wantDescription {
+					t.Errorf("Output = %s, want %s", output, wantDescription)
+				}
+			}
+		})
 	}
 }
diff --git a/go/callgraph/rta/rta.go b/go/callgraph/rta/rta.go
index d0ae0fc..72b383d 100644
--- a/go/callgraph/rta/rta.go
+++ b/go/callgraph/rta/rta.go
@@ -45,6 +45,7 @@
 	"golang.org/x/tools/go/callgraph"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/tools/internal/aliases"
 	"golang.org/x/tools/internal/compat"
 )
 
@@ -416,6 +417,9 @@
 // dynamic type of some interface or reflect.Value.
 // Adapted from needMethods in go/ssa/builder.go
 func (r *rta) addRuntimeType(T types.Type, skip bool) {
+	// Never record aliases.
+	T = aliases.Unalias(T)
+
 	if prev, ok := r.result.RuntimeTypes.At(T).(bool); ok {
 		if skip && !prev {
 			r.result.RuntimeTypes.Set(T, skip)
@@ -457,7 +461,7 @@
 	case *types.Named:
 		n = T
 	case *types.Pointer:
-		n, _ = T.Elem().(*types.Named)
+		n, _ = aliases.Unalias(T.Elem()).(*types.Named)
 	}
 	if n != nil {
 		owner := n.Obj().Pkg()
@@ -476,6 +480,9 @@
 	}
 
 	switch t := T.(type) {
+	case *aliases.Alias:
+		panic("unreachable")
+
 	case *types.Basic:
 		// nop
 
diff --git a/go/callgraph/rta/rta_test.go b/go/callgraph/rta/rta_test.go
index a855dd6..8552dc7 100644
--- a/go/callgraph/rta/rta_test.go
+++ b/go/callgraph/rta/rta_test.go
@@ -23,6 +23,7 @@
 	"golang.org/x/tools/go/loader"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/internal/aliases"
 )
 
 // TestRTA runs RTA on each testdata/*.go file and compares the
@@ -200,7 +201,7 @@
 		got := make(stringset)
 		res.RuntimeTypes.Iterate(func(key types.Type, value interface{}) {
 			if !value.(bool) { // accessible to reflection
-				typ := types.TypeString(key, types.RelativeTo(pkg.Pkg))
+				typ := types.TypeString(aliases.Unalias(key), types.RelativeTo(pkg.Pkg))
 				got[typ] = true
 			}
 		})
diff --git a/go/cfg/cfg.go b/go/cfg/cfg.go
index 37d799f..e9c48d5 100644
--- a/go/cfg/cfg.go
+++ b/go/cfg/cfg.go
@@ -113,7 +113,11 @@
 	return fmt.Sprintf("block %d (%s)", b.Index, b.comment)
 }
 
-// Return returns the return statement at the end of this block if present, nil otherwise.
+// Return returns the return statement at the end of this block if present, nil
+// otherwise.
+//
+// When control falls off the end of the function, the ReturnStmt is synthetic
+// and its [ast.Node.End] position may be beyond the end of the file.
 func (b *Block) Return() (ret *ast.ReturnStmt) {
 	if len(b.Nodes) > 0 {
 		ret, _ = b.Nodes[len(b.Nodes)-1].(*ast.ReturnStmt)
diff --git a/go/internal/gccgoimporter/parser.go b/go/internal/gccgoimporter/parser.go
index 9fdb6f8..72bbe79 100644
--- a/go/internal/gccgoimporter/parser.go
+++ b/go/internal/gccgoimporter/parser.go
@@ -950,6 +950,7 @@
 	gccgoBuiltinERROR      = 19
 	gccgoBuiltinBYTE       = 20
 	gccgoBuiltinRUNE       = 21
+	gccgoBuiltinANY        = 22
 )
 
 func lookupBuiltinType(typ int) types.Type {
@@ -974,6 +975,7 @@
 		gccgoBuiltinERROR:      types.Universe.Lookup("error").Type(),
 		gccgoBuiltinBYTE:       types.Universe.Lookup("byte").Type(),
 		gccgoBuiltinRUNE:       types.Universe.Lookup("rune").Type(),
+		gccgoBuiltinANY:        types.Universe.Lookup("any").Type(),
 	}[typ]
 }
 
diff --git a/go/loader/loader_test.go b/go/loader/loader_test.go
index cab2217..1e0b16e 100644
--- a/go/loader/loader_test.go
+++ b/go/loader/loader_test.go
@@ -837,6 +837,7 @@
 
 func TestCgoCwdIssue46877(t *testing.T) {
 	testenv.NeedsTool(t, "go")
+	testenv.NeedsTool(t, "cgo")
 	var conf loader.Config
 	conf.Import("golang.org/x/tools/go/loader/testdata/issue46877")
 	if _, err := conf.Load(); err != nil {
diff --git a/go/loader/stdlib_test.go b/go/loader/stdlib_test.go
index 83d70da..ef51325 100644
--- a/go/loader/stdlib_test.go
+++ b/go/loader/stdlib_test.go
@@ -130,13 +130,11 @@
 	case "darwin":
 		t.Skipf("golang/go#58493: file locations in this test are stale on darwin")
 	}
+	testenv.NeedsTool(t, "go")
 	// In nocgo builds (e.g. linux-amd64-nocgo),
 	// there is no "runtime/cgo" package,
 	// so cgo-generated Go files will have a failing import.
-	if !build.Default.CgoEnabled {
-		return
-	}
-	testenv.NeedsTool(t, "go")
+	testenv.NeedsTool(t, "cgo")
 
 	// Test that we can load cgo-using packages with
 	// CGO_ENABLED=[01], which causes go/build to select pure
diff --git a/go/packages/doc.go b/go/packages/doc.go
index b2a0b7c..a8d7b06 100644
--- a/go/packages/doc.go
+++ b/go/packages/doc.go
@@ -15,22 +15,10 @@
 The default build tool is the go command.
 Its supported patterns are described at
 https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns.
+Other build systems may be supported by providing a "driver";
+see [The driver protocol].
 
-Load may be used in Go projects that use alternative build systems, by
-installing an appropriate "driver" program for the build system and
-specifying its location in the GOPACKAGESDRIVER environment variable.
-For example,
-https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration
-explains how to use the driver for Bazel.
-The driver program is responsible for interpreting patterns in its
-preferred notation and reporting information about the packages that
-they identify.
-(See driverRequest and driverResponse types for the JSON
-schema used by the protocol.
-Though the protocol is supported, these types are currently unexported;
-see #64608 for a proposal to publish them.)
-
-Regardless of driver, all patterns with the prefix "query=", where query is a
+All patterns with the prefix "query=", where query is a
 non-empty string of letters from [a-z], are reserved and may be
 interpreted as query operators.
 
@@ -86,7 +74,29 @@
 Most tools should pass their command-line arguments (after any flags)
 uninterpreted to [Load], so that it can interpret them
 according to the conventions of the underlying build system.
+
 See the Example function for typical usage.
+
+# The driver protocol
+
+[Load] may be used to load Go packages even in Go projects that use
+alternative build systems, by installing an appropriate "driver"
+program for the build system and specifying its location in the
+GOPACKAGESDRIVER environment variable.
+For example,
+https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration
+explains how to use the driver for Bazel.
+
+The driver program is responsible for interpreting patterns in its
+preferred notation and reporting information about the packages that
+those patterns identify. Drivers must also support the special "file="
+and "pattern=" patterns described above.
+
+The patterns are provided as positional command-line arguments. A
+JSON-encoded [DriverRequest] message providing additional information
+is written to the driver's standard input. The driver must write a
+JSON-encoded [DriverResponse] message to its standard output. (This
+message differs from the JSON schema produced by 'go list'.)
 */
 package packages // import "golang.org/x/tools/go/packages"
 
diff --git a/go/packages/external.go b/go/packages/external.go
index 7db1d12..4335c1e 100644
--- a/go/packages/external.go
+++ b/go/packages/external.go
@@ -2,12 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This file enables an external tool to intercept package requests.
-// If the tool is present then its results are used in preference to
-// the go list command.
-
 package packages
 
+// This file defines the protocol that enables an external "driver"
+// tool to supply package metadata in place of 'go list'.
+
 import (
 	"bytes"
 	"encoding/json"
@@ -17,31 +16,71 @@
 	"strings"
 )
 
-// The Driver Protocol
+// DriverRequest defines the schema of a request for package metadata
+// from an external driver program. The JSON-encoded DriverRequest
+// message is provided to the driver program's standard input. The
+// query patterns are provided as command-line arguments.
 //
-// The driver, given the inputs to a call to Load, returns metadata about the packages specified.
-// This allows for different build systems to support go/packages by telling go/packages how the
-// packages' source is organized.
-// The driver is a binary, either specified by the GOPACKAGESDRIVER environment variable or in
-// the path as gopackagesdriver. It's given the inputs to load in its argv. See the package
-// documentation in doc.go for the full description of the patterns that need to be supported.
-// A driver receives as a JSON-serialized driverRequest struct in standard input and will
-// produce a JSON-serialized driverResponse (see definition in packages.go) in its standard output.
-
-// driverRequest is used to provide the portion of Load's Config that is needed by a driver.
-type driverRequest struct {
+// See the package documentation for an overview.
+type DriverRequest struct {
 	Mode LoadMode `json:"mode"`
+
 	// Env specifies the environment the underlying build system should be run in.
 	Env []string `json:"env"`
+
 	// BuildFlags are flags that should be passed to the underlying build system.
 	BuildFlags []string `json:"build_flags"`
+
 	// Tests specifies whether the patterns should also return test packages.
 	Tests bool `json:"tests"`
+
 	// Overlay maps file paths (relative to the driver's working directory) to the byte contents
 	// of overlay files.
 	Overlay map[string][]byte `json:"overlay"`
 }
 
+// DriverResponse defines the schema of a response from an external
+// driver program, providing the results of a query for package
+// metadata. The driver program must write a JSON-encoded
+// DriverResponse message to its standard output.
+//
+// See the package documentation for an overview.
+type DriverResponse struct {
+	// NotHandled is returned if the request can't be handled by the current
+	// driver. If an external driver returns a response with NotHandled, the
+	// rest of the DriverResponse is ignored, and go/packages will fallback
+	// to the next driver. If go/packages is extended in the future to support
+	// lists of multiple drivers, go/packages will fall back to the next driver.
+	NotHandled bool
+
+	// Compiler and Arch are the arguments pass of types.SizesFor
+	// to get a types.Sizes to use when type checking.
+	Compiler string
+	Arch     string
+
+	// Roots is the set of package IDs that make up the root packages.
+	// We have to encode this separately because when we encode a single package
+	// we cannot know if it is one of the roots as that requires knowledge of the
+	// graph it is part of.
+	Roots []string `json:",omitempty"`
+
+	// Packages is the full set of packages in the graph.
+	// The packages are not connected into a graph.
+	// The Imports if populated will be stubs that only have their ID set.
+	// Imports will be connected and then type and syntax information added in a
+	// later pass (see refine).
+	Packages []*Package
+
+	// GoVersion is the minor version number used by the driver
+	// (e.g. the go command on the PATH) when selecting .go files.
+	// Zero means unknown.
+	GoVersion int
+}
+
+// driver is the type for functions that query the build system for the
+// packages named by the patterns.
+type driver func(cfg *Config, patterns ...string) (*DriverResponse, error)
+
 // findExternalDriver returns the file path of a tool that supplies
 // the build system package structure, or "" if not found."
 // If GOPACKAGESDRIVER is set in the environment findExternalTool returns its
@@ -64,8 +103,8 @@
 			return nil
 		}
 	}
-	return func(cfg *Config, words ...string) (*driverResponse, error) {
-		req, err := json.Marshal(driverRequest{
+	return func(cfg *Config, words ...string) (*DriverResponse, error) {
+		req, err := json.Marshal(DriverRequest{
 			Mode:       cfg.Mode,
 			Env:        cfg.Env,
 			BuildFlags: cfg.BuildFlags,
@@ -92,7 +131,7 @@
 			fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd), stderr)
 		}
 
-		var response driverResponse
+		var response DriverResponse
 		if err := json.Unmarshal(buf.Bytes(), &response); err != nil {
 			return nil, err
 		}
diff --git a/go/packages/golist.go b/go/packages/golist.go
index cd375fb..22305d9 100644
--- a/go/packages/golist.go
+++ b/go/packages/golist.go
@@ -35,23 +35,23 @@
 	error
 }
 
-// responseDeduper wraps a driverResponse, deduplicating its contents.
+// responseDeduper wraps a DriverResponse, deduplicating its contents.
 type responseDeduper struct {
 	seenRoots    map[string]bool
 	seenPackages map[string]*Package
-	dr           *driverResponse
+	dr           *DriverResponse
 }
 
 func newDeduper() *responseDeduper {
 	return &responseDeduper{
-		dr:           &driverResponse{},
+		dr:           &DriverResponse{},
 		seenRoots:    map[string]bool{},
 		seenPackages: map[string]*Package{},
 	}
 }
 
-// addAll fills in r with a driverResponse.
-func (r *responseDeduper) addAll(dr *driverResponse) {
+// addAll fills in r with a DriverResponse.
+func (r *responseDeduper) addAll(dr *DriverResponse) {
 	for _, pkg := range dr.Packages {
 		r.addPackage(pkg)
 	}
@@ -128,7 +128,7 @@
 // goListDriver uses the go list command to interpret the patterns and produce
 // the build system package structure.
 // See driver for more details.
-func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
+func goListDriver(cfg *Config, patterns ...string) (_ *DriverResponse, err error) {
 	// Make sure that any asynchronous go commands are killed when we return.
 	parentCtx := cfg.Context
 	if parentCtx == nil {
@@ -146,16 +146,18 @@
 	}
 
 	// Fill in response.Sizes asynchronously if necessary.
-	var sizeserr error
-	var sizeswg sync.WaitGroup
 	if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 {
-		sizeswg.Add(1)
+		errCh := make(chan error)
 		go func() {
 			compiler, arch, err := packagesdriver.GetSizesForArgsGolist(ctx, state.cfgInvocation(), cfg.gocmdRunner)
-			sizeserr = err
 			response.dr.Compiler = compiler
 			response.dr.Arch = arch
-			sizeswg.Done()
+			errCh <- err
+		}()
+		defer func() {
+			if sizesErr := <-errCh; sizesErr != nil {
+				err = sizesErr
+			}
 		}()
 	}
 
@@ -208,10 +210,7 @@
 		}
 	}
 
-	sizeswg.Wait()
-	if sizeserr != nil {
-		return nil, sizeserr
-	}
+	// (We may yet return an error due to defer.)
 	return response.dr, nil
 }
 
@@ -266,7 +265,7 @@
 
 // adhocPackage attempts to load or construct an ad-hoc package for a given
 // query, if the original call to the driver produced inadequate results.
-func (state *golistState) adhocPackage(pattern, query string) (*driverResponse, error) {
+func (state *golistState) adhocPackage(pattern, query string) (*DriverResponse, error) {
 	response, err := state.createDriverResponse(query)
 	if err != nil {
 		return nil, err
@@ -357,7 +356,7 @@
 
 // createDriverResponse uses the "go list" command to expand the pattern
 // words and return a response for the specified packages.
-func (state *golistState) createDriverResponse(words ...string) (*driverResponse, error) {
+func (state *golistState) createDriverResponse(words ...string) (*DriverResponse, error) {
 	// go list uses the following identifiers in ImportPath and Imports:
 	//
 	// 	"p"			-- importable package or main (command)
@@ -384,7 +383,7 @@
 	pkgs := make(map[string]*Package)
 	additionalErrors := make(map[string][]Error)
 	// Decode the JSON and convert it to Package form.
-	response := &driverResponse{
+	response := &DriverResponse{
 		GoVersion: goVersion,
 	}
 	for dec := json.NewDecoder(buf); dec.More(); {
diff --git a/go/packages/packages.go b/go/packages/packages.go
index 81e9e6a..f33b0af 100644
--- a/go/packages/packages.go
+++ b/go/packages/packages.go
@@ -206,43 +206,6 @@
 	Overlay map[string][]byte
 }
 
-// driver is the type for functions that query the build system for the
-// packages named by the patterns.
-type driver func(cfg *Config, patterns ...string) (*driverResponse, error)
-
-// driverResponse contains the results for a driver query.
-type driverResponse struct {
-	// NotHandled is returned if the request can't be handled by the current
-	// driver. If an external driver returns a response with NotHandled, the
-	// rest of the driverResponse is ignored, and go/packages will fallback
-	// to the next driver. If go/packages is extended in the future to support
-	// lists of multiple drivers, go/packages will fall back to the next driver.
-	NotHandled bool
-
-	// Compiler and Arch are the arguments pass of types.SizesFor
-	// to get a types.Sizes to use when type checking.
-	Compiler string
-	Arch     string
-
-	// Roots is the set of package IDs that make up the root packages.
-	// We have to encode this separately because when we encode a single package
-	// we cannot know if it is one of the roots as that requires knowledge of the
-	// graph it is part of.
-	Roots []string `json:",omitempty"`
-
-	// Packages is the full set of packages in the graph.
-	// The packages are not connected into a graph.
-	// The Imports if populated will be stubs that only have their ID set.
-	// Imports will be connected and then type and syntax information added in a
-	// later pass (see refine).
-	Packages []*Package
-
-	// GoVersion is the minor version number used by the driver
-	// (e.g. the go command on the PATH) when selecting .go files.
-	// Zero means unknown.
-	GoVersion int
-}
-
 // Load loads and returns the Go packages named by the given patterns.
 //
 // Config specifies loading options;
@@ -291,7 +254,7 @@
 // no external driver, or the driver returns a response with NotHandled set,
 // defaultDriver will fall back to the go list driver.
 // The boolean result indicates that an external driver handled the request.
-func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, bool, error) {
+func defaultDriver(cfg *Config, patterns ...string) (*DriverResponse, bool, error) {
 	if driver := findExternalDriver(cfg); driver != nil {
 		response, err := driver(cfg, patterns...)
 		if err != nil {
@@ -303,7 +266,10 @@
 	}
 
 	response, err := goListDriver(cfg, patterns...)
-	return response, false, err
+	if err != nil {
+		return nil, false, err
+	}
+	return response, false, nil
 }
 
 // A Package describes a loaded Go package.
@@ -648,7 +614,7 @@
 
 // refine connects the supplied packages into a graph and then adds type
 // and syntax information as requested by the LoadMode.
-func (ld *loader) refine(response *driverResponse) ([]*Package, error) {
+func (ld *loader) refine(response *DriverResponse) ([]*Package, error) {
 	roots := response.Roots
 	rootMap := make(map[string]int, len(roots))
 	for i, root := range roots {
diff --git a/go/packages/packages_test.go b/go/packages/packages_test.go
index 6e461c8..e5687ba 100644
--- a/go/packages/packages_test.go
+++ b/go/packages/packages_test.go
@@ -2953,3 +2953,43 @@
 	cfg.Mode = packages.NeedTypes
 	packages.Load(cfg, "fmt")
 }
+
+// TestLoadEitherSucceedsOrFails is an attempt to reproduce a sporadic
+// failure observed on the Android emu builders in which Load would
+// return an empty list of packages but no error. We don't expect
+// packages.Load to succeed on that platform, and testenv.NeedsGoBuild
+// would ordinarily suppress the attempt if called early. But
+// regardless of whether the 'go' command is functional, Load should
+// never return an empty set of packages but no error.
+func TestLoadEitherSucceedsOrFails(t *testing.T) {
+	const src = `package p`
+	dir := t.TempDir()
+	cfg := &packages.Config{
+		Dir:  dir,
+		Mode: packages.LoadSyntax,
+		Overlay: map[string][]byte{
+			filepath.Join(dir, "p.go"): []byte(src),
+		},
+	}
+	initial, err := packages.Load(cfg, "./p.go")
+	if err != nil {
+		// If Load failed because it needed 'go' and the
+		// platform doesn't have it, silently skip the test.
+		testenv.NeedsGoBuild(t)
+
+		// Otherwise, it's a real failure.
+		t.Fatal(err)
+	}
+
+	// If Load returned without error,
+	// it had better give us error-free packages.
+	if packages.PrintErrors(initial) > 0 {
+		t.Errorf("packages contain errors")
+	}
+
+	// If Load returned without error,
+	// it had better give us the correct number packages.
+	if len(initial) != 1 {
+		t.Errorf("Load returned %d packages (want 1) and no error", len(initial))
+	}
+}
diff --git a/go/ssa/dom.go b/go/ssa/dom.go
index 66a2f5e..02c1ae8 100644
--- a/go/ssa/dom.go
+++ b/go/ssa/dom.go
@@ -40,20 +40,25 @@
 	return b.dom.pre <= c.dom.pre && c.dom.post <= b.dom.post
 }
 
-type byDomPreorder []*BasicBlock
-
-func (a byDomPreorder) Len() int           { return len(a) }
-func (a byDomPreorder) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
-func (a byDomPreorder) Less(i, j int) bool { return a[i].dom.pre < a[j].dom.pre }
-
-// DomPreorder returns a new slice containing the blocks of f in
-// dominator tree preorder.
+// DomPreorder returns a new slice containing the blocks of f
+// in a preorder traversal of the dominator tree.
 func (f *Function) DomPreorder() []*BasicBlock {
-	n := len(f.Blocks)
-	order := make(byDomPreorder, n)
-	copy(order, f.Blocks)
-	sort.Sort(order)
-	return order
+	slice := append([]*BasicBlock(nil), f.Blocks...)
+	sort.Slice(slice, func(i, j int) bool {
+		return slice[i].dom.pre < slice[j].dom.pre
+	})
+	return slice
+}
+
+// DomPostorder returns a new slice containing the blocks of f
+// in a postorder traversal of the dominator tree.
+// (This is not the same as a postdominance order.)
+func (f *Function) DomPostorder() []*BasicBlock {
+	slice := append([]*BasicBlock(nil), f.Blocks...)
+	sort.Slice(slice, func(i, j int) bool {
+		return slice[i].dom.post < slice[j].dom.post
+	})
+	return slice
 }
 
 // domInfo contains a BasicBlock's dominance information.
diff --git a/go/ssa/dom_test.go b/go/ssa/dom_test.go
new file mode 100644
index 0000000..f78c7a6
--- /dev/null
+++ b/go/ssa/dom_test.go
@@ -0,0 +1,59 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa_test
+
+import (
+	"fmt"
+	"path/filepath"
+	"testing"
+
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/internal/testenv"
+)
+
+func TestDominatorOrder(t *testing.T) {
+	testenv.NeedsGoBuild(t) // for go/packages
+
+	const src = `package p
+
+func f(cond bool) {
+	// (Print operands match BasicBlock IDs.)
+	print(0)
+	if cond {
+		print(1)
+	} else {
+		print(2)
+	}
+	print(3)
+}
+`
+	dir := t.TempDir()
+	cfg := &packages.Config{
+		Dir:  dir,
+		Mode: packages.LoadSyntax,
+		Overlay: map[string][]byte{
+			filepath.Join(dir, "p.go"): []byte(src),
+		},
+	}
+	initial, err := packages.Load(cfg, "./p.go")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if packages.PrintErrors(initial) > 0 {
+		t.Fatal("packages contain errors")
+	}
+	_, pkgs := ssautil.Packages(initial, 0)
+	p := pkgs[0]
+	p.Build()
+	f := p.Func("f")
+
+	if got, want := fmt.Sprint(f.DomPreorder()), "[0 1 2 3]"; got != want {
+		t.Errorf("DomPreorder: got %v, want %s", got, want)
+	}
+	if got, want := fmt.Sprint(f.DomPostorder()), "[1 2 3 0]"; got != want {
+		t.Errorf("DomPostorder: got %v, want %s", got, want)
+	}
+}
diff --git a/gopls/api-diff/api_diff.go b/gopls/api-diff/api_diff.go
index ffe9254..dfa1cb6 100644
--- a/gopls/api-diff/api_diff.go
+++ b/gopls/api-diff/api_diff.go
@@ -9,7 +9,6 @@
 
 import (
 	"bytes"
-	"context"
 	"encoding/json"
 	"flag"
 	"fmt"
@@ -50,8 +49,7 @@
 }
 
 func diffAPI(oldVer, newVer string) (string, error) {
-	ctx := context.Background()
-	previousAPI, err := loadAPI(ctx, oldVer)
+	previousAPI, err := loadAPI(oldVer)
 	if err != nil {
 		return "", fmt.Errorf("loading %s: %v", oldVer, err)
 	}
@@ -60,7 +58,7 @@
 		currentAPI = settings.GeneratedAPIJSON
 	} else {
 		var err error
-		currentAPI, err = loadAPI(ctx, newVer)
+		currentAPI, err = loadAPI(newVer)
 		if err != nil {
 			return "", fmt.Errorf("loading %s: %v", newVer, err)
 		}
@@ -69,7 +67,7 @@
 	return cmp.Diff(previousAPI, currentAPI), nil
 }
 
-func loadAPI(ctx context.Context, version string) (*settings.APIJSON, error) {
+func loadAPI(version string) (*settings.APIJSON, error) {
 	ver := fmt.Sprintf("golang.org/x/tools/gopls@%s", version)
 	cmd := exec.Command("go", "run", ver, "api-json")
 
diff --git a/gopls/doc/analyzers.md b/gopls/doc/analyzers.md
index 51eec8a..0a469a1 100644
--- a/gopls/doc/analyzers.md
+++ b/gopls/doc/analyzers.md
@@ -263,6 +263,29 @@
 
 **Disabled by default. Enable it by setting `"analyses": {"fieldalignment": true}`.**
 
+## **fillreturns**
+
+fillreturns: suggest fixes for errors due to an incorrect number of return values
+
+This checker provides suggested fixes for type errors of the
+type "wrong number of return values (want %d, got %d)". For example:
+
+	func m() (int, string, *bool, error) {
+		return
+	}
+
+will turn into
+
+	func m() (int, string, *bool, error) {
+		return 0, "", nil, nil
+	}
+
+This functionality is similar to https://github.com/sqs/goreturns.
+
+[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillreturns)
+
+**Enabled by default.**
+
 ## **httpresponse**
 
 httpresponse: check for mistakes using HTTP responses
@@ -306,6 +329,24 @@
 
 **Enabled by default.**
 
+## **infertypeargs**
+
+infertypeargs: check for unnecessary type arguments in call expressions
+
+Explicit type arguments may be omitted from call expressions if they can be
+inferred from function arguments, or from other type arguments:
+
+	func f[T any](T) {}
+	
+	func _() {
+		f[string]("foo") // string could be inferred
+	}
+
+
+[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/infertypeargs)
+
+**Enabled by default.**
+
 ## **loopclosure**
 
 loopclosure: check references to loop variables from within nested functions
@@ -442,6 +483,43 @@
 
 **Enabled by default.**
 
+## **nonewvars**
+
+nonewvars: suggested fixes for "no new vars on left side of :="
+
+This checker provides suggested fixes for type errors of the
+type "no new vars on left side of :=". For example:
+
+	z := 1
+	z := 2
+
+will turn into
+
+	z := 1
+	z = 2
+
+[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/nonewvars)
+
+**Enabled by default.**
+
+## **noresultvalues**
+
+noresultvalues: suggested fixes for unexpected return values
+
+This checker provides suggested fixes for type errors of the
+type "no result values expected" or "too many return values".
+For example:
+
+	func z() { return nil }
+
+will turn into
+
+	func z() { return }
+
+[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/noresultvars)
+
+**Enabled by default.**
+
 ## **printf**
 
 printf: check consistency of Printf format strings and arguments
@@ -673,6 +751,42 @@
 
 **Enabled by default.**
 
+## **stubmethods**
+
+stubmethods: detect missing methods and fix with stub implementations
+
+This analyzer detects type-checking errors due to missing methods
+in assignments from concrete types to interface types, and offers
+a suggested fix that will create a set of stub methods so that
+the concrete type satisfies the interface.
+
+For example, this function will not compile because the value
+NegativeErr{} does not implement the "error" interface:
+
+	func sqrt(x float64) (float64, error) {
+		if x < 0 {
+			return 0, NegativeErr{} // error: missing method
+		}
+		...
+	}
+
+	type NegativeErr struct{}
+
+This analyzer will suggest a fix to declare this method:
+
+	// Error implements error.Error.
+	func (NegativeErr) Error() string {
+		panic("unimplemented")
+	}
+
+(At least, it appears to behave that way, but technically it
+doesn't use the SuggestedFix mechanism and the stub is created by
+logic in gopls's golang.stub function.)
+
+[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/stubmethods)
+
+**Enabled by default.**
+
 ## **testinggoroutine**
 
 testinggoroutine: report calls to (*testing.T).Fatal from goroutines started by a test
@@ -719,6 +833,26 @@
 
 **Enabled by default.**
 
+## **undeclaredname**
+
+undeclaredname: suggested fixes for "undeclared name: <>"
+
+This checker provides suggested fixes for type errors of the
+type "undeclared name: <>". It will either insert a new statement,
+such as:
+
+	<> :=
+
+or a new function declaration, such as:
+
+	func <>(inferred parameters) {
+		panic("implement me!")
+	}
+
+[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/undeclaredname)
+
+**Enabled by default.**
+
 ## **unmarshal**
 
 unmarshal: report passing non-pointer or non-interface values to unmarshal
@@ -763,15 +897,29 @@
 The unusedparams analyzer checks functions to see if there are
 any parameters that are not being used.
 
-To reduce false positives it ignores:
-- methods
-- parameters that do not have a name or have the name '_' (the blank identifier)
-- functions in test files
-- functions with empty bodies or those with just a return stmt
+To ensure soundness, it ignores:
+  - "address-taken" functions, that is, functions that are used as
+    a value rather than being called directly; their signatures may
+    be required to conform to a func type.
+  - exported functions or methods, since they may be address-taken
+    in another package.
+  - unexported methods whose name matches an interface method
+    declared in the same package, since the method's signature
+    may be required to conform to the interface type.
+  - functions with empty bodies, or containing just a call to panic.
+  - parameters that are unnamed, or named "_", the blank identifier.
+
+The analyzer suggests a fix of replacing the parameter name by "_",
+but in such cases a deeper fix can be obtained by invoking the
+"Refactor: remove unused parameter" code action, which will
+eliminate the parameter entirely, along with all corresponding
+arguments at call sites, while taking care to preserve any side
+effects in the argument expressions; see
+https://github.com/golang/tools/releases/tag/gopls%2Fv0.14.
 
 [Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedparams)
 
-**Disabled by default. Enable it by setting `"analyses": {"unusedparams": true}`.**
+**Enabled by default.**
 
 ## **unusedresult**
 
@@ -789,6 +937,14 @@
 
 **Enabled by default.**
 
+## **unusedvariable**
+
+unusedvariable: check for unused variables and suggest fixes
+
+[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedvariable)
+
+**Disabled by default. Enable it by setting `"analyses": {"unusedvariable": true}`.**
+
 ## **unusedwrite**
 
 unusedwrite: checks for unused writes
@@ -829,160 +985,4 @@
 
 **Disabled by default. Enable it by setting `"analyses": {"useany": true}`.**
 
-## **fillreturns**
-
-fillreturns: suggest fixes for errors due to an incorrect number of return values
-
-This checker provides suggested fixes for type errors of the
-type "wrong number of return values (want %d, got %d)". For example:
-
-	func m() (int, string, *bool, error) {
-		return
-	}
-
-will turn into
-
-	func m() (int, string, *bool, error) {
-		return 0, "", nil, nil
-	}
-
-This functionality is similar to https://github.com/sqs/goreturns.
-
-[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillreturns)
-
-**Enabled by default.**
-
-## **nonewvars**
-
-nonewvars: suggested fixes for "no new vars on left side of :="
-
-This checker provides suggested fixes for type errors of the
-type "no new vars on left side of :=". For example:
-
-	z := 1
-	z := 2
-
-will turn into
-
-	z := 1
-	z = 2
-
-[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/nonewvars)
-
-**Enabled by default.**
-
-## **noresultvalues**
-
-noresultvalues: suggested fixes for unexpected return values
-
-This checker provides suggested fixes for type errors of the
-type "no result values expected" or "too many return values".
-For example:
-
-	func z() { return nil }
-
-will turn into
-
-	func z() { return }
-
-[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/noresultvars)
-
-**Enabled by default.**
-
-## **undeclaredname**
-
-undeclaredname: suggested fixes for "undeclared name: <>"
-
-This checker provides suggested fixes for type errors of the
-type "undeclared name: <>". It will either insert a new statement,
-such as:
-
-	<> :=
-
-or a new function declaration, such as:
-
-	func <>(inferred parameters) {
-		panic("implement me!")
-	}
-
-[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/undeclaredname)
-
-**Enabled by default.**
-
-## **unusedvariable**
-
-unusedvariable: check for unused variables and suggest fixes
-
-[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedvariable)
-
-**Disabled by default. Enable it by setting `"analyses": {"unusedvariable": true}`.**
-
-## **fillstruct**
-
-fillstruct: note incomplete struct initializations
-
-This analyzer provides diagnostics for any struct literals that do not have
-any fields initialized. Because the suggested fix for this analysis is
-expensive to compute, callers should compute it separately, using the
-SuggestedFix function below.
-
-
-[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillstruct)
-
-**Enabled by default.**
-
-## **infertypeargs**
-
-infertypeargs: check for unnecessary type arguments in call expressions
-
-Explicit type arguments may be omitted from call expressions if they can be
-inferred from function arguments, or from other type arguments:
-
-	func f[T any](T) {}
-	
-	func _() {
-		f[string]("foo") // string could be inferred
-	}
-
-
-[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/infertypeargs)
-
-**Enabled by default.**
-
-## **stubmethods**
-
-stubmethods: detect missing methods and fix with stub implementations
-
-This analyzer detects type-checking errors due to missing methods
-in assignments from concrete types to interface types, and offers
-a suggested fix that will create a set of stub methods so that
-the concrete type satisfies the interface.
-
-For example, this function will not compile because the value
-NegativeErr{} does not implement the "error" interface:
-
-	func sqrt(x float64) (float64, error) {
-		if x < 0 {
-			return 0, NegativeErr{} // error: missing method
-		}
-		...
-	}
-
-	type NegativeErr struct{}
-
-This analyzer will suggest a fix to declare this method:
-
-	// Error implements error.Error.
-	func (NegativeErr) Error() string {
-		panic("unimplemented")
-	}
-
-(At least, it appears to behave that way, but technically it
-doesn't use the SuggestedFix mechanism and the stub is created by
-logic in gopls's source.stub function.)
-
-[Full documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/stubmethods)
-
-**Enabled by default.**
-
 <!-- END Analyzers: DO NOT MANUALLY EDIT THIS SECTION -->
diff --git a/gopls/doc/commands.md b/gopls/doc/commands.md
index a838c73..6a651fa 100644
--- a/gopls/doc/commands.md
+++ b/gopls/doc/commands.md
@@ -66,7 +66,14 @@
 
 ```
 {
-	// The fix to apply.
+	// The name of the fix to apply.
+	//
+	// For fixes suggested by analyzers, this is a string constant
+	// advertised by the analyzer that matches the Category of
+	// the analysis.Diagnostic with a SuggestedFix containing no edits.
+	//
+	// For fixes suggested by code actions, this is a string agreed
+	// upon by the code action and golang.ApplyFix.
 	"Fix": string,
 	// The file URI for the document to fix.
 	"URI": string,
@@ -81,6 +88,47 @@
 			"character": uint32,
 		},
 	},
+	// Whether to resolve and return the edits.
+	"ResolveEdits": bool,
+}
+```
+
+Result:
+
+```
+{
+	// Holds changes to existing resources.
+	"changes": map[golang.org/x/tools/gopls/internal/protocol.DocumentURI][]golang.org/x/tools/gopls/internal/protocol.TextEdit,
+	// Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes
+	// are either an array of `TextDocumentEdit`s to express changes to n different text documents
+	// where each text document edit addresses a specific version of a text document. Or it can contain
+	// above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations.
+	//
+	// Whether a client supports versioned document edits is expressed via
+	// `workspace.workspaceEdit.documentChanges` client capability.
+	//
+	// If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then
+	// only plain `TextEdit`s using the `changes` property are supported.
+	"documentChanges": []{
+		"TextDocumentEdit": {
+			"textDocument": { ... },
+			"edits": { ... },
+		},
+		"RenameFile": {
+			"kind": string,
+			"oldUri": string,
+			"newUri": string,
+			"options": { ... },
+			"ResourceOperation": { ... },
+		},
+	},
+	// A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and
+	// delete file / folder operations.
+	//
+	// Whether clients honor this property depends on the client capability `workspace.changeAnnotationSupport`.
+	//
+	// @since 3.16.0
+	"changeAnnotations": map[string]golang.org/x/tools/gopls/internal/protocol.ChangeAnnotation,
 }
 ```
 
@@ -101,6 +149,47 @@
 			"end": { ... },
 		},
 	},
+	// Whether to resolve and return the edits.
+	"ResolveEdits": bool,
+}
+```
+
+Result:
+
+```
+{
+	// Holds changes to existing resources.
+	"changes": map[golang.org/x/tools/gopls/internal/protocol.DocumentURI][]golang.org/x/tools/gopls/internal/protocol.TextEdit,
+	// Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes
+	// are either an array of `TextDocumentEdit`s to express changes to n different text documents
+	// where each text document edit addresses a specific version of a text document. Or it can contain
+	// above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations.
+	//
+	// Whether a client supports versioned document edits is expressed via
+	// `workspace.workspaceEdit.documentChanges` client capability.
+	//
+	// If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then
+	// only plain `TextEdit`s using the `changes` property are supported.
+	"documentChanges": []{
+		"TextDocumentEdit": {
+			"textDocument": { ... },
+			"edits": { ... },
+		},
+		"RenameFile": {
+			"kind": string,
+			"oldUri": string,
+			"newUri": string,
+			"options": { ... },
+			"ResourceOperation": { ... },
+		},
+	},
+	// A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and
+	// delete file / folder operations.
+	//
+	// Whether clients honor this property depends on the client capability `workspace.changeAnnotationSupport`.
+	//
+	// @since 3.16.0
+	"changeAnnotations": map[string]golang.org/x/tools/gopls/internal/protocol.ChangeAnnotation,
 }
 ```
 
@@ -166,7 +255,7 @@
 Result:
 
 ```
-map[golang.org/x/tools/gopls/internal/lsp/protocol.DocumentURI]*golang.org/x/tools/gopls/internal/vulncheck.Result
+map[golang.org/x/tools/gopls/internal/protocol.DocumentURI]*golang.org/x/tools/gopls/internal/vulncheck.Result
 ```
 
 ### **Toggle gc_details**
diff --git a/gopls/doc/contributing.md b/gopls/doc/contributing.md
index aee9029..a2f987b 100644
--- a/gopls/doc/contributing.md
+++ b/gopls/doc/contributing.md
@@ -18,8 +18,8 @@
 
 ## Getting started
 
-Most of the `gopls` logic is in the `golang.org/x/tools/gopls/internal/lsp`
-directory.
+Most of the `gopls` logic is in the `golang.org/x/tools/gopls/internal`
+directory. See [design/implementation.md] for an overview of the code organization.
 
 ## Build
 
@@ -94,41 +94,43 @@
 
 ## Testing
 
-To run tests for just `gopls/`, run,
+The normal command you should use to run the tests after a change is:
 
 ```bash
-cd /path/to/tools/gopls
-go test ./...
+gopls$ go test -short ./...
 ```
 
-But, much of the gopls work involves `internal/lsp` too, so you will want to
-run both:
+(The `-short` flag skips some slow-running ones. The trybot builders
+run the complete set, on a wide range of platforms.)
 
-```bash
-cd /path/to/tools
-cd gopls && go test ./...
-cd ..
-go test ./internal/lsp/...
-```
+Gopls tests are a mix of two kinds.
 
-There is additional information about the `internal/lsp` tests in the
-[internal/lsp/tests `README`](https://github.com/golang/tools/blob/master/internal/lsp/tests/README.md).
+- [Marker tests](../internal/test/marker) express each test scenario
+  in a standalone text file that contains the target .go, go.mod, and
+  go.work files, in which special annotations embedded in comments
+  drive the test. These tests are generally easy to write and fast
+  to iterate, but have limitations on what they can express.
 
-### Integration tests
+- [Integration tests](../internal/test/integration) are regular Go
+  `func Test(*testing.T)` functions that make a series of calls to an
+  API for a fake LSP-enabled client editor. The API allows you to open
+  and edit a file, navigate to a definition, invoke other LSP
+  operations, and assert properties about the state.
 
-gopls has a suite of integration tests defined in the `./gopls/internal/test/integration`
-directory. Each of these tests writes files to a temporary directory, starts a
-separate gopls session, and scripts interactions using an editor-like API. As a
-result of this overhead they can be quite slow, particularly on systems where
-file operations are costly.
+  Due to the asynchronous nature of the LSP, integration tests make
+  assertions about states that the editor must achieve eventually,
+  even when the program goes wrong quickly, it may take a while before
+  the error is reported as a failure to achieve the desired state
+  within several minutes. We recommend that you set
+  `GOPLS_INTEGRATION_TEST_TIMEOUT=10s` to reduce the timeout for
+  integration tests when debugging.
+  
+  When they fail, the integration tests print the log of the LSP
+  session between client and server. Though verbose, they are very
+  helpful for debugging once you know how to read them.
 
-Due to the asynchronous nature of the LSP, integration tests assert
-'expectations' that the editor state must achieve _eventually_. This can
-make debugging the integration tests difficult. To aid with debugging, the tests
-output their LSP logs on any failure. If your CL gets a test failure while
-running the tests, please do take a look at the description of the error and
-the LSP logs, but don't hesitate to [reach out](#getting-help) to the gopls
-team if you need help.
+Don't hesitate to [reach out](#getting-help) to the gopls team if you
+need help.
 
 ### CI
 
diff --git a/gopls/doc/design/architecture.svg b/gopls/doc/design/architecture.svg
new file mode 100644
index 0000000..6c554d5
--- /dev/null
+++ b/gopls/doc/design/architecture.svg
@@ -0,0 +1 @@
+<svg version="1.1" viewBox="0.0 0.0 956.7664041994751 541.8188976377953" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><clipPath id="p.0"><path d="m0 0l956.7664 0l0 541.8189l-956.7664 0l0 -541.8189z" clip-rule="nonzero"/></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l956.7664 0l0 541.8189l-956.7664 0z" fill-rule="evenodd"/><path fill="#cfe2f3" d="m188.35957 270.61243l0 0c0 -11.590973 9.396332 -20.98729 20.987305 -20.98729l492.82855 0c5.566223 0 10.904419 2.2111511 14.840271 6.1470337c3.935913 3.9358673 6.1470337 9.274094 6.1470337 14.840256l0 83.946655c0 11.590973 -9.396301 20.987305 -20.987305 20.987305l-492.82855 0l0 0c-11.590973 0 -20.987305 -9.396332 -20.987305 -20.987305z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m188.35957 270.61243l0 0c0 -11.590973 9.396332 -20.98729 20.987305 -20.98729l492.82855 0c5.566223 0 10.904419 2.2111511 14.840271 6.1470337c3.935913 3.9358673 6.1470337 9.274094 6.1470337 14.840256l0 83.946655c0 11.590973 -9.396301 20.987305 -20.987305 20.987305l-492.82855 0l0 0c-11.590973 0 -20.987305 -9.396332 -20.987305 -20.987305z" fill-rule="evenodd"/><path fill="#000000" d="m442.29654 311.78952q-0.078125 0.078125 -0.140625 0.125q-0.0625 0.046875 -0.171875 0.046875q-0.125 0 -0.265625 -0.09375q-0.140625 -0.109375 -0.359375 -0.21875q-0.21875 -0.125 -0.53125 -0.21875q-0.296875 -0.109375 -0.75 -0.109375q-0.59375 0 -1.046875 0.21875q-0.453125 0.203125 -0.765625 0.609375q-0.296875 0.40625 -0.453125 0.96875q-0.15625 0.5625 -0.15625 1.265625q0 0.75 0.15625 1.328125q0.171875 0.5625 0.46875 0.953125q0.3125 0.375 0.75 0.59375q0.4375 0.203125 0.984375 0.203125q0.515625 0 0.84375 -0.125q0.34375 -0.125 0.5625 -0.28125q0.234375 -0.15625 0.375 -0.28125q0.140625 -0.125 0.28125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.53125 0.65625 -1.328125 0.953125q-0.78125 0.296875 -1.65625 0.296875q-0.765625 0 -1.421875 -0.28125q-0.640625 -0.28125 -1.125 -0.8125q-0.484375 -0.53125 -0.765625 -1.296875q-0.265625 -0.78125 -0.265625 -1.78125q0 -0.890625 0.25 -1.65625q0.25 -0.78125 0.734375 -1.328125q0.484375 -0.5625 1.1875 -0.875q0.71875 -0.3125 1.640625 -0.3125q0.84375 0 1.5 0.28125q0.65625 0.265625 1.171875 0.78125l-0.375 0.515625zm7.8937683 6.65625l-0.640625 0q-0.203125 0 -0.328125 -0.0625q-0.125 -0.0625 -0.171875 -0.28125l-0.15625 -0.75q-0.328125 0.296875 -0.640625 0.53125q-0.296875 0.21875 -0.640625 0.375q-0.328125 0.15625 -0.703125 0.234375q-0.375 0.078125 -0.84375 0.078125q-0.46875 0 -0.890625 -0.125q-0.40625 -0.140625 -0.71875 -0.390625q-0.296875 -0.265625 -0.484375 -0.671875q-0.171875 -0.40625 -0.171875 -0.96875q0 -0.46875 0.265625 -0.90625q0.265625 -0.453125 0.84375 -0.796875q0.59375 -0.34375 1.546875 -0.5625q0.953125 -0.21875 2.328125 -0.25l0 -0.640625q0 -0.9375 -0.40625 -1.421875q-0.40625 -0.484375 -1.1875 -0.484375q-0.53125 0 -0.890625 0.140625q-0.34375 0.125 -0.609375 0.296875q-0.25 0.15625 -0.453125 0.296875q-0.1875 0.125 -0.359375 0.125q-0.15625 0 -0.265625 -0.078125q-0.09375 -0.078125 -0.15625 -0.1875l-0.265625 -0.453125q0.671875 -0.65625 1.453125 -0.96875q0.78125 -0.328125 1.71875 -0.328125q0.671875 0 1.203125 0.234375q0.53125 0.21875 0.890625 0.625q0.359375 0.390625 0.546875 0.96875q0.1875 0.5625 0.1875 1.234375l0 5.1875zm-3.703125 -0.875q0.375 0 0.6875 -0.078125q0.3125 -0.078125 0.578125 -0.203125q0.28125 -0.140625 0.53125 -0.34375q0.265625 -0.203125 0.5 -0.453125l0 -1.6875q-0.984375 0.03125 -1.671875 0.15625q-0.6875 0.109375 -1.125 0.3125q-0.421875 0.203125 -0.625 0.484375q-0.1875 0.265625 -0.1875 0.59375q0 0.328125 0.09375 0.5625q0.109375 0.234375 0.28125 0.375q0.171875 0.140625 0.40625 0.21875q0.25 0.0625 0.53125 0.0625zm11.393158 -5.78125q-0.078125 0.078125 -0.140625 0.125q-0.0625 0.046875 -0.171875 0.046875q-0.125 0 -0.265625 -0.09375q-0.140625 -0.109375 -0.359375 -0.21875q-0.21875 -0.125 -0.53125 -0.21875q-0.296875 -0.109375 -0.75 -0.109375q-0.59375 0 -1.046875 0.21875q-0.453125 0.203125 -0.765625 0.609375q-0.296875 0.40625 -0.453125 0.96875q-0.15625 0.5625 -0.15625 1.265625q0 0.75 0.15625 1.328125q0.171875 0.5625 0.46875 0.953125q0.3125 0.375 0.75 0.59375q0.4375 0.203125 0.984375 0.203125q0.515625 0 0.84375 -0.125q0.34375 -0.125 0.5625 -0.28125q0.234375 -0.15625 0.375 -0.28125q0.140625 -0.125 0.28125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.53125 0.65625 -1.328125 0.953125q-0.78125 0.296875 -1.65625 0.296875q-0.765625 0 -1.421875 -0.28125q-0.640625 -0.28125 -1.125 -0.8125q-0.484375 -0.53125 -0.765625 -1.296875q-0.265625 -0.78125 -0.265625 -1.78125q0 -0.890625 0.25 -1.65625q0.25 -0.78125 0.734375 -1.328125q0.484375 -0.5625 1.1875 -0.875q0.71875 -0.3125 1.640625 -0.3125q0.84375 0 1.5 0.28125q0.65625 0.265625 1.171875 0.78125l-0.375 0.515625zm1.9406738 6.65625l0 -11.78125l1.421875 0l0 4.765625q0.515625 -0.546875 1.140625 -0.875q0.640625 -0.34375 1.46875 -0.34375q0.65625 0 1.15625 0.21875q0.515625 0.21875 0.859375 0.625q0.34375 0.40625 0.515625 0.984375q0.171875 0.5625 0.171875 1.25l0 5.15625l-1.421875 0l0 -5.15625q0 -0.921875 -0.421875 -1.421875q-0.421875 -0.515625 -1.28125 -0.515625q-0.625 0 -1.171875 0.3125q-0.546875 0.296875 -1.015625 0.8125l0 5.96875l-1.421875 0zm12.098999 -8.234375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m18.737848 278.1046l0 0c0 -3.6181946 2.9331226 -6.5513306 6.5513134 -6.5513306l95.71627 0c1.7375183 0 3.4038696 0.69021606 4.632477 1.9188538c1.2286148 1.2286072 1.9188385 2.8949585 1.9188385 4.632477l0 26.204437c0 3.6181946 -2.9331207 6.5513306 -6.5513153 6.5513306l-95.71627 0c-3.6181908 0 -6.5513134 -2.933136 -6.5513134 -6.5513306z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m18.737848 278.1046l0 0c0 -3.6181946 2.9331226 -6.5513306 6.5513134 -6.5513306l95.71627 0c1.7375183 0 3.4038696 0.69021606 4.632477 1.9188538c1.2286148 1.2286072 1.9188385 2.8949585 1.9188385 4.632477l0 26.204437c0 3.6181946 -2.9331207 6.5513306 -6.5513153 6.5513306l-95.71627 0c-3.6181908 0 -6.5513134 -2.933136 -6.5513134 -6.5513306z" fill-rule="evenodd"/><path fill="#000000" d="m43.66406 297.06683l0 -6.890625l-0.890625 -0.09375q-0.171875 -0.046875 -0.28125 -0.125q-0.109375 -0.09375 -0.109375 -0.25l0 -0.578125l1.28125 0l0 -0.453125q0 -0.75 0.234375 -1.359375q0.234375 -0.625 0.6875 -1.0625q0.46875 -0.453125 1.15625 -0.703125q0.703125 -0.25 1.625 -0.25q0.296875 0 0.609375 0.046875q0.328125 0.03125 0.5625 0.109375l-0.0625 0.75q-0.015625 0.09375 -0.09375 0.125q-0.078125 0.03125 -0.234375 0.03125q-0.078125 0 -0.171875 0q-0.09375 -0.015625 -0.21875 -0.015625q-1.421875 0 -2.0625 0.59375q-0.640625 0.59375 -0.640625 1.765625l0 0.421875l4.890625 0l0 7.9375l-1.421875 0l0 -6.90625l-3.421875 0l0 6.90625l-1.4375 0zm10.385513 -11.78125l0 11.78125l-1.421875 0l0 -11.78125l1.421875 0zm5.7209473 3.546875q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm10.680775 0.53125q-0.078125 0.078125 -0.140625 0.125q-0.0625 0.046875 -0.171875 0.046875q-0.125 0 -0.265625 -0.09375q-0.140625 -0.109375 -0.359375 -0.21875q-0.21875 -0.125 -0.53125 -0.21875q-0.296875 -0.109375 -0.75 -0.109375q-0.59375 0 -1.046875 0.21875q-0.453125 0.203125 -0.765625 0.609375q-0.296875 0.40625 -0.453125 0.96875q-0.15625 0.5625 -0.15625 1.265625q0 0.75 0.15625 1.328125q0.171875 0.5625 0.46875 0.953125q0.3125 0.375 0.75 0.59375q0.4375 0.203125 0.984375 0.203125q0.515625 0 0.84375 -0.125q0.34375 -0.125 0.5625 -0.28125q0.234375 -0.15625 0.375 -0.28125q0.140625 -0.125 0.28125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.53125 0.65625 -1.328125 0.953125q-0.78125 0.296875 -1.65625 0.296875q-0.765625 0 -1.421875 -0.28125q-0.640625 -0.28125 -1.125 -0.8125q-0.484375 -0.53125 -0.765625 -1.296875q-0.265625 -0.78125 -0.265625 -1.78125q0 -0.890625 0.25 -1.65625q0.25 -0.78125 0.734375 -1.328125q0.484375 -0.5625 1.1875 -0.875q0.71875 -0.3125 1.640625 -0.3125q0.84375 0 1.5 0.28125q0.65625 0.265625 1.171875 0.78125l-0.375 0.515625zm7.8937836 6.65625l-0.640625 0q-0.203125 0 -0.328125 -0.0625q-0.125 -0.0625 -0.171875 -0.28125l-0.15625 -0.75q-0.328125 0.296875 -0.640625 0.53125q-0.296875 0.21875 -0.640625 0.375q-0.328125 0.15625 -0.703125 0.234375q-0.375 0.078125 -0.84375 0.078125q-0.46875 0 -0.890625 -0.125q-0.40625 -0.140625 -0.71875 -0.390625q-0.296875 -0.265625 -0.484375 -0.671875q-0.171875 -0.40625 -0.171875 -0.96875q0 -0.46875 0.265625 -0.90625q0.265625 -0.453125 0.84375 -0.796875q0.59375 -0.34375 1.546875 -0.5625q0.953125 -0.21875 2.328125 -0.25l0 -0.640625q0 -0.9375 -0.40625 -1.421875q-0.40625 -0.484375 -1.1875 -0.484375q-0.53125 0 -0.890625 0.140625q-0.34375 0.125 -0.609375 0.296875q-0.25 0.15625 -0.453125 0.296875q-0.1875 0.125 -0.359375 0.125q-0.15625 0 -0.265625 -0.078125q-0.09375 -0.078125 -0.15625 -0.1875l-0.265625 -0.453125q0.671875 -0.65625 1.453125 -0.96875q0.78125 -0.328125 1.71875 -0.328125q0.671875 0 1.203125 0.234375q0.53125 0.21875 0.890625 0.625q0.359375 0.390625 0.546875 0.96875q0.1875 0.5625 0.1875 1.234375l0 5.1875zm-3.703125 -0.875q0.375 0 0.6875 -0.078125q0.3125 -0.078125 0.578125 -0.203125q0.28125 -0.140625 0.53125 -0.34375q0.265625 -0.203125 0.5 -0.453125l0 -1.6875q-0.984375 0.03125 -1.671875 0.15625q-0.6875 0.109375 -1.125 0.3125q-0.421875 0.203125 -0.625 0.484375q-0.1875 0.265625 -0.1875 0.59375q0 0.328125 0.09375 0.5625q0.109375 0.234375 0.28125 0.375q0.171875 0.140625 0.40625 0.21875q0.25 0.0625 0.53125 0.0625zm11.393143 -5.78125q-0.078125 0.078125 -0.140625 0.125q-0.0625 0.046875 -0.171875 0.046875q-0.125 0 -0.265625 -0.09375q-0.140625 -0.109375 -0.359375 -0.21875q-0.21875 -0.125 -0.53125 -0.21875q-0.296875 -0.109375 -0.75 -0.109375q-0.59375 0 -1.046875 0.21875q-0.453125 0.203125 -0.765625 0.609375q-0.296875 0.40625 -0.453125 0.96875q-0.15625 0.5625 -0.15625 1.265625q0 0.75 0.15625 1.328125q0.171875 0.5625 0.46875 0.953125q0.3125 0.375 0.75 0.59375q0.4375 0.203125 0.984375 0.203125q0.515625 0 0.84375 -0.125q0.34375 -0.125 0.5625 -0.28125q0.234375 -0.15625 0.375 -0.28125q0.140625 -0.125 0.28125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.53125 0.65625 -1.328125 0.953125q-0.78125 0.296875 -1.65625 0.296875q-0.765625 0 -1.421875 -0.28125q-0.640625 -0.28125 -1.125 -0.8125q-0.484375 -0.53125 -0.765625 -1.296875q-0.265625 -0.78125 -0.265625 -1.78125q0 -0.890625 0.25 -1.65625q0.25 -0.78125 0.734375 -1.328125q0.484375 -0.5625 1.1875 -0.875q0.71875 -0.3125 1.640625 -0.3125q0.84375 0 1.5 0.28125q0.65625 0.265625 1.171875 0.78125l-0.375 0.515625zm1.9406586 6.65625l0 -11.78125l1.421875 0l0 4.765625q0.515625 -0.546875 1.140625 -0.875q0.640625 -0.34375 1.46875 -0.34375q0.65625 0 1.15625 0.21875q0.515625 0.21875 0.859375 0.625q0.34375 0.40625 0.515625 0.984375q0.171875 0.5625 0.171875 1.25l0 5.15625l-1.421875 0l0 -5.15625q0 -0.921875 -0.421875 -1.421875q-0.421875 -0.515625 -1.28125 -0.515625q-0.625 0 -1.171875 0.3125q-0.546875 0.296875 -1.015625 0.8125l0 5.96875l-1.421875 0zm12.099014 -8.234375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m325.4042 489.12613l0 0c0 -3.6181946 2.9331055 -6.5513306 6.5513 -6.5513306l384.66113 0c1.7375488 0 3.4038696 0.69021606 4.6325073 1.9188538c1.2286377 1.2286072 1.9188232 2.8949585 1.9188232 4.632477l0 26.204437c0 3.618225 -2.9331055 6.5513306 -6.5513306 6.5513306l-384.66113 0l0 0c-3.6181946 0 -6.5513 -2.9331055 -6.5513 -6.5513306z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m325.4042 489.12613l0 0c0 -3.6181946 2.9331055 -6.5513306 6.5513 -6.5513306l384.66113 0c1.7375488 0 3.4038696 0.69021606 4.6325073 1.9188538c1.2286377 1.2286072 1.9188232 2.8949585 1.9188232 4.632477l0 26.204437c0 3.618225 -2.9331055 6.5513306 -6.5513306 6.5513306l-384.66113 0l0 0c-3.6181946 0 -6.5513 -2.9331055 -6.5513 -6.5513306z" fill-rule="evenodd"/><path fill="#000000" d="m495.70633 510.83835l0 -10.859375l0.84375 0q0.296875 0 0.390625 0.296875l0.109375 0.96875q0.53125 -0.640625 1.1875 -1.015625q0.671875 -0.390625 1.546875 -0.390625q0.6875 0 1.25 0.265625q0.578125 0.265625 0.96875 0.796875q0.40625 0.53125 0.625 1.3125q0.21875 0.765625 0.21875 1.765625q0 0.90625 -0.25 1.6875q-0.234375 0.765625 -0.6875 1.328125q-0.4375 0.5625 -1.09375 0.890625q-0.65625 0.3125 -1.46875 0.3125q-0.75 0 -1.28125 -0.25q-0.53125 -0.25 -0.9375 -0.703125l0 3.59375l-1.421875 0zm3.609375 -9.84375q-0.703125 0 -1.234375 0.328125q-0.515625 0.3125 -0.953125 0.890625l0 3.921875q0.390625 0.53125 0.859375 0.75q0.46875 0.21875 1.046875 0.21875q1.125 0 1.734375 -0.8125q0.609375 -0.8125 0.609375 -2.3125q0 -0.78125 -0.140625 -1.34375q-0.140625 -0.578125 -0.40625 -0.9375q-0.265625 -0.375 -0.65625 -0.53125q-0.375 -0.171875 -0.859375 -0.171875zm5.2225037 7.09375l0 -8.109375l0.8125 0q0.234375 0 0.3125 0.09375q0.09375 0.09375 0.125 0.296875l0.09375 1.265625q0.421875 -0.84375 1.03125 -1.3125q0.609375 -0.484375 1.4375 -0.484375q0.328125 0 0.59375 0.078125q0.28125 0.078125 0.515625 0.21875l-0.1875 1.0625q-0.046875 0.1875 -0.25 0.1875q-0.109375 0 -0.34375 -0.0625q-0.21875 -0.078125 -0.640625 -0.078125q-0.75 0 -1.25 0.4375q-0.5 0.421875 -0.828125 1.25l0 5.15625l-1.421875 0zm9.729187 -8.234375q0.875 0 1.59375 0.296875q0.71875 0.296875 1.21875 0.84375q0.5 0.546875 0.765625 1.3125q0.265625 0.765625 0.265625 1.71875q0 0.96875 -0.265625 1.734375q-0.265625 0.765625 -0.765625 1.3125q-0.5 0.546875 -1.21875 0.84375q-0.71875 0.28125 -1.59375 0.28125q-0.890625 0 -1.609375 -0.28125q-0.71875 -0.296875 -1.21875 -0.84375q-0.5 -0.546875 -0.78125 -1.3125q-0.265625 -0.765625 -0.265625 -1.734375q0 -0.953125 0.265625 -1.71875q0.28125 -0.765625 0.78125 -1.3125q0.5 -0.546875 1.21875 -0.84375q0.71875 -0.296875 1.609375 -0.296875zm0 7.234375q1.1875 0 1.78125 -0.796875q0.59375 -0.8125 0.59375 -2.25q0 -1.453125 -0.59375 -2.25q-0.59375 -0.8125 -1.78125 -0.8125q-0.609375 0 -1.0625 0.203125q-0.453125 0.203125 -0.75 0.609375q-0.296875 0.390625 -0.453125 0.96875q-0.140625 0.5625 -0.140625 1.28125q0 0.71875 0.140625 1.296875q0.15625 0.5625 0.453125 0.953125q0.296875 0.375 0.75 0.59375q0.453125 0.203125 1.0625 0.203125zm8.067749 1.125q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm6.7960815 -8.359375q0.875 0 1.59375 0.296875q0.71875 0.296875 1.21875 0.84375q0.5 0.546875 0.765625 1.3125q0.265625 0.765625 0.265625 1.71875q0 0.96875 -0.265625 1.734375q-0.265625 0.765625 -0.765625 1.3125q-0.5 0.546875 -1.21875 0.84375q-0.71875 0.28125 -1.59375 0.28125q-0.890625 0 -1.609375 -0.28125q-0.71875 -0.296875 -1.21875 -0.84375q-0.5 -0.546875 -0.78125 -1.3125q-0.265625 -0.765625 -0.265625 -1.734375q0 -0.953125 0.265625 -1.71875q0.28125 -0.765625 0.78125 -1.3125q0.5 -0.546875 1.21875 -0.84375q0.71875 -0.296875 1.609375 -0.296875zm0 7.234375q1.1875 0 1.78125 -0.796875q0.59375 -0.8125 0.59375 -2.25q0 -1.453125 -0.59375 -2.25q-0.59375 -0.8125 -1.78125 -0.8125q-0.609375 0 -1.0625 0.203125q-0.453125 0.203125 -0.75 0.609375q-0.296875 0.390625 -0.453125 0.96875q-0.140625 0.5625 -0.140625 1.28125q0 0.71875 0.140625 1.296875q0.15625 0.5625 0.453125 0.953125q0.296875 0.375 0.75 0.59375q0.453125 0.203125 1.0625 0.203125zm11.145874 -5.65625q-0.078125 0.078125 -0.140625 0.125q-0.0625 0.046875 -0.171875 0.046875q-0.125 0 -0.265625 -0.09375q-0.140625 -0.109375 -0.359375 -0.21875q-0.21875 -0.125 -0.53125 -0.21875q-0.296875 -0.109375 -0.75 -0.109375q-0.59375 0 -1.046875 0.21875q-0.453125 0.203125 -0.765625 0.609375q-0.296875 0.40625 -0.453125 0.96875q-0.15625 0.5625 -0.15625 1.265625q0 0.75 0.15625 1.328125q0.171875 0.5625 0.46875 0.953125q0.3125 0.375 0.75 0.59375q0.4375 0.203125 0.984375 0.203125q0.515625 0 0.84375 -0.125q0.34375 -0.125 0.5625 -0.28125q0.234375 -0.15625 0.375 -0.28125q0.140625 -0.125 0.28125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.53125 0.65625 -1.328125 0.953125q-0.78125 0.296875 -1.65625 0.296875q-0.765625 0 -1.421875 -0.28125q-0.640625 -0.28125 -1.125 -0.8125q-0.484375 -0.53125 -0.765625 -1.296875q-0.265625 -0.78125 -0.265625 -1.78125q0 -0.890625 0.25 -1.65625q0.25 -0.78125 0.734375 -1.328125q0.484375 -0.5625 1.1875 -0.875q0.71875 -0.3125 1.640625 -0.3125q0.84375 0 1.5 0.28125q0.65625 0.265625 1.171875 0.78125l-0.375 0.515625zm5.221924 -1.578125q0.875 0 1.59375 0.296875q0.71875 0.296875 1.21875 0.84375q0.5 0.546875 0.765625 1.3125q0.265625 0.765625 0.265625 1.71875q0 0.96875 -0.265625 1.734375q-0.265625 0.765625 -0.765625 1.3125q-0.5 0.546875 -1.21875 0.84375q-0.71875 0.28125 -1.59375 0.28125q-0.890625 0 -1.609375 -0.28125q-0.71875 -0.296875 -1.21875 -0.84375q-0.5 -0.546875 -0.78125 -1.3125q-0.265625 -0.765625 -0.265625 -1.734375q0 -0.953125 0.265625 -1.71875q0.28125 -0.765625 0.78125 -1.3125q0.5 -0.546875 1.21875 -0.84375q0.71875 -0.296875 1.609375 -0.296875zm0 7.234375q1.1875 0 1.78125 -0.796875q0.59375 -0.8125 0.59375 -2.25q0 -1.453125 -0.59375 -2.25q-0.59375 -0.8125 -1.78125 -0.8125q-0.609375 0 -1.0625 0.203125q-0.453125 0.203125 -0.75 0.609375q-0.296875 0.390625 -0.453125 0.96875q-0.140625 0.5625 -0.140625 1.28125q0 0.71875 0.140625 1.296875q0.15625 0.5625 0.453125 0.953125q0.296875 0.375 0.75 0.59375q0.453125 0.203125 1.0625 0.203125zm7.192749 -10.78125l0 11.78125l-1.421875 0l0 -11.78125l1.421875 0z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m188.35957 488.53293l0 0c0 -3.719635 3.0153809 -6.735016 6.7350464 -6.735016l115.002365 0c1.7862244 0 3.4993286 0.7095642 4.76239 1.9726257c1.2630615 1.2630615 1.9726562 2.9761658 1.9726562 4.76239l0 26.939362c0 3.7196655 -3.0153809 6.7350464 -6.7350464 6.7350464l-115.002365 0c-3.7196655 0 -6.7350464 -3.0153809 -6.7350464 -6.7350464z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m188.35957 488.53293l0 0c0 -3.719635 3.0153809 -6.735016 6.7350464 -6.735016l115.002365 0c1.7862244 0 3.4993286 0.7095642 4.76239 1.9726257c1.2630615 1.2630615 1.9726562 2.9761658 1.9726562 4.76239l0 26.939362c0 3.7196655 -3.0153809 6.7350464 -6.7350464 6.7350464l-115.002365 0c-3.7196655 0 -6.7350464 -3.0153809 -6.7350464 -6.7350464z" fill-rule="evenodd"/><path fill="#000000" d="m225.00337 501.2064q-0.078125 0.078125 -0.140625 0.125q-0.0625 0.046875 -0.171875 0.046875q-0.125 0 -0.265625 -0.09375q-0.140625 -0.109375 -0.359375 -0.21875q-0.21875 -0.125 -0.53125 -0.21875q-0.296875 -0.109375 -0.75 -0.109375q-0.59375 0 -1.046875 0.21875q-0.453125 0.203125 -0.765625 0.609375q-0.296875 0.40625 -0.453125 0.96875q-0.15625 0.5625 -0.15625 1.265625q0 0.75 0.15625 1.328125q0.171875 0.5625 0.46875 0.953125q0.3125 0.375 0.75 0.59375q0.4375 0.203125 0.984375 0.203125q0.515625 0 0.84375 -0.125q0.34375 -0.125 0.5625 -0.28125q0.234375 -0.15625 0.375 -0.28125q0.140625 -0.125 0.28125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.53125 0.65625 -1.328125 0.953125q-0.78125 0.296875 -1.65625 0.296875q-0.765625 0 -1.421875 -0.28125q-0.640625 -0.28125 -1.125 -0.8125q-0.484375 -0.53125 -0.765625 -1.296875q-0.265625 -0.78125 -0.265625 -1.78125q0 -0.890625 0.25 -1.65625q0.25 -0.78125 0.734375 -1.328125q0.484375 -0.5625 1.1875 -0.875q0.71875 -0.3125 1.640625 -0.3125q0.84375 0 1.5 0.28125q0.65625 0.265625 1.171875 0.78125l-0.375 0.515625zm5.2219086 -1.578125q0.875 0 1.59375 0.296875q0.71875 0.296875 1.21875 0.84375q0.5 0.546875 0.765625 1.3125q0.265625 0.765625 0.265625 1.71875q0 0.96875 -0.265625 1.734375q-0.265625 0.765625 -0.765625 1.3125q-0.5 0.546875 -1.21875 0.84375q-0.71875 0.28125 -1.59375 0.28125q-0.890625 0 -1.609375 -0.28125q-0.71875 -0.296875 -1.21875 -0.84375q-0.5 -0.546875 -0.78125 -1.3125q-0.265625 -0.765625 -0.265625 -1.734375q0 -0.953125 0.265625 -1.71875q0.28125 -0.765625 0.78125 -1.3125q0.5 -0.546875 1.21875 -0.84375q0.71875 -0.296875 1.609375 -0.296875zm0 7.234375q1.1875 0 1.78125 -0.796875q0.59375 -0.8125 0.59375 -2.25q0 -1.453125 -0.59375 -2.25q-0.59375 -0.8125 -1.78125 -0.8125q-0.609375 0 -1.0625 0.203125q-0.453125 0.203125 -0.75 0.609375q-0.296875 0.390625 -0.453125 0.96875q-0.140625 0.5625 -0.140625 1.28125q0 0.71875 0.140625 1.296875q0.15625 0.5625 0.453125 0.953125q0.296875 0.375 0.75 0.59375q0.453125 0.203125 1.0625 0.203125zm5.6146393 1.0l0 -8.109375l0.84375 0q0.296875 0 0.390625 0.296875l0.09375 0.84375q0.453125 -0.5625 1.0 -0.90625q0.5625 -0.359375 1.296875 -0.359375q0.828125 0 1.328125 0.46875q0.515625 0.453125 0.734375 1.21875q0.171875 -0.4375 0.4375 -0.75q0.28125 -0.328125 0.625 -0.53125q0.34375 -0.21875 0.734375 -0.3125q0.390625 -0.09375 0.796875 -0.09375q0.640625 0 1.140625 0.203125q0.5 0.203125 0.84375 0.59375q0.34375 0.390625 0.53125 0.96875q0.1875 0.578125 0.1875 1.3125l0 5.15625l-1.421875 0l0 -5.15625q0 -0.953125 -0.421875 -1.4375q-0.421875 -0.5 -1.203125 -0.5q-0.359375 0 -0.671875 0.125q-0.3125 0.125 -0.5625 0.359375q-0.234375 0.234375 -0.375 0.609375q-0.140625 0.359375 -0.140625 0.84375l0 5.15625l-1.421875 0l0 -5.15625q0 -0.984375 -0.390625 -1.453125q-0.390625 -0.484375 -1.140625 -0.484375q-0.53125 0 -0.984375 0.28125q-0.453125 0.28125 -0.828125 0.765625l0 6.046875l-1.421875 0zm13.135834 0l0 -8.109375l0.84375 0q0.296875 0 0.390625 0.296875l0.09375 0.84375q0.453125 -0.5625 1.0 -0.90625q0.5625 -0.359375 1.296875 -0.359375q0.828125 0 1.328125 0.46875q0.515625 0.453125 0.734375 1.21875q0.171875 -0.4375 0.4375 -0.75q0.28125 -0.328125 0.625 -0.53125q0.34373474 -0.21875 0.73435974 -0.3125q0.390625 -0.09375 0.796875 -0.09375q0.640625 0 1.140625 0.203125q0.5 0.203125 0.84375 0.59375q0.34375 0.390625 0.53125 0.96875q0.1875 0.578125 0.1875 1.3125l0 5.15625l-1.421875 0l0 -5.15625q0 -0.953125 -0.421875 -1.4375q-0.421875 -0.5 -1.203125 -0.5q-0.359375 0 -0.671875 0.125q-0.31248474 0.125 -0.56248474 0.359375q-0.234375 0.234375 -0.375 0.609375q-0.140625 0.359375 -0.140625 0.84375l0 5.15625l-1.421875 0l0 -5.15625q0 -0.984375 -0.390625 -1.453125q-0.390625 -0.484375 -1.140625 -0.484375q-0.53125 0 -0.984375 0.28125q-0.453125 0.28125 -0.828125 0.765625l0 6.046875l-1.421875 0zm19.088943 0l-0.640625 0q-0.203125 0 -0.328125 -0.0625q-0.125 -0.0625 -0.171875 -0.28125l-0.15625 -0.75q-0.328125 0.296875 -0.640625 0.53125q-0.296875 0.21875 -0.640625 0.375q-0.328125 0.15625 -0.703125 0.234375q-0.375 0.078125 -0.84375 0.078125q-0.46875 0 -0.890625 -0.125q-0.40625 -0.140625 -0.71875 -0.390625q-0.296875 -0.265625 -0.484375 -0.671875q-0.171875 -0.40625 -0.171875 -0.96875q0 -0.46875 0.265625 -0.90625q0.265625 -0.453125 0.84375 -0.796875q0.59375 -0.34375 1.546875 -0.5625q0.953125 -0.21875 2.328125 -0.25l0 -0.640625q0 -0.9375 -0.40625 -1.421875q-0.40625 -0.484375 -1.1875 -0.484375q-0.53125 0 -0.890625 0.140625q-0.34375 0.125 -0.609375 0.296875q-0.25 0.15625 -0.453125 0.296875q-0.1875 0.125 -0.359375 0.125q-0.15625 0 -0.265625 -0.078125q-0.09375 -0.078125 -0.15625 -0.1875l-0.265625 -0.453125q0.671875 -0.65625 1.453125 -0.96875q0.78125 -0.328125 1.71875 -0.328125q0.671875 0 1.203125 0.234375q0.53125 0.21875 0.890625 0.625q0.359375 0.390625 0.546875 0.96875q0.1875 0.5625 0.1875 1.234375l0 5.1875zm-3.703125 -0.875q0.375 0 0.6875 -0.078125q0.3125 -0.078125 0.578125 -0.203125q0.28125 -0.140625 0.53125 -0.34375q0.265625 -0.203125 0.5 -0.453125l0 -1.6875q-0.984375 0.03125 -1.671875 0.15625q-0.6875 0.109375 -1.125 0.3125q-0.421875 0.203125 -0.625 0.484375q-0.1875 0.265625 -0.1875 0.59375q0 0.328125 0.09375 0.5625q0.109375 0.234375 0.28125 0.375q0.171875 0.140625 0.40625 0.21875q0.25 0.0625 0.53125 0.0625zm5.861908 0.875l0 -8.109375l0.84375 0q0.296875 0 0.390625 0.296875l0.109375 0.890625q0.53125 -0.59375 1.171875 -0.953125q0.65625 -0.359375 1.515625 -0.359375q0.65625 0 1.15625 0.21875q0.515625 0.21875 0.859375 0.625q0.34375 0.40625 0.515625 0.984375q0.171875 0.5625 0.171875 1.25l0 5.15625l-1.421875 0l0 -5.15625q0 -0.921875 -0.421875 -1.421875q-0.421875 -0.515625 -1.28125 -0.515625q-0.625 0 -1.171875 0.3125q-0.546875 0.296875 -1.015625 0.8125l0 5.96875l-1.421875 0zm14.598999 0q-0.3125 0 -0.390625 -0.296875l-0.125 -0.984375q-0.515625 0.640625 -1.1875 1.015625q-0.671875 0.375 -1.53125 0.375q-0.703125 0 -1.265625 -0.265625q-0.5625 -0.265625 -0.96875 -0.78125q-0.390625 -0.53125 -0.609375 -1.296875q-0.21875 -0.78125 -0.21875 -1.796875q0 -0.890625 0.234375 -1.65625q0.25 -0.78125 0.6875 -1.34375q0.453125 -0.5625 1.09375 -0.890625q0.65625 -0.328125 1.484375 -0.328125q0.75 0 1.265625 0.25q0.53125 0.25 0.953125 0.71875l0 -4.5l1.421875 0l0 11.78125l-0.84375 0zm-2.765625 -1.046875q0.703125 0 1.21875 -0.3125q0.53125 -0.328125 0.96875 -0.90625l0 -3.921875q-0.390625 -0.53125 -0.859375 -0.734375q-0.46875 -0.21875 -1.03125 -0.21875q-1.140625 0 -1.75 0.8125q-0.609375 0.8125 -0.609375 2.296875q0 0.796875 0.125 1.359375q0.140625 0.5625 0.40625 0.9375q0.265625 0.359375 0.640625 0.53125q0.390625 0.15625 0.890625 0.15625z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m19.025703 355.75775l0 0c0 -7.6037903 6.164072 -13.767853 13.767838 -13.767853l99.21574 0c3.6514587 0 7.153351 1.450531 9.735321 4.032501c2.5819702 2.5819702 4.0325165 6.083893 4.0325165 9.735352l0 55.06967c0 7.6037903 -6.1640778 13.767853 -13.767838 13.767853l-99.21574 0c-7.6037655 0 -13.767838 -6.1640625 -13.767838 -13.767853z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m19.025703 355.75775l0 0c0 -7.6037903 6.164072 -13.767853 13.767838 -13.767853l99.21574 0c3.6514587 0 7.153351 1.450531 9.735321 4.032501c2.5819702 2.5819702 4.0325165 6.083893 4.0325165 9.735352l0 55.06967c0 7.6037903 -6.1640778 13.767853 -13.767838 13.767853l-99.21574 0c-7.6037655 0 -13.767838 -6.1640625 -13.767838 -13.767853z" fill-rule="evenodd"/><path fill="#000000" d="m66.152145 365.99634l-2.71875 -3.953125l1.359375 0q0.171875 0 0.25 0.0625q0.09375 0.0625 0.15625 0.15625l1.984375 3.046875q0.0625 -0.234375 0.203125 -0.453125l1.75 -2.5625q0.078125 -0.109375 0.15625 -0.171875q0.078125 -0.078125 0.203125 -0.078125l1.3125 0l-2.734375 3.875l2.84375 4.234375l-1.375 0q-0.171875 0 -0.28125 -0.09375q-0.09375 -0.09375 -0.15625 -0.203125l-2.046875 -3.171875q-0.046875 0.234375 -0.15625 0.40625l-1.890625 2.765625q-0.078125 0.109375 -0.171875 0.203125q-0.09375 0.09375 -0.25 0.09375l-1.28125 0l2.84375 -4.15625zm6.173279 4.15625l0 -8.109375l0.8125 0q0.234375 0 0.3125 0.09375q0.09375 0.09375 0.125 0.296875l0.09375 1.265625q0.421875 -0.84375 1.03125 -1.3125q0.609375 -0.484375 1.4375 -0.484375q0.328125 0 0.59375 0.078125q0.28125 0.078125 0.515625 0.21875l-0.1875 1.0625q-0.046875 0.1875 -0.25 0.1875q-0.109375 0 -0.34375 -0.0625q-0.21875 -0.078125 -0.640625 -0.078125q-0.75 0 -1.25 0.4375q-0.5 0.421875 -0.828125 1.25l0 5.15625l-1.421875 0zm9.651047 -8.234375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm5.462021 7.1875l0 -6.890625l-0.890625 -0.09375q-0.171875 -0.046875 -0.28125 -0.125q-0.109375 -0.09375 -0.109375 -0.25l0 -0.578125l1.28125 0l0 -0.796875q0 -0.6875 0.1875 -1.21875q0.203125 -0.546875 0.5625 -0.921875q0.375 -0.375 0.875 -0.5625q0.515625 -0.1875 1.15625 -0.1875q0.546875 0 1.015625 0.15625l-0.03125 0.703125q-0.015625 0.171875 -0.140625 0.203125q-0.125 0.03125 -0.359375 0.03125l-0.25 0q-0.359375 0 -0.671875 0.09375q-0.296875 0.09375 -0.515625 0.3125q-0.203125 0.21875 -0.328125 0.578125q-0.109375 0.34375 -0.109375 0.859375l0 0.75l2.34375 0l0 1.03125l-2.296875 0l0 6.90625l-1.4375 0zm9.720062 -6.765625q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm1.8814087 5.78125q0 -0.1875 0.0625 -0.34375q0.078125 -0.171875 0.203125 -0.296875q0.125 -0.125 0.296875 -0.1875q0.171875 -0.078125 0.390625 -0.078125q0.234375 0 0.421875 0.09375q0.1875 0.078125 0.3125 0.234375q0.125 0.15625 0.1875 0.375q0.0625 0.203125 0.0625 0.4375q0 0.359375 -0.109375 0.75q-0.09375 0.390625 -0.296875 0.765625q-0.1875 0.375 -0.46875 0.734375q-0.28125 0.359375 -0.640625 0.671875l-0.25 -0.234375q-0.09375 -0.09375 -0.09375 -0.21875q0 -0.109375 0.109375 -0.21875q0.078125 -0.09375 0.203125 -0.25q0.125 -0.140625 0.25 -0.328125q0.125 -0.1875 0.234375 -0.421875q0.109375 -0.234375 0.15625 -0.5l-0.09375 0q-0.21875 0 -0.390625 -0.0625q-0.15625 -0.078125 -0.28125 -0.203125q-0.125 -0.140625 -0.203125 -0.3125q-0.0625 -0.1875 -0.0625 -0.40625z" fill-rule="nonzero"/><path fill="#000000" d="m40.64583 389.1526l0 -8.109375l0.84375 0q0.296875 0 0.390625 0.296875l0.09375 0.84375q0.453125 -0.5625 1.0 -0.90625q0.5625 -0.359375 1.296875 -0.359375q0.828125 0 1.328125 0.46875q0.515625 0.453125 0.734375 1.21875q0.171875 -0.4375 0.4375 -0.75q0.28125 -0.328125 0.625 -0.53125q0.34375 -0.21875 0.734375 -0.3125q0.390625 -0.09375 0.796875 -0.09375q0.640625 0 1.140625 0.203125q0.5 0.203125 0.84375 0.59375q0.34375 0.390625 0.53125 0.96875q0.1875 0.578125 0.1875 1.3125l0 5.15625l-1.421875 0l0 -5.15625q0 -0.953125 -0.421875 -1.4375q-0.421875 -0.5 -1.203125 -0.5q-0.359375 0 -0.671875 0.125q-0.3125 0.125 -0.5625 0.359375q-0.234375 0.234375 -0.375 0.609375q-0.140625 0.359375 -0.140625 0.84375l0 5.15625l-1.421875 0l0 -5.15625q0 -0.984375 -0.390625 -1.453125q-0.390625 -0.484375 -1.140625 -0.484375q-0.53125 0 -0.984375 0.28125q-0.453125 0.28125 -0.828125 0.765625l0 6.046875l-1.421875 0zm16.338959 -8.234375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm7.602646 7.3125q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm3.514801 -0.125l0 -11.78125l1.421875 0l0 4.765625q0.515625 -0.546875 1.140625 -0.875q0.640625 -0.34375 1.46875 -0.34375q0.65625 0 1.15625 0.21875q0.515625 0.21875 0.859375 0.625q0.34375 0.40625 0.515625 0.984375q0.171875 0.5625 0.171875 1.25l0 5.15625l-1.421875 0l0 -5.15625q0 -0.921875 -0.421875 -1.421875q-0.421875 -0.515625 -1.28125 -0.515625q-0.625 0 -1.171875 0.3125q-0.546875 0.296875 -1.015625 0.8125l0 5.96875l-1.421875 0zm12.177139 -8.234375q0.875 0 1.59375 0.296875q0.71875 0.296875 1.21875 0.84375q0.5 0.546875 0.765625 1.3125q0.265625 0.765625 0.265625 1.71875q0 0.96875 -0.265625 1.734375q-0.265625 0.765625 -0.765625 1.3125q-0.5 0.546875 -1.21875 0.84375q-0.71875 0.28125 -1.59375 0.28125q-0.890625 0 -1.609375 -0.28125q-0.71875 -0.296875 -1.21875 -0.84375q-0.5 -0.546875 -0.78125 -1.3125q-0.265625 -0.765625 -0.265625 -1.734375q0 -0.953125 0.265625 -1.71875q0.28125 -0.765625 0.78125 -1.3125q0.5 -0.546875 1.21875 -0.84375q0.71875 -0.296875 1.609375 -0.296875zm0 7.234375q1.1875 0 1.78125 -0.796875q0.59375 -0.8125 0.59375 -2.25q0 -1.453125 -0.59375 -2.25q-0.59375 -0.8125 -1.78125 -0.8125q-0.609375 0 -1.0625 0.203125q-0.453125 0.203125 -0.75 0.609375q-0.296875 0.390625 -0.453125 0.96875q-0.140625 0.5625 -0.140625 1.28125q0 0.71875 0.140625 1.296875q0.15625 0.5625 0.453125 0.953125q0.296875 0.375 0.75 0.59375q0.453125 0.203125 1.0625 0.203125zm11.317764 1.0q-0.3125 0 -0.390625 -0.296875l-0.125 -0.984375q-0.515625 0.640625 -1.1875 1.015625q-0.671875 0.375 -1.53125 0.375q-0.703125 0 -1.265625 -0.265625q-0.5625 -0.265625 -0.96875 -0.78125q-0.390625 -0.53125 -0.609375 -1.296875q-0.21875 -0.78125 -0.21875 -1.796875q0 -0.890625 0.234375 -1.65625q0.25 -0.78125 0.6875 -1.34375q0.453125 -0.5625 1.09375 -0.890625q0.65625 -0.328125 1.484375 -0.328125q0.75 0 1.265625 0.25q0.53125 0.25 0.953125 0.71875l0 -4.5l1.421875 0l0 11.78125l-0.84375 0zm-2.765625 -1.046875q0.703125 0 1.21875 -0.3125q0.53125 -0.328125 0.96875 -0.90625l0 -3.921875q-0.390625 -0.53125 -0.859375 -0.734375q-0.46875 -0.21875 -1.03125 -0.21875q-1.140625 0 -1.75 0.8125q-0.609375 0.8125 -0.609375 2.296875q0 0.796875 0.125 1.359375q0.140625 0.5625 0.40625 0.9375q0.265625 0.359375 0.640625 0.53125q0.390625 0.15625 0.890625 0.15625zm10.647003 -5.71875q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm5.5064087 -1.46875q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm7.602646 7.3125q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm8.155426 -6.890625q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm1.8814087 5.78125q0 -0.1875 0.0625 -0.34375q0.078125 -0.171875 0.203125 -0.296875q0.125 -0.125 0.296875 -0.1875q0.171875 -0.078125 0.390625 -0.078125q0.234375 0 0.421875 0.09375q0.1875 0.078125 0.3125 0.234375q0.125 0.15625 0.1875 0.375q0.0625 0.203125 0.0625 0.4375q0 0.359375 -0.109375 0.75q-0.09375 0.390625 -0.296875 0.765625q-0.1875 0.375 -0.46875 0.734375q-0.28125 0.359375 -0.640625 0.671875l-0.25 -0.234375q-0.09375 -0.09375 -0.09375 -0.21875q0 -0.109375 0.109375 -0.21875q0.078125 -0.09375 0.203125 -0.25q0.125 -0.140625 0.25 -0.328125q0.125 -0.1875 0.234375 -0.421875q0.109375 -0.234375 0.15625 -0.5l-0.09375 0q-0.21875 0 -0.390625 -0.0625q-0.15625 -0.078125 -0.28125 -0.203125q-0.125 -0.140625 -0.203125 -0.3125q-0.0625 -0.1875 -0.0625 -0.40625z" fill-rule="nonzero"/><path fill="#000000" d="m56.75477 408.2776q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm5.889801 2.265625q-0.078125 0.15625 -0.1875 0.25q-0.109375 0.109375 -0.328125 0.109375l-1.0625 0l1.484375 -3.21875l-3.34375 -7.640625l1.234375 0q0.1875 0 0.28125 0.09375q0.109375 0.09375 0.15625 0.203125l2.171875 5.109375q0.078125 0.171875 0.125 0.359375q0.046875 0.171875 0.09375 0.359375q0.046875 -0.1875 0.109375 -0.359375q0.0625 -0.1875 0.125 -0.375l2.109375 -5.09375q0.046875 -0.125 0.15625 -0.203125q0.125 -0.09375 0.25 -0.09375l1.140625 0l-4.515625 10.5zm5.8168945 0.359375l0 -10.859375l0.84375 0q0.296875 0 0.390625 0.296875l0.109375 0.96875q0.53125 -0.640625 1.1875 -1.015625q0.671875 -0.390625 1.546875 -0.390625q0.6875 0 1.25 0.265625q0.578125 0.265625 0.96875 0.796875q0.40625 0.53125 0.625 1.3125q0.21875 0.765625 0.21875 1.765625q0 0.90625 -0.25 1.6875q-0.234375 0.765625 -0.6875 1.328125q-0.4375 0.5625 -1.09375 0.890625q-0.65625 0.3125 -1.46875 0.3125q-0.75 0 -1.28125 -0.25q-0.53125 -0.25 -0.9375 -0.703125l0 3.59375l-1.421875 0zm3.609375 -9.84375q-0.703125 0 -1.234375 0.328125q-0.515625 0.3125 -0.953125 0.890625l0 3.921875q0.390625 0.53125 0.859375 0.75q0.46875 0.21875 1.046875 0.21875q1.125 0 1.734375 -0.8125q0.609375 -0.8125 0.609375 -2.3125q0 -0.78125 -0.140625 -1.34375q-0.140625 -0.578125 -0.40625 -0.9375q-0.265625 -0.375 -0.65625 -0.53125q-0.375 -0.171875 -0.859375 -0.171875zm8.425644 -1.140625q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm5.149521 7.1875l0 -8.109375l0.8125 0q0.234375 0 0.3125 0.09375q0.09375 0.09375 0.125 0.296875l0.09375 1.265625q0.421875 -0.84375 1.03125 -1.3125q0.609375 -0.484375 1.4375 -0.484375q0.328125 0 0.59375 0.078125q0.28125 0.078125 0.515625 0.21875l-0.1875 1.0625q-0.046875 0.1875 -0.25 0.1875q-0.109375 0 -0.34375 -0.0625q-0.21875 -0.078125 -0.640625 -0.078125q-0.75 0 -1.25 0.4375q-0.5 0.421875 -0.828125 1.25l0 5.15625l-1.421875 0zm9.651047 -8.234375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm5.462021 7.1875l0 -6.890625l-0.890625 -0.09375q-0.171875 -0.046875 -0.28125 -0.125q-0.109375 -0.09375 -0.109375 -0.25l0 -0.578125l1.28125 0l0 -0.796875q0 -0.6875 0.1875 -1.21875q0.203125 -0.546875 0.5625 -0.921875q0.375 -0.375 0.875 -0.5625q0.515625 -0.1875 1.15625 -0.1875q0.546875 0 1.015625 0.15625l-0.03125 0.703125q-0.015625 0.171875 -0.140625 0.203125q-0.125 0.03125 -0.359375 0.03125l-0.25 0q-0.359375 0 -0.671875 0.09375q-0.296875 0.09375 -0.515625 0.3125q-0.203125 0.21875 -0.328125 0.578125q-0.109375 0.34375 -0.109375 0.859375l0 0.75l2.34375 0l0 1.03125l-2.296875 0l0 6.90625l-1.4375 0zm9.720062 -6.765625q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m12.180104 348.91214l0 0c0 -7.60376 6.164071 -13.767853 13.767837 -13.767853l99.21573 0c3.651451 0 7.1533585 1.4505615 9.735329 4.0325317c2.5819702 2.5819702 4.032501 6.0838623 4.032501 9.735321l0 55.069702c0 7.60376 -6.1640625 13.767822 -13.76783 13.767822l-99.21573 0c-7.6037655 0 -13.767837 -6.1640625 -13.767837 -13.767822z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m12.180104 348.91214l0 0c0 -7.60376 6.164071 -13.767853 13.767837 -13.767853l99.21573 0c3.651451 0 7.1533585 1.4505615 9.735329 4.0325317c2.5819702 2.5819702 4.032501 6.0838623 4.032501 9.735321l0 55.069702c0 7.60376 -6.1640625 13.767822 -13.76783 13.767822l-99.21573 0c-7.6037655 0 -13.767837 -6.1640625 -13.767837 -13.767822z" fill-rule="evenodd"/><path fill="#000000" d="m59.306545 359.15073l-2.71875 -3.953125l1.359375 0q0.171875 0 0.25 0.0625q0.09375 0.0625 0.15625 0.15625l1.984375 3.046875q0.0625 -0.234375 0.203125 -0.453125l1.75 -2.5625q0.078125 -0.109375 0.15625 -0.171875q0.078125 -0.078125 0.203125 -0.078125l1.3125 0l-2.734375 3.875l2.8437462 4.234375l-1.3749962 0q-0.171875 0 -0.28125 -0.09375q-0.09375 -0.09375 -0.15625 -0.203125l-2.046875 -3.171875q-0.046875 0.234375 -0.15625 0.40625l-1.890625 2.765625q-0.078125 0.109375 -0.171875 0.203125q-0.09375 0.09375 -0.25 0.09375l-1.28125 0l2.84375 -4.15625zm6.173275 4.15625l0 -8.109375l0.8125 0q0.234375 0 0.3125 0.09375q0.09375 0.09375 0.125 0.296875l0.09375 1.265625q0.421875 -0.84375 1.03125 -1.3125q0.609375 -0.484375 1.4375 -0.484375q0.328125 0 0.59375 0.078125q0.28125 0.078125 0.515625 0.21875l-0.1875 1.0625q-0.046875 0.1875 -0.25 0.1875q-0.109375 0 -0.34375 -0.0625q-0.21875 -0.078125 -0.640625 -0.078125q-0.75 0 -1.25 0.4375q-0.5 0.421875 -0.828125 1.25l0 5.15625l-1.421875 0zm9.651047 -8.234375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm5.462021 7.1875l0 -6.890625l-0.890625 -0.09375q-0.171875 -0.046875 -0.28125 -0.125q-0.109375 -0.09375 -0.109375 -0.25l0 -0.578125l1.28125 0l0 -0.796875q0 -0.6875 0.1875 -1.21875q0.203125 -0.546875 0.5625 -0.921875q0.375 -0.375 0.875 -0.5625q0.515625 -0.1875 1.15625 -0.1875q0.546875 0 1.015625 0.15625l-0.03125 0.703125q-0.015625 0.171875 -0.140625 0.203125q-0.125 0.03125 -0.359375 0.03125l-0.25 0q-0.359375 0 -0.671875 0.09375q-0.296875 0.09375 -0.515625 0.3125q-0.203125 0.21875 -0.328125 0.578125q-0.109375 0.34375 -0.109375 0.859375l0 0.75l2.34375 0l0 1.03125l-2.296875 0l0 6.90625l-1.4375 0zm9.720062 -6.765625q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm1.8814087 5.78125q0 -0.1875 0.0625 -0.34375q0.078125 -0.171875 0.203125 -0.296875q0.125 -0.125 0.296875 -0.1875q0.171875 -0.078125 0.390625 -0.078125q0.234375 0 0.421875 0.09375q0.1875 0.078125 0.3125 0.234375q0.125 0.15625 0.1875 0.375q0.0625 0.203125 0.0625 0.4375q0 0.359375 -0.109375 0.75q-0.09375 0.390625 -0.296875 0.765625q-0.1875 0.375 -0.46875 0.734375q-0.28125 0.359375 -0.640625 0.671875l-0.25 -0.234375q-0.09375 -0.09375 -0.09375 -0.21875q0 -0.109375 0.109375 -0.21875q0.078125 -0.09375 0.203125 -0.25q0.125 -0.140625 0.25 -0.328125q0.125 -0.1875 0.234375 -0.421875q0.109375 -0.234375 0.15625 -0.5l-0.09375 0q-0.21875 0 -0.390625 -0.0625q-0.15625 -0.078125 -0.28125 -0.203125q-0.125 -0.140625 -0.203125 -0.3125q-0.0625 -0.1875 -0.0625 -0.40625z" fill-rule="nonzero"/><path fill="#000000" d="m33.80023 382.30698l0 -8.109375l0.84375 0q0.296875 0 0.390625 0.296875l0.09375 0.84375q0.453125 -0.5625 1.0 -0.90625q0.5625 -0.359375 1.296875 -0.359375q0.828125 0 1.328125 0.46875q0.515625 0.453125 0.734375 1.21875q0.171875 -0.4375 0.4375 -0.75q0.28125 -0.328125 0.625 -0.53125q0.34375 -0.21875 0.734375 -0.3125q0.390625 -0.09375 0.796875 -0.09375q0.640625 0 1.140625 0.203125q0.5 0.203125 0.84375 0.59375q0.34375 0.390625 0.53125 0.96875q0.1875 0.578125 0.1875 1.3125l0 5.15625l-1.421875 0l0 -5.15625q0 -0.953125 -0.421875 -1.4375q-0.421875 -0.5 -1.203125 -0.5q-0.359375 0 -0.671875 0.125q-0.3125 0.125 -0.5625 0.359375q-0.234375 0.234375 -0.375 0.609375q-0.140625 0.359375 -0.140625 0.84375l0 5.15625l-1.421875 0l0 -5.15625q0 -0.984375 -0.390625 -1.453125q-0.390625 -0.484375 -1.140625 -0.484375q-0.53125 0 -0.984375 0.28125q-0.453125 0.28125 -0.828125 0.765625l0 6.046875l-1.421875 0zm16.338959 -8.234375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm7.602646 7.3125q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm3.514801 -0.125l0 -11.78125l1.421875 0l0 4.765625q0.515625 -0.546875 1.140625 -0.875q0.6406212 -0.34375 1.4687462 -0.34375q0.65625 0 1.15625 0.21875q0.515625 0.21875 0.859375 0.625q0.34375 0.40625 0.515625 0.984375q0.171875 0.5625 0.171875 1.25l0 5.15625l-1.421875 0l0 -5.15625q0 -0.921875 -0.421875 -1.421875q-0.421875 -0.515625 -1.28125 -0.515625q-0.625 0 -1.1718712 0.3125q-0.546875 0.296875 -1.015625 0.8125l0 5.96875l-1.421875 0zm12.177135 -8.234375q0.875 0 1.59375 0.296875q0.71875 0.296875 1.21875 0.84375q0.5 0.546875 0.765625 1.3125q0.265625 0.765625 0.265625 1.71875q0 0.96875 -0.265625 1.734375q-0.265625 0.765625 -0.765625 1.3125q-0.5 0.546875 -1.21875 0.84375q-0.71875 0.28125 -1.59375 0.28125q-0.890625 0 -1.609375 -0.28125q-0.71875 -0.296875 -1.21875 -0.84375q-0.5 -0.546875 -0.78125 -1.3125q-0.265625 -0.765625 -0.265625 -1.734375q0 -0.953125 0.265625 -1.71875q0.28125 -0.765625 0.78125 -1.3125q0.5 -0.546875 1.21875 -0.84375q0.71875 -0.296875 1.609375 -0.296875zm0 7.234375q1.1875 0 1.78125 -0.796875q0.59375 -0.8125 0.59375 -2.25q0 -1.453125 -0.59375 -2.25q-0.59375 -0.8125 -1.78125 -0.8125q-0.609375 0 -1.0625 0.203125q-0.453125 0.203125 -0.75 0.609375q-0.296875 0.390625 -0.453125 0.96875q-0.140625 0.5625 -0.140625 1.28125q0 0.71875 0.140625 1.296875q0.15625 0.5625 0.453125 0.953125q0.296875 0.375 0.75 0.59375q0.453125 0.203125 1.0625 0.203125zm11.317764 1.0q-0.3125 0 -0.390625 -0.296875l-0.125 -0.984375q-0.515625 0.640625 -1.1875 1.015625q-0.671875 0.375 -1.53125 0.375q-0.703125 0 -1.265625 -0.265625q-0.5625 -0.265625 -0.96875 -0.78125q-0.390625 -0.53125 -0.609375 -1.296875q-0.21875 -0.78125 -0.21875 -1.796875q0 -0.890625 0.234375 -1.65625q0.25 -0.78125 0.6875 -1.34375q0.453125 -0.5625 1.09375 -0.890625q0.65625 -0.328125 1.484375 -0.328125q0.75 0 1.265625 0.25q0.53125 0.25 0.953125 0.71875l0 -4.5l1.421875 0l0 11.78125l-0.84375 0zm-2.765625 -1.046875q0.703125 0 1.21875 -0.3125q0.53125 -0.328125 0.96875 -0.90625l0 -3.921875q-0.390625 -0.53125 -0.859375 -0.734375q-0.46875 -0.21875 -1.03125 -0.21875q-1.140625 0 -1.75 0.8125q-0.609375 0.8125 -0.609375 2.296875q0 0.796875 0.125 1.359375q0.140625 0.5625 0.40625 0.9375q0.265625 0.359375 0.640625 0.53125q0.390625 0.15625 0.890625 0.15625zm10.647003 -5.71875q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm5.5064087 -1.46875q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm7.602646 7.3125q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm8.155426 -6.890625q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm1.8814087 5.78125q0 -0.1875 0.0625 -0.34375q0.078125 -0.171875 0.203125 -0.296875q0.125 -0.125 0.296875 -0.1875q0.171875 -0.078125 0.390625 -0.078125q0.234375 0 0.421875 0.09375q0.1875 0.078125 0.3125 0.234375q0.125 0.15625 0.1875 0.375q0.0625 0.203125 0.0625 0.4375q0 0.359375 -0.109375 0.75q-0.09375 0.390625 -0.296875 0.765625q-0.1875 0.375 -0.46875 0.734375q-0.28125 0.359375 -0.640625 0.671875l-0.25 -0.234375q-0.09375 -0.09375 -0.09375 -0.21875q0 -0.109375 0.109375 -0.21875q0.078125 -0.09375 0.203125 -0.25q0.125 -0.140625 0.25 -0.328125q0.125 -0.1875 0.234375 -0.421875q0.109375 -0.234375 0.15625 -0.5l-0.09375 0q-0.21875 0 -0.390625 -0.0625q-0.15625 -0.078125 -0.28125 -0.203125q-0.125 -0.140625 -0.203125 -0.3125q-0.0625 -0.1875 -0.0625 -0.40625z" fill-rule="nonzero"/><path fill="#000000" d="m49.90917 401.43198q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm5.889801 2.265625q-0.078125 0.15625 -0.1875 0.25q-0.109375 0.109375 -0.328125 0.109375l-1.0625 0l1.484375 -3.21875l-3.34375 -7.640625l1.234375 0q0.1875 0 0.28125 0.09375q0.109375 0.09375 0.15625 0.203125l2.171875 5.109375q0.078125 0.171875 0.125 0.359375q0.046875 0.171875 0.09375 0.359375q0.046875 -0.1875 0.109375 -0.359375q0.0625 -0.1875 0.125 -0.375l2.109375 -5.09375q0.046875 -0.125 0.15625 -0.203125q0.125 -0.09375 0.25 -0.09375l1.140625 0l-4.515625 10.5zm5.8168945 0.359375l0 -10.859375l0.84375 0q0.296875 0 0.390625 0.296875l0.109375 0.96875q0.53125 -0.640625 1.1874962 -1.015625q0.671875 -0.390625 1.546875 -0.390625q0.6875 0 1.25 0.265625q0.578125 0.265625 0.96875 0.796875q0.40625 0.53125 0.625 1.3125q0.21875 0.765625 0.21875 1.765625q0 0.90625 -0.25 1.6875q-0.234375 0.765625 -0.6875 1.328125q-0.4375 0.5625 -1.09375 0.890625q-0.65625 0.3125 -1.46875 0.3125q-0.75 0 -1.2812462 -0.25q-0.53125 -0.25 -0.9375 -0.703125l0 3.59375l-1.421875 0zm3.6093712 -9.84375q-0.703125 0 -1.2343712 0.328125q-0.515625 0.3125 -0.953125 0.890625l0 3.921875q0.390625 0.53125 0.859375 0.75q0.4687462 0.21875 1.0468712 0.21875q1.125 0 1.734375 -0.8125q0.609375 -0.8125 0.609375 -2.3125q0 -0.78125 -0.140625 -1.34375q-0.140625 -0.578125 -0.40625 -0.9375q-0.265625 -0.375 -0.65625 -0.53125q-0.375 -0.171875 -0.859375 -0.171875zm8.425644 -1.140625q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm5.149521 7.1875l0 -8.109375l0.8125 0q0.234375 0 0.3125 0.09375q0.09375 0.09375 0.125 0.296875l0.09375 1.265625q0.421875 -0.84375 1.03125 -1.3125q0.609375 -0.484375 1.4375 -0.484375q0.328125 0 0.59375 0.078125q0.28125 0.078125 0.515625 0.21875l-0.1875 1.0625q-0.046875 0.1875 -0.25 0.1875q-0.109375 0 -0.34375 -0.0625q-0.21875 -0.078125 -0.640625 -0.078125q-0.75 0 -1.25 0.4375q-0.5 0.421875 -0.828125 1.25l0 5.15625l-1.421875 0zm9.651047 -8.234375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm5.462021 7.1875l0 -6.890625l-0.890625 -0.09375q-0.171875 -0.046875 -0.28125 -0.125q-0.109375 -0.09375 -0.109375 -0.25l0 -0.578125l1.28125 0l0 -0.796875q0 -0.6875 0.1875 -1.21875q0.203125 -0.546875 0.5625 -0.921875q0.375 -0.375 0.875 -0.5625q0.515625 -0.1875 1.15625 -0.1875q0.546875 0 1.015625 0.15625l-0.03125 0.703125q-0.015625 0.171875 -0.140625 0.203125q-0.125 0.03125 -0.359375 0.03125l-0.25 0q-0.359375 0 -0.671875 0.09375q-0.296875 0.09375 -0.515625 0.3125q-0.203125 0.21875 -0.328125 0.578125q-0.109375 0.34375 -0.109375 0.859375l0 0.75l2.34375 0l0 1.03125l-2.296875 0l0 6.90625l-1.4375 0zm9.720062 -6.765625q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m5.334504 342.06653l0 0c0 -7.60376 6.164071 -13.767822 13.767837 -13.767822l99.21573 0c3.6514587 0 7.153366 1.450531 9.735336 4.032501c2.5819702 2.5819702 4.032501 6.0838623 4.032501 9.735321l0 55.069702c0 7.60376 -6.16407 13.767853 -13.767838 13.767853l-99.21573 0c-7.6037655 0 -13.767837 -6.164093 -13.767837 -13.767853z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m5.334504 342.06653l0 0c0 -7.60376 6.164071 -13.767822 13.767837 -13.767822l99.21573 0c3.6514587 0 7.153366 1.450531 9.735336 4.032501c2.5819702 2.5819702 4.032501 6.0838623 4.032501 9.735321l0 55.069702c0 7.60376 -6.16407 13.767853 -13.767838 13.767853l-99.21573 0c-7.6037655 0 -13.767837 -6.164093 -13.767837 -13.767853z" fill-rule="evenodd"/><path fill="#000000" d="m52.460945 352.30515l-2.71875 -3.953125l1.359375 0q0.171875 0 0.25 0.0625q0.09375 0.0625 0.15625 0.15625l1.984375 3.046875q0.0625 -0.234375 0.203125 -0.453125l1.75 -2.5625q0.078125 -0.109375 0.15625 -0.171875q0.078125 -0.078125 0.203125 -0.078125l1.3125 0l-2.734375 3.875l2.84375 4.234375l-1.375 0q-0.171875 0 -0.28125 -0.09375q-0.09375 -0.09375 -0.15625 -0.203125l-2.046875 -3.171875q-0.046875 0.234375 -0.15625 0.40625l-1.890625 2.765625q-0.078125 0.109375 -0.171875 0.203125q-0.09375 0.09375 -0.25 0.09375l-1.28125 0l2.84375 -4.15625zm6.173279 4.15625l0 -8.109375l0.8125 0q0.234375 0 0.3125 0.09375q0.09375 0.09375 0.125 0.296875l0.09375 1.265625q0.421875 -0.84375 1.03125 -1.3125q0.609375 -0.484375 1.4375 -0.484375q0.328125 0 0.59375 0.078125q0.28125 0.078125 0.515625 0.21875l-0.1875 1.0625q-0.046875 0.1875 -0.25 0.1875q-0.109375 0 -0.34375 -0.0625q-0.21875 -0.078125 -0.640625 -0.078125q-0.75 0 -1.25 0.4375q-0.5 0.421875 -0.828125 1.25l0 5.15625l-1.421875 0zm9.651047 -8.234375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm5.462021 7.1875l0 -6.890625l-0.890625 -0.09375q-0.171875 -0.046875 -0.28125 -0.125q-0.109375 -0.09375 -0.109375 -0.25l0 -0.578125l1.28125 0l0 -0.796875q0 -0.6875 0.1875 -1.21875q0.203125 -0.546875 0.5625 -0.921875q0.375 -0.375 0.875 -0.5625q0.515625 -0.1875 1.15625 -0.1875q0.546875 0 1.015625 0.15625l-0.03125 0.703125q-0.015625 0.171875 -0.140625 0.203125q-0.125 0.03125 -0.359375 0.03125l-0.25 0q-0.359375 0 -0.671875 0.09375q-0.296875 0.09375 -0.515625 0.3125q-0.203125 0.21875 -0.328125 0.578125q-0.109375 0.34375 -0.109375 0.859375l0 0.75l2.34375 0l0 1.03125l-2.296875 0l0 6.90625l-1.4375 0zm9.720062 -6.765625q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm1.8814087 5.78125q0 -0.1875 0.0625 -0.34375q0.078125 -0.171875 0.203125 -0.296875q0.125 -0.125 0.296875 -0.1875q0.171875 -0.078125 0.390625 -0.078125q0.234375 0 0.421875 0.09375q0.1875 0.078125 0.3125 0.234375q0.125 0.15625 0.1875 0.375q0.0625 0.203125 0.0625 0.4375q0 0.359375 -0.109375 0.75q-0.09375 0.390625 -0.296875 0.765625q-0.1875 0.375 -0.46875 0.734375q-0.28125 0.359375 -0.640625 0.671875l-0.25 -0.234375q-0.09375 -0.09375 -0.09375 -0.21875q0 -0.109375 0.109375 -0.21875q0.078125 -0.09375 0.203125 -0.25q0.125 -0.140625 0.25 -0.328125q0.125 -0.1875 0.234375 -0.421875q0.109375 -0.234375 0.15625 -0.5l-0.09375 0q-0.21875 0 -0.390625 -0.0625q-0.15625 -0.078125 -0.28125 -0.203125q-0.125 -0.140625 -0.203125 -0.3125q-0.0625 -0.1875 -0.0625 -0.40625z" fill-rule="nonzero"/><path fill="#000000" d="m26.954628 375.4614l0 -8.109375l0.84375 0q0.296875 0 0.390625 0.296875l0.09375 0.84375q0.453125 -0.5625 1.0 -0.90625q0.5625 -0.359375 1.296875 -0.359375q0.828125 0 1.328125 0.46875q0.515625 0.453125 0.734375 1.21875q0.171875 -0.4375 0.4375 -0.75q0.28125 -0.328125 0.625 -0.53125q0.34375 -0.21875 0.734375 -0.3125q0.390625 -0.09375 0.796875 -0.09375q0.640625 0 1.140625 0.203125q0.5 0.203125 0.84375 0.59375q0.34375 0.390625 0.53125 0.96875q0.1875 0.578125 0.1875 1.3125l0 5.15625l-1.421875 0l0 -5.15625q0 -0.953125 -0.421875 -1.4375q-0.421875 -0.5 -1.203125 -0.5q-0.359375 0 -0.671875 0.125q-0.3125 0.125 -0.5625 0.359375q-0.234375 0.234375 -0.375 0.609375q-0.140625 0.359375 -0.140625 0.84375l0 5.15625l-1.421875 0l0 -5.15625q0 -0.984375 -0.390625 -1.453125q-0.390625 -0.484375 -1.140625 -0.484375q-0.53125 0 -0.984375 0.28125q-0.453125 0.28125 -0.828125 0.765625l0 6.046875l-1.421875 0zm16.338959 -8.234375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm7.602646 7.3125q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm3.514801 -0.125l0 -11.78125l1.421875 0l0 4.765625q0.515625 -0.546875 1.140625 -0.875q0.640625 -0.34375 1.46875 -0.34375q0.65625 0 1.15625 0.21875q0.515625 0.21875 0.859375 0.625q0.34375 0.40625 0.515625 0.984375q0.171875 0.5625 0.171875 1.25l0 5.15625l-1.421875 0l0 -5.15625q0 -0.921875 -0.421875 -1.421875q-0.421875 -0.515625 -1.28125 -0.515625q-0.625 0 -1.171875 0.3125q-0.546875 0.296875 -1.015625 0.8125l0 5.96875l-1.421875 0zm12.177139 -8.234375q0.875 0 1.59375 0.296875q0.71875 0.296875 1.21875 0.84375q0.5 0.546875 0.765625 1.3125q0.265625 0.765625 0.265625 1.71875q0 0.96875 -0.265625 1.734375q-0.265625 0.765625 -0.765625 1.3125q-0.5 0.546875 -1.21875 0.84375q-0.71875 0.28125 -1.59375 0.28125q-0.890625 0 -1.609375 -0.28125q-0.71875 -0.296875 -1.21875 -0.84375q-0.5 -0.546875 -0.78125 -1.3125q-0.265625 -0.765625 -0.265625 -1.734375q0 -0.953125 0.265625 -1.71875q0.28125 -0.765625 0.78125 -1.3125q0.5 -0.546875 1.21875 -0.84375q0.71875 -0.296875 1.609375 -0.296875zm0 7.234375q1.1875 0 1.78125 -0.796875q0.59375 -0.8125 0.59375 -2.25q0 -1.453125 -0.59375 -2.25q-0.59375 -0.8125 -1.78125 -0.8125q-0.609375 0 -1.0625 0.203125q-0.453125 0.203125 -0.75 0.609375q-0.296875 0.390625 -0.453125 0.96875q-0.140625 0.5625 -0.140625 1.28125q0 0.71875 0.140625 1.296875q0.15625 0.5625 0.453125 0.953125q0.296875 0.375 0.75 0.59375q0.453125 0.203125 1.0625 0.203125zm11.317764 1.0q-0.3125 0 -0.390625 -0.296875l-0.125 -0.984375q-0.515625 0.640625 -1.1875 1.015625q-0.671875 0.375 -1.53125 0.375q-0.703125 0 -1.265625 -0.265625q-0.5625 -0.265625 -0.96875 -0.78125q-0.390625 -0.53125 -0.609375 -1.296875q-0.21875 -0.78125 -0.21875 -1.796875q0 -0.890625 0.234375 -1.65625q0.25 -0.78125 0.6875 -1.34375q0.453125 -0.5625 1.09375 -0.890625q0.65625 -0.328125 1.484375 -0.328125q0.75 0 1.265625 0.25q0.53125 0.25 0.953125 0.71875l0 -4.5l1.421875 0l0 11.78125l-0.84375 0zm-2.765625 -1.046875q0.703125 0 1.21875 -0.3125q0.53125 -0.328125 0.96875 -0.90625l0 -3.921875q-0.390625 -0.53125 -0.859375 -0.734375q-0.46875 -0.21875 -1.03125 -0.21875q-1.140625 0 -1.75 0.8125q-0.609375 0.8125 -0.609375 2.296875q0 0.796875 0.125 1.359375q0.140625 0.5625 0.40625 0.9375q0.265625 0.359375 0.640625 0.53125q0.390625 0.15625 0.890625 0.15625zm10.647003 -5.71875q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm5.5064087 -1.46875q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm7.602646 7.3125q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm8.155426 -6.890625q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm1.8814087 5.78125q0 -0.1875 0.0625 -0.34375q0.078125 -0.171875 0.203125 -0.296875q0.125 -0.125 0.296875 -0.1875q0.171875 -0.078125 0.390625 -0.078125q0.234375 0 0.421875 0.09375q0.1875 0.078125 0.3125 0.234375q0.125 0.15625 0.1875 0.375q0.0625 0.203125 0.0625 0.4375q0 0.359375 -0.109375 0.75q-0.09375 0.390625 -0.296875 0.765625q-0.1875 0.375 -0.46875 0.734375q-0.28125 0.359375 -0.640625 0.671875l-0.25 -0.234375q-0.09375 -0.09375 -0.09375 -0.21875q0 -0.109375 0.109375 -0.21875q0.078125 -0.09375 0.203125 -0.25q0.125 -0.140625 0.25 -0.328125q0.125 -0.1875 0.234375 -0.421875q0.109375 -0.234375 0.15625 -0.5l-0.09375 0q-0.21875 0 -0.390625 -0.0625q-0.15625 -0.078125 -0.28125 -0.203125q-0.125 -0.140625 -0.203125 -0.3125q-0.0625 -0.1875 -0.0625 -0.40625z" fill-rule="nonzero"/><path fill="#000000" d="m43.06357 394.5864q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm5.889801 2.265625q-0.078125 0.15625 -0.1875 0.25q-0.109375 0.109375 -0.328125 0.109375l-1.0625 0l1.484375 -3.21875l-3.34375 -7.640625l1.234375 0q0.1875 0 0.28125 0.09375q0.109375 0.09375 0.15625 0.203125l2.171875 5.109375q0.078125 0.171875 0.125 0.359375q0.046875 0.171875 0.09375 0.359375q0.046875 -0.1875 0.109375 -0.359375q0.0625 -0.1875 0.125 -0.375l2.109375 -5.09375q0.046875 -0.125 0.15625 -0.203125q0.125 -0.09375 0.25 -0.09375l1.140625 0l-4.515625 10.5zm5.8168945 0.359375l0 -10.859375l0.84375 0q0.296875 0 0.390625 0.296875l0.109375 0.96875q0.53125 -0.640625 1.1875 -1.015625q0.671875 -0.390625 1.546875 -0.390625q0.6875 0 1.25 0.265625q0.578125 0.265625 0.96875 0.796875q0.40625 0.53125 0.625 1.3125q0.21875 0.765625 0.21875 1.765625q0 0.90625 -0.25 1.6875q-0.234375 0.765625 -0.6875 1.328125q-0.4375 0.5625 -1.09375 0.890625q-0.65625 0.3125 -1.46875 0.3125q-0.75 0 -1.28125 -0.25q-0.53125 -0.25 -0.9375 -0.703125l0 3.59375l-1.421875 0zm3.609375 -9.84375q-0.703125 0 -1.234375 0.328125q-0.515625 0.3125 -0.953125 0.890625l0 3.921875q0.390625 0.53125 0.859375 0.75q0.46875 0.21875 1.046875 0.21875q1.125 0 1.734375 -0.8125q0.609375 -0.8125 0.609375 -2.3125q0 -0.78125 -0.140625 -1.34375q-0.140625 -0.578125 -0.40625 -0.9375q-0.265625 -0.375 -0.65625 -0.53125q-0.375 -0.171875 -0.859375 -0.171875zm8.425644 -1.140625q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm5.149521 7.1875l0 -8.109375l0.8125 0q0.234375 0 0.3125 0.09375q0.09375 0.09375 0.125 0.296875l0.09375 1.265625q0.421875 -0.84375 1.03125 -1.3125q0.609375 -0.484375 1.4375 -0.484375q0.328125 0 0.59375 0.078125q0.28125 0.078125 0.515625 0.21875l-0.1875 1.0625q-0.046875 0.1875 -0.25 0.1875q-0.109375 0 -0.34375 -0.0625q-0.21875 -0.078125 -0.640625 -0.078125q-0.75 0 -1.25 0.4375q-0.5 0.421875 -0.828125 1.25l0 5.15625l-1.421875 0zm9.651047 -8.234375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm5.462021 7.1875l0 -6.890625l-0.890625 -0.09375q-0.171875 -0.046875 -0.28125 -0.125q-0.109375 -0.09375 -0.109375 -0.25l0 -0.578125l1.28125 0l0 -0.796875q0 -0.6875 0.1875 -1.21875q0.203125 -0.546875 0.5625 -0.921875q0.375 -0.375 0.875 -0.5625q0.515625 -0.1875 1.15625 -0.1875q0.546875 0 1.015625 0.15625l-0.03125 0.703125q-0.015625 0.171875 -0.140625 0.203125q-0.125 0.03125 -0.359375 0.03125l-0.25 0q-0.359375 0 -0.671875 0.09375q-0.296875 0.09375 -0.515625 0.3125q-0.203125 0.21875 -0.328125 0.578125q-0.109375 0.34375 -0.109375 0.859375l0 0.75l2.34375 0l0 1.03125l-2.296875 0l0 6.90625l-1.4375 0zm9.720062 -6.765625q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m188.35957 391.56705l0 0c0 -3.618164 2.933136 -6.5513 6.5513153 -6.5513l247.87375 0c1.7375183 0 3.4038696 0.69021606 4.632477 1.9188232c1.2286072 1.2286072 1.9188538 2.894989 1.9188538 4.632477l0 26.204468c0 3.6181946 -2.933136 6.5513306 -6.5513306 6.5513306l-247.87375 0c-3.6181793 0 -6.5513153 -2.933136 -6.5513153 -6.5513306z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m188.35957 391.56705l0 0c0 -3.618164 2.933136 -6.5513 6.5513153 -6.5513l247.87375 0c1.7375183 0 3.4038696 0.69021606 4.632477 1.9188232c1.2286072 1.2286072 1.9188538 2.894989 1.9188538 4.632477l0 26.204468c0 3.6181946 -2.933136 6.5513306 -6.5513306 6.5513306l-247.87375 0c-3.6181793 0 -6.5513153 -2.933136 -6.5513153 -6.5513306z" fill-rule="evenodd"/><path fill="#000000" d="m296.97263 403.76367q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm5.5064087 -1.46875q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm7.6026306 7.3125q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm5.967926 0q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm5.092926 -8.234375l0 8.109375l-1.421875 0l0 -8.109375l1.421875 0zm0.328125 -2.53125q0 0.203125 -0.09375 0.390625q-0.078125 0.171875 -0.21875 0.3125q-0.140625 0.140625 -0.328125 0.21875q-0.1875 0.078125 -0.390625 0.078125q-0.203125 0 -0.390625 -0.078125q-0.171875 -0.078125 -0.3125 -0.21875q-0.140625 -0.140625 -0.21875 -0.3125q-0.078125 -0.1875 -0.078125 -0.390625q0 -0.21875 0.078125 -0.40625q0.078125 -0.1875 0.21875 -0.328125q0.140625 -0.140625 0.3125 -0.21875q0.1875 -0.078125 0.390625 -0.078125q0.203125 0 0.390625 0.078125q0.1875 0.078125 0.328125 0.21875q0.140625 0.140625 0.21875 0.328125q0.09375 0.1875 0.09375 0.40625zm2.1896973 10.640625l0 -8.109375l0.84375 0q0.296875 0 0.390625 0.296875l0.109375 0.890625q0.53125 -0.59375 1.171875 -0.953125q0.65625 -0.359375 1.515625 -0.359375q0.65625 0 1.15625 0.21875q0.515625 0.21875 0.859375 0.625q0.34375 0.40625 0.515625 0.984375q0.171875 0.5625 0.171875 1.25l0 5.15625l-1.421875 0l0 -5.15625q0 -0.921875 -0.421875 -1.421875q-0.421875 -0.515625 -1.28125 -0.515625q-0.625 0 -1.171875 0.3125q-0.546875 0.296875 -1.015625 0.8125l0 5.96875l-1.421875 0zm11.614655 -8.234375q0.53125 0 0.984375 0.109375q0.46875 0.109375 0.84375 0.34375l2.203125 0l0 0.53125q0 0.265625 -0.34375 0.328125l-0.921875 0.125q0.28125 0.53125 0.28125 1.171875q0 0.578125 -0.234375 1.0625q-0.21875 0.484375 -0.625 0.828125q-0.40625 0.34375 -0.96875 0.53125q-0.546875 0.1875 -1.21875 0.1875q-0.5625 0 -1.0625 -0.140625q-0.265625 0.171875 -0.40625 0.359375q-0.125 0.171875 -0.125 0.34375q0 0.296875 0.234375 0.453125q0.234375 0.140625 0.609375 0.203125q0.390625 0.0625 0.875 0.078125q0.5 0.015625 1.0 0.0625q0.515625 0.03125 1.0 0.125q0.484375 0.078125 0.859375 0.28125q0.390625 0.1875 0.625 0.546875q0.234375 0.34375 0.234375 0.90625q0 0.53125 -0.265625 1.015625q-0.25 0.484375 -0.75 0.859375q-0.484375 0.390625 -1.1875 0.609375q-0.703125 0.234375 -1.59375 0.234375q-0.875 0 -1.546875 -0.1875q-0.671875 -0.171875 -1.109375 -0.46875q-0.4375 -0.296875 -0.65625 -0.6875q-0.21875 -0.375 -0.21875 -0.796875q0 -0.609375 0.375 -1.015625q0.375 -0.421875 1.046875 -0.671875q-0.34375 -0.171875 -0.546875 -0.4375q-0.203125 -0.265625 -0.203125 -0.71875q0 -0.171875 0.0625 -0.359375q0.0625 -0.1875 0.1875 -0.359375q0.140625 -0.1875 0.328125 -0.359375q0.1875 -0.171875 0.453125 -0.296875q-0.609375 -0.34375 -0.953125 -0.890625q-0.328125 -0.5625 -0.328125 -1.296875q0 -0.59375 0.21875 -1.078125q0.234375 -0.484375 0.640625 -0.828125q0.40625 -0.34375 0.96875 -0.515625q0.5625 -0.1875 1.234375 -0.1875zm2.53125 8.671875q0 -0.296875 -0.171875 -0.484375q-0.15625 -0.1875 -0.453125 -0.28125q-0.28125 -0.109375 -0.65625 -0.15625q-0.375 -0.046875 -0.796875 -0.0625q-0.421875 -0.015625 -0.859375 -0.03125q-0.421875 -0.03125 -0.8125 -0.109375q-0.453125 0.21875 -0.75 0.53125q-0.28125 0.3125 -0.28125 0.75q0 0.265625 0.140625 0.5q0.140625 0.25 0.421875 0.421875q0.296875 0.171875 0.734375 0.265625q0.4375 0.09375 1.03125 0.09375q0.578125 0 1.03125 -0.109375q0.453125 -0.09375 0.765625 -0.296875q0.328125 -0.1875 0.484375 -0.453125q0.171875 -0.25 0.171875 -0.578125zm-2.53125 -4.390625q0.4375 0 0.765625 -0.125q0.328125 -0.125 0.546875 -0.328125q0.234375 -0.21875 0.34375 -0.515625q0.109375 -0.3125 0.109375 -0.671875q0 -0.734375 -0.453125 -1.171875q-0.4375 -0.453125 -1.3125 -0.453125q-0.84375 0 -1.296875 0.453125q-0.453125 0.4375 -0.453125 1.171875q0 0.359375 0.109375 0.671875q0.125 0.296875 0.34375 0.515625q0.21875 0.203125 0.546875 0.328125q0.328125 0.125 0.75 0.125zm10.097748 -2.8125q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m188.35957 171.30994l0 0c0 -7.6045837 6.164734 -13.769302 13.769318 -13.769302l96.52437 0c3.6518555 0 7.1541443 1.4506836 9.736389 4.0329285c2.5822449 2.5822449 4.0329285 6.0845184 4.0329285 9.736374l0 55.07556c0 7.6045837 -6.164734 13.769302 -13.769318 13.769302l-96.52437 0c-7.6045837 0 -13.769318 -6.1647186 -13.769318 -13.769302z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m188.35957 171.30994l0 0c0 -7.6045837 6.164734 -13.769302 13.769318 -13.769302l96.52437 0c3.6518555 0 7.1541443 1.4506836 9.736389 4.0329285c2.5822449 2.5822449 4.0329285 6.0845184 4.0329285 9.736374l0 55.07556c0 7.6045837 -6.164734 13.769302 -13.769318 13.769302l-96.52437 0c-7.6045837 0 -13.769318 -6.1647186 -13.769318 -13.769302z" fill-rule="evenodd"/><path fill="#000000" d="m231.106 188.47334q0.53125 0 0.984375 0.109375q0.46875 0.109375 0.84375 0.34375l2.203125 0l0 0.53125q0 0.265625 -0.34375 0.328125l-0.921875 0.125q0.28125 0.53125 0.28125 1.171875q0 0.578125 -0.234375 1.0625q-0.21875 0.484375 -0.625 0.828125q-0.40625 0.34375 -0.96875 0.53125q-0.546875 0.1875 -1.21875 0.1875q-0.5625 0 -1.0625 -0.140625q-0.265625 0.171875 -0.40625 0.359375q-0.125 0.171875 -0.125 0.34375q0 0.296875 0.234375 0.453125q0.234375 0.140625 0.609375 0.203125q0.390625 0.0625 0.875 0.078125q0.5 0.015625 1.0 0.0625q0.515625 0.03125 1.0 0.125q0.484375 0.078125 0.859375 0.28125q0.390625 0.1875 0.625 0.546875q0.234375 0.34375 0.234375 0.90625q0 0.53125 -0.265625 1.015625q-0.25 0.484375 -0.75 0.859375q-0.484375 0.390625 -1.1875 0.609375q-0.703125 0.234375 -1.59375 0.234375q-0.875 0 -1.546875 -0.1875q-0.671875 -0.171875 -1.109375 -0.46875q-0.4375 -0.296875 -0.65625 -0.6875q-0.21875 -0.375 -0.21875 -0.796875q0 -0.609375 0.375 -1.015625q0.375 -0.421875 1.046875 -0.671875q-0.34375 -0.171875 -0.546875 -0.4375q-0.203125 -0.265625 -0.203125 -0.71875q0 -0.171875 0.0625 -0.359375q0.0625 -0.1875 0.1875 -0.359375q0.140625 -0.1875 0.328125 -0.359375q0.1875 -0.171875 0.453125 -0.296875q-0.609375 -0.34375 -0.953125 -0.890625q-0.328125 -0.5625 -0.328125 -1.296875q0 -0.59375 0.21875 -1.078125q0.234375 -0.484375 0.640625 -0.828125q0.40625 -0.34375 0.96875 -0.515625q0.5625 -0.1875 1.234375 -0.1875zm2.53125 8.671875q0 -0.296875 -0.171875 -0.484375q-0.15625 -0.1875 -0.453125 -0.28125q-0.28125 -0.109375 -0.65625 -0.15625q-0.375 -0.046875 -0.796875 -0.0625q-0.421875 -0.015625 -0.859375 -0.03125q-0.421875 -0.03125 -0.8125 -0.109375q-0.453125 0.21875 -0.75 0.53125q-0.28125 0.3125 -0.28125 0.75q0 0.265625 0.140625 0.5q0.140625 0.25 0.421875 0.421875q0.296875 0.171875 0.734375 0.265625q0.4375 0.09375 1.03125 0.09375q0.578125 0 1.03125 -0.109375q0.453125 -0.09375 0.765625 -0.296875q0.328125 -0.1875 0.484375 -0.453125q0.171875 -0.25 0.171875 -0.578125zm-2.53125 -4.390625q0.4375 0 0.765625 -0.125q0.328125 -0.125 0.546875 -0.328125q0.234375 -0.21875 0.34375 -0.515625q0.109375 -0.3125 0.109375 -0.671875q0 -0.734375 -0.453125 -1.171875q-0.4375 -0.453125 -1.3125 -0.453125q-0.84375 0 -1.296875 0.453125q-0.453125 0.4375 -0.453125 1.171875q0 0.359375 0.109375 0.671875q0.125 0.296875 0.34375 0.515625q0.21875 0.203125 0.546875 0.328125q0.328125 0.125 0.75 0.125zm8.738388 -4.28125q0.875 0 1.59375 0.296875q0.71875 0.296875 1.21875 0.84375q0.5 0.546875 0.765625 1.3125q0.265625 0.765625 0.265625 1.71875q0 0.96875 -0.265625 1.734375q-0.265625 0.765625 -0.765625 1.3125q-0.5 0.546875 -1.21875 0.84375q-0.71875 0.28125 -1.59375 0.28125q-0.890625 0 -1.609375 -0.28125q-0.71875 -0.296875 -1.21875 -0.84375q-0.5 -0.546875 -0.78125 -1.3125q-0.265625 -0.765625 -0.265625 -1.734375q0 -0.953125 0.265625 -1.71875q0.28125 -0.765625 0.78125 -1.3125q0.5 -0.546875 1.21875 -0.84375q0.71875 -0.296875 1.609375 -0.296875zm0 7.234375q1.1875 0 1.78125 -0.796875q0.59375 -0.8125 0.59375 -2.25q0 -1.453125 -0.59375 -2.25q-0.59375 -0.8125 -1.78125 -0.8125q-0.609375 0 -1.0625 0.203125q-0.453125 0.203125 -0.75 0.609375q-0.296875 0.390625 -0.453125 0.96875q-0.140625 0.5625 -0.140625 1.28125q0 0.71875 0.140625 1.296875q0.15625 0.5625 0.453125 0.953125q0.296875 0.375 0.75 0.59375q0.453125 0.203125 1.0625 0.203125zm7.1927643 -10.78125l0 11.78125l-1.421875 0l0 -11.78125l1.421875 0zm8.470947 11.78125l-0.640625 0q-0.203125 0 -0.328125 -0.0625q-0.125 -0.0625 -0.171875 -0.28125l-0.15625 -0.75q-0.328125 0.296875 -0.640625 0.53125q-0.296875 0.21875 -0.640625 0.375q-0.328125 0.15625 -0.703125 0.234375q-0.375 0.078125 -0.84375 0.078125q-0.46875 0 -0.890625 -0.125q-0.40625 -0.140625 -0.71875 -0.390625q-0.296875 -0.265625 -0.484375 -0.671875q-0.171875 -0.40625 -0.171875 -0.96875q0 -0.46875 0.265625 -0.90625q0.265625 -0.453125 0.84375 -0.796875q0.59375 -0.34375 1.546875 -0.5625q0.953125 -0.21875 2.328125 -0.25l0 -0.640625q0 -0.9375 -0.40625 -1.421875q-0.40625 -0.484375 -1.1875 -0.484375q-0.53125 0 -0.890625 0.140625q-0.34375 0.125 -0.609375 0.296875q-0.25 0.15625 -0.453125 0.296875q-0.1875 0.125 -0.359375 0.125q-0.15625 0 -0.265625 -0.078125q-0.09375 -0.078125 -0.15625 -0.1875l-0.265625 -0.453125q0.671875 -0.65625 1.453125 -0.96875q0.78125 -0.328125 1.71875 -0.328125q0.671875 0 1.203125 0.234375q0.53125 0.21875 0.890625 0.625q0.359375 0.390625 0.546875 0.96875q0.1875 0.5625 0.1875 1.234375l0 5.1875zm-3.703125 -0.875q0.375 0 0.6875 -0.078125q0.3125 -0.078125 0.578125 -0.203125q0.28125 -0.140625 0.53125 -0.34375q0.265625 -0.203125 0.5 -0.453125l0 -1.6875q-0.984375 0.03125 -1.671875 0.15625q-0.6875 0.109375 -1.125 0.3125q-0.421875 0.203125 -0.625 0.484375q-0.1875 0.265625 -0.1875 0.59375q0 0.328125 0.09375 0.5625q0.109375 0.234375 0.28125 0.375q0.171875 0.140625 0.40625 0.21875q0.25 0.0625 0.53125 0.0625zm5.8618927 0.875l0 -8.109375l0.84375 0q0.296875 0 0.390625 0.296875l0.109375 0.890625q0.53125 -0.59375 1.171875 -0.953125q0.65625 -0.359375 1.515625 -0.359375q0.65625 0 1.15625 0.21875q0.515625 0.21875 0.859375 0.625q0.34375 0.40625 0.515625 0.984375q0.171875 0.5625 0.171875 1.25l0 5.15625l-1.421875 0l0 -5.15625q0 -0.921875 -0.421875 -1.421875q-0.421875 -0.515625 -1.28125 -0.515625q-0.625 0 -1.171875 0.3125q-0.546875 0.296875 -1.015625 0.8125l0 5.96875l-1.421875 0zm11.614655 -8.234375q0.53125 0 0.984375 0.109375q0.46875 0.109375 0.84375 0.34375l2.203125 0l0 0.53125q0 0.265625 -0.34375 0.328125l-0.921875 0.125q0.28125 0.53125 0.28125 1.171875q0 0.578125 -0.234375 1.0625q-0.21875 0.484375 -0.625 0.828125q-0.40625 0.34375 -0.96875 0.53125q-0.546875 0.1875 -1.21875 0.1875q-0.5625 0 -1.0625 -0.140625q-0.265625 0.171875 -0.40625 0.359375q-0.125 0.171875 -0.125 0.34375q0 0.296875 0.234375 0.453125q0.234375 0.140625 0.609375 0.203125q0.390625 0.0625 0.875 0.078125q0.5 0.015625 1.0 0.0625q0.515625 0.03125 1.0 0.125q0.484375 0.078125 0.859375 0.28125q0.390625 0.1875 0.625 0.546875q0.234375 0.34375 0.234375 0.90625q0 0.53125 -0.265625 1.015625q-0.25 0.484375 -0.75 0.859375q-0.484375 0.390625 -1.1875 0.609375q-0.703125 0.234375 -1.59375 0.234375q-0.875 0 -1.546875 -0.1875q-0.671875 -0.171875 -1.109375 -0.46875q-0.4375 -0.296875 -0.65625 -0.6875q-0.21875 -0.375 -0.21875 -0.796875q0 -0.609375 0.375 -1.015625q0.375 -0.421875 1.046875 -0.671875q-0.34375 -0.171875 -0.546875 -0.4375q-0.203125 -0.265625 -0.203125 -0.71875q0 -0.171875 0.0625 -0.359375q0.0625 -0.1875 0.1875 -0.359375q0.140625 -0.1875 0.328125 -0.359375q0.1875 -0.171875 0.453125 -0.296875q-0.609375 -0.34375 -0.953125 -0.890625q-0.328125 -0.5625 -0.328125 -1.296875q0 -0.59375 0.21875 -1.078125q0.234375 -0.484375 0.640625 -0.828125q0.40625 -0.34375 0.96875 -0.515625q0.5625 -0.1875 1.234375 -0.1875zm2.53125 8.671875q0 -0.296875 -0.171875 -0.484375q-0.15625 -0.1875 -0.453125 -0.28125q-0.28125 -0.109375 -0.65625 -0.15625q-0.375 -0.046875 -0.796875 -0.0625q-0.421875 -0.015625 -0.859375 -0.03125q-0.421875 -0.03125 -0.8125 -0.109375q-0.453125 0.21875 -0.75 0.53125q-0.28125 0.3125 -0.28125 0.75q0 0.265625 0.140625 0.5q0.140625 0.25 0.421875 0.421875q0.296875 0.171875 0.734375 0.265625q0.4375 0.09375 1.03125 0.09375q0.578125 0 1.03125 -0.109375q0.453125 -0.09375 0.765625 -0.296875q0.328125 -0.1875 0.484375 -0.453125q0.171875 -0.25 0.171875 -0.578125zm-2.53125 -4.390625q0.4375 0 0.765625 -0.125q0.328125 -0.125 0.546875 -0.328125q0.234375 -0.21875 0.34375 -0.515625q0.109375 -0.3125 0.109375 -0.671875q0 -0.734375 -0.453125 -1.171875q-0.4375 -0.453125 -1.3125 -0.453125q-0.84375 0 -1.296875 0.453125q-0.453125 0.4375 -0.453125 1.171875q0 0.359375 0.109375 0.671875q0.125 0.296875 0.34375 0.515625q0.21875 0.203125 0.546875 0.328125q0.328125 0.125 0.75 0.125z" fill-rule="nonzero"/><path fill="#000000" d="m239.95792 208.96022q0 1.421875 0.359375 2.765625q0.375 1.34375 1.078125 2.5625q0.03125 0.078125 0.046875 0.125q0.015625 0.046875 0.015625 0.109375q0 0.09375 -0.046875 0.15625q-0.046875 0.0625 -0.125 0.09375l-0.53125 0.328125q-0.5 -0.765625 -0.84375 -1.515625q-0.34375 -0.75 -0.5625 -1.515625q-0.21875 -0.765625 -0.328125 -1.53125q-0.09375 -0.765625 -0.09375 -1.578125q0 -0.8125 0.09375 -1.578125q0.109375 -0.78125 0.328125 -1.53125q0.21875 -0.765625 0.5625 -1.515625q0.34375 -0.75 0.84375 -1.515625l0.53125 0.3125q0.078125 0.046875 0.125 0.109375q0.046875 0.0625 0.046875 0.15625q0 0.09375 -0.0625 0.234375q-0.703125 1.203125 -1.078125 2.546875q-0.359375 1.34375 -0.359375 2.78125zm7.2317657 3.25q0.375 0 0.703125 -0.03125q0.328125 -0.046875 0.609375 -0.109375q0.296875 -0.078125 0.546875 -0.171875q0.25 -0.109375 0.5 -0.25l0 -2.109375l-1.484375 0q-0.125 0 -0.203125 -0.0625q-0.0625 -0.078125 -0.0625 -0.1875l0 -0.734375l2.921875 0l0 3.671875q-0.359375 0.25 -0.75 0.453125q-0.390625 0.1875 -0.828125 0.328125q-0.4375 0.125 -0.953125 0.1875q-0.5 0.0625 -1.09375 0.0625q-1.046875 0 -1.921875 -0.359375q-0.859375 -0.359375 -1.484375 -1.0q-0.625 -0.640625 -0.984375 -1.53125q-0.34375 -0.90625 -0.34375 -1.984375q0 -1.09375 0.34375 -1.984375q0.34375 -0.90625 0.984375 -1.546875q0.640625 -0.65625 1.53125 -1.0q0.90625 -0.359375 2.03125 -0.359375q0.5625 0 1.046875 0.09375q0.5 0.078125 0.90625 0.234375q0.421875 0.15625 0.765625 0.375q0.359375 0.21875 0.671875 0.5l-0.375 0.59375q-0.109375 0.171875 -0.296875 0.171875q-0.09375 0 -0.21875 -0.0625q-0.171875 -0.09375 -0.390625 -0.21875q-0.203125 -0.140625 -0.5 -0.265625q-0.296875 -0.125 -0.703125 -0.203125q-0.390625 -0.09375 -0.953125 -0.09375q-0.796875 0 -1.453125 0.265625q-0.65625 0.25 -1.125 0.75q-0.453125 0.484375 -0.703125 1.1875q-0.234375 0.6875 -0.234375 1.5625q0 0.90625 0.25 1.609375q0.265625 0.703125 0.71875 1.203125q0.46875 0.5 1.109375 0.765625q0.640625 0.25 1.421875 0.25zm8.064056 -5.921875q0.734375 0 1.3281097 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59373474 0.234375 -1.3281097 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q0.99998474 0 1.4843597 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.4843597 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm5.4783173 -3.359375q0 -1.4375 -0.359375 -2.78125q-0.359375 -1.34375 -1.0625 -2.546875q-0.0625 -0.140625 -0.0625 -0.234375q0 -0.09375 0.046875 -0.15625q0.046875 -0.0625 0.109375 -0.109375l0.53125 -0.3125q0.5 0.765625 0.84375 1.515625q0.359375 0.75 0.5625 1.515625q0.21875 0.75 0.3125 1.53125q0.109375 0.765625 0.109375 1.578125q0 0.8125 -0.109375 1.578125q-0.09375 0.765625 -0.3125 1.53125q-0.203125 0.765625 -0.5625 1.515625q-0.34375 0.75 -0.84375 1.515625l-0.53125 -0.328125q-0.0625 -0.03125 -0.109375 -0.09375q-0.046875 -0.0625 -0.046875 -0.15625q0 -0.0625 0 -0.109375q0.015625 -0.046875 0.0625 -0.125q0.6875 -1.21875 1.046875 -2.5625q0.375 -1.34375 0.375 -2.765625z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m325.27264 171.30994l0 0c0 -7.6045837 6.164734 -13.769302 13.769287 -13.769302l96.52438 0c3.6518555 0 7.1541443 1.4506836 9.736389 4.0329285c2.5822449 2.5822449 4.0329285 6.0845184 4.0329285 9.736374l0 55.07556c0 7.6045837 -6.164734 13.769302 -13.769318 13.769302l-96.52438 0c-7.604553 0 -13.769287 -6.1647186 -13.769287 -13.769302z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m325.27264 171.30994l0 0c0 -7.6045837 6.164734 -13.769302 13.769287 -13.769302l96.52438 0c3.6518555 0 7.1541443 1.4506836 9.736389 4.0329285c2.5822449 2.5822449 4.0329285 6.0845184 4.0329285 9.736374l0 55.07556c0 7.6045837 -6.164734 13.769302 -13.769318 13.769302l-96.52438 0c-7.604553 0 -13.769287 -6.1647186 -13.769287 -13.769302z" fill-rule="evenodd"/><path fill="#000000" d="m372.98822 196.70772l0 -8.109375l0.84375 0q0.296875 0 0.390625 0.296875l0.09375 0.84375q0.453125 -0.5625 1.0 -0.90625q0.5625 -0.359375 1.296875 -0.359375q0.828125 0 1.328125 0.46875q0.515625 0.453125 0.734375 1.21875q0.171875 -0.4375 0.4375 -0.75q0.28125 -0.328125 0.625 -0.53125q0.34375 -0.21875 0.734375 -0.3125q0.390625 -0.09375 0.796875 -0.09375q0.640625 0 1.140625 0.203125q0.5 0.203125 0.84375 0.59375q0.34375 0.390625 0.53125 0.96875q0.1875 0.578125 0.1875 1.3125l0 5.15625l-1.421875 0l0 -5.15625q0 -0.953125 -0.421875 -1.4375q-0.421875 -0.5 -1.203125 -0.5q-0.359375 0 -0.671875 0.125q-0.3125 0.125 -0.5625 0.359375q-0.234375 0.234375 -0.375 0.609375q-0.140625 0.359375 -0.140625 0.84375l0 5.15625l-1.421875 0l0 -5.15625q0 -0.984375 -0.390625 -1.453125q-0.390625 -0.484375 -1.140625 -0.484375q-0.53125 0 -0.984375 0.28125q-0.453125 0.28125 -0.828125 0.765625l0 6.046875l-1.421875 0zm16.417084 -8.234375q0.875 0 1.59375 0.296875q0.71875 0.296875 1.21875 0.84375q0.5 0.546875 0.765625 1.3125q0.265625 0.765625 0.265625 1.71875q0 0.96875 -0.265625 1.734375q-0.265625 0.765625 -0.765625 1.3125q-0.5 0.546875 -1.21875 0.84375q-0.71875 0.28125 -1.59375 0.28125q-0.890625 0 -1.609375 -0.28125q-0.71875 -0.296875 -1.21875 -0.84375q-0.5 -0.546875 -0.78125 -1.3125q-0.265625 -0.765625 -0.265625 -1.734375q0 -0.953125 0.265625 -1.71875q0.28125 -0.765625 0.78125 -1.3125q0.5 -0.546875 1.21875 -0.84375q0.71875 -0.296875 1.609375 -0.296875zm0 7.234375q1.1875 0 1.78125 -0.796875q0.59375 -0.8125 0.59375 -2.25q0 -1.453125 -0.59375 -2.25q-0.59375 -0.8125 -1.78125 -0.8125q-0.609375 0 -1.0625 0.203125q-0.453125 0.203125 -0.75 0.609375q-0.296875 0.390625 -0.453125 0.96875q-0.140625 0.5625 -0.140625 1.28125q0 0.71875 0.140625 1.296875q0.15625 0.5625 0.453125 0.953125q0.296875 0.375 0.75 0.59375q0.453125 0.203125 1.0625 0.203125zm11.317749 1.0q-0.3125 0 -0.390625 -0.296875l-0.125 -0.984375q-0.515625 0.640625 -1.1875 1.015625q-0.671875 0.375 -1.53125 0.375q-0.703125 0 -1.265625 -0.265625q-0.5625 -0.265625 -0.96875 -0.78125q-0.390625 -0.53125 -0.609375 -1.296875q-0.21875 -0.78125 -0.21875 -1.796875q0 -0.890625 0.234375 -1.65625q0.25 -0.78125 0.6875 -1.34375q0.453125 -0.5625 1.09375 -0.890625q0.65625 -0.328125 1.484375 -0.328125q0.75 0 1.265625 0.25q0.53125 0.25 0.953125 0.71875l0 -4.5l1.421875 0l0 11.78125l-0.84375 0zm-2.765625 -1.046875q0.703125 0 1.21875 -0.3125q0.53125 -0.328125 0.96875 -0.90625l0 -3.921875q-0.390625 -0.53125 -0.859375 -0.734375q-0.46875 -0.21875 -1.03125 -0.21875q-1.140625 0 -1.75 0.8125q-0.609375 0.8125 -0.609375 2.296875q0 0.796875 0.125 1.359375q0.140625 0.5625 0.40625 0.9375q0.265625 0.359375 0.640625 0.53125q0.390625 0.15625 0.890625 0.15625z" fill-rule="nonzero"/><path fill="#000000" d="m363.8027 208.96022q0 1.421875 0.359375 2.765625q0.375 1.34375 1.078125 2.5625q0.03125 0.078125 0.046875 0.125q0.015625 0.046875 0.015625 0.109375q0 0.09375 -0.046875 0.15625q-0.046875 0.0625 -0.125 0.09375l-0.53125 0.328125q-0.5 -0.765625 -0.84375 -1.515625q-0.34375 -0.75 -0.5625 -1.515625q-0.21875 -0.765625 -0.328125 -1.53125q-0.09375 -0.765625 -0.09375 -1.578125q0 -0.8125 0.09375 -1.578125q0.109375 -0.78125 0.328125 -1.53125q0.21875 -0.765625 0.5625 -1.515625q0.34375 -0.75 0.84375 -1.515625l0.53125 0.3125q0.078125 0.046875 0.125 0.109375q0.046875 0.0625 0.046875 0.15625q0 0.09375 -0.0625 0.234375q-0.703125 1.203125 -1.078125 2.546875q-0.359375 1.34375 -0.359375 2.78125zm5.326538 -2.671875q0.4375 0 0.8125 0.09375q0.390625 0.09375 0.703125 0.28125l1.828125 0l0 0.4375q0 0.21875 -0.28125 0.28125l-0.765625 0.109375q0.234375 0.4375 0.234375 0.96875q0 0.484375 -0.203125 0.890625q-0.1875 0.40625 -0.53125 0.703125q-0.328125 0.28125 -0.796875 0.4375q-0.453125 0.140625 -1.0 0.140625q-0.484375 0 -0.890625 -0.109375q-0.21875 0.125 -0.328125 0.28125q-0.109375 0.15625 -0.109375 0.296875q0 0.25 0.1875 0.375q0.203125 0.125 0.515625 0.171875q0.328125 0.046875 0.734375 0.0625q0.40625 0.015625 0.828125 0.046875q0.421875 0.03125 0.828125 0.109375q0.40625 0.0625 0.71875 0.234375q0.328125 0.171875 0.515625 0.46875q0.1875 0.28125 0.1875 0.75q0 0.4375 -0.21875 0.84375q-0.203125 0.40625 -0.609375 0.71875q-0.40625 0.3125 -1.0 0.5q-0.578125 0.203125 -1.328125 0.203125q-0.734375 0 -1.296875 -0.15625q-0.546875 -0.140625 -0.921875 -0.390625q-0.359375 -0.25 -0.546875 -0.578125q-0.1875 -0.3125 -0.1875 -0.671875q0 -0.5 0.3125 -0.84375q0.328125 -0.34375 0.875 -0.5625q-0.28125 -0.125 -0.453125 -0.34375q-0.171875 -0.234375 -0.171875 -0.609375q0 -0.140625 0.046875 -0.296875q0.0625 -0.15625 0.171875 -0.3125q0.109375 -0.15625 0.265625 -0.296875q0.171875 -0.140625 0.375 -0.234375q-0.5 -0.28125 -0.78125 -0.75q-0.28125 -0.46875 -0.28125 -1.078125q0 -0.5 0.1875 -0.890625q0.1875 -0.40625 0.53125 -0.6875q0.34375 -0.296875 0.8125 -0.4375q0.46875 -0.15625 1.03125 -0.15625zm2.09375 7.21875q0 -0.25 -0.140625 -0.390625q-0.125 -0.15625 -0.375 -0.234375q-0.234375 -0.09375 -0.546875 -0.125q-0.3125 -0.046875 -0.671875 -0.0625q-0.34375 -0.015625 -0.703125 -0.03125q-0.359375 -0.03125 -0.6875 -0.078125q-0.375 0.171875 -0.609375 0.4375q-0.234375 0.265625 -0.234375 0.625q0 0.21875 0.109375 0.40625q0.125 0.203125 0.359375 0.34375q0.234375 0.15625 0.59375 0.234375q0.375 0.078125 0.875 0.078125q0.46875 0 0.84375 -0.09375q0.390625 -0.078125 0.65625 -0.234375q0.265625 -0.15625 0.390625 -0.375q0.140625 -0.21875 0.140625 -0.5zm-2.09375 -3.65625q0.359375 0 0.625 -0.09375q0.28125 -0.109375 0.46875 -0.28125q0.1875 -0.1875 0.28125 -0.4375q0.09375 -0.25 0.09375 -0.546875q0 -0.625 -0.375 -0.984375q-0.375 -0.375 -1.09375 -0.375q-0.71875 0 -1.09375 0.375q-0.375 0.359375 -0.375 0.984375q0 0.296875 0.09375 0.546875q0.09375 0.25 0.28125 0.4375q0.1875 0.171875 0.453125 0.28125q0.28125 0.09375 0.640625 0.09375zm7.263794 -3.5625q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm4.3010254 0.09375q0 -0.171875 0.0625 -0.328125q0.0625 -0.15625 0.171875 -0.265625q0.109375 -0.109375 0.25 -0.171875q0.15625 -0.078125 0.328125 -0.078125q0.1875 0 0.328125 0.078125q0.15625 0.0625 0.265625 0.171875q0.125 0.109375 0.1875 0.265625q0.0625 0.15625 0.0625 0.328125q0 0.1875 -0.0625 0.34375q-0.0625 0.140625 -0.1875 0.25q-0.109375 0.109375 -0.265625 0.171875q-0.140625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.25 -0.171875q-0.109375 -0.109375 -0.171875 -0.25q-0.0625 -0.15625 -0.0625 -0.34375zm3.2005615 0.734375l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.078125 0.6875q0.375 -0.453125 0.84375 -0.75q0.46875 -0.296875 1.078125 -0.296875q0.6875 0 1.109375 0.390625q0.421875 0.375 0.609375 1.015625q0.140625 -0.359375 0.359375 -0.625q0.234375 -0.265625 0.515625 -0.4375q0.296875 -0.1875 0.609375 -0.265625q0.328125 -0.078125 0.671875 -0.078125q0.53125 0 0.9375 0.171875q0.421875 0.171875 0.703125 0.5q0.296875 0.328125 0.453125 0.8125q0.15625 0.46875 0.15625 1.078125l0 4.296875l-1.1875 0l0 -4.296875q0 -0.796875 -0.34375 -1.203125q-0.34375 -0.40625 -1.015625 -0.40625q-0.28125 0 -0.546875 0.109375q-0.265625 0.09375 -0.46875 0.296875q-0.203125 0.203125 -0.328125 0.5q-0.109375 0.296875 -0.109375 0.703125l0 4.296875l-1.1875 0l0 -4.296875q0 -0.8125 -0.328125 -1.203125q-0.3125 -0.40625 -0.9375 -0.40625q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.6875 0.640625l0 5.03125l-1.1875 0zm13.676727 -6.859375q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm9.426025 0.828125q-0.25 0 -0.3125 -0.25l-0.109375 -0.8125q-0.4375 0.515625 -1.0 0.84375q-0.546875 0.3125 -1.265625 0.3125q-0.578125 0 -1.0625 -0.21875q-0.46875 -0.234375 -0.796875 -0.65625q-0.328125 -0.4375 -0.515625 -1.078125q-0.171875 -0.65625 -0.171875 -1.5q0 -0.734375 0.1875 -1.375q0.203125 -0.65625 0.578125 -1.125q0.375 -0.46875 0.921875 -0.734375q0.546875 -0.28125 1.234375 -0.28125q0.609375 0 1.046875 0.21875q0.4375 0.203125 0.796875 0.578125l0 -3.734375l1.1875 0l0 9.8125l-0.71875 0zm-2.296875 -0.859375q0.578125 0 1.015625 -0.265625q0.4375 -0.28125 0.8125 -0.765625l0 -3.265625q-0.328125 -0.4375 -0.71875 -0.609375q-0.390625 -0.171875 -0.859375 -0.171875q-0.953125 0 -1.46875 0.671875q-0.5 0.671875 -0.5 1.90625q0 0.671875 0.109375 1.140625q0.125 0.46875 0.34375 0.78125q0.21875 0.296875 0.53125 0.4375q0.328125 0.140625 0.734375 0.140625zm6.012909 -3.328125q0 -1.4375 -0.359375 -2.78125q-0.359375 -1.34375 -1.0625 -2.546875q-0.0625 -0.140625 -0.0625 -0.234375q0 -0.09375 0.046875 -0.15625q0.046875 -0.0625 0.109375 -0.109375l0.53125 -0.3125q0.5 0.765625 0.84375 1.515625q0.359375 0.75 0.5625 1.515625q0.21875 0.75 0.3125 1.53125q0.109375 0.765625 0.109375 1.578125q0 0.8125 -0.109375 1.578125q-0.09375 0.765625 -0.3125 1.53125q-0.203125 0.765625 -0.5625 1.515625q-0.34375 0.75 -0.84375 1.515625l-0.53125 -0.328125q-0.0625 -0.03125 -0.109375 -0.09375q-0.046875 -0.0625 -0.046875 -0.15625q0 -0.0625 0 -0.109375q0.015625 -0.046875 0.0625 -0.125q0.6875 -1.21875 1.046875 -2.5625q0.375 -1.34375 0.375 -2.765625z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m462.1857 171.30994l0 0c0 -7.6045837 6.1647034 -13.769302 13.769287 -13.769302l96.52438 0c3.6518555 0 7.154114 1.4506836 9.736389 4.0329285c2.5822144 2.5822449 4.032898 6.0845184 4.032898 9.736374l0 55.07556c0 7.6045837 -6.164673 13.769302 -13.769287 13.769302l-96.52438 0c-7.6045837 0 -13.769287 -6.1647186 -13.769287 -13.769302z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m462.1857 171.30994l0 0c0 -7.6045837 6.1647034 -13.769302 13.769287 -13.769302l96.52438 0c3.6518555 0 7.154114 1.4506836 9.736389 4.0329285c2.5822144 2.5822449 4.032898 6.0845184 4.032898 9.736374l0 55.07556c0 7.6045837 -6.164673 13.769302 -13.769287 13.769302l-96.52438 0c-7.6045837 0 -13.769287 -6.1647186 -13.769287 -13.769302z" fill-rule="evenodd"/><path fill="#000000" d="m506.33478 188.59834l1.125 0q0.171875 0 0.28125 0.09375q0.109375 0.09375 0.15625 0.203125l1.546875 5.21875q0.0625 0.296875 0.125 0.5625q0.0625 0.265625 0.09375 0.53125q0.0625 -0.265625 0.140625 -0.53125q0.078125 -0.265625 0.171875 -0.5625l1.71875 -5.25q0.03125 -0.109375 0.125 -0.1875q0.109375 -0.09375 0.265625 -0.09375l0.609375 0q0.15625 0 0.265625 0.09375q0.109375 0.078125 0.140625 0.1875l1.671875 5.25q0.09375 0.28125 0.15625 0.5625q0.078125 0.265625 0.140625 0.53125q0.03125 -0.265625 0.09375 -0.546875q0.078125 -0.296875 0.140625 -0.546875l1.578125 -5.21875q0.046875 -0.125 0.15625 -0.203125q0.109375 -0.09375 0.265625 -0.09375l1.078125 0l-2.625 8.109375l-1.125 0q-0.21875 0 -0.296875 -0.265625l-1.796875 -5.5q-0.0625 -0.1875 -0.109375 -0.375q-0.03125 -0.1875 -0.0625 -0.375q-0.046875 0.1875 -0.09375 0.390625q-0.03125 0.1875 -0.09375 0.359375l-1.8125 5.5q-0.09375 0.265625 -0.328125 0.265625l-1.078125 0l-2.625 -8.109375zm16.59961 -0.125q0.875 0 1.59375 0.296875q0.71875 0.296875 1.21875 0.84375q0.5 0.546875 0.765625 1.3125q0.265625 0.765625 0.265625 1.71875q0 0.96875 -0.265625 1.734375q-0.265625 0.765625 -0.765625 1.3125q-0.5 0.546875 -1.21875 0.84375q-0.71875 0.28125 -1.59375 0.28125q-0.890625 0 -1.609375 -0.28125q-0.71875 -0.296875 -1.21875 -0.84375q-0.5 -0.546875 -0.78125 -1.3125q-0.265625 -0.765625 -0.265625 -1.734375q0 -0.953125 0.265625 -1.71875q0.28125 -0.765625 0.78125 -1.3125q0.5 -0.546875 1.21875 -0.84375q0.71875 -0.296875 1.609375 -0.296875zm0 7.234375q1.1875 0 1.78125 -0.796875q0.59375 -0.8125 0.59375 -2.25q0 -1.453125 -0.59375 -2.25q-0.59375 -0.8125 -1.78125 -0.8125q-0.609375 0 -1.0625 0.203125q-0.453125 0.203125 -0.75 0.609375q-0.296875 0.390625 -0.453125 0.96875q-0.140625 0.5625 -0.140625 1.28125q0 0.71875 0.140625 1.296875q0.15625 0.5625 0.453125 0.953125q0.296875 0.375 0.75 0.59375q0.453125 0.203125 1.0625 0.203125zm5.614624 1.0l0 -8.109375l0.8125 0q0.234375 0 0.3125 0.09375q0.09375 0.09375 0.125 0.296875l0.09375 1.265625q0.421875 -0.84375 1.03125 -1.3125q0.609375 -0.484375 1.4375 -0.484375q0.328125 0 0.59375 0.078125q0.28125 0.078125 0.515625 0.21875l-0.1875 1.0625q-0.046875 0.1875 -0.25 0.1875q-0.109375 0 -0.34375 -0.0625q-0.21875 -0.078125 -0.640625 -0.078125q-0.75 0 -1.25 0.4375q-0.5 0.421875 -0.828125 1.25l0 5.15625l-1.421875 0zm7.916687 -11.78125l0 6.9375l0.375 0q0.15625 0 0.265625 -0.046875q0.109375 -0.046875 0.234375 -0.1875l2.5625 -2.734375q0.109375 -0.125 0.234375 -0.203125q0.125 -0.09375 0.3125 -0.09375l1.296875 0l-2.984375 3.1875q-0.109375 0.125 -0.21875 0.234375q-0.109375 0.109375 -0.234375 0.1875q0.140625 0.09375 0.25 0.21875q0.125 0.125 0.21875 0.28125l3.171875 4.0l-1.28125 0q-0.171875 0 -0.296875 -0.0625q-0.125 -0.078125 -0.234375 -0.21875l-2.671875 -3.3125q-0.109375 -0.171875 -0.234375 -0.21875q-0.125 -0.0625 -0.359375 -0.0625l-0.40625 0l0 3.875l-1.421875 0l0 -11.78125l1.421875 0z" fill-rule="nonzero"/><path fill="#000000" d="m498.83655 208.96022q0 1.421875 0.359375 2.765625q0.375 1.34375 1.078125 2.5625q0.03125 0.078125 0.046875 0.125q0.015625 0.046875 0.015625 0.109375q0 0.09375 -0.046875 0.15625q-0.046875 0.0625 -0.125 0.09375l-0.53125 0.328125q-0.5 -0.765625 -0.84375 -1.515625q-0.34375 -0.75 -0.5625 -1.515625q-0.21875 -0.765625 -0.328125 -1.53125q-0.09375 -0.765625 -0.09375 -1.578125q0 -0.8125 0.09375 -1.578125q0.109375 -0.78125 0.328125 -1.53125q0.21875 -0.765625 0.5625 -1.515625q0.34375 -0.75 0.84375 -1.515625l0.53125 0.3125q0.078125 0.046875 0.125 0.109375q0.046875 0.0625 0.046875 0.15625q0 0.09375 -0.0625 0.234375q-0.703125 1.203125 -1.078125 2.546875q-0.359375 1.34375 -0.359375 2.78125zm5.3265686 -2.671875q0.4375 0 0.8125 0.09375q0.390625 0.09375 0.703125 0.28125l1.828125 0l0 0.4375q0 0.21875 -0.28125 0.28125l-0.765625 0.109375q0.234375 0.4375 0.234375 0.96875q0 0.484375 -0.203125 0.890625q-0.1875 0.40625 -0.53125 0.703125q-0.328125 0.28125 -0.796875 0.4375q-0.453125 0.140625 -1.0 0.140625q-0.484375 0 -0.890625 -0.109375q-0.21875 0.125 -0.328125 0.28125q-0.109375 0.15625 -0.109375 0.296875q0 0.25 0.1875 0.375q0.203125 0.125 0.515625 0.171875q0.328125 0.046875 0.734375 0.0625q0.40625 0.015625 0.828125 0.046875q0.421875 0.03125 0.828125 0.109375q0.40625 0.0625 0.71875 0.234375q0.328125 0.171875 0.515625 0.46875q0.1875 0.28125 0.1875 0.75q0 0.4375 -0.21875 0.84375q-0.203125 0.40625 -0.609375 0.71875q-0.40625 0.3125 -1.0 0.5q-0.578125 0.203125 -1.328125 0.203125q-0.734375 0 -1.296875 -0.15625q-0.546875 -0.140625 -0.921875 -0.390625q-0.359375 -0.25 -0.546875 -0.578125q-0.1875 -0.3125 -0.1875 -0.671875q0 -0.5 0.3125 -0.84375q0.328125 -0.34375 0.875 -0.5625q-0.28125 -0.125 -0.453125 -0.34375q-0.171875 -0.234375 -0.171875 -0.609375q0 -0.140625 0.046875 -0.296875q0.0625 -0.15625 0.171875 -0.3125q0.109375 -0.15625 0.265625 -0.296875q0.171875 -0.140625 0.375 -0.234375q-0.5 -0.28125 -0.78125 -0.75q-0.28125 -0.46875 -0.28125 -1.078125q0 -0.5 0.1875 -0.890625q0.1875 -0.40625 0.53125 -0.6875q0.34375 -0.296875 0.8125 -0.4375q0.46875 -0.15625 1.03125 -0.15625zm2.09375 7.21875q0 -0.25 -0.140625 -0.390625q-0.125 -0.15625 -0.375 -0.234375q-0.234375 -0.09375 -0.546875 -0.125q-0.3125 -0.046875 -0.671875 -0.0625q-0.34375 -0.015625 -0.703125 -0.03125q-0.359375 -0.03125 -0.6875 -0.078125q-0.375 0.171875 -0.609375 0.4375q-0.234375 0.265625 -0.234375 0.625q0 0.21875 0.109375 0.40625q0.125 0.203125 0.359375 0.34375q0.234375 0.15625 0.59375 0.234375q0.375 0.078125 0.875 0.078125q0.46875 0 0.84375 -0.09375q0.390625 -0.078125 0.65625 -0.234375q0.265625 -0.15625 0.390625 -0.375q0.140625 -0.21875 0.140625 -0.5zm-2.09375 -3.65625q0.359375 0 0.625 -0.09375q0.28125 -0.109375 0.46875 -0.28125q0.1875 -0.1875 0.28125 -0.4375q0.09375 -0.25 0.09375 -0.546875q0 -0.625 -0.375 -0.984375q-0.375 -0.375 -1.09375 -0.375q-0.71875 0 -1.09375 0.375q-0.375 0.359375 -0.375 0.984375q0 0.296875 0.09375 0.546875q0.09375 0.25 0.28125 0.4375q0.1875 0.171875 0.453125 0.28125q0.28125 0.09375 0.640625 0.09375zm7.2637634 -3.5625q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm4.3010254 0.09375q0 -0.171875 0.0625 -0.328125q0.0625 -0.15625 0.171875 -0.265625q0.109375 -0.109375 0.25 -0.171875q0.15625 -0.078125 0.328125 -0.078125q0.1875 0 0.328125 0.078125q0.15625 0.0625 0.265625 0.171875q0.125 0.109375 0.1875 0.265625q0.0625 0.15625 0.0625 0.328125q0 0.1875 -0.0625 0.34375q-0.0625 0.140625 -0.1875 0.25q-0.109375 0.109375 -0.265625 0.171875q-0.140625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.25 -0.171875q-0.109375 -0.109375 -0.171875 -0.25q-0.0625 -0.15625 -0.0625 -0.34375zm1.9122314 -6.015625l0.9375 0q0.140625 0 0.234375 0.078125q0.09375 0.0625 0.125 0.171875l1.296875 4.34375q0.046875 0.234375 0.09375 0.46875q0.046875 0.21875 0.078125 0.4375q0.0625 -0.21875 0.125 -0.4375q0.0625 -0.234375 0.140625 -0.46875l1.421875 -4.375q0.03125 -0.09375 0.109375 -0.15625q0.09375 -0.078125 0.21875 -0.078125l0.515625 0q0.140625 0 0.21875 0.078125q0.09375 0.0625 0.125 0.15625l1.390625 4.375q0.078125 0.234375 0.125 0.46875q0.0625 0.21875 0.109375 0.4375q0.03125 -0.21875 0.078125 -0.453125q0.0625 -0.25 0.125 -0.453125l1.328125 -4.34375q0.03125 -0.109375 0.125 -0.171875q0.09375 -0.078125 0.21875 -0.078125l0.890625 0l-2.1875 6.75l-0.9375 0q-0.171875 0 -0.25 -0.234375l-1.484375 -4.578125q-0.046875 -0.140625 -0.09375 -0.296875q-0.03125 -0.15625 -0.0625 -0.3125q-0.03125 0.15625 -0.0625 0.3125q-0.03125 0.15625 -0.09375 0.3125l-1.515625 4.5625q-0.0625 0.234375 -0.265625 0.234375l-0.890625 0l-2.1875 -6.75zm13.818665 -0.109375q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm4.6760864 0.828125l0 -6.75l0.6875 0q0.1875 0 0.265625 0.078125q0.078125 0.0625 0.09375 0.25l0.078125 1.046875q0.359375 -0.703125 0.859375 -1.09375q0.515625 -0.40625 1.203125 -0.40625q0.28125 0 0.5 0.0625q0.234375 0.0625 0.421875 0.1875l-0.15625 0.875q-0.046875 0.171875 -0.203125 0.171875q-0.09375 0 -0.296875 -0.0625q-0.1875 -0.0625 -0.53125 -0.0625q-0.625 0 -1.046875 0.359375q-0.40625 0.359375 -0.6875 1.046875l0 4.296875l-1.1875 0zm6.605591 -9.8125l0 5.78125l0.3125 0q0.125 0 0.203125 -0.03125q0.09375 -0.046875 0.203125 -0.15625l2.140625 -2.296875q0.09375 -0.109375 0.1875 -0.171875q0.109375 -0.0625 0.28125 -0.0625l1.078125 0l-2.484375 2.640625q-0.09375 0.125 -0.1875 0.21875q-0.09375 0.078125 -0.203125 0.140625q0.125 0.078125 0.21875 0.1875q0.09375 0.09375 0.171875 0.234375l2.640625 3.328125l-1.0625 0q-0.140625 0 -0.25 -0.046875q-0.109375 -0.0625 -0.1875 -0.1875l-2.234375 -2.765625q-0.09375 -0.140625 -0.203125 -0.171875q-0.09375 -0.046875 -0.296875 -0.046875l-0.328125 0l0 3.21875l-1.1875 0l0 -9.8125l1.1875 0zm6.7651367 5.625q0 -1.4375 -0.359375 -2.78125q-0.359375 -1.34375 -1.0625 -2.546875q-0.0625 -0.140625 -0.0625 -0.234375q0 -0.09375 0.046875 -0.15625q0.046875 -0.0625 0.109375 -0.109375l0.53125 -0.3125q0.5 0.765625 0.84375 1.515625q0.359375 0.75 0.5625 1.515625q0.21875 0.75 0.3125 1.53125q0.109375 0.765625 0.109375 1.578125q0 0.8125 -0.109375 1.578125q-0.09375 0.765625 -0.3125 1.53125q-0.203125 0.765625 -0.5625 1.515625q-0.34375 0.75 -0.84375 1.515625l-0.53125 -0.328125q-0.0625 -0.03125 -0.109375 -0.09375q-0.046875 -0.0625 -0.046875 -0.15625q0 -0.0625 0 -0.109375q0.015625 -0.046875 0.0625 -0.125q0.6875 -1.21875 1.046875 -2.5625q0.375 -1.34375 0.375 -2.765625z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m599.09875 171.2955l0 0c0 -7.6045837 6.164734 -13.769302 13.769287 -13.769302l96.524414 0c3.6517944 0 7.154114 1.4506836 9.736328 4.0329285c2.5822754 2.5822449 4.032959 6.0845184 4.032959 9.736374l0 55.07556c0 7.6045837 -6.164734 13.769302 -13.769287 13.769302l-96.524414 0c-7.604553 0 -13.769287 -6.1647186 -13.769287 -13.769302z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m599.09875 171.2955l0 0c0 -7.6045837 6.164734 -13.769302 13.769287 -13.769302l96.524414 0c3.6517944 0 7.154114 1.4506836 9.736328 4.0329285c2.5822754 2.5822449 4.032959 6.0845184 4.032959 9.736374l0 55.07556c0 7.6045837 -6.164734 13.769302 -13.769287 13.769302l-96.524414 0c-7.604553 0 -13.769287 -6.1647186 -13.769287 -13.769302z" fill-rule="evenodd"/><path fill="#000000" d="m633.3156 196.81828q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm6.7179565 -8.359375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm5.149536 7.1875l0 -8.109375l0.84375 0q0.296875 0 0.390625 0.296875l0.09375 0.84375q0.453125 -0.5625 1.0 -0.90625q0.5625 -0.359375 1.296875 -0.359375q0.828125 0 1.328125 0.46875q0.515625 0.453125 0.734375 1.21875q0.171875 -0.4375 0.4375 -0.75q0.28125 -0.328125 0.625 -0.53125q0.34375 -0.21875 0.734375 -0.3125q0.390625 -0.09375 0.796875 -0.09375q0.640625 0 1.140625 0.203125q0.5 0.203125 0.84375 0.59375q0.34375 0.390625 0.53125 0.96875q0.1875 0.578125 0.1875 1.3125l0 5.15625l-1.421875 0l0 -5.15625q0 -0.953125 -0.421875 -1.4375q-0.421875 -0.5 -1.203125 -0.5q-0.359375 0 -0.671875 0.125q-0.3125 0.125 -0.5625 0.359375q-0.234375 0.234375 -0.375 0.609375q-0.140625 0.359375 -0.140625 0.84375l0 5.15625l-1.421875 0l0 -5.15625q0 -0.984375 -0.390625 -1.453125q-0.390625 -0.484375 -1.140625 -0.484375q-0.53125 0 -0.984375 0.28125q-0.453125 0.28125 -0.828125 0.765625l0 6.046875l-1.421875 0zm13.135803 2.75l0 -10.859375l0.84375 0q0.296875 0 0.390625 0.296875l0.109375 0.96875q0.53125 -0.640625 1.1875 -1.015625q0.671875 -0.390625 1.546875 -0.390625q0.6875 0 1.25 0.265625q0.578125 0.265625 0.96875 0.796875q0.40625 0.53125 0.625 1.3125q0.21875 0.765625 0.21875 1.765625q0 0.90625 -0.25 1.6875q-0.234375 0.765625 -0.6875 1.328125q-0.4375 0.5625 -1.09375 0.890625q-0.65625 0.3125 -1.46875 0.3125q-0.75 0 -1.28125 -0.25q-0.53125 -0.25 -0.9375 -0.703125l0 3.59375l-1.421875 0zm3.609375 -9.84375q-0.703125 0 -1.234375 0.328125q-0.515625 0.3125 -0.953125 0.890625l0 3.921875q0.390625 0.53125 0.859375 0.75q0.46875 0.21875 1.046875 0.21875q1.125 0 1.734375 -0.8125q0.609375 -0.8125 0.609375 -2.3125q0 -0.78125 -0.140625 -1.34375q-0.140625 -0.578125 -0.40625 -0.9375q-0.265625 -0.375 -0.65625 -0.53125q-0.375 -0.171875 -0.859375 -0.171875zm6.800659 -4.6875l0 11.78125l-1.421875 0l0 -11.78125l1.421875 0zm8.470947 11.78125l-0.640625 0q-0.203125 0 -0.328125 -0.0625q-0.125 -0.0625 -0.171875 -0.28125l-0.15625 -0.75q-0.328125 0.296875 -0.640625 0.53125q-0.296875 0.21875 -0.640625 0.375q-0.328125 0.15625 -0.703125 0.234375q-0.375 0.078125 -0.84375 0.078125q-0.46875 0 -0.890625 -0.125q-0.40625 -0.140625 -0.71875 -0.390625q-0.296875 -0.265625 -0.484375 -0.671875q-0.171875 -0.40625 -0.171875 -0.96875q0 -0.46875 0.265625 -0.90625q0.265625 -0.453125 0.84375 -0.796875q0.59375 -0.34375 1.546875 -0.5625q0.953125 -0.21875 2.328125 -0.25l0 -0.640625q0 -0.9375 -0.40625 -1.421875q-0.40625 -0.484375 -1.1875 -0.484375q-0.53125 0 -0.890625 0.140625q-0.34375 0.125 -0.609375 0.296875q-0.25 0.15625 -0.453125 0.296875q-0.1875 0.125 -0.359375 0.125q-0.15625 0 -0.265625 -0.078125q-0.09375 -0.078125 -0.15625 -0.1875l-0.265625 -0.453125q0.671875 -0.65625 1.453125 -0.96875q0.78125 -0.328125 1.71875 -0.328125q0.671875 0 1.203125 0.234375q0.53125 0.21875 0.890625 0.625q0.359375 0.390625 0.546875 0.96875q0.1875 0.5625 0.1875 1.234375l0 5.1875zm-3.703125 -0.875q0.375 0 0.6875 -0.078125q0.3125 -0.078125 0.578125 -0.203125q0.28125 -0.140625 0.53125 -0.34375q0.265625 -0.203125 0.5 -0.453125l0 -1.6875q-0.984375 0.03125 -1.671875 0.15625q-0.6875 0.109375 -1.125 0.3125q-0.421875 0.203125 -0.625 0.484375q-0.1875 0.265625 -0.1875 0.59375q0 0.328125 0.09375 0.5625q0.109375 0.234375 0.28125 0.375q0.171875 0.140625 0.40625 0.21875q0.25 0.0625 0.53125 0.0625zm8.315002 1.0q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm6.7179565 -8.359375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875z" fill-rule="nonzero"/><path fill="#000000" d="m619.003 208.94579q0 1.421875 0.359375 2.765625q0.375 1.34375 1.078125 2.5625q0.03125 0.078125 0.046875 0.125q0.015625 0.046875 0.015625 0.109375q0 0.09375 -0.046875 0.15625q-0.046875 0.0625 -0.125 0.09375l-0.53125 0.328125q-0.5 -0.765625 -0.84375 -1.515625q-0.34375 -0.75 -0.5625 -1.515625q-0.21875 -0.765625 -0.328125 -1.53125q-0.09375 -0.765625 -0.09375 -1.578125q0 -0.8125 0.09375 -1.578125q0.109375 -0.78125 0.328125 -1.53125q0.21875 -0.765625 0.5625 -1.515625q0.34375 -0.75 0.84375 -1.515625l0.53125 0.3125q0.078125 0.046875 0.125 0.109375q0.046875 0.0625 0.046875 0.15625q0 0.09375 -0.0625 0.234375q-0.703125 1.203125 -1.078125 2.546875q-0.359375 1.34375 -0.359375 2.78125zm5.092163 4.296875q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm5.5963745 -6.96875q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm5.4589233 2.53125l-2.265625 -3.296875l1.140625 0q0.140625 0 0.203125 0.046875q0.078125 0.046875 0.125 0.125l1.65625 2.546875q0.0625 -0.1875 0.171875 -0.375l1.453125 -2.140625q0.0625 -0.09375 0.125 -0.140625q0.078125 -0.0625 0.171875 -0.0625l1.09375 0l-2.265625 3.21875l2.359375 3.53125l-1.140625 0q-0.140625 0 -0.234375 -0.078125q-0.078125 -0.078125 -0.125 -0.171875l-1.703125 -2.640625q-0.046875 0.1875 -0.140625 0.34375l-1.578125 2.296875q-0.0625 0.09375 -0.140625 0.171875q-0.078125 0.078125 -0.203125 0.078125l-1.0625 0l2.359375 -3.453125zm7.186096 3.5625q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm3.0338745 0.03125q-0.09375 0.234375 -0.28125 0.34375q-0.1875 0.109375 -0.375 0.109375l-0.5 0l4.0 -9.96875q0.09375 -0.21875 0.25 -0.328125q0.15625 -0.109375 0.375 -0.109375l0.5 0l-3.96875 9.953125zm6.628845 -0.03125q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm5.5963745 -6.96875q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm4.2808228 5.984375l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.078125 0.6875q0.375 -0.453125 0.84375 -0.75q0.46875 -0.296875 1.078125 -0.296875q0.6875 0 1.109375 0.390625q0.421875 0.375 0.609375 1.015625q0.140625 -0.359375 0.359375 -0.625q0.234375 -0.265625 0.515625 -0.4375q0.296875 -0.1875 0.609375 -0.265625q0.328125 -0.078125 0.671875 -0.078125q0.53125 0 0.9375 0.171875q0.421875 0.171875 0.703125 0.5q0.296875 0.328125 0.453125 0.8125q0.15625 0.46875 0.15625 1.078125l0 4.296875l-1.1875 0l0 -4.296875q0 -0.796875 -0.34375 -1.203125q-0.34375 -0.40625 -1.015625 -0.40625q-0.28125 0 -0.546875 0.109375q-0.265625 0.09375 -0.46875 0.296875q-0.203125 0.203125 -0.328125 0.5q-0.109375 0.296875 -0.109375 0.703125l0 4.296875l-1.1875 0l0 -4.296875q0 -0.8125 -0.328125 -1.203125q-0.3125 -0.40625 -0.9375 -0.40625q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.6875 0.640625l0 5.03125l-1.1875 0zm10.942322 2.28125l0 -9.03125l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.796875q0.4375 -0.53125 0.984375 -0.84375q0.5625 -0.328125 1.296875 -0.328125q0.578125 0 1.046875 0.234375q0.46875 0.21875 0.796875 0.65625q0.34375 0.4375 0.515625 1.078125q0.1875 0.640625 0.1875 1.484375q0 0.75 -0.203125 1.390625q-0.1875 0.640625 -0.5625 1.109375q-0.375 0.46875 -0.921875 0.75q-0.546875 0.265625 -1.21875 0.265625q-0.625 0 -1.078125 -0.203125q-0.4375 -0.203125 -0.78125 -0.59375l0 2.984375l-1.1875 0zm3.015625 -8.1875q-0.578125 0 -1.015625 0.265625q-0.4375 0.265625 -0.8125 0.75l0 3.265625q0.328125 0.4375 0.71875 0.625q0.390625 0.171875 0.875 0.171875q0.9375 0 1.4375 -0.671875q0.515625 -0.671875 0.515625 -1.921875q0 -0.65625 -0.125 -1.125q-0.109375 -0.484375 -0.328125 -0.78125q-0.21875 -0.296875 -0.546875 -0.4375q-0.3125 -0.140625 -0.71875 -0.140625zm5.6696167 -3.90625l0 9.8125l-1.1875 0l0 -9.8125l1.1875 0zm7.0526123 9.8125l-0.53125 0q-0.171875 0 -0.28125 -0.046875q-0.109375 -0.0625 -0.140625 -0.234375l-0.140625 -0.625q-0.265625 0.234375 -0.515625 0.4375q-0.25 0.1875 -0.53125 0.3125q-0.28125 0.125 -0.59375 0.1875q-0.3125 0.078125 -0.703125 0.078125q-0.390625 0 -0.734375 -0.109375q-0.34375 -0.109375 -0.609375 -0.328125q-0.25 -0.21875 -0.40625 -0.546875q-0.140625 -0.34375 -0.140625 -0.8125q0 -0.390625 0.21875 -0.765625q0.21875 -0.375 0.703125 -0.65625q0.5 -0.296875 1.296875 -0.46875q0.796875 -0.1875 1.9375 -0.21875l0 -0.515625q0 -0.796875 -0.34375 -1.1875q-0.328125 -0.40625 -0.984375 -0.40625q-0.4375 0 -0.734375 0.109375q-0.296875 0.109375 -0.515625 0.25q-0.21875 0.125 -0.375 0.234375q-0.15625 0.109375 -0.3125 0.109375q-0.109375 0 -0.203125 -0.0625q-0.09375 -0.0625 -0.140625 -0.15625l-0.21875 -0.375q0.5625 -0.546875 1.203125 -0.8125q0.65625 -0.265625 1.4375 -0.265625q0.5625 0 1.0 0.1875q0.453125 0.1875 0.75 0.53125q0.296875 0.328125 0.453125 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.3125zm-3.078125 -0.71875q0.3125 0 0.5625 -0.0625q0.265625 -0.078125 0.484375 -0.1875q0.234375 -0.125 0.4375 -0.28125q0.21875 -0.171875 0.421875 -0.375l0 -1.40625q-0.828125 0.015625 -1.40625 0.125q-0.5625 0.09375 -0.921875 0.265625q-0.359375 0.171875 -0.53125 0.40625q-0.15625 0.21875 -0.15625 0.5q0 0.265625 0.078125 0.453125q0.09375 0.1875 0.234375 0.3125q0.15625 0.125 0.359375 0.1875q0.203125 0.0625 0.4375 0.0625zm6.913574 0.828125q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm5.5963745 -6.96875q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm5.08313 1.796875q0 -1.4375 -0.359375 -2.78125q-0.359375 -1.34375 -1.0625 -2.546875q-0.0625 -0.140625 -0.0625 -0.234375q0 -0.09375 0.046875 -0.15625q0.046875 -0.0625 0.109375 -0.109375l0.53125 -0.3125q0.5 0.765625 0.84375 1.515625q0.359375 0.75 0.5625 1.515625q0.21875 0.75 0.3125 1.53125q0.109375 0.765625 0.109375 1.578125q0 0.8125 -0.109375 1.578125q-0.09375 0.765625 -0.3125 1.53125q-0.203125 0.765625 -0.5625 1.515625q-0.34375 0.75 -0.84375 1.515625l-0.53125 -0.328125q-0.0625 -0.03125 -0.109375 -0.09375q-0.046875 -0.0625 -0.046875 -0.15625q0 -0.0625 0 -0.109375q0.015625 -0.046875 0.0625 -0.125q0.6875 -1.21875 1.046875 -2.5625q0.375 -1.34375 0.375 -2.765625z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m188.49312 440.3466l0 0c0 -3.6181946 2.9331207 -6.5513 6.5513153 -6.5513l182.61392 0c1.7375183 0 3.4038696 0.69021606 4.632477 1.9188232c1.2286072 1.2286072 1.9188232 2.8949585 1.9188232 4.632477l0 26.204468c0 3.6181946 -2.9331055 6.5513 -6.5513 6.5513l-182.61392 0l0 0c-3.6181946 0 -6.5513153 -2.9331055 -6.5513153 -6.5513z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m188.49312 440.3466l0 0c0 -3.6181946 2.9331207 -6.5513 6.5513153 -6.5513l182.61392 0c1.7375183 0 3.4038696 0.69021606 4.632477 1.9188232c1.2286072 1.2286072 1.9188232 2.8949585 1.9188232 4.632477l0 26.204468c0 3.6181946 -2.9331055 6.5513 -6.5513 6.5513l-182.61392 0l0 0c-3.6181946 0 -6.5513153 -2.9331055 -6.5513153 -6.5513z" fill-rule="evenodd"/><path fill="#000000" d="m277.0359 459.3088l0 -6.890625l-0.890625 -0.09375q-0.171875 -0.046875 -0.28125 -0.125q-0.109375 -0.09375 -0.109375 -0.25l0 -0.578125l1.28125 0l0 -0.453125q0 -0.75 0.234375 -1.359375q0.234375 -0.625 0.6875 -1.0625q0.46875 -0.453125 1.15625 -0.703125q0.703125 -0.25 1.625 -0.25q0.296875 0 0.609375 0.046875q0.328125 0.03125 0.5625 0.109375l-0.0625 0.75q-0.015625 0.09375 -0.09375 0.125q-0.078125 0.03125 -0.234375 0.03125q-0.078125 0 -0.171875 0q-0.09375 -0.015625 -0.21875 -0.015625q-1.421875 0 -2.0625 0.59375q-0.640625 0.59375 -0.640625 1.765625l0 0.421875l4.890625 0l0 7.9375l-1.421875 0l0 -6.90625l-3.421875 0l0 6.90625l-1.4375 0zm10.385529 -11.78125l0 11.78125l-1.421875 0l0 -11.78125l1.421875 0zm5.7209473 3.546875q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m789.7638 383.82462l0 0c0 -13.197144 10.698364 -23.895508 23.895447 -23.895508l95.5791 0l0 0c6.3375244 0 12.415405 2.5175476 16.896667 6.9988403c4.4813232 4.481262 6.9988403 10.559174 6.9988403 16.896667l0 114.16177c0 13.197113 -10.698364 23.895447 -23.895508 23.895447l-95.5791 0c-13.1970825 0 -23.895447 -10.698334 -23.895447 -23.895447z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m789.7638 383.82462l0 0c0 -13.197144 10.698364 -23.895508 23.895447 -23.895508l95.5791 0l0 0c6.3375244 0 12.415405 2.5175476 16.896667 6.9988403c4.4813232 4.481262 6.9988403 10.559174 6.9988403 16.896667l0 114.16177c0 13.197113 -10.698364 23.895447 -23.895508 23.895447l-95.5791 0c-13.1970825 0 -23.895447 -10.698334 -23.895447 -23.895447z" fill-rule="evenodd"/><path fill="#000000" d="m840.8782 438.76547l-0.640625 0q-0.203125 0 -0.328125 -0.0625q-0.125 -0.0625 -0.171875 -0.28125l-0.15625 -0.75q-0.328125 0.296875 -0.640625 0.53125q-0.296875 0.21875 -0.640625 0.375q-0.328125 0.15625 -0.703125 0.234375q-0.375 0.078125 -0.84375 0.078125q-0.46875 0 -0.890625 -0.125q-0.40625 -0.140625 -0.71875 -0.390625q-0.296875 -0.265625 -0.484375 -0.671875q-0.171875 -0.40625 -0.171875 -0.96875q0 -0.46875 0.265625 -0.90625q0.265625 -0.453125 0.84375 -0.796875q0.59375 -0.34375 1.546875 -0.5625q0.953125 -0.21875 2.328125 -0.25l0 -0.640625q0 -0.9375 -0.40625 -1.421875q-0.40625 -0.484375 -1.1875 -0.484375q-0.53125 0 -0.890625 0.140625q-0.34375 0.125 -0.609375 0.296875q-0.25 0.15625 -0.453125 0.296875q-0.1875 0.125 -0.359375 0.125q-0.15625 0 -0.265625 -0.078125q-0.09375 -0.078125 -0.15625 -0.1875l-0.265625 -0.453125q0.671875 -0.65625 1.453125 -0.96875q0.78125 -0.328125 1.71875 -0.328125q0.671875 0 1.203125 0.234375q0.53125 0.21875 0.890625 0.625q0.359375 0.390625 0.546875 0.96875q0.1875 0.5625 0.1875 1.234375l0 5.1875zm-3.703125 -0.875q0.375 0 0.6875 -0.078125q0.3125 -0.078125 0.578125 -0.203125q0.28125 -0.140625 0.53125 -0.34375q0.265625 -0.203125 0.5 -0.453125l0 -1.6875q-0.984375 0.03125 -1.671875 0.15625q-0.6875 0.109375 -1.125 0.3125q-0.421875 0.203125 -0.625 0.484375q-0.1875 0.265625 -0.1875 0.59375q0 0.328125 0.09375 0.5625q0.109375 0.234375 0.28125 0.375q0.171875 0.140625 0.40625 0.21875q0.25 0.0625 0.53125 0.0625zm5.8618774 0.875l0 -8.109375l0.84375 0q0.296875 0 0.390625 0.296875l0.109375 0.890625q0.53125 -0.59375 1.171875 -0.953125q0.65625 -0.359375 1.515625 -0.359375q0.65625 0 1.15625 0.21875q0.515625 0.21875 0.859375 0.625q0.34375 0.40625 0.515625 0.984375q0.171875 0.5625 0.171875 1.25l0 5.15625l-1.421875 0l0 -5.15625q0 -0.921875 -0.421875 -1.421875q-0.421875 -0.515625 -1.28125 -0.515625q-0.625 0 -1.171875 0.3125q-0.546875 0.296875 -1.015625 0.8125l0 5.96875l-1.421875 0zm14.84906 0l-0.640625 0q-0.203125 0 -0.328125 -0.0625q-0.125 -0.0625 -0.171875 -0.28125l-0.15625 -0.75q-0.328125 0.296875 -0.640625 0.53125q-0.296875 0.21875 -0.640625 0.375q-0.328125 0.15625 -0.703125 0.234375q-0.375 0.078125 -0.84375 0.078125q-0.46875 0 -0.890625 -0.125q-0.40625 -0.140625 -0.71875 -0.390625q-0.296875 -0.265625 -0.484375 -0.671875q-0.171875 -0.40625 -0.171875 -0.96875q0 -0.46875 0.265625 -0.90625q0.265625 -0.453125 0.84375 -0.796875q0.59375 -0.34375 1.546875 -0.5625q0.953125 -0.21875 2.328125 -0.25l0 -0.640625q0 -0.9375 -0.40625 -1.421875q-0.40625 -0.484375 -1.1875 -0.484375q-0.53125 0 -0.890625 0.140625q-0.34375 0.125 -0.609375 0.296875q-0.25 0.15625 -0.453125 0.296875q-0.1875 0.125 -0.359375 0.125q-0.15625 0 -0.265625 -0.078125q-0.09375 -0.078125 -0.15625 -0.1875l-0.265625 -0.453125q0.671875 -0.65625 1.453125 -0.96875q0.78125 -0.328125 1.71875 -0.328125q0.671875 0 1.203125 0.234375q0.53125 0.21875 0.890625 0.625q0.359375 0.390625 0.546875 0.96875q0.1875 0.5625 0.1875 1.234375l0 5.1875zm-3.703125 -0.875q0.375 0 0.6875 -0.078125q0.3125 -0.078125 0.578125 -0.203125q0.28125 -0.140625 0.53125 -0.34375q0.265625 -0.203125 0.5 -0.453125l0 -1.6875q-0.984375 0.03125 -1.671875 0.15625q-0.6875 0.109375 -1.125 0.3125q-0.421875 0.203125 -0.625 0.484375q-0.1875 0.265625 -0.1875 0.59375q0 0.328125 0.09375 0.5625q0.109375 0.234375 0.28125 0.375q0.171875 0.140625 0.40625 0.21875q0.25 0.0625 0.53125 0.0625zm7.4400024 -10.90625l0 11.78125l-1.421875 0l0 -11.78125l1.421875 0zm4.8928223 14.171875q-0.078125 0.15625 -0.1875 0.25q-0.109375 0.109375 -0.328125 0.109375l-1.0625 0l1.484375 -3.21875l-3.34375 -7.640625l1.234375 0q0.1875 0 0.28125 0.09375q0.109375 0.09375 0.15625 0.203125l2.171875 5.109375q0.078125 0.171875 0.125 0.359375q0.046875 0.171875 0.09375 0.359375q0.046875 -0.1875 0.109375 -0.359375q0.0625 -0.1875 0.125 -0.375l2.109375 -5.09375q0.046875 -0.125 0.15625 -0.203125q0.125 -0.09375 0.25 -0.09375l1.140625 0l-4.515625 10.5zm10.45752 -9.15625q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm3.8814087 -1.34375l0 8.109375l-1.421875 0l0 -8.109375l1.421875 0zm0.328125 -2.53125q0 0.203125 -0.09375 0.390625q-0.078125 0.171875 -0.21875 0.3125q-0.140625 0.140625 -0.328125 0.21875q-0.1875 0.078125 -0.390625 0.078125q-0.203125 0 -0.390625 -0.078125q-0.171875 -0.078125 -0.3125 -0.21875q-0.140625 -0.140625 -0.21875 -0.3125q-0.078125 -0.1875 -0.078125 -0.390625q0 -0.21875 0.078125 -0.40625q0.078125 -0.1875 0.21875 -0.328125q0.140625 -0.140625 0.3125 -0.21875q0.1875 -0.078125 0.390625 -0.078125q0.203125 0 0.390625 0.078125q0.1875 0.078125 0.328125 0.21875q0.140625 0.140625 0.21875 0.328125q0.09375 0.1875 0.09375 0.40625zm6.8303223 3.875q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625z" fill-rule="nonzero"/><path fill="#000000" d="m840.14655 451.01797q0 1.421875 0.359375 2.765625q0.375 1.34375 1.078125 2.5625q0.03125 0.078125 0.046875 0.125q0.015625 0.046875 0.015625 0.109375q0 0.09375 -0.046875 0.15625q-0.046875 0.0625 -0.125 0.09375l-0.53125 0.328125q-0.5 -0.765625 -0.84375 -1.515625q-0.34375 -0.75 -0.5625 -1.515625q-0.21875 -0.765625 -0.328125 -1.53125q-0.09375 -0.765625 -0.09375 -1.578125q0 -0.8125 0.09375 -1.578125q0.109375 -0.78125 0.328125 -1.53125q0.21875 -0.765625 0.5625 -1.515625q0.34375 -0.75 0.84375 -1.515625l0.53125 0.3125q0.078125 0.046875 0.125 0.109375q0.046875 0.0625 0.046875 0.15625q0 0.09375 -0.0625 0.234375q-0.703125 1.203125 -1.078125 2.546875q-0.359375 1.34375 -0.359375 2.78125zm3.045288 6.46875l0 -9.03125l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.796875q0.4375 -0.53125 0.984375 -0.84375q0.5625 -0.328125 1.296875 -0.328125q0.578125 0 1.046875 0.234375q0.46875 0.21875 0.796875 0.65625q0.34375 0.4375 0.515625 1.078125q0.1875 0.640625 0.1875 1.484375q0 0.75 -0.203125 1.390625q-0.1875 0.640625 -0.5625 1.109375q-0.375 0.46875 -0.921875 0.75q-0.546875 0.265625 -1.21875 0.265625q-0.625 0 -1.078125 -0.203125q-0.4375 -0.203125 -0.78125 -0.59375l0 2.984375l-1.1875 0zm3.015625 -8.1875q-0.578125 0 -1.015625 0.265625q-0.4375 0.265625 -0.8125 0.75l0 3.265625q0.328125 0.4375 0.71875 0.625q0.390625 0.171875 0.875 0.171875q0.9375 0 1.4375 -0.671875q0.515625 -0.671875 0.515625 -1.921875q0 -0.65625 -0.125 -1.125q-0.109375 -0.484375 -0.328125 -0.78125q-0.21875 -0.296875 -0.546875 -0.4375q-0.3125 -0.140625 -0.71875 -0.140625zm9.310242 5.90625l-0.53125 0q-0.171875 0 -0.28125 -0.046875q-0.109375 -0.0625 -0.140625 -0.234375l-0.140625 -0.625q-0.265625 0.234375 -0.515625 0.4375q-0.25 0.1875 -0.53125 0.3125q-0.28125 0.125 -0.59375 0.1875q-0.3125 0.078125 -0.703125 0.078125q-0.390625 0 -0.734375 -0.109375q-0.34375 -0.109375 -0.609375 -0.328125q-0.25 -0.21875 -0.40625 -0.546875q-0.140625 -0.34375 -0.140625 -0.8125q0 -0.390625 0.21875 -0.765625q0.21875 -0.375 0.703125 -0.65625q0.5 -0.296875 1.296875 -0.46875q0.796875 -0.1875 1.9375 -0.21875l0 -0.515625q0 -0.796875 -0.34375 -1.1875q-0.328125 -0.40625 -0.984375 -0.40625q-0.4375 0 -0.734375 0.109375q-0.296875 0.109375 -0.515625 0.25q-0.21875 0.125 -0.375 0.234375q-0.15625 0.109375 -0.3125 0.109375q-0.109375 0 -0.203125 -0.0625q-0.09375 -0.0625 -0.140625 -0.15625l-0.21875 -0.375q0.5625 -0.546875 1.203125 -0.8125q0.65625 -0.265625 1.4375 -0.265625q0.5625 0 1.0 0.1875q0.453125 0.1875 0.75 0.53125q0.296875 0.328125 0.453125 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.3125zm-3.078125 -0.71875q0.3125 0 0.5625 -0.0625q0.265625 -0.078125 0.484375 -0.1875q0.234375 -0.125 0.4375 -0.28125q0.21875 -0.171875 0.421875 -0.375l0 -1.40625q-0.828125 0.015625 -1.40625 0.125q-0.5625 0.09375 -0.921875 0.265625q-0.359375 0.171875 -0.53125 0.40625q-0.15625 0.21875 -0.15625 0.5q0 0.265625 0.078125 0.453125q0.09375 0.1875 0.234375 0.3125q0.15625 0.125 0.359375 0.1875q0.203125 0.0625 0.4375 0.0625zm8.741699 -4.921875q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm5.784363 0q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm4.581238 -1.21875q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm8.155823 0.34375q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm2.9249878 1.453125q0 -1.4375 -0.359375 -2.78125q-0.359375 -1.34375 -1.0625 -2.546875q-0.0625 -0.140625 -0.0625 -0.234375q0 -0.09375 0.046875 -0.15625q0.046875 -0.0625 0.109375 -0.109375l0.53125 -0.3125q0.5 0.765625 0.84375 1.515625q0.359375 0.75 0.5625 1.515625q0.21875 0.75 0.3125 1.53125q0.109375 0.765625 0.109375 1.578125q0 0.8125 -0.109375 1.578125q-0.09375 0.765625 -0.3125 1.53125q-0.203125 0.765625 -0.5625 1.515625q-0.34375 0.75 -0.84375 1.515625l-0.53125 -0.328125q-0.0625 -0.03125 -0.109375 -0.09375q-0.046875 -0.0625 -0.046875 -0.15625q0 -0.0625 0 -0.109375q0.015625 -0.046875 0.0625 -0.125q0.6875 -1.21875 1.046875 -2.5625q0.375 -1.34375 0.375 -2.765625z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m582.7346 440.34744l0 0c0 -3.6181946 2.9331055 -6.5513306 6.5513306 -6.5513306l127.33832 0c1.7374878 0 3.4038696 0.6902466 4.6324463 1.9188538c1.2286377 1.2286072 1.9188843 2.8949585 1.9188843 4.632477l0 26.204468c0 3.618164 -2.9331665 6.5513 -6.5513306 6.5513l-127.33832 0c-3.618225 0 -6.5513306 -2.933136 -6.5513306 -6.5513z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m582.7346 440.34744l0 0c0 -3.6181946 2.9331055 -6.5513306 6.5513306 -6.5513306l127.33832 0c1.7374878 0 3.4038696 0.6902466 4.6324463 1.9188538c1.2286377 1.2286072 1.9188843 2.8949585 1.9188843 4.632477l0 26.204468c0 3.618164 -2.9331665 6.5513 -6.5513306 6.5513l-127.33832 0c-3.618225 0 -6.5513306 -2.933136 -6.5513306 -6.5513z" fill-rule="evenodd"/><path fill="#000000" d="m620.7594 459.30966l0 -8.109375l0.84375 0q0.296875 0 0.390625 0.296875l0.09375 0.84375q0.453125 -0.5625 1.0 -0.90625q0.5625 -0.359375 1.296875 -0.359375q0.828125 0 1.328125 0.46875q0.515625 0.453125 0.734375 1.21875q0.171875 -0.4375 0.4375 -0.75q0.28125 -0.328125 0.625 -0.53125q0.34375 -0.21875 0.734375 -0.3125q0.390625 -0.09375 0.796875 -0.09375q0.640625 0 1.140625 0.203125q0.5 0.203125 0.84375 0.59375q0.34375 0.390625 0.53125 0.96875q0.1875 0.578125 0.1875 1.3125l0 5.15625l-1.421875 0l0 -5.15625q0 -0.953125 -0.421875 -1.4375q-0.421875 -0.5 -1.203125 -0.5q-0.359375 0 -0.671875 0.125q-0.3125 0.125 -0.5625 0.359375q-0.234375 0.234375 -0.375 0.609375q-0.140625 0.359375 -0.140625 0.84375l0 5.15625l-1.421875 0l0 -5.15625q0 -0.984375 -0.390625 -1.453125q-0.390625 -0.484375 -1.140625 -0.484375q-0.53125 0 -0.984375 0.28125q-0.453125 0.28125 -0.828125 0.765625l0 6.046875l-1.421875 0zm16.33899 -8.234375q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm7.6026 7.3125q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm9.467957 -0.125l-0.640625 0q-0.203125 0 -0.328125 -0.0625q-0.125 -0.0625 -0.171875 -0.28125l-0.15625 -0.75q-0.328125 0.296875 -0.640625 0.53125q-0.296875 0.21875 -0.640625 0.375q-0.328125 0.15625 -0.703125 0.234375q-0.375 0.078125 -0.84375 0.078125q-0.46875 0 -0.890625 -0.125q-0.40625 -0.140625 -0.71875 -0.390625q-0.296875 -0.265625 -0.484375 -0.671875q-0.171875 -0.40625 -0.171875 -0.96875q0 -0.46875 0.265625 -0.90625q0.265625 -0.453125 0.84375 -0.796875q0.59375 -0.34375 1.546875 -0.5625q0.953125 -0.21875 2.328125 -0.25l0 -0.640625q0 -0.9375 -0.40625 -1.421875q-0.40625 -0.484375 -1.1875 -0.484375q-0.53125 0 -0.890625 0.140625q-0.34375 0.125 -0.609375 0.296875q-0.25 0.15625 -0.453125 0.296875q-0.1875 0.125 -0.359375 0.125q-0.15625 0 -0.265625 -0.078125q-0.09375 -0.078125 -0.15625 -0.1875l-0.265625 -0.453125q0.671875 -0.65625 1.453125 -0.96875q0.78125 -0.328125 1.71875 -0.328125q0.671875 0 1.203125 0.234375q0.53125 0.21875 0.890625 0.625q0.359375 0.390625 0.546875 0.96875q0.1875 0.5625 0.1875 1.234375l0 5.1875zm-3.703125 -0.875q0.375 0 0.6875 -0.078125q0.3125 -0.078125 0.578125 -0.203125q0.28125 -0.140625 0.53125 -0.34375q0.265625 -0.203125 0.5 -0.453125l0 -1.6875q-0.984375 0.03125 -1.671875 0.15625q-0.6875 0.109375 -1.125 0.3125q-0.421875 0.203125 -0.625 0.484375q-0.1875 0.265625 -0.1875 0.59375q0 0.328125 0.09375 0.5625q0.109375 0.234375 0.28125 0.375q0.171875 0.140625 0.40625 0.21875q0.25 0.0625 0.53125 0.0625zm11.565002 0.875q-0.3125 0 -0.390625 -0.296875l-0.125 -0.984375q-0.515625 0.640625 -1.1875 1.015625q-0.671875 0.375 -1.53125 0.375q-0.703125 0 -1.265625 -0.265625q-0.5625 -0.265625 -0.96875 -0.78125q-0.390625 -0.53125 -0.609375 -1.296875q-0.21875 -0.78125 -0.21875 -1.796875q0 -0.890625 0.234375 -1.65625q0.25 -0.78125 0.6875 -1.34375q0.453125 -0.5625 1.09375 -0.890625q0.65625 -0.328125 1.484375 -0.328125q0.75 0 1.265625 0.25q0.53125 0.25 0.953125 0.71875l0 -4.5l1.421875 0l0 11.78125l-0.84375 0zm-2.765625 -1.046875q0.703125 0 1.21875 -0.3125q0.53125 -0.328125 0.96875 -0.90625l0 -3.921875q-0.390625 -0.53125 -0.859375 -0.734375q-0.46875 -0.21875 -1.03125 -0.21875q-1.140625 0 -1.75 0.8125q-0.609375 0.8125 -0.609375 2.296875q0 0.796875 0.125 1.359375q0.140625 0.5625 0.40625 0.9375q0.265625 0.359375 0.640625 0.53125q0.390625 0.15625 0.890625 0.15625zm11.959534 1.046875l-0.640625 0q-0.203125 0 -0.328125 -0.0625q-0.125 -0.0625 -0.171875 -0.28125l-0.15625 -0.75q-0.328125 0.296875 -0.640625 0.53125q-0.296875 0.21875 -0.640625 0.375q-0.328125 0.15625 -0.703125 0.234375q-0.375 0.078125 -0.84375 0.078125q-0.46875 0 -0.890625 -0.125q-0.40625 -0.140625 -0.71875 -0.390625q-0.296875 -0.265625 -0.484375 -0.671875q-0.171875 -0.40625 -0.171875 -0.96875q0 -0.46875 0.265625 -0.90625q0.265625 -0.453125 0.84375 -0.796875q0.59375 -0.34375 1.546875 -0.5625q0.953125 -0.21875 2.328125 -0.25l0 -0.640625q0 -0.9375 -0.40625 -1.421875q-0.40625 -0.484375 -1.1875 -0.484375q-0.53125 0 -0.890625 0.140625q-0.34375 0.125 -0.609375 0.296875q-0.25 0.15625 -0.453125 0.296875q-0.1875 0.125 -0.359375 0.125q-0.15625 0 -0.265625 -0.078125q-0.09375 -0.078125 -0.15625 -0.1875l-0.265625 -0.453125q0.671875 -0.65625 1.453125 -0.96875q0.78125 -0.328125 1.71875 -0.328125q0.671875 0 1.203125 0.234375q0.53125 0.21875 0.890625 0.625q0.359375 0.390625 0.546875 0.96875q0.1875 0.5625 0.1875 1.234375l0 5.1875zm-3.703125 -0.875q0.375 0 0.6875 -0.078125q0.3125 -0.078125 0.578125 -0.203125q0.28125 -0.140625 0.53125 -0.34375q0.265625 -0.203125 0.5 -0.453125l0 -1.6875q-0.984375 0.03125 -1.671875 0.15625q-0.6875 0.109375 -1.125 0.3125q-0.421875 0.203125 -0.625 0.484375q-0.1875 0.265625 -0.1875 0.59375q0 0.328125 0.09375 0.5625q0.109375 0.234375 0.28125 0.375q0.171875 0.140625 0.40625 0.21875q0.25 0.0625 0.53125 0.0625zm8.315002 1.0q-0.96875 0 -1.484375 -0.53125q-0.515625 -0.53125 -0.515625 -1.546875l0 -4.953125l-0.96875 0q-0.125 0 -0.21875 -0.078125q-0.078125 -0.078125 -0.078125 -0.234375l0 -0.578125l1.328125 -0.15625l0.328125 -2.515625q0.015625 -0.109375 0.09375 -0.1875q0.09375 -0.078125 0.234375 -0.078125l0.71875 0l0 2.796875l2.3125 0l0 1.03125l-2.3125 0l0 4.859375q0 0.515625 0.234375 0.765625q0.25 0.234375 0.640625 0.234375q0.234375 0 0.390625 -0.046875q0.171875 -0.0625 0.28125 -0.125q0.125 -0.078125 0.203125 -0.140625q0.09375 -0.0625 0.15625 -0.0625q0.109375 0 0.203125 0.140625l0.40625 0.671875q-0.359375 0.34375 -0.890625 0.546875q-0.515625 0.1875 -1.0625 0.1875zm9.4678955 -0.125l-0.640625 0q-0.203125 0 -0.328125 -0.0625q-0.125 -0.0625 -0.171875 -0.28125l-0.15625 -0.75q-0.328125 0.296875 -0.640625 0.53125q-0.296875 0.21875 -0.640625 0.375q-0.328125 0.15625 -0.703125 0.234375q-0.375 0.078125 -0.84375 0.078125q-0.46875 0 -0.890625 -0.125q-0.40625 -0.140625 -0.71875 -0.390625q-0.296875 -0.265625 -0.484375 -0.671875q-0.171875 -0.40625 -0.171875 -0.96875q0 -0.46875 0.265625 -0.90625q0.265625 -0.453125 0.84375 -0.796875q0.59375 -0.34375 1.546875 -0.5625q0.953125 -0.21875 2.328125 -0.25l0 -0.640625q0 -0.9375 -0.40625 -1.421875q-0.40625 -0.484375 -1.1875 -0.484375q-0.53125 0 -0.890625 0.140625q-0.34375 0.125 -0.609375 0.296875q-0.25 0.15625 -0.453125 0.296875q-0.1875 0.125 -0.359375 0.125q-0.15625 0 -0.265625 -0.078125q-0.09375 -0.078125 -0.15625 -0.1875l-0.265625 -0.453125q0.671875 -0.65625 1.453125 -0.96875q0.78125 -0.328125 1.71875 -0.328125q0.671875 0 1.203125 0.234375q0.53125 0.21875 0.890625 0.625q0.359375 0.390625 0.546875 0.96875q0.1875 0.5625 0.1875 1.234375l0 5.1875zm-3.703125 -0.875q0.375 0 0.6875 -0.078125q0.3125 -0.078125 0.578125 -0.203125q0.28125 -0.140625 0.53125 -0.34375q0.265625 -0.203125 0.5 -0.453125l0 -1.6875q-0.984375 0.03125 -1.671875 0.15625q-0.6875 0.109375 -1.125 0.3125q-0.421875 0.203125 -0.625 0.484375q-0.1875 0.265625 -0.1875 0.59375q0 0.328125 0.09375 0.5625q0.109375 0.234375 0.28125 0.375q0.171875 0.140625 0.40625 0.21875q0.25 0.0625 0.53125 0.0625z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m395.41864 440.3466l0 0c0 -3.6181946 2.9331055 -6.5513 6.5513 -6.5513l163.90524 0c1.7375488 0 3.4038696 0.69021606 4.6325073 1.9188232c1.2285767 1.2286072 1.9188232 2.8949585 1.9188232 4.632477l0 26.204468c0 3.6181946 -2.9331055 6.5513 -6.5513306 6.5513l-163.90524 0c-3.6181946 0 -6.5513 -2.9331055 -6.5513 -6.5513z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m395.41864 440.3466l0 0c0 -3.6181946 2.9331055 -6.5513 6.5513 -6.5513l163.90524 0c1.7375488 0 3.4038696 0.69021606 4.6325073 1.9188232c1.2285767 1.2286072 1.9188232 2.8949585 1.9188232 4.632477l0 26.204468c0 3.6181946 -2.9331055 6.5513 -6.5513306 6.5513l-163.90524 0c-3.6181946 0 -6.5513 -2.9331055 -6.5513 -6.5513z" fill-rule="evenodd"/><path fill="#000000" d="m457.1988 462.0588l0 -10.859375l0.84375 0q0.296875 0 0.390625 0.296875l0.109375 0.96875q0.53125 -0.640625 1.1875 -1.015625q0.671875 -0.390625 1.546875 -0.390625q0.6875 0 1.25 0.265625q0.578125 0.265625 0.96875 0.796875q0.40625 0.53125 0.625 1.3125q0.21875 0.765625 0.21875 1.765625q0 0.90625 -0.25 1.6875q-0.234375 0.765625 -0.6875 1.328125q-0.4375 0.5625 -1.09375 0.890625q-0.65625 0.3125 -1.46875 0.3125q-0.75 0 -1.28125 -0.25q-0.53125 -0.25 -0.9375 -0.703125l0 3.59375l-1.421875 0zm3.609375 -9.84375q-0.703125 0 -1.234375 0.328125q-0.515625 0.3125 -0.953125 0.890625l0 3.921875q0.390625 0.53125 0.859375 0.75q0.46875 0.21875 1.046875 0.21875q1.125 0 1.734375 -0.8125q0.609375 -0.8125 0.609375 -2.3125q0 -0.78125 -0.140625 -1.34375q-0.140625 -0.578125 -0.40625 -0.9375q-0.265625 -0.375 -0.65625 -0.53125q-0.375 -0.171875 -0.859375 -0.171875zm11.175659 7.09375l-0.640625 0q-0.203125 0 -0.328125 -0.0625q-0.125 -0.0625 -0.171875 -0.28125l-0.15625 -0.75q-0.328125 0.296875 -0.640625 0.53125q-0.296875 0.21875 -0.640625 0.375q-0.328125 0.15625 -0.703125 0.234375q-0.375 0.078125 -0.84375 0.078125q-0.46875 0 -0.890625 -0.125q-0.40625 -0.140625 -0.71875 -0.390625q-0.296875 -0.265625 -0.484375 -0.671875q-0.171875 -0.40625 -0.171875 -0.96875q0 -0.46875 0.265625 -0.90625q0.265625 -0.453125 0.84375 -0.796875q0.59375 -0.34375 1.546875 -0.5625q0.953125 -0.21875 2.328125 -0.25l0 -0.640625q0 -0.9375 -0.40625 -1.421875q-0.40625 -0.484375 -1.1875 -0.484375q-0.53125 0 -0.890625 0.140625q-0.34375 0.125 -0.609375 0.296875q-0.25 0.15625 -0.453125 0.296875q-0.1875 0.125 -0.359375 0.125q-0.15625 0 -0.265625 -0.078125q-0.09375 -0.078125 -0.15625 -0.1875l-0.265625 -0.453125q0.671875 -0.65625 1.453125 -0.96875q0.78125 -0.328125 1.71875 -0.328125q0.671875 0 1.203125 0.234375q0.53125 0.21875 0.890625 0.625q0.359375 0.390625 0.546875 0.96875q0.1875 0.5625 0.1875 1.234375l0 5.1875zm-3.703125 -0.875q0.375 0 0.6875 -0.078125q0.3125 -0.078125 0.578125 -0.203125q0.28125 -0.140625 0.53125 -0.34375q0.265625 -0.203125 0.5 -0.453125l0 -1.6875q-0.984375 0.03125 -1.671875 0.15625q-0.6875 0.109375 -1.125 0.3125q-0.421875 0.203125 -0.625 0.484375q-0.1875 0.265625 -0.1875 0.59375q0 0.328125 0.09375 0.5625q0.109375 0.234375 0.28125 0.375q0.171875 0.140625 0.40625 0.21875q0.25 0.0625 0.53125 0.0625zm5.8618774 0.875l0 -8.109375l0.8125 0q0.234375 0 0.3125 0.09375q0.09375 0.09375 0.125 0.296875l0.09375 1.265625q0.421875 -0.84375 1.03125 -1.3125q0.609375 -0.484375 1.4375 -0.484375q0.328125 0 0.59375 0.078125q0.28125 0.078125 0.515625 0.21875l-0.1875 1.0625q-0.046875 0.1875 -0.25 0.1875q-0.109375 0 -0.34375 -0.0625q-0.21875 -0.078125 -0.640625 -0.078125q-0.75 0 -1.25 0.4375q-0.5 0.421875 -0.828125 1.25l0 5.15625l-1.421875 0zm11.088562 -6.765625q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm5.5064087 -1.46875q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5625 0.53125 0.9375q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.359375q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm7.8682556 -1.046875q0.53125 0 0.984375 0.109375q0.46875 0.109375 0.84375 0.34375l2.203125 0l0 0.53125q0 0.265625 -0.34375 0.328125l-0.921875 0.125q0.28125 0.53125 0.28125 1.171875q0 0.578125 -0.234375 1.0625q-0.21875 0.484375 -0.625 0.828125q-0.40625 0.34375 -0.96875 0.53125q-0.546875 0.1875 -1.21875 0.1875q-0.5625 0 -1.0625 -0.140625q-0.265625 0.171875 -0.40625 0.359375q-0.125 0.171875 -0.125 0.34375q0 0.296875 0.234375 0.453125q0.234375 0.140625 0.609375 0.203125q0.390625 0.0625 0.875 0.078125q0.5 0.015625 1.0 0.0625q0.515625 0.03125 1.0 0.125q0.484375 0.078125 0.859375 0.28125q0.390625 0.1875 0.625 0.546875q0.234375 0.34375 0.234375 0.90625q0 0.53125 -0.265625 1.015625q-0.25 0.484375 -0.75 0.859375q-0.484375 0.390625 -1.1875 0.609375q-0.703125 0.234375 -1.59375 0.234375q-0.875 0 -1.546875 -0.1875q-0.671875 -0.171875 -1.109375 -0.46875q-0.4375 -0.296875 -0.65625 -0.6875q-0.21875 -0.375 -0.21875 -0.796875q0 -0.609375 0.375 -1.015625q0.375 -0.421875 1.046875 -0.671875q-0.34375 -0.171875 -0.546875 -0.4375q-0.203125 -0.265625 -0.203125 -0.71875q0 -0.171875 0.0625 -0.359375q0.0625 -0.1875 0.1875 -0.359375q0.140625 -0.1875 0.328125 -0.359375q0.1875 -0.171875 0.453125 -0.296875q-0.609375 -0.34375 -0.953125 -0.890625q-0.328125 -0.5625 -0.328125 -1.296875q0 -0.59375 0.21875 -1.078125q0.234375 -0.484375 0.640625 -0.828125q0.40625 -0.34375 0.96875 -0.515625q0.5625 -0.1875 1.234375 -0.1875zm2.53125 8.671875q0 -0.296875 -0.171875 -0.484375q-0.15625 -0.1875 -0.453125 -0.28125q-0.28125 -0.109375 -0.65625 -0.15625q-0.375 -0.046875 -0.796875 -0.0625q-0.421875 -0.015625 -0.859375 -0.03125q-0.421875 -0.03125 -0.8125 -0.109375q-0.453125 0.21875 -0.75 0.53125q-0.28125 0.3125 -0.28125 0.75q0 0.265625 0.140625 0.5q0.140625 0.25 0.421875 0.421875q0.296875 0.171875 0.734375 0.265625q0.4375 0.09375 1.03125 0.09375q0.578125 0 1.03125 -0.109375q0.453125 -0.09375 0.765625 -0.296875q0.328125 -0.1875 0.484375 -0.453125q0.171875 -0.25 0.171875 -0.578125zm-2.53125 -4.390625q0.4375 0 0.765625 -0.125q0.328125 -0.125 0.546875 -0.328125q0.234375 -0.21875 0.34375 -0.515625q0.109375 -0.3125 0.109375 -0.671875q0 -0.734375 -0.453125 -1.171875q-0.4375 -0.453125 -1.3125 -0.453125q-0.84375 0 -1.296875 0.453125q-0.453125 0.4375 -0.453125 1.171875q0 0.359375 0.109375 0.671875q0.125 0.296875 0.34375 0.515625q0.21875 0.203125 0.546875 0.328125q0.328125 0.125 0.75 0.125zm8.738403 -4.28125q0.875 0 1.59375 0.296875q0.71875 0.296875 1.21875 0.84375q0.5 0.546875 0.765625 1.3125q0.265625 0.765625 0.265625 1.71875q0 0.96875 -0.265625 1.734375q-0.265625 0.765625 -0.765625 1.3125q-0.5 0.546875 -1.21875 0.84375q-0.71875 0.28125 -1.59375 0.28125q-0.890625 0 -1.609375 -0.28125q-0.71875 -0.296875 -1.21875 -0.84375q-0.5 -0.546875 -0.78125 -1.3125q-0.265625 -0.765625 -0.265625 -1.734375q0 -0.953125 0.265625 -1.71875q0.28125 -0.765625 0.78125 -1.3125q0.5 -0.546875 1.21875 -0.84375q0.71875 -0.296875 1.609375 -0.296875zm0 7.234375q1.1875 0 1.78125 -0.796875q0.59375 -0.8125 0.59375 -2.25q0 -1.453125 -0.59375 -2.25q-0.59375 -0.8125 -1.78125 -0.8125q-0.609375 0 -1.0625 0.203125q-0.453125 0.203125 -0.75 0.609375q-0.296875 0.390625 -0.453125 0.96875q-0.140625 0.5625 -0.140625 1.28125q0 0.71875 0.140625 1.296875q0.15625 0.5625 0.453125 0.953125q0.296875 0.375 0.75 0.59375q0.453125 0.203125 1.0625 0.203125z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m188.35957 108.64577l0 0c0 -4.3516846 3.5277405 -7.879425 7.879425 -7.879425l519.0443 0c2.0897217 0 4.093872 0.8301468 5.571594 2.3078308c1.4776611 1.4776764 2.3078003 3.4818344 2.3078003 5.571594l0 31.516739c0 4.3516846 -3.52771 7.879425 -7.8793945 7.879425l-519.0443 0c-4.3516846 0 -7.879425 -3.5277405 -7.879425 -7.879425z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m188.35957 108.64577l0 0c0 -4.3516846 3.5277405 -7.879425 7.879425 -7.879425l519.0443 0c2.0897217 0 4.093872 0.8301468 5.571594 2.3078308c1.4776611 1.4776764 2.3078003 3.4818344 2.3078003 5.571594l0 31.516739c0 4.3516846 -3.52771 7.879425 -7.8793945 7.879425l-519.0443 0c-4.3516846 0 -7.879425 -3.5277405 -7.879425 -7.879425z" fill-rule="evenodd"/><path fill="#000000" d="m439.27795 123.49851q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5624924 -0.203125 1.0468674q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.32811737 -0.1875 -0.5468674q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm5.5064087 -1.46875q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5624924 0.53125 0.9374924q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.3593674q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm5.1495056 7.1874924l0 -8.109367l0.8125 0q0.234375 0 0.3125 0.09375q0.09375 0.09375 0.125 0.296875l0.09375 1.265625q0.421875 -0.84375 1.03125 -1.3125q0.609375 -0.484375 1.4375 -0.484375q0.328125 0 0.59375 0.078125q0.28125 0.078125 0.515625 0.21875l-0.1875 1.0625q-0.046875 0.1875 -0.25 0.1875q-0.109375 0 -0.34375 -0.0625q-0.21875 -0.078125 -0.640625 -0.078125q-0.75 0 -1.25 0.4375q-0.5 0.421875 -0.828125 1.25l0 5.1562424l-1.421875 0zm5.416687 -8.109367l1.171875 0q0.171875 0 0.28125 0.09375q0.109375 0.09375 0.15625 0.203125l2.0625 5.21875q0.109375 0.296875 0.171875 0.5781174q0.0625 0.28125 0.125 0.5625q0.0625 -0.28125 0.125 -0.5625q0.078125 -0.28124237 0.1875 -0.5781174l2.078125 -5.21875q0.046875 -0.125 0.15625 -0.203125q0.109375 -0.09375 0.265625 -0.09375l1.125 0l-3.3125 8.109367l-1.28125 0l-3.3125 -8.109367zm12.218262 -0.125q0.734375 0 1.34375 0.25q0.609375 0.234375 1.0625 0.703125q0.453125 0.453125 0.703125 1.140625q0.25 0.671875 0.25 1.53125q0 0.34375 -0.078125 0.453125q-0.0625 0.109375 -0.265625 0.109375l-5.390625 0q0.015625 0.765625 0.203125 1.34375q0.203125 0.5624924 0.53125 0.9374924q0.34375 0.375 0.796875 0.5625q0.46875 0.1875 1.046875 0.1875q0.53125 0 0.921875 -0.109375q0.390625 -0.125 0.671875 -0.265625q0.28125 -0.15625 0.46875 -0.28125q0.1875 -0.125 0.3125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.25 0.328125 -0.625 0.5625q-0.375 0.234375 -0.796875 0.390625q-0.40625 0.140625 -0.859375 0.21875q-0.453125 0.078125 -0.890625 0.078125q-0.84375 0 -1.546875 -0.28125q-0.703125 -0.28125 -1.21875 -0.828125q-0.515625 -0.546875 -0.8125 -1.3593674q-0.28125 -0.8125 -0.28125 -1.859375q0 -0.84375 0.25 -1.578125q0.265625 -0.734375 0.75 -1.265625q0.5 -0.546875 1.203125 -0.859375q0.703125 -0.3125 1.578125 -0.3125zm0.03125 1.046875q-1.03125 0 -1.625 0.609375q-0.59375 0.59375 -0.734375 1.640625l4.40625 0q0 -0.5 -0.140625 -0.90625q-0.125 -0.40625 -0.390625 -0.703125q-0.265625 -0.3125 -0.65625 -0.46875q-0.375 -0.171875 -0.859375 -0.171875zm5.149536 7.1874924l0 -8.109367l0.8125 0q0.234375 0 0.3125 0.09375q0.09375 0.09375 0.125 0.296875l0.09375 1.265625q0.421875 -0.84375 1.03125 -1.3125q0.609375 -0.484375 1.4375 -0.484375q0.328125 0 0.59375 0.078125q0.28125 0.078125 0.515625 0.21875l-0.1875 1.0625q-0.046875 0.1875 -0.25 0.1875q-0.109375 0 -0.34375 -0.0625q-0.21875 -0.078125 -0.640625 -0.078125q-0.75 0 -1.25 0.4375q-0.5 0.421875 -0.828125 1.25l0 5.1562424l-1.421875 0z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m188.35957 64.67202l0 0c0 -2.9368782 2.3808136 -5.317688 5.3177032 -5.317688l524.1677 0c1.4103394 0 2.7629395 0.56025314 3.7601929 1.5575142c0.9972534 0.99726105 1.5574951 2.3498383 1.5574951 3.7601738l0 21.270134c0 2.9368744 -2.3807983 5.317688 -5.317688 5.317688l-524.1677 0c-2.9368896 0 -5.3177032 -2.3808136 -5.3177032 -5.317688z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m188.35957 64.67202l0 0c0 -2.9368782 2.3808136 -5.317688 5.3177032 -5.317688l524.1677 0c1.4103394 0 2.7629395 0.56025314 3.7601929 1.5575142c0.9972534 0.99726105 1.5574951 2.3498383 1.5574951 3.7601738l0 21.270134c0 2.9368744 -2.3807983 5.317688 -5.317688 5.317688l-524.1677 0c-2.9368896 0 -5.3177032 -2.3808136 -5.3177032 -5.317688z" fill-rule="evenodd"/><path fill="#000000" d="m437.19943 69.38583l0 11.78125l-1.421875 0l0 -11.78125l1.421875 0zm7.1584473 5.015625q-0.09375 0.171875 -0.296875 0.171875q-0.125 0 -0.28125 -0.078125q-0.140625 -0.09375 -0.375 -0.203125q-0.21875 -0.109375 -0.515625 -0.203125q-0.296875 -0.09375 -0.71875 -0.09375q-0.359375 0 -0.65625 0.09375q-0.28125 0.09375 -0.484375 0.265625q-0.203125 0.15625 -0.3125 0.375q-0.109375 0.203125 -0.109375 0.453125q0 0.296875 0.171875 0.515625q0.1875 0.203125 0.484375 0.359375q0.296875 0.15625 0.671875 0.265625q0.375 0.109375 0.765625 0.25q0.40625 0.125 0.78125 0.296875q0.375 0.15625 0.671875 0.40625q0.296875 0.234375 0.46875 0.578125q0.1875 0.34375 0.1875 0.828125q0 0.5625 -0.203125 1.046875q-0.203125 0.46875 -0.59375 0.828125q-0.390625 0.34375 -0.96875 0.546875q-0.5625 0.1875 -1.296875 0.1875q-0.84375 0 -1.546875 -0.265625q-0.6875 -0.28125 -1.15625 -0.71875l0.328125 -0.546875q0.0625 -0.09375 0.15625 -0.140625q0.09375 -0.0625 0.234375 -0.0625q0.140625 0 0.296875 0.109375q0.171875 0.109375 0.390625 0.25q0.234375 0.125 0.546875 0.25q0.328125 0.109375 0.8125 0.109375q0.421875 0 0.734375 -0.109375q0.3125 -0.109375 0.515625 -0.296875q0.21875 -0.1875 0.3125 -0.421875q0.09375 -0.234375 0.09375 -0.515625q0 -0.328125 -0.1875 -0.546875q-0.171875 -0.234375 -0.46875 -0.375q-0.296875 -0.15625 -0.671875 -0.265625q-0.375 -0.125 -0.78125 -0.25q-0.390625 -0.140625 -0.78125 -0.296875q-0.375 -0.171875 -0.671875 -0.40625q-0.28125 -0.25 -0.46875 -0.609375q-0.171875 -0.375 -0.171875 -0.890625q0 -0.46875 0.1875 -0.890625q0.1875 -0.4375 0.546875 -0.75q0.375 -0.328125 0.90625 -0.515625q0.546875 -0.203125 1.234375 -0.203125q0.796875 0 1.421875 0.25q0.640625 0.25 1.109375 0.703125l-0.3125 0.515625zm2.3032837 9.515625l0 -10.859375l0.84375 0q0.296875 0 0.390625 0.296875l0.109375 0.96875q0.53125 -0.640625 1.1875 -1.015625q0.671875 -0.390625 1.546875 -0.390625q0.6875 0 1.25 0.265625q0.578125 0.265625 0.96875 0.796875q0.40625 0.53125 0.625 1.3125q0.21875 0.765625 0.21875 1.765625q0 0.90625 -0.25 1.6875q-0.234375 0.765625 -0.6875 1.328125q-0.4375 0.5625 -1.09375 0.890625q-0.65625 0.3125 -1.46875 0.3125q-0.75 0 -1.28125 -0.25q-0.53125 -0.25 -0.9375 -0.703125l0 3.59375l-1.421875 0zm3.609375 -9.84375q-0.703125 0 -1.234375 0.328125q-0.515625 0.3125 -0.953125 0.890625l0 3.921875q0.390625 0.53125 0.859375 0.75q0.46875 0.21875 1.046875 0.21875q1.125 0 1.734375 -0.8125q0.609375 -0.8125 0.609375 -2.3125q0 -0.78125 -0.140625 -1.34375q-0.140625 -0.578125 -0.40625 -0.9375q-0.265625 -0.375 -0.65625 -0.53125q-0.375 -0.171875 -0.859375 -0.171875zm5.222534 7.09375l0 -8.109375l0.8125 0q0.234375 0 0.3125 0.09375q0.09375 0.09375 0.125 0.296875l0.09375 1.265625q0.421875 -0.84375 1.03125 -1.3125q0.609375 -0.484375 1.4375 -0.484375q0.328125 0 0.59375 0.078125q0.28125 0.078125 0.515625 0.21875l-0.1875 1.0625q-0.046875 0.1875 -0.25 0.1875q-0.109375 0 -0.34375 -0.0625q-0.21875 -0.078125 -0.640625 -0.078125q-0.75 0 -1.25 0.4375q-0.5 0.421875 -0.828125 1.25l0 5.15625l-1.421875 0zm6.4479065 2.75l0 -10.859375l0.84375 0q0.296875 0 0.390625 0.296875l0.109375 0.96875q0.53125 -0.640625 1.1875 -1.015625q0.671875 -0.390625 1.546875 -0.390625q0.6875 0 1.25 0.265625q0.578125 0.265625 0.96875 0.796875q0.40625 0.53125 0.625 1.3125q0.21875 0.765625 0.21875 1.765625q0 0.90625 -0.25 1.6875q-0.234375 0.765625 -0.6875 1.328125q-0.4375 0.5625 -1.09375 0.890625q-0.65625 0.3125 -1.46875 0.3125q-0.75 0 -1.28125 -0.25q-0.53125 -0.25 -0.9375 -0.703125l0 3.59375l-1.421875 0zm3.609375 -9.84375q-0.703125 0 -1.234375 0.328125q-0.515625 0.3125 -0.953125 0.890625l0 3.921875q0.390625 0.53125 0.859375 0.75q0.46875 0.21875 1.046875 0.21875q1.125 0 1.734375 -0.8125q0.609375 -0.8125 0.609375 -2.3125q0 -0.78125 -0.140625 -1.34375q-0.140625 -0.578125 -0.40625 -0.9375q-0.265625 -0.375 -0.65625 -0.53125q-0.375 -0.171875 -0.859375 -0.171875zm10.753754 0.4375q-0.078125 0.078125 -0.140625 0.125q-0.0625 0.046875 -0.171875 0.046875q-0.125 0 -0.265625 -0.09375q-0.140625 -0.109375 -0.359375 -0.21875q-0.21875 -0.125 -0.53125 -0.21875q-0.296875 -0.109375 -0.75 -0.109375q-0.59375 0 -1.046875 0.21875q-0.453125 0.203125 -0.765625 0.609375q-0.296875 0.40625 -0.453125 0.96875q-0.15625 0.5625 -0.15625 1.265625q0 0.75 0.15625 1.328125q0.171875 0.5625 0.46875 0.953125q0.3125 0.375 0.75 0.59375q0.4375 0.203125 0.984375 0.203125q0.515625 0 0.84375 -0.125q0.34375 -0.125 0.5625 -0.28125q0.234375 -0.15625 0.375 -0.28125q0.140625 -0.125 0.28125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.53125 0.65625 -1.328125 0.953125q-0.78125 0.296875 -1.65625 0.296875q-0.765625 0 -1.421875 -0.28125q-0.640625 -0.28125 -1.125 -0.8125q-0.484375 -0.53125 -0.765625 -1.296875q-0.265625 -0.78125 -0.265625 -1.78125q0 -0.890625 0.25 -1.65625q0.25 -0.78125 0.734375 -1.328125q0.484375 -0.5625 1.1875 -0.875q0.71875 -0.3125 1.640625 -0.3125q0.84375 0 1.5 0.28125q0.65625 0.265625 1.171875 0.78125l-0.375 0.515625z" fill-rule="nonzero"/><path fill="#cfe2f3" d="m188.35957 23.259949l0 0c0 -2.93688 2.3808136 -5.317692 5.3177032 -5.317692l524.1677 0c1.4103394 0 2.7629395 0.56025505 3.7601929 1.5575161c0.9972534 0.99726105 1.5574951 2.3498363 1.5574951 3.7601757l0 21.27013c0 2.9368782 -2.3807983 5.317692 -5.317688 5.317692l-524.1677 0c-2.9368896 0 -5.3177032 -2.3808136 -5.3177032 -5.317692z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m188.35957 23.259949l0 0c0 -2.93688 2.3808136 -5.317692 5.3177032 -5.317692l524.1677 0c1.4103394 0 2.7629395 0.56025505 3.7601929 1.5575161c0.9972534 0.99726105 1.5574951 2.3498363 1.5574951 3.7601757l0 21.27013c0 2.9368782 -2.3807983 5.317692 -5.317688 5.317692l-524.1677 0c-2.9368896 0 -5.3177032 -2.3808136 -5.3177032 -5.317692z" fill-rule="evenodd"/><path fill="#000000" d="m447.68848 33.098763q-0.078125 0.078125 -0.140625 0.125q-0.0625 0.046875 -0.171875 0.046875q-0.125 0 -0.265625 -0.09375q-0.140625 -0.109375 -0.359375 -0.21875q-0.21875 -0.125 -0.53125 -0.21875q-0.296875 -0.109375 -0.75 -0.109375q-0.59375 0 -1.046875 0.21875q-0.453125 0.203125 -0.765625 0.609375q-0.296875 0.40625 -0.453125 0.96875q-0.15625 0.5625 -0.15625 1.265625q0 0.75 0.15625 1.328125q0.171875 0.5625 0.46875 0.953125q0.3125 0.375 0.75 0.59375q0.4375 0.203125 0.984375 0.203125q0.515625 0 0.84375 -0.125q0.34375 -0.125 0.5625 -0.28125q0.234375 -0.15625 0.375 -0.28125q0.140625 -0.125 0.28125 -0.125q0.1875 0 0.28125 0.140625l0.390625 0.515625q-0.53125 0.65625 -1.328125 0.953125q-0.78125 0.296875 -1.65625 0.296875q-0.765625 0 -1.421875 -0.28125q-0.640625 -0.28125 -1.125 -0.8125q-0.484375 -0.53125 -0.765625 -1.296875q-0.265625 -0.78125 -0.265625 -1.78125q0 -0.890625 0.25 -1.65625q0.25 -0.78125 0.734375 -1.328125q0.484375 -0.5625 1.1875 -0.875q0.71875 -0.3125 1.640625 -0.3125q0.84375 0 1.5 0.28125q0.65625 0.265625 1.171875 0.78125l-0.375 0.515625zm1.9406433 6.65625l0 -8.109375l0.84375 0q0.296875 0 0.390625 0.296875l0.09375 0.84375q0.453125 -0.5625 1.0 -0.90625q0.5625 -0.359375 1.296875 -0.359375q0.828125 0 1.328125 0.46875q0.515625 0.453125 0.734375 1.21875q0.171875 -0.4375 0.4375 -0.75q0.28125 -0.328125 0.625 -0.53125q0.34375 -0.21875 0.734375 -0.3125q0.390625 -0.09375 0.796875 -0.09375q0.640625 0 1.140625 0.203125q0.5 0.203125 0.84375 0.59375q0.34375 0.390625 0.53125 0.96875q0.1875 0.578125 0.1875 1.3125l0 5.15625l-1.421875 0l0 -5.15625q0 -0.953125 -0.421875 -1.4375q-0.421875 -0.5 -1.203125 -0.5q-0.359375 0 -0.671875 0.125q-0.3125 0.125 -0.5625 0.359375q-0.234375 0.234375 -0.375 0.609375q-0.140625 0.359375 -0.140625 0.84375l0 5.15625l-1.421875 0l0 -5.15625q0 -0.984375 -0.390625 -1.453125q-0.390625 -0.484375 -1.140625 -0.484375q-0.53125 0 -0.984375 0.28125q-0.453125 0.28125 -0.828125 0.765625l0 6.046875l-1.421875 0zm18.83899 0q-0.3125 0 -0.390625 -0.296875l-0.125 -0.984375q-0.515625 0.640625 -1.1875 1.015625q-0.671875 0.375 -1.53125 0.375q-0.703125 0 -1.265625 -0.265625q-0.5625 -0.265625 -0.96875 -0.78125q-0.390625 -0.53125 -0.609375 -1.296875q-0.21875 -0.78125 -0.21875 -1.796875q0 -0.890625 0.234375 -1.65625q0.25 -0.78125 0.6875 -1.34375q0.453125 -0.5625 1.09375 -0.890625q0.65625 -0.328125 1.484375 -0.328125q0.75 0 1.265625 0.25q0.53125 0.25 0.953125 0.71875l0 -4.5l1.421875 0l0 11.78125l-0.84375 0zm-2.765625 -1.046875q0.703125 0 1.21875 -0.3125q0.53125 -0.328125 0.96875 -0.90625l0 -3.921875q-0.390625 -0.53125 -0.859375 -0.734375q-0.46875 -0.21875 -1.03125 -0.21875q-1.140625 0 -1.75 0.8125q-0.609375 0.8125 -0.609375 2.296875q0 0.796875 0.125 1.359375q0.140625 0.5625 0.40625 0.9375q0.265625 0.359375 0.640625 0.53125q0.390625 0.15625 0.890625 0.15625z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m188.84776 269.45407l-59.18109 22.236206" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m188.84776 269.45407l-53.56447 20.125885" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m134.70233 288.03375l-3.6671753 3.1423645l4.8290863 -0.049987793z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m724.2021 345.2126l66.677185 40.409454" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m724.2021 345.2126l61.54596 37.299713" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m784.89197 383.92487l4.7370605 0.93948364l-3.0249023 -3.764618z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m188.84776 302.54593l-56.15747 35.590546" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m188.84776 302.54593l-51.08954 32.378693" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m136.87402 333.52948l-2.9489288 3.8244324l4.7173157 -1.0341492z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m727.72015 16.929134l180.72443 0l0 35.59055l-180.72443 0z" fill-rule="evenodd"/><path fill="#000000" d="m744.6108 36.760384q0.109375 0 0.1875 0.078125l0.515625 0.5625q-0.59375 0.671875 -1.4375 1.0625q-0.828125 0.375 -2.0 0.375q-1.03125 0 -1.875 -0.359375q-0.84375 -0.359375 -1.4375 -1.0q-0.59375 -0.640625 -0.921875 -1.53125q-0.328125 -0.90625 -0.328125 -1.984375q0 -1.078125 0.34375 -1.984375q0.359375 -0.90625 0.984375 -1.546875q0.640625 -0.640625 1.515625 -1.0q0.890625 -0.359375 1.953125 -0.359375q1.0625 0 1.828125 0.328125q0.765625 0.328125 1.34375 0.890625l-0.40625 0.59375q-0.046875 0.0625 -0.109375 0.109375q-0.0625 0.03125 -0.171875 0.03125q-0.09375 0 -0.1875 -0.0625q-0.09375 -0.0625 -0.234375 -0.15625q-0.125 -0.09375 -0.3125 -0.1875q-0.171875 -0.109375 -0.421875 -0.203125q-0.25 -0.09375 -0.578125 -0.15625q-0.328125 -0.0625 -0.75 -0.0625q-0.765625 0 -1.40625 0.265625q-0.625 0.25 -1.09375 0.75q-0.453125 0.484375 -0.71875 1.1875q-0.25 0.6875 -0.25 1.5625q0 0.890625 0.25 1.59375q0.265625 0.6875 0.703125 1.171875q0.4375 0.484375 1.046875 0.75q0.609375 0.25 1.3125 0.25q0.421875 0 0.765625 -0.046875q0.34375 -0.0625 0.625 -0.15625q0.296875 -0.109375 0.546875 -0.265625q0.25 -0.171875 0.5 -0.40625q0.109375 -0.09375 0.21875 -0.09375zm3.6922607 0.875l4.125 0l0 1.09375l-5.421875 0l0 -9.546875l1.296875 0l0 8.453125zm7.084961 1.09375l-1.28125 0l0 -9.546875l1.28125 0l0 9.546875zm6.9921875 0.109375q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm5.6588745 -6.96875q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm7.4104004 -6.03125q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm6.0041504 -8.984375l0 9.8125l-1.1875 0l0 -9.8125l1.1875 0zm1.7401123 9.0q0 -0.15625 0.046875 -0.296875q0.0625 -0.140625 0.171875 -0.234375q0.109375 -0.109375 0.25 -0.171875q0.140625 -0.0625 0.3125 -0.0625q0.203125 0 0.359375 0.078125q0.15625 0.078125 0.25 0.203125q0.109375 0.125 0.15625 0.296875q0.0625 0.171875 0.0625 0.375q0 0.296875 -0.09375 0.625q-0.078125 0.3125 -0.234375 0.625q-0.15625 0.328125 -0.40625 0.625q-0.234375 0.296875 -0.53125 0.5625l-0.203125 -0.203125q-0.078125 -0.078125 -0.078125 -0.1875q0 -0.078125 0.09375 -0.171875q0.0625 -0.078125 0.15625 -0.203125q0.109375 -0.125 0.21875 -0.28125q0.109375 -0.15625 0.203125 -0.359375q0.09375 -0.1875 0.125 -0.40625l-0.078125 0q-0.1875 0 -0.328125 -0.0625q-0.125 -0.0625 -0.234375 -0.171875q-0.109375 -0.109375 -0.171875 -0.25q-0.046875 -0.15625 -0.046875 -0.328125zm7.226013 -0.28125l4.125 0l0 1.09375l-5.421875 0l0 -9.546875l1.296875 0l0 8.453125zm10.444397 -6.96875q-0.0625 0.109375 -0.125 0.15625q-0.0625 0.046875 -0.171875 0.046875q-0.109375 0 -0.265625 -0.109375q-0.140625 -0.109375 -0.375 -0.25q-0.234375 -0.140625 -0.5625 -0.25q-0.3125 -0.109375 -0.78125 -0.109375q-0.421875 0 -0.765625 0.125q-0.328125 0.109375 -0.5625 0.3125q-0.21875 0.1875 -0.328125 0.46875q-0.109375 0.265625 -0.109375 0.578125q0 0.390625 0.1875 0.65625q0.203125 0.265625 0.515625 0.453125q0.328125 0.1875 0.734375 0.328125q0.421875 0.125 0.84375 0.28125q0.4375 0.140625 0.84375 0.328125q0.40625 0.1875 0.734375 0.46875q0.328125 0.265625 0.515625 0.6875q0.203125 0.40625 0.203125 0.984375q0 0.640625 -0.21875 1.1875q-0.203125 0.546875 -0.625 0.953125q-0.40625 0.40625 -1.0 0.640625q-0.59375 0.234375 -1.359375 0.234375q-0.921875 0 -1.6875 -0.328125q-0.765625 -0.34375 -1.296875 -0.921875l0.375 -0.609375q0.046875 -0.078125 0.125 -0.125q0.078125 -0.046875 0.171875 -0.046875q0.140625 0 0.3125 0.15625q0.1875 0.140625 0.453125 0.328125q0.265625 0.171875 0.640625 0.328125q0.390625 0.140625 0.953125 0.140625q0.453125 0 0.8125 -0.125q0.359375 -0.125 0.609375 -0.34375q0.25 -0.234375 0.375 -0.546875q0.140625 -0.328125 0.140625 -0.734375q0 -0.421875 -0.203125 -0.703125q-0.1875 -0.28125 -0.515625 -0.46875q-0.3125 -0.1875 -0.71875 -0.3125q-0.40625 -0.125 -0.84375 -0.265625q-0.421875 -0.140625 -0.84375 -0.3125q-0.40625 -0.1875 -0.734375 -0.46875q-0.3125 -0.28125 -0.515625 -0.703125q-0.1875 -0.4375 -0.1875 -1.078125q0 -0.5 0.1875 -0.96875q0.203125 -0.484375 0.578125 -0.84375q0.375 -0.375 0.921875 -0.59375q0.546875 -0.21875 1.265625 -0.21875q0.796875 0 1.453125 0.25q0.671875 0.25 1.15625 0.734375l-0.3125 0.609375zm3.5950928 4.484375l0 3.578125l-1.28125 0l0 -9.546875l2.8125 0q0.90625 0 1.578125 0.21875q0.671875 0.203125 1.109375 0.59375q0.4375 0.375 0.65625 0.921875q0.21875 0.546875 0.21875 1.21875q0 0.671875 -0.234375 1.234375q-0.234375 0.546875 -0.6875 0.953125q-0.453125 0.390625 -1.125 0.609375q-0.65625 0.21875 -1.515625 0.21875l-1.53125 0zm0 -1.015625l1.53125 0q0.5625 0 0.984375 -0.140625q0.421875 -0.15625 0.703125 -0.421875q0.28125 -0.265625 0.421875 -0.625q0.15625 -0.375 0.15625 -0.8125q0 -0.90625 -0.5625 -1.421875q-0.5625 -0.515625 -1.703125 -0.515625l-1.53125 0l0 3.9375zm13.715759 -0.953125q-0.046875 0.0625 -0.109375 0.109375q-0.046875 0.046875 -0.15625 0.046875q-0.09375 0 -0.21875 -0.078125q-0.109375 -0.09375 -0.296875 -0.1875q-0.171875 -0.109375 -0.4375 -0.1875q-0.25 -0.09375 -0.625 -0.09375q-0.484375 0 -0.875 0.1875q-0.375 0.171875 -0.640625 0.515625q-0.25 0.328125 -0.375 0.796875q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.140625 1.09375q0.140625 0.46875 0.390625 0.796875q0.25 0.3125 0.609375 0.484375q0.359375 0.171875 0.8125 0.171875q0.4375 0 0.71875 -0.09375q0.28125 -0.109375 0.46875 -0.234375q0.1875 -0.125 0.296875 -0.234375q0.125 -0.109375 0.25 -0.109375q0.15625 0 0.21875 0.125l0.34375 0.421875q-0.4375 0.546875 -1.109375 0.796875q-0.65625 0.25 -1.390625 0.25q-0.625 0 -1.171875 -0.234375q-0.546875 -0.234375 -0.953125 -0.671875q-0.390625 -0.453125 -0.625 -1.09375q-0.21875 -0.640625 -0.21875 -1.46875q0 -0.75 0.203125 -1.390625q0.203125 -0.640625 0.609375 -1.109375q0.40625 -0.46875 1.0 -0.71875q0.59375 -0.265625 1.359375 -0.265625q0.703125 0 1.25 0.234375q0.546875 0.234375 0.96875 0.640625l-0.3125 0.4375zm2.9429932 -4.265625l0 9.8125l-1.1875 0l0 -9.8125l1.1875 0zm3.4119873 3.0625l0 6.75l-1.1875 0l0 -6.75l1.1875 0zm0.265625 -2.125q0 0.171875 -0.078125 0.328125q-0.0625 0.15625 -0.1875 0.28125q-0.109375 0.109375 -0.265625 0.171875q-0.15625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.265625 -0.171875q-0.109375 -0.125 -0.1875 -0.28125q-0.0625 -0.15625 -0.0625 -0.328125q0 -0.171875 0.0625 -0.328125q0.078125 -0.15625 0.1875 -0.265625q0.125 -0.125 0.265625 -0.1875q0.15625 -0.0625 0.328125 -0.0625q0.171875 0 0.328125 0.0625q0.15625 0.0625 0.265625 0.1875q0.125 0.109375 0.1875 0.265625q0.078125 0.15625 0.078125 0.328125zm4.4901123 2.015625q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm4.2807617 5.984375l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.734375q0.4375 -0.484375 0.984375 -0.78125q0.546875 -0.3125 1.25 -0.3125q0.5625 0 0.984375 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0625 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0zm9.457275 0.109375q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m727.72015 56.929134l180.72443 0l0 35.59055l-180.72443 0z" fill-rule="evenodd"/><path fill="#000000" d="m741.47015 75.43226q0 0.796875 -0.203125 1.4375q-0.1875 0.625 -0.578125 1.0625q-0.375 0.4375 -0.9375 0.671875q-0.5625 0.234375 -1.28125 0.234375q-0.65625 0 -1.34375 -0.1875q0 -0.1875 0.015625 -0.375q0.03125 -0.203125 0.046875 -0.390625q0.015625 -0.109375 0.078125 -0.171875q0.078125 -0.078125 0.21875 -0.078125q0.125 0 0.3125 0.0625q0.203125 0.0625 0.546875 0.0625q0.4375 0 0.78125 -0.125q0.34375 -0.140625 0.578125 -0.421875q0.234375 -0.28125 0.359375 -0.71875q0.125 -0.4375 0.125 -1.03125l0 -6.28125l1.28125 0l0 6.25zm7.2145386 -4.765625q-0.0625 0.109375 -0.125 0.15625q-0.0625 0.046875 -0.171875 0.046875q-0.109375 0 -0.265625 -0.109375q-0.140625 -0.109375 -0.375 -0.25q-0.234375 -0.140625 -0.5625 -0.25q-0.3125 -0.109375 -0.78125 -0.109375q-0.421875 0 -0.765625 0.125q-0.328125 0.109375 -0.5625 0.3125q-0.21875 0.1875 -0.328125 0.46875q-0.109375 0.265625 -0.109375 0.578125q0 0.390625 0.1875 0.65625q0.203125 0.265625 0.515625 0.453125q0.328125 0.1875 0.734375 0.328125q0.421875 0.125 0.84375 0.28125q0.4375 0.140625 0.84375 0.328125q0.40625 0.1875 0.734375 0.46875q0.328125 0.265625 0.515625 0.6875q0.203125 0.40625 0.203125 0.984375q0 0.640625 -0.21875 1.1875q-0.203125 0.546875 -0.625 0.953125q-0.40625 0.40625 -1.0 0.640625q-0.59375 0.234375 -1.359375 0.234375q-0.921875 0 -1.6875 -0.328125q-0.765625 -0.34375 -1.296875 -0.921875l0.375 -0.609375q0.046875 -0.078125 0.125 -0.125q0.078125 -0.046875 0.171875 -0.046875q0.140625 0 0.3125 0.15625q0.1875 0.140625 0.453125 0.328125q0.265625 0.171875 0.640625 0.328125q0.390625 0.140625 0.953125 0.140625q0.453125 0 0.8125 -0.125q0.359375 -0.125 0.609375 -0.34375q0.25 -0.234375 0.375 -0.546875q0.140625 -0.328125 0.140625 -0.734375q0 -0.421875 -0.203125 -0.703125q-0.1875 -0.28125 -0.515625 -0.46875q-0.3125 -0.1875 -0.71875 -0.3125q-0.40625 -0.125 -0.84375 -0.265625q-0.421875 -0.140625 -0.84375 -0.3125q-0.40625 -0.1875 -0.734375 -0.46875q-0.3125 -0.28125 -0.515625 -0.703125q-0.1875 -0.4375 -0.1875 -1.078125q0 -0.5 0.1875 -0.96875q0.203125 -0.484375 0.578125 -0.84375q0.375 -0.375 0.921875 -0.59375q0.546875 -0.21875 1.265625 -0.21875q0.796875 0 1.453125 0.25q0.671875 0.25 1.15625 0.734375l-0.3125 0.609375zm11.048279 3.296875q0 1.0625 -0.34375 1.96875q-0.34375 0.890625 -0.96875 1.546875q-0.609375 0.640625 -1.484375 1.0q-0.859375 0.34375 -1.921875 0.34375q-1.046875 0 -1.921875 -0.34375q-0.859375 -0.359375 -1.484375 -1.0q-0.609375 -0.65625 -0.953125 -1.546875q-0.34375 -0.90625 -0.34375 -1.96875q0 -1.078125 0.34375 -1.96875q0.34375 -0.90625 0.953125 -1.546875q0.625 -0.65625 1.484375 -1.015625q0.875 -0.359375 1.921875 -0.359375q1.0625 0 1.921875 0.359375q0.875 0.359375 1.484375 1.015625q0.625 0.640625 0.96875 1.546875q0.34375 0.890625 0.34375 1.96875zm-1.328125 0q0 -0.890625 -0.25 -1.578125q-0.234375 -0.703125 -0.671875 -1.1875q-0.4375 -0.484375 -1.0625 -0.734375q-0.625 -0.265625 -1.40625 -0.265625q-0.765625 0 -1.390625 0.265625q-0.625 0.25 -1.078125 0.734375q-0.4375 0.484375 -0.671875 1.1875q-0.234375 0.6875 -0.234375 1.578125q0 0.875 0.234375 1.578125q0.234375 0.6875 0.671875 1.171875q0.453125 0.484375 1.078125 0.75q0.625 0.25 1.390625 0.25q0.78125 0 1.40625 -0.25q0.625 -0.265625 1.0625 -0.75q0.4375 -0.484375 0.671875 -1.171875q0.25 -0.703125 0.25 -1.578125zm3.7608032 -4.78125q0.171875 0 0.25 0.046875q0.09375 0.03125 0.1875 0.171875l5.53125 7.203125q-0.015625 -0.1875 -0.03125 -0.34375q0 -0.15625 0 -0.3125l0 -6.765625l1.140625 0l0 9.546875l-0.65625 0q-0.15625 0 -0.265625 -0.046875q-0.09375 -0.0625 -0.1875 -0.1875l-5.53125 -7.1875q0.015625 0.171875 0.015625 0.328125q0.015625 0.15625 0.015625 0.296875l0 6.796875l-1.140625 0l0 -9.546875l0.671875 0l0 0zm10.825989 5.5625l0 3.984375l-1.28125 0l0 -9.546875l2.6875 0q0.90625 0 1.5625 0.1875q0.671875 0.171875 1.09375 0.53125q0.4375 0.34375 0.640625 0.828125q0.203125 0.484375 0.203125 1.09375q0 0.515625 -0.15625 0.953125q-0.15625 0.4375 -0.46875 0.796875q-0.296875 0.34375 -0.734375 0.59375q-0.4375 0.234375 -0.984375 0.359375q0.234375 0.140625 0.421875 0.40625l2.78125 3.796875l-1.140625 0q-0.359375 0 -0.515625 -0.265625l-2.484375 -3.421875q-0.109375 -0.15625 -0.25 -0.21875q-0.125 -0.078125 -0.390625 -0.078125l-0.984375 0zm0 -0.9375l1.359375 0q0.5625 0 0.984375 -0.140625q0.4375 -0.140625 0.71875 -0.390625q0.296875 -0.25 0.4375 -0.59375q0.15625 -0.34375 0.15625 -0.765625q0 -0.84375 -0.5625 -1.28125q-0.5625 -0.4375 -1.6875 -0.4375l-1.40625 0l0 3.609375zm8.583313 1.34375l0 3.578125l-1.28125 0l0 -9.546875l2.8125 0q0.90625 0 1.578125 0.21875q0.671875 0.203125 1.109375 0.59375q0.4375 0.375 0.65625 0.921875q0.21875 0.546875 0.21875 1.21875q0 0.671875 -0.234375 1.234375q-0.234375 0.546875 -0.6875 0.953125q-0.453125 0.390625 -1.125 0.609375q-0.65625 0.21875 -1.515625 0.21875l-1.53125 0zm0 -1.015625l1.53125 0q0.5625 0 0.984375 -0.140625q0.421875 -0.15625 0.703125 -0.421875q0.28125 -0.265625 0.421875 -0.625q0.15625 -0.375 0.15625 -0.8125q0 -0.90625 -0.5625 -1.421875q-0.5625 -0.515625 -1.703125 -0.515625l-1.53125 0l0 3.9375zm13.455933 2.625q0.109375 0 0.1875 0.078125l0.515625 0.5625q-0.59375 0.671875 -1.4375 1.0625q-0.828125 0.375 -2.0 0.375q-1.03125 0 -1.875 -0.359375q-0.84375 -0.359375 -1.4375 -1.0q-0.59375 -0.640625 -0.921875 -1.53125q-0.328125 -0.90625 -0.328125 -1.984375q0 -1.078125 0.34375 -1.984375q0.359375 -0.90625 0.984375 -1.546875q0.640625 -0.640625 1.515625 -1.0q0.890625 -0.359375 1.953125 -0.359375q1.0625 0 1.828125 0.328125q0.765625 0.328125 1.34375 0.890625l-0.40625 0.59375q-0.046875 0.0625 -0.109375 0.109375q-0.0625 0.03125 -0.171875 0.03125q-0.09375 0 -0.1875 -0.0625q-0.09375 -0.0625 -0.234375 -0.15625q-0.125 -0.09375 -0.3125 -0.1875q-0.171875 -0.109375 -0.421875 -0.203125q-0.25 -0.09375 -0.578125 -0.15625q-0.328125 -0.0625 -0.75 -0.0625q-0.765625 0 -1.40625 0.265625q-0.625 0.25 -1.09375 0.75q-0.453125 0.484375 -0.71875 1.1875q-0.25 0.6875 -0.25 1.5625q0 0.890625 0.25 1.59375q0.265625 0.6875 0.703125 1.171875q0.4375 0.484375 1.046875 0.75q0.609375 0.25 1.3125 0.25q0.421875 0 0.765625 -0.046875q0.34375 -0.0625 0.625 -0.15625q0.296875 -0.109375 0.546875 -0.265625q0.25 -0.171875 0.5 -0.40625q0.109375 -0.09375 0.21875 -0.09375zm8.655151 -3.671875q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm4.581238 -1.21875q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm4.2808228 5.984375l0 -6.75l0.6875 0q0.1875 0 0.265625 0.078125q0.078125 0.0625 0.09375 0.25l0.078125 1.046875q0.359375 -0.703125 0.859375 -1.09375q0.515625 -0.40625 1.203125 -0.40625q0.28125 0 0.5 0.0625q0.234375 0.0625 0.421875 0.1875l-0.15625 0.875q-0.046875 0.171875 -0.203125 0.171875q-0.09375 0 -0.296875 -0.0625q-0.1875 -0.0625 -0.53125 -0.0625q-0.625 0 -1.046875 0.359375q-0.40625 0.359375 -0.6875 1.046875l0 4.296875l-1.1875 0zm4.527466 -6.75l0.96875 0q0.140625 0 0.234375 0.078125q0.09375 0.0625 0.125 0.171875l1.71875 4.34375q0.09375 0.234375 0.140625 0.484375q0.0625 0.234375 0.109375 0.46875q0.046875 -0.234375 0.109375 -0.46875q0.0625 -0.25 0.15625 -0.484375l1.734375 -4.34375q0.03125 -0.109375 0.125 -0.171875q0.09375 -0.078125 0.21875 -0.078125l0.9375 0l-2.765625 6.75l-1.0625 0l-2.75 -6.75zm10.16626 -0.109375q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm4.2807617 5.984375l0 -6.75l0.6875 0q0.1875 0 0.265625 0.078125q0.078125 0.0625 0.09375 0.25l0.078125 1.046875q0.359375 -0.703125 0.859375 -1.09375q0.515625 -0.40625 1.203125 -0.40625q0.28125 0 0.5 0.0625q0.234375 0.0625 0.421875 0.1875l-0.15625 0.875q-0.046875 0.171875 -0.203125 0.171875q-0.09375 0 -0.296875 -0.0625q-0.1875 -0.0625 -0.53125 -0.0625q-0.625 0 -1.046875 0.359375q-0.40625 0.359375 -0.6875 1.046875l0 4.296875l-1.1875 0zm7.9904175 0l0 -9.8125l1.1875 0l0 4.03125q0.421875 -0.484375 0.96875 -0.78125q0.546875 -0.296875 1.234375 -0.296875q0.59375 0 1.0625 0.21875q0.46875 0.21875 0.796875 0.65625q0.34375 0.4375 0.515625 1.078125q0.1875 0.640625 0.1875 1.484375q0 0.75 -0.203125 1.390625q-0.1875 0.640625 -0.578125 1.109375q-0.375 0.46875 -0.921875 0.75q-0.53125 0.265625 -1.21875 0.265625q-0.640625 0 -1.109375 -0.25q-0.453125 -0.25 -0.796875 -0.703125l-0.0625 0.609375q-0.046875 0.25 -0.296875 0.25l-0.765625 0zm3.015625 -5.90625q-0.59375 0 -1.03125 0.265625q-0.421875 0.265625 -0.796875 0.75l0 3.265625q0.328125 0.4375 0.71875 0.625q0.390625 0.171875 0.859375 0.171875q0.953125 0 1.453125 -0.671875q0.515625 -0.671875 0.515625 -1.921875q0 -0.65625 -0.125 -1.125q-0.109375 -0.484375 -0.328125 -0.78125q-0.21875 -0.296875 -0.546875 -0.4375q-0.3125 -0.140625 -0.71875 -0.140625zm5.7160034 -0.84375l0 6.75l-1.1875 0l0 -6.75l1.1875 0zm0.265625 -2.125q0 0.171875 -0.078125 0.328125q-0.0625 0.15625 -0.1875 0.28125q-0.109375 0.109375 -0.265625 0.171875q-0.15625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.265625 -0.171875q-0.109375 -0.125 -0.1875 -0.28125q-0.0625 -0.15625 -0.0625 -0.328125q0 -0.171875 0.0625 -0.328125q0.078125 -0.15625 0.1875 -0.265625q0.125 -0.125 0.265625 -0.1875q0.15625 -0.0625 0.328125 -0.0625q0.171875 0 0.328125 0.0625q0.15625 0.0625 0.265625 0.1875q0.125 0.109375 0.1875 0.265625q0.078125 0.15625 0.078125 0.328125zm1.8182373 8.875l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.734375q0.4375 -0.484375 0.984375 -0.78125q0.546875 -0.3125 1.25 -0.3125q0.5625 0 0.984375 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0625 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0zm12.160461 0q-0.25 0 -0.3125 -0.25l-0.109375 -0.8125q-0.4375 0.515625 -1.0 0.84375q-0.546875 0.3125 -1.265625 0.3125q-0.578125 0 -1.0625 -0.21875q-0.46875 -0.234375 -0.796875 -0.65625q-0.328125 -0.4375 -0.515625 -1.078125q-0.171875 -0.65625 -0.171875 -1.5q0 -0.734375 0.1875 -1.375q0.203125 -0.65625 0.578125 -1.125q0.375 -0.46875 0.921875 -0.734375q0.546875 -0.28125 1.234375 -0.28125q0.609375 0 1.046875 0.21875q0.4375 0.203125 0.796875 0.578125l0 -3.734375l1.1875 0l0 9.8125l-0.71875 0zm-2.296875 -0.859375q0.578125 0 1.015625 -0.265625q0.4375 -0.28125 0.8125 -0.765625l0 -3.265625q-0.328125 -0.4375 -0.71875 -0.609375q-0.390625 -0.171875 -0.859375 -0.171875q-0.953125 0 -1.46875 0.671875q-0.5 0.671875 -0.5 1.90625q0 0.671875 0.109375 1.140625q0.125 0.46875 0.34375 0.78125q0.21875 0.296875 0.53125 0.4375q0.328125 0.140625 0.734375 0.140625zm6.3253784 -5.890625l0 6.75l-1.1875 0l0 -6.75l1.1875 0zm0.265625 -2.125q0 0.171875 -0.078125 0.328125q-0.0625 0.15625 -0.1875 0.28125q-0.109375 0.109375 -0.265625 0.171875q-0.15625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.265625 -0.171875q-0.109375 -0.125 -0.1875 -0.28125q-0.0625 -0.15625 -0.0625 -0.328125q0 -0.171875 0.0625 -0.328125q0.078125 -0.15625 0.1875 -0.265625q0.125 -0.125 0.265625 -0.1875q0.15625 -0.0625 0.328125 -0.0625q0.171875 0 0.328125 0.0625q0.15625 0.0625 0.265625 0.1875q0.125 0.109375 0.1875 0.265625q0.078125 0.15625 0.078125 0.328125zm1.8182373 8.875l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.734375q0.4375 -0.484375 0.984375 -0.78125q0.546875 -0.3125 1.25 -0.3125q0.5625 0 0.984375 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0625 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0zm9.69165 -6.859375q0.4375 0 0.8125 0.09375q0.390625 0.09375 0.703125 0.28125l1.828125 0l0 0.4375q0 0.21875 -0.28125 0.28125l-0.765625 0.109375q0.234375 0.4375 0.234375 0.96875q0 0.484375 -0.203125 0.890625q-0.1875 0.40625 -0.53125 0.703125q-0.328125 0.28125 -0.796875 0.4375q-0.453125 0.140625 -1.0 0.140625q-0.484375 0 -0.890625 -0.109375q-0.21875 0.125 -0.328125 0.28125q-0.109375 0.15625 -0.109375 0.296875q0 0.25 0.1875 0.375q0.203125 0.125 0.515625 0.171875q0.328125 0.046875 0.734375 0.0625q0.40625 0.015625 0.828125 0.046875q0.421875 0.03125 0.828125 0.109375q0.40625 0.0625 0.71875 0.234375q0.328125 0.171875 0.515625 0.46875q0.1875 0.28125 0.1875 0.75q0 0.4375 -0.21875 0.84375q-0.203125 0.40625 -0.609375 0.71875q-0.40625 0.3125 -1.0 0.5q-0.578125 0.203125 -1.328125 0.203125q-0.734375 0 -1.296875 -0.15625q-0.546875 -0.140625 -0.921875 -0.390625q-0.359375 -0.25 -0.546875 -0.578125q-0.1875 -0.3125 -0.1875 -0.671875q0 -0.5 0.3125 -0.84375q0.328125 -0.34375 0.875 -0.5625q-0.28125 -0.125 -0.453125 -0.34375q-0.171875 -0.234375 -0.171875 -0.609375q0 -0.140625 0.046875 -0.296875q0.0625 -0.15625 0.171875 -0.3125q0.109375 -0.15625 0.265625 -0.296875q0.171875 -0.140625 0.375 -0.234375q-0.5 -0.28125 -0.78125 -0.75q-0.28125 -0.46875 -0.28125 -1.078125q0 -0.5 0.1875 -0.890625q0.1875 -0.40625 0.53125 -0.6875q0.34375 -0.296875 0.8125 -0.4375q0.46875 -0.15625 1.03125 -0.15625zm2.09375 7.21875q0 -0.25 -0.140625 -0.390625q-0.125 -0.15625 -0.375 -0.234375q-0.234375 -0.09375 -0.546875 -0.125q-0.3125 -0.046875 -0.671875 -0.0625q-0.34375 -0.015625 -0.703125 -0.03125q-0.359375 -0.03125 -0.6875 -0.078125q-0.375 0.171875 -0.609375 0.4375q-0.234375 0.265625 -0.234375 0.625q0 0.21875 0.109375 0.40625q0.125 0.203125 0.359375 0.34375q0.234375 0.15625 0.59375 0.234375q0.375 0.078125 0.875 0.078125q0.46875 0 0.84375 -0.09375q0.390625 -0.078125 0.65625 -0.234375q0.265625 -0.15625 0.390625 -0.375q0.140625 -0.21875 0.140625 -0.5zm-2.09375 -3.65625q0.359375 0 0.625 -0.09375q0.28125 -0.109375 0.46875 -0.28125q0.1875 -0.1875 0.28125 -0.4375q0.09375 -0.25 0.09375 -0.546875q0 -0.625 -0.375 -0.984375q-0.375 -0.375 -1.09375 -0.375q-0.71875 0 -1.09375 0.375q-0.375 0.359375 -0.375 0.984375q0 0.296875 0.09375 0.546875q0.09375 0.25 0.28125 0.4375q0.1875 0.171875 0.453125 0.28125q0.28125 0.09375 0.640625 0.09375zm8.404419 -2.34375q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m727.72015 104.92913l180.72443 0l0 35.590553l-180.72443 0z" fill-rule="evenodd"/><path fill="#000000" d="m739.1733 125.63538l4.125 0l0 1.09375l-5.421875 0l0 -9.546875l1.296875 0l0 8.453125zm10.444397 -6.96875q-0.0625 0.109375 -0.125 0.15625q-0.0625 0.046875 -0.171875 0.046875q-0.109375 0 -0.265625 -0.109375q-0.140625 -0.109375 -0.375 -0.25q-0.234375 -0.140625 -0.5625 -0.25q-0.3125 -0.109375 -0.78125 -0.109375q-0.421875 0 -0.765625 0.125q-0.328125 0.109375 -0.5625 0.3125q-0.21875 0.1875 -0.328125 0.46875q-0.109375 0.265625 -0.109375 0.578125q0 0.390625 0.1875 0.65625q0.203125 0.265625 0.515625 0.453125q0.328125 0.1875 0.734375 0.328125q0.421875 0.125 0.84375 0.28125q0.4375 0.140625 0.84375 0.328125q0.40625 0.1875 0.734375 0.46875q0.328125 0.265625 0.515625 0.6875q0.203125 0.40625 0.203125 0.984375q0 0.640625 -0.21875 1.1875q-0.203125 0.546875 -0.625 0.953125q-0.40625 0.40625 -1.0 0.640625q-0.59375 0.234375 -1.359375 0.234375q-0.921875 0 -1.6875 -0.328125q-0.765625 -0.34375 -1.296875 -0.921875l0.375 -0.609375q0.046875 -0.078125 0.125 -0.125q0.078125 -0.046875 0.171875 -0.046875q0.140625 0 0.3125 0.15625q0.1875 0.140625 0.453125 0.328125q0.265625 0.171875 0.640625 0.328125q0.390625 0.140625 0.953125 0.140625q0.453125 0 0.8125 -0.125q0.359375 -0.125 0.609375 -0.34375q0.25 -0.234375 0.375 -0.546875q0.140625 -0.328125 0.140625 -0.734375q0 -0.421875 -0.203125 -0.703125q-0.1875 -0.28125 -0.515625 -0.46875q-0.3125 -0.1875 -0.71875 -0.3125q-0.40625 -0.125 -0.84375 -0.265625q-0.421875 -0.140625 -0.84375 -0.3125q-0.40625 -0.1875 -0.734375 -0.46875q-0.3125 -0.28125 -0.515625 -0.703125q-0.1875 -0.4375 -0.1875 -1.078125q0 -0.5 0.1875 -0.96875q0.203125 -0.484375 0.578125 -0.84375q0.375 -0.375 0.921875 -0.59375q0.546875 -0.21875 1.265625 -0.21875q0.796875 0 1.453125 0.25q0.671875 0.25 1.15625 0.734375l-0.3125 0.609375zm3.5950928 4.484375l0 3.578125l-1.28125 0l0 -9.546875l2.8125 0q0.90625 0 1.578125 0.21875q0.671875 0.203125 1.109375 0.59375q0.4375 0.375 0.65625 0.921875q0.21875 0.546875 0.21875 1.21875q0 0.671875 -0.234375 1.234375q-0.234375 0.546875 -0.6875 0.953125q-0.453125 0.390625 -1.125 0.609375q-0.65625 0.21875 -1.515625 0.21875l-1.53125 0zm0 -1.015625l1.53125 0q0.5625 0 0.984375 -0.140625q0.421875 -0.15625 0.703125 -0.421875q0.28125 -0.265625 0.421875 -0.625q0.15625 -0.375 0.15625 -0.8125q0 -0.90625 -0.5625 -1.421875q-0.5625 -0.515625 -1.703125 -0.515625l-1.53125 0l0 3.9375zm12.981384 -1.046875q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm4.581299 -1.21875q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm4.2807617 5.984375l0 -6.75l0.6875 0q0.1875 0 0.265625 0.078125q0.078125 0.0625 0.09375 0.25l0.078125 1.046875q0.359375 -0.703125 0.859375 -1.09375q0.515625 -0.40625 1.203125 -0.40625q0.28125 0 0.5 0.0625q0.234375 0.0625 0.421875 0.1875l-0.15625 0.875q-0.046875 0.171875 -0.203125 0.171875q-0.09375 0 -0.296875 -0.0625q-0.1875 -0.0625 -0.53125 -0.0625q-0.625 0 -1.046875 0.359375q-0.40625 0.359375 -0.6875 1.046875l0 4.296875l-1.1875 0zm4.527466 -6.75l0.96875 0q0.140625 0 0.234375 0.078125q0.09375 0.0625 0.125 0.171875l1.71875 4.34375q0.09375 0.234375 0.140625 0.484375q0.0625 0.234375 0.109375 0.46875q0.046875 -0.234375 0.109375 -0.46875q0.0625 -0.25 0.15625 -0.484375l1.734375 -4.34375q0.03125 -0.109375 0.125 -0.171875q0.09375 -0.078125 0.21875 -0.078125l0.9375 0l-2.765625 6.75l-1.0625 0l-2.75 -6.75zm10.16626 -0.109375q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm4.2808228 5.984375l0 -6.75l0.6875 0q0.1875 0 0.265625 0.078125q0.078125 0.0625 0.09375 0.25l0.078125 1.046875q0.359375 -0.703125 0.859375 -1.09375q0.515625 -0.40625 1.203125 -0.40625q0.28125 0 0.5 0.0625q0.234375 0.0625 0.421875 0.1875l-0.15625 0.875q-0.046875 0.171875 -0.203125 0.171875q-0.09375 0 -0.296875 -0.0625q-0.1875 -0.0625 -0.53125 -0.0625q-0.625 0 -1.046875 0.359375q-0.40625 0.359375 -0.6875 1.046875l0 4.296875l-1.1875 0z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m727.72015 184.92914l180.72443 0l0 35.590546l-180.72443 0z" fill-rule="evenodd"/><path fill="#000000" d="m739.1733 205.63538l4.125 0l0 1.09375l-5.421875 0l0 -9.546875l1.296875 0l0 8.453125zm10.335022 1.09375l-0.53125 0q-0.171875 0 -0.28125 -0.046875q-0.109375 -0.0625 -0.140625 -0.234375l-0.140625 -0.625q-0.265625 0.234375 -0.515625 0.4375q-0.25 0.1875 -0.53125 0.3125q-0.28125 0.125 -0.59375 0.1875q-0.3125 0.078125 -0.703125 0.078125q-0.390625 0 -0.734375 -0.109375q-0.34375 -0.109375 -0.609375 -0.328125q-0.25 -0.21875 -0.40625 -0.546875q-0.140625 -0.34375 -0.140625 -0.8125q0 -0.390625 0.21875 -0.765625q0.21875 -0.375 0.703125 -0.65625q0.5 -0.296875 1.296875 -0.46875q0.796875 -0.1875 1.9375 -0.21875l0 -0.515625q0 -0.796875 -0.34375 -1.1875q-0.328125 -0.40625 -0.984375 -0.40625q-0.4375 0 -0.734375 0.109375q-0.296875 0.109375 -0.515625 0.25q-0.21875 0.125 -0.375 0.234375q-0.15625 0.109375 -0.3125 0.109375q-0.109375 0 -0.203125 -0.0625q-0.09375 -0.0625 -0.140625 -0.15625l-0.21875 -0.375q0.5625 -0.546875 1.203125 -0.8125q0.65625 -0.265625 1.4375 -0.265625q0.5625 0 1.0 0.1875q0.453125 0.1875 0.75 0.53125q0.296875 0.328125 0.453125 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.3125zm-3.078125 -0.71875q0.3125 0 0.5625 -0.0625q0.265625 -0.078125 0.484375 -0.1875q0.234375 -0.125 0.4375 -0.28125q0.21875 -0.171875 0.421875 -0.375l0 -1.40625q-0.828125 0.015625 -1.40625 0.125q-0.5625 0.09375 -0.921875 0.265625q-0.359375 0.171875 -0.53125 0.40625q-0.15625 0.21875 -0.15625 0.5q0 0.265625 0.078125 0.453125q0.09375 0.1875 0.234375 0.3125q0.15625 0.125 0.359375 0.1875q0.203125 0.0625 0.4375 0.0625zm4.866699 0.71875l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.734375q0.4375 -0.484375 0.984375 -0.78125q0.546875 -0.3125 1.25 -0.3125q0.5625 0 0.984375 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0625 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0zm9.69165 -6.859375q0.4375 0 0.8125 0.09375q0.390625 0.09375 0.703125 0.28125l1.828125 0l0 0.4375q0 0.21875 -0.28125 0.28125l-0.765625 0.109375q0.234375 0.4375 0.234375 0.96875q0 0.484375 -0.203125 0.890625q-0.1875 0.40625 -0.53125 0.703125q-0.328125 0.28125 -0.796875 0.4375q-0.453125 0.140625 -1.0 0.140625q-0.484375 0 -0.890625 -0.109375q-0.21875 0.125 -0.328125 0.28125q-0.109375 0.15625 -0.109375 0.296875q0 0.25 0.1875 0.375q0.203125 0.125 0.515625 0.171875q0.328125 0.046875 0.734375 0.0625q0.40625 0.015625 0.828125 0.046875q0.421875 0.03125 0.828125 0.109375q0.40625 0.0625 0.71875 0.234375q0.328125 0.171875 0.515625 0.46875q0.1875 0.28125 0.1875 0.75q0 0.4375 -0.21875 0.84375q-0.203125 0.40625 -0.609375 0.71875q-0.40625 0.3125 -1.0 0.5q-0.578125 0.203125 -1.328125 0.203125q-0.734375 0 -1.296875 -0.15625q-0.546875 -0.140625 -0.921875 -0.390625q-0.359375 -0.25 -0.546875 -0.578125q-0.1875 -0.3125 -0.1875 -0.671875q0 -0.5 0.3125 -0.84375q0.328125 -0.34375 0.875 -0.5625q-0.28125 -0.125 -0.453125 -0.34375q-0.171875 -0.234375 -0.171875 -0.609375q0 -0.140625 0.046875 -0.296875q0.0625 -0.15625 0.171875 -0.3125q0.109375 -0.15625 0.265625 -0.296875q0.171875 -0.140625 0.375 -0.234375q-0.5 -0.28125 -0.78125 -0.75q-0.28125 -0.46875 -0.28125 -1.078125q0 -0.5 0.1875 -0.890625q0.1875 -0.40625 0.53125 -0.6875q0.34375 -0.296875 0.8125 -0.4375q0.46875 -0.15625 1.03125 -0.15625zm2.09375 7.21875q0 -0.25 -0.140625 -0.390625q-0.125 -0.15625 -0.375 -0.234375q-0.234375 -0.09375 -0.546875 -0.125q-0.3125 -0.046875 -0.671875 -0.0625q-0.34375 -0.015625 -0.703125 -0.03125q-0.359375 -0.03125 -0.6875 -0.078125q-0.375 0.171875 -0.609375 0.4375q-0.234375 0.265625 -0.234375 0.625q0 0.21875 0.109375 0.40625q0.125 0.203125 0.359375 0.34375q0.234375 0.15625 0.59375 0.234375q0.375 0.078125 0.875 0.078125q0.46875 0 0.84375 -0.09375q0.390625 -0.078125 0.65625 -0.234375q0.265625 -0.15625 0.390625 -0.375q0.140625 -0.21875 0.140625 -0.5zm-2.09375 -3.65625q0.359375 0 0.625 -0.09375q0.28125 -0.109375 0.46875 -0.28125q0.1875 -0.1875 0.28125 -0.4375q0.09375 -0.25 0.09375 -0.546875q0 -0.625 -0.375 -0.984375q-0.375 -0.375 -1.09375 -0.375q-0.71875 0 -1.09375 0.375q-0.375 0.359375 -0.375 0.984375q0 0.296875 0.09375 0.546875q0.09375 0.25 0.28125 0.4375q0.1875 0.171875 0.453125 0.28125q0.28125 0.09375 0.640625 0.09375zm5.560669 -3.453125l0 4.296875q0 0.78125 0.34375 1.203125q0.359375 0.40625 1.078125 0.40625q0.515625 0 0.96875 -0.234375q0.46875 -0.25 0.859375 -0.6875l0 -4.984375l1.1875 0l0 6.75l-0.71875 0q-0.25 0 -0.3125 -0.25l-0.09375 -0.71875q-0.4375 0.484375 -0.984375 0.78125q-0.546875 0.296875 -1.25 0.296875q-0.5625 0 -0.984375 -0.1875q-0.421875 -0.1875 -0.71875 -0.515625q-0.28125 -0.328125 -0.421875 -0.796875q-0.140625 -0.484375 -0.140625 -1.0625l0 -4.296875l1.1875 0zm11.3479 6.75l-0.53125 0q-0.171875 0 -0.28125 -0.046875q-0.109375 -0.0625 -0.140625 -0.234375l-0.140625 -0.625q-0.265625 0.234375 -0.515625 0.4375q-0.25 0.1875 -0.53125 0.3125q-0.28125 0.125 -0.59375 0.1875q-0.3125 0.078125 -0.703125 0.078125q-0.390625 0 -0.734375 -0.109375q-0.34375 -0.109375 -0.609375 -0.328125q-0.25 -0.21875 -0.40625 -0.546875q-0.140625 -0.34375 -0.140625 -0.8125q0 -0.390625 0.21875 -0.765625q0.21875 -0.375 0.703125 -0.65625q0.5 -0.296875 1.296875 -0.46875q0.796875 -0.1875 1.9375 -0.21875l0 -0.515625q0 -0.796875 -0.34375 -1.1875q-0.328125 -0.40625 -0.984375 -0.40625q-0.4375 0 -0.734375 0.109375q-0.296875 0.109375 -0.515625 0.25q-0.21875 0.125 -0.375 0.234375q-0.15625 0.109375 -0.3125 0.109375q-0.109375 0 -0.203125 -0.0625q-0.09375 -0.0625 -0.140625 -0.15625l-0.21875 -0.375q0.5625 -0.546875 1.203125 -0.8125q0.65625 -0.265625 1.4375 -0.265625q0.5625 0 1.0 0.1875q0.453125 0.1875 0.75 0.53125q0.296875 0.328125 0.453125 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.3125zm-3.078125 -0.71875q0.3125 0 0.5625 -0.0625q0.265625 -0.078125 0.484375 -0.1875q0.234375 -0.125 0.4375 -0.28125q0.21875 -0.171875 0.421875 -0.375l0 -1.40625q-0.828125 0.015625 -1.40625 0.125q-0.5625 0.09375 -0.921875 0.265625q-0.359375 0.171875 -0.53125 0.40625q-0.15625 0.21875 -0.15625 0.5q0 0.265625 0.078125 0.453125q0.09375 0.1875 0.234375 0.3125q0.15625 0.125 0.359375 0.1875q0.203125 0.0625 0.4375 0.0625zm7.1480103 -6.140625q0.4375 0 0.8125 0.09375q0.390625 0.09375 0.703125 0.28125l1.828125 0l0 0.4375q0 0.21875 -0.28125 0.28125l-0.765625 0.109375q0.234375 0.4375 0.234375 0.96875q0 0.484375 -0.203125 0.890625q-0.1875 0.40625 -0.53125 0.703125q-0.328125 0.28125 -0.796875 0.4375q-0.453125 0.140625 -1.0 0.140625q-0.484375 0 -0.890625 -0.109375q-0.21875 0.125 -0.328125 0.28125q-0.109375 0.15625 -0.109375 0.296875q0 0.25 0.1875 0.375q0.203125 0.125 0.515625 0.171875q0.328125 0.046875 0.734375 0.0625q0.40625 0.015625 0.828125 0.046875q0.421875 0.03125 0.828125 0.109375q0.40625 0.0625 0.71875 0.234375q0.328125 0.171875 0.515625 0.46875q0.1875 0.28125 0.1875 0.75q0 0.4375 -0.21875 0.84375q-0.203125 0.40625 -0.609375 0.71875q-0.40625 0.3125 -1.0 0.5q-0.578125 0.203125 -1.328125 0.203125q-0.734375 0 -1.296875 -0.15625q-0.546875 -0.140625 -0.921875 -0.390625q-0.359375 -0.25 -0.546875 -0.578125q-0.1875 -0.3125 -0.1875 -0.671875q0 -0.5 0.3125 -0.84375q0.328125 -0.34375 0.875 -0.5625q-0.28125 -0.125 -0.453125 -0.34375q-0.171875 -0.234375 -0.171875 -0.609375q0 -0.140625 0.046875 -0.296875q0.0625 -0.15625 0.171875 -0.3125q0.109375 -0.15625 0.265625 -0.296875q0.171875 -0.140625 0.375 -0.234375q-0.5 -0.28125 -0.78125 -0.75q-0.28125 -0.46875 -0.28125 -1.078125q0 -0.5 0.1875 -0.890625q0.1875 -0.40625 0.53125 -0.6875q0.34375 -0.296875 0.8125 -0.4375q0.46875 -0.15625 1.03125 -0.15625zm2.09375 7.21875q0 -0.25 -0.140625 -0.390625q-0.125 -0.15625 -0.375 -0.234375q-0.234375 -0.09375 -0.546875 -0.125q-0.3125 -0.046875 -0.671875 -0.0625q-0.34375 -0.015625 -0.703125 -0.03125q-0.359375 -0.03125 -0.6875 -0.078125q-0.375 0.171875 -0.609375 0.4375q-0.234375 0.265625 -0.234375 0.625q0 0.21875 0.109375 0.40625q0.125 0.203125 0.359375 0.34375q0.234375 0.15625 0.59375 0.234375q0.375 0.078125 0.875 0.078125q0.46875 0 0.84375 -0.09375q0.390625 -0.078125 0.65625 -0.234375q0.265625 -0.15625 0.390625 -0.375q0.140625 -0.21875 0.140625 -0.5zm-2.09375 -3.65625q0.359375 0 0.625 -0.09375q0.28125 -0.109375 0.46875 -0.28125q0.1875 -0.1875 0.28125 -0.4375q0.09375 -0.25 0.09375 -0.546875q0 -0.625 -0.375 -0.984375q-0.375 -0.375 -1.09375 -0.375q-0.71875 0 -1.09375 0.375q-0.375 0.359375 -0.375 0.984375q0 0.296875 0.09375 0.546875q0.09375 0.25 0.28125 0.4375q0.1875 0.171875 0.453125 0.28125q0.28125 0.09375 0.640625 0.09375zm7.201233 -3.5625q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm7.1187744 5.984375l0 -5.734375l-0.734375 -0.09375q-0.140625 -0.03125 -0.234375 -0.09375q-0.09375 -0.078125 -0.09375 -0.203125l0 -0.5l1.0625 0l0 -0.640625q0 -0.578125 0.15625 -1.03125q0.171875 -0.453125 0.46875 -0.765625q0.3125 -0.3125 0.734375 -0.46875q0.4375 -0.15625 0.96875 -0.15625q0.453125 0 0.828125 0.125l-0.015625 0.59375q-0.015625 0.140625 -0.125 0.171875q-0.09375 0.015625 -0.296875 0.015625l-0.203125 0q-0.3125 0 -0.5625 0.09375q-0.234375 0.078125 -0.421875 0.265625q-0.1875 0.171875 -0.28125 0.46875q-0.09375 0.28125 -0.09375 0.71875l0 0.609375l1.953125 0l0 0.875l-1.90625 0l0 5.75l-1.203125 0zm6.897766 -6.859375q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm9.249573 5.984375l-0.53125 0q-0.171875 0 -0.28125 -0.046875q-0.109375 -0.0625 -0.140625 -0.234375l-0.140625 -0.625q-0.265625 0.234375 -0.515625 0.4375q-0.25 0.1875 -0.53125 0.3125q-0.28125 0.125 -0.59375 0.1875q-0.3125 0.078125 -0.703125 0.078125q-0.390625 0 -0.734375 -0.109375q-0.34375 -0.109375 -0.609375 -0.328125q-0.25 -0.21875 -0.40625 -0.546875q-0.140625 -0.34375 -0.140625 -0.8125q0 -0.390625 0.21875 -0.765625q0.21875 -0.375 0.703125 -0.65625q0.5 -0.296875 1.296875 -0.46875q0.796875 -0.1875 1.9375 -0.21875l0 -0.515625q0 -0.796875 -0.34375 -1.1875q-0.328125 -0.40625 -0.984375 -0.40625q-0.4375 0 -0.734375 0.109375q-0.296875 0.109375 -0.515625 0.25q-0.21875 0.125 -0.375 0.234375q-0.15625 0.109375 -0.3125 0.109375q-0.109375 0 -0.203125 -0.0625q-0.09375 -0.0625 -0.140625 -0.15625l-0.21875 -0.375q0.5625 -0.546875 1.203125 -0.8125q0.65625 -0.265625 1.4375 -0.265625q0.5625 0 1.0 0.1875q0.453125 0.1875 0.75 0.53125q0.296875 0.328125 0.453125 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.3125zm-3.078125 -0.71875q0.3125 0 0.5625 -0.0625q0.265625 -0.078125 0.484375 -0.1875q0.234375 -0.125 0.4375 -0.28125q0.21875 -0.171875 0.421875 -0.375l0 -1.40625q-0.828125 0.015625 -1.40625 0.125q-0.5625 0.09375 -0.921875 0.265625q-0.359375 0.171875 -0.53125 0.40625q-0.15625 0.21875 -0.15625 0.5q0 0.265625 0.078125 0.453125q0.09375 0.1875 0.234375 0.3125q0.15625 0.125 0.359375 0.1875q0.203125 0.0625 0.4375 0.0625zm6.913574 0.828125q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm3.9557495 -6.859375l0 4.296875q0 0.78125 0.34375 1.203125q0.359375 0.40625 1.078125 0.40625q0.515625 0 0.96875 -0.234375q0.46875 -0.25 0.859375 -0.6875l0 -4.984375l1.1875 0l0 6.75l-0.71875 0q-0.25 0 -0.3125 -0.25l-0.09375 -0.71875q-0.4375 0.484375 -0.984375 0.78125q-0.546875 0.296875 -1.25 0.296875q-0.5625 0 -0.984375 -0.1875q-0.421875 -0.1875 -0.71875 -0.515625q-0.28125 -0.328125 -0.421875 -0.796875q-0.140625 -0.484375 -0.140625 -1.0625l0 -4.296875l1.1875 0zm6.3791504 6.75l0 -6.75l0.6875 0q0.1875 0 0.265625 0.078125q0.078125 0.0625 0.09375 0.25l0.078125 1.046875q0.359375 -0.703125 0.859375 -1.09375q0.515625 -0.40625 1.203125 -0.40625q0.28125 0 0.5 0.0625q0.234375 0.0625 0.421875 0.1875l-0.15625 0.875q-0.046875 0.171875 -0.203125 0.171875q-0.09375 0 -0.296875 -0.0625q-0.1875 -0.0625 -0.53125 -0.0625q-0.625 0 -1.046875 0.359375q-0.40625 0.359375 -0.6875 1.046875l0 4.296875l-1.1875 0zm8.043091 -6.859375q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm8.155823 0.34375q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m727.71906 256.92914l195.71655 0l0 35.590546l-195.71655 0z" fill-rule="evenodd"/><path fill="#000000" d="m742.7659 270.66663q-0.0625 0.109375 -0.125 0.15625q-0.0625 0.046875 -0.171875 0.046875q-0.109375 0 -0.265625 -0.109375q-0.140625 -0.109375 -0.375 -0.25q-0.234375 -0.140625 -0.5625 -0.25q-0.3125 -0.109375 -0.78125 -0.109375q-0.421875 0 -0.765625 0.125q-0.328125 0.109375 -0.5625 0.3125q-0.21875 0.1875 -0.328125 0.46875q-0.109375 0.265625 -0.109375 0.578125q0 0.390625 0.1875 0.65625q0.203125 0.265625 0.515625 0.453125q0.328125 0.1875 0.734375 0.328125q0.421875 0.125 0.84375 0.28125q0.4375 0.140625 0.84375 0.328125q0.40625 0.1875 0.734375 0.46875q0.328125 0.265625 0.515625 0.6875q0.203125 0.40625 0.203125 0.984375q0 0.640625 -0.21875 1.1875q-0.203125 0.546875 -0.625 0.953125q-0.40625 0.40625 -1.0 0.640625q-0.59375 0.234375 -1.359375 0.234375q-0.921875 0 -1.6875 -0.328125q-0.765625 -0.34375 -1.296875 -0.921875l0.375 -0.609375q0.046875 -0.078125 0.125 -0.125q0.078125 -0.046875 0.171875 -0.046875q0.140625 0 0.3125 0.15625q0.1875 0.140625 0.453125 0.328125q0.265625 0.171875 0.640625 0.328125q0.390625 0.140625 0.953125 0.140625q0.453125 0 0.8125 -0.125q0.359375 -0.125 0.609375 -0.34375q0.25 -0.234375 0.375 -0.546875q0.140625 -0.328125 0.140625 -0.734375q0 -0.421875 -0.203125 -0.703125q-0.1875 -0.28125 -0.515625 -0.46875q-0.3125 -0.1875 -0.71875 -0.3125q-0.40625 -0.125 -0.84375 -0.265625q-0.421875 -0.140625 -0.84375 -0.3125q-0.40625 -0.1875 -0.734375 -0.46875q-0.3125 -0.28125 -0.515625 -0.703125q-0.1875 -0.4375 -0.1875 -1.078125q0 -0.5 0.1875 -0.96875q0.203125 -0.484375 0.578125 -0.84375q0.375 -0.375 0.921875 -0.59375q0.546875 -0.21875 1.265625 -0.21875q0.796875 0 1.453125 0.25q0.671875 0.25 1.15625 0.734375l-0.3125 0.609375zm1.9857788 8.0625l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.734375q0.4375 -0.484375 0.984375 -0.78125q0.546875 -0.3125 1.25 -0.3125q0.5625 0 0.984375 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0625 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0zm12.37915 0l-0.53125 0q-0.171875 0 -0.28125 -0.046875q-0.109375 -0.0625 -0.140625 -0.234375l-0.140625 -0.625q-0.265625 0.234375 -0.515625 0.4375q-0.25 0.1875 -0.53125 0.3125q-0.28125 0.125 -0.59375 0.1875q-0.3125 0.078125 -0.703125 0.078125q-0.390625 0 -0.734375 -0.109375q-0.34375 -0.109375 -0.609375 -0.328125q-0.25 -0.21875 -0.40625 -0.546875q-0.140625 -0.34375 -0.140625 -0.8125q0 -0.390625 0.21875 -0.765625q0.21875 -0.375 0.703125 -0.65625q0.5 -0.296875 1.296875 -0.46875q0.796875 -0.1875 1.9375 -0.21875l0 -0.515625q0 -0.796875 -0.34375 -1.1875q-0.328125 -0.40625 -0.984375 -0.40625q-0.4375 0 -0.734375 0.109375q-0.296875 0.109375 -0.515625 0.25q-0.21875 0.125 -0.375 0.234375q-0.15625 0.109375 -0.3125 0.109375q-0.109375 0 -0.203125 -0.0625q-0.09375 -0.0625 -0.140625 -0.15625l-0.21875 -0.375q0.5625 -0.546875 1.203125 -0.8125q0.65625 -0.265625 1.4375 -0.265625q0.5625 0 1.0 0.1875q0.453125 0.1875 0.75 0.53125q0.296875 0.328125 0.453125 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.3125zm-3.078125 -0.71875q0.3125 0 0.5625 -0.0625q0.265625 -0.078125 0.484375 -0.1875q0.234375 -0.125 0.4375 -0.28125q0.21875 -0.171875 0.421875 -0.375l0 -1.40625q-0.828125 0.015625 -1.40625 0.125q-0.5625 0.09375 -0.921875 0.265625q-0.359375 0.171875 -0.53125 0.40625q-0.15625 0.21875 -0.15625 0.5q0 0.265625 0.078125 0.453125q0.09375 0.1875 0.234375 0.3125q0.15625 0.125 0.359375 0.1875q0.203125 0.0625 0.4375 0.0625zm4.866699 3.0l0 -9.03125l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.796875q0.4375 -0.53125 0.984375 -0.84375q0.5625 -0.328125 1.296875 -0.328125q0.578125 0 1.046875 0.234375q0.46875 0.21875 0.796875 0.65625q0.34375 0.4375 0.515625 1.078125q0.1875 0.640625 0.1875 1.484375q0 0.75 -0.203125 1.390625q-0.1875 0.640625 -0.5625 1.109375q-0.375 0.46875 -0.921875 0.75q-0.546875 0.265625 -1.21875 0.265625q-0.625 0 -1.078125 -0.203125q-0.4375 -0.203125 -0.78125 -0.59375l0 2.984375l-1.1875 0zm3.015625 -8.1875q-0.578125 0 -1.015625 0.265625q-0.4375 0.265625 -0.8125 0.75l0 3.265625q0.328125 0.4375 0.71875 0.625q0.390625 0.171875 0.875 0.171875q0.9375 0 1.4375 -0.671875q0.515625 -0.671875 0.515625 -1.921875q0 -0.65625 -0.125 -1.125q-0.109375 -0.484375 -0.328125 -0.78125q-0.21875 -0.296875 -0.546875 -0.4375q-0.3125 -0.140625 -0.71875 -0.140625zm8.216492 0.265625q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm1.9093628 5.640625l0 -9.8125l1.1875 0l0 3.96875q0.4375 -0.453125 0.953125 -0.734375q0.53125 -0.28125 1.21875 -0.28125q0.5625 0 0.984375 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0625 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0zm10.144775 -6.859375q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm6.7229614 0.9375q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm2.5807495 -0.921875q0 -0.15625 0.046875 -0.296875q0.0625 -0.140625 0.171875 -0.234375q0.109375 -0.109375 0.25 -0.171875q0.140625 -0.0625 0.3125 -0.0625q0.203125 0 0.359375 0.078125q0.15625 0.078125 0.25 0.203125q0.109375 0.125 0.15625 0.296875q0.0625 0.171875 0.0625 0.375q0 0.296875 -0.09375 0.625q-0.078125 0.3125 -0.234375 0.625q-0.15625 0.328125 -0.40625 0.625q-0.234375 0.296875 -0.53125 0.5625l-0.203125 -0.203125q-0.078125 -0.078125 -0.078125 -0.1875q0 -0.078125 0.09375 -0.171875q0.0625 -0.078125 0.15625 -0.203125q0.109375 -0.125 0.21875 -0.28125q0.109375 -0.15625 0.203125 -0.359375q0.09375 -0.1875 0.125 -0.40625l-0.078125 0q-0.1875 0 -0.328125 -0.0625q-0.125 -0.0625 -0.234375 -0.171875q-0.109375 -0.109375 -0.171875 -0.25q-0.046875 -0.15625 -0.046875 -0.328125zm4.897827 -5.9375l0.96875 0q0.140625 0 0.234375 0.078125q0.09375 0.0625 0.125 0.171875l1.71875 4.34375q0.09375 0.234375 0.140625 0.484375q0.0625 0.234375 0.109375 0.46875q0.046875 -0.234375 0.109375 -0.46875q0.0625 -0.25 0.15625 -0.484375l1.734375 -4.34375q0.03125 -0.109375 0.125 -0.171875q0.09375 -0.078125 0.21875 -0.078125l0.9375 0l-2.765625 6.75l-1.0625 0l-2.75 -6.75zm8.99585 0l0 6.75l-1.1875 0l0 -6.75l1.1875 0zm0.265625 -2.125q0 0.171875 -0.078125 0.328125q-0.0625 0.15625 -0.1875 0.28125q-0.109375 0.109375 -0.265625 0.171875q-0.15625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.265625 -0.171875q-0.109375 -0.125 -0.1875 -0.28125q-0.0625 -0.15625 -0.0625 -0.328125q0 -0.171875 0.0625 -0.328125q0.078125 -0.15625 0.1875 -0.265625q0.125 -0.125 0.265625 -0.1875q0.15625 -0.0625 0.328125 -0.0625q0.171875 0 0.328125 0.0625q0.15625 0.0625 0.265625 0.1875q0.125 0.109375 0.1875 0.265625q0.078125 0.15625 0.078125 0.328125zm4.4901123 2.015625q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm3.4058228 -0.765625l0.9375 0q0.140625 0 0.234375 0.078125q0.09375 0.0625 0.125 0.171875l1.296875 4.34375q0.046875 0.234375 0.09375 0.46875q0.046875 0.21875 0.078125 0.4375q0.0625 -0.21875 0.125 -0.4375q0.0625 -0.234375 0.140625 -0.46875l1.421875 -4.375q0.03125 -0.09375 0.109375 -0.15625q0.09375 -0.078125 0.21875 -0.078125l0.515625 0q0.140625 0 0.21875 0.078125q0.09375 0.0625 0.125 0.15625l1.390625 4.375q0.078125 0.234375 0.125 0.46875q0.0625 0.21875 0.109375 0.4375q0.03125 -0.21875 0.078125 -0.453125q0.0625 -0.25 0.125 -0.453125l1.328125 -4.34375q0.03125 -0.109375 0.125 -0.171875q0.09375 -0.078125 0.21875 -0.078125l0.890625 0l-2.1875 6.75l-0.9375 0q-0.171875 0 -0.25 -0.234375l-1.484375 -4.578125q-0.046875 -0.140625 -0.09375 -0.296875q-0.03125 -0.15625 -0.0625 -0.3125q-0.03125 0.15625 -0.0625 0.3125q-0.03125 0.15625 -0.09375 0.3125l-1.515625 4.5625q-0.0625 0.234375 -0.265625 0.234375l-0.890625 0l-2.1875 -6.75zm10.327209 5.9375q0 -0.15625 0.046875 -0.296875q0.0625 -0.140625 0.171875 -0.234375q0.109375 -0.109375 0.25 -0.171875q0.140625 -0.0625 0.3125 -0.0625q0.203125 0 0.359375 0.078125q0.15625 0.078125 0.25 0.203125q0.109375 0.125 0.15625 0.296875q0.0625 0.171875 0.0625 0.375q0 0.296875 -0.09375 0.625q-0.078125 0.3125 -0.234375 0.625q-0.15625 0.328125 -0.40625 0.625q-0.234375 0.296875 -0.53125 0.5625l-0.203125 -0.203125q-0.078125 -0.078125 -0.078125 -0.1875q0 -0.078125 0.09375 -0.171875q0.0625 -0.078125 0.15625 -0.203125q0.109375 -0.125 0.21875 -0.28125q0.109375 -0.15625 0.203125 -0.359375q0.09375 -0.1875 0.125 -0.40625l-0.078125 0q-0.1875 0 -0.328125 -0.0625q-0.125 -0.0625 -0.234375 -0.171875q-0.109375 -0.109375 -0.171875 -0.25q-0.046875 -0.15625 -0.046875 -0.328125zm9.616577 -4.828125q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm4.581299 -1.21875q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm8.155762 0.34375q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm5.784363 0q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm3.2375488 -1.109375l0 6.75l-1.1875 0l0 -6.75l1.1875 0zm0.265625 -2.125q0 0.171875 -0.078125 0.328125q-0.0625 0.15625 -0.1875 0.28125q-0.109375 0.109375 -0.265625 0.171875q-0.15625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.265625 -0.171875q-0.109375 -0.125 -0.1875 -0.28125q-0.0625 -0.15625 -0.0625 -0.328125q0 -0.171875 0.0625 -0.328125q0.078125 -0.15625 0.1875 -0.265625q0.125 -0.125 0.265625 -0.1875q0.15625 -0.0625 0.328125 -0.0625q0.171875 0 0.328125 0.0625q0.15625 0.0625 0.265625 0.1875q0.125 0.109375 0.1875 0.265625q0.078125 0.15625 0.078125 0.328125zm4.5526123 2.015625q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm4.6760254 0.828125l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.734375q0.4375 -0.484375 0.984375 -0.78125q0.546875 -0.3125 1.25 -0.3125q0.5625 0 0.984375 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0625 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0zm7.0666504 -0.8125q0 -0.15625 0.046875 -0.296875q0.0625 -0.140625 0.171875 -0.234375q0.109375 -0.109375 0.25 -0.171875q0.140625 -0.0625 0.3125 -0.0625q0.203125 0 0.359375 0.078125q0.15625 0.078125 0.25 0.203125q0.109375 0.125 0.15625 0.296875q0.0625 0.171875 0.0625 0.375q0 0.296875 -0.09375 0.625q-0.078125 0.3125 -0.234375 0.625q-0.15625 0.328125 -0.40625 0.625q-0.234375 0.296875 -0.53125 0.5625l-0.203125 -0.203125q-0.078125 -0.078125 -0.078125 -0.1875q0 -0.078125 0.09375 -0.171875q0.0625 -0.078125 0.15625 -0.203125q0.109375 -0.125 0.21875 -0.28125q0.109375 -0.15625 0.203125 -0.359375q0.09375 -0.1875 0.125 -0.40625l-0.078125 0q-0.1875 0 -0.328125 -0.0625q-0.125 -0.0625 -0.234375 -0.171875q-0.109375 -0.109375 -0.171875 -0.25q-0.046875 -0.15625 -0.046875 -0.328125z" fill-rule="nonzero"/><path fill="#000000" d="m736.8128 287.97913l0.9375 0q0.140625 0 0.234375 0.078125q0.09375 0.0625 0.125 0.171875l1.296875 4.34375q0.046875 0.234375 0.09375 0.46875q0.046875 0.21875 0.078125 0.4375q0.0625 -0.21875 0.125 -0.4375q0.0625 -0.234375 0.140625 -0.46875l1.421875 -4.375q0.03125 -0.09375 0.109375 -0.15625q0.09375 -0.078125 0.21875 -0.078125l0.515625 0q0.140625 0 0.21875 0.078125q0.09375 0.0625 0.125 0.15625l1.390625 4.375q0.078125 0.234375 0.125 0.46875q0.0625 0.21875 0.109375 0.4375q0.03125 -0.21875 0.078125 -0.453125q0.0625 -0.25 0.125 -0.453125l1.328125 -4.34375q0.03125 -0.109375 0.125 -0.171875q0.09375 -0.078125 0.21875 -0.078125l0.890625 0l-2.1875 6.75l-0.9375 0q-0.171875 0 -0.25 -0.234375l-1.484375 -4.578125q-0.046875 -0.140625 -0.09375 -0.296875q-0.03125 -0.15625 -0.0625 -0.3125q-0.03125 0.15625 -0.0625 0.3125q-0.03125 0.15625 -0.09375 0.3125l-1.515625 4.5625q-0.0625 0.234375 -0.265625 0.234375l-0.890625 0l-2.1875 -6.75zm13.818665 -0.109375q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm4.6760864 0.828125l0 -6.75l0.6875 0q0.1875 0 0.265625 0.078125q0.078125 0.0625 0.09375 0.25l0.078125 1.046875q0.359375 -0.703125 0.859375 -1.09375q0.515625 -0.40625 1.203125 -0.40625q0.28125 0 0.5 0.0625q0.234375 0.0625 0.421875 0.1875l-0.15625 0.875q-0.046875 0.171875 -0.203125 0.171875q-0.09375 0 -0.296875 -0.0625q-0.1875 -0.0625 -0.53125 -0.0625q-0.625 0 -1.046875 0.359375q-0.40625 0.359375 -0.6875 1.046875l0 4.296875l-1.1875 0zm6.605591 -9.8125l0 5.78125l0.3125 0q0.125 0 0.203125 -0.03125q0.09375 -0.046875 0.203125 -0.15625l2.140625 -2.296875q0.09375 -0.109375 0.1875 -0.171875q0.109375 -0.0625 0.28125 -0.0625l1.078125 0l-2.484375 2.640625q-0.09375 0.125 -0.1875 0.21875q-0.09375 0.078125 -0.203125 0.140625q0.125 0.078125 0.21875 0.1875q0.09375 0.09375 0.171875 0.234375l2.640625 3.328125l-1.0625 0q-0.140625 0 -0.25 -0.046875q-0.109375 -0.0625 -0.1875 -0.1875l-2.234375 -2.765625q-0.09375 -0.140625 -0.203125 -0.171875q-0.09375 -0.046875 -0.296875 -0.046875l-0.328125 0l0 3.21875l-1.1875 0l0 -9.8125l1.1875 0zm9.624512 4.171875q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm1.9093628 7.921875l0 -9.03125l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.796875q0.4375 -0.53125 0.984375 -0.84375q0.5625 -0.328125 1.296875 -0.328125q0.578125 0 1.046875 0.234375q0.46875 0.21875 0.796875 0.65625q0.34375 0.4375 0.515625 1.078125q0.1875 0.640625 0.1875 1.484375q0 0.75 -0.203125 1.390625q-0.1875 0.640625 -0.5625 1.109375q-0.375 0.46875 -0.921875 0.75q-0.546875 0.265625 -1.21875 0.265625q-0.625 0 -1.078125 -0.203125q-0.4375 -0.203125 -0.78125 -0.59375l0 2.984375l-1.1875 0zm3.015625 -8.1875q-0.578125 0 -1.015625 0.265625q-0.4375 0.265625 -0.8125 0.75l0 3.265625q0.328125 0.4375 0.71875 0.625q0.390625 0.171875 0.875 0.171875q0.9375 0 1.4375 -0.671875q0.515625 -0.671875 0.515625 -1.921875q0 -0.65625 -0.125 -1.125q-0.109375 -0.484375 -0.328125 -0.78125q-0.21875 -0.296875 -0.546875 -0.4375q-0.3125 -0.140625 -0.71875 -0.140625zm9.310242 5.90625l-0.53125 0q-0.171875 0 -0.28125 -0.046875q-0.109375 -0.0625 -0.140625 -0.234375l-0.140625 -0.625q-0.265625 0.234375 -0.515625 0.4375q-0.25 0.1875 -0.53125 0.3125q-0.28125 0.125 -0.59375 0.1875q-0.3125 0.078125 -0.703125 0.078125q-0.390625 0 -0.734375 -0.109375q-0.34375 -0.109375 -0.609375 -0.328125q-0.25 -0.21875 -0.40625 -0.546875q-0.140625 -0.34375 -0.140625 -0.8125q0 -0.390625 0.21875 -0.765625q0.21875 -0.375 0.703125 -0.65625q0.5 -0.296875 1.296875 -0.46875q0.796875 -0.1875 1.9375 -0.21875l0 -0.515625q0 -0.796875 -0.34375 -1.1875q-0.328125 -0.40625 -0.984375 -0.40625q-0.4375 0 -0.734375 0.109375q-0.296875 0.109375 -0.515625 0.25q-0.21875 0.125 -0.375 0.234375q-0.15625 0.109375 -0.3125 0.109375q-0.109375 0 -0.203125 -0.0625q-0.09375 -0.0625 -0.140625 -0.15625l-0.21875 -0.375q0.5625 -0.546875 1.203125 -0.8125q0.65625 -0.265625 1.4375 -0.265625q0.5625 0 1.0 0.1875q0.453125 0.1875 0.75 0.53125q0.296875 0.328125 0.453125 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.3125zm-3.078125 -0.71875q0.3125 0 0.5625 -0.0625q0.265625 -0.078125 0.484375 -0.1875q0.234375 -0.125 0.4375 -0.28125q0.21875 -0.171875 0.421875 -0.375l0 -1.40625q-0.828125 0.015625 -1.40625 0.125q-0.5625 0.09375 -0.921875 0.265625q-0.359375 0.171875 -0.53125 0.40625q-0.15625 0.21875 -0.15625 0.5q0 0.265625 0.078125 0.453125q0.09375 0.1875 0.234375 0.3125q0.15625 0.125 0.359375 0.1875q0.203125 0.0625 0.4375 0.0625zm9.476074 -4.828125q-0.046875 0.0625 -0.109375 0.109375q-0.046875 0.046875 -0.15625 0.046875q-0.09375 0 -0.21875 -0.078125q-0.109375 -0.09375 -0.296875 -0.1875q-0.171875 -0.109375 -0.4375 -0.1875q-0.25 -0.09375 -0.625 -0.09375q-0.484375 0 -0.875 0.1875q-0.375 0.171875 -0.640625 0.515625q-0.25 0.328125 -0.375 0.796875q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.140625 1.09375q0.140625 0.46875 0.390625 0.796875q0.25 0.3125 0.609375 0.484375q0.359375 0.171875 0.8125 0.171875q0.4375 0 0.71875 -0.09375q0.28125 -0.109375 0.46875 -0.234375q0.1875 -0.125 0.296875 -0.234375q0.125 -0.109375 0.25 -0.109375q0.15625 0 0.21875 0.125l0.34375 0.421875q-0.4375 0.546875 -1.109375 0.796875q-0.65625 0.25 -1.390625 0.25q-0.625 0 -1.171875 -0.234375q-0.546875 -0.234375 -0.953125 -0.671875q-0.390625 -0.453125 -0.625 -1.09375q-0.21875 -0.640625 -0.21875 -1.46875q0 -0.75 0.203125 -1.390625q0.203125 -0.640625 0.609375 -1.109375q0.40625 -0.46875 1.0 -0.71875q0.59375 -0.265625 1.359375 -0.265625q0.703125 0 1.25 0.234375q0.546875 0.234375 0.96875 0.640625l-0.3125 0.4375zm4.286743 -1.3125q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm3.9370117 5.171875q0 -0.15625 0.046875 -0.296875q0.0625 -0.140625 0.171875 -0.234375q0.109375 -0.109375 0.25 -0.171875q0.140625 -0.0625 0.3125 -0.0625q0.203125 0 0.359375 0.078125q0.15625 0.078125 0.25 0.203125q0.109375 0.125 0.15625 0.296875q0.0625 0.171875 0.0625 0.375q0 0.296875 -0.09375 0.625q-0.078125 0.3125 -0.234375 0.625q-0.15625 0.328125 -0.40625 0.625q-0.234375 0.296875 -0.53125 0.5625l-0.203125 -0.203125q-0.078125 -0.078125 -0.078125 -0.1875q0 -0.078125 0.09375 -0.171875q0.0625 -0.078125 0.15625 -0.203125q0.109375 -0.125 0.21875 -0.28125q0.109375 -0.15625 0.203125 -0.359375q0.09375 -0.1875 0.125 -0.40625l-0.078125 0q-0.1875 0 -0.328125 -0.0625q-0.125 -0.0625 -0.234375 -0.171875q-0.109375 -0.109375 -0.171875 -0.25q-0.046875 -0.15625 -0.046875 -0.328125zm7.069763 -5.9375l0 6.75l-1.1875 0l0 -6.75l1.1875 0zm0.265625 -2.125q0 0.171875 -0.078125 0.328125q-0.0625 0.15625 -0.1875 0.28125q-0.109375 0.109375 -0.265625 0.171875q-0.15625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.265625 -0.171875q-0.109375 -0.125 -0.1875 -0.28125q-0.0625 -0.15625 -0.0625 -0.328125q0 -0.171875 0.0625 -0.328125q0.078125 -0.15625 0.1875 -0.265625q0.125 -0.125 0.265625 -0.1875q0.15625 -0.0625 0.328125 -0.0625q0.171875 0 0.328125 0.0625q0.15625 0.0625 0.265625 0.1875q0.125 0.109375 0.1875 0.265625q0.078125 0.15625 0.078125 0.328125zm1.8182373 8.875l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.734375q0.4375 -0.484375 0.984375 -0.78125q0.546875 -0.3125 1.25 -0.3125q0.5625 0 0.984375 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0625 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0zm6.3533325 -6.75l0.96875 0q0.140625 0 0.234375 0.078125q0.09375 0.0625 0.125 0.171875l1.71875 4.34375q0.09375 0.234375 0.140625 0.484375q0.0625 0.234375 0.109375 0.46875q0.046875 -0.234375 0.109375 -0.46875q0.0625 -0.25 0.15625 -0.484375l1.734375 -4.34375q0.03125 -0.109375 0.125 -0.171875q0.09375 -0.078125 0.21875 -0.078125l0.9375 0l-2.765625 6.75l-1.0625 0l-2.75 -6.75zm12.636475 6.75l-0.53125 0q-0.171875 0 -0.28125 -0.046875q-0.109375 -0.0625 -0.140625 -0.234375l-0.140625 -0.625q-0.265625 0.234375 -0.515625 0.4375q-0.25 0.1875 -0.53125 0.3125q-0.28125 0.125 -0.59375 0.1875q-0.3125 0.078125 -0.703125 0.078125q-0.390625 0 -0.734375 -0.109375q-0.34375 -0.109375 -0.609375 -0.328125q-0.25 -0.21875 -0.40625 -0.546875q-0.140625 -0.34375 -0.140625 -0.8125q0 -0.390625 0.21875 -0.765625q0.21875 -0.375 0.703125 -0.65625q0.5 -0.296875 1.296875 -0.46875q0.796875 -0.1875 1.9375 -0.21875l0 -0.515625q0 -0.796875 -0.34375 -1.1875q-0.328125 -0.40625 -0.984375 -0.40625q-0.4375 0 -0.734375 0.109375q-0.296875 0.109375 -0.515625 0.25q-0.21875 0.125 -0.375 0.234375q-0.15625 0.109375 -0.3125 0.109375q-0.109375 0 -0.203125 -0.0625q-0.09375 -0.0625 -0.140625 -0.15625l-0.21875 -0.375q0.5625 -0.546875 1.203125 -0.8125q0.65625 -0.265625 1.4375 -0.265625q0.5625 0 1.0 0.1875q0.453125 0.1875 0.75 0.53125q0.296875 0.328125 0.453125 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.3125zm-3.078125 -0.71875q0.3125 0 0.5625 -0.0625q0.265625 -0.078125 0.484375 -0.1875q0.234375 -0.125 0.4375 -0.28125q0.21875 -0.171875 0.421875 -0.375l0 -1.40625q-0.828125 0.015625 -1.40625 0.125q-0.5625 0.09375 -0.921875 0.265625q-0.359375 0.171875 -0.53125 0.40625q-0.15625 0.21875 -0.15625 0.5q0 0.265625 0.078125 0.453125q0.09375 0.1875 0.234375 0.3125q0.15625 0.125 0.359375 0.1875q0.203125 0.0625 0.4375 0.0625zm6.194824 -9.09375l0 9.8125l-1.1875 0l0 -9.8125l1.1875 0zm3.4119873 3.0625l0 6.75l-1.1875 0l0 -6.75l1.1875 0zm0.265625 -2.125q0 0.171875 -0.078125 0.328125q-0.0625 0.15625 -0.1875 0.28125q-0.109375 0.109375 -0.265625 0.171875q-0.15625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.265625 -0.171875q-0.109375 -0.125 -0.1875 -0.28125q-0.0625 -0.15625 -0.0625 -0.328125q0 -0.171875 0.0625 -0.328125q0.078125 -0.15625 0.1875 -0.265625q0.125 -0.125 0.265625 -0.1875q0.15625 -0.0625 0.328125 -0.0625q0.171875 0 0.328125 0.0625q0.15625 0.0625 0.265625 0.1875q0.125 0.109375 0.1875 0.265625q0.078125 0.15625 0.078125 0.328125zm6.5682373 8.875q-0.25 0 -0.3125 -0.25l-0.109375 -0.8125q-0.4375 0.515625 -1.0 0.84375q-0.546875 0.3125 -1.265625 0.3125q-0.578125 0 -1.0625 -0.21875q-0.46875 -0.234375 -0.796875 -0.65625q-0.328125 -0.4375 -0.515625 -1.078125q-0.171875 -0.65625 -0.171875 -1.5q0 -0.734375 0.1875 -1.375q0.203125 -0.65625 0.578125 -1.125q0.375 -0.46875 0.921875 -0.734375q0.546875 -0.28125 1.234375 -0.28125q0.609375 0 1.046875 0.21875q0.4375 0.203125 0.796875 0.578125l0 -3.734375l1.1875 0l0 9.8125l-0.71875 0zm-2.296875 -0.859375q0.578125 0 1.015625 -0.265625q0.4375 -0.28125 0.8125 -0.765625l0 -3.265625q-0.328125 -0.4375 -0.71875 -0.609375q-0.390625 -0.171875 -0.859375 -0.171875q-0.953125 0 -1.46875 0.671875q-0.5 0.671875 -0.5 1.90625q0 0.671875 0.109375 1.140625q0.125 0.46875 0.34375 0.78125q0.21875 0.296875 0.53125 0.4375q0.328125 0.140625 0.734375 0.140625zm9.966003 0.859375l-0.53125 0q-0.171875 0 -0.28125 -0.046875q-0.109375 -0.0625 -0.140625 -0.234375l-0.140625 -0.625q-0.265625 0.234375 -0.515625 0.4375q-0.25 0.1875 -0.53125 0.3125q-0.28125 0.125 -0.59375 0.1875q-0.3125 0.078125 -0.703125 0.078125q-0.390625 0 -0.734375 -0.109375q-0.34375 -0.109375 -0.609375 -0.328125q-0.25 -0.21875 -0.40625 -0.546875q-0.140625 -0.34375 -0.140625 -0.8125q0 -0.390625 0.21875 -0.765625q0.21875 -0.375 0.703125 -0.65625q0.5 -0.296875 1.296875 -0.46875q0.796875 -0.1875 1.9375 -0.21875l0 -0.515625q0 -0.796875 -0.34375 -1.1875q-0.328125 -0.40625 -0.984375 -0.40625q-0.4375 0 -0.734375 0.109375q-0.296875 0.109375 -0.515625 0.25q-0.21875 0.125 -0.375 0.234375q-0.15625 0.109375 -0.3125 0.109375q-0.109375 0 -0.203125 -0.0625q-0.09375 -0.0625 -0.140625 -0.15625l-0.21875 -0.375q0.5625 -0.546875 1.203125 -0.8125q0.65625 -0.265625 1.4375 -0.265625q0.5625 0 1.0 0.1875q0.453125 0.1875 0.75 0.53125q0.296875 0.328125 0.453125 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.3125zm-3.078125 -0.71875q0.3125 0 0.5625 -0.0625q0.265625 -0.078125 0.484375 -0.1875q0.234375 -0.125 0.4375 -0.28125q0.21875 -0.171875 0.421875 -0.375l0 -1.40625q-0.828125 0.015625 -1.40625 0.125q-0.5625 0.09375 -0.921875 0.265625q-0.359375 0.171875 -0.53125 0.40625q-0.15625 0.21875 -0.15625 0.5q0 0.265625 0.078125 0.453125q0.09375 0.1875 0.234375 0.3125q0.15625 0.125 0.359375 0.1875q0.203125 0.0625 0.4375 0.0625zm6.9136353 0.828125q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm4.2526245 -6.859375l0 6.75l-1.1875 0l0 -6.75l1.1875 0zm0.265625 -2.125q0 0.171875 -0.078125 0.328125q-0.0625 0.15625 -0.1875 0.28125q-0.109375 0.109375 -0.265625 0.171875q-0.15625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.265625 -0.171875q-0.109375 -0.125 -0.1875 -0.28125q-0.0625 -0.15625 -0.0625 -0.328125q0 -0.171875 0.0625 -0.328125q0.078125 -0.15625 0.1875 -0.265625q0.125 -0.125 0.265625 -0.1875q0.15625 -0.0625 0.328125 -0.0625q0.171875 0 0.328125 0.0625q0.15625 0.0625 0.265625 0.1875q0.125 0.109375 0.1875 0.265625q0.078125 0.15625 0.078125 0.328125zm4.5526123 2.015625q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm4.6760254 0.828125l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.734375q0.4375 -0.484375 0.984375 -0.78125q0.546875 -0.3125 1.25 -0.3125q0.5625 0 0.984375 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0625 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0z" fill-rule="nonzero"/><path fill="#000000" d="m744.3753 301.18225l0 1.078125l-3.078125 0l0 8.46875l-1.296875 0l0 -8.46875l-3.09375 0l0 -1.078125l7.46875 0zm1.9604492 11.546875q-0.0625 0.125 -0.15625 0.203125q-0.078125 0.078125 -0.265625 0.078125l-0.890625 0l1.234375 -2.671875l-2.78125 -6.359375l1.03125 0q0.140625 0 0.234375 0.078125q0.09375 0.078125 0.125 0.171875l1.8125 4.25q0.0625 0.140625 0.09375 0.296875q0.046875 0.140625 0.078125 0.296875q0.046875 -0.15625 0.09375 -0.296875q0.046875 -0.15625 0.109375 -0.3125l1.75 -4.234375q0.046875 -0.109375 0.140625 -0.171875q0.09375 -0.078125 0.203125 -0.078125l0.953125 0l-3.765625 8.75zm4.8395996 0.28125l0 -9.03125l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.796875q0.4375 -0.53125 0.984375 -0.84375q0.5625 -0.328125 1.296875 -0.328125q0.578125 0 1.046875 0.234375q0.46875 0.21875 0.796875 0.65625q0.34375 0.4375 0.515625 1.078125q0.1875 0.640625 0.1875 1.484375q0 0.75 -0.203125 1.390625q-0.1875 0.640625 -0.5625 1.109375q-0.375 0.46875 -0.921875 0.75q-0.546875 0.265625 -1.21875 0.265625q-0.625 0 -1.078125 -0.203125q-0.4375 -0.203125 -0.78125 -0.59375l0 2.984375l-1.1875 0zm3.015625 -8.1875q-0.578125 0 -1.015625 0.265625q-0.4375 0.265625 -0.8125 0.75l0 3.265625q0.328125 0.4375 0.71875 0.625q0.390625 0.171875 0.875 0.171875q0.9375 0 1.4375 -0.671875q0.515625 -0.671875 0.515625 -1.921875q0 -0.65625 -0.125 -1.125q-0.109375 -0.484375 -0.328125 -0.78125q-0.21875 -0.296875 -0.546875 -0.4375q-0.3125 -0.140625 -0.71875 -0.140625zm7.0133667 -0.953125q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm11.462463 0.4375q-0.046875 0.0625 -0.109375 0.109375q-0.046875 0.046875 -0.15625 0.046875q-0.09375 0 -0.21875 -0.078125q-0.109375 -0.09375 -0.296875 -0.1875q-0.171875 -0.109375 -0.4375 -0.1875q-0.25 -0.09375 -0.625 -0.09375q-0.484375 0 -0.875 0.1875q-0.375 0.171875 -0.640625 0.515625q-0.25 0.328125 -0.375 0.796875q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.140625 1.09375q0.140625 0.46875 0.390625 0.796875q0.25 0.3125 0.609375 0.484375q0.359375 0.171875 0.8125 0.171875q0.4375 0 0.71875 -0.09375q0.28125 -0.109375 0.46875 -0.234375q0.1875 -0.125 0.296875 -0.234375q0.125 -0.109375 0.25 -0.109375q0.15625 0 0.21875 0.125l0.34375 0.421875q-0.4375 0.546875 -1.109375 0.796875q-0.65625 0.25 -1.390625 0.25q-0.625 0 -1.171875 -0.234375q-0.546875 -0.234375 -0.953125 -0.671875q-0.390625 -0.453125 -0.625 -1.09375q-0.21875 -0.640625 -0.21875 -1.46875q0 -0.75 0.203125 -1.390625q0.203125 -0.640625 0.609375 -1.109375q0.40625 -0.46875 1.0 -0.71875q0.59375 -0.265625 1.359375 -0.265625q0.703125 0 1.25 0.234375q0.546875 0.234375 0.96875 0.640625l-0.3125 0.4375zm1.6148682 5.546875l0 -9.8125l1.1875 0l0 3.96875q0.4375 -0.453125 0.953125 -0.734375q0.53125 -0.28125 1.21875 -0.28125q0.5625 0 0.984375 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0625 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0zm10.082275 -6.859375q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm8.890137 0.4375q-0.046875 0.0625 -0.109375 0.109375q-0.046875 0.046875 -0.15625 0.046875q-0.09375 0 -0.21875 -0.078125q-0.109375 -0.09375 -0.296875 -0.1875q-0.171875 -0.109375 -0.4375 -0.1875q-0.25 -0.09375 -0.625 -0.09375q-0.484375 0 -0.875 0.1875q-0.375 0.171875 -0.640625 0.515625q-0.25 0.328125 -0.375 0.796875q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.140625 1.09375q0.140625 0.46875 0.390625 0.796875q0.25 0.3125 0.609375 0.484375q0.359375 0.171875 0.8125 0.171875q0.4375 0 0.71875 -0.09375q0.28125 -0.109375 0.46875 -0.234375q0.1875 -0.125 0.296875 -0.234375q0.125 -0.109375 0.25 -0.109375q0.15625 0 0.21875 0.125l0.34375 0.421875q-0.4375 0.546875 -1.109375 0.796875q-0.65625 0.25 -1.390625 0.25q-0.625 0 -1.171875 -0.234375q-0.546875 -0.234375 -0.953125 -0.671875q-0.390625 -0.453125 -0.625 -1.09375q-0.21875 -0.640625 -0.21875 -1.46875q0 -0.75 0.203125 -1.390625q0.203125 -0.640625 0.609375 -1.109375q0.40625 -0.46875 1.0 -0.71875q0.59375 -0.265625 1.359375 -0.265625q0.703125 0 1.25 0.234375q0.546875 0.234375 0.96875 0.640625l-0.3125 0.4375zm2.8492432 -4.265625l0 5.78125l0.3125 0q0.125 0 0.203125 -0.03125q0.09375 -0.046875 0.203125 -0.15625l2.140625 -2.296875q0.09375 -0.109375 0.1875 -0.171875q0.109375 -0.0625 0.28125 -0.0625l1.078125 0l-2.484375 2.640625q-0.09375 0.125 -0.1875 0.21875q-0.09375 0.078125 -0.203125 0.140625q0.125 0.078125 0.21875 0.1875q0.09375 0.09375 0.171875 0.234375l2.640625 3.328125l-1.0625 0q-0.140625 0 -0.25 -0.046875q-0.109375 -0.0625 -0.1875 -0.1875l-2.234375 -2.765625q-0.09375 -0.140625 -0.203125 -0.171875q-0.09375 -0.046875 -0.296875 -0.046875l-0.328125 0l0 3.21875l-1.1875 0l0 -9.8125l1.1875 0zm7.0776367 3.0625l0 6.75l-1.1875 0l0 -6.75l1.1875 0zm0.265625 -2.125q0 0.171875 -0.078125 0.328125q-0.0625 0.15625 -0.1875 0.28125q-0.109375 0.109375 -0.265625 0.171875q-0.15625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.265625 -0.171875q-0.109375 -0.125 -0.1875 -0.28125q-0.0625 -0.15625 -0.0625 -0.328125q0 -0.171875 0.0625 -0.328125q0.078125 -0.15625 0.1875 -0.265625q0.125 -0.125 0.265625 -0.1875q0.15625 -0.0625 0.328125 -0.0625q0.171875 0 0.328125 0.0625q0.15625 0.0625 0.265625 0.1875q0.125 0.109375 0.1875 0.265625q0.078125 0.15625 0.078125 0.328125zm1.8182373 8.875l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.734375q0.4375 -0.484375 0.984375 -0.78125q0.546875 -0.3125 1.25 -0.3125q0.5625 0 0.984375 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0625 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0zm9.691711 -6.859375q0.4375 0 0.8125 0.09375q0.390625 0.09375 0.703125 0.28125l1.828125 0l0 0.4375q0 0.21875 -0.28125 0.28125l-0.765625 0.109375q0.234375 0.4375 0.234375 0.96875q0 0.484375 -0.203125 0.890625q-0.1875 0.40625 -0.53125 0.703125q-0.328125 0.28125 -0.796875 0.4375q-0.453125 0.140625 -1.0 0.140625q-0.484375 0 -0.890625 -0.109375q-0.21875 0.125 -0.328125 0.28125q-0.109375 0.15625 -0.109375 0.296875q0 0.25 0.1875 0.375q0.203125 0.125 0.515625 0.171875q0.328125 0.046875 0.734375 0.0625q0.40625 0.015625 0.828125 0.046875q0.421875 0.03125 0.828125 0.109375q0.40625 0.0625 0.71875 0.234375q0.328125 0.171875 0.515625 0.46875q0.1875 0.28125 0.1875 0.75q0 0.4375 -0.21875 0.84375q-0.203125 0.40625 -0.609375 0.71875q-0.40625 0.3125 -1.0 0.5q-0.578125 0.203125 -1.328125 0.203125q-0.734375 0 -1.296875 -0.15625q-0.546875 -0.140625 -0.921875 -0.390625q-0.359375 -0.25 -0.546875 -0.578125q-0.1875 -0.3125 -0.1875 -0.671875q0 -0.5 0.3125 -0.84375q0.328125 -0.34375 0.875 -0.5625q-0.28125 -0.125 -0.453125 -0.34375q-0.171875 -0.234375 -0.171875 -0.609375q0 -0.140625 0.046875 -0.296875q0.0625 -0.15625 0.171875 -0.3125q0.109375 -0.15625 0.265625 -0.296875q0.171875 -0.140625 0.375 -0.234375q-0.5 -0.28125 -0.78125 -0.75q-0.28125 -0.46875 -0.28125 -1.078125q0 -0.5 0.1875 -0.890625q0.1875 -0.40625 0.53125 -0.6875q0.34375 -0.296875 0.8125 -0.4375q0.46875 -0.15625 1.03125 -0.15625zm2.09375 7.21875q0 -0.25 -0.140625 -0.390625q-0.125 -0.15625 -0.375 -0.234375q-0.234375 -0.09375 -0.546875 -0.125q-0.3125 -0.046875 -0.671875 -0.0625q-0.34375 -0.015625 -0.703125 -0.03125q-0.359375 -0.03125 -0.6875 -0.078125q-0.375 0.171875 -0.609375 0.4375q-0.234375 0.265625 -0.234375 0.625q0 0.21875 0.109375 0.40625q0.125 0.203125 0.359375 0.34375q0.234375 0.15625 0.59375 0.234375q0.375 0.078125 0.875 0.078125q0.46875 0 0.84375 -0.09375q0.390625 -0.078125 0.65625 -0.234375q0.265625 -0.15625 0.390625 -0.375q0.140625 -0.21875 0.140625 -0.5zm-2.09375 -3.65625q0.359375 0 0.625 -0.09375q0.28125 -0.109375 0.46875 -0.28125q0.1875 -0.1875 0.28125 -0.4375q0.09375 -0.25 0.09375 -0.546875q0 -0.625 -0.375 -0.984375q-0.375 -0.375 -1.09375 -0.375q-0.71875 0 -1.09375 0.375q-0.375 0.359375 -0.375 0.984375q0 0.296875 0.09375 0.546875q0.09375 0.25 0.28125 0.4375q0.1875 0.171875 0.453125 0.28125q0.28125 0.09375 0.640625 0.09375z" fill-rule="nonzero"/><path fill="#000000" d="m745.7347 326.72913l-1.0 0q-0.171875 0 -0.28125 -0.078125q-0.109375 -0.09375 -0.15625 -0.234375l-0.890625 -2.296875l-4.28125 0l-0.90625 2.296875q-0.046875 0.125 -0.15625 0.21875q-0.109375 0.09375 -0.28125 0.09375l-1.0 0l3.828125 -9.546875l1.3125 0l3.8125 9.546875zm-6.25 -3.546875l3.5625 0l-1.5 -3.890625q-0.15625 -0.359375 -0.296875 -0.890625q-0.0625 0.265625 -0.140625 0.5q-0.0625 0.234375 -0.125 0.40625l-1.5 3.875zm7.2662354 3.546875l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.734375q0.4375 -0.484375 0.984375 -0.78125q0.546875 -0.3125 1.25 -0.3125q0.5625 0 0.984375 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0625 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0zm12.37915 0l-0.53125 0q-0.171875 0 -0.28125 -0.046875q-0.109375 -0.0625 -0.140625 -0.234375l-0.140625 -0.625q-0.265625 0.234375 -0.515625 0.4375q-0.25 0.1875 -0.53125 0.3125q-0.28125 0.125 -0.59375 0.1875q-0.3125 0.078125 -0.703125 0.078125q-0.390625 0 -0.734375 -0.109375q-0.34375 -0.109375 -0.609375 -0.328125q-0.25 -0.21875 -0.40625 -0.546875q-0.140625 -0.34375 -0.140625 -0.8125q0 -0.390625 0.21875 -0.765625q0.21875 -0.375 0.703125 -0.65625q0.5 -0.296875 1.296875 -0.46875q0.796875 -0.1875 1.9375 -0.21875l0 -0.515625q0 -0.796875 -0.34375 -1.1875q-0.328125 -0.40625 -0.984375 -0.40625q-0.4375 0 -0.734375 0.109375q-0.296875 0.109375 -0.515625 0.25q-0.21875 0.125 -0.375 0.234375q-0.15625 0.109375 -0.3125 0.109375q-0.109375 0 -0.203125 -0.0625q-0.09375 -0.0625 -0.140625 -0.15625l-0.21875 -0.375q0.5625 -0.546875 1.203125 -0.8125q0.65625 -0.265625 1.4375 -0.265625q0.5625 0 1.0 0.1875q0.453125 0.1875 0.75 0.53125q0.296875 0.328125 0.453125 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.3125zm-3.078125 -0.71875q0.3125 0 0.5625 -0.0625q0.265625 -0.078125 0.484375 -0.1875q0.234375 -0.125 0.4375 -0.28125q0.21875 -0.171875 0.421875 -0.375l0 -1.40625q-0.828125 0.015625 -1.40625 0.125q-0.5625 0.09375 -0.921875 0.265625q-0.359375 0.171875 -0.53125 0.40625q-0.15625 0.21875 -0.15625 0.5q0 0.265625 0.078125 0.453125q0.09375 0.1875 0.234375 0.3125q0.15625 0.125 0.359375 0.1875q0.203125 0.0625 0.4375 0.0625zm6.194824 -9.09375l0 9.8125l-1.1875 0l0 -9.8125l1.1875 0zm4.0682373 11.8125q-0.0625 0.125 -0.15625 0.203125q-0.078125 0.078125 -0.265625 0.078125l-0.890625 0l1.234375 -2.671875l-2.78125 -6.359375l1.03125 0q0.140625 0 0.234375 0.078125q0.09375 0.078125 0.125 0.171875l1.8125 4.25q0.0625 0.140625 0.09375 0.296875q0.046875 0.140625 0.078125 0.296875q0.046875 -0.15625 0.09375 -0.296875q0.046875 -0.15625 0.109375 -0.3125l1.75 -4.234375q0.046875 -0.109375 0.140625 -0.171875q0.09375 -0.078125 0.203125 -0.078125l0.953125 0l-3.765625 8.75zm8.7146 -7.640625q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm3.2375488 -1.109375l0 6.75l-1.1875 0l0 -6.75l1.1875 0zm0.265625 -2.125q0 0.171875 -0.078125 0.328125q-0.0625 0.15625 -0.1875 0.28125q-0.109375 0.109375 -0.265625 0.171875q-0.15625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.265625 -0.171875q-0.109375 -0.125 -0.1875 -0.28125q-0.0625 -0.15625 -0.0625 -0.328125q0 -0.171875 0.0625 -0.328125q0.078125 -0.15625 0.1875 -0.265625q0.125 -0.125 0.265625 -0.1875q0.15625 -0.0625 0.328125 -0.0625q0.171875 0 0.328125 0.0625q0.15625 0.0625 0.265625 0.1875q0.125 0.109375 0.1875 0.265625q0.078125 0.15625 0.078125 0.328125zm5.6932373 3.234375q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm9.231689 5.640625q-0.25 0 -0.3125 -0.25l-0.109375 -0.8125q-0.4375 0.515625 -1.0 0.84375q-0.546875 0.3125 -1.265625 0.3125q-0.578125 0 -1.0625 -0.21875q-0.46875 -0.234375 -0.796875 -0.65625q-0.328125 -0.4375 -0.515625 -1.078125q-0.171875 -0.65625 -0.171875 -1.5q0 -0.734375 0.1875 -1.375q0.203125 -0.65625 0.578125 -1.125q0.375 -0.46875 0.921875 -0.734375q0.546875 -0.28125 1.234375 -0.28125q0.609375 0 1.046875 0.21875q0.4375 0.203125 0.796875 0.578125l0 -3.734375l1.1875 0l0 9.8125l-0.71875 0zm-2.296875 -0.859375q0.578125 0 1.015625 -0.265625q0.4375 -0.28125 0.8125 -0.765625l0 -3.265625q-0.328125 -0.4375 -0.71875 -0.609375q-0.390625 -0.171875 -0.859375 -0.171875q-0.953125 0 -1.46875 0.671875q-0.5 0.671875 -0.5 1.90625q0 0.671875 0.109375 1.140625q0.125 0.46875 0.34375 0.78125q0.21875 0.296875 0.53125 0.4375q0.328125 0.140625 0.734375 0.140625zm4.9972534 0.859375l0 -6.75l0.6875 0q0.1875 0 0.265625 0.078125q0.078125 0.0625 0.09375 0.25l0.078125 1.046875q0.359375 -0.703125 0.859375 -1.09375q0.515625 -0.40625 1.203125 -0.40625q0.28125 0 0.5 0.0625q0.234375 0.0625 0.421875 0.1875l-0.15625 0.875q-0.046875 0.171875 -0.203125 0.171875q-0.09375 0 -0.296875 -0.0625q-0.1875 -0.0625 -0.53125 -0.0625q-0.625 0 -1.046875 0.359375q-0.40625 0.359375 -0.6875 1.046875l0 4.296875l-1.1875 0zm6.699341 -6.75l0 6.75l-1.1875 0l0 -6.75l1.1875 0zm0.265625 -2.125q0 0.171875 -0.078125 0.328125q-0.0625 0.15625 -0.1875 0.28125q-0.109375 0.109375 -0.265625 0.171875q-0.15625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.265625 -0.171875q-0.109375 -0.125 -0.1875 -0.28125q-0.0625 -0.15625 -0.0625 -0.328125q0 -0.171875 0.0625 -0.328125q0.078125 -0.15625 0.1875 -0.265625q0.125 -0.125 0.265625 -0.1875q0.15625 -0.0625 0.328125 -0.0625q0.171875 0 0.328125 0.0625q0.15625 0.0625 0.265625 0.1875q0.125 0.109375 0.1875 0.265625q0.078125 0.15625 0.078125 0.328125zm0.9744873 2.125l0.96875 0q0.140625 0 0.234375 0.078125q0.09375 0.0625 0.125 0.171875l1.71875 4.34375q0.09375 0.234375 0.140625 0.484375q0.0625 0.234375 0.109375 0.46875q0.046875 -0.234375 0.109375 -0.46875q0.0625 -0.25 0.15625 -0.484375l1.734375 -4.34375q0.03125 -0.109375 0.125 -0.171875q0.09375 -0.078125 0.21875 -0.078125l0.9375 0l-2.765625 6.75l-1.0625 0l-2.75 -6.75zm10.16626 -0.109375q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm4.2807617 5.984375l0 -6.75l0.6875 0q0.1875 0 0.265625 0.078125q0.078125 0.0625 0.09375 0.25l0.078125 1.046875q0.359375 -0.703125 0.859375 -1.09375q0.515625 -0.40625 1.203125 -0.40625q0.28125 0 0.5 0.0625q0.234375 0.0625 0.421875 0.1875l-0.15625 0.875q-0.046875 0.171875 -0.203125 0.171875q-0.09375 0 -0.296875 -0.0625q-0.1875 -0.0625 -0.53125 -0.0625q-0.625 0 -1.046875 0.359375q-0.40625 0.359375 -0.6875 1.046875l0 4.296875l-1.1875 0z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m-2.6656628 437.06442l180.72441 0l0 35.590546l-180.72441 0z" fill-rule="evenodd"/><path fill="#000000" d="m86.16409 453.50504l0.484375 0q0.25 0 0.40625 -0.0625q0.15625 -0.0625 0.28125 -0.21875l3.1875 -3.609375q0.140625 -0.15625 0.265625 -0.21875q0.140625 -0.078125 0.359375 -0.078125l1.09375 0l-3.625 4.109375q-0.140625 0.15625 -0.265625 0.265625q-0.125 0.09375 -0.265625 0.171875q0.1875 0.0625 0.328125 0.1875q0.140625 0.109375 0.296875 0.28125l3.796875 4.53125l-1.125 0q-0.125 0 -0.21875 -0.015625q-0.078125 -0.03125 -0.140625 -0.0625q-0.0625 -0.03125 -0.125 -0.078125q-0.046875 -0.0625 -0.109375 -0.109375l-3.296875 -3.796875q-0.0625 -0.078125 -0.125 -0.140625q-0.0625 -0.0625 -0.15625 -0.09375q-0.078125 -0.046875 -0.1875 -0.0625q-0.109375 -0.015625 -0.265625 -0.015625l-0.59375 0l0 4.375l-1.28125 0l0 -9.546875l1.28125 0l0 4.1875zm9.8989105 -1.5q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm6.0918274 7.984375q-0.0625 0.125 -0.15625 0.203125q-0.078125 0.078125 -0.265625 0.078125l-0.890625 0l1.234375 -2.671875l-2.78125 -6.359375l1.03125 0q0.140625 0 0.234375 0.078125q0.09375 0.078125 0.125 0.171875l1.8125 4.25q0.0625 0.140625 0.09375 0.296875q0.046875 0.140625 0.078125 0.296875q0.046875 -0.15625 0.09375 -0.296875q0.046875 -0.15625 0.109375 -0.3125l1.75 -4.234375q0.046875 -0.109375 0.140625 -0.171875q0.09375 -0.078125 0.203125 -0.078125l0.953125 0l-3.765625 8.75zm12.161911 -2.0q-0.25 0 -0.3125 -0.25l-0.109375 -0.8125q-0.4375 0.515625 -1.0 0.84375q-0.546875 0.3125 -1.265625 0.3125q-0.578125 0 -1.0625 -0.21875q-0.46875 -0.234375 -0.796875 -0.65625q-0.328125 -0.4375 -0.515625 -1.078125q-0.171875 -0.65625 -0.171875 -1.5q0 -0.734375 0.1875 -1.375q0.203125 -0.65625 0.578125 -1.125q0.375 -0.46875 0.921875 -0.734375q0.546875 -0.28125 1.234375 -0.28125q0.609375 0 1.046875 0.21875q0.4375 0.203125 0.796875 0.578125l0 -3.734375l1.1875 0l0 9.8125l-0.71875 0zm-2.296875 -0.859375q0.578125 0 1.015625 -0.265625q0.4375 -0.28125 0.8125 -0.765625l0 -3.265625q-0.328125 -0.4375 -0.71875 -0.609375q-0.390625 -0.171875 -0.859375 -0.171875q-0.953125 0 -1.46875 0.671875q-0.5 0.671875 -0.5 1.90625q0 0.671875 0.109375 1.140625q0.125 0.46875 0.34375 0.78125q0.21875 0.296875 0.53125 0.4375q0.328125 0.140625 0.734375 0.140625zm9.966019 0.859375l-0.53125 0q-0.171875 0 -0.28125 -0.046875q-0.109375 -0.0625 -0.140625 -0.234375l-0.140625 -0.625q-0.265625 0.234375 -0.515625 0.4375q-0.25 0.1875 -0.53125 0.3125q-0.28125 0.125 -0.59375 0.1875q-0.3125 0.078125 -0.703125 0.078125q-0.390625 0 -0.734375 -0.109375q-0.34375 -0.109375 -0.609375 -0.328125q-0.25 -0.21875 -0.40625 -0.546875q-0.140625 -0.34375 -0.140625 -0.8125q0 -0.390625 0.21875 -0.765625q0.21875 -0.375 0.703125 -0.65625q0.5 -0.296875 1.296875 -0.46875q0.796875 -0.1875 1.9375 -0.21875l0 -0.515625q0 -0.796875 -0.34375 -1.1875q-0.328125 -0.40625 -0.984375 -0.40625q-0.4375 0 -0.734375 0.109375q-0.296875 0.109375 -0.515625 0.25q-0.21875 0.125 -0.375 0.234375q-0.15625 0.109375 -0.3125 0.109375q-0.109375 0 -0.203125 -0.0625q-0.09375 -0.0625 -0.140625 -0.15625l-0.21875 -0.375q0.5625 -0.546875 1.203125 -0.8125q0.65625 -0.265625 1.4375 -0.265625q0.5625 0 1.0 0.1875q0.453125 0.1875 0.75 0.53125q0.296875 0.328125 0.453125 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.3125zm-3.078125 -0.71875q0.3125 0 0.5625 -0.0625q0.265625 -0.078125 0.484375 -0.1875q0.234375 -0.125 0.4375 -0.28125q0.21875 -0.171875 0.421875 -0.375l0 -1.40625q-0.828125 0.015625 -1.40625 0.125q-0.5625 0.09375 -0.921875 0.265625q-0.359375 0.171875 -0.53125 0.40625q-0.15625 0.21875 -0.15625 0.5q0 0.265625 0.078125 0.453125q0.09375 0.1875 0.234375 0.3125q0.15625 0.125 0.359375 0.1875q0.203125 0.0625 0.4375 0.0625zm6.9135895 0.828125q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm7.8932495 -0.109375l-0.53125 0q-0.171875 0 -0.28125 -0.046875q-0.109375 -0.0625 -0.140625 -0.234375l-0.140625 -0.625q-0.265625 0.234375 -0.515625 0.4375q-0.25 0.1875 -0.53125 0.3125q-0.28125 0.125 -0.59375 0.1875q-0.3125 0.078125 -0.703125 0.078125q-0.390625 0 -0.734375 -0.109375q-0.34375 -0.109375 -0.609375 -0.328125q-0.25 -0.21875 -0.40625 -0.546875q-0.140625 -0.34375 -0.140625 -0.8125q0 -0.390625 0.21875 -0.765625q0.21875 -0.375 0.703125 -0.65625q0.5 -0.296875 1.296875 -0.46875q0.796875 -0.1875 1.9375 -0.21875l0 -0.515625q0 -0.796875 -0.34375 -1.1875q-0.328125 -0.40625 -0.984375 -0.40625q-0.4375 0 -0.734375 0.109375q-0.296875 0.109375 -0.515625 0.25q-0.21875 0.125 -0.375 0.234375q-0.15625 0.109375 -0.3125 0.109375q-0.109375 0 -0.203125 -0.0625q-0.09375 -0.0625 -0.140625 -0.15625l-0.21875 -0.375q0.5625 -0.546875 1.203125 -0.8125q0.65625 -0.265625 1.4375 -0.265625q0.5625 0 1.0 0.1875q0.453125 0.1875 0.75 0.53125q0.296875 0.328125 0.453125 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.3125zm-3.078125 -0.71875q0.3125 0 0.5625 -0.0625q0.265625 -0.078125 0.484375 -0.1875q0.234375 -0.125 0.4375 -0.28125q0.21875 -0.171875 0.421875 -0.375l0 -1.40625q-0.828125 0.015625 -1.40625 0.125q-0.5625 0.09375 -0.921875 0.265625q-0.359375 0.171875 -0.53125 0.40625q-0.15625 0.21875 -0.15625 0.5q0 0.265625 0.078125 0.453125q0.09375 0.1875 0.234375 0.3125q0.15625 0.125 0.359375 0.1875q0.203125 0.0625 0.4375 0.0625zm9.485901 0.828125q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm4.9088745 1.890625q-0.0625 0.125 -0.15625 0.203125q-0.078125 0.078125 -0.265625 0.078125l-0.890625 0l1.234375 -2.671875l-2.78125 -6.359375l1.03125 0q0.140625 0 0.234375 0.078125q0.09375 0.078125 0.125 0.171875l1.8125 4.25q0.0625 0.140625 0.09375 0.296875q0.046875 0.140625 0.078125 0.296875q0.046875 -0.15625 0.09375 -0.296875q0.046875 -0.15625 0.109375 -0.3125l1.75 -4.234375q0.046875 -0.109375 0.140625 -0.171875q0.09375 -0.078125 0.203125 -0.078125l0.953125 0l-3.765625 8.75zm4.8395996 0.28125l0 -9.03125l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.796875q0.4375 -0.53125 0.984375 -0.84375q0.5625 -0.328125 1.296875 -0.328125q0.578125 0 1.046875 0.234375q0.46875 0.21875 0.796875 0.65625q0.34375 0.4375 0.515625 1.078125q0.1875 0.640625 0.1875 1.484375q0 0.75 -0.203125 1.390625q-0.1875 0.640625 -0.5625 1.109375q-0.375 0.46875 -0.921875 0.75q-0.546875 0.265625 -1.21875 0.265625q-0.625 0 -1.078125 -0.203125q-0.4375 -0.203125 -0.78125 -0.59375l0 2.984375l-1.1875 0zm3.015625 -8.1875q-0.578125 0 -1.015625 0.265625q-0.4375 0.265625 -0.8125 0.75l0 3.265625q0.328125 0.4375 0.71875 0.625q0.390625 0.171875 0.875 0.171875q0.9375 0 1.4375 -0.671875q0.515625 -0.671875 0.515625 -1.921875q0 -0.65625 -0.125 -1.125q-0.109375 -0.484375 -0.328125 -0.78125q-0.21875 -0.296875 -0.546875 -0.4375q-0.3125 -0.140625 -0.71875 -0.140625zm7.0133514 -0.953125q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm8.155792 0.34375q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m-2.6656628 485.06442l180.72441 0l0 35.590546l-180.72441 0z" fill-rule="evenodd"/><path fill="#000000" d="m97.31447 505.77066l4.125 0l0 1.09375l-5.421875 0l0 -9.546875l1.296875 0l0 8.453125zm10.444382 -6.96875q-0.0625 0.109375 -0.125 0.15625q-0.0625 0.046875 -0.171875 0.046875q-0.109375 0 -0.265625 -0.109375q-0.140625 -0.109375 -0.375 -0.25q-0.234375 -0.140625 -0.5625 -0.25q-0.3125 -0.109375 -0.78125 -0.109375q-0.421875 0 -0.765625 0.125q-0.328125 0.109375 -0.5625 0.3125q-0.21875 0.1875 -0.328125 0.46875q-0.109375 0.265625 -0.109375 0.578125q0 0.390625 0.1875 0.65625q0.203125 0.265625 0.515625 0.453125q0.328125 0.1875 0.734375 0.328125q0.421875 0.125 0.84375 0.28125q0.4375 0.140625 0.84375 0.328125q0.40625 0.1875 0.734375 0.46875q0.328125 0.265625 0.515625 0.6875q0.203125 0.40625 0.203125 0.984375q0 0.640625 -0.21875 1.1875q-0.203125 0.546875 -0.625 0.953125q-0.40625 0.40625 -1.0 0.640625q-0.59375 0.234375 -1.359375 0.234375q-0.921875 0 -1.6875 -0.328125q-0.765625 -0.34375 -1.296875 -0.921875l0.375 -0.609375q0.046875 -0.078125 0.125 -0.125q0.078125 -0.046875 0.171875 -0.046875q0.140625 0 0.3125 0.15625q0.1875 0.140625 0.453125 0.328125q0.265625 0.171875 0.640625 0.328125q0.390625 0.140625 0.953125 0.140625q0.453125 0 0.8125 -0.125q0.359375 -0.125 0.609375 -0.34375q0.25 -0.234375 0.375 -0.546875q0.140625 -0.328125 0.140625 -0.734375q0 -0.421875 -0.203125 -0.703125q-0.1875 -0.28125 -0.515625 -0.46875q-0.3125 -0.1875 -0.71875 -0.3125q-0.40625 -0.125 -0.84375 -0.265625q-0.421875 -0.140625 -0.84375 -0.3125q-0.40625 -0.1875 -0.734375 -0.46875q-0.3125 -0.28125 -0.515625 -0.703125q-0.1875 -0.4375 -0.1875 -1.078125q0 -0.5 0.1875 -0.96875q0.203125 -0.484375 0.578125 -0.84375q0.375 -0.375 0.921875 -0.59375q0.546875 -0.21875 1.265625 -0.21875q0.796875 0 1.453125 0.25q0.671875 0.25 1.15625 0.734375l-0.3125 0.609375zm3.5951233 4.484375l0 3.578125l-1.28125 0l0 -9.546875l2.8125 0q0.90625 0 1.578125 0.21875q0.671875 0.203125 1.109375 0.59375q0.4375 0.375 0.65625 0.921875q0.21875 0.546875 0.21875 1.21875q0 0.671875 -0.234375 1.234375q-0.234375 0.546875 -0.6875 0.953125q-0.453125 0.390625 -1.125 0.609375q-0.65625 0.21875 -1.515625 0.21875l-1.53125 0zm0 -1.015625l1.53125 0q0.5625 0 0.984375 -0.140625q0.421875 -0.15625 0.703125 -0.421875q0.28125 -0.265625 0.421875 -0.625q0.15625 -0.375 0.15625 -0.8125q0 -0.90625 -0.5625 -1.421875q-0.5625 -0.515625 -1.703125 -0.515625l-1.53125 0l0 3.9375zm9.106384 6.875l0 -9.03125l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.796875q0.4375 -0.53125 0.984375 -0.84375q0.5625 -0.328125 1.296875 -0.328125q0.578125 0 1.046875 0.234375q0.46875 0.21875 0.796875 0.65625q0.34375 0.4375 0.515625 1.078125q0.1875 0.640625 0.1875 1.484375q0 0.75 -0.203125 1.390625q-0.1875 0.640625 -0.5625 1.109375q-0.375 0.46875 -0.921875 0.75q-0.546875 0.265625 -1.21875 0.265625q-0.625 0 -1.078125 -0.203125q-0.4375 -0.203125 -0.78125 -0.59375l0 2.984375l-1.1875 0zm3.015625 -8.1875q-0.578125 0 -1.015625 0.265625q-0.4375 0.265625 -0.8125 0.75l0 3.265625q0.328125 0.4375 0.71875 0.625q0.390625 0.171875 0.875 0.171875q0.9375 0 1.4375 -0.671875q0.515625 -0.671875 0.515625 -1.921875q0 -0.65625 -0.125 -1.125q-0.109375 -0.484375 -0.328125 -0.78125q-0.21875 -0.296875 -0.546875 -0.4375q-0.3125 -0.140625 -0.71875 -0.140625zm4.3414764 5.90625l0 -6.75l0.6875 0q0.1875 0 0.265625 0.078125q0.078125 0.0625 0.09375 0.25l0.078125 1.046875q0.359375 -0.703125 0.859375 -1.09375q0.515625 -0.40625 1.203125 -0.40625q0.28125 0 0.5 0.0625q0.234375 0.0625 0.421875 0.1875l-0.15625 0.875q-0.046875 0.171875 -0.203125 0.171875q-0.09375 0 -0.296875 -0.0625q-0.1875 -0.0625 -0.53125 -0.0625q-0.625 0 -1.046875 0.359375q-0.40625 0.359375 -0.6875 1.046875l0 4.296875l-1.1875 0zm8.105591 -6.859375q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm6.7229156 0.9375q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm5.6588745 -6.96875q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm9.285416 -4.71875q-0.046875 0.0625 -0.109375 0.109375q-0.046875 0.046875 -0.15625 0.046875q-0.09375 0 -0.21875 -0.078125q-0.109375 -0.09375 -0.296875 -0.1875q-0.171875 -0.109375 -0.4375 -0.1875q-0.25 -0.09375 -0.625 -0.09375q-0.484375 0 -0.875 0.1875q-0.375 0.171875 -0.640625 0.515625q-0.25 0.328125 -0.375 0.796875q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.140625 1.09375q0.140625 0.46875 0.390625 0.796875q0.25 0.3125 0.609375 0.484375q0.359375 0.171875 0.8125 0.171875q0.4375 0 0.71875 -0.09375q0.28125 -0.109375 0.46875 -0.234375q0.1875 -0.125 0.296875 -0.234375q0.125 -0.109375 0.25 -0.109375q0.15625 0 0.21875 0.125l0.34375 0.421875q-0.4375 0.546875 -1.109375 0.796875q-0.65625 0.25 -1.390625 0.25q-0.625 0 -1.171875 -0.234375q-0.546875 -0.234375 -0.953125 -0.671875q-0.390625 -0.453125 -0.625 -1.09375q-0.21875 -0.640625 -0.21875 -1.46875q0 -0.75 0.203125 -1.390625q0.203125 -0.640625 0.609375 -1.109375q0.40625 -0.46875 1.0 -0.71875q0.59375 -0.265625 1.359375 -0.265625q0.703125 0 1.25 0.234375q0.546875 0.234375 0.96875 0.640625l-0.3125 0.4375zm4.3492126 -1.3125q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm6.0041656 -8.984375l0 9.8125l-1.1875 0l0 -9.8125l1.1875 0z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m-66.665665 229.06442l180.72441 0l0 35.590546l-180.72441 0z" fill-rule="evenodd"/><path fill="#000000" d="m14.926851 247.2863l0 3.578125l-1.28125 0l0 -9.546875l2.8125 0q0.90625 0 1.578125 0.21875q0.671875 0.203125 1.109375 0.59375q0.4375 0.375 0.65625 0.921875q0.21875 0.546875 0.21875 1.21875q0 0.671875 -0.234375 1.234375q-0.234375 0.546875 -0.6875 0.953125q-0.453125 0.390625 -1.125 0.609375q-0.65625 0.21875 -1.515625 0.21875l-1.53125 0zm0 -1.015625l1.53125 0q0.5625 0 0.984375 -0.140625q0.421875 -0.15625 0.703125 -0.421875q0.28125 -0.265625 0.421875 -0.625q0.15625 -0.375 0.15625 -0.8125q0 -0.90625 -0.5625 -1.421875q-0.5625 -0.515625 -1.703125 -0.515625l-1.53125 0l0 3.9375zm9.005951 -2.265625q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm4.280792 5.984375l0 -6.75l0.6875 0q0.1875 0 0.265625 0.078125q0.078125 0.0625 0.09375 0.25l0.078125 1.046875q0.359375 -0.703125 0.859375 -1.09375q0.515625 -0.40625 1.203125 -0.40625q0.28125 0 0.5 0.0625q0.2343769 0.0625 0.4218769 0.1875l-0.15625 0.875q-0.046875 0.171875 -0.2031269 0.171875q-0.09375 0 -0.296875 -0.0625q-0.1875 -0.0625 -0.53125 -0.0625q-0.625 0 -1.046875 0.359375q-0.40625 0.359375 -0.6875 1.046875l0 4.296875l-1.1875 0zm9.246218 -5.640625q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm3.237503 -1.109375l0 6.75l-1.1875 0l0 -6.75l1.1875 0zm0.265625 -2.125q0 0.171875 -0.078125 0.328125q-0.0625 0.15625 -0.1875 0.28125q-0.109375 0.109375 -0.265625 0.171875q-0.15625 0.0625 -0.328125 0.0625q-0.171875 0 -0.328125 -0.0625q-0.140625 -0.0625 -0.265625 -0.171875q-0.109375 -0.125 -0.1875 -0.28125q-0.0625 -0.15625 -0.0625 -0.328125q0 -0.171875 0.0625 -0.328125q0.078125 -0.15625 0.1875 -0.265625q0.125 -0.125 0.265625 -0.1875q0.15625 -0.0625 0.328125 -0.0625q0.171875 0 0.328125 0.0625q0.15625 0.0625 0.265625 0.1875q0.125 0.109375 0.1875 0.265625q0.078125 0.15625 0.078125 0.328125zm5.6932373 3.234375q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm3.956253 5.75q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm5.5963745 -6.96875q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625zm4.280792 5.984375l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.734375q0.4375 -0.484375 0.984375 -0.78125q0.546875 -0.3125 1.25 -0.3125q0.5624962 0 0.9843712 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0624962 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0zm9.457287 0.109375q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm9.371811 -5.75q-0.078125 0.15625 -0.25 0.15625q-0.109375 0 -0.234375 -0.078125q-0.125 -0.078125 -0.3125 -0.15625q-0.171875 -0.09375 -0.4375 -0.171875q-0.25 -0.078125 -0.59375 -0.078125q-0.296875 0 -0.546875 0.078125q-0.234375 0.078125 -0.40625 0.21875q-0.15625 0.125 -0.25 0.296875q-0.09375 0.171875 -0.09375 0.390625q0 0.25 0.140625 0.421875q0.15625 0.171875 0.40625 0.3125q0.25 0.125 0.5625 0.21875q0.3125 0.09375 0.640625 0.203125q0.328125 0.109375 0.640625 0.25q0.3125 0.125 0.5625 0.328125q0.25 0.203125 0.390625 0.5q0.15625 0.28125 0.15625 0.6875q0 0.46875 -0.171875 0.859375q-0.15625 0.390625 -0.484375 0.6875q-0.328125 0.28125 -0.8125 0.453125q-0.46875 0.171875 -1.078125 0.171875q-0.71875 0 -1.296875 -0.234375q-0.5625 -0.234375 -0.96875 -0.59375l0.28125 -0.453125q0.0625 -0.078125 0.125 -0.125q0.078125 -0.046875 0.203125 -0.046875q0.125 0 0.25 0.09375q0.140625 0.09375 0.328125 0.203125q0.1875 0.109375 0.453125 0.203125q0.265625 0.09375 0.671875 0.09375q0.359375 0 0.609375 -0.078125q0.265625 -0.09375 0.4375 -0.25q0.171875 -0.15625 0.25 -0.34375q0.09375 -0.203125 0.09375 -0.4375q0 -0.28125 -0.15625 -0.453125q-0.140625 -0.1875 -0.390625 -0.3125q-0.25 -0.140625 -0.578125 -0.234375q-0.3125 -0.09375 -0.640625 -0.203125q-0.328125 -0.109375 -0.640625 -0.234375q-0.3125 -0.140625 -0.5625 -0.34375q-0.25 -0.21875 -0.40625 -0.515625q-0.140625 -0.3125 -0.140625 -0.734375q0 -0.390625 0.15625 -0.75q0.15625 -0.359375 0.46875 -0.625q0.3125 -0.265625 0.75 -0.421875q0.453125 -0.171875 1.015625 -0.171875q0.671875 0 1.203125 0.21875q0.53125 0.203125 0.921875 0.5625l-0.265625 0.4375zm3.956253 5.75q-0.796875 0 -1.234375 -0.4375q-0.421875 -0.453125 -0.421875 -1.296875l0 -4.125l-0.8125 0q-0.109375 0 -0.1875 -0.0625q-0.0625 -0.078125 -0.0625 -0.203125l0 -0.46875l1.109375 -0.140625l0.265625 -2.09375q0.015625 -0.09375 0.078125 -0.15625q0.078125 -0.0625 0.203125 -0.0625l0.59375 0l0 2.3125l1.9375 0l0 0.875l-1.9375 0l0 4.046875q0 0.421875 0.203125 0.640625q0.203125 0.203125 0.53125 0.203125q0.1875 0 0.328125 -0.046875q0.140625 -0.0625 0.234375 -0.125q0.09375 -0.0625 0.15625 -0.109375q0.078125 -0.046875 0.140625 -0.046875q0.09375 0 0.171875 0.109375l0.34375 0.578125q-0.3125 0.28125 -0.75 0.453125q-0.421875 0.15625 -0.890625 0.15625zm5.6588745 -6.96875q0.734375 0 1.328125 0.25q0.609375 0.25 1.015625 0.703125q0.421875 0.453125 0.640625 1.09375q0.234375 0.640625 0.234375 1.4375q0 0.796875 -0.234375 1.4375q-0.21875 0.640625 -0.640625 1.09375q-0.40625 0.453125 -1.015625 0.703125q-0.59375 0.234375 -1.328125 0.234375q-0.734375 0 -1.34375 -0.234375q-0.59375 -0.25 -1.015625 -0.703125q-0.40625 -0.453125 -0.640625 -1.09375q-0.21875 -0.640625 -0.21875 -1.4375q0 -0.796875 0.21875 -1.4375q0.234375 -0.640625 0.640625 -1.09375q0.421875 -0.453125 1.015625 -0.703125q0.609375 -0.25 1.34375 -0.25zm0 6.03125q1.0 0 1.484375 -0.671875q0.5 -0.671875 0.5 -1.875q0 -1.203125 -0.5 -1.875q-0.484375 -0.671875 -1.484375 -0.671875q-0.5 0 -0.875 0.171875q-0.375 0.171875 -0.625 0.5q-0.25 0.328125 -0.375 0.8125q-0.125 0.46875 -0.125 1.0625q0 0.609375 0.125 1.078125q0.125 0.46875 0.375 0.796875q0.25 0.328125 0.625 0.5q0.375 0.171875 0.875 0.171875zm4.6760406 0.828125l0 -6.75l0.6875 0q0.1875 0 0.265625 0.078125q0.078125 0.0625 0.09375 0.25l0.078125 1.046875q0.359375 -0.703125 0.859375 -1.09375q0.515625 -0.40625 1.203125 -0.40625q0.28125 0 0.5 0.0625q0.234375 0.0625 0.421875 0.1875l-0.15625 0.875q-0.046875 0.171875 -0.203125 0.171875q-0.09375 0 -0.296875 -0.0625q-0.1875 -0.0625 -0.53125 -0.0625q-0.625 0 -1.046875 0.359375q-0.40625 0.359375 -0.6875 1.046875l0 4.296875l-1.1875 0zm8.043091 -6.859375q0.609375 0 1.125 0.203125q0.515625 0.203125 0.890625 0.59375q0.375 0.375 0.578125 0.9375q0.203125 0.5625 0.203125 1.28125q0 0.28125 -0.0625 0.375q-0.046875 0.09375 -0.21875 0.09375l-4.484375 0q0 0.640625 0.15625 1.125q0.171875 0.46875 0.453125 0.78125q0.28125 0.3125 0.65625 0.46875q0.390625 0.15625 0.875 0.15625q0.453125 0 0.765625 -0.09375q0.328125 -0.109375 0.5625 -0.21875q0.234375 -0.125 0.390625 -0.234375q0.15625 -0.109375 0.265625 -0.109375q0.140625 0 0.234375 0.125l0.328125 0.421875q-0.21875 0.265625 -0.53125 0.46875q-0.296875 0.203125 -0.65625 0.328125q-0.34375 0.125 -0.71875 0.1875q-0.375 0.0625 -0.734375 0.0625q-0.703125 0 -1.296875 -0.234375q-0.59375 -0.234375 -1.03125 -0.6875q-0.421875 -0.46875 -0.65625 -1.140625q-0.234375 -0.671875 -0.234375 -1.546875q0 -0.703125 0.203125 -1.3125q0.21875 -0.609375 0.625 -1.0625q0.40625 -0.453125 0.984375 -0.703125q0.59375 -0.265625 1.328125 -0.265625zm0.03125 0.875q-0.859375 0 -1.359375 0.5q-0.484375 0.5 -0.609375 1.375l3.671875 0q0 -0.421875 -0.109375 -0.765625q-0.109375 -0.34375 -0.328125 -0.59375q-0.21875 -0.25 -0.546875 -0.375q-0.3125 -0.140625 -0.71875 -0.140625z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m18.737534 17.942257l124.06299 0l0 35.590553l-124.06299 0z" fill-rule="evenodd"/><path fill="#000000" d="m32.487534 36.44538q0 0.796875 -0.203125 1.4375q-0.1875 0.625 -0.578125 1.0625q-0.375 0.4375 -0.9375 0.671875q-0.5625 0.234375 -1.28125 0.234375q-0.65625 0 -1.34375 -0.1875q0 -0.1875 0.015625 -0.375q0.03125 -0.203125 0.046875 -0.390625q0.015625 -0.109375 0.078125 -0.171875q0.078125 -0.078125 0.21875 -0.078125q0.125 0 0.3125 0.0625q0.203125 0.0625 0.546875 0.0625q0.4375 0 0.78125 -0.125q0.34375 -0.140625 0.578125 -0.421875q0.234375 -0.28125 0.359375 -0.71875q0.125 -0.4375 0.125 -1.03125l0 -6.28125l1.28125 0l0 6.25zm7.1051636 3.296875l-0.53125 0q-0.171875 0 -0.28125 -0.046875q-0.109375 -0.0625 -0.140625 -0.234375l-0.140625 -0.625q-0.265625 0.234375 -0.515625 0.4375q-0.25 0.1875 -0.53125 0.3125q-0.28125 0.125 -0.59375 0.1875q-0.3125 0.078125 -0.703125 0.078125q-0.390625 0 -0.734375 -0.109375q-0.34375 -0.109375 -0.609375 -0.328125q-0.25 -0.21875 -0.40625 -0.546875q-0.140625 -0.34375 -0.140625 -0.8125q0 -0.390625 0.21875 -0.765625q0.21875 -0.375 0.703125 -0.65625q0.5 -0.296875 1.296875 -0.46875q0.796875 -0.1875 1.9375 -0.21875l0 -0.515625q0 -0.796875 -0.34375 -1.1875q-0.328125 -0.40625 -0.984375 -0.40625q-0.4375 0 -0.734375 0.109375q-0.296875 0.109375 -0.515625 0.25q-0.21875 0.125 -0.375 0.234375q-0.15625 0.109375 -0.3125 0.109375q-0.109375 0 -0.203125 -0.0625q-0.09375 -0.0625 -0.140625 -0.15625l-0.21875 -0.375q0.5625 -0.546875 1.203125 -0.8125q0.65625 -0.265625 1.4375 -0.265625q0.5625 0 1.0 0.1875q0.453125 0.1875 0.75 0.53125q0.296875 0.328125 0.453125 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.3125zm-3.078125 -0.71875q0.3125 0 0.5625 -0.0625q0.265625 -0.078125 0.484375 -0.1875q0.234375 -0.125 0.4375 -0.28125q0.21875 -0.171875 0.421875 -0.375l0 -1.40625q-0.828125 0.015625 -1.40625 0.125q-0.5625 0.09375 -0.921875 0.265625q-0.359375 0.171875 -0.53125 0.40625q-0.15625 0.21875 -0.15625 0.5q0 0.265625 0.078125 0.453125q0.09375 0.1875 0.234375 0.3125q0.15625 0.125 0.359375 0.1875q0.203125 0.0625 0.4375 0.0625zm4.8667145 0.71875l0 -6.75l0.703125 0q0.265625 0 0.328125 0.25l0.09375 0.734375q0.4375 -0.484375 0.984375 -0.78125q0.546875 -0.3125 1.25 -0.3125q0.5625 0 0.984375 0.1875q0.421875 0.1875 0.703125 0.53125q0.28125 0.328125 0.421875 0.796875q0.15625 0.46875 0.15625 1.046875l0 4.296875l-1.1875 0l0 -4.296875q0 -0.765625 -0.359375 -1.1875q-0.34375 -0.421875 -1.0625 -0.421875q-0.53125 0 -0.984375 0.25q-0.453125 0.25 -0.84375 0.6875l0 4.96875l-1.1875 0zm13.013977 -9.65625q0.609375 0 1.140625 0.1875q0.53125 0.171875 0.90625 0.515625q0.390625 0.34375 0.609375 0.84375q0.21875 0.484375 0.21875 1.109375q0 0.53125 -0.171875 0.984375q-0.15625 0.453125 -0.4375 0.875q-0.265625 0.421875 -0.625 0.8125q-0.34375 0.390625 -0.75 0.796875l-2.515625 2.5625q0.265625 -0.078125 0.53125 -0.109375q0.28125 -0.046875 0.53125 -0.046875l3.203125 0q0.203125 0 0.3125 0.109375q0.109375 0.109375 0.109375 0.296875l0 0.71875l-6.375 0l0 -0.40625q0 -0.125 0.046875 -0.25q0.0625 -0.140625 0.171875 -0.25l3.0625 -3.078125q0.375 -0.390625 0.6875 -0.734375q0.3125 -0.359375 0.53125 -0.71875q0.234375 -0.359375 0.34375 -0.734375q0.125 -0.375 0.125 -0.796875q0 -0.421875 -0.140625 -0.734375q-0.125 -0.3125 -0.359375 -0.515625q-0.234375 -0.21875 -0.546875 -0.3125q-0.3125 -0.109375 -0.671875 -0.109375q-0.359375 0 -0.671875 0.109375q-0.296875 0.109375 -0.53125 0.296875q-0.234375 0.1875 -0.40625 0.453125q-0.15625 0.25 -0.234375 0.578125q-0.046875 0.1875 -0.15625 0.28125q-0.109375 0.078125 -0.28125 0.078125q-0.03125 0 -0.078125 0q-0.03125 0 -0.078125 -0.015625l-0.609375 -0.109375q0.09375 -0.640625 0.359375 -1.140625q0.265625 -0.515625 0.671875 -0.84375q0.40625 -0.34375 0.9375 -0.515625q0.53125 -0.1875 1.140625 -0.1875zm7.8552856 0q0.609375 0 1.125 0.171875q0.515625 0.171875 0.875 0.5q0.375 0.3125 0.578125 0.765625q0.21875 0.453125 0.21875 1.015625q0 0.453125 -0.125 0.8125q-0.109375 0.34375 -0.328125 0.625q-0.21875 0.265625 -0.53125 0.453125q-0.296875 0.1875 -0.671875 0.296875q0.921875 0.25 1.390625 0.828125q0.46875 0.578125 0.46875 1.453125q0 0.65625 -0.25 1.1875q-0.25 0.515625 -0.6875 0.890625q-0.421875 0.375 -1.0 0.578125q-0.578125 0.1875 -1.234375 0.1875q-0.765625 0 -1.3125 -0.1875q-0.53125 -0.1875 -0.90625 -0.515625q-0.375 -0.34375 -0.609375 -0.796875q-0.234375 -0.46875 -0.40625 -1.0l0.5 -0.203125q0.140625 -0.0625 0.28125 -0.0625q0.140625 0 0.234375 0.0625q0.109375 0.046875 0.171875 0.171875q0 0.015625 0.015625 0.046875q0.015625 0.03125 0.03125 0.0625q0.09375 0.203125 0.21875 0.453125q0.140625 0.234375 0.359375 0.453125q0.234375 0.203125 0.5625 0.359375q0.34375 0.140625 0.84375 0.140625q0.5 0 0.875 -0.15625q0.375 -0.171875 0.625 -0.421875q0.25 -0.265625 0.375 -0.578125q0.125 -0.328125 0.125 -0.640625q0 -0.390625 -0.109375 -0.703125q-0.09375 -0.328125 -0.359375 -0.5625q-0.265625 -0.234375 -0.75 -0.359375q-0.46875 -0.140625 -1.21875 -0.140625l0 -0.859375q0.609375 0 1.03125 -0.125q0.4375 -0.125 0.703125 -0.34375q0.28125 -0.234375 0.390625 -0.53125q0.125 -0.3125 0.125 -0.6875q0 -0.40625 -0.125 -0.703125q-0.125 -0.3125 -0.359375 -0.515625q-0.21875 -0.203125 -0.53125 -0.296875q-0.3125 -0.109375 -0.671875 -0.109375q-0.359375 0 -0.671875 0.109375q-0.296875 0.109375 -0.53125 0.296875q-0.234375 0.1875 -0.40625 0.453125q-0.15625 0.265625 -0.234375 0.578125q-0.046875 0.1875 -0.15625 0.28125q-0.109375 0.078125 -0.28125 0.078125q-0.03125 0 -0.078125 0q-0.03125 0 -0.078125 -0.015625l-0.609375 -0.109375q0.09375 -0.640625 0.359375 -1.140625q0.265625 -0.515625 0.671875 -0.84375q0.40625 -0.34375 0.9375 -0.515625q0.53125 -0.1875 1.140625 -0.1875zm10.177597 0q0.609375 0 1.140625 0.1875q0.53125 0.171875 0.90625 0.515625q0.390625 0.34375 0.609375 0.84375q0.21875 0.484375 0.21875 1.109375q0 0.53125 -0.171875 0.984375q-0.15625 0.453125 -0.4375 0.875q-0.265625 0.421875 -0.625 0.8125q-0.34375 0.390625 -0.75 0.796875l-2.515625 2.5625q0.265625 -0.078125 0.53125 -0.109375q0.28125 -0.046875 0.53125 -0.046875l3.203125 0q0.203125 0 0.3125 0.109375q0.109375 0.109375 0.109375 0.296875l0 0.71875l-6.375 0l0 -0.40625q0 -0.125 0.046875 -0.25q0.0625 -0.140625 0.171875 -0.25l3.0625 -3.078125q0.375 -0.390625 0.6875 -0.734375q0.3125 -0.359375 0.53125 -0.71875q0.234375 -0.359375 0.34375 -0.734375q0.125 -0.375 0.125 -0.796875q0 -0.421875 -0.140625 -0.734375q-0.125 -0.3125 -0.359375 -0.515625q-0.234375 -0.21875 -0.546875 -0.3125q-0.3125 -0.109375 -0.671875 -0.109375q-0.359375 0 -0.671875 0.109375q-0.296875 0.109375 -0.53125 0.296875q-0.234375 0.1875 -0.40625 0.453125q-0.15625 0.25 -0.234375 0.578125q-0.046875 0.1875 -0.15625 0.28125q-0.109375 0.078125 -0.28125 0.078125q-0.03125 0 -0.078125 0q-0.03125 0 -0.078125 -0.015625l-0.609375 -0.109375q0.09375 -0.640625 0.359375 -1.140625q0.265625 -0.515625 0.671875 -0.84375q0.40625 -0.34375 0.9375 -0.515625q0.53125 -0.1875 1.140625 -0.1875zm11.058411 4.890625q0 1.25 -0.265625 2.171875q-0.265625 0.90625 -0.734375 1.515625q-0.46875 0.59375 -1.109375 0.890625q-0.640625 0.28125 -1.359375 0.28125q-0.734375 0 -1.375 -0.28125q-0.625 -0.296875 -1.09375 -0.890625q-0.453125 -0.609375 -0.71875 -1.515625q-0.265625 -0.921875 -0.265625 -2.171875q0 -1.265625 0.265625 -2.171875q0.265625 -0.921875 0.71875 -1.515625q0.46875 -0.609375 1.09375 -0.90625q0.640625 -0.296875 1.375 -0.296875q0.71875 0 1.359375 0.296875q0.640625 0.296875 1.109375 0.90625q0.46875 0.59375 0.734375 1.515625q0.265625 0.90625 0.265625 2.171875zm-1.234375 0q0 -1.09375 -0.1875 -1.828125q-0.171875 -0.75 -0.484375 -1.203125q-0.3125 -0.453125 -0.71875 -0.65625q-0.40625 -0.203125 -0.84375 -0.203125q-0.4375 0 -0.84375 0.203125q-0.40625 0.203125 -0.71875 0.65625q-0.296875 0.453125 -0.484375 1.203125q-0.1875 0.734375 -0.1875 1.828125q0 1.09375 0.1875 1.828125q0.1875 0.734375 0.484375 1.1875q0.3125 0.453125 0.71875 0.65625q0.40625 0.1875 0.84375 0.1875q0.4375 0 0.84375 -0.1875q0.40625 -0.203125 0.71875 -0.65625q0.3125 -0.453125 0.484375 -1.1875q0.1875 -0.734375 0.1875 -1.828125zm5.6365356 -4.890625q0.609375 0 1.140625 0.1875q0.53125 0.171875 0.90625 0.515625q0.390625 0.34375 0.609375 0.84375q0.21875 0.484375 0.21875 1.109375q0 0.53125 -0.171875 0.984375q-0.15625 0.453125 -0.4375 0.875q-0.265625 0.421875 -0.625 0.8125q-0.34375 0.390625 -0.75 0.796875l-2.515625 2.5625q0.265625 -0.078125 0.53125 -0.109375q0.28125 -0.046875 0.53125 -0.046875l3.203125 0q0.203125 0 0.3125 0.109375q0.109375 0.109375 0.109375 0.296875l0 0.71875l-6.375 0l0 -0.40625q0 -0.125 0.046875 -0.25q0.0625 -0.140625 0.171875 -0.25l3.0625 -3.078125q0.375 -0.390625 0.6875 -0.734375q0.3125 -0.359375 0.53125 -0.71875q0.234375 -0.359375 0.34375 -0.734375q0.125 -0.375 0.125 -0.796875q0 -0.421875 -0.140625 -0.734375q-0.125 -0.3125 -0.359375 -0.515625q-0.234375 -0.21875 -0.546875 -0.3125q-0.3125 -0.109375 -0.671875 -0.109375q-0.359375 0 -0.671875 0.109375q-0.296875 0.109375 -0.53125 0.296875q-0.234375 0.1875 -0.40625 0.453125q-0.15625 0.25 -0.234375 0.578125q-0.046875 0.1875 -0.15625 0.28125q-0.109375 0.078125 -0.28125 0.078125q-0.03125 0 -0.078125 0q-0.03125 0 -0.078125 -0.015625l-0.609375 -0.109375q0.09375 -0.640625 0.359375 -1.140625q0.265625 -0.515625 0.671875 -0.84375q0.40625 -0.34375 0.9375 -0.515625q0.53125 -0.1875 1.140625 -0.1875zm9.745911 6.21875l1.453125 0l0 0.671875q0 0.109375 -0.0625 0.1875q-0.0625 0.0625 -0.203125 0.0625l-1.1875 0l0 2.515625l-1.046875 0l0 -2.515625l-4.234375 0q-0.125 0 -0.234375 -0.078125q-0.09375 -0.078125 -0.109375 -0.1875l-0.125 -0.609375l4.640625 -6.15625l1.109375 0l0 6.109375zm-1.046875 -3.953125q0 -0.171875 0 -0.359375q0.015625 -0.203125 0.0625 -0.421875l-3.484375 4.734375l3.421875 0l0 -3.953125z" fill-rule="nonzero"/></g></svg>
\ No newline at end of file
diff --git a/gopls/doc/design/implementation.md b/gopls/doc/design/implementation.md
index f8d734f..12d655c 100644
--- a/gopls/doc/design/implementation.md
+++ b/gopls/doc/design/implementation.md
@@ -1,46 +1,172 @@
-# gopls implementation documentation
 
-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.
-Instead this is meant to be a guide into finding parts of the implementation, and understanding some core concepts used throughout the implementation.
+# Gopls architecture
 
-## View/Session/Cache
+Last major update: Jan 16 2024
 
-Throughout the code there are references to these three concepts, and they build on each other.
+This doc presents a high-level overview of the structure of gopls to
+help new contributors find their way. It is not intended to be a
+complete description of the implementation, nor even of any key
+components; for that, the package documentation (linked below) and
+other comments within the code are a better guide.
 
-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.
+The diagram below shows selected components of the gopls module and
+their relationship to each other according to the Go import graph.
+Tests and test infrastructure are not shown, nor are utility packages,
+nor packages from the [x/tools] module. For brevity, packages are
+referred to by their last segment, which is usually unambiguous.
 
-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).
+The height of each blob corresponds loosely to its technical depth.
+Some blocks are wide and shallow, such as [protocol], which declares
+Go types for the entire LSP protocol. Others are deep, such as [cache]
+and [golang], as they contain a lot of dense logic and algorithms.
 
-The top layer is called the *View*. This holds the configuration, and the mapping to configured packages.
+<!-- Source: https://docs.google.com/drawings/d/1CK6YSLt7G3svRoZf7skJI-lxRol2VI90YOxHcYS0DP4 -->
+![Gopls architecture](architecture.svg)
 
-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.
-In theory if only the View layer existed, the results would be identical, but slower and using more memory.
+Starting from the bottom, we'll describe the various components.
 
-## Code location
+The lowest layer defines the request and response types of the
+Language Server Protocol:
 
-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].
+- The [protocol] package defines the standard protocol; it is mostly
+  generated mechanically from the schema definition provided by
+  Microsoft.
+  The most important type is DocumentURI, which represents a `file:`
+  URL that identifies a client editor document. It also provides
+  `Mapper`, which maps between the different coordinate systems used
+  for source positions: UTF-8, UTF-16, and token.Pos.
 
-Below is a list of the core packages of gopls, and their primary purpose:
+- The [command] package defines Gopls's non-standard commands, which
+  are all invoked through the `workspace/executeCommand` extension
+  mechanism. These commands are typically returned by the server as
+  continuations of Code Actions or Code Lenses; most clients do not
+  construct calls to them directly.
 
-Package | Description
---- | ---
-[gopls] | the main binary, plugins and integration tests
-[internal/lsp] | the core message handling package
-[internal/lsp/cache] | the cache layer
-[internal/cmd] | the gopls command line layer
-[internal/debug] | features to aid in debugging gopls
-[internal/lsp/protocol] | the types of LSP request and response messages
-[internal/lsp/source] | the core feature implementations
-[internal/memoize] | a function invocation cache used to reduce the work done
-[internal/jsonrpc2] | an implementation of the JSON RPC2 specification
+The next layer defines a number of important and very widely used data structures:
 
-[gopls]: https://github.com/golang/tools/tree/master/gopls
-[internal/jsonrpc2]: https://github.com/golang/tools/tree/master/internal/jsonrpc2
-[internal/lsp]: https://github.com/golang/tools/tree/master/gopls/internal/lsp
-[internal/lsp/cache]: https://github.com/golang/tools/tree/master/gopls/internal/lsp/cache
-[internal/cmd]: https://github.com/golang/tools/tree/master/gopls/internal/cmd
-[internal/debug]: https://github.com/golang/tools/tree/master/gopls/internal/lsp/debug
-[internal/lsp/source]: https://github.com/golang/tools/tree/master/gopls/internal/lsp/source
-[internal/memoize]: https://github.com/golang/tools/tree/master/internal/memoize
-[internal/lsp/protocol]: https://github.com/golang/tools/tree/master/gopls/internal/lsp/protocol
-[x/tools]: https://github.com/golang/tools
+- The [file] package defines the primary abstractions of a client
+  file: its `Identity` (URI and content hash), and its `Handle` (which
+  additionally provides the version and content of a particular
+  snapshot of the file.
+
+- The [parsego] package defines `File`, the parsed form of a Go source
+  file, including its content, syntax tree, and coordinary mappings
+  (Mapper and token.File). The package performs various kinds of tree
+  repair to work around error-recovery shortcomings of the Go parser.
+
+- The [metadata] package defines `Package`, an abstraction of the
+  metadata of a Go package, similar to the output of `go list -json`.
+  Metadata is produced from [go/packages], which takes
+  care of invoking `go list`. (Users report that it works to some extent
+  with a GOPACKAGESDRIVER for Bazel, though we maintain no tests for this
+  scenario.)
+
+  The package also provides `Graph`, the complete import graph for a
+  workspace; each graph node is a `Package`.
+
+The [settings] layer defines the data structure (effectively a large
+tree) for gopls configuration options, along with its JSON encoding.
+
+The [cache] layer is the largest and most complex component of gopls.
+It is concerned with state management, dependency analysis, and invalidation:
+the `Session` of communication with the client;
+the `Folder`s that the client has opened;
+the `View` of a particular workspace tree with particular build
+options;
+the `Snapshot` of the state of all files in the workspace after a
+particular edit operation;
+the contents of all files, whether saved to disk (`DiskFile`) or
+edited and unsaved (`Overlay`);
+the `Cache` of in-memory memoized computations,
+such as parsing go.mod files or build the symbol index;
+and the `Package`, which holds the results of type checking a package
+from Go syntax.
+
+The cache layer depends on various auxiliary packages, including:
+
+- The [filecache] package, which manages gopls' persistent, transactional,
+  file-based key/value store.
+  
+- The [xrefs], [methodsets], and [typerefs] packages define algorithms
+  for constructing indexes of information derived from type-checking,
+  and for encoding and decoding these serializable indexes in the file
+  cache.
+
+  Together these packages enable the fast restart, reduced memory
+  consumption, and synergy across processes that were delivered by the
+  v0.12 redesign and described in ["Scaling gopls for the growing Go
+  ecosystem"](https://go.dev/blog/gopls-scalability).
+
+The cache also defines gopls's [go/analysis] driver, which runs
+modular analysis (similar to `go vet`) across the workspace.
+Gopls also includes a number of analysis passes that are not part of vet.
+
+The next layer defines four packages, each for handling files in a
+particular language:
+[mod] for go.mod files;
+[work] for go.work files;
+[template] for files in `text/template` syntax; and
+[golang], for files in Go itself.
+This package, by far the largest, provides the main features of gopls:
+navigation, analysis, and refactoring of Go code.
+As most users imagine it, this package _is_ gopls.
+
+The [server] package defines the LSP service implementation, with one
+handler method per LSP request type. Each handler switches on the type
+of the file and dispatches to one of the four language-specific
+packages.
+
+The [lsprpc] package connects the service interface to our [JSON RPC](jsonrpc2)
+server.
+
+Bear in mind that the diagram is a dependency graph, a "static"
+viewpoint of the program's structure. A more dynamic viewpoint would
+order the packages based on the sequence in which they are encountered
+during processing of a particular request; in such a view, the bottom
+layer would represent the "wire" (protocol and command), the next
+layer up would hold the RPC-related packages (lsprpc and server), and
+features (e.g. golang, mod, work, template) would be at the top.
+
+<!--
+A dynamic view would be an interesting topic for another article.
+This slide deck [requires Google network]
+The Life of a (gopls) Query (Oct 2021)
+https://docs.google.com/presentation/d/1c8XJaIldzii-F3YvEOPWHK_MQJ_o8ua5Bct1yDa3ZlU
+provides useful (if somewhat out of date) information.
+-->
+
+The [cmd] package defines the command-line interface of the `gopls`
+command, around which gopls's main package is just a trivial wrapper.
+It is usually run without arguments, causing it to start a server and
+listen indefinitely.
+It also provides a number of subcommands that start a server, make a
+single request to it, and exit, providing traditional batch-command
+access to server functionality. These subcommands are primarily
+provided as a debugging aid (but see
+[#63693](https://github.com/golang/go/issues/63693)).
+
+[cache]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache
+[cmd]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cmd
+[command]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/protocol/command
+[debug]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/debug
+[file]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/file
+[filecache]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/filecache
+[go/analysis]: https://pkg.go.dev/golang.org/x/tools@master/go/analysis
+[go/packages]: https://pkg.go.dev/golang.org/x/tools@master/go/packages
+[gopls]: https://pkg.go.dev/golang.org/x/tools/gopls@master
+[jsonrpc2]: https://pkg.go.dev/golang.org/x/tools@master/internal/jsonrpc2
+[lsprpc]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsprpc
+[memoize]: https://github.com/golang/tools/tree/master/internal/memoize
+[metadata]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/metadata
+[methodsets]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/methodsets
+[mod]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/mod
+[parsego]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/parsego
+[protocol]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/protocol
+[server]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/server
+[settings]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/settings
+[golang]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/golang
+[template]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/template
+[typerefs]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/typerefs
+[work]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/work
+[x/tools]: https://github.com/golang/tools@master
+[xrefs]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/xrefs
diff --git a/gopls/doc/design/integrating.md b/gopls/doc/design/integrating.md
index 3448402..2d8e01a 100644
--- a/gopls/doc/design/integrating.md
+++ b/gopls/doc/design/integrating.md
@@ -59,9 +59,9 @@
 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`].
 This is currently being added to gopls by a community member, and tracked in [#31553]
 
-[InitializeResult]: https://pkg.go.dev/golang.org/x/tools/gopls/internal/lsp/protocol#InitializeResult
-[ServerCapabilities]: https://pkg.go.dev/golang.org/x/tools/gopls/internal/lsp/protocol#ServerCapabilities
-[`golang.org/x/tools/gopls/internal/lsp/protocol`]: https://pkg.go.dev/golang.org/x/tools/internal/lsp/protocol#NewPoint
+[InitializeResult]: https://pkg.go.dev/golang.org/x/tools/gopls/internal/protocol#InitializeResult
+[ServerCapabilities]: https://pkg.go.dev/golang.org/x/tools/gopls/internal/protocol#ServerCapabilities
+[`golang.org/x/tools/gopls/internal/protocol`]: https://pkg.go.dev/golang.org/x/tools/internal/protocol#NewPoint
 
 [LSP specification]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/
 [lsp-response]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#response-message
diff --git a/gopls/doc/emacs.md b/gopls/doc/emacs.md
index 486f493..8a54cf1 100644
--- a/gopls/doc/emacs.md
+++ b/gopls/doc/emacs.md
@@ -144,12 +144,14 @@
 (or a key of your choice bound to the `eglot-code-actions` function) and
 selecting `Organize Imports` at the prompt.
 
-Eglot does not currently support a standalone function to execute a specific
-code action (see
-[joaotavora/eglot#411](https://github.com/joaotavora/eglot/issues/411)), nor an
-option to organize imports as a `before-save-hook` (see
-[joaotavora/eglot#574](https://github.com/joaotavora/eglot/issues/574)). In the
-meantime, see those issues for discussion and possible workarounds.
+To automatically organize imports before saving, add a hook:
+
+```elisp
+(add-hook 'before-save-hook
+    (lambda ()
+        (call-interactively 'eglot-code-action-organize-imports))
+    nil t)
+```
 
 ## Troubleshooting
 
diff --git a/gopls/doc/generate.go b/gopls/doc/generate.go
index ee5c52b..c7d1226 100644
--- a/gopls/doc/generate.go
+++ b/gopls/doc/generate.go
@@ -32,10 +32,10 @@
 	"github.com/jba/printsrc"
 	"golang.org/x/tools/go/ast/astutil"
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/command/commandmeta"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
 	"golang.org/x/tools/gopls/internal/mod"
+	"golang.org/x/tools/gopls/internal/protocol/command"
+	"golang.org/x/tools/gopls/internal/protocol/command/commandmeta"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 )
@@ -108,12 +108,13 @@
 	}
 	pkg := pkgs[0]
 
-	api := &settings.APIJSON{
-		Options: map[string][]*settings.OptionJSON{},
-	}
 	defaults := settings.DefaultOptions()
+	api := &settings.APIJSON{
+		Options:   map[string][]*settings.OptionJSON{},
+		Analyzers: loadAnalyzers(defaults.DefaultAnalyzers), // no staticcheck analyzers
+	}
 
-	api.Commands, err = loadCommands(pkg)
+	api.Commands, err = loadCommands()
 	if err != nil {
 		return nil, err
 	}
@@ -123,15 +124,7 @@
 	for _, c := range api.Commands {
 		c.Command = command.ID(c.Command)
 	}
-	for _, m := range []map[string]*settings.Analyzer{
-		defaults.DefaultAnalyzers,
-		defaults.TypeErrorAnalyzers,
-		defaults.ConvenienceAnalyzers,
-		// Don't yet add staticcheck analyzers.
-	} {
-		api.Analyzers = append(api.Analyzers, loadAnalyzers(m)...)
-	}
-	api.Hints = loadHints(source.AllInlayHints)
+	api.Hints = loadHints(golang.AllInlayHints)
 	for _, category := range []reflect.Value{
 		reflect.ValueOf(defaults.UserOptions),
 	} {
@@ -410,7 +403,7 @@
 	return fmt.Sprintf("`%s`: %s", value, doc)
 }
 
-func loadCommands(pkg *packages.Package) ([]*settings.CommandJSON, error) {
+func loadCommands() ([]*settings.CommandJSON, error) {
 	var commands []*settings.CommandJSON
 
 	_, cmds, err := commandmeta.Load()
@@ -488,7 +481,7 @@
 
 func loadLenses(commands []*settings.CommandJSON) []*settings.LensJSON {
 	all := map[command.Command]struct{}{}
-	for k := range source.LensFuncs() {
+	for k := range golang.LensFuncs() {
 		all[k] = struct{}{}
 	}
 	for k := range mod.LensFuncs() {
@@ -531,7 +524,7 @@
 	return json
 }
 
-func loadHints(m map[string]*source.Hint) []*settings.HintJSON {
+func loadHints(m map[string]*golang.Hint) []*settings.HintJSON {
 	var sorted []string
 	for _, h := range m {
 		sorted = append(sorted, h.Name)
diff --git a/gopls/doc/helix.md b/gopls/doc/helix.md
new file mode 100644
index 0000000..83f923d
--- /dev/null
+++ b/gopls/doc/helix.md
@@ -0,0 +1,51 @@
+# Helix
+
+Configuring `gopls` to work with Helix is rather straightforward. Install `gopls`, and then add it to the `PATH` variable. If it is in the `PATH` variable, Helix will be able to detect it automatically.
+
+The documentation explaining how to install the default language servers for Helix can be found [here](https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers)
+
+## Installing `gopls`
+
+The first step is to install `gopls` on your machine.
+You can follow installation instructions [here](https://github.com/golang/tools/tree/master/gopls#installation).
+
+## Setting your path to include `gopls`
+
+Set your `PATH` environment variable to point to `gopls`.
+If you used `go install` to download `gopls`, it should be in `$GOPATH/bin`.
+If you don't have `GOPATH` set, you can use `go env GOPATH` to find it.
+
+## Additional information
+
+You can find more information about how to set up the LSP formatter [here](https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers#autoformatting).
+
+It is possible to use `hx --health go` to see that the language server is properly set up.
+
+### Configuration
+
+The settings for `gopls` can be configured in the `languages.toml` file.
+The official Helix documentation for this can be found [here](https://docs.helix-editor.com/languages.html)
+
+Configuration pertaining to `gopls` should be in the table `language-server.gopls`.
+
+#### How to set flags
+
+To set flags, add them to the `args` array in the `language-server.gopls` section of the `languages.toml` file.
+
+#### How to set LSP configuration
+
+Configuration options can be set in the `language-server.gopls.config` section of the `languages.toml` file, or in the `config` key of the `language-server.gopls` section of the `languages.toml` file.
+
+#### A minimal config example
+
+In the `~/.config/helix/languages.toml` file, the following snippet would set up `gopls` with a logfile located at `/tmp/gopls.log` and enable staticcheck.
+
+```toml
+[language-server.gopls]
+command = "gopls"
+args = ["-logfile=/tmp/gopls.log",  "serve"]
+[language-server.gopls.config]
+"ui.diagnostic.staticcheck" = true
+```
+
+
diff --git a/gopls/doc/settings.md b/gopls/doc/settings.md
index d6ec1df..9f692cf 100644
--- a/gopls/doc/settings.md
+++ b/gopls/doc/settings.md
@@ -1,6 +1,6 @@
 # Settings
 
-<!--TODO: Generate this file from the documentation in golang.org/x/tools/gopls/internal/lsp/source/options.go.-->
+<!--TODO: Generate this file from the documentation in golang.org/x/tools/gopls/internal/golang/options.go.-->
 
 This document describes the global settings for `gopls` inside the editor.
 The settings block will be called `"gopls"` and contains a collection of
@@ -286,7 +286,7 @@
 ...
 "analyses": {
   "unreachable": false, // Disable the unreachable analyzer.
-  "unusedparams": true  // Enable the unusedparams analyzer.
+  "unusedvariable": true  // Enable the unusedvariable analyzer.
 }
 ...
 ```
diff --git a/gopls/go.mod b/gopls/go.mod
index 3eabeef..bafca53 100644
--- a/gopls/go.mod
+++ b/gopls/go.mod
@@ -3,26 +3,28 @@
 go 1.18
 
 require (
-	github.com/google/go-cmp v0.5.9
+	github.com/google/go-cmp v0.6.0
 	github.com/jba/printsrc v0.2.2
 	github.com/jba/templatecheck v0.6.0
 	golang.org/x/mod v0.14.0
-	golang.org/x/sync v0.5.0
-	golang.org/x/telemetry v0.0.0-20231114163143-69313e640400
+	golang.org/x/sync v0.6.0
+	golang.org/x/telemetry v0.0.0-20240201224847-0a1d30dda509
 	golang.org/x/text v0.14.0
-	golang.org/x/tools v0.16.2-0.20240105173808-36a523fefd90
+	golang.org/x/tools v0.17.0
 	golang.org/x/vuln v1.0.1
 	gopkg.in/yaml.v3 v3.0.1
-	honnef.co/go/tools v0.4.5
-	mvdan.cc/gofumpt v0.4.0
-	mvdan.cc/xurls/v2 v2.4.0
+	honnef.co/go/tools v0.4.6
+	mvdan.cc/gofumpt v0.6.0
+	mvdan.cc/xurls/v2 v2.5.0
 )
 
 require (
 	github.com/BurntSushi/toml v1.2.1 // indirect
 	github.com/google/safehtml v0.1.0 // indirect
 	golang.org/x/exp/typeparams v0.0.0-20221212164502-fae10dda9338 // indirect
-	golang.org/x/sys v0.15.0 // indirect
+	golang.org/x/sys v0.16.0 // indirect
 	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
 
 )
+
+replace golang.org/x/tools => ../
diff --git a/gopls/go.sum b/gopls/go.sum
index 1f982dd..89bac97 100644
--- a/gopls/go.sum
+++ b/gopls/go.sum
@@ -1,8 +1,8 @@
 github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
 github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
-github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
-github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/safehtml v0.0.2/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU=
 github.com/google/safehtml v0.1.0 h1:EwLKo8qawTKfsi0orxcQAZzu07cICaBeFMegAU9eaT8=
 github.com/google/safehtml v0.1.0/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU=
@@ -10,43 +10,35 @@
 github.com/jba/printsrc v0.2.2/go.mod h1:1xULjw59sL0dPdWpDoVU06TIEO/Wnfv6AHRpiElTwYM=
 github.com/jba/templatecheck v0.6.0 h1:SwM8C4hlK/YNLsdcXStfnHWE2HKkuTVwy5FKQHt5ro8=
 github.com/jba/templatecheck v0.6.0/go.mod h1:/1k7EajoSErFI9GLHAsiIJEaNLt3ALKNw2TV7z2SYv4=
-github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
-github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
-github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
 golang.org/x/exp/typeparams v0.0.0-20221212164502-fae10dda9338 h1:2O2DON6y3XMJiQRAS1UWU+54aec2uopH3x7MAiqGW6Y=
 golang.org/x/exp/typeparams v0.0.0-20221212164502-fae10dda9338/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
 golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
 golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
-golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/telemetry v0.0.0-20231114163143-69313e640400 h1:brbkEFfGwNGAEkykUOcryE/JiHUMMJouzE0fWWmz/QU=
-golang.org/x/telemetry v0.0.0-20231114163143-69313e640400/go.mod h1:P6hMdmAcoG7FyATwqSr6R/U0n7yeXNP/QXeRlxb1szE=
+golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
+golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/telemetry v0.0.0-20240201224847-0a1d30dda509 h1:Nr7eTQpQZ/ytesxDJpQgaf0t4sdLnnDtAbmtViTrSUo=
+golang.org/x/telemetry v0.0.0-20240201224847-0a1d30dda509/go.mod h1:ZthVHHkOi8rlMEsfFr3Ie42Ym1NonbFNNRKW3ci0UrU=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.16.2-0.20240105173808-36a523fefd90 h1:3dw2Y1Aes2o83VYvSZSPc+p70AuT9zvNCTBHCvUUZrE=
-golang.org/x/tools v0.16.2-0.20240105173808-36a523fefd90/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
+golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
+golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
 golang.org/x/vuln v1.0.1 h1:KUas02EjQK5LTuIx1OylBQdKKZ9jeugs+HiqO5HormU=
 golang.org/x/vuln v1.0.1/go.mod h1:bb2hMwln/tqxg32BNY4CcxHWtHXuYa3SbIBmtsyjxtM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-honnef.co/go/tools v0.4.5 h1:YGD4H+SuIOOqsyoLOpZDWcieM28W47/zRO7f+9V3nvo=
-honnef.co/go/tools v0.4.5/go.mod h1:GUV+uIBCLpdf0/v6UhHHG/yzI/z6qPskBeQCjcNB96k=
-mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM=
-mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ=
-mvdan.cc/xurls/v2 v2.4.0 h1:tzxjVAj+wSBmDcF6zBB7/myTy3gX9xvi8Tyr28AuQgc=
-mvdan.cc/xurls/v2 v2.4.0/go.mod h1:+GEjq9uNjqs8LQfM9nVnM8rff0OQ5Iash5rzX+N1CSg=
+honnef.co/go/tools v0.4.6 h1:oFEHCKeID7to/3autwsWfnuv69j3NsfcXbvJKuIcep8=
+honnef.co/go/tools v0.4.6/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0=
+mvdan.cc/gofumpt v0.6.0 h1:G3QvahNDmpD+Aek/bNOLrFR2XC6ZAdo62dZu65gmwGo=
+mvdan.cc/gofumpt v0.6.0/go.mod h1:4L0wf+kgIPZtcCWXynNS2e6bhmj73umwnuXSZarixzA=
+mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
+mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE=
diff --git a/gopls/internal/analysis/embeddirective/doc.go b/gopls/internal/analysis/embeddirective/doc.go
index f8cc69f..bfed47f 100644
--- a/gopls/internal/analysis/embeddirective/doc.go
+++ b/gopls/internal/analysis/embeddirective/doc.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // Package embeddirective defines an Analyzer that validates //go:embed directives.
-// The analyzer defers fixes to its parent source.Analyzer.
+// The analyzer defers fixes to its parent golang.Analyzer.
 //
 // # Analyzer embed
 //
diff --git a/gopls/internal/analysis/embeddirective/embeddirective.go b/gopls/internal/analysis/embeddirective/embeddirective.go
index 20d3cbf..2e41563 100644
--- a/gopls/internal/analysis/embeddirective/embeddirective.go
+++ b/gopls/internal/analysis/embeddirective/embeddirective.go
@@ -26,9 +26,7 @@
 	URL:              "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/embeddirective",
 }
 
-// source.fixedByImportingEmbed relies on this message to filter
-// out fixable diagnostics from this Analyzer.
-const MissingImportMessage = `must import "embed" when using go:embed directives`
+const FixCategory = "addembedimport" // recognized by gopls ApplyFix
 
 func run(pass *analysis.Pass) (interface{}, error) {
 	for _, f := range pass.Files {
@@ -46,28 +44,39 @@
 		}
 
 		for _, c := range comments {
-			report := func(msg string) {
+			pos, end := c.Pos(), c.Pos()+token.Pos(len("//go:embed"))
+
+			if !hasEmbedImport {
 				pass.Report(analysis.Diagnostic{
-					Pos:     c.Pos(),
-					End:     c.Pos() + token.Pos(len("//go:embed")),
-					Message: msg,
+					Pos:      pos,
+					End:      end,
+					Message:  `must import "embed" when using go:embed directives`,
+					Category: FixCategory,
+					SuggestedFixes: []analysis.SuggestedFix{{
+						Message: `Add missing "embed" import`,
+						// No TextEdits => computed by a gopls command.
+					}},
 				})
 			}
 
-			if !hasEmbedImport {
-				report(MissingImportMessage)
-			}
-
+			var msg string
 			spec := nextVarSpec(c, f)
 			switch {
 			case spec == nil:
-				report(`go:embed directives must precede a "var" declaration`)
+				msg = `go:embed directives must precede a "var" declaration`
 			case len(spec.Names) != 1:
-				report("declarations following go:embed directives must define a single variable")
+				msg = "declarations following go:embed directives must define a single variable"
 			case len(spec.Values) > 0:
-				report("declarations following go:embed directives must not specify a value")
+				msg = "declarations following go:embed directives must not specify a value"
 			case !embeddableType(pass.TypesInfo.Defs[spec.Names[0]]):
-				report("declarations following go:embed directives must be of type string, []byte or embed.FS")
+				msg = "declarations following go:embed directives must be of type string, []byte or embed.FS"
+			}
+			if msg != "" {
+				pass.Report(analysis.Diagnostic{
+					Pos:     pos,
+					End:     end,
+					Message: msg,
+				})
 			}
 		}
 	}
diff --git a/gopls/internal/analysis/fillstruct/fillstruct.go b/gopls/internal/analysis/fillstruct/fillstruct.go
index e2337a1..1f8183f 100644
--- a/gopls/internal/analysis/fillstruct/fillstruct.go
+++ b/gopls/internal/analysis/fillstruct/fillstruct.go
@@ -23,7 +23,6 @@
 	"unicode"
 
 	"golang.org/x/tools/go/analysis"
-	"golang.org/x/tools/go/analysis/passes/inspect"
 	"golang.org/x/tools/go/ast/astutil"
 	"golang.org/x/tools/go/ast/inspector"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
@@ -31,41 +30,14 @@
 	"golang.org/x/tools/internal/fuzzy"
 )
 
-const Doc = `note incomplete struct initializations
-
-This analyzer provides diagnostics for any struct literals that do not have
-any fields initialized. Because the suggested fix for this analysis is
-expensive to compute, callers should compute it separately, using the
-SuggestedFix function below.
-`
-
-var Analyzer = &analysis.Analyzer{
-	Name:             "fillstruct",
-	Doc:              Doc,
-	Requires:         []*analysis.Analyzer{inspect.Analyzer},
-	Run:              run,
-	URL:              "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillstruct",
-	RunDespiteErrors: true,
-}
-
-// TODO(rfindley): remove this thin wrapper around the fillstruct refactoring,
-// and eliminate the fillstruct analyzer.
+// Diagnose computes diagnostics for fillable struct literals overlapping with
+// the provided start and end position.
 //
-// Previous iterations used the analysis framework for computing refactorings,
-// which proved inefficient.
-func run(pass *analysis.Pass) (interface{}, error) {
-	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
-	for _, d := range DiagnoseFillableStructs(inspect, token.NoPos, token.NoPos, pass.Pkg, pass.TypesInfo) {
-		pass.Report(d)
-	}
-	return nil, nil
-}
-
-// DiagnoseFillableStructs computes diagnostics for fillable struct composite
-// literals overlapping with the provided start and end position.
+// The diagnostic contains a lazy fix; the actual patch is computed
+// (via the ApplyFix command) by a call to [SuggestedFix].
 //
-// If either start or end is invalid, it is considered an unbounded condition.
-func DiagnoseFillableStructs(inspect *inspector.Inspector, start, end token.Pos, pkg *types.Package, info *types.Info) []analysis.Diagnostic {
+// If either start or end is invalid, the entire package is inspected.
+func Diagnose(inspect *inspector.Inspector, start, end token.Pos, pkg *types.Package, info *types.Info) []analysis.Diagnostic {
 	var diags []analysis.Diagnostic
 	nodeFilter := []ast.Node{(*ast.CompositeLit)(nil)}
 	inspect.Preorder(nodeFilter, func(n ast.Node) {
@@ -130,18 +102,25 @@
 			if i < totalFields {
 				fillableFields = append(fillableFields, "...")
 			}
-			name = fmt.Sprintf("anonymous struct { %s }", strings.Join(fillableFields, ", "))
+			name = fmt.Sprintf("anonymous struct{ %s }", strings.Join(fillableFields, ", "))
 		}
 		diags = append(diags, analysis.Diagnostic{
-			Message: fmt.Sprintf("Fill %s", name),
-			Pos:     expr.Pos(),
-			End:     expr.End(),
+			Message:  fmt.Sprintf("%s literal has missing fields", name),
+			Pos:      expr.Pos(),
+			End:      expr.End(),
+			Category: FixCategory,
+			SuggestedFixes: []analysis.SuggestedFix{{
+				Message: fmt.Sprintf("Fill %s", name),
+				// No TextEdits => computed later by gopls.
+			}},
 		})
 	})
 
 	return diags
 }
 
+const FixCategory = "fillstruct" // recognized by gopls ApplyFix
+
 // SuggestedFix computes the suggested fix for the kinds of
 // diagnostics produced by the Analyzer above.
 func SuggestedFix(fset *token.FileSet, start, end token.Pos, content []byte, file *ast.File, pkg *types.Package, info *types.Info) (*token.FileSet, *analysis.SuggestedFix, error) {
diff --git a/gopls/internal/analysis/fillstruct/fillstruct_test.go b/gopls/internal/analysis/fillstruct/fillstruct_test.go
index 39fc81f..f90998f 100644
--- a/gopls/internal/analysis/fillstruct/fillstruct_test.go
+++ b/gopls/internal/analysis/fillstruct/fillstruct_test.go
@@ -5,13 +5,34 @@
 package fillstruct_test
 
 import (
+	"go/token"
 	"testing"
 
+	"golang.org/x/tools/go/analysis"
 	"golang.org/x/tools/go/analysis/analysistest"
+	"golang.org/x/tools/go/analysis/passes/inspect"
+	"golang.org/x/tools/go/ast/inspector"
 	"golang.org/x/tools/gopls/internal/analysis/fillstruct"
 )
 
+// analyzer allows us to test the fillstruct code action using the analysistest
+// harness. (fillstruct used to be a gopls analyzer.)
+var analyzer = &analysis.Analyzer{
+	Name:     "fillstruct",
+	Doc:      "test only",
+	Requires: []*analysis.Analyzer{inspect.Analyzer},
+	Run: func(pass *analysis.Pass) (any, error) {
+		inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+		for _, d := range fillstruct.Diagnose(inspect, token.NoPos, token.NoPos, pass.Pkg, pass.TypesInfo) {
+			pass.Report(d)
+		}
+		return nil, nil
+	},
+	URL:              "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillstruct",
+	RunDespiteErrors: true,
+}
+
 func Test(t *testing.T) {
 	testdata := analysistest.TestData()
-	analysistest.Run(t, testdata, fillstruct.Analyzer, "a", "typeparams")
+	analysistest.Run(t, testdata, analyzer, "a", "typeparams")
 }
diff --git a/gopls/internal/analysis/fillstruct/testdata/src/a/a.go b/gopls/internal/analysis/fillstruct/testdata/src/a/a.go
index 9ee3860..79c51d2 100644
--- a/gopls/internal/analysis/fillstruct/testdata/src/a/a.go
+++ b/gopls/internal/analysis/fillstruct/testdata/src/a/a.go
@@ -19,16 +19,16 @@
 	foo int
 }
 
-var _ = basicStruct{} // want `Fill basicStruct`
+var _ = basicStruct{} // want `basicStruct literal has missing fields`
 
 type twoArgStruct struct {
 	foo int
 	bar string
 }
 
-var _ = twoArgStruct{} // want `Fill twoArgStruct`
+var _ = twoArgStruct{} // want `twoArgStruct literal has missing fields`
 
-var _ = twoArgStruct{ // want `Fill twoArgStruct`
+var _ = twoArgStruct{ // want `twoArgStruct literal has missing fields`
 	bar: "bar",
 }
 
@@ -37,9 +37,9 @@
 	basic basicStruct
 }
 
-var _ = nestedStruct{} // want `Fill nestedStruct`
+var _ = nestedStruct{} // want `nestedStruct literal has missing fields`
 
-var _ = data.B{} // want `Fill b.B`
+var _ = data.B{} // want `b.B literal has missing fields`
 
 type typedStruct struct {
 	m  map[string]int
@@ -49,25 +49,25 @@
 	a  [2]string
 }
 
-var _ = typedStruct{} // want `Fill typedStruct`
+var _ = typedStruct{} // want `typedStruct literal has missing fields`
 
 type funStruct struct {
 	fn func(i int) int
 }
 
-var _ = funStruct{} // want `Fill funStruct`
+var _ = funStruct{} // want `funStruct literal has missing fields`
 
 type funStructComplex struct {
 	fn func(i int, s string) (string, int)
 }
 
-var _ = funStructComplex{} // want `Fill funStructComplex`
+var _ = funStructComplex{} // want `funStructComplex literal has missing fields`
 
 type funStructEmpty struct {
 	fn func()
 }
 
-var _ = funStructEmpty{} // want `Fill funStructEmpty`
+var _ = funStructEmpty{} // want `funStructEmpty literal has missing fields`
 
 type Foo struct {
 	A int
@@ -78,7 +78,7 @@
 	Y *Foo
 }
 
-var _ = Bar{} // want `Fill Bar`
+var _ = Bar{} // want `Bar literal has missing fields`
 
 type importedStruct struct {
 	m  map[*ast.CompositeLit]ast.Field
@@ -89,7 +89,7 @@
 	st ast.CompositeLit
 }
 
-var _ = importedStruct{} // want `Fill importedStruct`
+var _ = importedStruct{} // want `importedStruct literal has missing fields`
 
 type pointerBuiltinStruct struct {
 	b *bool
@@ -97,17 +97,16 @@
 	i *int
 }
 
-var _ = pointerBuiltinStruct{} // want `Fill pointerBuiltinStruct`
+var _ = pointerBuiltinStruct{} // want `pointerBuiltinStruct literal has missing fields`
 
 var _ = []ast.BasicLit{
-	{}, // want `Fill go/ast.BasicLit`
+	{}, // want `go/ast.BasicLit literal has missing fields`
 }
 
-var _ = []ast.BasicLit{{}, // want "go/ast.BasicLit"
-}
+var _ = []ast.BasicLit{{}} // want "go/ast.BasicLit literal has missing fields"
 
 type unsafeStruct struct {
 	foo unsafe.Pointer
 }
 
-var _ = unsafeStruct{} // want `Fill unsafeStruct`
+var _ = unsafeStruct{} // want `unsafeStruct literal has missing fields`
diff --git a/gopls/internal/analysis/fillstruct/testdata/src/typeparams/typeparams.go b/gopls/internal/analysis/fillstruct/testdata/src/typeparams/typeparams.go
index 46bb8ae..d9e3da4 100644
--- a/gopls/internal/analysis/fillstruct/testdata/src/typeparams/typeparams.go
+++ b/gopls/internal/analysis/fillstruct/testdata/src/typeparams/typeparams.go
@@ -12,16 +12,16 @@
 	foo T
 }
 
-var _ = basicStruct[int]{} // want `Fill basicStruct\[int\]`
+var _ = basicStruct[int]{} // want `basicStruct\[int\] literal has missing fields`
 
 type twoArgStruct[F, B any] struct {
 	foo F
 	bar B
 }
 
-var _ = twoArgStruct[string, int]{} // want `Fill twoArgStruct\[string, int\]`
+var _ = twoArgStruct[string, int]{} // want `twoArgStruct\[string, int\] literal has missing fields`
 
-var _ = twoArgStruct[int, string]{ // want `Fill twoArgStruct\[int, string\]`
+var _ = twoArgStruct[int, string]{ // want `twoArgStruct\[int, string\] literal has missing fields`
 	bar: "bar",
 }
 
@@ -30,11 +30,11 @@
 	basic basicStruct[int]
 }
 
-var _ = nestedStruct{} // want "Fill nestedStruct"
+var _ = nestedStruct{} // want "nestedStruct literal has missing fields"
 
 func _[T any]() {
 	type S struct{ t T }
-	x := S{} // want "Fill S"
+	x := S{} // want "S"
 	_ = x
 }
 
@@ -42,7 +42,7 @@
 	var tests = []struct {
 		a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p string
 	}{
-		{}, // want "Fill anonymous struct { a: string, b: string, c: string, ... }"
+		{}, // want "anonymous struct{ a: string, b: string, c: string, ... } literal has missing fields"
 	}
 	for _, test := range tests {
 		_ = test
diff --git a/gopls/internal/analysis/infertypeargs/infertypeargs.go b/gopls/internal/analysis/infertypeargs/infertypeargs.go
index 2c3fdd3..9a514ad 100644
--- a/gopls/internal/analysis/infertypeargs/infertypeargs.go
+++ b/gopls/internal/analysis/infertypeargs/infertypeargs.go
@@ -2,16 +2,18 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package infertypeargs defines an analyzer that checks for explicit function
-// arguments that could be inferred.
 package infertypeargs
 
 import (
+	"go/ast"
 	"go/token"
+	"go/types"
 
 	"golang.org/x/tools/go/analysis"
 	"golang.org/x/tools/go/analysis/passes/inspect"
 	"golang.org/x/tools/go/ast/inspector"
+	"golang.org/x/tools/internal/typeparams"
+	"golang.org/x/tools/internal/versions"
 )
 
 const Doc = `check for unnecessary type arguments in call expressions
@@ -34,15 +36,114 @@
 	URL:      "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/infertypeargs",
 }
 
-// TODO(rfindley): remove this thin wrapper around the infertypeargs refactoring,
-// and eliminate the infertypeargs analyzer.
-//
-// Previous iterations used the analysis framework for computing refactorings,
-// which proved inefficient.
-func run(pass *analysis.Pass) (interface{}, error) {
+func run(pass *analysis.Pass) (any, error) {
 	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
-	for _, diag := range DiagnoseInferableTypeArgs(pass.Fset, inspect, token.NoPos, token.NoPos, pass.Pkg, pass.TypesInfo) {
+	for _, diag := range diagnose(pass.Fset, inspect, token.NoPos, token.NoPos, pass.Pkg, pass.TypesInfo) {
 		pass.Report(diag)
 	}
 	return nil, nil
 }
+
+// Diagnose reports diagnostics describing simplifications to type
+// arguments overlapping with the provided start and end position.
+//
+// If start or end is token.NoPos, the corresponding bound is not checked
+// (i.e. if both start and end are NoPos, all call expressions are considered).
+func diagnose(fset *token.FileSet, inspect *inspector.Inspector, start, end token.Pos, pkg *types.Package, info *types.Info) []analysis.Diagnostic {
+	var diags []analysis.Diagnostic
+
+	nodeFilter := []ast.Node{(*ast.CallExpr)(nil)}
+	inspect.Preorder(nodeFilter, func(node ast.Node) {
+		call := node.(*ast.CallExpr)
+		x, lbrack, indices, rbrack := typeparams.UnpackIndexExpr(call.Fun)
+		ident := calledIdent(x)
+		if ident == nil || len(indices) == 0 {
+			return // no explicit args, nothing to do
+		}
+
+		if (start.IsValid() && call.End() < start) || (end.IsValid() && call.Pos() > end) {
+			return // non-overlapping
+		}
+
+		// Confirm that instantiation actually occurred at this ident.
+		idata, ok := info.Instances[ident]
+		if !ok {
+			return // something went wrong, but fail open
+		}
+		instance := idata.Type
+
+		// Start removing argument expressions from the right, and check if we can
+		// still infer the call expression.
+		required := len(indices) // number of type expressions that are required
+		for i := len(indices) - 1; i >= 0; i-- {
+			var fun ast.Expr
+			if i == 0 {
+				// No longer an index expression: just use the parameterized operand.
+				fun = x
+			} else {
+				fun = typeparams.PackIndexExpr(x, lbrack, indices[:i], indices[i-1].End())
+			}
+			newCall := &ast.CallExpr{
+				Fun:      fun,
+				Lparen:   call.Lparen,
+				Args:     call.Args,
+				Ellipsis: call.Ellipsis,
+				Rparen:   call.Rparen,
+			}
+			info := &types.Info{
+				Instances: make(map[*ast.Ident]types.Instance),
+			}
+			versions.InitFileVersions(info)
+			if err := types.CheckExpr(fset, pkg, call.Pos(), newCall, info); err != nil {
+				// Most likely inference failed.
+				break
+			}
+			newIData := info.Instances[ident]
+			newInstance := newIData.Type
+			if !types.Identical(instance, newInstance) {
+				// The inferred result type does not match the original result type, so
+				// this simplification is not valid.
+				break
+			}
+			required = i
+		}
+		if required < len(indices) {
+			var s, e token.Pos
+			var edit analysis.TextEdit
+			if required == 0 {
+				s, e = lbrack, rbrack+1 // erase the entire index
+				edit = analysis.TextEdit{Pos: s, End: e}
+			} else {
+				s = indices[required].Pos()
+				e = rbrack
+				//  erase from end of last arg to include last comma & white-spaces
+				edit = analysis.TextEdit{Pos: indices[required-1].End(), End: e}
+			}
+			// Recheck that our (narrower) fixes overlap with the requested range.
+			if (start.IsValid() && e < start) || (end.IsValid() && s > end) {
+				return // non-overlapping
+			}
+			diags = append(diags, analysis.Diagnostic{
+				Pos:     s,
+				End:     e,
+				Message: "unnecessary type arguments",
+				SuggestedFixes: []analysis.SuggestedFix{{
+					Message:   "Simplify type arguments",
+					TextEdits: []analysis.TextEdit{edit},
+				}},
+			})
+		}
+	})
+
+	return diags
+}
+
+func calledIdent(x ast.Expr) *ast.Ident {
+	switch x := x.(type) {
+	case *ast.Ident:
+		return x
+	case *ast.SelectorExpr:
+		return x.Sel
+	}
+	return nil
+}
diff --git a/gopls/internal/analysis/infertypeargs/run_go117.go b/gopls/internal/analysis/infertypeargs/run_go117.go
deleted file mode 100644
index fdf8318..0000000
--- a/gopls/internal/analysis/infertypeargs/run_go117.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.18
-// +build !go1.18
-
-package infertypeargs
-
-import (
-	"go/token"
-	"go/types"
-
-	"golang.org/x/tools/go/analysis"
-	"golang.org/x/tools/go/ast/inspector"
-)
-
-// DiagnoseInferableTypeArgs returns an empty slice, as generics are not supported at
-// this go version.
-func DiagnoseInferableTypeArgs(fset *token.FileSet, inspect *inspector.Inspector, start, end token.Pos, pkg *types.Package, info *types.Info) []analysis.Diagnostic {
-	return nil
-}
diff --git a/gopls/internal/analysis/infertypeargs/run_go118.go b/gopls/internal/analysis/infertypeargs/run_go118.go
deleted file mode 100644
index b3fff4e..0000000
--- a/gopls/internal/analysis/infertypeargs/run_go118.go
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package infertypeargs
-
-import (
-	"go/ast"
-	"go/token"
-	"go/types"
-
-	"golang.org/x/tools/go/analysis"
-	"golang.org/x/tools/go/ast/inspector"
-	"golang.org/x/tools/internal/typeparams"
-	"golang.org/x/tools/internal/versions"
-)
-
-// DiagnoseInferableTypeArgs reports diagnostics describing simplifications to type
-// arguments overlapping with the provided start and end position.
-//
-// If start or end is token.NoPos, the corresponding bound is not checked
-// (i.e. if both start and end are NoPos, all call expressions are considered).
-func DiagnoseInferableTypeArgs(fset *token.FileSet, inspect *inspector.Inspector, start, end token.Pos, pkg *types.Package, info *types.Info) []analysis.Diagnostic {
-	var diags []analysis.Diagnostic
-
-	nodeFilter := []ast.Node{(*ast.CallExpr)(nil)}
-	inspect.Preorder(nodeFilter, func(node ast.Node) {
-		call := node.(*ast.CallExpr)
-		x, lbrack, indices, rbrack := typeparams.UnpackIndexExpr(call.Fun)
-		ident := calledIdent(x)
-		if ident == nil || len(indices) == 0 {
-			return // no explicit args, nothing to do
-		}
-
-		if (start.IsValid() && call.End() < start) || (end.IsValid() && call.Pos() > end) {
-			return // non-overlapping
-		}
-
-		// Confirm that instantiation actually occurred at this ident.
-		idata, ok := info.Instances[ident]
-		if !ok {
-			return // something went wrong, but fail open
-		}
-		instance := idata.Type
-
-		// Start removing argument expressions from the right, and check if we can
-		// still infer the call expression.
-		required := len(indices) // number of type expressions that are required
-		for i := len(indices) - 1; i >= 0; i-- {
-			var fun ast.Expr
-			if i == 0 {
-				// No longer an index expression: just use the parameterized operand.
-				fun = x
-			} else {
-				fun = typeparams.PackIndexExpr(x, lbrack, indices[:i], indices[i-1].End())
-			}
-			newCall := &ast.CallExpr{
-				Fun:      fun,
-				Lparen:   call.Lparen,
-				Args:     call.Args,
-				Ellipsis: call.Ellipsis,
-				Rparen:   call.Rparen,
-			}
-			info := &types.Info{
-				Instances: make(map[*ast.Ident]types.Instance),
-			}
-			versions.InitFileVersions(info)
-			if err := types.CheckExpr(fset, pkg, call.Pos(), newCall, info); err != nil {
-				// Most likely inference failed.
-				break
-			}
-			newIData := info.Instances[ident]
-			newInstance := newIData.Type
-			if !types.Identical(instance, newInstance) {
-				// The inferred result type does not match the original result type, so
-				// this simplification is not valid.
-				break
-			}
-			required = i
-		}
-		if required < len(indices) {
-			var s, e token.Pos
-			var edit analysis.TextEdit
-			if required == 0 {
-				s, e = lbrack, rbrack+1 // erase the entire index
-				edit = analysis.TextEdit{Pos: s, End: e}
-			} else {
-				s = indices[required].Pos()
-				e = rbrack
-				//  erase from end of last arg to include last comma & white-spaces
-				edit = analysis.TextEdit{Pos: indices[required-1].End(), End: e}
-			}
-			// Recheck that our (narrower) fixes overlap with the requested range.
-			if (start.IsValid() && e < start) || (end.IsValid() && s > end) {
-				return // non-overlapping
-			}
-			diags = append(diags, analysis.Diagnostic{
-				Pos:     s,
-				End:     e,
-				Message: "unnecessary type arguments",
-				SuggestedFixes: []analysis.SuggestedFix{{
-					Message:   "simplify type arguments",
-					TextEdits: []analysis.TextEdit{edit},
-				}},
-			})
-		}
-	})
-
-	return diags
-}
-
-func calledIdent(x ast.Expr) *ast.Ident {
-	switch x := x.(type) {
-	case *ast.Ident:
-		return x
-	case *ast.SelectorExpr:
-		return x.Sel
-	}
-	return nil
-}
diff --git a/gopls/internal/analysis/stubmethods/doc.go b/gopls/internal/analysis/stubmethods/doc.go
index 5b5957d..e1383cf 100644
--- a/gopls/internal/analysis/stubmethods/doc.go
+++ b/gopls/internal/analysis/stubmethods/doc.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package stubmethods defines an analyzer for missing interface methods.
+// Package stubmethods defines a code action for missing interface methods.
 //
 // # Analyzer stubmethods
 //
@@ -34,5 +34,5 @@
 //
 // (At least, it appears to behave that way, but technically it
 // doesn't use the SuggestedFix mechanism and the stub is created by
-// logic in gopls's source.stub function.)
+// logic in gopls's golang.stub function.)
 package stubmethods
diff --git a/gopls/internal/analysis/stubmethods/stubmethods.go b/gopls/internal/analysis/stubmethods/stubmethods.go
index 02eef5c..1215be8 100644
--- a/gopls/internal/analysis/stubmethods/stubmethods.go
+++ b/gopls/internal/analysis/stubmethods/stubmethods.go
@@ -12,11 +12,11 @@
 	"go/format"
 	"go/token"
 	"go/types"
-	"strconv"
 	"strings"
 
 	"golang.org/x/tools/go/analysis"
 	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/gopls/internal/util/typesutil"
 	"golang.org/x/tools/internal/analysisinternal"
 	"golang.org/x/tools/internal/typesinternal"
 )
@@ -73,9 +73,6 @@
 // interface to fix the type checking error defined by (start, end, msg).
 //
 // If no such fix is possible, the second result is false.
-//
-// TODO(rfindley): simplify this signature once the stubmethods refactoring is
-// no longer wedged into the analysis framework.
 func DiagnosticForError(fset *token.FileSet, file *ast.File, start, end token.Pos, msg string, info *types.Info) (analysis.Diagnostic, bool) {
 	if !MatchesMessage(msg) {
 		return analysis.Diagnostic{}, false
@@ -86,14 +83,22 @@
 	if si == nil {
 		return analysis.Diagnostic{}, false
 	}
-	qf := RelativeToFiles(si.Concrete.Obj().Pkg(), file, nil, nil)
+	qf := typesutil.FileQualifier(file, si.Concrete.Obj().Pkg(), info)
+	iface := types.TypeString(si.Interface.Type(), qf)
 	return analysis.Diagnostic{
-		Pos:     start,
-		End:     end,
-		Message: fmt.Sprintf("Implement %s", types.TypeString(si.Interface.Type(), qf)),
+		Pos:      start,
+		End:      end,
+		Message:  msg,
+		Category: FixCategory,
+		SuggestedFixes: []analysis.SuggestedFix{{
+			Message: fmt.Sprintf("Declare missing methods of %s", iface),
+			// No TextEdits => computed later by gopls.
+		}},
 	}, true
 }
 
+const FixCategory = "stubmethods" // recognized by gopls ApplyFix
+
 // StubInfo represents a concrete type
 // that wants to stub out an interface type
 type StubInfo struct {
@@ -328,71 +333,6 @@
 	}
 }
 
-// RelativeToFiles returns a types.Qualifier that formats package
-// names according to the import environments of the files that define
-// the concrete type and the interface type. (Only the imports of the
-// latter file are provided.)
-//
-// This is similar to types.RelativeTo except if a file imports the package with a different name,
-// then it will use it. And if the file does import the package but it is ignored,
-// then it will return the original name. It also prefers package names in importEnv in case
-// an import is missing from concFile but is present among importEnv.
-//
-// Additionally, if missingImport is not nil, the function will be called whenever the concFile
-// is presented with a package that is not imported. This is useful so that as types.TypeString is
-// formatting a function signature, it is identifying packages that will need to be imported when
-// stubbing an interface.
-//
-// TODO(rfindley): investigate if this can be merged with source.Qualifier.
-func RelativeToFiles(concPkg *types.Package, concFile *ast.File, ifaceImports []*ast.ImportSpec, missingImport func(name, path string)) types.Qualifier {
-	return func(other *types.Package) string {
-		if other == concPkg {
-			return ""
-		}
-
-		// Check if the concrete file already has the given import,
-		// if so return the default package name or the renamed import statement.
-		for _, imp := range concFile.Imports {
-			impPath, _ := strconv.Unquote(imp.Path.Value)
-			isIgnored := imp.Name != nil && (imp.Name.Name == "." || imp.Name.Name == "_")
-			// TODO(adonovan): this comparison disregards a vendor prefix in 'other'.
-			if impPath == other.Path() && !isIgnored {
-				importName := other.Name()
-				if imp.Name != nil {
-					importName = imp.Name.Name
-				}
-				return importName
-			}
-		}
-
-		// If the concrete file does not have the import, check if the package
-		// is renamed in the interface file and prefer that.
-		var importName string
-		for _, imp := range ifaceImports {
-			impPath, _ := strconv.Unquote(imp.Path.Value)
-			isIgnored := imp.Name != nil && (imp.Name.Name == "." || imp.Name.Name == "_")
-			// TODO(adonovan): this comparison disregards a vendor prefix in 'other'.
-			if impPath == other.Path() && !isIgnored {
-				if imp.Name != nil && imp.Name.Name != concPkg.Name() {
-					importName = imp.Name.Name
-				}
-				break
-			}
-		}
-
-		if missingImport != nil {
-			missingImport(importName, other.Path())
-		}
-
-		// Up until this point, importName must stay empty when calling missingImport,
-		// otherwise we'd end up with `import time "time"` which doesn't look idiomatic.
-		if importName == "" {
-			importName = other.Name()
-		}
-		return importName
-	}
-}
-
 // ifaceType returns the named interface type to which e refers, if any.
 func ifaceType(e ast.Expr, info *types.Info) *types.TypeName {
 	tv, ok := info.Types[e]
diff --git a/gopls/internal/analysis/undeclaredname/undeclared.go b/gopls/internal/analysis/undeclaredname/undeclared.go
index 377c635..10393d4 100644
--- a/gopls/internal/analysis/undeclaredname/undeclared.go
+++ b/gopls/internal/analysis/undeclaredname/undeclared.go
@@ -44,6 +44,7 @@
 }
 
 func runForError(pass *analysis.Pass, err types.Error) {
+	// Extract symbol name from error.
 	var name string
 	for _, prefix := range undeclaredNamePrefixes {
 		if !strings.HasPrefix(err.Msg, prefix) {
@@ -54,6 +55,8 @@
 	if name == "" {
 		return
 	}
+
+	// Find file enclosing error.
 	var file *ast.File
 	for _, f := range pass.Files {
 		if f.Pos() <= err.Pos && err.Pos < f.End() {
@@ -65,7 +68,7 @@
 		return
 	}
 
-	// Get the path for the relevant range.
+	// Find path to identifier in the error.
 	path, _ := astutil.PathEnclosingInterval(file, err.Pos, err.Pos)
 	if len(path) < 2 {
 		return
@@ -75,6 +78,12 @@
 		return
 	}
 
+	// Skip selector expressions because it might be too complex
+	// to try and provide a suggested fix for fields and methods.
+	if _, ok := path[1].(*ast.SelectorExpr); ok {
+		return
+	}
+
 	// Undeclared quick fixes only work in function bodies.
 	inFunc := false
 	for i := range path {
@@ -91,24 +100,27 @@
 	if !inFunc {
 		return
 	}
-	// Skip selector expressions because it might be too complex
-	// to try and provide a suggested fix for fields and methods.
-	if _, ok := path[1].(*ast.SelectorExpr); ok {
-		return
+
+	// Offer a fix.
+	noun := "variable"
+	if isCallPosition(path) {
+		noun = "function"
 	}
-	tok := pass.Fset.File(file.Pos())
-	if tok == nil {
-		return
-	}
-	offset := safetoken.StartPosition(pass.Fset, err.Pos).Offset
-	end := tok.Pos(offset + len(name)) // TODO(adonovan): dubious! err.Pos + len(name)??
 	pass.Report(analysis.Diagnostic{
-		Pos:     err.Pos,
-		End:     end,
-		Message: err.Msg,
+		Pos:      err.Pos,
+		End:      err.Pos + token.Pos(len(name)),
+		Message:  err.Msg,
+		Category: FixCategory,
+		SuggestedFixes: []analysis.SuggestedFix{{
+			Message: fmt.Sprintf("Create %s %q", noun, name),
+			// No TextEdits => computed by a gopls command
+		}},
 	})
 }
 
+const FixCategory = "undeclaredname" // recognized by gopls ApplyFix
+
+// SuggestedFix computes the edits for the lazy (no-edits) fix suggested by the analyzer.
 func SuggestedFix(fset *token.FileSet, start, end token.Pos, content []byte, file *ast.File, pkg *types.Package, info *types.Info) (*token.FileSet, *analysis.SuggestedFix, error) {
 	pos := start // don't use the end
 	path, _ := astutil.PathEnclosingInterval(file, pos, pos)
@@ -122,10 +134,8 @@
 
 	// Check for a possible call expression, in which case we should add a
 	// new function declaration.
-	if len(path) > 1 {
-		if _, ok := path[1].(*ast.CallExpr); ok {
-			return newFunctionDeclaration(path, file, pkg, info, fset)
-		}
+	if isCallPosition(path) {
+		return newFunctionDeclaration(path, file, pkg, info, fset)
 	}
 
 	// Get the place to insert the new statement.
@@ -146,7 +156,7 @@
 	// Create the new local variable statement.
 	newStmt := fmt.Sprintf("%s := %s", ident.Name, indent)
 	return fset, &analysis.SuggestedFix{
-		Message: fmt.Sprintf("Create variable \"%s\"", ident.Name),
+		Message: fmt.Sprintf("Create variable %q", ident.Name),
 		TextEdits: []analysis.TextEdit{{
 			Pos:     insertBeforeStmt.Pos(),
 			End:     insertBeforeStmt.Pos(),
@@ -271,7 +281,8 @@
 		Name: ast.NewIdent(ident.Name),
 		Type: &ast.FuncType{
 			Params: params,
-			// TODO(rstambler): Also handle result parameters here.
+			// TODO(golang/go#47558): Also handle result
+			// parameters here based on context of CallExpr.
 		},
 		Body: &ast.BlockStmt{
 			List: []ast.Stmt{
@@ -294,7 +305,7 @@
 		return nil, nil, err
 	}
 	return fset, &analysis.SuggestedFix{
-		Message: fmt.Sprintf("Create function \"%s\"", ident.Name),
+		Message: fmt.Sprintf("Create function %q", ident.Name),
 		TextEdits: []analysis.TextEdit{{
 			Pos:     pos,
 			End:     pos,
@@ -302,6 +313,7 @@
 		}},
 	}, nil
 }
+
 func typeToArgName(ty types.Type) string {
 	s := types.Default(ty).String()
 
@@ -333,3 +345,15 @@
 	a[0] = unicode.ToLower(a[0])
 	return string(a)
 }
+
+// isCallPosition reports whether the path denotes the subtree in call position, f().
+func isCallPosition(path []ast.Node) bool {
+	return len(path) > 1 &&
+		is[*ast.CallExpr](path[1]) &&
+		path[1].(*ast.CallExpr).Fun == path[0]
+}
+
+func is[T any](x any) bool {
+	_, ok := x.(T)
+	return ok
+}
diff --git a/gopls/internal/analysis/unusedparams/cmd/main.go b/gopls/internal/analysis/unusedparams/cmd/main.go
index 2355e3c..2f35fb0 100644
--- a/gopls/internal/analysis/unusedparams/cmd/main.go
+++ b/gopls/internal/analysis/unusedparams/cmd/main.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The stringintconv command runs the stringintconv analyzer.
+// The unusedparams command runs the unusedparams analyzer.
 package main
 
 import (
diff --git a/gopls/internal/analysis/unusedparams/doc.go b/gopls/internal/analysis/unusedparams/doc.go
index 2bf9fa9..07e43c0 100644
--- a/gopls/internal/analysis/unusedparams/doc.go
+++ b/gopls/internal/analysis/unusedparams/doc.go
@@ -12,9 +12,23 @@
 // The unusedparams analyzer checks functions to see if there are
 // any parameters that are not being used.
 //
-// To reduce false positives it ignores:
-// - methods
-// - parameters that do not have a name or have the name '_' (the blank identifier)
-// - functions in test files
-// - functions with empty bodies or those with just a return stmt
+// To ensure soundness, it ignores:
+//   - "address-taken" functions, that is, functions that are used as
+//     a value rather than being called directly; their signatures may
+//     be required to conform to a func type.
+//   - exported functions or methods, since they may be address-taken
+//     in another package.
+//   - unexported methods whose name matches an interface method
+//     declared in the same package, since the method's signature
+//     may be required to conform to the interface type.
+//   - functions with empty bodies, or containing just a call to panic.
+//   - parameters that are unnamed, or named "_", the blank identifier.
+//
+// The analyzer suggests a fix of replacing the parameter name by "_",
+// but in such cases a deeper fix can be obtained by invoking the
+// "Refactor: remove unused parameter" code action, which will
+// eliminate the parameter entirely, along with all corresponding
+// arguments at call sites, while taking care to preserve any side
+// effects in the argument expressions; see
+// https://github.com/golang/tools/releases/tag/gopls%2Fv0.14.
 package unusedparams
diff --git a/gopls/internal/analysis/unusedparams/testdata/src/a/a.go b/gopls/internal/analysis/unusedparams/testdata/src/a/a.go
index 23e4122..3661e1f 100644
--- a/gopls/internal/analysis/unusedparams/testdata/src/a/a.go
+++ b/gopls/internal/analysis/unusedparams/testdata/src/a/a.go
@@ -24,28 +24,28 @@
 	}
 }
 
-func a(i1 int, i2 int, i3 int) int { // want "potentially unused parameter: 'i2'"
+func a(i1 int, i2 int, i3 int) int { // want "unused parameter: i2"
 	i3 += i1
-	_ = func(z int) int { // want "potentially unused parameter: 'z'"
+	_ = func(z int) int { // want "unused parameter: z"
 		_ = 1
 		return 1
 	}
 	return i3
 }
 
-func b(c bytes.Buffer) { // want "potentially unused parameter: 'c'"
+func b(c bytes.Buffer) { // want "unused parameter: c"
 	_ = 1
 }
 
-func z(h http.ResponseWriter, _ *http.Request) { // want "potentially unused parameter: 'h'"
+func z(h http.ResponseWriter, _ *http.Request) { // no report: func z is address-taken
 	fmt.Println("Before")
 }
 
-func l(h http.Handler) http.Handler {
+func l(h http.Handler) http.Handler { // want "unused parameter: h"
 	return http.HandlerFunc(z)
 }
 
-func mult(a, b int) int { // want "potentially unused parameter: 'b'"
+func mult(a, b int) int { // want "unused parameter: b"
 	a += 1
 	return a
 }
@@ -53,3 +53,35 @@
 func y(a int) {
 	panic("yo")
 }
+
+var _ = func(x int) {} // empty body: no diagnostic
+
+var _ = func(x int) { println() } // want "unused parameter: x"
+
+var (
+	calledGlobal       = func(x int) { println() } // want "unused parameter: x"
+	addressTakenGlobal = func(x int) { println() } // no report: function is address-taken
+)
+
+func _() {
+	calledGlobal(1)
+	println(addressTakenGlobal)
+}
+
+func Exported(unused int) {} // no finding: an exported function may be address-taken
+
+type T int
+
+func (T) m(f bool) { println() } // want "unused parameter: f"
+func (T) n(f bool) { println() } // no finding: n may match the interface method parent.n
+
+func _() {
+	var fib func(x, y int) int
+	fib = func(x, y int) int { // want "unused parameter: y"
+		if x < 2 {
+			return x
+		}
+		return fib(x-1, 123) + fib(x-2, 456)
+	}
+	fib(10, 42)
+}
diff --git a/gopls/internal/analysis/unusedparams/testdata/src/a/a.go.golden b/gopls/internal/analysis/unusedparams/testdata/src/a/a.go.golden
index e28a6bd..dea8a6d 100644
--- a/gopls/internal/analysis/unusedparams/testdata/src/a/a.go.golden
+++ b/gopls/internal/analysis/unusedparams/testdata/src/a/a.go.golden
@@ -24,28 +24,28 @@
 	}
 }
 
-func a(i1 int, _ int, i3 int) int { // want "potentially unused parameter: 'i2'"
+func a(i1 int, _ int, i3 int) int { // want "unused parameter: i2"
 	i3 += i1
-	_ = func(_ int) int { // want "potentially unused parameter: 'z'"
+	_ = func(_ int) int { // want "unused parameter: z"
 		_ = 1
 		return 1
 	}
 	return i3
 }
 
-func b(_ bytes.Buffer) { // want "potentially unused parameter: 'c'"
+func b(_ bytes.Buffer) { // want "unused parameter: c"
 	_ = 1
 }
 
-func z(_ http.ResponseWriter, _ *http.Request) { // want "potentially unused parameter: 'h'"
+func z(h http.ResponseWriter, _ *http.Request) { // no report: func z is address-taken
 	fmt.Println("Before")
 }
 
-func l(h http.Handler) http.Handler {
+func l(_ http.Handler) http.Handler { // want "unused parameter: h"
 	return http.HandlerFunc(z)
 }
 
-func mult(a, _ int) int { // want "potentially unused parameter: 'b'"
+func mult(a, _ int) int { // want "unused parameter: b"
 	a += 1
 	return a
 }
@@ -53,3 +53,35 @@
 func y(a int) {
 	panic("yo")
 }
+
+var _ = func(x int) {} // empty body: no diagnostic
+
+var _ = func(_ int) { println() } // want "unused parameter: x"
+
+var (
+	calledGlobal       = func(_ int) { println() } // want "unused parameter: x"
+	addressTakenGlobal = func(x int) { println() } // no report: function is address-taken
+)
+
+func _() {
+	calledGlobal(1)
+	println(addressTakenGlobal)
+}
+
+func Exported(unused int) {} // no finding: an exported function may be address-taken
+
+type T int
+
+func (T) m(_ bool) { println() } // want "unused parameter: f"
+func (T) n(f bool) { println() } // no finding: n may match the interface method parent.n
+
+func _() {
+	var fib func(x, y int) int
+	fib = func(x, _ int) int { // want "unused parameter: y"
+		if x < 2 {
+			return x
+		}
+		return fib(x-1, 123) + fib(x-2, 456)
+	}
+	fib(10, 42)
+}
diff --git a/gopls/internal/analysis/unusedparams/testdata/src/typeparams/typeparams.go b/gopls/internal/analysis/unusedparams/testdata/src/typeparams/typeparams.go
index 93af268..d89926a 100644
--- a/gopls/internal/analysis/unusedparams/testdata/src/typeparams/typeparams.go
+++ b/gopls/internal/analysis/unusedparams/testdata/src/typeparams/typeparams.go
@@ -24,28 +24,28 @@
 	}
 }
 
-func a[T comparable](i1 int, i2 T, i3 int) int { // want "potentially unused parameter: 'i2'"
+func a[T comparable](i1 int, i2 T, i3 int) int { // want "unused parameter: i2"
 	i3 += i1
-	_ = func(z int) int { // want "potentially unused parameter: 'z'"
+	_ = func(z int) int { // want "unused parameter: z"
 		_ = 1
 		return 1
 	}
 	return i3
 }
 
-func b[T any](c bytes.Buffer) { // want "potentially unused parameter: 'c'"
+func b[T any](c bytes.Buffer) { // want "unused parameter: c"
 	_ = 1
 }
 
-func z[T http.ResponseWriter](h T, _ *http.Request) { // want "potentially unused parameter: 'h'"
+func z[T http.ResponseWriter](h T, _ *http.Request) { // no report: func z is address-taken
 	fmt.Println("Before")
 }
 
-func l(h http.Handler) http.Handler {
+func l(h http.Handler) http.Handler { // want "unused parameter: h"
 	return http.HandlerFunc(z[http.ResponseWriter])
 }
 
-func mult(a, b int) int { // want "potentially unused parameter: 'b'"
+func mult(a, b int) int { // want "unused parameter: b"
 	a += 1
 	return a
 }
diff --git a/gopls/internal/analysis/unusedparams/testdata/src/typeparams/typeparams.go.golden b/gopls/internal/analysis/unusedparams/testdata/src/typeparams/typeparams.go.golden
index c86bf28..85479bc 100644
--- a/gopls/internal/analysis/unusedparams/testdata/src/typeparams/typeparams.go.golden
+++ b/gopls/internal/analysis/unusedparams/testdata/src/typeparams/typeparams.go.golden
@@ -24,28 +24,28 @@
 	}
 }
 
-func a[T comparable](i1 int, _ T, i3 int) int { // want "potentially unused parameter: 'i2'"
+func a[T comparable](i1 int, _ T, i3 int) int { // want "unused parameter: i2"
 	i3 += i1
-	_ = func(_ int) int { // want "potentially unused parameter: 'z'"
+	_ = func(_ int) int { // want "unused parameter: z"
 		_ = 1
 		return 1
 	}
 	return i3
 }
 
-func b[T any](_ bytes.Buffer) { // want "potentially unused parameter: 'c'"
+func b[T any](_ bytes.Buffer) { // want "unused parameter: c"
 	_ = 1
 }
 
-func z[T http.ResponseWriter](_ T, _ *http.Request) { // want "potentially unused parameter: 'h'"
+func z[T http.ResponseWriter](h T, _ *http.Request) { // no report: func z is address-taken
 	fmt.Println("Before")
 }
 
-func l(h http.Handler) http.Handler {
+func l(_ http.Handler) http.Handler { // want "unused parameter: h"
 	return http.HandlerFunc(z[http.ResponseWriter])
 }
 
-func mult(a, _ int) int { // want "potentially unused parameter: 'b'"
+func mult(a, _ int) int { // want "unused parameter: b"
 	a += 1
 	return a
 }
diff --git a/gopls/internal/analysis/unusedparams/unusedparams.go b/gopls/internal/analysis/unusedparams/unusedparams.go
index 076acf7..74cd662 100644
--- a/gopls/internal/analysis/unusedparams/unusedparams.go
+++ b/gopls/internal/analysis/unusedparams/unusedparams.go
@@ -9,151 +9,300 @@
 	"fmt"
 	"go/ast"
 	"go/types"
-	"strings"
 
 	"golang.org/x/tools/go/analysis"
 	"golang.org/x/tools/go/analysis/passes/inspect"
 	"golang.org/x/tools/go/ast/inspector"
+	"golang.org/x/tools/gopls/internal/util/slices"
 	"golang.org/x/tools/internal/analysisinternal"
 )
 
 //go:embed doc.go
 var doc string
 
-var (
-	Analyzer = &analysis.Analyzer{
-		Name:     "unusedparams",
-		Doc:      analysisinternal.MustExtractDoc(doc, "unusedparams"),
-		Requires: []*analysis.Analyzer{inspect.Analyzer},
-		Run:      run,
-		URL:      "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedparams",
-	}
-	inspectLits     bool
-	inspectWrappers bool
-)
-
-func init() {
-	Analyzer.Flags.BoolVar(&inspectLits, "lits", true, "inspect function literals")
-	Analyzer.Flags.BoolVar(&inspectWrappers, "wrappers", false, "inspect functions whose body consists of a single return statement")
+var Analyzer = &analysis.Analyzer{
+	Name:     "unusedparams",
+	Doc:      analysisinternal.MustExtractDoc(doc, "unusedparams"),
+	Requires: []*analysis.Analyzer{inspect.Analyzer},
+	Run:      run,
+	URL:      "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedparams",
 }
 
-type paramData struct {
-	field  *ast.Field
-	ident  *ast.Ident
-	typObj types.Object
-}
+const FixCategory = "unusedparam" // recognized by gopls ApplyFix
 
-func run(pass *analysis.Pass) (interface{}, error) {
+func run(pass *analysis.Pass) (any, error) {
 	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
-	nodeFilter := []ast.Node{
-		(*ast.FuncDecl)(nil),
-	}
-	if inspectLits {
-		nodeFilter = append(nodeFilter, (*ast.FuncLit)(nil))
-	}
 
-	inspect.Preorder(nodeFilter, func(n ast.Node) {
-		var fieldList *ast.FieldList
-		var body *ast.BlockStmt
+	// First find all "address-taken" functions.
+	// We must conservatively assume that their parameters
+	// are all required to conform to some signature.
+	//
+	// A named function is address-taken if it is somewhere
+	// used not in call position:
+	//
+	//	f(...)		// not address-taken
+	//      use(f)          // address-taken
+	//
+	// A literal function is address-taken if it is not
+	// immediately bound to a variable, or if that variable is
+	// used not in call position:
+	//
+	//    f := func() { ... }; f()     			used only in call position
+	//    var f func(); f = func() { ...f()... }; f()     	ditto
+	//    use(func() { ... })				address-taken
+	//
 
-		// Get the fieldList and body from the function node.
-		switch f := n.(type) {
-		case *ast.FuncDecl:
-			fieldList, body = f.Type.Params, f.Body
-			// TODO(golang/go#36602): add better handling for methods, if we enable methods
-			// we will get false positives if a struct is potentially implementing
-			// an interface.
-			if f.Recv != nil {
-				return
-			}
+	// Note: this algorithm relies on the assumption that the
+	// analyzer is called only for the "widest" package for a
+	// given file: that is, p_test in preference to p, if both
+	// exist. Analyzing only package p may produce diagnostics
+	// that would be falsified based on declarations in p_test.go
+	// files. The gopls analysis driver does this, but most
+	// drivers to not, so running this command in, say,
+	// unitchecker or multichecker may produce incorrect results.
 
-			// Ignore functions in _test.go files to reduce false positives.
-			if file := pass.Fset.File(n.Pos()); file != nil && strings.HasSuffix(file.Name(), "_test.go") {
-				return
-			}
-		case *ast.FuncLit:
-			fieldList, body = f.Type.Params, f.Body
+	// Gather global information:
+	// - uses of functions not in call position
+	// - unexported interface methods
+	// - all referenced variables
+
+	usesOutsideCall := make(map[types.Object][]*ast.Ident)
+	unexportedIMethodNames := make(map[string]bool)
+	{
+		callPosn := make(map[*ast.Ident]bool) // all idents f appearing in f() calls
+		filter := []ast.Node{
+			(*ast.CallExpr)(nil),
+			(*ast.InterfaceType)(nil),
 		}
-		// If there are no arguments or the function is empty, then return.
-		if fieldList.NumFields() == 0 || body == nil || len(body.List) == 0 {
-			return
-		}
-
-		switch expr := body.List[0].(type) {
-		case *ast.ReturnStmt:
-			if !inspectWrappers {
-				// Ignore functions that only contain a return statement to reduce false positives.
-				return
-			}
-		case *ast.ExprStmt:
-			callExpr, ok := expr.X.(*ast.CallExpr)
-			if !ok || len(body.List) > 1 {
-				break
-			}
-			// Ignore functions that only contain a panic statement to reduce false positives.
-			if fun, ok := callExpr.Fun.(*ast.Ident); ok && fun.Name == "panic" {
-				return
-			}
-		}
-
-		// Get the useful data from each field.
-		params := make(map[string]*paramData)
-		unused := make(map[*paramData]bool)
-		for _, f := range fieldList.List {
-			for _, i := range f.Names {
-				if i.Name == "_" {
-					continue
+		inspect.Preorder(filter, func(n ast.Node) {
+			switch n := n.(type) {
+			case *ast.CallExpr:
+				// Strip off any generic instantiation.
+				fun := n.Fun
+				switch fun_ := fun.(type) {
+				case *ast.IndexExpr:
+					fun = fun_.X // f[T]()  (funcs[i]() is rejected below)
+				case *ast.IndexListExpr:
+					fun = fun_.X // f[K, V]()
 				}
-				params[i.Name] = &paramData{
-					field:  f,
-					ident:  i,
-					typObj: pass.TypesInfo.ObjectOf(i),
-				}
-				unused[params[i.Name]] = true
-			}
-		}
 
-		// Traverse through the body of the function and
-		// check to see which parameters are unused.
-		ast.Inspect(body, func(node ast.Node) bool {
-			n, ok := node.(*ast.Ident)
-			if !ok {
-				return true
+				// Find object:
+				// record non-exported function, method, or func-typed var.
+				var id *ast.Ident
+				switch fun := fun.(type) {
+				case *ast.Ident:
+					id = fun
+				case *ast.SelectorExpr:
+					id = fun.Sel
+				}
+				if id != nil && !id.IsExported() {
+					switch pass.TypesInfo.Uses[id].(type) {
+					case *types.Func, *types.Var:
+						callPosn[id] = true
+					}
+				}
+
+			case *ast.InterfaceType:
+				// Record the set of names of unexported interface methods.
+				// (It would be more precise to record signatures but
+				// generics makes it tricky, and this conservative
+				// heuristic is close enough.)
+				t := pass.TypesInfo.TypeOf(n).(*types.Interface)
+				for i := 0; i < t.NumExplicitMethods(); i++ {
+					m := t.ExplicitMethod(i)
+					if !m.Exported() && m.Name() != "_" {
+						unexportedIMethodNames[m.Name()] = true
+					}
+				}
 			}
-			param, ok := params[n.Name]
-			if !ok {
-				return false
-			}
-			if nObj := pass.TypesInfo.ObjectOf(n); nObj != param.typObj {
-				return false
-			}
-			delete(unused, param)
-			return false
 		})
 
-		// Create the reports for the unused parameters.
-		for u := range unused {
-			start, end := u.field.Pos(), u.field.End()
-			if len(u.field.Names) > 1 {
-				start, end = u.ident.Pos(), u.ident.End()
+		for id, obj := range pass.TypesInfo.Uses {
+			if !callPosn[id] {
+				// This includes "f = func() {...}", which we deal with below.
+				usesOutsideCall[obj] = append(usesOutsideCall[obj], id)
 			}
-			// TODO(golang/go#36602): Add suggested fixes to automatically
-			// remove the unused parameter from every use of this
-			// function.
-			pass.Report(analysis.Diagnostic{
-				Pos:     start,
-				End:     end,
-				Message: fmt.Sprintf("potentially unused parameter: '%s'", u.ident.Name),
-				SuggestedFixes: []analysis.SuggestedFix{{
-					Message: `Replace with "_"`,
-					TextEdits: []analysis.TextEdit{{
-						Pos:     u.ident.Pos(),
-						End:     u.ident.End(),
-						NewText: []byte("_"),
-					}},
-				}},
-			})
 		}
+	}
+
+	// Find all vars (notably parameters) that are used.
+	usedVars := make(map[*types.Var]bool)
+	for _, obj := range pass.TypesInfo.Uses {
+		if v, ok := obj.(*types.Var); ok {
+			if v.IsField() {
+				continue // no point gathering these
+			}
+			usedVars[v] = true
+		}
+	}
+
+	// Check each non-address-taken function's parameters are all used.
+	filter := []ast.Node{
+		(*ast.FuncDecl)(nil),
+		(*ast.FuncLit)(nil),
+	}
+	inspect.WithStack(filter, func(n ast.Node, push bool, stack []ast.Node) bool {
+		// (We always return true so that we visit nested FuncLits.)
+
+		if !push {
+			return true
+		}
+
+		var (
+			fn    types.Object // function symbol (*Func, possibly *Var for a FuncLit)
+			ftype *ast.FuncType
+			body  *ast.BlockStmt
+		)
+		switch n := n.(type) {
+		case *ast.FuncDecl:
+			// We can't analyze non-Go functions.
+			if n.Body == nil {
+				return true
+			}
+
+			// Ignore exported functions and methods: we
+			// must assume they may be address-taken in
+			// another package.
+			if n.Name.IsExported() {
+				return true
+			}
+
+			// Ignore methods that match the name of any
+			// interface method declared in this package,
+			// as the method's signature may need to conform
+			// to the interface.
+			if n.Recv != nil && unexportedIMethodNames[n.Name.Name] {
+				return true
+			}
+
+			fn = pass.TypesInfo.Defs[n.Name].(*types.Func)
+			ftype, body = n.Type, n.Body
+
+		case *ast.FuncLit:
+			// Find the symbol for the variable (if any)
+			// to which the FuncLit is bound.
+			// (We don't bother to allow ParenExprs.)
+			switch parent := stack[len(stack)-2].(type) {
+			case *ast.AssignStmt:
+				// f  = func() {...}
+				// f := func() {...}
+				for i, rhs := range parent.Rhs {
+					if rhs == n {
+						if id, ok := parent.Lhs[i].(*ast.Ident); ok {
+							fn = pass.TypesInfo.ObjectOf(id)
+
+							// Edge case: f = func() {...}
+							// should not count as a use.
+							if pass.TypesInfo.Uses[id] != nil {
+								usesOutsideCall[fn] = slices.Remove(usesOutsideCall[fn], id)
+							}
+
+							if fn == nil && id.Name == "_" {
+								// Edge case: _ = func() {...}
+								// has no var. Fake one.
+								fn = types.NewVar(id.Pos(), pass.Pkg, id.Name, pass.TypesInfo.TypeOf(n))
+							}
+						}
+						break
+					}
+				}
+
+			case *ast.ValueSpec:
+				// var f = func() { ... }
+				// (unless f is an exported package-level var)
+				for i, val := range parent.Values {
+					if val == n {
+						v := pass.TypesInfo.Defs[parent.Names[i]]
+						if !(v.Parent() == pass.Pkg.Scope() && v.Exported()) {
+							fn = v
+						}
+						break
+					}
+				}
+			}
+
+			ftype, body = n.Type, n.Body
+		}
+
+		// Ignore address-taken functions and methods: unused
+		// parameters may be needed to conform to a func type.
+		if fn == nil || len(usesOutsideCall[fn]) > 0 {
+			return true
+		}
+
+		// If there are no parameters, there are no unused parameters.
+		if ftype.Params.NumFields() == 0 {
+			return true
+		}
+
+		// To reduce false positives, ignore functions with an
+		// empty or panic body.
+		//
+		// We choose not to ignore functions whose body is a
+		// single return statement (as earlier versions did)
+		// 	func f() { return }
+		// 	func f() { return g(...) }
+		// as we suspect that was just heuristic to reduce
+		// false positives in the earlier unsound algorithm.
+		switch len(body.List) {
+		case 0:
+			// Empty body. Although the parameter is
+			// unnecessary, it's pretty obvious to the
+			// reader that that's the case, so we allow it.
+			return true // func f() {}
+		case 1:
+			if stmt, ok := body.List[0].(*ast.ExprStmt); ok {
+				// We allow a panic body, as it is often a
+				// placeholder for a future implementation:
+				// 	func f() { panic(...) }
+				if call, ok := stmt.X.(*ast.CallExpr); ok {
+					if fun, ok := call.Fun.(*ast.Ident); ok && fun.Name == "panic" {
+						return true
+					}
+				}
+			}
+		}
+
+		// Report each unused parameter.
+		for _, field := range ftype.Params.List {
+			for _, id := range field.Names {
+				if id.Name == "_" {
+					continue
+				}
+				param := pass.TypesInfo.Defs[id].(*types.Var)
+				if !usedVars[param] {
+					start, end := field.Pos(), field.End()
+					if len(field.Names) > 1 {
+						start, end = id.Pos(), id.End()
+					}
+					// This diagnostic carries both an edit-based fix to
+					// rename the unused parameter, and a command-based fix
+					// to remove it (see golang.RemoveUnusedParameter).
+					pass.Report(analysis.Diagnostic{
+						Pos:      start,
+						End:      end,
+						Message:  fmt.Sprintf("unused parameter: %s", id.Name),
+						Category: FixCategory,
+						SuggestedFixes: []analysis.SuggestedFix{
+							{
+								Message: `Rename parameter to "_"`,
+								TextEdits: []analysis.TextEdit{{
+									Pos:     id.Pos(),
+									End:     id.End(),
+									NewText: []byte("_"),
+								}},
+							},
+							{
+								Message: fmt.Sprintf("Remove unused parameter %q", id.Name),
+								// No TextEdits => computed by gopls command
+							},
+						},
+					})
+				}
+			}
+		}
+
+		return true
 	})
 	return nil, nil
 }
diff --git a/gopls/internal/analysis/unusedvariable/unusedvariable.go b/gopls/internal/analysis/unusedvariable/unusedvariable.go
index e85b9dc..67866d0 100644
--- a/gopls/internal/analysis/unusedvariable/unusedvariable.go
+++ b/gopls/internal/analysis/unusedvariable/unusedvariable.go
@@ -104,7 +104,7 @@
 				continue
 			}
 
-			fixes := removeVariableFromAssignment(pass, path, stmt, ident)
+			fixes := removeVariableFromAssignment(path, stmt, ident)
 			// fixes may be nil
 			if len(fixes) > 0 {
 				diag.SuggestedFixes = fixes
@@ -185,7 +185,7 @@
 	}
 }
 
-func removeVariableFromAssignment(pass *analysis.Pass, path []ast.Node, stmt *ast.AssignStmt, ident *ast.Ident) []analysis.SuggestedFix {
+func removeVariableFromAssignment(path []ast.Node, stmt *ast.AssignStmt, ident *ast.Ident) []analysis.SuggestedFix {
 	// The only variable in the assignment is unused
 	if len(stmt.Lhs) == 1 {
 		// If LHS has only one expression to be valid it has to have 1 expression
diff --git a/gopls/internal/lsp/cache/analysis.go b/gopls/internal/cache/analysis.go
similarity index 98%
rename from gopls/internal/lsp/cache/analysis.go
rename to gopls/internal/cache/analysis.go
index dfbb9ef..0b7bc08 100644
--- a/gopls/internal/lsp/cache/analysis.go
+++ b/gopls/internal/cache/analysis.go
@@ -34,9 +34,9 @@
 	"golang.org/x/tools/go/analysis"
 	"golang.org/x/tools/gopls/internal/file"
 	"golang.org/x/tools/gopls/internal/filecache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/progress"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/progress"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/util/astutil"
 	"golang.org/x/tools/gopls/internal/util/bug"
@@ -150,7 +150,7 @@
 //   Even if the ultimate consumer decides to ignore errors,
 //   tests and other situations want to be assured of freedom from
 //   errors, not just missing results. This should be recorded.
-// - Split this into a subpackage, gopls/internal/lsp/cache/driver,
+// - Split this into a subpackage, gopls/internal/cache/driver,
 //   consisting of this file and three helpers from errors.go.
 //   The (*snapshot).Analyze method would stay behind and make calls
 //   to the driver package.
@@ -172,7 +172,7 @@
 // The analyzers list must be duplicate free; order does not matter.
 //
 // Notifications of progress may be sent to the optional reporter.
-func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]unit, analyzers []*settings.Analyzer, reporter *progress.Tracker) ([]*Diagnostic, error) {
+func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Package, analyzers []*settings.Analyzer, reporter *progress.Tracker) ([]*Diagnostic, error) {
 	start := time.Now() // for progress reporting
 
 	var tagStr string // sorted comma-separated list of PackageIDs
@@ -1269,10 +1269,21 @@
 		factFilter[reflect.TypeOf(f)] = true
 	}
 
+	// If the package contains "fixed" files, it's not necessarily an error if we
+	// can't convert positions.
+	hasFixedFiles := false
+	for _, p := range pkg.parsed {
+		if p.Fixed() {
+			hasFixedFiles = true
+			break
+		}
+	}
+
 	// posToLocation converts from token.Pos to protocol form.
 	// TODO(adonovan): improve error messages.
 	posToLocation := func(start, end token.Pos) (protocol.Location, error) {
 		tokFile := pkg.fset.File(start)
+
 		for _, p := range pkg.parsed {
 			if p.Tok == tokFile {
 				if end == token.NoPos {
@@ -1281,8 +1292,11 @@
 				return p.PosLocation(start, end)
 			}
 		}
-		return protocol.Location{},
-			bug.Errorf("internal error: token.Pos not within package")
+		errorf := bug.Errorf
+		if hasFixedFiles {
+			errorf = fmt.Errorf
+		}
+		return protocol.Location{}, errorf("token.Pos not within package")
 	}
 
 	// Now run the (pkg, analyzer) action.
@@ -1299,7 +1313,9 @@
 		Report: func(d analysis.Diagnostic) {
 			diagnostic, err := toGobDiagnostic(posToLocation, analyzer, d)
 			if err != nil {
-				bug.Reportf("internal error converting diagnostic from analyzer %q: %v", analyzer.Name, err)
+				if !hasFixedFiles {
+					bug.Reportf("internal error converting diagnostic from analyzer %q: %v", analyzer.Name, err)
+				}
 				return
 			}
 			diagnostics = append(diagnostics, diagnostic)
@@ -1421,7 +1437,7 @@
 
 var analyzeSummaryCodec = frob.CodecFor[*analyzeSummary]()
 
-// -- data types for serialization of analysis.Diagnostic and source.Diagnostic --
+// -- data types for serialization of analysis.Diagnostic and golang.Diagnostic --
 
 // (The name says gob but we use frob.)
 var diagnosticsCodec = frob.CodecFor[[]gobDiagnostic]()
diff --git a/gopls/internal/cache/cache.go b/gopls/internal/cache/cache.go
new file mode 100644
index 0000000..a6a166a
--- /dev/null
+++ b/gopls/internal/cache/cache.go
@@ -0,0 +1,76 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cache
+
+import (
+	"reflect"
+	"strconv"
+	"sync/atomic"
+
+	"golang.org/x/tools/gopls/internal/protocol/command"
+	"golang.org/x/tools/internal/imports"
+	"golang.org/x/tools/internal/memoize"
+)
+
+// New Creates a new cache for gopls operation results, using the given file
+// set, shared store, and session options.
+//
+// Both the fset and store may be nil, but if store is non-nil so must be fset
+// (and they must always be used together), otherwise it may be possible to get
+// cached data referencing token.Pos values not mapped by the FileSet.
+func New(store *memoize.Store) *Cache {
+	index := atomic.AddInt64(&cacheIndex, 1)
+
+	if store == nil {
+		store = &memoize.Store{}
+	}
+
+	c := &Cache{
+		id:         strconv.FormatInt(index, 10),
+		store:      store,
+		memoizedFS: newMemoizedFS(),
+		modCache: &sharedModCache{
+			caches: make(map[string]*imports.DirInfoCache),
+			timers: make(map[string]*refreshTimer),
+		},
+	}
+	return c
+}
+
+// A Cache holds content that is shared across multiple gopls sessions.
+type Cache struct {
+	id string
+
+	// store holds cached calculations.
+	//
+	// TODO(rfindley): at this point, these are not important, as we've moved our
+	// content-addressable cache to the file system (the filecache package). It
+	// is unlikely that this shared cache provides any shared value. We should
+	// consider removing it, replacing current uses with a simpler futures cache,
+	// as we've done for e.g. type-checked packages.
+	store *memoize.Store
+
+	// memoizedFS holds a shared file.Source that caches reads.
+	//
+	// Reads are invalidated when *any* session gets a didChangeWatchedFile
+	// notification. This is fine: it is the responsibility of memoizedFS to hold
+	// our best knowledge of the current file system state.
+	*memoizedFS
+
+	// modCache holds the
+	modCache *sharedModCache
+}
+
+var cacheIndex, sessionIndex, viewIndex int64
+
+func (c *Cache) ID() string                     { return c.id }
+func (c *Cache) MemStats() map[reflect.Type]int { return c.store.Stats() }
+
+// FileStats returns information about the set of files stored in the cache.
+// It is intended for debugging only.
+func (c *Cache) FileStats() (stats command.FileStats) {
+	stats.Total, stats.Largest, stats.Errs = c.fileStats()
+	return
+}
diff --git a/gopls/internal/lsp/cache/check.go b/gopls/internal/cache/check.go
similarity index 97%
rename from gopls/internal/lsp/cache/check.go
rename to gopls/internal/cache/check.go
index 502ebb2..0af5965 100644
--- a/gopls/internal/lsp/cache/check.go
+++ b/gopls/internal/cache/check.go
@@ -22,11 +22,11 @@
 	"golang.org/x/mod/module"
 	"golang.org/x/sync/errgroup"
 	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/typerefs"
 	"golang.org/x/tools/gopls/internal/file"
 	"golang.org/x/tools/gopls/internal/filecache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/typerefs"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/analysisinternal"
@@ -610,6 +610,16 @@
 			if item.Path == string(mp.PkgPath) {
 				id = mp.ID
 				pkg = thisPackage
+
+				// debugging issues #60904, #64235
+				if pkg.Name() != item.Name {
+					// This would mean that mp.Name != item.Name, so the
+					// manifest in the export data of mp.PkgPath is
+					// inconsistent with mp.Name. Or perhaps there
+					// are duplicate PkgPath items in the manifest?
+					return bug.Errorf("internal error: package name is %q, want %q (id=%q, path=%q) (see issue #60904)",
+						pkg.Name(), item.Name, id, item.Path)
+				}
 			} else {
 				id = impMap[item.Path]
 				var err error
@@ -617,14 +627,22 @@
 				if err != nil {
 					return err
 				}
+
+				// We intentionally duplicate the bug.Errorf calls because
+				// telemetry tells us only the program counter, not the message.
+
+				// debugging issues #60904, #64235
+				if pkg.Name() != item.Name {
+					// This means that, while reading the manifest of the
+					// export data of mp.PkgPath, one of its indirect
+					// dependencies had a name that differs from the
+					// Metadata.Name
+					return bug.Errorf("internal error: package name is %q, want %q (id=%q, path=%q) (see issue #60904)",
+						pkg.Name(), item.Name, id, item.Path)
+				}
 			}
 			items[i].Pkg = pkg
 
-			// debugging issue #60904
-			if pkg.Name() != item.Name {
-				return bug.Errorf("internal error: package name is %q, want %q (id=%q, path=%q) (see issue #60904)",
-					pkg.Name(), item.Name, id, item.Path)
-			}
 		}
 		return nil
 	}
@@ -724,7 +742,11 @@
 	populateDeps = func(parent *metadata.Package) {
 		for _, id := range parent.DepsByPkgPath {
 			mp := b.handles[id].mp
-			if _, ok := impMap[string(mp.PkgPath)]; ok {
+			if prevID, ok := impMap[string(mp.PkgPath)]; ok {
+				// debugging #63822
+				if prevID != mp.ID {
+					bug.Reportf("inconsistent view of dependencies")
+				}
 				continue
 			}
 			impMap[string(mp.PkgPath)] = mp.ID
@@ -1565,8 +1587,8 @@
 	return &Package{ph.mp, ph.loadDiagnostics, pkg}, nil
 }
 
-// TODO(golang/go#63472): this looks wrong with the new Go version syntax.
-var goVersionRx = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
+// e.g. "go1" or "go1.2" or "go1.2.3"
+var goVersionRx = regexp.MustCompile(`^go[1-9][0-9]*(?:\.(0|[1-9][0-9]*)){0,2}$`)
 
 func (b *typeCheckBatch) typesConfig(ctx context.Context, inputs typeCheckInputs, onError func(e error)) *types.Config {
 	cfg := &types.Config{
@@ -1693,7 +1715,7 @@
 					Message:        fmt.Sprintf("error while importing %v: %v", item, depErr.Err),
 					SuggestedFixes: goGetQuickFixes(mp.Module != nil, imp.cgf.URI, item),
 				}
-				if !BundleQuickFixes(diag) {
+				if !bundleQuickFixes(diag) {
 					bug.Reportf("failed to bundle fixes for diagnostic %q", diag.Message)
 				}
 				errors = append(errors, diag)
@@ -1736,7 +1758,7 @@
 				Message:        fmt.Sprintf("error while importing %v: %v", item, depErr.Err),
 				SuggestedFixes: goGetQuickFixes(true, pm.URI, item),
 			}
-			if !BundleQuickFixes(diag) {
+			if !bundleQuickFixes(diag) {
 				bug.Reportf("failed to bundle fixes for diagnostic %q", diag.Message)
 			}
 			errors = append(errors, diag)
diff --git a/gopls/internal/lsp/cache/constraints.go b/gopls/internal/cache/constraints.go
similarity index 100%
rename from gopls/internal/lsp/cache/constraints.go
rename to gopls/internal/cache/constraints.go
diff --git a/gopls/internal/lsp/cache/constraints_test.go b/gopls/internal/cache/constraints_test.go
similarity index 74%
rename from gopls/internal/lsp/cache/constraints_test.go
rename to gopls/internal/cache/constraints_test.go
index 9adf01e..23c9f39 100644
--- a/gopls/internal/lsp/cache/constraints_test.go
+++ b/gopls/internal/cache/constraints_test.go
@@ -94,3 +94,33 @@
 		})
 	}
 }
+
+func TestVersionRegexp(t *testing.T) {
+	// good
+	for _, s := range []string{
+		"go1",
+		"go1.2",
+		"go1.2.3",
+		"go1.0.33",
+	} {
+		if !goVersionRx.MatchString(s) {
+			t.Errorf("Valid Go version %q does not match the regexp", s)
+		}
+	}
+
+	// bad
+	for _, s := range []string{
+		"go",          // missing numbers
+		"go0",         // Go starts at 1
+		"go01",        // leading zero
+		"go1.π",       // non-decimal
+		"go1.-1",      // negative
+		"go1.02.3",    // leading zero
+		"go1.2.3.4",   // too many segments
+		"go1.2.3-pre", // textual suffix
+	} {
+		if goVersionRx.MatchString(s) {
+			t.Errorf("Invalid Go version %q unexpectedly matches the regexp", s)
+		}
+	}
+}
diff --git a/gopls/internal/lsp/cache/debug.go b/gopls/internal/cache/debug.go
similarity index 100%
rename from gopls/internal/lsp/cache/debug.go
rename to gopls/internal/cache/debug.go
diff --git a/gopls/internal/lsp/cache/diagnostics.go b/gopls/internal/cache/diagnostics.go
similarity index 92%
rename from gopls/internal/lsp/cache/diagnostics.go
rename to gopls/internal/cache/diagnostics.go
index 76c8263..5489b56 100644
--- a/gopls/internal/lsp/cache/diagnostics.go
+++ b/gopls/internal/cache/diagnostics.go
@@ -8,7 +8,7 @@
 	"encoding/json"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 )
 
@@ -37,7 +37,7 @@
 	URI      protocol.DocumentURI // of diagnosed file (not diagnostic documentation)
 	Range    protocol.Range
 	Severity protocol.DiagnosticSeverity
-	Code     string
+	Code     string // analysis.Diagnostic.Category (or "default" if empty) or hidden go/types error code
 	CodeHref string
 
 	// Source is a human-readable description of the source of the error.
@@ -119,10 +119,10 @@
 	Fixes []protocol.CodeAction
 }
 
-// BundleQuickFixes attempts to bundle sd.SuggestedFixes into the
+// bundleQuickFixes attempts to bundle sd.SuggestedFixes into the
 // sd.BundledFixes field, so that it can be round-tripped through the client.
 // It returns false if the quick-fixes cannot be bundled.
-func BundleQuickFixes(sd *Diagnostic) bool {
+func bundleQuickFixes(sd *Diagnostic) bool {
 	if len(sd.SuggestedFixes) == 0 {
 		return true
 	}
@@ -164,16 +164,13 @@
 // BundledQuickFixes extracts any bundled codeActions from the
 // diag.Data field.
 func BundledQuickFixes(diag protocol.Diagnostic) []protocol.CodeAction {
-	// Clients may express "no fixes" in a variety of ways (#64503).
-	if diag.Data == nil ||
-		len(*diag.Data) == 0 ||
-		len(*diag.Data) == 4 && string(*diag.Data) == "null" {
-		return nil
-	}
 	var fix quickFixesJSON
-	if err := json.Unmarshal(*diag.Data, &fix); err != nil {
-		bug.Reportf("unmarshalling quick fix: %v", err)
-		return nil
+	if diag.Data != nil {
+		err := protocol.UnmarshalJSON(*diag.Data, &fix)
+		if err != nil {
+			bug.Reportf("unmarshalling quick fix: %v", err)
+			return nil
+		}
 	}
 
 	var actions []protocol.CodeAction
diff --git a/gopls/internal/lsp/cache/errors.go b/gopls/internal/cache/errors.go
similarity index 86%
rename from gopls/internal/lsp/cache/errors.go
rename to gopls/internal/cache/errors.go
index ded226e..1ed193b 100644
--- a/gopls/internal/lsp/cache/errors.go
+++ b/gopls/internal/cache/errors.go
@@ -6,7 +6,7 @@
 
 // This file defines routines to convert diagnostics from go list, go
 // get, go/packages, parsing, type checking, and analysis into
-// source.Diagnostic form, and suggesting quick fixes.
+// golang.Diagnostic form, and suggesting quick fixes.
 
 import (
 	"context"
@@ -21,11 +21,10 @@
 	"strings"
 
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/gopls/internal/analysis/embeddirective"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/protocol/command"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/internal/typesinternal"
@@ -295,27 +294,47 @@
 		Related:  related,
 		Tags:     srcAnalyzer.Tag,
 	}
-	if canFix(srcAnalyzer, diag) {
-		// We cross the set of fixes (whether edit- or command-based)
-		// with the set of kinds, as a single fix may represent more
-		// than one kind of action (e.g. refactor, quickfix, fixall),
-		// each corresponding to a distinct client UI element
-		// or operation.
-		kinds := srcAnalyzer.ActionKind
-		if len(kinds) == 0 {
-			kinds = []protocol.CodeActionKind{protocol.QuickFix}
-		}
 
-		// Accumulate edit-based fixes supplied by the diagnostic itself.
-		fixes := suggestedAnalysisFixes(gobDiag, kinds)
+	// We cross the set of fixes (whether edit- or command-based)
+	// with the set of kinds, as a single fix may represent more
+	// than one kind of action (e.g. refactor, quickfix, fixall),
+	// each corresponding to a distinct client UI element
+	// or operation.
+	kinds := srcAnalyzer.ActionKinds
+	if len(kinds) == 0 {
+		kinds = []protocol.CodeActionKind{protocol.QuickFix}
+	}
 
-		// Accumulate command-based fixes computed on demand by
-		// (logic adjacent to) the analyzer.
-		if srcAnalyzer.Fix != "" {
-			cmd, err := command.NewApplyFixCommand(gobDiag.Message, command.ApplyFixArgs{
+	var fixes []SuggestedFix
+	for _, fix := range gobDiag.SuggestedFixes {
+		if len(fix.TextEdits) > 0 {
+			// Accumulate edit-based fixes supplied by the diagnostic itself.
+			edits := make(map[protocol.DocumentURI][]protocol.TextEdit)
+			for _, e := range fix.TextEdits {
+				uri := e.Location.URI
+				edits[uri] = append(edits[uri], protocol.TextEdit{
+					Range:   e.Location.Range,
+					NewText: string(e.NewText),
+				})
+			}
+			for _, kind := range kinds {
+				fixes = append(fixes, SuggestedFix{
+					Title:      fix.Message,
+					Edits:      edits,
+					ActionKind: kind,
+				})
+			}
+
+		} else {
+			// Accumulate command-based fixes, whose edits
+			// are not provided by the analyzer but are computed on demand
+			// by logic "adjacent to" the analyzer.
+			//
+			// The analysis.Diagnostic.Category is used as the fix name.
+			cmd, err := command.NewApplyFixCommand(fix.Message, command.ApplyFixArgs{
+				Fix:   diag.Code,
 				URI:   gobDiag.Location.URI,
 				Range: gobDiag.Location.Range,
-				Fix:   string(srcAnalyzer.Fix),
 			})
 			if err != nil {
 				// JSON marshalling of these argument values cannot fail.
@@ -324,9 +343,14 @@
 			for _, kind := range kinds {
 				fixes = append(fixes, SuggestedFixFromCommand(cmd, kind))
 			}
+
+			// Ensure that the analyzer specifies a category for all its no-edit fixes.
+			if diag.Code == "" || diag.Code == "default" {
+				panic(fmt.Sprintf("missing Diagnostic.Code: %#v", *diag))
+			}
 		}
-		diag.SuggestedFixes = fixes
 	}
+	diag.SuggestedFixes = fixes
 
 	// If the fixes only delete code, assume that the diagnostic is reporting dead code.
 	if onlyDeletions(diag.SuggestedFixes) {
@@ -335,17 +359,6 @@
 	return diag
 }
 
-// canFix reports whether the Analyzer can fix the Diagnostic.
-func canFix(a *settings.Analyzer, diag *Diagnostic) bool {
-	if a.Fix == settings.AddEmbedImport {
-		return diag.Message == embeddirective.MissingImportMessage
-	}
-
-	// This doesn't make sense, but preserves pre-existing semantics.
-	// TODO(rfindley): reconcile the semantics of Fix and suggestedAnalysisFixes.
-	return true
-}
-
 // onlyDeletions returns true if fixes is non-empty and all of the suggested
 // fixes are deletions.
 func onlyDeletions(fixes []SuggestedFix) bool {
@@ -380,31 +393,6 @@
 	return link + "#" + anchor
 }
 
-// suggestedAnalysisFixes converts edit-based fixes associated
-// with a gobDiagnostic to cache.SuggestedFixes.
-// It returns the cross product of fixes and kinds.
-func suggestedAnalysisFixes(diag *gobDiagnostic, kinds []protocol.CodeActionKind) []SuggestedFix {
-	var fixes []SuggestedFix
-	for _, fix := range diag.SuggestedFixes {
-		edits := make(map[protocol.DocumentURI][]protocol.TextEdit)
-		for _, e := range fix.TextEdits {
-			uri := e.Location.URI
-			edits[uri] = append(edits[uri], protocol.TextEdit{
-				Range:   e.Location.Range,
-				NewText: string(e.NewText),
-			})
-		}
-		for _, kind := range kinds {
-			fixes = append(fixes, SuggestedFix{
-				Title:      fix.Message,
-				Edits:      edits,
-				ActionKind: kind,
-			})
-		}
-	}
-	return fixes
-}
-
 func parseGoListError(e packages.Error, dir string) (filename string, line, col8 int) {
 	input := e.Pos
 	if input == "" {
diff --git a/gopls/internal/lsp/cache/errors_test.go b/gopls/internal/cache/errors_test.go
similarity index 98%
rename from gopls/internal/lsp/cache/errors_test.go
rename to gopls/internal/cache/errors_test.go
index 38bd652..56b29c3 100644
--- a/gopls/internal/lsp/cache/errors_test.go
+++ b/gopls/internal/cache/errors_test.go
@@ -11,7 +11,7 @@
 
 	"github.com/google/go-cmp/cmp"
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 func TestParseErrorMessage(t *testing.T) {
diff --git a/gopls/internal/lsp/cache/filemap.go b/gopls/internal/cache/filemap.go
similarity index 71%
rename from gopls/internal/lsp/cache/filemap.go
rename to gopls/internal/cache/filemap.go
index 8ca7ab7..ee64d7c 100644
--- a/gopls/internal/lsp/cache/filemap.go
+++ b/gopls/internal/cache/filemap.go
@@ -8,7 +8,7 @@
 	"path/filepath"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/persistent"
 )
 
@@ -17,21 +17,21 @@
 // file.
 type fileMap struct {
 	files    *persistent.Map[protocol.DocumentURI, file.Handle]
-	overlays *persistent.Map[protocol.DocumentURI, *Overlay] // the subset of files that are overlays
+	overlays *persistent.Map[protocol.DocumentURI, *overlay] // the subset of files that are overlays
 	dirs     *persistent.Set[string]                         // all dirs containing files; if nil, dirs have not been initialized
 }
 
 func newFileMap() *fileMap {
 	return &fileMap{
 		files:    new(persistent.Map[protocol.DocumentURI, file.Handle]),
-		overlays: new(persistent.Map[protocol.DocumentURI, *Overlay]),
+		overlays: new(persistent.Map[protocol.DocumentURI, *overlay]),
 		dirs:     new(persistent.Set[string]),
 	}
 }
 
-// Clone creates a copy of the fileMap, incorporating the changes specified by
+// clone creates a copy of the fileMap, incorporating the changes specified by
 // the changes map.
-func (m *fileMap) Clone(changes map[protocol.DocumentURI]file.Handle) *fileMap {
+func (m *fileMap) clone(changes map[protocol.DocumentURI]file.Handle) *fileMap {
 	m2 := &fileMap{
 		files:    m.files.Clone(),
 		overlays: m.overlays.Clone(),
@@ -52,18 +52,18 @@
 	// first, as a set before a deletion would result in pointless work.
 	for uri, fh := range changes {
 		if !fileExists(fh) {
-			m2.Delete(uri)
+			m2.delete(uri)
 		}
 	}
 	for uri, fh := range changes {
 		if fileExists(fh) {
-			m2.Set(uri, fh)
+			m2.set(uri, fh)
 		}
 	}
 	return m2
 }
 
-func (m *fileMap) Destroy() {
+func (m *fileMap) destroy() {
 	m.files.Destroy()
 	m.overlays.Destroy()
 	if m.dirs != nil {
@@ -71,24 +71,24 @@
 	}
 }
 
-// Get returns the file handle mapped by the given key, or (nil, false) if the
+// get returns the file handle mapped by the given key, or (nil, false) if the
 // key is not present.
-func (m *fileMap) Get(key protocol.DocumentURI) (file.Handle, bool) {
+func (m *fileMap) get(key protocol.DocumentURI) (file.Handle, bool) {
 	return m.files.Get(key)
 }
 
-// Range calls f for each (uri, fh) in the map.
-func (m *fileMap) Range(f func(uri protocol.DocumentURI, fh file.Handle)) {
+// foreach calls f for each (uri, fh) in the map.
+func (m *fileMap) foreach(f func(uri protocol.DocumentURI, fh file.Handle)) {
 	m.files.Range(f)
 }
 
-// Set stores the given file handle for key, updating overlays and directories
+// set stores the given file handle for key, updating overlays and directories
 // accordingly.
-func (m *fileMap) Set(key protocol.DocumentURI, fh file.Handle) {
+func (m *fileMap) set(key protocol.DocumentURI, fh file.Handle) {
 	m.files.Set(key, fh, nil)
 
 	// update overlays
-	if o, ok := fh.(*Overlay); ok {
+	if o, ok := fh.(*overlay); ok {
 		m.overlays.Set(key, o, nil)
 	} else {
 		// Setting a non-overlay must delete the corresponding overlay, to preserve
@@ -111,9 +111,9 @@
 	}
 }
 
-// Delete removes a file from the map, and updates overlays and dirs
+// delete removes a file from the map, and updates overlays and dirs
 // accordingly.
-func (m *fileMap) Delete(key protocol.DocumentURI) {
+func (m *fileMap) delete(key protocol.DocumentURI) {
 	m.files.Delete(key)
 	m.overlays.Delete(key)
 
@@ -127,20 +127,20 @@
 	}
 }
 
-// Overlays returns a new unordered array of overlay files.
-func (m *fileMap) Overlays() []*Overlay {
-	var overlays []*Overlay
-	m.overlays.Range(func(_ protocol.DocumentURI, o *Overlay) {
+// getOverlays returns a new unordered array of overlay files.
+func (m *fileMap) getOverlays() []*overlay {
+	var overlays []*overlay
+	m.overlays.Range(func(_ protocol.DocumentURI, o *overlay) {
 		overlays = append(overlays, o)
 	})
 	return overlays
 }
 
-// Dirs reports returns the set of dirs observed by the fileMap.
+// getDirs reports returns the set of dirs observed by the fileMap.
 //
 // This operation mutates the fileMap.
 // The result must not be mutated by the caller.
-func (m *fileMap) Dirs() *persistent.Set[string] {
+func (m *fileMap) getDirs() *persistent.Set[string] {
 	if m.dirs == nil {
 		m.dirs = new(persistent.Set[string])
 		m.files.Range(func(u protocol.DocumentURI, _ file.Handle) {
diff --git a/gopls/internal/lsp/cache/filemap_test.go b/gopls/internal/cache/filemap_test.go
similarity index 89%
rename from gopls/internal/lsp/cache/filemap_test.go
rename to gopls/internal/cache/filemap_test.go
index d829d24..13f2c1a 100644
--- a/gopls/internal/lsp/cache/filemap_test.go
+++ b/gopls/internal/cache/filemap_test.go
@@ -11,7 +11,7 @@
 
 	"github.com/google/go-cmp/cmp"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 func TestFileMap(t *testing.T) {
@@ -72,18 +72,18 @@
 				case set:
 					var fh file.Handle
 					if op.overlay {
-						fh = &Overlay{uri: uri}
+						fh = &overlay{uri: uri}
 					} else {
-						fh = &DiskFile{uri: uri}
+						fh = &diskFile{uri: uri}
 					}
-					m.Set(uri, fh)
+					m.set(uri, fh)
 				case del:
-					m.Delete(uri)
+					m.delete(uri)
 				}
 			}
 
 			var gotFiles []string
-			m.Range(func(uri protocol.DocumentURI, _ file.Handle) {
+			m.foreach(func(uri protocol.DocumentURI, _ file.Handle) {
 				gotFiles = append(gotFiles, normalize(uri.Path()))
 			})
 			sort.Strings(gotFiles)
@@ -92,7 +92,7 @@
 			}
 
 			var gotOverlays []string
-			for _, o := range m.Overlays() {
+			for _, o := range m.getOverlays() {
 				gotOverlays = append(gotOverlays, normalize(o.URI().Path()))
 			}
 			if diff := cmp.Diff(test.wantOverlays, gotOverlays); diff != "" {
@@ -100,7 +100,7 @@
 			}
 
 			var gotDirs []string
-			m.Dirs().Range(func(dir string) {
+			m.getDirs().Range(func(dir string) {
 				gotDirs = append(gotDirs, normalize(dir))
 			})
 			sort.Strings(gotDirs)
diff --git a/gopls/internal/lsp/cache/filterer.go b/gopls/internal/cache/filterer.go
similarity index 100%
rename from gopls/internal/lsp/cache/filterer.go
rename to gopls/internal/cache/filterer.go
diff --git a/gopls/internal/lsp/cache/fs_memoized.go b/gopls/internal/cache/fs_memoized.go
similarity index 84%
rename from gopls/internal/lsp/cache/fs_memoized.go
rename to gopls/internal/cache/fs_memoized.go
index 11f877d..dd8293f 100644
--- a/gopls/internal/lsp/cache/fs_memoized.go
+++ b/gopls/internal/cache/fs_memoized.go
@@ -11,7 +11,7 @@
 	"time"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
 	"golang.org/x/tools/internal/robustio"
@@ -24,16 +24,16 @@
 	// filesByID maps existing file inodes to the result of a read.
 	// (The read may have failed, e.g. due to EACCES or a delete between stat+read.)
 	// Each slice is a non-empty list of aliases: different URIs.
-	filesByID map[robustio.FileID][]*DiskFile
+	filesByID map[robustio.FileID][]*diskFile
 }
 
 func newMemoizedFS() *memoizedFS {
-	return &memoizedFS{filesByID: make(map[robustio.FileID][]*DiskFile)}
+	return &memoizedFS{filesByID: make(map[robustio.FileID][]*diskFile)}
 }
 
-// A DiskFile is a file on the filesystem, or a failure to read one.
-// It implements the source.FileHandle interface.
-type DiskFile struct {
+// A diskFile is a file in the filesystem, or a failure to read one.
+// It implements the file.Source interface.
+type diskFile struct {
 	uri     protocol.DocumentURI
 	modTime time.Time
 	content []byte
@@ -41,25 +41,25 @@
 	err     error
 }
 
-func (h *DiskFile) URI() protocol.DocumentURI { return h.uri }
+func (h *diskFile) URI() protocol.DocumentURI { return h.uri }
 
-func (h *DiskFile) Identity() file.Identity {
+func (h *diskFile) Identity() file.Identity {
 	return file.Identity{
 		URI:  h.uri,
 		Hash: h.hash,
 	}
 }
 
-func (h *DiskFile) SameContentsOnDisk() bool { return true }
-func (h *DiskFile) Version() int32           { return 0 }
-func (h *DiskFile) Content() ([]byte, error) { return h.content, h.err }
+func (h *diskFile) SameContentsOnDisk() bool { return true }
+func (h *diskFile) Version() int32           { return 0 }
+func (h *diskFile) Content() ([]byte, error) { return h.content, h.err }
 
 // ReadFile stats and (maybe) reads the file, updates the cache, and returns it.
 func (fs *memoizedFS) ReadFile(ctx context.Context, uri protocol.DocumentURI) (file.Handle, error) {
 	id, mtime, err := robustio.GetFileID(uri.Path())
 	if err != nil {
 		// file does not exist
-		return &DiskFile{
+		return &diskFile{
 			err: err,
 			uri: uri,
 		}, nil
@@ -79,7 +79,7 @@
 	fs.mu.Lock()
 	fhs, ok := fs.filesByID[id]
 	if ok && fhs[0].modTime.Equal(mtime) {
-		var fh *DiskFile
+		var fh *diskFile
 		// We have already seen this file and it has not changed.
 		for _, h := range fhs {
 			if h.uri == uri {
@@ -108,7 +108,7 @@
 
 	fs.mu.Lock()
 	if !recentlyModified {
-		fs.filesByID[id] = []*DiskFile{fh}
+		fs.filesByID[id] = []*diskFile{fh}
 	} else {
 		delete(fs.filesByID, id)
 	}
@@ -141,7 +141,7 @@
 // ioLimit limits the number of parallel file reads per process.
 var ioLimit = make(chan struct{}, 128)
 
-func readFile(ctx context.Context, uri protocol.DocumentURI, mtime time.Time) (*DiskFile, error) {
+func readFile(ctx context.Context, uri protocol.DocumentURI, mtime time.Time) (*diskFile, error) {
 	select {
 	case ioLimit <- struct{}{}:
 	case <-ctx.Done():
@@ -161,7 +161,7 @@
 	if err != nil {
 		content = nil // just in case
 	}
-	return &DiskFile{
+	return &diskFile{
 		modTime: mtime,
 		uri:     uri,
 		content: content,
diff --git a/gopls/internal/lsp/cache/fs_overlay.go b/gopls/internal/cache/fs_overlay.go
similarity index 61%
rename from gopls/internal/lsp/cache/fs_overlay.go
rename to gopls/internal/cache/fs_overlay.go
index 8abfbc9..265598b 100644
--- a/gopls/internal/lsp/cache/fs_overlay.go
+++ b/gopls/internal/cache/fs_overlay.go
@@ -9,7 +9,7 @@
 	"sync"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // An overlayFS is a file.Source that keeps track of overlays on top of a
@@ -18,21 +18,21 @@
 	delegate file.Source
 
 	mu       sync.Mutex
-	overlays map[protocol.DocumentURI]*Overlay
+	overlays map[protocol.DocumentURI]*overlay
 }
 
 func newOverlayFS(delegate file.Source) *overlayFS {
 	return &overlayFS{
 		delegate: delegate,
-		overlays: make(map[protocol.DocumentURI]*Overlay),
+		overlays: make(map[protocol.DocumentURI]*overlay),
 	}
 }
 
 // Overlays returns a new unordered array of overlays.
-func (fs *overlayFS) Overlays() []*Overlay {
+func (fs *overlayFS) Overlays() []*overlay {
 	fs.mu.Lock()
 	defer fs.mu.Unlock()
-	overlays := make([]*Overlay, 0, len(fs.overlays))
+	overlays := make([]*overlay, 0, len(fs.overlays))
 	for _, overlay := range fs.overlays {
 		overlays = append(overlays, overlay)
 	}
@@ -49,9 +49,10 @@
 	return fs.delegate.ReadFile(ctx, uri)
 }
 
-// An Overlay is a file open in the editor. It may have unsaved edits.
-// It implements the file.Handle interface.
-type Overlay struct {
+// An overlay is a file open in the editor. It may have unsaved edits.
+// It implements the file.Handle interface, and the implicit contract
+// of the debug.FileTmpl template.
+type overlay struct {
 	uri     protocol.DocumentURI
 	content []byte
 	hash    file.Hash
@@ -63,16 +64,16 @@
 	saved bool
 }
 
-func (o *Overlay) URI() protocol.DocumentURI { return o.uri }
+func (o *overlay) URI() protocol.DocumentURI { return o.uri }
 
-func (o *Overlay) Identity() file.Identity {
+func (o *overlay) Identity() file.Identity {
 	return file.Identity{
 		URI:  o.uri,
 		Hash: o.hash,
 	}
 }
 
-func (o *Overlay) Content() ([]byte, error) { return o.content, nil }
-func (o *Overlay) Version() int32           { return o.version }
-func (o *Overlay) SameContentsOnDisk() bool { return o.saved }
-func (o *Overlay) Kind() file.Kind          { return o.kind }
+func (o *overlay) Content() ([]byte, error) { return o.content, nil }
+func (o *overlay) Version() int32           { return o.version }
+func (o *overlay) SameContentsOnDisk() bool { return o.saved }
+func (o *overlay) Kind() file.Kind          { return o.kind }
diff --git a/gopls/internal/cache/imports.go b/gopls/internal/cache/imports.go
new file mode 100644
index 0000000..7964427
--- /dev/null
+++ b/gopls/internal/cache/imports.go
@@ -0,0 +1,229 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cache
+
+import (
+	"context"
+	"fmt"
+	"sync"
+	"time"
+
+	"golang.org/x/tools/gopls/internal/file"
+	"golang.org/x/tools/internal/event"
+	"golang.org/x/tools/internal/event/keys"
+	"golang.org/x/tools/internal/event/tag"
+	"golang.org/x/tools/internal/imports"
+)
+
+// refreshTimer implements delayed asynchronous refreshing of state.
+//
+// See the [refreshTimer.schedule] documentation for more details.
+type refreshTimer struct {
+	mu        sync.Mutex
+	duration  time.Duration
+	timer     *time.Timer
+	refreshFn func()
+}
+
+// newRefreshTimer constructs a new refresh timer which schedules refreshes
+// using the given function.
+func newRefreshTimer(refresh func()) *refreshTimer {
+	return &refreshTimer{
+		refreshFn: refresh,
+	}
+}
+
+// schedule schedules the refresh function to run at some point in the future,
+// if no existing refresh is already scheduled.
+//
+// At a minimum, scheduled refreshes are delayed by 30s, but they may be
+// delayed longer to keep their expected execution time under 2% of wall clock
+// time.
+func (t *refreshTimer) schedule() {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+
+	if t.timer == nil {
+		// Don't refresh more than twice per minute.
+		delay := 30 * time.Second
+		// Don't spend more than ~2% of the time refreshing.
+		if adaptive := 50 * t.duration; adaptive > delay {
+			delay = adaptive
+		}
+		t.timer = time.AfterFunc(delay, func() {
+			start := time.Now()
+			t.refreshFn()
+			t.mu.Lock()
+			t.duration = time.Since(start)
+			t.timer = nil
+			t.mu.Unlock()
+		})
+	}
+}
+
+// A sharedModCache tracks goimports state for GOMODCACHE directories
+// (each session may have its own GOMODCACHE).
+//
+// This state is refreshed independently of view-specific imports state.
+type sharedModCache struct {
+	mu     sync.Mutex
+	caches map[string]*imports.DirInfoCache // GOMODCACHE -> cache content; never invalidated
+	timers map[string]*refreshTimer         // GOMODCACHE -> timer
+}
+
+func (c *sharedModCache) dirCache(dir string) *imports.DirInfoCache {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+
+	cache, ok := c.caches[dir]
+	if !ok {
+		cache = imports.NewDirInfoCache()
+		c.caches[dir] = cache
+	}
+	return cache
+}
+
+// refreshDir schedules a refresh of the given directory, which must be a
+// module cache.
+func (c *sharedModCache) refreshDir(ctx context.Context, dir string, logf func(string, ...any)) {
+	cache := c.dirCache(dir)
+
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	timer, ok := c.timers[dir]
+	if !ok {
+		timer = newRefreshTimer(func() {
+			_, done := event.Start(ctx, "cache.sharedModCache.refreshDir", tag.Directory.Of(dir))
+			defer done()
+			imports.ScanModuleCache(dir, cache, logf)
+		})
+		c.timers[dir] = timer
+	}
+
+	timer.schedule()
+}
+
+// importsState tracks view-specific imports state.
+type importsState struct {
+	ctx          context.Context
+	modCache     *sharedModCache
+	refreshTimer *refreshTimer
+
+	mu                sync.Mutex
+	processEnv        *imports.ProcessEnv
+	cachedModFileHash file.Hash
+}
+
+// newImportsState constructs a new imports state for running goimports
+// functions via [runProcessEnvFunc].
+//
+// The returned state will automatically refresh itself following a call to
+// runProcessEnvFunc.
+func newImportsState(backgroundCtx context.Context, modCache *sharedModCache, env *imports.ProcessEnv) *importsState {
+	s := &importsState{
+		ctx:        backgroundCtx,
+		modCache:   modCache,
+		processEnv: env,
+	}
+	s.refreshTimer = newRefreshTimer(s.refreshProcessEnv)
+	return s
+}
+
+// runProcessEnvFunc runs goimports.
+//
+// Any call to runProcessEnvFunc will schedule a refresh of the imports state
+// at some point in the future, if such a refresh is not already scheduled. See
+// [refreshTimer] for more details.
+func (s *importsState) runProcessEnvFunc(ctx context.Context, snapshot *Snapshot, fn func(context.Context, *imports.Options) error) error {
+	ctx, done := event.Start(ctx, "cache.importsState.runProcessEnvFunc")
+	defer done()
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	// Find the hash of active mod files, if any. Using the unsaved content
+	// is slightly wasteful, since we'll drop caches a little too often, but
+	// the mod file shouldn't be changing while people are autocompleting.
+	//
+	// TODO(rfindley): consider instead hashing on-disk modfiles here.
+	var modFileHash file.Hash
+	for m := range snapshot.view.workspaceModFiles {
+		fh, err := snapshot.ReadFile(ctx, m)
+		if err != nil {
+			return err
+		}
+		modFileHash.XORWith(fh.Identity().Hash)
+	}
+
+	// If anything relevant to imports has changed, clear caches and
+	// update the processEnv. Clearing caches blocks on any background
+	// scans.
+	if modFileHash != s.cachedModFileHash {
+		s.processEnv.ClearModuleInfo()
+		s.cachedModFileHash = modFileHash
+	}
+
+	// Run the user function.
+	opts := &imports.Options{
+		// Defaults.
+		AllErrors:   true,
+		Comments:    true,
+		Fragment:    true,
+		FormatOnly:  false,
+		TabIndent:   true,
+		TabWidth:    8,
+		Env:         s.processEnv,
+		LocalPrefix: snapshot.Options().Local,
+	}
+
+	if err := fn(ctx, opts); err != nil {
+		return err
+	}
+
+	// Refresh the imports resolver after usage. This may seem counterintuitive,
+	// since it means the first ProcessEnvFunc after a long period of inactivity
+	// may be stale, but in practice we run ProcessEnvFuncs frequently during
+	// active development (e.g. during completion), and so this mechanism will be
+	// active while gopls is in use, and inactive when gopls is idle.
+	s.refreshTimer.schedule()
+
+	// TODO(rfindley): the GOMODCACHE value used here isn't directly tied to the
+	// ProcessEnv.Env["GOMODCACHE"], though they should theoretically always
+	// agree. It would be better if we guaranteed this, possibly by setting all
+	// required environment variables in ProcessEnv.Env, to avoid the redundant
+	// Go command invocation.
+	gomodcache := snapshot.view.folder.Env.GOMODCACHE
+	s.modCache.refreshDir(s.ctx, gomodcache, s.processEnv.Logf)
+
+	return nil
+}
+
+func (s *importsState) refreshProcessEnv() {
+	ctx, done := event.Start(s.ctx, "cache.importsState.refreshProcessEnv")
+	defer done()
+
+	start := time.Now()
+
+	s.mu.Lock()
+	resolver, err := s.processEnv.GetResolver()
+	s.mu.Unlock()
+	if err != nil {
+		return
+	}
+
+	event.Log(s.ctx, "background imports cache refresh starting")
+
+	// Prime the new resolver before updating the processEnv, so that gopls
+	// doesn't wait on an unprimed cache.
+	if err := imports.PrimeCache(context.Background(), resolver); err == nil {
+		event.Log(ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start)))
+	} else {
+		event.Log(ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start)), keys.Err.Of(err))
+	}
+
+	s.mu.Lock()
+	s.processEnv.UpdateResolver(resolver)
+	s.mu.Unlock()
+}
diff --git a/gopls/internal/lsp/cache/keys.go b/gopls/internal/cache/keys.go
similarity index 98%
rename from gopls/internal/lsp/cache/keys.go
rename to gopls/internal/cache/keys.go
index 449daba..664e539 100644
--- a/gopls/internal/lsp/cache/keys.go
+++ b/gopls/internal/cache/keys.go
@@ -4,6 +4,8 @@
 
 package cache
 
+// session event tracing
+
 import (
 	"io"
 
diff --git a/gopls/internal/lsp/cache/load.go b/gopls/internal/cache/load.go
similarity index 89%
rename from gopls/internal/lsp/cache/load.go
rename to gopls/internal/cache/load.go
index 9831a4d..4bbeb2d 100644
--- a/gopls/internal/lsp/cache/load.go
+++ b/gopls/internal/cache/load.go
@@ -16,9 +16,9 @@
 	"time"
 
 	"golang.org/x/tools/go/packages"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/immutable"
 	"golang.org/x/tools/gopls/internal/util/pathutil"
@@ -151,6 +151,45 @@
 		event.Log(ctx, eventName, labels...)
 	}
 
+	if standalone {
+		// Handle standalone package result.
+		//
+		// In general, this should just be a single "command-line-arguments"
+		// package containing the requested file. However, if the file is a test
+		// file, go/packages may return test variants of the command-line-arguments
+		// package. We don't support this; theoretically we could, but it seems
+		// unnecessarily complicated.
+		//
+		// Prior to golang/go#64233 we just assumed that we'd get exactly one
+		// package here. The categorization of bug reports below may be a bit
+		// verbose, but anticipates that perhaps we don't fully understand
+		// possible failure modes.
+		errorf := bug.Errorf
+		if s.view.typ == GoPackagesDriverView {
+			errorf = fmt.Errorf // all bets are off
+		}
+
+		var standalonePkg *packages.Package
+		for _, pkg := range pkgs {
+			if pkg.ID == "command-line-arguments" {
+				if standalonePkg != nil {
+					return errorf("internal error: go/packages returned multiple standalone packages")
+				}
+				standalonePkg = pkg
+			} else if packagesinternal.GetForTest(pkg) == "" && !strings.HasSuffix(pkg.ID, ".test") {
+				return errorf("internal error: go/packages returned unexpected package %q for standalone file", pkg.ID)
+			}
+		}
+		if standalonePkg == nil {
+			return errorf("internal error: go/packages failed to return non-test standalone package")
+		}
+		if len(standalonePkg.CompiledGoFiles) > 0 {
+			pkgs = []*packages.Package{standalonePkg}
+		} else {
+			pkgs = nil
+		}
+	}
+
 	if len(pkgs) == 0 {
 		if err == nil {
 			err = errNoPackages
@@ -158,10 +197,6 @@
 		return fmt.Errorf("packages.Load error: %w", err)
 	}
 
-	if standalone && len(pkgs) > 1 {
-		return bug.Errorf("internal error: go/packages returned multiple packages for standalone file")
-	}
-
 	moduleErrs := make(map[string][]packages.Error) // module path -> errors
 	filterFunc := s.view.filterFunc()
 	newMetadata := make(map[PackageID]*metadata.Package)
@@ -306,13 +341,26 @@
 	id := PackageID(pkg.ID)
 
 	if metadata.IsCommandLineArguments(id) {
-		if len(pkg.CompiledGoFiles) != 1 {
-			bug.Reportf("unexpected files in command-line-arguments package: %v", pkg.CompiledGoFiles)
+		var f string // file to use as disambiguating suffix
+		if len(pkg.CompiledGoFiles) > 0 {
+			f = pkg.CompiledGoFiles[0]
+
+			// If there are multiple files,
+			// we can't use only the first.
+			// (Can this happen? #64557)
+			if len(pkg.CompiledGoFiles) > 1 {
+				bug.Reportf("unexpected files in command-line-arguments package: %v", pkg.CompiledGoFiles)
+				return
+			}
+		} else if len(pkg.IgnoredFiles) > 0 {
+			// A file=empty.go query results in IgnoredFiles=[empty.go].
+			f = pkg.IgnoredFiles[0]
+		} else {
+			bug.Reportf("command-line-arguments package has neither CompiledGoFiles nor IgnoredFiles: %#v", "") //*pkg.Metadata)
 			return
 		}
-		suffix := pkg.CompiledGoFiles[0]
-		id = PackageID(pkg.ID + suffix)
-		pkgPath = PackagePath(pkg.PkgPath + suffix)
+		id = PackageID(pkg.ID + f)
+		pkgPath = PackagePath(pkg.PkgPath + f)
 	}
 
 	// Duplicate?
@@ -601,8 +649,8 @@
 	}
 
 	for uri := range uris {
-		fh, _ := s.files.Get(uri)
-		if _, open := fh.(*Overlay); open {
+		fh, _ := s.files.get(uri)
+		if _, open := fh.(*overlay); open {
 			return true
 		}
 	}
diff --git a/gopls/internal/lsp/cache/metadata/cycle_test.go b/gopls/internal/cache/metadata/cycle_test.go
similarity index 80%
rename from gopls/internal/lsp/cache/metadata/cycle_test.go
rename to gopls/internal/cache/metadata/cycle_test.go
index 3597be7..09628d8 100644
--- a/gopls/internal/lsp/cache/metadata/cycle_test.go
+++ b/gopls/internal/cache/metadata/cycle_test.go
@@ -8,58 +8,25 @@
 	"sort"
 	"strings"
 	"testing"
+
+	"golang.org/x/tools/gopls/internal/util/bug"
 )
 
+func init() {
+	bug.PanicOnBugs = true
+}
+
 // This is an internal test of the breakImportCycles logic.
 func TestBreakImportCycles(t *testing.T) {
 
-	type Graph = map[PackageID]*Package
-
-	// cyclic returns a description of a cycle,
-	// if the graph is cyclic, otherwise "".
-	cyclic := func(graph Graph) string {
-		const (
-			unvisited = 0
-			visited   = 1
-			onstack   = 2
-		)
-		color := make(map[PackageID]int)
-		var visit func(id PackageID) string
-		visit = func(id PackageID) string {
-			switch color[id] {
-			case unvisited:
-				color[id] = onstack
-			case onstack:
-				return string(id) // cycle!
-			case visited:
-				return ""
-			}
-			if mp := graph[id]; mp != nil {
-				for _, depID := range mp.DepsByPkgPath {
-					if cycle := visit(depID); cycle != "" {
-						return string(id) + "->" + cycle
-					}
-				}
-			}
-			color[id] = visited
-			return ""
-		}
-		for id := range graph {
-			if cycle := visit(id); cycle != "" {
-				return cycle
-			}
-		}
-		return ""
-	}
-
 	// parse parses an import dependency graph.
 	// The input is a semicolon-separated list of node descriptions.
 	// Each node description is a package ID, optionally followed by
 	// "->" and a comma-separated list of successor IDs.
 	// Thus "a->b;b->c,d;e" represents the set of nodes {a,b,e}
 	// and the set of edges {a->b, b->c, b->d}.
-	parse := func(s string) Graph {
-		m := make(Graph)
+	parse := func(s string) map[PackageID]*Package {
+		m := make(map[PackageID]*Package)
 		makeNode := func(name string) *Package {
 			id := PackageID(name)
 			n, ok := m[id]
@@ -98,7 +65,7 @@
 	// format formats an import graph, in lexicographic order,
 	// in the notation of parse, but with a "!" after the name
 	// of each node that has errors.
-	format := func(graph Graph) string {
+	format := func(graph map[PackageID]*Package) string {
 		var items []string
 		for _, mp := range graph {
 			item := string(mp.ID)
diff --git a/gopls/internal/lsp/cache/metadata/graph.go b/gopls/internal/cache/metadata/graph.go
similarity index 88%
rename from gopls/internal/lsp/cache/metadata/graph.go
rename to gopls/internal/cache/metadata/graph.go
index ca8c683..f09822d 100644
--- a/gopls/internal/lsp/cache/metadata/graph.go
+++ b/gopls/internal/cache/metadata/graph.go
@@ -8,7 +8,7 @@
 	"sort"
 
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 )
 
@@ -38,6 +38,22 @@
 		return g
 	}
 
+	// Debugging golang/go#64227, golang/vscode-go#3126:
+	// Assert that the existing metadata graph is acyclic.
+	if cycle := cyclic(g.Packages); cycle != "" {
+		bug.Reportf("metadata is cyclic even before updates: %s", cycle)
+	}
+	// Assert that the updates contain no self-cycles.
+	for id, mp := range updates {
+		if mp != nil {
+			for _, depID := range mp.DepsByPkgPath {
+				if depID == id {
+					bug.Reportf("self-cycle in metadata update: %s", id)
+				}
+			}
+		}
+	}
+
 	// Copy pkgs map then apply updates.
 	pkgs := make(map[PackageID]*Package, len(g.Packages))
 	for id, mp := range g.Packages {
@@ -223,6 +239,43 @@
 	}
 }
 
+// cyclic returns a description of a cycle,
+// if the graph is cyclic, otherwise "".
+func cyclic(graph map[PackageID]*Package) string {
+	const (
+		unvisited = 0
+		visited   = 1
+		onstack   = 2
+	)
+	color := make(map[PackageID]int)
+	var visit func(id PackageID) string
+	visit = func(id PackageID) string {
+		switch color[id] {
+		case unvisited:
+			color[id] = onstack
+		case onstack:
+			return string(id) // cycle!
+		case visited:
+			return ""
+		}
+		if mp := graph[id]; mp != nil {
+			for _, depID := range mp.DepsByPkgPath {
+				if cycle := visit(depID); cycle != "" {
+					return string(id) + "->" + cycle
+				}
+			}
+		}
+		color[id] = visited
+		return ""
+	}
+	for id := range graph {
+		if cycle := visit(id); cycle != "" {
+			return cycle
+		}
+	}
+	return ""
+}
+
 // detectImportCycles reports cycles in the metadata graph. It returns a new
 // unordered array of all cycles (nontrivial strong components) in the
 // metadata graph reachable from a non-nil 'updates' value.
diff --git a/gopls/internal/lsp/cache/metadata/metadata.go b/gopls/internal/cache/metadata/metadata.go
similarity index 99%
rename from gopls/internal/lsp/cache/metadata/metadata.go
rename to gopls/internal/cache/metadata/metadata.go
index 922605c..b635516 100644
--- a/gopls/internal/lsp/cache/metadata/metadata.go
+++ b/gopls/internal/cache/metadata/metadata.go
@@ -20,7 +20,7 @@
 	"strings"
 
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/packagesinternal"
 )
 
diff --git a/gopls/internal/lsp/cache/methodsets/methodsets.go b/gopls/internal/cache/methodsets/methodsets.go
similarity index 100%
rename from gopls/internal/lsp/cache/methodsets/methodsets.go
rename to gopls/internal/cache/methodsets/methodsets.go
diff --git a/gopls/internal/lsp/cache/mod.go b/gopls/internal/cache/mod.go
similarity index 97%
rename from gopls/internal/lsp/cache/mod.go
rename to gopls/internal/cache/mod.go
index 6d83166..a120037 100644
--- a/gopls/internal/lsp/cache/mod.go
+++ b/gopls/internal/cache/mod.go
@@ -15,8 +15,8 @@
 	"golang.org/x/mod/modfile"
 	"golang.org/x/mod/module"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
 	"golang.org/x/tools/internal/gocommand"
@@ -350,7 +350,7 @@
 				// file/position information, so don't even try to find it.
 				continue
 			}
-			loc, found, err := s.matchErrorToModule(ctx, pm, msg)
+			loc, found, err := s.matchErrorToModule(pm, msg)
 			if err != nil {
 				event.Error(ctx, "matching error to module", err)
 				continue
@@ -395,7 +395,7 @@
 //
 // It returns the location of a reference to the one of the modules and true
 // if one exists. If none is found it returns a fallback location and false.
-func (s *Snapshot) matchErrorToModule(ctx context.Context, pm *ParsedModule, goCmdError string) (protocol.Location, bool, error) {
+func (s *Snapshot) matchErrorToModule(pm *ParsedModule, goCmdError string) (protocol.Location, bool, error) {
 	var reference *modfile.Line
 	matches := moduleVersionInErrorRe.FindAllStringSubmatch(goCmdError, -1)
 
diff --git a/gopls/internal/lsp/cache/mod_tidy.go b/gopls/internal/cache/mod_tidy.go
similarity index 98%
rename from gopls/internal/lsp/cache/mod_tidy.go
rename to gopls/internal/cache/mod_tidy.go
index 67c6d64..6dbe982 100644
--- a/gopls/internal/lsp/cache/mod_tidy.go
+++ b/gopls/internal/cache/mod_tidy.go
@@ -17,8 +17,8 @@
 
 	"golang.org/x/mod/modfile"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/diff"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
@@ -66,7 +66,7 @@
 		if err != nil {
 			return nil, err
 		}
-		if _, ok := fh.(*Overlay); ok {
+		if _, ok := fh.(*overlay); ok {
 			if info, _ := os.Stat(uri.Path()); info == nil {
 				return nil, ErrNoModOnDisk
 			}
diff --git a/gopls/internal/lsp/cache/mod_vuln.go b/gopls/internal/cache/mod_vuln.go
similarity index 98%
rename from gopls/internal/lsp/cache/mod_vuln.go
rename to gopls/internal/cache/mod_vuln.go
index 5704863..a92f5b5 100644
--- a/gopls/internal/lsp/cache/mod_vuln.go
+++ b/gopls/internal/cache/mod_vuln.go
@@ -16,8 +16,8 @@
 	"golang.org/x/mod/semver"
 	"golang.org/x/sync/errgroup"
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/vulncheck"
 	"golang.org/x/tools/gopls/internal/vulncheck/govulncheck"
 	"golang.org/x/tools/gopls/internal/vulncheck/osv"
diff --git a/gopls/internal/lsp/cache/os_darwin.go b/gopls/internal/cache/os_darwin.go
similarity index 100%
rename from gopls/internal/lsp/cache/os_darwin.go
rename to gopls/internal/cache/os_darwin.go
diff --git a/gopls/internal/lsp/cache/os_windows.go b/gopls/internal/cache/os_windows.go
similarity index 100%
rename from gopls/internal/lsp/cache/os_windows.go
rename to gopls/internal/cache/os_windows.go
diff --git a/gopls/internal/lsp/cache/parse.go b/gopls/internal/cache/parse.go
similarity index 95%
rename from gopls/internal/lsp/cache/parse.go
rename to gopls/internal/cache/parse.go
index 0f93a08..c8da20e 100644
--- a/gopls/internal/lsp/cache/parse.go
+++ b/gopls/internal/cache/parse.go
@@ -12,7 +12,7 @@
 	"path/filepath"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
 )
 
 // ParseGo parses the file whose contents are provided by fh.
diff --git a/gopls/internal/lsp/cache/parse_cache.go b/gopls/internal/cache/parse_cache.go
similarity index 98%
rename from gopls/internal/lsp/cache/parse_cache.go
rename to gopls/internal/cache/parse_cache.go
index 0e5160c..55eced5 100644
--- a/gopls/internal/lsp/cache/parse_cache.go
+++ b/gopls/internal/cache/parse_cache.go
@@ -18,8 +18,8 @@
 
 	"golang.org/x/sync/errgroup"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/memoize"
 	"golang.org/x/tools/internal/tokeninternal"
 )
diff --git a/gopls/internal/lsp/cache/parse_cache_test.go b/gopls/internal/cache/parse_cache_test.go
similarity index 98%
rename from gopls/internal/lsp/cache/parse_cache_test.go
rename to gopls/internal/cache/parse_cache_test.go
index 61a204d..eee7ded 100644
--- a/gopls/internal/lsp/cache/parse_cache_test.go
+++ b/gopls/internal/cache/parse_cache_test.go
@@ -13,7 +13,7 @@
 	"time"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 func skipIfNoParseCache(t *testing.T) {
diff --git a/gopls/internal/lsp/cache/parsego/file.go b/gopls/internal/cache/parsego/file.go
similarity index 98%
rename from gopls/internal/lsp/cache/parsego/file.go
rename to gopls/internal/cache/parsego/file.go
index 6f47ca3..3e13d5b 100644
--- a/gopls/internal/lsp/cache/parsego/file.go
+++ b/gopls/internal/cache/parsego/file.go
@@ -10,7 +10,7 @@
 	"go/scanner"
 	"go/token"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 )
 
diff --git a/gopls/internal/lsp/cache/parsego/parse.go b/gopls/internal/cache/parsego/parse.go
similarity index 99%
rename from gopls/internal/lsp/cache/parsego/parse.go
rename to gopls/internal/cache/parsego/parse.go
index 575699f..89fc15f 100644
--- a/gopls/internal/lsp/cache/parsego/parse.go
+++ b/gopls/internal/cache/parsego/parse.go
@@ -14,7 +14,7 @@
 	"go/token"
 	"reflect"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/astutil"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/diff"
diff --git a/gopls/internal/lsp/cache/parsego/parse_test.go b/gopls/internal/cache/parsego/parse_test.go
similarity index 95%
rename from gopls/internal/lsp/cache/parsego/parse_test.go
rename to gopls/internal/cache/parsego/parse_test.go
index 0c8f00b..4018e9e 100644
--- a/gopls/internal/lsp/cache/parsego/parse_test.go
+++ b/gopls/internal/cache/parsego/parse_test.go
@@ -10,7 +10,7 @@
 	"go/token"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/tokeninternal"
 )
diff --git a/gopls/internal/lsp/cache/pkg.go b/gopls/internal/cache/pkg.go
similarity index 81%
rename from gopls/internal/lsp/cache/pkg.go
rename to gopls/internal/cache/pkg.go
index 19b974f..821b1cc 100644
--- a/gopls/internal/lsp/cache/pkg.go
+++ b/gopls/internal/cache/pkg.go
@@ -5,7 +5,6 @@
 package cache
 
 import (
-	"context"
 	"fmt"
 	"go/ast"
 	"go/scanner"
@@ -13,29 +12,23 @@
 	"go/types"
 	"sync"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/methodsets"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/cache/xrefs"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/methodsets"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
+	"golang.org/x/tools/gopls/internal/cache/xrefs"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
-// Temporary refactoring, reversing the source import:
-// Types
+// Convenient aliases for very heavily used types.
 type (
-	// Metadata.
-	PackageID   = metadata.PackageID
-	PackagePath = metadata.PackagePath
-	PackageName = metadata.PackageName
-	ImportPath  = metadata.ImportPath
-
-	// Computed objects.
+	PackageID    = metadata.PackageID
+	PackagePath  = metadata.PackagePath
+	PackageName  = metadata.PackageName
+	ImportPath   = metadata.ImportPath
 	ParsedGoFile = parsego.File
 )
 
-// Values
-var (
-	// Parse Modes
+const (
 	ParseHeader = parsego.ParseHeader
 	ParseFull   = parsego.ParseFull
 )
@@ -172,19 +165,3 @@
 func (p *Package) GetTypeErrors() []types.Error {
 	return p.pkg.typeErrors
 }
-
-func (p *Package) DiagnosticsForFile(ctx context.Context, uri protocol.DocumentURI) ([]*Diagnostic, error) {
-	var diags []*Diagnostic
-	for _, diag := range p.loadDiagnostics {
-		if diag.URI == uri {
-			diags = append(diags, diag)
-		}
-	}
-	for _, diag := range p.pkg.diagnostics {
-		if diag.URI == uri {
-			diags = append(diags, diag)
-		}
-	}
-
-	return diags, nil
-}
diff --git a/gopls/internal/lsp/cache/port.go b/gopls/internal/cache/port.go
similarity index 100%
rename from gopls/internal/lsp/cache/port.go
rename to gopls/internal/cache/port.go
diff --git a/gopls/internal/lsp/cache/port_test.go b/gopls/internal/cache/port_test.go
similarity index 98%
rename from gopls/internal/lsp/cache/port_test.go
rename to gopls/internal/cache/port_test.go
index 96ba318..3c38a11 100644
--- a/gopls/internal/lsp/cache/port_test.go
+++ b/gopls/internal/cache/port_test.go
@@ -12,7 +12,7 @@
 	"golang.org/x/sync/errgroup"
 	"golang.org/x/tools/go/packages"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/internal/testenv"
 )
diff --git a/gopls/internal/lsp/cache/session.go b/gopls/internal/cache/session.go
similarity index 89%
rename from gopls/internal/lsp/cache/session.go
rename to gopls/internal/cache/session.go
index 7436bcb..102a226 100644
--- a/gopls/internal/lsp/cache/session.go
+++ b/gopls/internal/cache/session.go
@@ -15,13 +15,15 @@
 	"strings"
 	"sync"
 	"sync/atomic"
+	"time"
 
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/typerefs"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/typerefs"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/persistent"
+	"golang.org/x/tools/gopls/internal/util/slices"
 	"golang.org/x/tools/gopls/internal/vulncheck"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/gocommand"
@@ -30,6 +32,25 @@
 	"golang.org/x/tools/internal/xcontext"
 )
 
+// NewSession creates a new gopls session with the given cache.
+func NewSession(ctx context.Context, c *Cache) *Session {
+	index := atomic.AddInt64(&sessionIndex, 1)
+	s := &Session{
+		id:          strconv.FormatInt(index, 10),
+		cache:       c,
+		gocmdRunner: &gocommand.Runner{},
+		overlayFS:   newOverlayFS(c),
+		parseCache:  newParseCache(1 * time.Minute), // keep recently parsed files for a minute, to optimize typing CPU
+		viewMap:     make(map[protocol.DocumentURI]*View),
+	}
+	event.Log(ctx, "New session", KeyCreateSession.Of(s))
+	return s
+}
+
+// A Session holds the state (views, file contents, parse cache,
+// memoized computations) of a gopls server process.
+//
+// It implements the file.Source interface.
 type Session struct {
 	// Unique identifier for this session.
 	id string
@@ -42,6 +63,11 @@
 	views   []*View
 	viewMap map[protocol.DocumentURI]*View // file->best view; nil after shutdown
 
+	// snapshots is a counting semaphore that records the number
+	// of unreleased snapshots associated with this session.
+	// Shutdown waits for it to fall to zero.
+	snapshotWG sync.WaitGroup
+
 	parseCache *parseCache
 
 	*overlayFS
@@ -68,6 +94,7 @@
 		view.shutdown()
 	}
 	s.parseCache.stop()
+	s.snapshotWG.Wait() // wait for all work on associated snapshots to finish
 	event.Log(ctx, "Shutdown session", KeyShutdownSession.Of(s))
 }
 
@@ -164,6 +191,33 @@
 		ignoreFilter = newIgnoreFilter(dirs)
 	}
 
+	var pe *imports.ProcessEnv
+	{
+		env := make(map[string]string)
+		envSlice := slices.Concat(os.Environ(), def.folder.Options.EnvSlice(), []string{"GO111MODULE=" + def.adjustedGO111MODULE()})
+		for _, kv := range envSlice {
+			if k, v, ok := strings.Cut(kv, "="); ok {
+				env[k] = v
+			}
+		}
+		pe = &imports.ProcessEnv{
+			GocmdRunner: s.gocmdRunner,
+			BuildFlags:  slices.Clone(def.folder.Options.BuildFlags),
+			// TODO(rfindley): an old comment said "processEnv operations should not mutate the modfile"
+			// But shouldn't we honor the default behavior of mod vendoring?
+			ModFlag:        "readonly",
+			SkipPathInScan: skipPath,
+			Env:            env,
+			WorkingDir:     def.root.Path(),
+			ModCache:       s.cache.modCache.dirCache(def.folder.Env.GOMODCACHE),
+		}
+		if def.folder.Options.VerboseOutput {
+			pe.Logf = func(format string, args ...interface{}) {
+				event.Log(ctx, fmt.Sprintf(format, args...))
+			}
+		}
+	}
+
 	v := &View{
 		id:                   strconv.FormatInt(index, 10),
 		gocmdRunner:          s.gocmdRunner,
@@ -174,21 +228,17 @@
 		ignoreFilter:         ignoreFilter,
 		fs:                   s.overlayFS,
 		viewDefinition:       def,
-		importsState: &importsState{
-			ctx: backgroundCtx,
-			processEnv: &imports.ProcessEnv{
-				GocmdRunner:    s.gocmdRunner,
-				SkipPathInScan: skipPath,
-			},
-		},
+		importsState:         newImportsState(backgroundCtx, s.cache.modCache, pe),
 	}
 
+	s.snapshotWG.Add(1)
 	v.snapshot = &Snapshot{
 		view:             v,
 		backgroundCtx:    backgroundCtx,
 		cancel:           cancel,
 		store:            s.cache.store,
 		refcount:         1, // Snapshots are born referenced.
+		done:             s.snapshotWG.Done,
 		packages:         new(persistent.Map[PackageID, *packageHandle]),
 		meta:             new(metadata.Graph),
 		files:            newFileMap(),
@@ -217,7 +267,7 @@
 
 	// Initialize the view without blocking.
 	initCtx, initCancel := context.WithCancel(xcontext.Detach(ctx))
-	v.initCancelFirstAttempt = initCancel
+	v.cancelInitialWorkspaceLoad = initCancel
 	snapshot := v.snapshot
 
 	// Pass a second reference to the background goroutine.
@@ -603,7 +653,7 @@
 //
 // If the resulting error is non-nil, the view may or may not have already been
 // dropped from the session.
-func (s *Session) updateViewLocked(ctx context.Context, view *View, def *viewDefinition, folder *Folder) (*View, error) {
+func (s *Session) updateViewLocked(ctx context.Context, view *View, def *viewDefinition) (*View, error) {
 	i := s.dropView(view)
 	if i == -1 {
 		return nil, fmt.Errorf("view %q not found", view.id)
@@ -655,7 +705,7 @@
 	if err != nil {
 		return nil, err
 	}
-	return s.updateViewLocked(ctx, v, v.viewDefinition, v.folder)
+	return s.updateViewLocked(ctx, v, v.viewDefinition)
 }
 
 // DidModifyFiles reports a file modification to the session. It returns
@@ -667,7 +717,7 @@
 // TODO(rfindley): what happens if this function fails? It must leave us in a
 // broken state, which we should surface to the user, probably as a request to
 // restart gopls.
-func (s *Session) DidModifyFiles(ctx context.Context, changes []file.Modification) (map[*View][]protocol.DocumentURI, error) {
+func (s *Session) DidModifyFiles(ctx context.Context, modifications []file.Modification) (map[*View][]protocol.DocumentURI, error) {
 	s.viewMu.Lock()
 	defer s.viewMu.Unlock()
 
@@ -676,7 +726,7 @@
 	// This is done while holding viewMu because the set of open files affects
 	// the set of views, and to prevent views from seeing updated file content
 	// before they have processed invalidations.
-	replaced, err := s.updateOverlays(ctx, changes)
+	replaced, err := s.updateOverlays(ctx, modifications)
 	if err != nil {
 		return nil, err
 	}
@@ -687,7 +737,7 @@
 	checkViews := false
 
 	changed := make(map[protocol.DocumentURI]file.Handle)
-	for _, c := range changes {
+	for _, c := range modifications {
 		fh := mustReadFile(ctx, s, c.URI)
 		changed[c.URI] = fh
 
@@ -725,7 +775,7 @@
 		// branch change. Be careful to only do this if both files are open Go
 		// files.
 		if old, ok := replaced[c.URI]; ok && !checkViews && fileKind(fh) == file.Go {
-			if new, ok := fh.(*Overlay); ok {
+			if new, ok := fh.(*overlay); ok {
 				if buildComment(old.content) != buildComment(new.content) {
 					checkViews = true
 				}
@@ -805,7 +855,7 @@
 	// We only want to run fast-path diagnostics (i.e. diagnoseChangedFiles) once
 	// for each changed file, in its best view.
 	viewsToDiagnose := map[*View][]protocol.DocumentURI{}
-	for _, mod := range changes {
+	for _, mod := range modifications {
 		v, err := s.viewOfLocked(ctx, mod.URI)
 		if err != nil {
 			// bestViewForURI only returns an error in the event of context
@@ -822,7 +872,7 @@
 	// ...but changes may be relevant to other views, for example if they are
 	// changes to a shared package.
 	for _, v := range s.views {
-		_, release, needsDiagnosis := v.Invalidate(ctx, StateChange{Files: changed})
+		_, release, needsDiagnosis := s.invalidateViewLocked(ctx, v, StateChange{Modifications: modifications, Files: changed})
 		release()
 
 		if needsDiagnosis || checkViews {
@@ -886,11 +936,11 @@
 //
 // Precondition: caller holds s.viewMu lock.
 // TODO(rfindley): move this to fs_overlay.go.
-func (fs *overlayFS) updateOverlays(ctx context.Context, changes []file.Modification) (map[protocol.DocumentURI]*Overlay, error) {
+func (fs *overlayFS) updateOverlays(ctx context.Context, changes []file.Modification) (map[protocol.DocumentURI]*overlay, error) {
 	fs.mu.Lock()
 	defer fs.mu.Unlock()
 
-	replaced := make(map[protocol.DocumentURI]*Overlay)
+	replaced := make(map[protocol.DocumentURI]*overlay)
 	for _, c := range changes {
 		o, ok := fs.overlays[c.URI]
 		if ok {
@@ -956,7 +1006,7 @@
 			_, readErr := fh.Content()
 			sameContentOnDisk = (readErr == nil && fh.Identity().Hash == hash)
 		}
-		o = &Overlay{
+		o = &overlay{
 			uri:     c.URI,
 			version: version,
 			content: text,
@@ -997,9 +1047,9 @@
 func (b brokenFile) Version() int32            { return 0 }
 func (b brokenFile) Content() ([]byte, error)  { return nil, b.err }
 
-// FileWatchingGlobPatterns returns a set of glob patterns patterns that the
-// client is required to watch for changes, and notify the server of them, in
-// order to keep the server's state up to date.
+// FileWatchingGlobPatterns returns a set of glob patterns that the client is
+// required to watch for changes, and notify the server of them, in order to
+// keep the server's state up to date.
 //
 // This set includes
 //  1. all go.mod and go.work files in the workspace; and
@@ -1015,17 +1065,27 @@
 // The watch for workspace directories in (2) should keep each View up to date,
 // as it should capture any newly added/modified/deleted Go files.
 //
+// Patterns are returned as a set of protocol.RelativePatterns, since they can
+// always be later translated to glob patterns (i.e. strings) if the client
+// lacks relative pattern support. By convention, any pattern returned with
+// empty baseURI should be served as a glob pattern.
+//
+// In general, we prefer to serve relative patterns, as they work better on
+// most clients that support both, and do not have issues with Windows driver
+// letter casing:
+// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#relativePattern
+//
 // TODO(golang/go#57979): we need to reset the memoizedFS when a view changes.
 // Consider the case where we incidentally read a file, then it moved outside
 // of an active module, and subsequently changed: we would still observe the
 // original file state.
-func (s *Session) FileWatchingGlobPatterns(ctx context.Context) map[string]unit {
+func (s *Session) FileWatchingGlobPatterns(ctx context.Context) map[protocol.RelativePattern]unit {
 	s.viewMu.Lock()
 	defer s.viewMu.Unlock()
 
 	// Always watch files that may change the set of views.
-	patterns := map[string]unit{
-		"**/*.{mod,work}": {},
+	patterns := map[protocol.RelativePattern]unit{
+		{Pattern: "**/*.{mod,work}"}: {},
 	}
 
 	for _, view := range s.views {
@@ -1033,7 +1093,7 @@
 		if err != nil {
 			continue // view is shut down; continue with others
 		}
-		for k, v := range snapshot.fileWatchingGlobPatterns(ctx) {
+		for k, v := range snapshot.fileWatchingGlobPatterns() {
 			patterns[k] = v
 		}
 		release()
@@ -1053,7 +1113,7 @@
 	// funcs.
 	diagnostics := make(map[protocol.DocumentURI][]*Diagnostic)
 
-	byView := make(map[*View][]*Overlay)
+	byView := make(map[*View][]*overlay)
 	for _, o := range s.Overlays() {
 		uri := o.URI()
 		snapshot, release, err := s.SnapshotOf(ctx, uri)
diff --git a/gopls/internal/lsp/cache/session_test.go b/gopls/internal/cache/session_test.go
similarity index 97%
rename from gopls/internal/lsp/cache/session_test.go
rename to gopls/internal/cache/session_test.go
index 11046a2..cc6f664 100644
--- a/gopls/internal/lsp/cache/session_test.go
+++ b/gopls/internal/cache/session_test.go
@@ -12,12 +12,15 @@
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
+	"golang.org/x/tools/internal/testenv"
 )
 
 func TestZeroConfigAlgorithm(t *testing.T) {
+	testenv.NeedsExec(t) // executes the Go command
+
 	type viewSummary struct {
 		// fields exported for cmp.Diff
 		Type ViewType
@@ -250,7 +253,7 @@
 				}
 				env, err := FetchGoEnv(ctx, toURI(f.dir), opts)
 				if err != nil {
-					t.Fatalf("fetching env: %v", env)
+					t.Fatalf("FetchGoEnv failed: %v", err)
 				}
 				folders = append(folders, &Folder{
 					Dir:     toURI(f.dir),
diff --git a/gopls/internal/lsp/cache/snapshot.go b/gopls/internal/cache/snapshot.go
similarity index 94%
rename from gopls/internal/lsp/cache/snapshot.go
rename to gopls/internal/cache/snapshot.go
index 1b1ed12..3d97ed4 100644
--- a/gopls/internal/lsp/cache/snapshot.go
+++ b/gopls/internal/cache/snapshot.go
@@ -16,6 +16,7 @@
 	"go/types"
 	"io"
 	"os"
+	"path"
 	"path/filepath"
 	"regexp"
 	"runtime"
@@ -27,14 +28,14 @@
 	"golang.org/x/sync/errgroup"
 	"golang.org/x/tools/go/packages"
 	"golang.org/x/tools/go/types/objectpath"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/methodsets"
+	"golang.org/x/tools/gopls/internal/cache/typerefs"
+	"golang.org/x/tools/gopls/internal/cache/xrefs"
 	"golang.org/x/tools/gopls/internal/file"
 	"golang.org/x/tools/gopls/internal/filecache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/methodsets"
-	"golang.org/x/tools/gopls/internal/lsp/cache/typerefs"
-	"golang.org/x/tools/gopls/internal/lsp/cache/xrefs"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/constraints"
@@ -85,12 +86,14 @@
 	store *memoize.Store // cache of handles shared by all snapshots
 
 	refMu sync.Mutex
+
 	// refcount holds the number of outstanding references to the current
-	// Snapshot. When refcount is decremented to 0, the Snapshot maps can be
-	// safely destroyed.
+	// Snapshot. When refcount is decremented to 0, the Snapshot maps are
+	// destroyed and the done function is called.
 	//
 	// TODO(rfindley): use atomic.Int32 on Go 1.19+.
 	refcount int
+	done     func() // for implementing Session.Shutdown
 
 	// mu guards all of the maps in the snapshot, as well as the builtin URI and
 	// initialized.
@@ -238,7 +241,7 @@
 	if s.refcount == 0 {
 		s.packages.Destroy()
 		s.activePackages.Destroy()
-		s.files.Destroy()
+		s.files.destroy()
 		s.symbolizeHandles.Destroy()
 		s.parseModHandles.Destroy()
 		s.parseWorkHandles.Destroy()
@@ -248,6 +251,7 @@
 		s.unloadableFiles.Destroy()
 		s.moduleUpgrades.Destroy()
 		s.vulns.Destroy()
+		s.done()
 	}
 }
 
@@ -310,7 +314,7 @@
 	// The kind of an unsaved buffer comes from the
 	// TextDocumentItem.LanguageID field in the didChange event,
 	// not from the file name. They may differ.
-	if o, ok := fh.(*Overlay); ok {
+	if o, ok := fh.(*overlay); ok {
 		if o.kind != file.UnknownKind {
 			return o.kind
 		}
@@ -347,7 +351,7 @@
 	defer s.mu.Unlock()
 
 	tmpls := map[protocol.DocumentURI]file.Handle{}
-	s.files.Range(func(k protocol.DocumentURI, fh file.Handle) {
+	s.files.foreach(func(k protocol.DocumentURI, fh file.Handle) {
 		if s.FileKind(fh) == file.Tmpl {
 			tmpls[k] = fh
 		}
@@ -543,51 +547,17 @@
 	//
 	// TODO(rfindley): should we set -overlays here?
 
-	var modURI protocol.DocumentURI
-	// Select the module context to use.
-	// If we're type checking, we need to use the workspace context, meaning
-	// the main (workspace) module. Otherwise, we should use the module for
-	// the passed-in working dir.
-	if mode == LoadWorkspace {
-		// TODO(rfindley): this seems unnecessary and overly complicated. Remove
-		// this along with 'allowModFileModifications'.
-		if s.view.typ == GoModView {
-			modURI = s.view.gomod
-		}
-	} else {
-		modURI = s.GoModForFile(protocol.URIFromPath(inv.WorkingDir))
-	}
-
-	var modContent []byte
-	if modURI != "" {
-		modFH, err := s.ReadFile(ctx, modURI)
-		if err != nil {
-			return "", nil, cleanup, err
-		}
-		modContent, err = modFH.Content()
-		if err != nil {
-			return "", nil, cleanup, err
-		}
-	}
-
-	// TODO(rfindley): in the case of go.work mode, modURI is empty and we fall
-	// back on the default behavior of vendorEnabled with an empty modURI. Figure
-	// out what is correct here and implement it explicitly.
-	vendorEnabled, err := s.vendorEnabled(ctx, modURI, modContent)
-	if err != nil {
-		return "", nil, cleanup, err
-	}
-
 	const mutableModFlag = "mod"
+
 	// If the mod flag isn't set, populate it based on the mode and workspace.
+	//
+	// (As noted in various TODOs throughout this function, this is very
+	// confusing and not obviously correct, but tests pass and we will eventually
+	// rewrite this entire function.)
 	if inv.ModFlag == "" {
 		switch mode {
 		case LoadWorkspace, Normal:
-			if vendorEnabled {
-				inv.ModFlag = "vendor"
-			} else if !allowModfileModificationOption {
-				inv.ModFlag = "readonly"
-			} else {
+			if allowModfileModificationOption {
 				inv.ModFlag = mutableModFlag
 			}
 		case WriteTemporaryModFile:
@@ -604,6 +574,32 @@
 
 	// If the invocation needs to mutate the modfile, we must use a temp mod.
 	if inv.ModFlag == mutableModFlag {
+		var modURI protocol.DocumentURI
+		// Select the module context to use.
+		// If we're type checking, we need to use the workspace context, meaning
+		// the main (workspace) module. Otherwise, we should use the module for
+		// the passed-in working dir.
+		if mode == LoadWorkspace {
+			// TODO(rfindley): this seems unnecessary and overly complicated. Remove
+			// this along with 'allowModFileModifications'.
+			if s.view.typ == GoModView {
+				modURI = s.view.gomod
+			}
+		} else {
+			modURI = s.GoModForFile(protocol.URIFromPath(inv.WorkingDir))
+		}
+
+		var modContent []byte
+		if modURI != "" {
+			modFH, err := s.ReadFile(ctx, modURI)
+			if err != nil {
+				return "", nil, cleanup, err
+			}
+			modContent, err = modFH.Content()
+			if err != nil {
+				return "", nil, cleanup, err
+			}
+		}
 		if modURI == "" {
 			return "", nil, cleanup, fmt.Errorf("no go.mod file found in %s", inv.WorkingDir)
 		}
@@ -637,11 +633,11 @@
 //
 // Note that this may differ from the set of overlays on the server, if the
 // snapshot observed a historical state.
-func (s *Snapshot) Overlays() []*Overlay {
+func (s *Snapshot) Overlays() []*overlay {
 	s.mu.Lock()
 	defer s.mu.Unlock()
 
-	return s.files.Overlays()
+	return s.files.getOverlays()
 }
 
 // Package data kinds, identifying various package data that may be stored in
@@ -694,15 +690,15 @@
 //
 // If these indexes cannot be loaded from cache, the requested packages may
 // be type-checked.
-func (s *Snapshot) References(ctx context.Context, ids ...PackageID) ([]XrefIndex, error) {
+func (s *Snapshot) References(ctx context.Context, ids ...PackageID) ([]xrefIndex, error) {
 	ctx, done := event.Start(ctx, "cache.snapshot.References")
 	defer done()
 
-	indexes := make([]XrefIndex, len(ids))
+	indexes := make([]xrefIndex, len(ids))
 	pre := func(i int, ph *packageHandle) bool {
 		data, err := filecache.Get(xrefsKind, ph.key)
 		if err == nil { // hit
-			indexes[i] = XrefIndex{mp: ph.mp, data: data}
+			indexes[i] = xrefIndex{mp: ph.mp, data: data}
 			return false
 		} else if err != filecache.ErrNotFound {
 			event.Error(ctx, "reading xrefs from filecache", err)
@@ -710,18 +706,18 @@
 		return true
 	}
 	post := func(i int, pkg *Package) {
-		indexes[i] = XrefIndex{mp: pkg.metadata, data: pkg.pkg.xrefs()}
+		indexes[i] = xrefIndex{mp: pkg.metadata, data: pkg.pkg.xrefs()}
 	}
 	return indexes, s.forEachPackage(ctx, ids, pre, post)
 }
 
-// An XrefIndex is a helper for looking up references in a given package.
-type XrefIndex struct {
+// An xrefIndex is a helper for looking up references in a given package.
+type xrefIndex struct {
 	mp   *metadata.Package
 	data []byte
 }
 
-func (index XrefIndex) Lookup(targets map[PackagePath]map[objectpath.Path]struct{}) []protocol.Location {
+func (index xrefIndex) Lookup(targets map[PackagePath]map[objectpath.Path]struct{}) []protocol.Location {
 	return xrefs.Lookup(index.mp, index.data, targets)
 }
 
@@ -935,23 +931,33 @@
 
 // See Session.FileWatchingGlobPatterns for a description of gopls' file
 // watching heuristic.
-func (s *Snapshot) fileWatchingGlobPatterns(ctx context.Context) map[string]struct{} {
+func (s *Snapshot) fileWatchingGlobPatterns() map[protocol.RelativePattern]unit {
+	// Always watch files that may change the view definition.
+	patterns := make(map[protocol.RelativePattern]unit)
+
+	// If GOWORK is outside the folder, ensure we are watching it.
+	if s.view.gowork != "" && !s.view.folder.Dir.Encloses(s.view.gowork) {
+		workPattern := protocol.RelativePattern{
+			BaseURI: s.view.gowork.Dir(),
+			Pattern: path.Base(string(s.view.gowork)),
+		}
+		patterns[workPattern] = unit{}
+	}
+
 	extensions := "go,mod,sum,work"
 	for _, ext := range s.Options().TemplateExtensions {
 		extensions += "," + ext
 	}
-
-	// Always watch files that may change the view definition.
-	patterns := make(map[string]unit)
-
-	// If GOWORK is outside the folder, ensure we are watching it.
-	if s.view.gowork != "" && !s.view.folder.Dir.Encloses(s.view.gowork) {
-		// TODO(rfindley): use RelativePatterns here as well (see below).
-		patterns[filepath.ToSlash(s.view.gowork.Path())] = unit{}
-	}
+	watchGoFiles := fmt.Sprintf("**/*.{%s}", extensions)
 
 	var dirs []string
 	if s.view.moduleMode() {
+		if s.view.typ == GoWorkView {
+			workVendorDir := filepath.Join(s.view.gowork.Dir().Path(), "vendor")
+			workVendorURI := protocol.URIFromPath(workVendorDir)
+			patterns[protocol.RelativePattern{BaseURI: workVendorURI, Pattern: watchGoFiles}] = unit{}
+		}
+
 		// In module mode, watch directories containing active modules, and collect
 		// these dirs for later filtering the set of known directories.
 		//
@@ -961,21 +967,17 @@
 			dir := filepath.Dir(modFile.Path())
 			dirs = append(dirs, dir)
 
-			// TODO(golang/go#64763): Switch to RelativePatterns if RelativePatternSupport
-			// is available. Relative patterns do not have issues with Windows drive
-			// letter casing.
-			// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#relativePattern
-			//
-			// TODO(golang/go#64724): thoroughly test, particularly on on Windows.
+			// TODO(golang/go#64724): thoroughly test these patterns, particularly on
+			// on Windows.
 			//
 			// Note that glob patterns should use '/' on Windows:
 			// https://code.visualstudio.com/docs/editor/glob-patterns
-			patterns[fmt.Sprintf("%s/**/*.{%s}", filepath.ToSlash(dir), extensions)] = unit{}
+			patterns[protocol.RelativePattern{BaseURI: modFile.Dir(), Pattern: watchGoFiles}] = unit{}
 		}
 	} else {
 		// In non-module modes (GOPATH or AdHoc), we just watch the workspace root.
 		dirs = []string{s.view.root.Path()}
-		patterns[fmt.Sprintf("**/*.{%s}", extensions)] = unit{}
+		patterns[protocol.RelativePattern{Pattern: watchGoFiles}] = unit{}
 	}
 
 	if s.watchSubdirs() {
@@ -1004,14 +1006,14 @@
 	return patterns
 }
 
-func (s *Snapshot) addKnownSubdirs(patterns map[string]unit, wsDirs []string) {
+func (s *Snapshot) addKnownSubdirs(patterns map[protocol.RelativePattern]unit, wsDirs []string) {
 	s.mu.Lock()
 	defer s.mu.Unlock()
 
-	s.files.Dirs().Range(func(dir string) {
+	s.files.getDirs().Range(func(dir string) {
 		for _, wsDir := range wsDirs {
 			if pathutil.InDir(wsDir, dir) {
-				patterns[filepath.ToSlash(dir)] = unit{}
+				patterns[protocol.RelativePattern{Pattern: filepath.ToSlash(dir)}] = unit{}
 			}
 		}
 	})
@@ -1052,11 +1054,11 @@
 	defer s.mu.Unlock()
 
 	dir := uri.Path()
-	if !s.files.Dirs().Contains(dir) {
+	if !s.files.getDirs().Contains(dir) {
 		return nil
 	}
 	var files []protocol.DocumentURI
-	s.files.Range(func(uri protocol.DocumentURI, _ file.Handle) {
+	s.files.foreach(func(uri protocol.DocumentURI, _ file.Handle) {
 		if pathutil.InDir(dir, uri.Path()) {
 			files = append(files, uri)
 		}
@@ -1258,7 +1260,7 @@
 	s.mu.Lock()
 	defer s.mu.Unlock()
 
-	result, _ := s.files.Get(uri)
+	result, _ := s.files.get(uri)
 	return result
 }
 
@@ -1271,14 +1273,14 @@
 	s.mu.Lock()
 	defer s.mu.Unlock()
 
-	fh, ok := s.files.Get(uri)
+	fh, ok := s.files.get(uri)
 	if !ok {
 		var err error
 		fh, err = s.view.fs.ReadFile(ctx, uri)
 		if err != nil {
 			return nil, err
 		}
-		s.files.Set(uri, fh)
+		s.files.set(uri, fh)
 	}
 	return fh, nil
 }
@@ -1313,8 +1315,8 @@
 			continue // error logged above
 		}
 		uri := uris[i]
-		if _, ok := s.files.Get(uri); !ok {
-			s.files.Set(uri, fh)
+		if _, ok := s.files.get(uri); !ok {
+			s.files.set(uri, fh)
 		}
 	}
 }
@@ -1324,8 +1326,8 @@
 	s.mu.Lock()
 	defer s.mu.Unlock()
 
-	fh, _ := s.files.Get(uri)
-	_, open := fh.(*Overlay)
+	fh, _ := s.files.get(uri)
+	_, open := fh.(*overlay)
 	return open
 }
 
@@ -1404,13 +1406,13 @@
 	}
 }
 
-func (s *Snapshot) orphanedFileDiagnostics(ctx context.Context, overlays []*Overlay) ([]*Diagnostic, error) {
+func (s *Snapshot) orphanedFileDiagnostics(ctx context.Context, overlays []*overlay) ([]*Diagnostic, error) {
 	if err := s.awaitLoaded(ctx); err != nil {
 		return nil, err
 	}
 
 	var diagnostics []*Diagnostic
-	var orphaned []*Overlay
+	var orphaned []*overlay
 searchOverlays:
 	for _, o := range overlays {
 		uri := o.URI()
@@ -1600,7 +1602,7 @@
 				Message:        msg,
 				SuggestedFixes: suggestedFixes,
 			}
-			if ok := BundleQuickFixes(d); !ok {
+			if ok := bundleQuickFixes(d); !ok {
 				bug.Reportf("failed to bundle quick fixes for %v", d)
 			}
 			// Only report diagnostics if we detect an actual exclusion.
@@ -1663,10 +1665,10 @@
 // also require more strictness about diagnostic dependencies. For example,
 // template.Diagnostics currently re-parses every time: there is no Snapshot
 // data responsible for providing these diagnostics.
-func (s *Snapshot) clone(ctx, bgCtx context.Context, changed StateChange) (*Snapshot, bool) {
+func (s *Snapshot) clone(ctx, bgCtx context.Context, changed StateChange, done func()) (*Snapshot, bool) {
 	changedFiles := changed.Files
-	ctx, done := event.Start(ctx, "cache.snapshot.clone")
-	defer done()
+	ctx, stop := event.Start(ctx, "cache.snapshot.clone")
+	defer stop()
 
 	s.mu.Lock()
 	defer s.mu.Unlock()
@@ -1680,6 +1682,7 @@
 		sequenceID:        s.sequenceID + 1,
 		store:             s.store,
 		refcount:          1, // Snapshots are born referenced.
+		done:              done,
 		view:              s.view,
 		backgroundCtx:     bgCtx,
 		cancel:            cancel,
@@ -1688,7 +1691,7 @@
 		initialErr:        s.initialErr,
 		packages:          s.packages.Clone(),
 		activePackages:    s.activePackages.Clone(),
-		files:             s.files.Clone(changedFiles),
+		files:             s.files.clone(changedFiles),
 		symbolizeHandles:  cloneWithout(s.symbolizeHandles, changedFiles, nil),
 		workspacePackages: s.workspacePackages,
 		shouldLoad:        s.shouldLoad.Clone(),      // not cloneWithout: shouldLoad is cleared on loads
@@ -1731,10 +1734,14 @@
 	// one or more modules may have moved into or out of the
 	// vendor tree after 'go mod vendor' or 'rm -fr vendor/'.
 	//
+	// In this case, we consider the actual modification to see if was a creation
+	// or deletion.
+	//
 	// TODO(rfindley): revisit the location of this check.
-	for uri := range changedFiles {
-		if inVendor(uri) && s.initialErr != nil ||
-			strings.HasSuffix(string(uri), "/vendor/modules.txt") {
+	for _, mod := range changed.Modifications {
+		if inVendor(mod.URI) && (mod.Action == file.Create || mod.Action == file.Delete) ||
+			strings.HasSuffix(string(mod.URI), "/vendor/modules.txt") {
+
 			reinit = true
 			break
 		}
@@ -1744,9 +1751,14 @@
 	// they exist. Importantly, we don't call ReadFile here: consider the case
 	// where a file is added on disk; we don't want to read the newly added file
 	// into the old snapshot, as that will break our change detection below.
+	//
+	// TODO(rfindley): it may be more accurate to rely on the modification type
+	// here, similarly to what we do for vendored files above. If we happened not
+	// to have read a file in the previous snapshot, that's not the same as it
+	// actually being created.
 	oldFiles := make(map[protocol.DocumentURI]file.Handle)
 	for uri := range changedFiles {
-		if fh, ok := s.files.Get(uri); ok {
+		if fh, ok := s.files.get(uri); ok {
 			oldFiles[uri] = fh
 		}
 	}
@@ -1816,8 +1828,8 @@
 	for uri, newFH := range changedFiles {
 		// The original FileHandle for this URI is cached on the snapshot.
 		oldFH := oldFiles[uri] // may be nil
-		_, oldOpen := oldFH.(*Overlay)
-		_, newOpen := newFH.(*Overlay)
+		_, oldOpen := oldFH.(*overlay)
+		_, newOpen := newFH.(*overlay)
 
 		anyFileOpenedOrClosed = anyFileOpenedOrClosed || (oldOpen != newOpen)
 		anyFileAdded = anyFileAdded || (oldFH == nil || !fileExists(oldFH)) && fileExists(newFH)
@@ -2126,11 +2138,11 @@
 // are both overlays, and if the current FileHandle is saved while the original
 // FileHandle was not saved.
 func fileWasSaved(originalFH, currentFH file.Handle) bool {
-	c, ok := currentFH.(*Overlay)
+	c, ok := currentFH.(*overlay)
 	if !ok || c == nil {
 		return true
 	}
-	o, ok := originalFH.(*Overlay)
+	o, ok := originalFH.(*overlay)
 	if !ok || o == nil {
 		return c.saved
 	}
diff --git a/gopls/internal/lsp/cache/symbols.go b/gopls/internal/cache/symbols.go
similarity index 98%
rename from gopls/internal/lsp/cache/symbols.go
rename to gopls/internal/cache/symbols.go
index d2c9015..5dce87d 100644
--- a/gopls/internal/lsp/cache/symbols.go
+++ b/gopls/internal/cache/symbols.go
@@ -12,7 +12,7 @@
 	"strings"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/astutil"
 )
 
diff --git a/gopls/internal/lsp/cache/typerefs/doc.go b/gopls/internal/cache/typerefs/doc.go
similarity index 98%
rename from gopls/internal/lsp/cache/typerefs/doc.go
rename to gopls/internal/cache/typerefs/doc.go
index 700da5d..18042c6 100644
--- a/gopls/internal/lsp/cache/typerefs/doc.go
+++ b/gopls/internal/cache/typerefs/doc.go
@@ -111,7 +111,7 @@
 // The [BuildPackageGraph] constructor implements a whole-graph analysis similar
 // to that which will be implemented by gopls, but for various reasons the
 // logic for this analysis will eventually live in the
-// [golang.org/x/tools/gopls/internal/lsp/cache] package. Nevertheless,
+// [golang.org/x/tools/gopls/internal/cache] package. Nevertheless,
 // BuildPackageGraph and its test serve to verify the syntactic analysis, and
 // may serve as a proving ground for new optimizations of the whole-graph analysis.
 //
diff --git a/gopls/internal/lsp/cache/typerefs/packageset.go b/gopls/internal/cache/typerefs/packageset.go
similarity index 98%
rename from gopls/internal/lsp/cache/typerefs/packageset.go
rename to gopls/internal/cache/typerefs/packageset.go
index 9d2026f..29c37cd 100644
--- a/gopls/internal/lsp/cache/typerefs/packageset.go
+++ b/gopls/internal/cache/typerefs/packageset.go
@@ -11,7 +11,7 @@
 	"strings"
 	"sync"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
 )
 
 // PackageIndex stores common data to enable efficient representation of
diff --git a/gopls/internal/lsp/cache/typerefs/pkggraph_test.go b/gopls/internal/cache/typerefs/pkggraph_test.go
similarity index 96%
rename from gopls/internal/lsp/cache/typerefs/pkggraph_test.go
rename to gopls/internal/cache/typerefs/pkggraph_test.go
index 7c53f40..01cd1a8 100644
--- a/gopls/internal/lsp/cache/typerefs/pkggraph_test.go
+++ b/gopls/internal/cache/typerefs/pkggraph_test.go
@@ -17,10 +17,10 @@
 	"sync"
 
 	"golang.org/x/sync/errgroup"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/cache/typerefs"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
+	"golang.org/x/tools/gopls/internal/cache/typerefs"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 const (
diff --git a/gopls/internal/lsp/cache/typerefs/pkgrefs_test.go b/gopls/internal/cache/typerefs/pkgrefs_test.go
similarity index 96%
rename from gopls/internal/lsp/cache/typerefs/pkgrefs_test.go
rename to gopls/internal/cache/typerefs/pkgrefs_test.go
index 4cc8a82..da14b90 100644
--- a/gopls/internal/lsp/cache/typerefs/pkgrefs_test.go
+++ b/gopls/internal/cache/typerefs/pkgrefs_test.go
@@ -20,10 +20,10 @@
 
 	"golang.org/x/tools/go/gcexportdata"
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/cache/typerefs"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
+	"golang.org/x/tools/gopls/internal/cache/typerefs"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/astutil"
 	"golang.org/x/tools/internal/packagesinternal"
 	"golang.org/x/tools/internal/testenv"
@@ -327,7 +327,7 @@
 }
 
 // This function is a compressed version of snapshot.load from the
-// internal/lsp/cache package, for use in testing.
+// internal/cache package, for use in testing.
 //
 // TODO(rfindley): it may be valuable to extract this logic from the snapshot,
 // since it is otherwise standalone.
@@ -386,7 +386,7 @@
 		for importPath, imported := range pkg.Imports {
 			importPath := ImportPath(importPath)
 
-			// see note in gopls/internal/lsp/cache/load.go for an explanation of this check.
+			// see note in gopls/internal/cache/load.go for an explanation of this check.
 			if importPath != "unsafe" && len(imported.CompiledGoFiles) == 0 {
 				mp.DepsByImpPath[importPath] = "" // missing
 				continue
diff --git a/gopls/internal/lsp/cache/typerefs/refs.go b/gopls/internal/cache/typerefs/refs.go
similarity index 99%
rename from gopls/internal/lsp/cache/typerefs/refs.go
rename to gopls/internal/cache/typerefs/refs.go
index 53dcd5e..b389667 100644
--- a/gopls/internal/lsp/cache/typerefs/refs.go
+++ b/gopls/internal/cache/typerefs/refs.go
@@ -11,8 +11,8 @@
 	"sort"
 	"strings"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
 	"golang.org/x/tools/gopls/internal/util/astutil"
 	"golang.org/x/tools/gopls/internal/util/frob"
 )
diff --git a/gopls/internal/lsp/cache/typerefs/refs_test.go b/gopls/internal/cache/typerefs/refs_test.go
similarity index 97%
rename from gopls/internal/lsp/cache/typerefs/refs_test.go
rename to gopls/internal/cache/typerefs/refs_test.go
index bbd0885..9bb9ec5 100644
--- a/gopls/internal/lsp/cache/typerefs/refs_test.go
+++ b/gopls/internal/cache/typerefs/refs_test.go
@@ -12,10 +12,10 @@
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/cache/typerefs"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
+	"golang.org/x/tools/gopls/internal/cache/typerefs"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // TestRefs checks that the analysis reports, for each exported member
diff --git a/gopls/internal/lsp/cache/view.go b/gopls/internal/cache/view.go
similarity index 88%
rename from gopls/internal/lsp/cache/view.go
rename to gopls/internal/cache/view.go
index 0b1e1db..78e85a1 100644
--- a/gopls/internal/lsp/cache/view.go
+++ b/gopls/internal/cache/view.go
@@ -2,7 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package cache implements the caching layer for gopls.
+// Package cache is the core of gopls: it is concerned with state
+// management, dependency analysis, and invalidation; and it holds the
+// machinery of type checking and modular static analysis. Its
+// principal types are [Session], [Folder], [View], [Snapshot],
+// [Cache], and [Package].
 package cache
 
 import (
@@ -21,14 +25,13 @@
 	"sync"
 	"time"
 
-	"golang.org/x/mod/modfile"
-	"golang.org/x/mod/semver"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/util/maps"
 	"golang.org/x/tools/gopls/internal/util/pathutil"
+	"golang.org/x/tools/gopls/internal/util/slices"
 	"golang.org/x/tools/gopls/internal/vulncheck"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/gocommand"
@@ -100,21 +103,12 @@
 	// ignoreFilter is used for fast checking of ignored files.
 	ignoreFilter *ignoreFilter
 
-	// initCancelFirstAttempt can be used to terminate the view's first
+	// cancelInitialWorkspaceLoad can be used to terminate the view's first
 	// attempt at initialization.
-	initCancelFirstAttempt context.CancelFunc
+	cancelInitialWorkspaceLoad context.CancelFunc
 
-	// Track the latest snapshot via the snapshot field, guarded by snapshotMu.
-	//
-	// Invariant: whenever the snapshot field is overwritten, destroy(snapshot)
-	// is called on the previous (overwritten) snapshot while snapshotMu is held,
-	// incrementing snapshotWG. During shutdown the final snapshot is
-	// overwritten with nil and destroyed, guaranteeing that all observed
-	// snapshots have been destroyed via the destroy method, and snapshotWG may
-	// be waited upon to let these destroy operations complete.
 	snapshotMu sync.Mutex
-	snapshot   *Snapshot      // latest snapshot; nil after shutdown has been called
-	snapshotWG sync.WaitGroup // refcount for pending destroy operations
+	snapshot   *Snapshot // latest snapshot; nil after shutdown has been called
 
 	// initialWorkspaceLoad is closed when the first workspace initialization has
 	// completed. If we failed to load, we only retry if the go.mod file changes,
@@ -129,6 +123,10 @@
 	// initialization of snapshots. Do not change it without adjusting snapshot
 	// accordingly.
 	initializationSema chan struct{}
+
+	// Document filters are constructed once, in View.filterFunc.
+	filterFuncOnce sync.Once
+	_filterFunc    func(protocol.DocumentURI) bool // only accessed by View.filterFunc
 }
 
 // definition implements the viewDefiner interface.
@@ -498,26 +496,32 @@
 
 // filterFunc returns a func that reports whether uri is filtered by the currently configured
 // directoryFilters.
-//
-// TODO(rfindley): memoize this func or filterer, as it is invariant on the
-// view.
 func (v *View) filterFunc() func(protocol.DocumentURI) bool {
-	folderDir := v.folder.Dir.Path()
-	filterer := buildFilterer(folderDir, v.folder.Env.GOMODCACHE, v.folder.Options.DirectoryFilters)
-	return func(uri protocol.DocumentURI) bool {
-		// Only filter relative to the configured root directory.
-		if pathutil.InDir(folderDir, uri.Path()) {
-			return relPathExcludedByFilter(strings.TrimPrefix(uri.Path(), folderDir), filterer)
+	v.filterFuncOnce.Do(func() {
+		folderDir := v.folder.Dir.Path()
+		gomodcache := v.folder.Env.GOMODCACHE
+		var filters []string
+		filters = append(filters, v.folder.Options.DirectoryFilters...)
+		if pref := strings.TrimPrefix(gomodcache, folderDir); pref != gomodcache {
+			modcacheFilter := "-" + strings.TrimPrefix(filepath.ToSlash(pref), "/")
+			filters = append(filters, modcacheFilter)
 		}
-		return false
-	}
+		filterer := NewFilterer(filters)
+		v._filterFunc = func(uri protocol.DocumentURI) bool {
+			// Only filter relative to the configured root directory.
+			if pathutil.InDir(folderDir, uri.Path()) {
+				return relPathExcludedByFilter(strings.TrimPrefix(uri.Path(), folderDir), filterer)
+			}
+			return false
+		}
+	})
+	return v._filterFunc
 }
 
-// shutdown releases resources associated with the view, and waits for ongoing
-// work to complete.
+// shutdown releases resources associated with the view.
 func (v *View) shutdown() {
 	// Cancel the initial workspace load if it is still running.
-	v.initCancelFirstAttempt()
+	v.cancelInitialWorkspaceLoad()
 
 	v.snapshotMu.Lock()
 	if v.snapshot != nil {
@@ -526,8 +530,6 @@
 		v.snapshot = nil
 	}
 	v.snapshotMu.Unlock()
-
-	v.snapshotWG.Wait()
 }
 
 // IgnoredFile reports if a file would be ignored by a `go list` of the whole
@@ -761,22 +763,40 @@
 // By far the most common of these is a change to file state, but a query of
 // module upgrade information or vulnerabilities also affects gopls' behavior.
 type StateChange struct {
+	Modifications  []file.Modification // if set, the raw modifications originating this change
 	Files          map[protocol.DocumentURI]file.Handle
 	ModuleUpgrades map[protocol.DocumentURI]map[string]string
 	Vulns          map[protocol.DocumentURI]*vulncheck.Result
 	GCDetails      map[metadata.PackageID]bool // package -> whether or not we want details
 }
 
-// Invalidate processes the provided state change, invalidating any derived
+// InvalidateView processes the provided state change, invalidating any derived
 // results that depend on the changed state.
 //
 // The resulting snapshot is non-nil, representing the outcome of the state
 // change. The second result is a function that must be called to release the
 // snapshot when the snapshot is no longer needed.
 //
-// The resulting bool reports whether the new View needs to be re-diagnosed.
-// See Snapshot.clone for more details.
-func (v *View) Invalidate(ctx context.Context, changed StateChange) (*Snapshot, func(), bool) {
+// An error is returned if the given view is no longer active in the session.
+func (s *Session) InvalidateView(ctx context.Context, view *View, changed StateChange) (*Snapshot, func(), error) {
+	s.viewMu.Lock()
+	defer s.viewMu.Unlock()
+
+	if !slices.Contains(s.views, view) {
+		return nil, nil, fmt.Errorf("view is no longer active")
+	}
+	snapshot, release, _ := s.invalidateViewLocked(ctx, view, changed)
+	return snapshot, release, nil
+}
+
+// invalidateViewLocked invalidates the content of the given view.
+// (See [Session.InvalidateView]).
+//
+// The resulting bool reports whether the View needs to be re-diagnosed.
+// (See [Snapshot.clone]).
+//
+// s.viewMu must be held while calling this method.
+func (s *Session) invalidateViewLocked(ctx context.Context, v *View, changed StateChange) (*Snapshot, func(), bool) {
 	// Detach the context so that content invalidation cannot be canceled.
 	ctx = xcontext.Detach(ctx)
 
@@ -799,9 +819,9 @@
 	// TODO(rfindley): shouldn't we do this before canceling?
 	prevSnapshot.AwaitInitialized(ctx)
 
-	// Save one lease of the cloned snapshot in the view.
 	var needsDiagnosis bool
-	v.snapshot, needsDiagnosis = prevSnapshot.clone(ctx, v.baseCtx, changed)
+	s.snapshotWG.Add(1)
+	v.snapshot, needsDiagnosis = prevSnapshot.clone(ctx, v.baseCtx, changed, s.snapshotWG.Done)
 
 	// Remove the initial reference created when prevSnapshot was created.
 	prevSnapshot.decref()
@@ -1081,43 +1101,6 @@
 	return nil
 }
 
-// findWorkspaceModFile searches for a single go.mod file relative to the given
-// folder URI, using the following algorithm:
-//  1. if there is a go.mod file in a parent directory, return it
-//  2. else, if there is exactly one nested module, return it
-//  3. else, return ""
-func findWorkspaceModFile(ctx context.Context, folderURI protocol.DocumentURI, fs file.Source, excludePath func(string) bool) (protocol.DocumentURI, error) {
-	match, err := findRootPattern(ctx, folderURI, "go.mod", fs)
-	if err != nil {
-		if ctxErr := ctx.Err(); ctxErr != nil {
-			return "", ctxErr
-		}
-		return "", err
-	}
-	if match != "" {
-		return match, nil
-	}
-
-	// ...else we should check if there's exactly one nested module.
-	all, err := findModules(folderURI, excludePath, 2)
-	if err == errExhausted {
-		// Fall-back behavior: if we don't find any modules after searching 10000
-		// files, assume there are none.
-		event.Log(ctx, fmt.Sprintf("stopped searching for modules after %d files", fileLimit))
-		return "", nil
-	}
-	if err != nil {
-		return "", err
-	}
-	if len(all) == 1 {
-		// range to access first element.
-		for uri := range all {
-			return uri, nil
-		}
-	}
-	return "", nil
-}
-
 // findRootPattern looks for files with the given basename in dir or any parent
 // directory of dir, using the provided FileSource. It returns the first match,
 // starting from dir and search parents.
@@ -1280,47 +1263,6 @@
 
 var modFlagRegexp = regexp.MustCompile(`-mod[ =](\w+)`)
 
-// TODO(rstambler): Consolidate modURI and modContent back into a FileHandle
-// after we have a version of the workspace go.mod file on disk. Getting a
-// FileHandle from the cache for temporary files is problematic, since we
-// cannot delete it.
-//
-// TODO(rfindley): move this to snapshot.go.
-func (s *Snapshot) vendorEnabled(ctx context.Context, modURI protocol.DocumentURI, modContent []byte) (bool, error) {
-	// Legacy GOPATH workspace?
-	if len(s.view.workspaceModFiles) == 0 {
-		return false, nil
-	}
-
-	// Explicit -mod flag?
-	matches := modFlagRegexp.FindStringSubmatch(s.view.folder.Env.GOFLAGS)
-	if len(matches) != 0 {
-		modFlag := matches[1]
-		if modFlag != "" {
-			// Don't override an explicit '-mod=vendor' argument.
-			// We do want to override '-mod=readonly': it would break various module code lenses,
-			// and on 1.16 we know -modfile is available, so we won't mess with go.mod anyway.
-			return modFlag == "vendor", nil
-		}
-	}
-
-	modFile, err := modfile.Parse(modURI.Path(), modContent, nil)
-	if err != nil {
-		return false, err
-	}
-
-	// No vendor directory?
-	// TODO(golang/go#57514): this is wrong if the working dir is not the module
-	// root.
-	if fi, err := os.Stat(filepath.Join(s.view.root.Path(), "vendor")); err != nil || !fi.IsDir() {
-		return false, nil
-	}
-
-	// Vendoring enabled by default by go declaration in go.mod?
-	vendorEnabled := modFile.Go != nil && modFile.Go.Version != "" && semver.Compare("v"+modFile.Go.Version, "v1.14") >= 0
-	return vendorEnabled, nil
-}
-
 // TODO(rfindley): clean up the redundancy of allFilesExcluded,
 // pathExcludedByFilterFunc, pathExcludedByFilter, view.filterFunc...
 func allFilesExcluded(files []string, filterFunc func(protocol.DocumentURI) bool) bool {
@@ -1337,13 +1279,3 @@
 	path = strings.TrimPrefix(filepath.ToSlash(path), "/")
 	return filterer.Disallow(path)
 }
-
-func buildFilterer(folder, gomodcache string, directoryFilters []string) *Filterer {
-	var filters []string
-	filters = append(filters, directoryFilters...)
-	if pref := strings.TrimPrefix(gomodcache, folder); pref != gomodcache {
-		modcacheFilter := "-" + strings.TrimPrefix(filepath.ToSlash(pref), "/")
-		filters = append(filters, modcacheFilter)
-	}
-	return NewFilterer(filters)
-}
diff --git a/gopls/internal/lsp/cache/view_test.go b/gopls/internal/cache/view_test.go
similarity index 75%
rename from gopls/internal/lsp/cache/view_test.go
rename to gopls/internal/cache/view_test.go
index 44e0840..992a3d6 100644
--- a/gopls/internal/lsp/cache/view_test.go
+++ b/gopls/internal/cache/view_test.go
@@ -4,13 +4,11 @@
 package cache
 
 import (
-	"context"
 	"os"
 	"path/filepath"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/test/integration/fake"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 func TestCaseInsensitiveFilesystem(t *testing.T) {
@@ -44,63 +42,6 @@
 	}
 }
 
-func TestFindWorkspaceModFile(t *testing.T) {
-	workspace := `
--- a/go.mod --
-module a
--- a/x/x.go
-package x
--- a/x/y/y.go
-package x
--- b/go.mod --
-module b
--- b/c/go.mod --
-module bc
--- d/gopls.mod --
-module d-goplsworkspace
--- d/e/go.mod --
-module de
--- f/g/go.mod --
-module fg
-`
-	dir, err := fake.Tempdir(fake.UnpackTxt(workspace))
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer os.RemoveAll(dir)
-
-	tests := []struct {
-		folder, want string
-	}{
-		{"", ""}, // no module at root, and more than one nested module
-		{"a", "a/go.mod"},
-		{"a/x", "a/go.mod"},
-		{"a/x/y", "a/go.mod"},
-		{"b/c", "b/c/go.mod"},
-		{"d", "d/e/go.mod"},
-		{"d/e", "d/e/go.mod"},
-		{"f", "f/g/go.mod"},
-	}
-
-	for _, test := range tests {
-		ctx := context.Background()
-		rel := fake.RelativeTo(dir)
-		folderURI := protocol.URIFromPath(rel.AbsPath(test.folder))
-		excludeNothing := func(string) bool { return false }
-		got, err := findWorkspaceModFile(ctx, folderURI, New(nil), excludeNothing)
-		if err != nil {
-			t.Fatal(err)
-		}
-		want := protocol.DocumentURI("")
-		if test.want != "" {
-			want = protocol.URIFromPath(rel.AbsPath(test.want))
-		}
-		if got != want {
-			t.Errorf("findWorkspaceModFile(%q) = %q, want %q", test.folder, got, want)
-		}
-	}
-}
-
 func TestInVendor(t *testing.T) {
 	for _, tt := range []struct {
 		path     string
diff --git a/gopls/internal/cache/workspace.go b/gopls/internal/cache/workspace.go
new file mode 100644
index 0000000..4f01ebf
--- /dev/null
+++ b/gopls/internal/cache/workspace.go
@@ -0,0 +1,74 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cache
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"path/filepath"
+
+	"golang.org/x/mod/modfile"
+	"golang.org/x/tools/gopls/internal/file"
+	"golang.org/x/tools/gopls/internal/protocol"
+)
+
+// TODO(rfindley): now that experimentalWorkspaceModule is gone, this file can
+// be massively cleaned up and/or removed.
+
+// goWorkModules returns the URIs of go.mod files named by the go.work file.
+func goWorkModules(ctx context.Context, gowork protocol.DocumentURI, fs file.Source) (map[protocol.DocumentURI]unit, error) {
+	fh, err := fs.ReadFile(ctx, gowork)
+	if err != nil {
+		return nil, err // canceled
+	}
+	content, err := fh.Content()
+	if err != nil {
+		return nil, err
+	}
+	filename := gowork.Path()
+	dir := filepath.Dir(filename)
+	workFile, err := modfile.ParseWork(filename, content, nil)
+	if err != nil {
+		return nil, fmt.Errorf("parsing go.work: %w", err)
+	}
+	modFiles := make(map[protocol.DocumentURI]unit)
+	for _, use := range workFile.Use {
+		modDir := filepath.FromSlash(use.Path)
+		if !filepath.IsAbs(modDir) {
+			modDir = filepath.Join(dir, modDir)
+		}
+		modURI := protocol.URIFromPath(filepath.Join(modDir, "go.mod"))
+		modFiles[modURI] = unit{}
+	}
+	return modFiles, nil
+}
+
+// isGoMod reports if uri is a go.mod file.
+func isGoMod(uri protocol.DocumentURI) bool {
+	return filepath.Base(uri.Path()) == "go.mod"
+}
+
+// isGoWork reports if uri is a go.work file.
+func isGoWork(uri protocol.DocumentURI) bool {
+	return filepath.Base(uri.Path()) == "go.work"
+}
+
+// fileExists reports whether the file has a Content (which may be empty).
+// An overlay exists even if it is not reflected in the file system.
+func fileExists(fh file.Handle) bool {
+	_, err := fh.Content()
+	return err == nil
+}
+
+// errExhausted is returned by findModules if the file scan limit is reached.
+var errExhausted = errors.New("exhausted")
+
+// Limit go.mod search to 1 million files. As a point of reference,
+// Kubernetes has 22K files (as of 2020-11-24).
+//
+// Note: per golang/go#56496, the previous limit of 1M files was too slow, at
+// which point this limit was decreased to 100K.
+const fileLimit = 100_000
diff --git a/gopls/internal/lsp/cache/xrefs/xrefs.go b/gopls/internal/cache/xrefs/xrefs.go
similarity index 97%
rename from gopls/internal/lsp/cache/xrefs/xrefs.go
rename to gopls/internal/cache/xrefs/xrefs.go
index c6a5f04..6ab5432 100644
--- a/gopls/internal/lsp/cache/xrefs/xrefs.go
+++ b/gopls/internal/cache/xrefs/xrefs.go
@@ -14,9 +14,9 @@
 	"sort"
 
 	"golang.org/x/tools/go/types/objectpath"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/frob"
 	"golang.org/x/tools/gopls/internal/util/typesutil"
 	"golang.org/x/tools/internal/typeparams"
diff --git a/gopls/internal/cmd/call_hierarchy.go b/gopls/internal/cmd/call_hierarchy.go
index 5566bdc..82c18d0 100644
--- a/gopls/internal/cmd/call_hierarchy.go
+++ b/gopls/internal/cmd/call_hierarchy.go
@@ -10,7 +10,7 @@
 	"fmt"
 	"strings"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/tool"
 )
 
diff --git a/gopls/internal/cmd/capabilities_test.go b/gopls/internal/cmd/capabilities_test.go
index 9a66e6d..4767057 100644
--- a/gopls/internal/cmd/capabilities_test.go
+++ b/gopls/internal/cmd/capabilities_test.go
@@ -11,8 +11,8 @@
 	"path/filepath"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/server"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/internal/testenv"
@@ -40,10 +40,10 @@
 	}
 	defer os.RemoveAll(tmpDir)
 
-	app := New("gopls-test", tmpDir, os.Environ(), nil)
+	app := New(nil)
 
 	params := &protocol.ParamInitialize{}
-	params.RootURI = protocol.URIFromPath(app.wd)
+	params.RootURI = protocol.URIFromPath(tmpDir)
 	params.Capabilities.Workspace.Configuration = true
 
 	// Send an initialize request to the server.
diff --git a/gopls/internal/cmd/check.go b/gopls/internal/cmd/check.go
index 4d0ff04..2d7a767 100644
--- a/gopls/internal/cmd/check.go
+++ b/gopls/internal/cmd/check.go
@@ -9,7 +9,7 @@
 	"flag"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // check implements the check verb for gopls.
diff --git a/gopls/internal/cmd/cmd.go b/gopls/internal/cmd/cmd.go
index 3c9e8f9..31ca098 100644
--- a/gopls/internal/cmd/cmd.go
+++ b/gopls/internal/cmd/cmd.go
@@ -21,12 +21,12 @@
 	"text/tabwriter"
 	"time"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/debug"
 	"golang.org/x/tools/gopls/internal/filecache"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/lsprpc"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/server"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/util/browser"
@@ -35,7 +35,6 @@
 	"golang.org/x/tools/internal/diff"
 	"golang.org/x/tools/internal/jsonrpc2"
 	"golang.org/x/tools/internal/tool"
-	"golang.org/x/tools/internal/xcontext"
 )
 
 // Application is the main application as passed to tool.Main
@@ -54,15 +53,6 @@
 	// the options configuring function to invoke when building a server
 	options func(*settings.Options)
 
-	// The name of the binary, used in help and telemetry.
-	name string
-
-	// The working directory to run commands in.
-	wd string
-
-	// The environment variables to use.
-	env []string
-
 	// Support for remote LSP server.
 	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."`
 
@@ -105,15 +95,9 @@
 }
 
 // New returns a new Application ready to run.
-func New(name, wd string, env []string, options func(*settings.Options)) *Application {
-	if wd == "" {
-		wd, _ = os.Getwd()
-	}
+func New(options func(*settings.Options)) *Application {
 	app := &Application{
 		options: options,
-		name:    name,
-		wd:      wd,
-		env:     env,
 		OCAgent: "off", //TODO: Remove this line to default the exporter to on
 
 		Serve: Serve{
@@ -125,7 +109,7 @@
 }
 
 // Name implements tool.Application returning the binary name.
-func (app *Application) Name() string { return app.name }
+func (app *Application) Name() string { return "gopls" }
 
 // Usage implements tool.Application returning empty extra argument usage.
 func (app *Application) Usage() string { return "" }
@@ -250,7 +234,7 @@
 	// executable, and immediately runs a gc.
 	filecache.Start()
 
-	ctx = debug.WithInstance(ctx, app.wd, app.OCAgent)
+	ctx = debug.WithInstance(ctx, app.OCAgent)
 	if len(args) == 0 {
 		s := flag.NewFlagSet(app.Name(), flag.ExitOnError)
 		return tool.Run(ctx, s, &app.Serve, args)
@@ -341,22 +325,6 @@
 		}
 		return conn, nil
 
-	case strings.HasPrefix(app.Remote, "internal@"):
-		internalMu.Lock()
-		defer internalMu.Unlock()
-		opts := settings.DefaultOptions(app.options)
-		key := fmt.Sprintf("%s %v %v %v", app.wd, opts.PreferredContentFormat, opts.HierarchicalDocumentSymbolSupport, opts.SymbolMatcher)
-		if c := internalConnections[key]; c != nil {
-			return c, nil
-		}
-		remote := app.Remote[len("internal@"):]
-		ctx := xcontext.Detach(ctx) //TODO:a way of shutting down the internal server
-		connection, err := app.connectRemote(ctx, remote)
-		if err != nil {
-			return nil, err
-		}
-		internalConnections[key] = connection
-		return connection, nil
 	default:
 		return app.connectRemote(ctx, app.Remote)
 	}
@@ -380,8 +348,12 @@
 }
 
 func (c *connection) initialize(ctx context.Context, options func(*settings.Options)) error {
+	wd, err := os.Getwd()
+	if err != nil {
+		return fmt.Errorf("finding workdir: %v", err)
+	}
 	params := &protocol.ParamInitialize{}
-	params.RootURI = protocol.URIFromPath(c.client.app.wd)
+	params.RootURI = protocol.URIFromPath(wd)
 	params.Capabilities.Workspace.Configuration = true
 
 	// Make sure to respect configured options when sending initialize request.
@@ -513,16 +485,7 @@
 		if item.Section != "gopls" {
 			continue
 		}
-		env := map[string]interface{}{}
-		for _, value := range c.app.env {
-			l := strings.SplitN(value, "=", 2)
-			if len(l) != 2 {
-				continue
-			}
-			env[l[0]] = l[1]
-		}
 		m := map[string]interface{}{
-			"env": env,
 			"analyses": map[string]any{
 				"fillreturns":    true,
 				"nonewvars":      true,
@@ -776,10 +739,6 @@
 }
 
 func (c *connection) terminate(ctx context.Context) {
-	if strings.HasPrefix(c.client.app.Remote, "internal@") {
-		// internal connections need to be left alive for the next test
-		return
-	}
 	//TODO: do we need to handle errors on these calls?
 	c.Shutdown(ctx)
 	//TODO: right now calling exit terminates the process, we should rethink that
diff --git a/gopls/internal/cmd/codelens.go b/gopls/internal/cmd/codelens.go
index f861eca..28986cc 100644
--- a/gopls/internal/cmd/codelens.go
+++ b/gopls/internal/cmd/codelens.go
@@ -9,7 +9,7 @@
 	"flag"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/internal/tool"
 )
@@ -71,7 +71,7 @@
 	// Override the default setting for codelenses[Test], which is
 	// off by default because VS Code has a superior client-side
 	// implementation. But this client is not VS Code.
-	// See source.LensFuncs().
+	// See golang.LensFuncs().
 	origOptions := r.app.options
 	r.app.options = func(opts *settings.Options) {
 		origOptions(opts)
diff --git a/gopls/internal/cmd/definition.go b/gopls/internal/cmd/definition.go
index c20dcc14..e5e119b 100644
--- a/gopls/internal/cmd/definition.go
+++ b/gopls/internal/cmd/definition.go
@@ -12,7 +12,7 @@
 	"os"
 	"strings"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/internal/tool"
 )
diff --git a/gopls/internal/cmd/execute.go b/gopls/internal/cmd/execute.go
index 22e7820..381c2a7 100644
--- a/gopls/internal/cmd/execute.go
+++ b/gopls/internal/cmd/execute.go
@@ -13,8 +13,8 @@
 	"os"
 	"strings"
 
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/server"
 	"golang.org/x/tools/gopls/internal/util/slices"
 	"golang.org/x/tools/internal/tool"
diff --git a/gopls/internal/cmd/folding_range.go b/gopls/internal/cmd/folding_range.go
index 4012241..13f78c1 100644
--- a/gopls/internal/cmd/folding_range.go
+++ b/gopls/internal/cmd/folding_range.go
@@ -9,7 +9,7 @@
 	"flag"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/tool"
 )
 
diff --git a/gopls/internal/cmd/format.go b/gopls/internal/cmd/format.go
index 9643cd2..75982c9 100644
--- a/gopls/internal/cmd/format.go
+++ b/gopls/internal/cmd/format.go
@@ -9,7 +9,7 @@
 	"flag"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // format implements the format verb for gopls.
diff --git a/gopls/internal/cmd/help_test.go b/gopls/internal/cmd/help_test.go
index 5c11cd5..dd79c2f 100644
--- a/gopls/internal/cmd/help_test.go
+++ b/gopls/internal/cmd/help_test.go
@@ -32,7 +32,7 @@
 
 func TestHelpFiles(t *testing.T) {
 	testenv.NeedsGoBuild(t) // This is a lie. We actually need the source code.
-	app := cmd.New(appName, "", nil, nil)
+	app := cmd.New(nil)
 	ctx := context.Background()
 	for _, page := range append(app.Commands(), app) {
 		t.Run(page.Name(), func(t *testing.T) {
@@ -65,7 +65,7 @@
 
 func TestVerboseHelp(t *testing.T) {
 	testenv.NeedsGoBuild(t) // This is a lie. We actually need the source code.
-	app := cmd.New(appName, "", nil, nil)
+	app := cmd.New(nil)
 	ctx := context.Background()
 	var buf bytes.Buffer
 	s := flag.NewFlagSet(appName, flag.ContinueOnError)
diff --git a/gopls/internal/cmd/highlight.go b/gopls/internal/cmd/highlight.go
index 3fddf9d..9c1488b 100644
--- a/gopls/internal/cmd/highlight.go
+++ b/gopls/internal/cmd/highlight.go
@@ -9,7 +9,7 @@
 	"flag"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/tool"
 )
 
diff --git a/gopls/internal/cmd/implementation.go b/gopls/internal/cmd/implementation.go
index 180d04d..fcfb631 100644
--- a/gopls/internal/cmd/implementation.go
+++ b/gopls/internal/cmd/implementation.go
@@ -10,7 +10,7 @@
 	"fmt"
 	"sort"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/tool"
 )
 
diff --git a/gopls/internal/cmd/imports.go b/gopls/internal/cmd/imports.go
index d32b094..414ce34 100644
--- a/gopls/internal/cmd/imports.go
+++ b/gopls/internal/cmd/imports.go
@@ -9,7 +9,7 @@
 	"flag"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/tool"
 )
 
diff --git a/gopls/internal/cmd/integration_test.go b/gopls/internal/cmd/integration_test.go
index 80b4e34..aabb8c2 100644
--- a/gopls/internal/cmd/integration_test.go
+++ b/gopls/internal/cmd/integration_test.go
@@ -41,8 +41,9 @@
 	"golang.org/x/tools/gopls/internal/cmd"
 	"golang.org/x/tools/gopls/internal/debug"
 	"golang.org/x/tools/gopls/internal/hooks"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
+	"golang.org/x/tools/gopls/internal/version"
 	"golang.org/x/tools/internal/testenv"
 	"golang.org/x/tools/internal/tool"
 	"golang.org/x/tools/txtar"
@@ -55,7 +56,7 @@
 	tree := writeTree(t, "")
 
 	// There's not much we can robustly assert about the actual version.
-	want := debug.Version() // e.g. "master"
+	want := version.Version() // e.g. "master"
 
 	// basic
 	{
@@ -64,6 +65,13 @@
 		res.checkStdout(want)
 	}
 
+	// basic, with version override
+	{
+		res := goplsWithEnv(t, tree, []string{"TEST_GOPLS_VERSION=v1.2.3"}, "version")
+		res.checkExit(true)
+		res.checkStdout(`v1\.2\.3`)
+	}
+
 	// -json flag
 	{
 		res := gopls(t, tree, "version", "-json")
@@ -894,13 +902,13 @@
 		if got := len(stats2.BugReports); got > 0 {
 			t.Errorf("Got %d bug reports with -anon, want 0. Reports:%+v", got, stats2.BugReports)
 		}
-		var stats2AsMap map[string]interface{}
+		var stats2AsMap map[string]any
 		if err := json.Unmarshal([]byte(res2.stdout), &stats2AsMap); err != nil {
 			t.Fatalf("failed to unmarshal JSON output of stats command: %v", err)
 		}
 		// GOPACKAGESDRIVER is user information, but is ok to print zero value.
-		if v, ok := stats2AsMap["GOPACKAGESDRIVER"]; !ok || v != "" {
-			t.Errorf(`Got GOPACKAGESDRIVER=(%q, %v); want ("", true(found))`, v, ok)
+		if v, ok := stats2AsMap["GOPACKAGESDRIVER"]; ok && v != "" {
+			t.Errorf(`Got GOPACKAGESDRIVER=(%v, %v); want ("", true(found))`, v, ok)
 		}
 	}
 
@@ -978,7 +986,7 @@
 type C struct{}
 
 // Read implements io.Reader.
-func (C) Read(p []byte) (n int, err error) {
+func (c C) Read(p []byte) (n int, err error) {
 	panic("unimplemented")
 }
 `[1:]
@@ -1034,7 +1042,11 @@
 		bug.PanicOnBugs = true
 	}
 
-	tool.Main(context.Background(), cmd.New("gopls", "", nil, hooks.Options), os.Args[1:])
+	if v := os.Getenv("TEST_GOPLS_VERSION"); v != "" {
+		version.VersionOverride = v
+	}
+
+	tool.Main(context.Background(), cmd.New(hooks.Options), os.Args[1:])
 }
 
 // writeTree extracts a txtar archive into a new directory and returns its path.
@@ -1077,6 +1089,7 @@
 
 	goplsCmd := exec.Command(os.Args[0], args...)
 	goplsCmd.Env = append(os.Environ(), "ENTRYPOINT=goplsMain")
+	goplsCmd.Env = append(goplsCmd.Env, "GOPACKAGESDRIVER=off")
 	goplsCmd.Env = append(goplsCmd.Env, env...)
 	goplsCmd.Dir = dir
 	goplsCmd.Stdout = new(bytes.Buffer)
diff --git a/gopls/internal/cmd/links.go b/gopls/internal/cmd/links.go
index f7041ec..0f1d671 100644
--- a/gopls/internal/cmd/links.go
+++ b/gopls/internal/cmd/links.go
@@ -11,7 +11,7 @@
 	"fmt"
 	"os"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/tool"
 )
 
diff --git a/gopls/internal/cmd/parsespan.go b/gopls/internal/cmd/parsespan.go
index c70b85e..556beb9 100644
--- a/gopls/internal/cmd/parsespan.go
+++ b/gopls/internal/cmd/parsespan.go
@@ -9,7 +9,7 @@
 	"strings"
 	"unicode/utf8"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // parseSpan returns the location represented by the input.
diff --git a/gopls/internal/cmd/prepare_rename.go b/gopls/internal/cmd/prepare_rename.go
index 69ed6ca..c7901e6 100644
--- a/gopls/internal/cmd/prepare_rename.go
+++ b/gopls/internal/cmd/prepare_rename.go
@@ -10,7 +10,7 @@
 	"flag"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/tool"
 )
 
diff --git a/gopls/internal/cmd/references.go b/gopls/internal/cmd/references.go
index 670f5fe..3c294c7 100644
--- a/gopls/internal/cmd/references.go
+++ b/gopls/internal/cmd/references.go
@@ -10,7 +10,7 @@
 	"fmt"
 	"sort"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/tool"
 )
 
diff --git a/gopls/internal/cmd/remote.go b/gopls/internal/cmd/remote.go
index 684981c..8de4365 100644
--- a/gopls/internal/cmd/remote.go
+++ b/gopls/internal/cmd/remote.go
@@ -13,8 +13,8 @@
 	"log"
 	"os"
 
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
+	"golang.org/x/tools/gopls/internal/lsprpc"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 )
 
 type remote struct {
diff --git a/gopls/internal/cmd/rename.go b/gopls/internal/cmd/rename.go
index 589f202..6d83168 100644
--- a/gopls/internal/cmd/rename.go
+++ b/gopls/internal/cmd/rename.go
@@ -9,7 +9,7 @@
 	"flag"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/tool"
 )
 
diff --git a/gopls/internal/cmd/semantictokens.go b/gopls/internal/cmd/semantictokens.go
index 538cedc..f181f30 100644
--- a/gopls/internal/cmd/semantictokens.go
+++ b/gopls/internal/cmd/semantictokens.go
@@ -13,7 +13,7 @@
 	"os"
 	"unicode/utf8"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 )
 
diff --git a/gopls/internal/cmd/serve.go b/gopls/internal/cmd/serve.go
index 03eb452..a2f9be9 100644
--- a/gopls/internal/cmd/serve.go
+++ b/gopls/internal/cmd/serve.go
@@ -14,10 +14,10 @@
 	"os"
 	"time"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/debug"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/lsprpc"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/telemetry"
 	"golang.org/x/tools/internal/fakenet"
 	"golang.org/x/tools/internal/jsonrpc2"
diff --git a/gopls/internal/cmd/signature.go b/gopls/internal/cmd/signature.go
index 2402669..cf976a6 100644
--- a/gopls/internal/cmd/signature.go
+++ b/gopls/internal/cmd/signature.go
@@ -9,7 +9,7 @@
 	"flag"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/tool"
 )
 
diff --git a/gopls/internal/cmd/span.go b/gopls/internal/cmd/span.go
index fe8f947..4753d53 100644
--- a/gopls/internal/cmd/span.go
+++ b/gopls/internal/cmd/span.go
@@ -13,7 +13,7 @@
 	"sort"
 	"strings"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // A span represents a range of text within a source file.  The start
@@ -28,7 +28,7 @@
 // representations, such as go/token (also UTF-8) or the LSP protocol
 // (UTF-16). The latter requires access to file contents.
 //
-// See overview comments at ../lsp/protocol/mapper.go.
+// See overview comments at ../protocol/mapper.go.
 type span struct {
 	v _span
 }
diff --git a/gopls/internal/cmd/stats.go b/gopls/internal/cmd/stats.go
index 9417bfe..8da1a1a 100644
--- a/gopls/internal/cmd/stats.go
+++ b/gopls/internal/cmd/stats.go
@@ -19,13 +19,13 @@
 	"sync"
 	"time"
 
-	"golang.org/x/tools/gopls/internal/debug"
 	"golang.org/x/tools/gopls/internal/filecache"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/server"
 	"golang.org/x/tools/gopls/internal/settings"
-	goplsbug "golang.org/x/tools/gopls/internal/util/bug"
+	bugpkg "golang.org/x/tools/gopls/internal/util/bug"
+	versionpkg "golang.org/x/tools/gopls/internal/version"
 	"golang.org/x/tools/internal/event"
 )
 
@@ -74,7 +74,7 @@
 		GOARCH:           runtime.GOARCH,
 		GOPLSCACHE:       os.Getenv("GOPLSCACHE"),
 		GoVersion:        runtime.Version(),
-		GoplsVersion:     debug.Version(),
+		GoplsVersion:     versionpkg.Version(),
 		GOPACKAGESDRIVER: os.Getenv("GOPACKAGESDRIVER"),
 	}
 
@@ -147,7 +147,7 @@
 	do("Gathering bug reports", func() error {
 		stats.CacheDir, stats.BugReports = filecache.BugReports()
 		if stats.BugReports == nil {
-			stats.BugReports = []goplsbug.Bug{} // non-nil for JSON
+			stats.BugReports = []bugpkg.Bug{} // non-nil for JSON
 		}
 		return nil
 	})
@@ -180,7 +180,7 @@
 
 	if _, err := do("Collecting directory info", func() error {
 		var err error
-		stats.DirStats, err = findDirStats(ctx)
+		stats.DirStats, err = findDirStats()
 		if err != nil {
 			return err
 		}
@@ -232,7 +232,7 @@
 	GOPACKAGESDRIVER             string
 	InitialWorkspaceLoadDuration string `anon:"ok"` // in time.Duration string form
 	CacheDir                     string
-	BugReports                   []goplsbug.Bug
+	BugReports                   []bugpkg.Bug
 	MemStats                     command.MemStatsResult       `anon:"ok"`
 	WorkspaceStats               command.WorkspaceStatsResult `anon:"ok"`
 	DirStats                     dirStats                     `anon:"ok"`
@@ -248,7 +248,7 @@
 
 // findDirStats collects information about the current directory and its
 // subdirectories.
-func findDirStats(ctx context.Context) (dirStats, error) {
+func findDirStats() (dirStats, error) {
 	var ds dirStats
 	filepath.WalkDir(".", func(path string, d fs.DirEntry, err error) error {
 		if err != nil {
diff --git a/gopls/internal/cmd/suggested_fix.go b/gopls/internal/cmd/suggested_fix.go
index 9fe6497..f6a88be 100644
--- a/gopls/internal/cmd/suggested_fix.go
+++ b/gopls/internal/cmd/suggested_fix.go
@@ -9,7 +9,7 @@
 	"flag"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/slices"
 	"golang.org/x/tools/internal/tool"
 )
diff --git a/gopls/internal/cmd/symbols.go b/gopls/internal/cmd/symbols.go
index 5000046..249397d 100644
--- a/gopls/internal/cmd/symbols.go
+++ b/gopls/internal/cmd/symbols.go
@@ -11,7 +11,7 @@
 	"fmt"
 	"sort"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/tool"
 )
 
diff --git a/gopls/internal/cmd/usage/vulncheck.hlp b/gopls/internal/cmd/usage/vulncheck.hlp
index d16cb13..7f2818d 100644
--- a/gopls/internal/cmd/usage/vulncheck.hlp
+++ b/gopls/internal/cmd/usage/vulncheck.hlp
@@ -6,7 +6,7 @@
 	WARNING: this command is for internal-use only.
 
 	By default, the command outputs a JSON-encoded
-	golang.org/x/tools/gopls/internal/lsp/command.VulncheckResult
+	golang.org/x/tools/gopls/internal/protocol/command.VulncheckResult
 	message.
 	Example:
 	$ gopls vulncheck <packages>
diff --git a/gopls/internal/cmd/vulncheck.go b/gopls/internal/cmd/vulncheck.go
index 855b9ee..7babf0d 100644
--- a/gopls/internal/cmd/vulncheck.go
+++ b/gopls/internal/cmd/vulncheck.go
@@ -30,7 +30,7 @@
 	WARNING: this command is for internal-use only.
 
 	By default, the command outputs a JSON-encoded
-	golang.org/x/tools/gopls/internal/lsp/command.VulncheckResult
+	golang.org/x/tools/gopls/internal/protocol/command.VulncheckResult
 	message.
 	Example:
 	$ gopls vulncheck <packages>
diff --git a/gopls/internal/cmd/workspace_symbol.go b/gopls/internal/cmd/workspace_symbol.go
index f41a85f..9fa7526 100644
--- a/gopls/internal/cmd/workspace_symbol.go
+++ b/gopls/internal/cmd/workspace_symbol.go
@@ -10,7 +10,7 @@
 	"fmt"
 	"strings"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/internal/tool"
 )
diff --git a/gopls/internal/debug/info.go b/gopls/internal/debug/info.go
index 84027ec..b2824d8 100644
--- a/gopls/internal/debug/info.go
+++ b/gopls/internal/debug/info.go
@@ -14,6 +14,8 @@
 	"runtime"
 	"runtime/debug"
 	"strings"
+
+	"golang.org/x/tools/gopls/internal/version"
 )
 
 type PrintMode int
@@ -25,16 +27,6 @@
 	JSON
 )
 
-// Version is a manually-updated mechanism for tracking versions.
-func Version() string {
-	if info, ok := debug.ReadBuildInfo(); ok {
-		if info.Main.Version != "" {
-			return info.Main.Version
-		}
-	}
-	return "(unknown)"
-}
-
 // ServerVersion is the format used by gopls to report its version to the
 // client. This format is structured so that the client can parse it easily.
 type ServerVersion struct {
@@ -48,12 +40,12 @@
 func VersionInfo() *ServerVersion {
 	if info, ok := debug.ReadBuildInfo(); ok {
 		return &ServerVersion{
-			Version:   Version(),
+			Version:   version.Version(),
 			BuildInfo: info,
 		}
 	}
 	return &ServerVersion{
-		Version: Version(),
+		Version: version.Version(),
 		BuildInfo: &debug.BuildInfo{
 			Path:      "gopls, built in GOPATH mode",
 			GoVersion: runtime.Version(),
@@ -63,11 +55,12 @@
 
 // PrintServerInfo writes HTML debug info to w for the Instance.
 func (i *Instance) PrintServerInfo(ctx context.Context, w io.Writer) {
+	workDir, _ := os.Getwd()
 	section(w, HTML, "Server Instance", func() {
 		fmt.Fprintf(w, "Start time: %v\n", i.StartTime)
 		fmt.Fprintf(w, "LogFile: %s\n", i.Logfile)
 		fmt.Fprintf(w, "pid: %d\n", os.Getpid())
-		fmt.Fprintf(w, "Working directory: %s\n", i.Workdir)
+		fmt.Fprintf(w, "Working directory: %s\n", workDir)
 		fmt.Fprintf(w, "Address: %s\n", i.ServerAddress)
 		fmt.Fprintf(w, "Debug address: %s\n", i.DebugAddress())
 	})
@@ -123,11 +116,11 @@
 }
 
 func printBuildInfo(w io.Writer, info *ServerVersion, verbose bool, mode PrintMode) {
-	fmt.Fprintf(w, "%v %v\n", info.Path, Version())
-	printModuleInfo(w, info.Main, mode)
+	fmt.Fprintf(w, "%v %v\n", info.Path, version.Version())
 	if !verbose {
 		return
 	}
+	printModuleInfo(w, info.Main, mode)
 	for _, dep := range info.Deps {
 		printModuleInfo(w, *dep, mode)
 	}
diff --git a/gopls/internal/debug/info_test.go b/gopls/internal/debug/info_test.go
index 3bc9290..7f24b69 100644
--- a/gopls/internal/debug/info_test.go
+++ b/gopls/internal/debug/info_test.go
@@ -11,6 +11,8 @@
 	"encoding/json"
 	"runtime"
 	"testing"
+
+	"golang.org/x/tools/gopls/internal/version"
 )
 
 func TestPrintVersionInfoJSON(t *testing.T) {
@@ -27,7 +29,7 @@
 	if g, w := got.GoVersion, runtime.Version(); g != w {
 		t.Errorf("go version = %v, want %v", g, w)
 	}
-	if g, w := got.Version, Version(); g != w {
+	if g, w := got.Version, version.Version(); g != w {
 		t.Errorf("gopls version = %v, want %v", g, w)
 	}
 	// Other fields of BuildInfo may not be available during test.
@@ -41,7 +43,7 @@
 	res := buf.Bytes()
 
 	// Other fields of BuildInfo may not be available during test.
-	wantGoplsVersion, wantGoVersion := Version(), runtime.Version()
+	wantGoplsVersion, wantGoVersion := version.Version(), runtime.Version()
 	if !bytes.Contains(res, []byte(wantGoplsVersion)) || !bytes.Contains(res, []byte(wantGoVersion)) {
 		t.Errorf("plaintext output = %q,\nwant (version: %v, go: %v)", res, wantGoplsVersion, wantGoVersion)
 	}
diff --git a/gopls/internal/debug/rpc.go b/gopls/internal/debug/rpc.go
index 5610021..0fee0f4 100644
--- a/gopls/internal/debug/rpc.go
+++ b/gopls/internal/debug/rpc.go
@@ -84,19 +84,19 @@
 	defer r.mu.Unlock()
 	switch {
 	case event.IsStart(ev):
-		if _, stats := r.getRPCSpan(ctx, ev); stats != nil {
+		if _, stats := r.getRPCSpan(ctx); stats != nil {
 			stats.Started++
 		}
 	case event.IsEnd(ev):
-		span, stats := r.getRPCSpan(ctx, ev)
+		span, stats := r.getRPCSpan(ctx)
 		if stats != nil {
-			endRPC(ctx, ev, span, stats)
+			endRPC(span, stats)
 		}
 	case event.IsMetric(ev):
 		sent := byteUnits(tag.SentBytes.Get(lm))
 		rec := byteUnits(tag.ReceivedBytes.Get(lm))
 		if sent != 0 || rec != 0 {
-			if _, stats := r.getRPCSpan(ctx, ev); stats != nil {
+			if _, stats := r.getRPCSpan(ctx); stats != nil {
 				stats.Sent += sent
 				stats.Received += rec
 			}
@@ -105,7 +105,7 @@
 	return ctx
 }
 
-func endRPC(ctx context.Context, ev core.Event, span *export.Span, stats *rpcStats) {
+func endRPC(span *export.Span, stats *rpcStats) {
 	// update the basic counts
 	stats.Completed++
 
@@ -152,7 +152,7 @@
 	}
 }
 
-func (r *Rpcs) getRPCSpan(ctx context.Context, ev core.Event) (*export.Span, *rpcStats) {
+func (r *Rpcs) getRPCSpan(ctx context.Context) (*export.Span, *rpcStats) {
 	// get the span
 	span := export.GetSpan(ctx)
 	if span == nil {
diff --git a/gopls/internal/debug/serve.go b/gopls/internal/debug/serve.go
index d7ba381..62e4168 100644
--- a/gopls/internal/debug/serve.go
+++ b/gopls/internal/debug/serve.go
@@ -24,9 +24,9 @@
 	"sync"
 	"time"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/debug/log"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/core"
@@ -51,7 +51,6 @@
 	Logfile       string
 	StartTime     time.Time
 	ServerAddress string
-	Workdir       string
 	OCAgentConfig string
 
 	LogWriter io.Writer
@@ -368,10 +367,9 @@
 
 // WithInstance creates debug instance ready for use using the supplied
 // configuration and stores it in the returned context.
-func WithInstance(ctx context.Context, workdir, agent string) context.Context {
+func WithInstance(ctx context.Context, agent string) context.Context {
 	i := &Instance{
 		StartTime:     time.Now(),
-		Workdir:       workdir,
 		OCAgentConfig: agent,
 	}
 	i.LogWriter = os.Stderr
@@ -464,7 +462,6 @@
 		mux.HandleFunc("/analysis/", render(AnalysisTmpl, i.getAnalysis))
 		mux.HandleFunc("/cache/", render(CacheTmpl, i.getCache))
 		mux.HandleFunc("/session/", render(SessionTmpl, i.getSession))
-		mux.HandleFunc("/view/", render(ViewTmpl, i.getView))
 		mux.HandleFunc("/client/", render(ClientTmpl, i.getClient))
 		mux.HandleFunc("/server/", render(ServerTmpl, i.getServer))
 		mux.HandleFunc("/file/", render(FileTmpl, i.getFile))
@@ -646,12 +643,17 @@
 	width:6rem;
 }
 td.value {
-  text-align: right;
+	text-align: right;
 }
 ul.spans {
 	font-family: monospace;
 	font-size:   85%;
 }
+body {
+	font-family: sans-serif;
+	font-size: 1rem;
+	line-height: normal;
+}
 </style>
 {{block "head" .}}{{end}}
 </head>
@@ -676,7 +678,6 @@
 {{define "clientlink"}}<a href="/client/{{.}}">Client {{.}}</a>{{end}}
 {{define "serverlink"}}<a href="/server/{{.}}">Server {{.}}</a>{{end}}
 {{define "sessionlink"}}<a href="/session/{{.}}">Session {{.}}</a>{{end}}
-{{define "viewlink"}}<a href="/view/{{.}}">View {{.}}</a>{{end}}
 `)).Funcs(template.FuncMap{
 	"fuint64":  fuint64,
 	"fuint32":  fuint32,
@@ -708,7 +709,7 @@
 })
 
 var MainTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
-{{define "title"}}GoPls server information{{end}}
+{{define "title"}}Gopls server information{{end}}
 {{define "body"}}
 <h2>Caches</h2>
 <ul>{{range .State.Caches}}<li>{{template "cachelink" .ID}}</li>{{end}}</ul>
@@ -724,7 +725,7 @@
 `))
 
 var InfoTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
-{{define "title"}}GoPls version information{{end}}
+{{define "title"}}Gopls version information{{end}}
 {{define "body"}}
 {{.}}
 {{end}}
@@ -773,6 +774,13 @@
 {{define "body"}}
 <h2>memoize.Store entries</h2>
 <ul>{{range $k,$v := .MemStats}}<li>{{$k}} - {{$v}}</li>{{end}}</ul>
+<h2>File stats</h2>
+<p>
+{{- $stats := .FileStats -}}
+Total: <b>{{$stats.Total}}</b><br>
+Largest: <b>{{$stats.Largest}}</b><br>
+Errors: <b>{{$stats.Errs}}</b><br>
+</p>
 {{end}}
 `))
 
@@ -808,7 +816,16 @@
 {{define "body"}}
 From: <b>{{template "cachelink" .Cache.ID}}</b><br>
 <h2>Views</h2>
-<ul>{{range .Views}}<li>{{.Folder.Name}} is {{template "viewlink" .ID}} in {{.Folder.Dir}}</li>{{end}}</ul>
+<ul>{{range .Views}}
+{{- $envOverlay := .EnvOverlay -}}
+<li>ID: <b>{{.ID}}</b><br>
+Type: <b>{{.Type}}</b><br>
+Root: <b>{{.Root}}</b><br>
+{{- if $envOverlay}}
+Env overlay: <b>{{$envOverlay}})</b><br>
+{{end -}}
+Folder: <b>{{.Folder.Name}}:{{.Folder.Dir}}</b></li>
+{{end}}</ul>
 <h2>Overlays</h2>
 {{$session := .}}
 <ul>{{range .Overlays}}
@@ -818,14 +835,6 @@
 {{end}}
 `))
 
-var ViewTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
-{{define "title"}}View {{.ID}}{{end}}
-{{define "body"}}
-Name: <b>{{.Folder.Name}}</b><br>
-Folder: <b>{{.Folder.Dir}}</b><br>
-{{end}}
-`))
-
 var FileTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
 {{define "title"}}Overlay {{.Identity.Hash}}{{end}}
 {{define "body"}}
diff --git a/gopls/internal/debug/template_test.go b/gopls/internal/debug/template_test.go
index 53d4cb1..db940ef 100644
--- a/gopls/internal/debug/template_test.go
+++ b/gopls/internal/debug/template_test.go
@@ -21,8 +21,9 @@
 
 	"github.com/jba/templatecheck"
 	"golang.org/x/tools/go/packages"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/debug"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
+	"golang.org/x/tools/gopls/internal/file"
 	"golang.org/x/tools/internal/testenv"
 )
 
@@ -30,16 +31,18 @@
 	tmpl *template.Template
 	data interface{} // a value of the needed type
 }{
-	"MainTmpl":     {debug.MainTmpl, &debug.Instance{}},
-	"DebugTmpl":    {debug.DebugTmpl, nil},
-	"RPCTmpl":      {debug.RPCTmpl, &debug.Rpcs{}},
-	"TraceTmpl":    {debug.TraceTmpl, debug.TraceResults{}},
-	"CacheTmpl":    {debug.CacheTmpl, &cache.Cache{}},
-	"SessionTmpl":  {debug.SessionTmpl, &cache.Session{}},
-	"ViewTmpl":     {debug.ViewTmpl, &cache.View{}},
-	"ClientTmpl":   {debug.ClientTmpl, &debug.Client{}},
-	"ServerTmpl":   {debug.ServerTmpl, &debug.Server{}},
-	"FileTmpl":     {debug.FileTmpl, &cache.Overlay{}},
+	"MainTmpl":    {debug.MainTmpl, &debug.Instance{}},
+	"DebugTmpl":   {debug.DebugTmpl, nil},
+	"RPCTmpl":     {debug.RPCTmpl, &debug.Rpcs{}},
+	"TraceTmpl":   {debug.TraceTmpl, debug.TraceResults{}},
+	"CacheTmpl":   {debug.CacheTmpl, &cache.Cache{}},
+	"SessionTmpl": {debug.SessionTmpl, &cache.Session{}},
+	"ClientTmpl":  {debug.ClientTmpl, &debug.Client{}},
+	"ServerTmpl":  {debug.ServerTmpl, &debug.Server{}},
+	"FileTmpl": {debug.FileTmpl, *new(interface {
+		file.Handle
+		Kind() file.Kind // (overlay files only)
+	})},
 	"InfoTmpl":     {debug.InfoTmpl, "something"},
 	"MemoryTmpl":   {debug.MemoryTmpl, runtime.MemStats{}},
 	"AnalysisTmpl": {debug.AnalysisTmpl, new(debug.State).Analysis()},
@@ -75,7 +78,7 @@
 	if tree == nil {
 		t.Fatalf("found no syntax tree for %s", "serve.go")
 	}
-	renders := callsOf(p, tree, "render")
+	renders := callsOf(tree, "render")
 	if len(renders) == 0 {
 		t.Fatalf("found no calls to render")
 	}
@@ -123,7 +126,7 @@
 	}
 }
 
-func callsOf(p *packages.Package, tree *ast.File, name string) []*ast.CallExpr {
+func callsOf(tree *ast.File, name string) []*ast.CallExpr {
 	var ans []*ast.CallExpr
 	f := func(n ast.Node) bool {
 		x, ok := n.(*ast.CallExpr)
diff --git a/gopls/internal/debug/trace.go b/gopls/internal/debug/trace.go
index 31c5a53..9314a04 100644
--- a/gopls/internal/debug/trace.go
+++ b/gopls/internal/debug/trace.go
@@ -150,14 +150,14 @@
 				ctx = context.WithValue(ctx, traceKey, task)
 			}
 			// Log the start event as it may contain useful labels.
-			msg := formatEvent(ctx, ev, lm)
+			msg := formatEvent(ev, lm)
 			trace.Log(ctx, "start", msg)
 		case event.IsLog(ev):
 			category := ""
 			if event.IsError(ev) {
 				category = "error"
 			}
-			msg := formatEvent(ctx, ev, lm)
+			msg := formatEvent(ev, lm)
 			trace.Log(ctx, category, msg)
 		case event.IsEnd(ev):
 			if v := ctx.Value(traceKey); v != nil {
@@ -168,7 +168,7 @@
 	}
 }
 
-func formatEvent(ctx context.Context, ev core.Event, lm label.Map) string {
+func formatEvent(ev core.Event, lm label.Map) string {
 	buf := &bytes.Buffer{}
 	p := export.Printer{}
 	p.WriteEvent(buf, ev, lm)
diff --git a/gopls/internal/file/file.go b/gopls/internal/file/file.go
index 5a9d0ac..5f8be06 100644
--- a/gopls/internal/file/file.go
+++ b/gopls/internal/file/file.go
@@ -9,7 +9,7 @@
 	"context"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // An Identity identifies the name and contents of a file.
diff --git a/gopls/internal/file/modification.go b/gopls/internal/file/modification.go
index 97313dd..5deef71 100644
--- a/gopls/internal/file/modification.go
+++ b/gopls/internal/file/modification.go
@@ -4,7 +4,7 @@
 
 package file
 
-import "golang.org/x/tools/gopls/internal/lsp/protocol"
+import "golang.org/x/tools/gopls/internal/protocol"
 
 // Modification represents a modification to a file.
 type Modification struct {
diff --git a/gopls/internal/lsp/source/add_import.go b/gopls/internal/golang/add_import.go
similarity index 86%
rename from gopls/internal/lsp/source/add_import.go
rename to gopls/internal/golang/add_import.go
index 90d136d..201edce 100644
--- a/gopls/internal/lsp/source/add_import.go
+++ b/gopls/internal/golang/add_import.go
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/imports"
 )
 
diff --git a/gopls/internal/lsp/source/call_hierarchy.go b/gopls/internal/golang/call_hierarchy.go
similarity index 96%
rename from gopls/internal/lsp/source/call_hierarchy.go
rename to gopls/internal/golang/call_hierarchy.go
index e1b8f00..87a6a54 100644
--- a/gopls/internal/lsp/source/call_hierarchy.go
+++ b/gopls/internal/golang/call_hierarchy.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -14,9 +14,9 @@
 	"path/filepath"
 
 	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/event"
@@ -25,7 +25,7 @@
 
 // PrepareCallHierarchy returns an array of CallHierarchyItem for a file and the position within the file.
 func PrepareCallHierarchy(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, pp protocol.Position) ([]protocol.CallHierarchyItem, error) {
-	ctx, done := event.Start(ctx, "source.PrepareCallHierarchy")
+	ctx, done := event.Start(ctx, "golang.PrepareCallHierarchy")
 	defer done()
 
 	pkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())
@@ -66,7 +66,7 @@
 
 // IncomingCalls returns an array of CallHierarchyIncomingCall for a file and the position within the file.
 func IncomingCalls(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, pos protocol.Position) ([]protocol.CallHierarchyIncomingCall, error) {
-	ctx, done := event.Start(ctx, "source.IncomingCalls")
+	ctx, done := event.Start(ctx, "golang.IncomingCalls")
 	defer done()
 
 	refs, err := references(ctx, snapshot, fh, pos, false)
@@ -180,7 +180,7 @@
 
 // OutgoingCalls returns an array of CallHierarchyOutgoingCall for a file and the position within the file.
 func OutgoingCalls(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, pp protocol.Position) ([]protocol.CallHierarchyOutgoingCall, error) {
-	ctx, done := event.Start(ctx, "source.OutgoingCalls")
+	ctx, done := event.Start(ctx, "golang.OutgoingCalls")
 	defer done()
 
 	pkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())
diff --git a/gopls/internal/lsp/source/change_quote.go b/gopls/internal/golang/change_quote.go
similarity index 84%
rename from gopls/internal/lsp/source/change_quote.go
rename to gopls/internal/golang/change_quote.go
index 57dffdb..98a60e1 100644
--- a/gopls/internal/lsp/source/change_quote.go
+++ b/gopls/internal/golang/change_quote.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"go/ast"
@@ -12,7 +12,7 @@
 
 	"golang.org/x/tools/go/ast/astutil"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/diff"
@@ -78,17 +78,7 @@
 		Title: title,
 		Kind:  protocol.RefactorRewrite,
 		Edit: &protocol.WorkspaceEdit{
-			DocumentChanges: []protocol.DocumentChanges{
-				{
-					TextDocumentEdit: &protocol.TextDocumentEdit{
-						TextDocument: protocol.OptionalVersionedTextDocumentIdentifier{
-							Version:                fh.Version(),
-							TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI: fh.URI()},
-						},
-						Edits: protocol.AsAnnotatedTextEdits(pedits),
-					},
-				},
-			},
+			DocumentChanges: documentChanges(fh, pedits),
 		},
 	}, true
 }
diff --git a/gopls/internal/lsp/source/change_signature.go b/gopls/internal/golang/change_signature.go
similarity index 96%
rename from gopls/internal/lsp/source/change_signature.go
rename to gopls/internal/golang/change_signature.go
index 76ea0d2..e0a829e 100644
--- a/gopls/internal/lsp/source/change_signature.go
+++ b/gopls/internal/golang/change_signature.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"bytes"
@@ -16,10 +16,10 @@
 	"regexp"
 
 	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/imports"
@@ -134,6 +134,7 @@
 	if err != nil {
 		return nil, err
 	}
+
 	// Finally, rewrite the original declaration. We do this after inlining all
 	// calls, as there may be calls in the same file as the declaration. But none
 	// of the inlining should have changed the location of the original
@@ -149,7 +150,10 @@
 			src = pgf.Src
 		}
 		fset := tokeninternal.FileSetFor(pgf.Tok)
-		src, err = rewriteSignature(fset, idx, src, newDecl)
+		src, err := rewriteSignature(fset, idx, src, newDecl)
+		if err != nil {
+			return nil, err
+		}
 		newContent[pgf.URI] = src
 	}
 
@@ -170,15 +174,7 @@
 		if err != nil {
 			return nil, fmt.Errorf("computing edits for %s: %v", uri, err)
 		}
-		changes = append(changes, protocol.DocumentChanges{
-			TextDocumentEdit: &protocol.TextDocumentEdit{
-				TextDocument: protocol.OptionalVersionedTextDocumentIdentifier{
-					Version:                fh.Version(),
-					TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI: uri},
-				},
-				Edits: protocol.AsAnnotatedTextEdits(pedits),
-			},
-		})
+		changes = append(changes, documentChanges(fh, pedits)...)
 	}
 	return changes, nil
 }
diff --git a/gopls/internal/lsp/source/code_lens.go b/gopls/internal/golang/code_lens.go
similarity index 97%
rename from gopls/internal/lsp/source/code_lens.go
rename to gopls/internal/golang/code_lens.go
index 3646656..c4a7e5f 100644
--- a/gopls/internal/lsp/source/code_lens.go
+++ b/gopls/internal/golang/code_lens.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -12,10 +12,10 @@
 	"regexp"
 	"strings"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 )
 
 type LensFunc func(context.Context, *cache.Snapshot, file.Handle) ([]protocol.CodeLens, error)
diff --git a/gopls/internal/golang/codeaction.go b/gopls/internal/golang/codeaction.go
new file mode 100644
index 0000000..a9aae82
--- /dev/null
+++ b/gopls/internal/golang/codeaction.go
@@ -0,0 +1,454 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package golang
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"go/ast"
+	"strings"
+
+	"golang.org/x/tools/go/ast/inspector"
+	"golang.org/x/tools/gopls/internal/analysis/fillstruct"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
+	"golang.org/x/tools/gopls/internal/file"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
+	"golang.org/x/tools/gopls/internal/settings"
+	"golang.org/x/tools/gopls/internal/util/bug"
+	"golang.org/x/tools/gopls/internal/util/slices"
+	"golang.org/x/tools/internal/event"
+	"golang.org/x/tools/internal/event/tag"
+	"golang.org/x/tools/internal/imports"
+)
+
+// CodeActions returns all code actions (edits and other commands)
+// available for the selected range.
+func CodeActions(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range, diagnostics []protocol.Diagnostic, want map[protocol.CodeActionKind]bool) (actions []protocol.CodeAction, _ error) {
+	// Only compute quick fixes if there are any diagnostics to fix.
+	wantQuickFixes := want[protocol.QuickFix] && len(diagnostics) > 0
+
+	// Code actions requiring syntax information alone.
+	if wantQuickFixes || want[protocol.SourceOrganizeImports] || want[protocol.RefactorExtract] {
+		pgf, err := snapshot.ParseGo(ctx, fh, parsego.ParseFull)
+		if err != nil {
+			return nil, err
+		}
+
+		// Process any missing imports and pair them with the diagnostics they fix.
+		if wantQuickFixes || want[protocol.SourceOrganizeImports] {
+			importEdits, importEditsPerFix, err := allImportsFixes(ctx, snapshot, pgf)
+			if err != nil {
+				event.Error(ctx, "imports fixes", err, tag.File.Of(fh.URI().Path()))
+				importEdits = nil
+				importEditsPerFix = nil
+			}
+
+			// Separate this into a set of codeActions per diagnostic, where
+			// each action is the addition, removal, or renaming of one import.
+			if wantQuickFixes {
+				for _, importFix := range importEditsPerFix {
+					fixed := fixedByImportFix(importFix.fix, diagnostics)
+					if len(fixed) == 0 {
+						continue
+					}
+					actions = append(actions, protocol.CodeAction{
+						Title: importFixTitle(importFix.fix),
+						Kind:  protocol.QuickFix,
+						Edit: &protocol.WorkspaceEdit{
+							DocumentChanges: documentChanges(fh, importFix.edits),
+						},
+						Diagnostics: fixed,
+					})
+				}
+			}
+
+			// Send all of the import edits as one code action if the file is
+			// being organized.
+			if want[protocol.SourceOrganizeImports] && len(importEdits) > 0 {
+				actions = append(actions, protocol.CodeAction{
+					Title: "Organize Imports",
+					Kind:  protocol.SourceOrganizeImports,
+					Edit: &protocol.WorkspaceEdit{
+						DocumentChanges: documentChanges(fh, importEdits),
+					},
+				})
+			}
+		}
+
+		if want[protocol.RefactorExtract] {
+			extractions, err := getExtractCodeActions(pgf, rng, snapshot.Options())
+			if err != nil {
+				return nil, err
+			}
+			actions = append(actions, extractions...)
+		}
+	}
+
+	// Code actions requiring type information.
+	if want[protocol.RefactorRewrite] ||
+		want[protocol.RefactorInline] ||
+		want[protocol.GoTest] {
+		pkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())
+		if err != nil {
+			return nil, err
+		}
+		if want[protocol.RefactorRewrite] {
+			rewrites, err := getRewriteCodeActions(pkg, pgf, fh, rng, snapshot.Options())
+			if err != nil {
+				return nil, err
+			}
+			actions = append(actions, rewrites...)
+		}
+
+		if want[protocol.RefactorInline] {
+			rewrites, err := getInlineCodeActions(pkg, pgf, rng)
+			if err != nil {
+				return nil, err
+			}
+			actions = append(actions, rewrites...)
+		}
+
+		if want[protocol.GoTest] {
+			fixes, err := getGoTestCodeActions(pkg, pgf, rng)
+			if err != nil {
+				return nil, err
+			}
+			actions = append(actions, fixes...)
+		}
+	}
+	return actions, nil
+}
+
+func supportsResolveEdits(options *settings.Options) bool {
+	return options.CodeActionResolveOptions != nil && slices.Contains(options.CodeActionResolveOptions, "edit")
+}
+
+func importFixTitle(fix *imports.ImportFix) string {
+	var str string
+	switch fix.FixType {
+	case imports.AddImport:
+		str = fmt.Sprintf("Add import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
+	case imports.DeleteImport:
+		str = fmt.Sprintf("Delete import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
+	case imports.SetImportName:
+		str = fmt.Sprintf("Rename import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
+	}
+	return str
+}
+
+// fixedByImportFix filters the provided slice of diagnostics to those that
+// would be fixed by the provided imports fix.
+func fixedByImportFix(fix *imports.ImportFix, diagnostics []protocol.Diagnostic) []protocol.Diagnostic {
+	var results []protocol.Diagnostic
+	for _, diagnostic := range diagnostics {
+		switch {
+		// "undeclared name: X" may be an unresolved import.
+		case strings.HasPrefix(diagnostic.Message, "undeclared name: "):
+			ident := strings.TrimPrefix(diagnostic.Message, "undeclared name: ")
+			if ident == fix.IdentName {
+				results = append(results, diagnostic)
+			}
+		// "undefined: X" may be an unresolved import at Go 1.20+.
+		case strings.HasPrefix(diagnostic.Message, "undefined: "):
+			ident := strings.TrimPrefix(diagnostic.Message, "undefined: ")
+			if ident == fix.IdentName {
+				results = append(results, diagnostic)
+			}
+		// "could not import: X" may be an invalid import.
+		case strings.HasPrefix(diagnostic.Message, "could not import: "):
+			ident := strings.TrimPrefix(diagnostic.Message, "could not import: ")
+			if ident == fix.IdentName {
+				results = append(results, diagnostic)
+			}
+		// "X imported but not used" is an unused import.
+		// "X imported but not used as Y" is an unused import.
+		case strings.Contains(diagnostic.Message, " imported but not used"):
+			idx := strings.Index(diagnostic.Message, " imported but not used")
+			importPath := diagnostic.Message[:idx]
+			if importPath == fmt.Sprintf("%q", fix.StmtInfo.ImportPath) {
+				results = append(results, diagnostic)
+			}
+		}
+	}
+	return results
+}
+
+// getExtractCodeActions returns any refactor.extract code actions for the selection.
+func getExtractCodeActions(pgf *ParsedGoFile, rng protocol.Range, options *settings.Options) ([]protocol.CodeAction, error) {
+	if rng.Start == rng.End {
+		return nil, nil
+	}
+
+	start, end, err := pgf.RangePos(rng)
+	if err != nil {
+		return nil, err
+	}
+	puri := pgf.URI
+	var commands []protocol.Command
+	if _, ok, methodOk, _ := CanExtractFunction(pgf.Tok, start, end, pgf.Src, pgf.File); ok {
+		cmd, err := command.NewApplyFixCommand("Extract function", command.ApplyFixArgs{
+			Fix:          fixExtractFunction,
+			URI:          puri,
+			Range:        rng,
+			ResolveEdits: supportsResolveEdits(options),
+		})
+		if err != nil {
+			return nil, err
+		}
+		commands = append(commands, cmd)
+		if methodOk {
+			cmd, err := command.NewApplyFixCommand("Extract method", command.ApplyFixArgs{
+				Fix:          fixExtractMethod,
+				URI:          puri,
+				Range:        rng,
+				ResolveEdits: supportsResolveEdits(options),
+			})
+			if err != nil {
+				return nil, err
+			}
+			commands = append(commands, cmd)
+		}
+	}
+	if _, _, ok, _ := CanExtractVariable(start, end, pgf.File); ok {
+		cmd, err := command.NewApplyFixCommand("Extract variable", command.ApplyFixArgs{
+			Fix:          fixExtractVariable,
+			URI:          puri,
+			Range:        rng,
+			ResolveEdits: supportsResolveEdits(options),
+		})
+		if err != nil {
+			return nil, err
+		}
+		commands = append(commands, cmd)
+	}
+	var actions []protocol.CodeAction
+	for i := range commands {
+		actions = append(actions, newCodeAction(commands[i].Title, protocol.RefactorExtract, &commands[i], nil, options))
+	}
+	return actions, nil
+}
+
+func newCodeAction(title string, kind protocol.CodeActionKind, cmd *protocol.Command, diagnostics []protocol.Diagnostic, options *settings.Options) protocol.CodeAction {
+	action := protocol.CodeAction{
+		Title:       title,
+		Kind:        kind,
+		Diagnostics: diagnostics,
+	}
+	if !supportsResolveEdits(options) {
+		action.Command = cmd
+	} else {
+		data, err := json.Marshal(cmd)
+		if err != nil {
+			panic("unable to marshal")
+		}
+		msg := json.RawMessage(data)
+		action.Data = &msg
+	}
+	return action
+}
+
+// getRewriteCodeActions returns refactor.rewrite code actions available at the specified range.
+func getRewriteCodeActions(pkg *cache.Package, pgf *ParsedGoFile, fh file.Handle, rng protocol.Range, options *settings.Options) (_ []protocol.CodeAction, rerr error) {
+	// golang/go#61693: code actions were refactored to run outside of the
+	// analysis framework, but as a result they lost their panic recovery.
+	//
+	// These code actions should never fail, but put back the panic recovery as a
+	// defensive measure.
+	defer func() {
+		if r := recover(); r != nil {
+			rerr = bug.Errorf("refactor.rewrite code actions panicked: %v", r)
+		}
+	}()
+
+	var actions []protocol.CodeAction
+
+	if canRemoveParameter(pkg, pgf, rng) {
+		cmd, err := command.NewChangeSignatureCommand("remove unused parameter", command.ChangeSignatureArgs{
+			RemoveParameter: protocol.Location{
+				URI:   pgf.URI,
+				Range: rng,
+			},
+			ResolveEdits: supportsResolveEdits(options),
+		})
+		if err != nil {
+			return nil, err
+		}
+		actions = append(actions, newCodeAction("Refactor: remove unused parameter", protocol.RefactorRewrite, &cmd, nil, options))
+	}
+
+	if action, ok := ConvertStringLiteral(pgf, fh, rng); ok {
+		actions = append(actions, action)
+	}
+
+	start, end, err := pgf.RangePos(rng)
+	if err != nil {
+		return nil, err
+	}
+
+	var commands []protocol.Command
+	if _, ok, _ := CanInvertIfCondition(pgf.File, start, end); ok {
+		cmd, err := command.NewApplyFixCommand("Invert 'if' condition", command.ApplyFixArgs{
+			Fix:          fixInvertIfCondition,
+			URI:          pgf.URI,
+			Range:        rng,
+			ResolveEdits: supportsResolveEdits(options),
+		})
+		if err != nil {
+			return nil, err
+		}
+		commands = append(commands, cmd)
+	}
+
+	// N.B.: an inspector only pays for itself after ~5 passes, which means we're
+	// currently not getting a good deal on this inspection.
+	//
+	// TODO: Consider removing the inspection after convenienceAnalyzers are removed.
+	inspect := inspector.New([]*ast.File{pgf.File})
+	for _, diag := range fillstruct.Diagnose(inspect, start, end, pkg.GetTypes(), pkg.GetTypesInfo()) {
+		rng, err := pgf.Mapper.PosRange(pgf.Tok, diag.Pos, diag.End)
+		if err != nil {
+			return nil, err
+		}
+		for _, fix := range diag.SuggestedFixes {
+			cmd, err := command.NewApplyFixCommand(fix.Message, command.ApplyFixArgs{
+				Fix:          diag.Category,
+				URI:          pgf.URI,
+				Range:        rng,
+				ResolveEdits: supportsResolveEdits(options),
+			})
+			if err != nil {
+				return nil, err
+			}
+			commands = append(commands, cmd)
+		}
+	}
+
+	for i := range commands {
+		actions = append(actions, newCodeAction(commands[i].Title, protocol.RefactorRewrite, &commands[i], nil, options))
+	}
+
+	return actions, nil
+}
+
+// canRemoveParameter reports whether we can remove the function parameter
+// indicated by the given [start, end) range.
+//
+// This is true if:
+//   - [start, end) is contained within an unused field or parameter name
+//   - ... of a non-method function declaration.
+//
+// (Note that the unusedparam analyzer also computes this property, but
+// much more precisely, allowing it to report its findings as diagnostics.)
+func canRemoveParameter(pkg *cache.Package, pgf *ParsedGoFile, rng protocol.Range) bool {
+	info, err := FindParam(pgf, rng)
+	if err != nil {
+		return false // e.g. invalid range
+	}
+	if info.Field == nil {
+		return false // range does not span a parameter
+	}
+	if info.Decl.Body == nil {
+		return false // external function
+	}
+	if len(info.Field.Names) == 0 {
+		return true // no names => field is unused
+	}
+	if info.Name == nil {
+		return false // no name is indicated
+	}
+	if info.Name.Name == "_" {
+		return true // trivially unused
+	}
+
+	obj := pkg.GetTypesInfo().Defs[info.Name]
+	if obj == nil {
+		return false // something went wrong
+	}
+
+	used := false
+	ast.Inspect(info.Decl.Body, func(node ast.Node) bool {
+		if n, ok := node.(*ast.Ident); ok && pkg.GetTypesInfo().Uses[n] == obj {
+			used = true
+		}
+		return !used // keep going until we find a use
+	})
+	return !used
+}
+
+// getInlineCodeActions returns refactor.inline actions available at the specified range.
+func getInlineCodeActions(pkg *cache.Package, pgf *ParsedGoFile, rng protocol.Range) ([]protocol.CodeAction, error) {
+	start, end, err := pgf.RangePos(rng)
+	if err != nil {
+		return nil, err
+	}
+
+	// If range is within call expression, offer inline action.
+	var commands []protocol.Command
+	if _, fn, err := EnclosingStaticCall(pkg, pgf, start, end); err == nil {
+		cmd, err := command.NewApplyFixCommand(fmt.Sprintf("Inline call to %s", fn.Name()), command.ApplyFixArgs{
+			Fix:   fixInlineCall,
+			URI:   pgf.URI,
+			Range: rng,
+		})
+		if err != nil {
+			return nil, err
+		}
+		commands = append(commands, cmd)
+	}
+
+	// Convert commands to actions.
+	var actions []protocol.CodeAction
+	for i := range commands {
+		actions = append(actions, protocol.CodeAction{
+			Title:   commands[i].Title,
+			Kind:    protocol.RefactorInline,
+			Command: &commands[i],
+		})
+	}
+	return actions, nil
+}
+
+// getGoTestCodeActions returns any "run this test/benchmark" code actions for the selection.
+func getGoTestCodeActions(pkg *cache.Package, pgf *ParsedGoFile, rng protocol.Range) ([]protocol.CodeAction, error) {
+	fns, err := TestsAndBenchmarks(pkg, pgf)
+	if err != nil {
+		return nil, err
+	}
+
+	var tests, benchmarks []string
+	for _, fn := range fns.Tests {
+		if !protocol.Intersect(fn.Rng, rng) {
+			continue
+		}
+		tests = append(tests, fn.Name)
+	}
+	for _, fn := range fns.Benchmarks {
+		if !protocol.Intersect(fn.Rng, rng) {
+			continue
+		}
+		benchmarks = append(benchmarks, fn.Name)
+	}
+
+	if len(tests) == 0 && len(benchmarks) == 0 {
+		return nil, nil
+	}
+
+	cmd, err := command.NewTestCommand("Run tests and benchmarks", pgf.URI, tests, benchmarks)
+	if err != nil {
+		return nil, err
+	}
+	return []protocol.CodeAction{{
+		Title:   cmd.Title,
+		Kind:    protocol.GoTest,
+		Command: &cmd,
+	}}, nil
+}
+
+func documentChanges(fh file.Handle, edits []protocol.TextEdit) []protocol.DocumentChanges {
+	return protocol.TextEditsToDocumentChanges(fh.URI(), fh.Version(), edits)
+}
diff --git a/gopls/internal/lsp/source/comment.go b/gopls/internal/golang/comment.go
similarity index 99%
rename from gopls/internal/lsp/source/comment.go
rename to gopls/internal/golang/comment.go
index 578399e..ece1238 100644
--- a/gopls/internal/lsp/source/comment.go
+++ b/gopls/internal/golang/comment.go
@@ -5,7 +5,7 @@
 //go:build !go1.19
 // +build !go1.19
 
-package source
+package golang
 
 import (
 	"bytes"
diff --git a/gopls/internal/lsp/source/comment_go118_test.go b/gopls/internal/golang/comment_go118_test.go
similarity index 99%
rename from gopls/internal/lsp/source/comment_go118_test.go
rename to gopls/internal/golang/comment_go118_test.go
index 60bd14b..c38898a 100644
--- a/gopls/internal/lsp/source/comment_go118_test.go
+++ b/gopls/internal/golang/comment_go118_test.go
@@ -5,7 +5,7 @@
 //go:build !go1.19
 // +build !go1.19
 
-package source
+package golang
 
 import (
 	"bytes"
diff --git a/gopls/internal/lsp/source/comment_go119.go b/gopls/internal/golang/comment_go119.go
similarity index 82%
rename from gopls/internal/lsp/source/comment_go119.go
rename to gopls/internal/golang/comment_go119.go
index d36d110..eec338d 100644
--- a/gopls/internal/lsp/source/comment_go119.go
+++ b/gopls/internal/golang/comment_go119.go
@@ -5,17 +5,13 @@
 //go:build go1.19
 // +build go1.19
 
-package source
+package golang
 
 // Starting with go1.19, the formatting of comments has changed, and there
 // is a new package (go/doc/comment) for processing them.
 // As long as gopls has to compile under earlier versions, tests
 // have to pass with both the old and new code, which produce
-// slightly different results. (cmd/test/definition.go, source/comment_test.go,
-// and source/source_test.go) Each of the test files checks the results
-// with a function, tests.CheckSameMarkdown, that accepts both the old and the new
-// results. (The old code escapes many characters the new code does not,
-// and the new code sometimes adds a blank line.)
+// slightly different results.
 
 // When gopls no longer needs to compile with go1.18, the old comment.go should
 // be replaced by this file, the golden test files should be updated.
diff --git a/gopls/internal/lsp/source/completion/builtin.go b/gopls/internal/golang/completion/builtin.go
similarity index 100%
rename from gopls/internal/lsp/source/completion/builtin.go
rename to gopls/internal/golang/completion/builtin.go
diff --git a/gopls/internal/lsp/source/completion/completion.go b/gopls/internal/golang/completion/completion.go
similarity index 97%
rename from gopls/internal/lsp/source/completion/completion.go
rename to gopls/internal/golang/completion/completion.go
index d241cbd..b796de4 100644
--- a/gopls/internal/lsp/source/completion/completion.go
+++ b/gopls/internal/golang/completion/completion.go
@@ -27,15 +27,16 @@
 
 	"golang.org/x/sync/errgroup"
 	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
-	"golang.org/x/tools/gopls/internal/lsp/source/completion/snippet"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/golang/completion/snippet"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	goplsastutil "golang.org/x/tools/gopls/internal/util/astutil"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
+	"golang.org/x/tools/gopls/internal/util/typesutil"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/fuzzy"
 	"golang.org/x/tools/internal/imports"
@@ -172,7 +173,7 @@
 	snapshot *cache.Snapshot
 	pkg      *cache.Package
 	qf       types.Qualifier          // for qualifying typed expressions
-	mq       source.MetadataQualifier // for syntactic qualifying
+	mq       golang.MetadataQualifier // for syntactic qualifying
 	opts     *completionOptions
 
 	// completionContext contains information about the trigger for this
@@ -376,6 +377,7 @@
 type candidate struct {
 	// obj is the types.Object to complete to.
 	// TODO(adonovan): eliminate dependence on go/types throughout this struct.
+	// See comment in (*completer).selector for explanation.
 	obj types.Object
 
 	// score is used to rank candidates.
@@ -451,7 +453,7 @@
 
 	startTime := time.Now()
 
-	pkg, pgf, err := source.NarrowestPackageForFile(ctx, snapshot, fh.URI())
+	pkg, pgf, err := golang.NarrowestPackageForFile(ctx, snapshot, fh.URI())
 	if err != nil || pgf.File.Package == token.NoPos {
 		// If we can't parse this file or find position for the package
 		// keyword, it may be missing a package declaration. Try offering
@@ -520,15 +522,15 @@
 	}
 
 	// Collect all surrounding scopes, innermost first.
-	scopes := source.CollectScopes(pkg.GetTypesInfo(), path, pos)
+	scopes := golang.CollectScopes(pkg.GetTypesInfo(), path, pos)
 	scopes = append(scopes, pkg.GetTypes().Scope(), types.Universe)
 
 	opts := snapshot.Options()
 	c := &completer{
 		pkg:      pkg,
 		snapshot: snapshot,
-		qf:       source.Qualifier(pgf.File, pkg.GetTypes(), pkg.GetTypesInfo()),
-		mq:       source.MetadataQualifierForFile(snapshot, pgf.File, pkg.Metadata()),
+		qf:       typesutil.FileQualifier(pgf.File, pkg.GetTypes(), pkg.GetTypesInfo()),
+		mq:       golang.MetadataQualifierForFile(snapshot, pgf.File, pkg.Metadata()),
 		completionContext: completionContext{
 			triggerCharacter: protoContext.TriggerCharacter,
 			triggerKind:      protoContext.TriggerKind,
@@ -645,7 +647,7 @@
 	// Inside comments, offer completions for the name of the relevant symbol.
 	for _, comment := range c.file.Comments {
 		if comment.Pos() < c.pos && c.pos <= comment.End() {
-			c.populateCommentCompletions(ctx, comment)
+			c.populateCommentCompletions(comment)
 			return nil
 		}
 	}
@@ -920,7 +922,7 @@
 }
 
 // populateCommentCompletions yields completions for comments preceding or in declarations.
-func (c *completer) populateCommentCompletions(ctx context.Context, comment *ast.CommentGroup) {
+func (c *completer) populateCommentCompletions(comment *ast.CommentGroup) {
 	// If the completion was triggered by a period, ignore it. These types of
 	// completions will not be useful in comments.
 	if c.completionContext.triggerCharacter == "." {
@@ -972,12 +974,12 @@
 					// add TypeSpec fields to completion
 					switch typeNode := spec.Type.(type) {
 					case *ast.StructType:
-						c.addFieldItems(ctx, typeNode.Fields)
+						c.addFieldItems(typeNode.Fields)
 					case *ast.FuncType:
-						c.addFieldItems(ctx, typeNode.Params)
-						c.addFieldItems(ctx, typeNode.Results)
+						c.addFieldItems(typeNode.Params)
+						c.addFieldItems(typeNode.Results)
 					case *ast.InterfaceType:
-						c.addFieldItems(ctx, typeNode.Methods)
+						c.addFieldItems(typeNode.Methods)
 					}
 
 					if spec.Name.String() == "_" {
@@ -998,9 +1000,9 @@
 			}
 		// handle functions
 		case *ast.FuncDecl:
-			c.addFieldItems(ctx, node.Recv)
-			c.addFieldItems(ctx, node.Type.Params)
-			c.addFieldItems(ctx, node.Type.Results)
+			c.addFieldItems(node.Recv)
+			c.addFieldItems(node.Type.Params)
+			c.addFieldItems(node.Type.Results)
 
 			// collect receiver struct fields
 			if node.Recv != nil {
@@ -1084,7 +1086,7 @@
 }
 
 // adds struct fields, interface methods, function declaration fields to completion
-func (c *completer) addFieldItems(ctx context.Context, fields *ast.FieldList) {
+func (c *completer) addFieldItems(fields *ast.FieldList) {
 	if fields == nil {
 		return
 	}
@@ -1156,7 +1158,7 @@
 		imp := pkgName.Imported()
 
 		// Known direct dependency? Expand using type information.
-		if _, ok := c.pkg.Metadata().DepsByPkgPath[source.PackagePath(imp.Path())]; ok {
+		if _, ok := c.pkg.Metadata().DepsByPkgPath[golang.PackagePath(imp.Path())]; ok {
 			c.packageMembers(imp, stdScore, nil, c.deepState.enqueue)
 			return nil
 		}
@@ -1208,7 +1210,7 @@
 	if err != nil {
 		return err
 	}
-	known := make(map[source.PackagePath]*metadata.Package)
+	known := make(map[golang.PackagePath]*metadata.Package)
 	for _, mp := range all {
 		if mp.Name == "main" {
 			continue // not importable
@@ -1346,6 +1348,11 @@
 					return params
 				}
 
+				// Ideally we would eliminate the suffix of type
+				// parameters that are redundant with inference
+				// from the argument types (#51783), but it's
+				// quite fiddly to do using syntax alone.
+				// (See inferableTypeParams in format.go.)
 				tparams := paramList(fn.Type.TypeParams)
 				params := paramList(fn.Type.Params)
 				var sn snippet.Builder
@@ -1366,7 +1373,7 @@
 	// Extract the package-level candidates using a quick parse.
 	var g errgroup.Group
 	for _, path := range paths {
-		mp := known[source.PackagePath(path)]
+		mp := known[golang.PackagePath(path)]
 		for _, uri := range mp.CompiledGoFiles {
 			uri := uri
 			g.Go(func() error {
@@ -1389,7 +1396,7 @@
 		mu.Lock()
 		defer mu.Unlock()
 		// TODO(adonovan): what if the actual package has a vendor/ prefix?
-		if _, ok := known[source.PackagePath(pkgExport.Fix.StmtInfo.ImportPath)]; ok {
+		if _, ok := known[golang.PackagePath(pkgExport.Fix.StmtInfo.ImportPath)]; ok {
 			return // We got this one above.
 		}
 
@@ -1459,7 +1466,7 @@
 
 	if isStarTestingDotF(typ) && addressable {
 		// is that a sufficient test? (or is more care needed?)
-		if c.fuzz(typ, mset, imp, cb, c.pkg.FileSet()) {
+		if c.fuzz(mset, imp, cb) {
 			return
 		}
 	}
@@ -1578,7 +1585,7 @@
 	}
 
 	if c.inference.objType != nil {
-		if named, _ := source.Deref(c.inference.objType).(*types.Named); named != nil {
+		if named, _ := golang.Deref(c.inference.objType).(*types.Named); named != nil {
 			// If we expected a named type, check the type's package for
 			// completion items. This is useful when the current file hasn't
 			// imported the type's package yet.
@@ -1589,7 +1596,7 @@
 				// Make sure the package name isn't already in use by another
 				// object, and that this file doesn't import the package yet.
 				// TODO(adonovan): what if pkg.Path has vendor/ prefix?
-				if _, ok := seen[pkg.Name()]; !ok && pkg != c.pkg.GetTypes() && !alreadyImports(c.file, source.ImportPath(pkg.Path())) {
+				if _, ok := seen[pkg.Name()]; !ok && pkg != c.pkg.GetTypes() && !alreadyImports(c.file, golang.ImportPath(pkg.Path())) {
 					seen[pkg.Name()] = struct{}{}
 					obj := types.NewPkgName(0, nil, pkg.Name(), pkg)
 					imp := &importInfo{
@@ -1644,7 +1651,7 @@
 		return
 	}
 
-	t = source.Deref(t)
+	t = golang.Deref(t)
 
 	// If we have an expected type and it is _not_ a named type, handle
 	// it specially. Non-named types like "[]int" will never be
@@ -1692,7 +1699,7 @@
 	if err != nil {
 		return err
 	}
-	pkgNameByPath := make(map[source.PackagePath]string)
+	pkgNameByPath := make(map[golang.PackagePath]string)
 	var paths []string // actually PackagePaths
 	for _, mp := range all {
 		if mp.ForTest != "" {
@@ -1730,7 +1737,7 @@
 	})
 
 	for _, path := range paths {
-		name := pkgNameByPath[source.PackagePath(path)]
+		name := pkgNameByPath[golang.PackagePath(path)]
 		if _, ok := seen[name]; ok {
 			continue
 		}
@@ -1752,8 +1759,6 @@
 		count++
 	}
 
-	ctx, cancel := context.WithCancel(ctx)
-
 	var mu sync.Mutex
 	add := func(pkg imports.ImportFix) {
 		if ignoreUnimportedCompletion(&pkg) {
@@ -1769,7 +1774,6 @@
 		}
 
 		if count >= maxUnimportedPackageNames {
-			cancel()
 			return
 		}
 
@@ -1787,15 +1791,16 @@
 		})
 		count++
 	}
+
 	c.completionCallbacks = append(c.completionCallbacks, func(ctx context.Context, opts *imports.Options) error {
-		defer cancel()
 		return imports.GetAllCandidates(ctx, add, prefix, c.filename, c.pkg.GetTypes().Name(), opts.Env)
 	})
+
 	return nil
 }
 
 // alreadyImports reports whether f has an import with the specified path.
-func alreadyImports(f *ast.File, path source.ImportPath) bool {
+func alreadyImports(f *ast.File, path golang.ImportPath) bool {
 	for _, s := range f.Imports {
 		if metadata.UnquoteImportPath(s) == path {
 			return true
@@ -1891,7 +1896,7 @@
 
 			clInfo := compLitInfo{
 				cl:     n,
-				clType: source.Deref(tv.Type).Underlying(),
+				clType: golang.Deref(tv.Type).Underlying(),
 			}
 
 			var (
diff --git a/gopls/internal/lsp/source/completion/deep_completion.go b/gopls/internal/golang/completion/deep_completion.go
similarity index 100%
rename from gopls/internal/lsp/source/completion/deep_completion.go
rename to gopls/internal/golang/completion/deep_completion.go
diff --git a/gopls/internal/lsp/source/completion/deep_completion_test.go b/gopls/internal/golang/completion/deep_completion_test.go
similarity index 100%
rename from gopls/internal/lsp/source/completion/deep_completion_test.go
rename to gopls/internal/golang/completion/deep_completion_test.go
diff --git a/gopls/internal/lsp/source/completion/definition.go b/gopls/internal/golang/completion/definition.go
similarity index 94%
rename from gopls/internal/lsp/source/completion/definition.go
rename to gopls/internal/golang/completion/definition.go
index e4c1841..1e3852b 100644
--- a/gopls/internal/lsp/source/completion/definition.go
+++ b/gopls/internal/golang/completion/definition.go
@@ -11,9 +11,9 @@
 	"unicode"
 	"unicode/utf8"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
-	"golang.org/x/tools/gopls/internal/lsp/source/completion/snippet"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/golang/completion/snippet"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // some function definitions in test files can be completed
@@ -21,7 +21,7 @@
 // BenchmarkFoo(b *testing.B), FuzzFoo(f *testing.F)
 
 // path[0] is known to be *ast.Ident
-func definition(path []ast.Node, obj types.Object, pgf *source.ParsedGoFile) ([]CompletionItem, *Selection) {
+func definition(path []ast.Node, obj types.Object, pgf *golang.ParsedGoFile) ([]CompletionItem, *Selection) {
 	if _, ok := obj.(*types.Func); !ok {
 		return nil, nil // not a function at all
 	}
diff --git a/gopls/internal/lsp/source/completion/format.go b/gopls/internal/golang/completion/format.go
similarity index 74%
rename from gopls/internal/lsp/source/completion/format.go
rename to gopls/internal/golang/completion/format.go
index 0d47161..e533860 100644
--- a/gopls/internal/lsp/source/completion/format.go
+++ b/gopls/internal/golang/completion/format.go
@@ -13,9 +13,9 @@
 	"go/types"
 	"strings"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
-	"golang.org/x/tools/gopls/internal/lsp/source/completion/snippet"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/golang/completion/snippet"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/imports"
@@ -62,7 +62,7 @@
 		x := cand.obj.(*types.TypeName)
 		if named, ok := x.Type().(*types.Named); ok {
 			tp := named.TypeParams()
-			label += source.FormatTypeParams(tp)
+			label += golang.FormatTypeParams(tp)
 			insert = label // maintain invariant above (label == insert)
 		}
 	}
@@ -71,7 +71,7 @@
 
 	switch obj := obj.(type) {
 	case *types.TypeName:
-		detail, kind = source.FormatType(obj.Type(), c.qf)
+		detail, kind = golang.FormatType(obj.Type(), c.qf)
 	case *types.Const:
 		kind = protocol.ConstantCompletion
 	case *types.Var:
@@ -79,7 +79,7 @@
 			detail = "struct{...}" // for anonymous structs
 		} else if obj.IsField() {
 			var err error
-			detail, err = source.FormatVarType(ctx, c.snapshot, c.pkg, obj, c.qf, c.mq)
+			detail, err = golang.FormatVarType(ctx, c.snapshot, c.pkg, obj, c.qf, c.mq)
 			if err != nil {
 				return CompletionItem{}, err
 			}
@@ -131,11 +131,31 @@
 		switch mod {
 		case invoke:
 			if sig, ok := funcType.Underlying().(*types.Signature); ok {
-				s, err := source.NewSignature(ctx, c.snapshot, c.pkg, sig, nil, c.qf, c.mq)
+				s, err := golang.NewSignature(ctx, c.snapshot, c.pkg, sig, nil, c.qf, c.mq)
 				if err != nil {
 					return CompletionItem{}, err
 				}
-				c.functionCallSnippet("", s.TypeParams(), s.Params(), &snip)
+
+				tparams := s.TypeParams()
+				if len(tparams) > 0 {
+					// Eliminate the suffix of type parameters that are
+					// likely redundant because they can probably be
+					// inferred from the argument types (#51783).
+					//
+					// We don't bother doing the reverse inference from
+					// result types as result-only type parameters are
+					// quite unusual.
+					free := inferableTypeParams(sig)
+					for i := sig.TypeParams().Len() - 1; i >= 0; i-- {
+						tparam := sig.TypeParams().At(i)
+						if !free[tparam] {
+							break
+						}
+						tparams = tparams[:i] // eliminate
+					}
+				}
+
+				c.functionCallSnippet("", tparams, s.Params(), &snip)
 				if sig.Results().Len() == 1 {
 					funcType = sig.Results().At(0).Type()
 				}
@@ -247,7 +267,7 @@
 		return item, nil
 	}
 
-	comment, err := source.HoverDocForObject(ctx, c.snapshot, c.pkg.FileSet(), obj)
+	comment, err := golang.HoverDocForObject(ctx, c.snapshot, c.pkg.FileSet(), obj)
 	if err != nil {
 		event.Error(ctx, fmt.Sprintf("failed to find Hover for %q", obj.Name()), err)
 		return item, nil
@@ -282,7 +302,7 @@
 		return nil, err
 	}
 
-	return source.ComputeOneImportFixEdits(c.snapshot, pgf, &imports.ImportFix{
+	return golang.ComputeOneImportFixEdits(c.snapshot, pgf, &imports.ImportFix{
 		StmtInfo: imports.ImportInfo{
 			ImportPath: imp.importPath,
 			Name:       imp.name,
@@ -304,12 +324,13 @@
 		item.Kind = protocol.ConstantCompletion
 	case *types.Builtin:
 		item.Kind = protocol.FunctionCompletion
-		sig, err := source.NewBuiltinSignature(ctx, c.snapshot, obj.Name())
+		sig, err := golang.NewBuiltinSignature(ctx, c.snapshot, obj.Name())
 		if err != nil {
 			return CompletionItem{}, err
 		}
 		item.Detail = "func" + sig.Format()
 		item.snippet = &snippet.Builder{}
+		// The signature inferred for a built-in is instantiated, so TypeParams=∅.
 		c.functionCallSnippet(obj.Name(), sig.TypeParams(), sig.Params(), item.snippet)
 	case *types.TypeName:
 		if types.IsInterface(obj.Type()) {
@@ -341,3 +362,78 @@
 	}
 	return false
 }
+
+// inferableTypeParams returns the set of type parameters
+// of sig that are constrained by (inferred from) the argument types.
+func inferableTypeParams(sig *types.Signature) map[*types.TypeParam]bool {
+	free := make(map[*types.TypeParam]bool)
+
+	// visit adds to free all the free type parameters of t.
+	var visit func(t types.Type)
+	visit = func(t types.Type) {
+		switch t := t.(type) {
+		case *types.Array:
+			visit(t.Elem())
+		case *types.Chan:
+			visit(t.Elem())
+		case *types.Map:
+			visit(t.Key())
+			visit(t.Elem())
+		case *types.Pointer:
+			visit(t.Elem())
+		case *types.Slice:
+			visit(t.Elem())
+		case *types.Interface:
+			for i := 0; i < t.NumExplicitMethods(); i++ {
+				visit(t.ExplicitMethod(i).Type())
+			}
+			for i := 0; i < t.NumEmbeddeds(); i++ {
+				visit(t.EmbeddedType(i))
+			}
+		case *types.Union:
+			for i := 0; i < t.Len(); i++ {
+				visit(t.Term(i).Type())
+			}
+		case *types.Signature:
+			if tp := t.TypeParams(); tp != nil {
+				// Generic signatures only appear as the type of generic
+				// function declarations, so this isn't really reachable.
+				for i := 0; i < tp.Len(); i++ {
+					visit(tp.At(i).Constraint())
+				}
+			}
+			visit(t.Params())
+			visit(t.Results())
+		case *types.Tuple:
+			for i := 0; i < t.Len(); i++ {
+				visit(t.At(i).Type())
+			}
+		case *types.Struct:
+			for i := 0; i < t.NumFields(); i++ {
+				visit(t.Field(i).Type())
+			}
+		case *types.TypeParam:
+			free[t] = true
+		case *types.Basic, *types.Named:
+			// nop
+		default:
+			panic(t)
+		}
+	}
+
+	visit(sig.Params())
+
+	// Perform induction through constraints.
+restart:
+	for i := 0; i < sig.TypeParams().Len(); i++ {
+		tp := sig.TypeParams().At(i)
+		if free[tp] {
+			n := len(free)
+			visit(tp.Constraint())
+			if len(free) > n {
+				goto restart // iterate until fixed point
+			}
+		}
+	}
+	return free
+}
diff --git a/gopls/internal/lsp/source/completion/fuzz.go b/gopls/internal/golang/completion/fuzz.go
similarity index 94%
rename from gopls/internal/lsp/source/completion/fuzz.go
rename to gopls/internal/golang/completion/fuzz.go
index 08e7654..382676a 100644
--- a/gopls/internal/lsp/source/completion/fuzz.go
+++ b/gopls/internal/golang/completion/fuzz.go
@@ -7,11 +7,10 @@
 import (
 	"fmt"
 	"go/ast"
-	"go/token"
 	"go/types"
 	"strings"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // golang/go#51089
@@ -21,7 +20,7 @@
 // PJW: are there other packages where we can deduce usage constraints?
 
 // if we find fuzz completions, then return true, as those are the only completions to offer
-func (c *completer) fuzz(typ types.Type, mset *types.MethodSet, imp *importInfo, cb func(candidate), fset *token.FileSet) bool {
+func (c *completer) fuzz(mset *types.MethodSet, imp *importInfo, cb func(candidate)) bool {
 	// 1. inside f.Fuzz? (only f.Failed and f.Name)
 	// 2. possible completing f.Fuzz?
 	//    [Ident,SelectorExpr,Callexpr,ExprStmt,BlockiStmt,FuncDecl(Fuzz...)]
diff --git a/gopls/internal/lsp/source/completion/keywords.go b/gopls/internal/golang/completion/keywords.go
similarity index 98%
rename from gopls/internal/lsp/source/completion/keywords.go
rename to gopls/internal/golang/completion/keywords.go
index 1dcd584..cad04fd 100644
--- a/gopls/internal/lsp/source/completion/keywords.go
+++ b/gopls/internal/golang/completion/keywords.go
@@ -7,7 +7,7 @@
 import (
 	"go/ast"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/astutil"
 )
 
diff --git a/gopls/internal/lsp/source/completion/labels.go b/gopls/internal/golang/completion/labels.go
similarity index 100%
rename from gopls/internal/lsp/source/completion/labels.go
rename to gopls/internal/golang/completion/labels.go
diff --git a/gopls/internal/lsp/source/completion/literal.go b/gopls/internal/golang/completion/literal.go
similarity index 96%
rename from gopls/internal/lsp/source/completion/literal.go
rename to gopls/internal/golang/completion/literal.go
index b48407b..45f772d 100644
--- a/gopls/internal/lsp/source/completion/literal.go
+++ b/gopls/internal/golang/completion/literal.go
@@ -11,9 +11,9 @@
 	"strings"
 	"unicode"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
-	"golang.org/x/tools/gopls/internal/lsp/source/completion/snippet"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/golang/completion/snippet"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 )
 
@@ -50,7 +50,7 @@
 	// don't offer "mySlice{}" since we have already added a candidate
 	// of "[]int{}".
 	if _, named := literalType.(*types.Named); named && expType != nil {
-		if _, named := source.Deref(expType).(*types.Named); !named {
+		if _, named := golang.Deref(expType).(*types.Named); !named {
 			return
 		}
 	}
@@ -201,9 +201,9 @@
 			// If the param has no name in the signature, guess a name based
 			// on the type. Use an empty qualifier to ignore the package.
 			// For example, we want to name "http.Request" "r", not "hr".
-			typeName, err := source.FormatVarType(ctx, c.snapshot, c.pkg, p,
+			typeName, err := golang.FormatVarType(ctx, c.snapshot, c.pkg, p,
 				func(p *types.Package) string { return "" },
-				func(source.PackageName, source.ImportPath, source.PackagePath) string { return "" })
+				func(golang.PackageName, golang.ImportPath, golang.PackagePath) string { return "" })
 			if err != nil {
 				// In general, the only error we should encounter while formatting is
 				// context cancellation.
@@ -271,7 +271,7 @@
 		// of "i int, j int".
 		if i == sig.Params().Len()-1 || !types.Identical(p.Type(), sig.Params().At(i+1).Type()) {
 			snip.WriteText(" ")
-			typeStr, err := source.FormatVarType(ctx, c.snapshot, c.pkg, p, c.qf, c.mq)
+			typeStr, err := golang.FormatVarType(ctx, c.snapshot, c.pkg, p, c.qf, c.mq)
 			if err != nil {
 				// In general, the only error we should encounter while formatting is
 				// context cancellation.
@@ -329,7 +329,7 @@
 			snip.WriteText(name + " ")
 		}
 
-		text, err := source.FormatVarType(ctx, c.snapshot, c.pkg, r, c.qf, c.mq)
+		text, err := golang.FormatVarType(ctx, c.snapshot, c.pkg, r, c.qf, c.mq)
 		if err != nil {
 			// In general, the only error we should encounter while formatting is
 			// context cancellation.
diff --git a/gopls/internal/lsp/source/completion/package.go b/gopls/internal/golang/completion/package.go
similarity index 95%
rename from gopls/internal/lsp/source/completion/package.go
rename to gopls/internal/golang/completion/package.go
index 084191f..709d65c 100644
--- a/gopls/internal/lsp/source/completion/package.go
+++ b/gopls/internal/golang/completion/package.go
@@ -18,10 +18,10 @@
 	"strings"
 	"unicode"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/fuzzy"
 )
@@ -32,7 +32,7 @@
 	// We know that the AST for this file will be empty due to the missing
 	// package declaration, but parse it anyway to get a mapper.
 	// TODO(adonovan): opt: there's no need to parse just to get a mapper.
-	pgf, err := snapshot.ParseGo(ctx, fh, source.ParseFull)
+	pgf, err := snapshot.ParseGo(ctx, fh, golang.ParseFull)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -68,7 +68,7 @@
 // packageCompletionSurrounding returns surrounding for package completion if a
 // package completions can be suggested at a given cursor offset. A valid location
 // for package completion is above any declarations or import statements.
-func packageCompletionSurrounding(pgf *source.ParsedGoFile, offset int) (*Selection, error) {
+func packageCompletionSurrounding(pgf *golang.ParsedGoFile, offset int) (*Selection, error) {
 	m := pgf.Mapper
 	// If the file lacks a package declaration, the parser will return an empty
 	// AST. As a work-around, try to parse an expression from the file contents.
@@ -230,7 +230,7 @@
 	}
 	pkgName := convertDirNameToPkgName(dirName)
 
-	seenPkgs := make(map[source.PackageName]struct{})
+	seenPkgs := make(map[golang.PackageName]struct{})
 
 	// The `go` command by default only allows one package per directory but we
 	// support multiple package suggestions since gopls is build system agnostic.
@@ -320,7 +320,7 @@
 
 // convertDirNameToPkgName converts a valid directory name to a valid package name.
 // It leaves only letters and digits. All letters are mapped to lower case.
-func convertDirNameToPkgName(dirName string) source.PackageName {
+func convertDirNameToPkgName(dirName string) golang.PackageName {
 	var buf bytes.Buffer
 	for _, ch := range dirName {
 		switch {
@@ -331,7 +331,7 @@
 			buf.WriteRune(ch)
 		}
 	}
-	return source.PackageName(buf.String())
+	return golang.PackageName(buf.String())
 }
 
 // isLetter and isDigit allow only ASCII characters because
diff --git a/gopls/internal/lsp/source/completion/package_test.go b/gopls/internal/golang/completion/package_test.go
similarity index 96%
rename from gopls/internal/lsp/source/completion/package_test.go
rename to gopls/internal/golang/completion/package_test.go
index 614359f..dc4058f 100644
--- a/gopls/internal/lsp/source/completion/package_test.go
+++ b/gopls/internal/golang/completion/package_test.go
@@ -7,7 +7,7 @@
 import (
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
 )
 
 func TestIsValidDirName(t *testing.T) {
@@ -55,7 +55,7 @@
 func TestConvertDirNameToPkgName(t *testing.T) {
 	tests := []struct {
 		dirName string
-		pkgName source.PackageName
+		pkgName golang.PackageName
 	}{
 		{dirName: "a", pkgName: "a"},
 		{dirName: "abcdef", pkgName: "abcdef"},
diff --git a/gopls/internal/lsp/source/completion/postfix_snippets.go b/gopls/internal/golang/completion/postfix_snippets.go
similarity index 73%
rename from gopls/internal/lsp/source/completion/postfix_snippets.go
rename to gopls/internal/golang/completion/postfix_snippets.go
index 1661709..252d2e7 100644
--- a/gopls/internal/lsp/source/completion/postfix_snippets.go
+++ b/gopls/internal/golang/completion/postfix_snippets.go
@@ -16,10 +16,10 @@
 	"sync"
 	"text/template"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
-	"golang.org/x/tools/gopls/internal/lsp/source/completion/snippet"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/golang/completion/snippet"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/imports"
@@ -68,6 +68,10 @@
 	// Type is the type of "foo.bar" in "foo.bar.print!".
 	Type types.Type
 
+	// FuncResult are results of the enclosed function
+	FuncResults []*types.Var
+
+	sel            *ast.SelectorExpr
 	scope          *types.Scope
 	snip           snippet.Builder
 	importIfNeeded func(pkgPath string, scope *types.Scope) (name string, edits []protocol.TextEdit, err error)
@@ -75,6 +79,7 @@
 	qf             types.Qualifier
 	varNames       map[string]bool
 	placeholders   bool
+	currentTabStop int
 }
 
 var postfixTmpls = []postfixTmpl{{
@@ -250,26 +255,119 @@
 	body: `{{if (eq .Kind "slice" "map" "array" "chan") -}}
 len({{.X}})
 {{- end}}`,
+}, {
+	label:   "iferr",
+	details: "check error and return",
+	body: `{{if and .StmtOK (eq (.TypeName .Type) "error") -}}
+{{- $errName := (or (and .IsIdent .X) "err") -}}
+if {{if not .IsIdent}}err := {{.X}}; {{end}}{{$errName}} != nil {
+	return {{$a := .}}{{range $i, $v := .FuncResults}}
+		{{- if $i}}, {{end -}}
+		{{- if eq ($a.TypeName $v.Type) "error" -}}
+			{{$a.Placeholder $errName}}
+		{{- else -}}
+			{{$a.Zero $v.Type}}
+		{{- end -}}
+	{{end}}
+}
+{{end}}`,
+}, {
+	label:   "iferr",
+	details: "check error and return",
+	body: `{{if and .StmtOK (eq .Kind "tuple") (len .Tuple) (eq (.TypeName .TupleLast.Type) "error") -}}
+{{- $a := . -}}
+if {{range $i, $v := .Tuple}}{{if $i}}, {{end}}{{if and (eq ($a.TypeName $v.Type) "error") (eq (inc $i) (len $a.Tuple))}}err{{else}}_{{end}}{{end}} := {{.X -}}
+; err != nil {
+	return {{range $i, $v := .FuncResults}}
+		{{- if $i}}, {{end -}}
+		{{- if eq ($a.TypeName $v.Type) "error" -}}
+			{{$a.Placeholder "err"}}
+		{{- else -}}
+			{{$a.Zero $v.Type}}
+		{{- end -}}
+	{{end}}
+}
+{{end}}`,
+}, {
+	// variferr snippets use nested placeholders, as described in
+	// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#snippet_syntax,
+	// so that users can wrap the returned error without modifying the error
+	// variable name.
+	label:   "variferr",
+	details: "assign variables and check error",
+	body: `{{if and .StmtOK (eq .Kind "tuple") (len .Tuple) (eq (.TypeName .TupleLast.Type) "error") -}}
+{{- $a := . -}}
+{{- $errName := "err" -}}
+{{- range $i, $v := .Tuple -}}
+	{{- if $i}}, {{end -}}
+	{{- if and (eq ($a.TypeName $v.Type) "error") (eq (inc $i) (len $a.Tuple)) -}}
+		{{$errName | $a.SpecifiedPlaceholder (len $a.Tuple)}}
+	{{- else -}}
+		{{$a.VarName $v.Type $v.Name | $a.Placeholder}}
+	{{- end -}}
+{{- end}} := {{.X}}
+if {{$errName | $a.SpecifiedPlaceholder (len $a.Tuple)}} != nil {
+	return {{range $i, $v := .FuncResults}}
+		{{- if $i}}, {{end -}}
+		{{- if eq ($a.TypeName $v.Type) "error" -}}
+			{{$errName | $a.SpecifiedPlaceholder (len $a.Tuple) |
+				$a.SpecifiedPlaceholder (inc (len $a.Tuple))}}
+		{{- else -}}
+			{{$a.Zero $v.Type}}
+		{{- end -}}
+	{{end}}
+}
+{{end}}`,
+}, {
+	label:   "variferr",
+	details: "assign variables and check error",
+	body: `{{if and .StmtOK (eq (.TypeName .Type) "error") -}}
+{{- $a := . -}}
+{{- $errName := .VarName nil "err" -}}
+{{$errName | $a.SpecifiedPlaceholder 1}} := {{.X}}
+if {{$errName | $a.SpecifiedPlaceholder 1}} != nil {
+	return {{range $i, $v := .FuncResults}}
+		{{- if $i}}, {{end -}}
+		{{- if eq ($a.TypeName $v.Type) "error" -}}
+			{{$errName | $a.SpecifiedPlaceholder 1 | $a.SpecifiedPlaceholder 2}}
+		{{- else -}}
+			{{$a.Zero $v.Type}}
+		{{- end -}}
+	{{end}}
+}
+{{end}}`,
 }}
 
 // Cursor indicates where the client's cursor should end up after the
 // snippet is done.
 func (a *postfixTmplArgs) Cursor() string {
-	a.snip.WriteFinalTabstop()
-	return ""
+	return "$0"
 }
 
-// Placeholder indicate a tab stops with the placeholder string, the order
+// Placeholder indicate a tab stop with the placeholder string, the order
 // of tab stops is the same as the order of invocation
-func (a *postfixTmplArgs) Placeholder(s string) string {
-	if a.placeholders {
-		a.snip.WritePlaceholder(func(b *snippet.Builder) {
-			b.WriteText(s)
-		})
-	} else {
-		a.snip.WritePlaceholder(nil)
+func (a *postfixTmplArgs) Placeholder(placeholder string) string {
+	if !a.placeholders {
+		placeholder = ""
 	}
-	return ""
+	return fmt.Sprintf("${%d:%s}", a.nextTabStop(), placeholder)
+}
+
+// nextTabStop returns the next tab stop index for a new placeholder.
+func (a *postfixTmplArgs) nextTabStop() int {
+	// Tab stops start from 1, so increment before returning.
+	a.currentTabStop++
+	return a.currentTabStop
+}
+
+// SpecifiedPlaceholder indicate a specified tab stop with the placeholder string.
+// Sometimes the same tab stop appears in multiple places and their numbers
+// need to be specified. e.g. variferr
+func (a *postfixTmplArgs) SpecifiedPlaceholder(tabStop int, placeholder string) string {
+	if !a.placeholders {
+		placeholder = ""
+	}
+	return fmt.Sprintf("${%d:%s}", tabStop, placeholder)
 }
 
 // Import makes sure the package corresponding to path is imported,
@@ -309,7 +407,7 @@
 	return a.Type.Underlying().(*types.Map).Key()
 }
 
-// Tuple returns the tuple result vars if X is a call expression.
+// Tuple returns the tuple result vars if the type of X is tuple.
 func (a *postfixTmplArgs) Tuple() []*types.Var {
 	tuple, _ := a.Type.(*types.Tuple)
 	if tuple == nil {
@@ -323,6 +421,18 @@
 	return typs
 }
 
+// TupleLast returns the last tuple result vars if the type of X is tuple.
+func (a *postfixTmplArgs) TupleLast() *types.Var {
+	tuple, _ := a.Type.(*types.Tuple)
+	if tuple == nil {
+		return nil
+	}
+	if tuple.Len() == 0 {
+		return nil
+	}
+	return tuple.At(tuple.Len() - 1)
+}
+
 // TypeName returns the textual representation of type t.
 func (a *postfixTmplArgs) TypeName(t types.Type) (string, error) {
 	if t == nil || t == types.Typ[types.Invalid] {
@@ -331,6 +441,16 @@
 	return types.TypeString(t, a.qf), nil
 }
 
+// Zero return the zero value representation of type t
+func (a *postfixTmplArgs) Zero(t types.Type) string {
+	return formatZeroValue(t, a.qf)
+}
+
+func (a *postfixTmplArgs) IsIdent() bool {
+	_, ok := a.sel.X.(*ast.Ident)
+	return ok
+}
+
 // VarName returns a suitable variable name for the type t. If t
 // implements the error interface, "err" is used. If t is not a named
 // type then nonNamedDefault is used. Otherwise a name is made by
@@ -345,7 +465,7 @@
 	// go/types predicates are undefined on types.Typ[types.Invalid].
 	if !types.Identical(t, types.Typ[types.Invalid]) && types.Implements(t, errorIntf) {
 		name = "err"
-	} else if _, isNamed := source.Deref(t).(*types.Named); !isNamed {
+	} else if _, isNamed := golang.Deref(t).(*types.Named); !isNamed {
 		name = nonNamedDefault
 	}
 
@@ -417,6 +537,17 @@
 		}
 	}
 
+	var funcResults []*types.Var
+	if c.enclosingFunc != nil {
+		results := c.enclosingFunc.sig.Results()
+		if results != nil {
+			funcResults = make([]*types.Var, results.Len())
+			for i := 0; i < results.Len(); i++ {
+				funcResults[i] = results.At(i)
+			}
+		}
+	}
+
 	scope := c.pkg.GetTypes().Scope().Innermost(c.pos)
 	if scope == nil {
 		return
@@ -451,10 +582,12 @@
 		}
 
 		tmplArgs := postfixTmplArgs{
-			X:              source.FormatNode(c.pkg.FileSet(), sel.X),
+			X:              golang.FormatNode(c.pkg.FileSet(), sel.X),
 			StmtOK:         stmtOK,
 			Obj:            exprObj(c.pkg.GetTypesInfo(), sel.X),
 			Type:           selType,
+			FuncResults:    funcResults,
+			sel:            sel,
 			qf:             c.qf,
 			importIfNeeded: c.importIfNeeded,
 			scope:          scope,
@@ -497,7 +630,9 @@
 		var idx int
 		for _, rule := range postfixTmpls {
 			var err error
-			rule.tmpl, err = template.New("postfix_snippet").Parse(rule.body)
+			rule.tmpl, err = template.New("postfix_snippet").Funcs(template.FuncMap{
+				"inc": inc,
+			}).Parse(rule.body)
 			if err != nil {
 				log.Panicf("error parsing postfix snippet template: %v", err)
 			}
@@ -508,6 +643,10 @@
 	})
 }
 
+func inc(i int) int {
+	return i + 1
+}
+
 // importIfNeeded returns the package identifier and any necessary
 // edits to import package pkgPath.
 func (c *completer) importIfNeeded(pkgPath string, scope *types.Scope) (string, []protocol.TextEdit, error) {
diff --git a/gopls/internal/lsp/source/completion/printf.go b/gopls/internal/golang/completion/printf.go
similarity index 100%
rename from gopls/internal/lsp/source/completion/printf.go
rename to gopls/internal/golang/completion/printf.go
diff --git a/gopls/internal/lsp/source/completion/printf_test.go b/gopls/internal/golang/completion/printf_test.go
similarity index 100%
rename from gopls/internal/lsp/source/completion/printf_test.go
rename to gopls/internal/golang/completion/printf_test.go
diff --git a/gopls/internal/lsp/source/completion/snippet.go b/gopls/internal/golang/completion/snippet.go
similarity index 90%
rename from gopls/internal/lsp/source/completion/snippet.go
rename to gopls/internal/golang/completion/snippet.go
index c377362..8df81f8 100644
--- a/gopls/internal/lsp/source/completion/snippet.go
+++ b/gopls/internal/golang/completion/snippet.go
@@ -7,7 +7,7 @@
 import (
 	"go/ast"
 
-	"golang.org/x/tools/gopls/internal/lsp/source/completion/snippet"
+	"golang.org/x/tools/gopls/internal/golang/completion/snippet"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 )
 
@@ -50,6 +50,11 @@
 }
 
 // functionCallSnippet calculates the snippet for function calls.
+//
+// Callers should omit the suffix of type parameters that are
+// constrained by the argument types, to avoid offering completions
+// that contain instantiations that are redundant because of type
+// inference, such as f[int](1) for func f[T any](x T).
 func (c *completer) functionCallSnippet(name string, tparams, params []string, snip *snippet.Builder) {
 	if !c.opts.completeFunctionCalls {
 		snip.WriteText(name)
diff --git a/gopls/internal/lsp/source/completion/snippet/snippet_builder.go b/gopls/internal/golang/completion/snippet/snippet_builder.go
similarity index 100%
rename from gopls/internal/lsp/source/completion/snippet/snippet_builder.go
rename to gopls/internal/golang/completion/snippet/snippet_builder.go
diff --git a/gopls/internal/lsp/source/completion/snippet/snippet_builder_test.go b/gopls/internal/golang/completion/snippet/snippet_builder_test.go
similarity index 100%
rename from gopls/internal/lsp/source/completion/snippet/snippet_builder_test.go
rename to gopls/internal/golang/completion/snippet/snippet_builder_test.go
diff --git a/gopls/internal/lsp/source/completion/statements.go b/gopls/internal/golang/completion/statements.go
similarity index 96%
rename from gopls/internal/lsp/source/completion/statements.go
rename to gopls/internal/golang/completion/statements.go
index 029766d..5a945d6 100644
--- a/gopls/internal/lsp/source/completion/statements.go
+++ b/gopls/internal/golang/completion/statements.go
@@ -11,10 +11,10 @@
 	"go/types"
 	"strings"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
-	"golang.org/x/tools/gopls/internal/lsp/source/completion/snippet"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/golang/completion/snippet"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // addStatementCandidates adds full statement completion candidates
@@ -81,7 +81,7 @@
 		}
 
 		// The name or our slice is whatever's in the LHS expression.
-		sliceText = source.FormatNode(fset, n.Lhs[exprIdx])
+		sliceText = golang.FormatNode(fset, n.Lhs[exprIdx])
 	case *ast.SelectorExpr:
 		// Make sure we are a selector at the beginning of a statement.
 		if _, parentIsExprtStmt := c.path[2].(*ast.ExprStmt); !parentIsExprtStmt {
@@ -91,7 +91,7 @@
 		// So far we only know the first part of our slice name. For
 		// example in "s.a<>" we only know our slice begins with "s."
 		// since the user could still be typing.
-		sliceText = source.FormatNode(fset, n.X) + "."
+		sliceText = golang.FormatNode(fset, n.X) + "."
 		needsLHS = true
 	case *ast.ExprStmt:
 		needsLHS = true
@@ -212,7 +212,7 @@
 
 	var (
 		// errVar is e.g. "err" in "foo, err := bar()".
-		errVar = source.FormatNode(c.pkg.FileSet(), lastAssignee)
+		errVar = golang.FormatNode(c.pkg.FileSet(), lastAssignee)
 
 		// Whether we need to include the "if" keyword in our candidate.
 		needsIf = true
diff --git a/gopls/internal/lsp/source/completion/util.go b/gopls/internal/golang/completion/util.go
similarity index 97%
rename from gopls/internal/lsp/source/completion/util.go
rename to gopls/internal/golang/completion/util.go
index 82c56e0..65d1b4d 100644
--- a/gopls/internal/lsp/source/completion/util.go
+++ b/gopls/internal/golang/completion/util.go
@@ -10,8 +10,8 @@
 	"go/types"
 
 	"golang.org/x/tools/go/types/typeutil"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/diff"
 )
@@ -38,7 +38,7 @@
 
 	var visit func(T types.Type)
 	visit = func(T types.Type) {
-		if T, ok := source.Deref(T).Underlying().(*types.Struct); ok {
+		if T, ok := golang.Deref(T).Underlying().(*types.Struct); ok {
 			if seen.At(T) != nil {
 				return
 			}
@@ -120,7 +120,7 @@
 		}
 	})
 	// Construct a fake type for the object and return a fake object with this type.
-	typename := source.FormatNode(fset, resultExpr)
+	typename := golang.FormatNode(fset, resultExpr)
 	typ := types.NewNamed(types.NewTypeName(token.NoPos, obj.Pkg(), typename, nil), types.Typ[types.Invalid], nil)
 	return types.NewVar(obj.Pos(), obj.Pkg(), obj.Name(), typ)
 }
diff --git a/gopls/internal/lsp/source/completion/util_test.go b/gopls/internal/golang/completion/util_test.go
similarity index 100%
rename from gopls/internal/lsp/source/completion/util_test.go
rename to gopls/internal/golang/completion/util_test.go
diff --git a/gopls/internal/lsp/source/definition.go b/gopls/internal/golang/definition.go
similarity index 93%
rename from gopls/internal/lsp/source/definition.go
rename to gopls/internal/golang/definition.go
index d803874..4cc5229 100644
--- a/gopls/internal/lsp/source/definition.go
+++ b/gopls/internal/golang/definition.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -13,18 +13,18 @@
 	"go/token"
 	"go/types"
 
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/internal/event"
 )
 
 // Definition handles the textDocument/definition request for Go files.
 func Definition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, position protocol.Position) ([]protocol.Location, error) {
-	ctx, done := event.Start(ctx, "source.Definition")
+	ctx, done := event.Start(ctx, "golang.Definition")
 	defer done()
 
 	pkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())
@@ -118,7 +118,9 @@
 		astObj := file.Scope.Lookup(name)
 		if astObj == nil {
 			// Every built-in should have documentation syntax.
-			return nil, bug.Errorf("internal error: no object for %s", name)
+			// However, it is possible to reach this statement by
+			// commenting out declarations in {builtin,unsafe}.go.
+			return nil, fmt.Errorf("internal error: no object for %s", name)
 		}
 		decl, ok := astObj.Decl.(ast.Node)
 		if !ok {
@@ -150,8 +152,10 @@
 		if err != nil {
 			return nil, nil, err
 		}
-
 		decl, err = getDecl(pgf.File, obj.Name())
+		if err != nil {
+			return nil, nil, err
+		}
 	} else {
 		// pseudo-package "builtin":
 		// use parsed $GOROOT/src/builtin/builtin.go
@@ -163,7 +167,9 @@
 		if obj.Parent() == types.Universe {
 			// built-in function or type
 			decl, err = getDecl(pgf.File, obj.Name())
-
+			if err != nil {
+				return nil, nil, err
+			}
 		} else if obj.Name() == "Error" {
 			// error.Error method
 			decl, err = getDecl(pgf.File, "error")
@@ -194,7 +200,7 @@
 // than the var (field) object.
 //
 // TODO(rfindley): this function exists to preserve the pre-existing behavior
-// of source.Identifier. Eliminate this helper in favor of sharing
+// of golang.Identifier. Eliminate this helper in favor of sharing
 // functionality with objectsAt, after choosing suitable primitives.
 func referencedObject(pkg *cache.Package, pgf *ParsedGoFile, pos token.Pos) (*ast.Ident, types.Object, types.Type) {
 	path := pathEnclosingObjNode(pgf.File, pos)
diff --git a/gopls/internal/lsp/source/diagnostics.go b/gopls/internal/golang/diagnostics.go
similarity index 79%
rename from gopls/internal/lsp/source/diagnostics.go
rename to gopls/internal/golang/diagnostics.go
index d2e9332..b0fa8da 100644
--- a/gopls/internal/lsp/source/diagnostics.go
+++ b/gopls/internal/golang/diagnostics.go
@@ -2,14 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/progress"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/progress"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/util/maps"
 )
@@ -18,7 +19,7 @@
 //
 // If the provided tracker is non-nil, it may be used to provide notifications
 // of the ongoing analysis pass.
-func Analyze(ctx context.Context, snapshot *cache.Snapshot, pkgIDs map[PackageID]unit, tracker *progress.Tracker) (map[protocol.DocumentURI][]*cache.Diagnostic, error) {
+func Analyze(ctx context.Context, snapshot *cache.Snapshot, pkgIDs map[PackageID]*metadata.Package, tracker *progress.Tracker) (map[protocol.DocumentURI][]*cache.Diagnostic, error) {
 	// Exit early if the context has been canceled. This also protects us
 	// from a race on Options, see golang/go#36699.
 	if ctx.Err() != nil {
@@ -29,7 +30,6 @@
 	categories := []map[string]*settings.Analyzer{
 		options.DefaultAnalyzers,
 		options.StaticcheckAnalyzers,
-		options.TypeErrorAnalyzers,
 	}
 
 	var analyzers []*settings.Analyzer
diff --git a/gopls/internal/lsp/source/embeddirective.go b/gopls/internal/golang/embeddirective.go
similarity index 98%
rename from gopls/internal/lsp/source/embeddirective.go
rename to gopls/internal/golang/embeddirective.go
index e656378..485da5c 100644
--- a/gopls/internal/lsp/source/embeddirective.go
+++ b/gopls/internal/golang/embeddirective.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"errors"
@@ -14,7 +14,7 @@
 	"unicode"
 	"unicode/utf8"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // ErrNoEmbed is returned by EmbedDefinition when no embed
diff --git a/gopls/internal/lsp/source/extract.go b/gopls/internal/golang/extract.go
similarity index 99%
rename from gopls/internal/lsp/source/extract.go
rename to gopls/internal/golang/extract.go
index 0cc1950..c07faec 100644
--- a/gopls/internal/lsp/source/extract.go
+++ b/gopls/internal/golang/extract.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"bytes"
diff --git a/gopls/internal/lsp/source/fix.go b/gopls/internal/golang/fix.go
similarity index 60%
rename from gopls/internal/lsp/source/fix.go
rename to gopls/internal/golang/fix.go
index 74703cf..6f07cb8 100644
--- a/gopls/internal/lsp/source/fix.go
+++ b/gopls/internal/golang/fix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -12,18 +12,20 @@
 	"go/types"
 
 	"golang.org/x/tools/go/analysis"
+	"golang.org/x/tools/gopls/internal/analysis/embeddirective"
 	"golang.org/x/tools/gopls/internal/analysis/fillstruct"
+	"golang.org/x/tools/gopls/internal/analysis/stubmethods"
 	"golang.org/x/tools/gopls/internal/analysis/undeclaredname"
+	"golang.org/x/tools/gopls/internal/analysis/unusedparams"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/settings"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/internal/imports"
 )
 
-// A Fixer is a function that suggests a fix for a diagnostic produced
+// A fixer is a function that suggests a fix for a diagnostic produced
 // by the analysis framework. This is done outside of the analyzer Run
 // function so that the construction of expensive fixes can be
 // deferred until they are requested by the user.
@@ -37,21 +39,8 @@
 // (SuggestedFix.TextEdits[*].{Pos,End}) must belong to the returned
 // FileSet.
 //
-// A Fixer may return (nil, nil) if no fix is available.
-type Fixer func(ctx context.Context, s *cache.Snapshot, pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error)
-
-// fixers maps each Fix id to its Fixer function.
-var fixers = map[settings.Fix]Fixer{
-	settings.AddEmbedImport:    addEmbedImport,
-	settings.ExtractFunction:   singleFile(extractFunction),
-	settings.ExtractMethod:     singleFile(extractMethod),
-	settings.ExtractVariable:   singleFile(extractVariable),
-	settings.FillStruct:        singleFile(fillstruct.SuggestedFix),
-	settings.InlineCall:        inlineCall,
-	settings.InvertIfCondition: singleFile(invertIfCondition),
-	settings.StubMethods:       stubMethodsFixer,
-	settings.UndeclaredName:    singleFile(undeclaredname.SuggestedFix),
-}
+// A fixer may return (nil, nil) if no fix is available.
+type fixer func(ctx context.Context, s *cache.Snapshot, pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error)
 
 // A singleFileFixer is a Fixer that inspects only a single file,
 // and does not depend on data types from the cache package.
@@ -62,15 +51,71 @@
 type singleFileFixer func(fset *token.FileSet, start, end token.Pos, src []byte, file *ast.File, pkg *types.Package, info *types.Info) (*token.FileSet, *analysis.SuggestedFix, error)
 
 // singleFile adapts a single-file fixer to a Fixer.
-func singleFile(fixer singleFileFixer) Fixer {
+func singleFile(fixer1 singleFileFixer) fixer {
 	return func(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {
-		return fixer(pkg.FileSet(), start, end, pgf.Src, pgf.File, pkg.GetTypes(), pkg.GetTypesInfo())
+		return fixer1(pkg.FileSet(), start, end, pgf.Src, pgf.File, pkg.GetTypes(), pkg.GetTypesInfo())
 	}
 }
 
+// Names of ApplyFix.Fix created directly by the CodeAction handler.
+const (
+	fixExtractVariable   = "extract_variable"
+	fixExtractFunction   = "extract_function"
+	fixExtractMethod     = "extract_method"
+	fixInlineCall        = "inline_call"
+	fixInvertIfCondition = "invert_if_condition"
+)
+
 // ApplyFix applies the specified kind of suggested fix to the given
 // file and range, returning the resulting edits.
-func ApplyFix(ctx context.Context, fix settings.Fix, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.TextDocumentEdit, error) {
+//
+// A fix kind is either the Category of an analysis.Diagnostic that
+// had a SuggestedFix with no edits; or the name of a fix agreed upon
+// by [CodeActions] and this function.
+// Fix kinds identify fixes in the command protocol.
+//
+// TODO(adonovan): come up with a better mechanism for registering the
+// connection between analyzers, code actions, and fixers. A flaw of
+// the current approach is that the same Category could in theory
+// apply to a Diagnostic with several lazy fixes, making them
+// impossible to distinguish. It would more precise if there was a
+// SuggestedFix.Category field, or some other way to squirrel metadata
+// in the fix.
+func ApplyFix(ctx context.Context, fix string, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.TextDocumentEdit, error) {
+	// This can't be expressed as an entry in the fixer table below
+	// because it operates in the protocol (not go/{token,ast}) domain.
+	// (Sigh; perhaps it was a mistake to factor out the
+	// NarrowestPackageForFile/RangePos/suggestedFixToEdits
+	// steps.)
+	if fix == unusedparams.FixCategory {
+		changes, err := RemoveUnusedParameter(ctx, fh, rng, snapshot)
+		if err != nil {
+			return nil, err
+		}
+		// Unwrap TextDocumentEdits again!
+		var edits []protocol.TextDocumentEdit
+		for _, change := range changes {
+			edits = append(edits, *change.TextDocumentEdit)
+		}
+		return edits, nil
+	}
+
+	fixers := map[string]fixer{
+		// Fixes for analyzer-provided diagnostics.
+		// These match the Diagnostic.Category.
+		embeddirective.FixCategory: addEmbedImport,
+		fillstruct.FixCategory:     singleFile(fillstruct.SuggestedFix),
+		stubmethods.FixCategory:    stubMethodsFixer,
+		undeclaredname.FixCategory: singleFile(undeclaredname.SuggestedFix),
+
+		// Ad-hoc fixers: these are used when the command is
+		// constructed directly by logic in server/code_action.
+		fixExtractFunction:   singleFile(extractFunction),
+		fixExtractMethod:     singleFile(extractMethod),
+		fixExtractVariable:   singleFile(extractVariable),
+		fixInlineCall:        inlineCall,
+		fixInvertIfCondition: singleFile(invertIfCondition),
+	}
 	fixer, ok := fixers[fix]
 	if !ok {
 		return nil, fmt.Errorf("no suggested fix function for %s", fix)
@@ -93,7 +138,7 @@
 	return suggestedFixToEdits(ctx, snapshot, fixFset, suggestion)
 }
 
-// suggestedFixToEdits converts the suggestion's edits from analysis form into protocol form,
+// suggestedFixToEdits converts the suggestion's edits from analysis form into protocol form.
 func suggestedFixToEdits(ctx context.Context, snapshot *cache.Snapshot, fset *token.FileSet, suggestion *analysis.SuggestedFix) ([]protocol.TextDocumentEdit, error) {
 	editsPerFile := map[protocol.DocumentURI]*protocol.TextDocumentEdit{}
 	for _, edit := range suggestion.TextEdits {
@@ -146,7 +191,7 @@
 
 // addEmbedImport adds a missing embed "embed" import with blank name.
 func addEmbedImport(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, pgf *parsego.File, _, _ token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {
-	// Like source.AddImport, but with _ as Name and using our pgf.
+	// Like golang.AddImport, but with _ as Name and using our pgf.
 	protoEdits, err := ComputeOneImportFixEdits(snapshot, pgf, &imports.ImportFix{
 		StmtInfo: imports.ImportInfo{
 			ImportPath: "embed",
diff --git a/gopls/internal/lsp/source/folding_range.go b/gopls/internal/golang/folding_range.go
similarity index 98%
rename from gopls/internal/lsp/source/folding_range.go
rename to gopls/internal/golang/folding_range.go
index 130f2fb..c856f0a 100644
--- a/gopls/internal/lsp/source/folding_range.go
+++ b/gopls/internal/golang/folding_range.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -11,9 +11,9 @@
 	"sort"
 	"strings"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 )
diff --git a/gopls/internal/lsp/source/format.go b/gopls/internal/golang/format.go
similarity index 85%
rename from gopls/internal/lsp/source/format.go
rename to gopls/internal/golang/format.go
index 8c46990..2eb2b8b 100644
--- a/gopls/internal/lsp/source/format.go
+++ b/gopls/internal/golang/format.go
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package source provides core features for use by Go editors and tools.
-package source
+// Package golang defines the LSP features for navigation, analysis,
+// and refactoring of Go source code.
+package golang
 
 import (
 	"bytes"
@@ -16,9 +17,9 @@
 	"strings"
 	"text/scanner"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/diff"
 	"golang.org/x/tools/internal/event"
@@ -28,7 +29,7 @@
 
 // Format formats a file with a given range.
 func Format(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.TextEdit, error) {
-	ctx, done := event.Start(ctx, "source.Format")
+	ctx, done := event.Start(ctx, "golang.Format")
 	defer done()
 
 	// Generated files shouldn't be edited. So, don't format them
@@ -48,7 +49,7 @@
 		if err != nil {
 			return nil, err
 		}
-		return computeTextEdits(ctx, snapshot, pgf, string(formatted))
+		return computeTextEdits(ctx, pgf, string(formatted))
 	}
 
 	// format.Node changes slightly from one release to another, so the version
@@ -87,11 +88,11 @@
 		}
 		formatted = string(b)
 	}
-	return computeTextEdits(ctx, snapshot, pgf, formatted)
+	return computeTextEdits(ctx, pgf, formatted)
 }
 
 func formatSource(ctx context.Context, fh file.Handle) ([]byte, error) {
-	_, done := event.Start(ctx, "source.formatSource")
+	_, done := event.Start(ctx, "golang.formatSource")
 	defer done()
 
 	data, err := fh.Content()
@@ -101,21 +102,21 @@
 	return format.Source(data)
 }
 
-type ImportFix struct {
-	Fix   *imports.ImportFix
-	Edits []protocol.TextEdit
+type importFix struct {
+	fix   *imports.ImportFix
+	edits []protocol.TextEdit
 }
 
-// AllImportsFixes formats f for each possible fix to the imports.
+// allImportsFixes formats f for each possible fix to the imports.
 // In addition to returning the result of applying all edits,
 // it returns a list of fixes that could be applied to the file, with the
 // corresponding TextEdits that would be needed to apply that fix.
-func AllImportsFixes(ctx context.Context, snapshot *cache.Snapshot, pgf *ParsedGoFile) (allFixEdits []protocol.TextEdit, editsPerFix []*ImportFix, err error) {
-	ctx, done := event.Start(ctx, "source.AllImportsFixes")
+func allImportsFixes(ctx context.Context, snapshot *cache.Snapshot, pgf *ParsedGoFile) (allFixEdits []protocol.TextEdit, editsPerFix []*importFix, err error) {
+	ctx, done := event.Start(ctx, "golang.AllImportsFixes")
 	defer done()
 
 	if err := snapshot.RunProcessEnvFunc(ctx, func(ctx context.Context, opts *imports.Options) error {
-		allFixEdits, editsPerFix, err = computeImportEdits(ctx, snapshot, pgf, opts)
+		allFixEdits, editsPerFix, err = computeImportEdits(ctx, pgf, opts)
 		return err
 	}); err != nil {
 		return nil, nil, fmt.Errorf("AllImportsFixes: %v", err)
@@ -125,7 +126,7 @@
 
 // computeImportEdits computes a set of edits that perform one or all of the
 // necessary import fixes.
-func computeImportEdits(ctx context.Context, snapshot *cache.Snapshot, pgf *ParsedGoFile, options *imports.Options) (allFixEdits []protocol.TextEdit, editsPerFix []*ImportFix, err error) {
+func computeImportEdits(ctx context.Context, pgf *ParsedGoFile, options *imports.Options) (allFixEdits []protocol.TextEdit, editsPerFix []*importFix, err error) {
 	filename := pgf.URI.Path()
 
 	// Build up basic information about the original file.
@@ -134,7 +135,7 @@
 		return nil, nil, err
 	}
 
-	allFixEdits, err = computeFixEdits(snapshot, pgf, options, allFixes)
+	allFixEdits, err = computeFixEdits(pgf, options, allFixes)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -142,13 +143,13 @@
 	// Apply all of the import fixes to the file.
 	// Add the edits for each fix to the result.
 	for _, fix := range allFixes {
-		edits, err := computeFixEdits(snapshot, pgf, options, []*imports.ImportFix{fix})
+		edits, err := computeFixEdits(pgf, options, []*imports.ImportFix{fix})
 		if err != nil {
 			return nil, nil, err
 		}
-		editsPerFix = append(editsPerFix, &ImportFix{
-			Fix:   fix,
-			Edits: edits,
+		editsPerFix = append(editsPerFix, &importFix{
+			fix:   fix,
+			edits: edits,
 		})
 	}
 	return allFixEdits, editsPerFix, nil
@@ -166,10 +167,10 @@
 		TabIndent:  true,
 		TabWidth:   8,
 	}
-	return computeFixEdits(snapshot, pgf, options, []*imports.ImportFix{fix})
+	return computeFixEdits(pgf, options, []*imports.ImportFix{fix})
 }
 
-func computeFixEdits(snapshot *cache.Snapshot, pgf *ParsedGoFile, options *imports.Options, fixes []*imports.ImportFix) ([]protocol.TextEdit, error) {
+func computeFixEdits(pgf *ParsedGoFile, options *imports.Options, fixes []*imports.ImportFix) ([]protocol.TextEdit, error) {
 	// trim the original data to match fixedData
 	left, err := importPrefix(pgf.Src)
 	if err != nil {
@@ -302,8 +303,8 @@
 	return 0
 }
 
-func computeTextEdits(ctx context.Context, snapshot *cache.Snapshot, pgf *ParsedGoFile, formatted string) ([]protocol.TextEdit, error) {
-	_, done := event.Start(ctx, "source.computeTextEdits")
+func computeTextEdits(ctx context.Context, pgf *ParsedGoFile, formatted string) ([]protocol.TextEdit, error) {
+	_, done := event.Start(ctx, "golang.computeTextEdits")
 	defer done()
 
 	edits := diff.Strings(string(pgf.Src), formatted)
diff --git a/gopls/internal/lsp/source/format_test.go b/gopls/internal/golang/format_test.go
similarity index 98%
rename from gopls/internal/lsp/source/format_test.go
rename to gopls/internal/golang/format_test.go
index daa5b8f..4dbb4db 100644
--- a/gopls/internal/lsp/source/format_test.go
+++ b/gopls/internal/golang/format_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"strings"
diff --git a/gopls/internal/lsp/source/gc_annotations.go b/gopls/internal/golang/gc_annotations.go
similarity index 96%
rename from gopls/internal/lsp/source/gc_annotations.go
rename to gopls/internal/golang/gc_annotations.go
index b6230ce..8bcf402 100644
--- a/gopls/internal/lsp/source/gc_annotations.go
+++ b/gopls/internal/golang/gc_annotations.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"bytes"
@@ -13,9 +13,9 @@
 	"path/filepath"
 	"strings"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/internal/gocommand"
 )
diff --git a/gopls/internal/lsp/source/highlight.go b/gopls/internal/golang/highlight.go
similarity index 67%
rename from gopls/internal/lsp/source/highlight.go
rename to gopls/internal/golang/highlight.go
index 7e15dae..f114263 100644
--- a/gopls/internal/lsp/source/highlight.go
+++ b/gopls/internal/golang/highlight.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -12,15 +12,15 @@
 	"go/types"
 
 	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/typesutil"
 	"golang.org/x/tools/internal/event"
 )
 
 func Highlight(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, position protocol.Position) ([]protocol.Range, error) {
-	ctx, done := event.Start(ctx, "source.Highlight")
+	ctx, done := event.Start(ctx, "golang.Highlight")
 	defer done()
 
 	// We always want fully parsed files for highlight, regardless
@@ -65,6 +65,8 @@
 	return ranges, nil
 }
 
+// highlightPath returns ranges to highlight for the given enclosing path,
+// which should be the result of astutil.PathEnclosingInterval.
 func highlightPath(path []ast.Node, file *ast.File, info *types.Info) (map[posRange]struct{}, error) {
 	result := make(map[posRange]struct{})
 	switch node := path[0].(type) {
@@ -133,116 +135,170 @@
 	start, end token.Pos
 }
 
-func highlightFuncControlFlow(path []ast.Node, result map[posRange]struct{}) {
-	var enclosingFunc ast.Node
-	var returnStmt *ast.ReturnStmt
-	var resultsList *ast.FieldList
-	inReturnList := false
+// highlightFuncControlFlow adds highlight ranges to the result map to
+// associate results and result parameters.
+//
+// Specifically, if the cursor is in a result or result parameter, all
+// results and result parameters with the same index are highlighted. If the
+// cursor is in a 'func' or 'return' keyword, the func keyword as well as all
+// returns from that func are highlighted.
+//
+// As a special case, if the cursor is within a complicated expression, control
+// flow highlighting is disabled, as it would highlight too much.
+func highlightFuncControlFlow(path []ast.Node, result map[posRange]unit) {
 
-Outer:
-	// Reverse walk the path till we get to the func block.
+	var (
+		funcType   *ast.FuncType   // type of enclosing func, or nil
+		funcBody   *ast.BlockStmt  // body of enclosing func, or nil
+		returnStmt *ast.ReturnStmt // enclosing ReturnStmt within the func, or nil
+	)
+
+findEnclosingFunc:
 	for i, n := range path {
-		switch node := n.(type) {
+		switch n := n.(type) {
+		// TODO(rfindley, low priority): these pre-existing cases for KeyValueExpr
+		// and CallExpr appear to avoid highlighting when the cursor is in a
+		// complicated expression. However, the basis for this heuristic is
+		// unclear. Can we formalize a rationale?
 		case *ast.KeyValueExpr:
-			// If cursor is in a key: value expr, we don't want control flow highlighting
+			// If cursor is in a key: value expr, we don't want control flow highlighting.
 			return
+
 		case *ast.CallExpr:
 			// If cursor is an arg in a callExpr, we don't want control flow highlighting.
 			if i > 0 {
-				for _, arg := range node.Args {
+				for _, arg := range n.Args {
 					if arg == path[i-1] {
 						return
 					}
 				}
 			}
-		case *ast.Field:
-			inReturnList = true
-		case *ast.FuncLit:
-			enclosingFunc = n
-			resultsList = node.Type.Results
-			break Outer
-		case *ast.FuncDecl:
-			enclosingFunc = n
-			resultsList = node.Type.Results
-			break Outer
-		case *ast.ReturnStmt:
-			returnStmt = node
-			// If the cursor is not directly in a *ast.ReturnStmt, then
-			// we need to know if it is within one of the values that is being returned.
-			inReturnList = inReturnList || path[0] != returnStmt
-		}
-	}
-	// Cursor is not in a function.
-	if enclosingFunc == nil {
-		return
-	}
-	// If the cursor is on a "return" or "func" keyword, we should highlight all of the exit
-	// points of the function, including the "return" and "func" keywords.
-	highlightAllReturnsAndFunc := path[0] == returnStmt || path[0] == enclosingFunc
-	switch path[0].(type) {
-	case *ast.Ident, *ast.BasicLit:
-		// Cursor is in an identifier and not in a return statement or in the results list.
-		if returnStmt == nil && !inReturnList {
-			return
-		}
-	case *ast.FuncType:
-		highlightAllReturnsAndFunc = true
-	}
-	// The user's cursor may be within the return statement of a function,
-	// or within the result section of a function's signature.
-	// index := -1
-	var nodes []ast.Node
-	if returnStmt != nil {
-		for _, n := range returnStmt.Results {
-			nodes = append(nodes, n)
-		}
-	} else if resultsList != nil {
-		for _, n := range resultsList.List {
-			nodes = append(nodes, n)
-		}
-	}
-	_, index := nodeAtPos(nodes, path[0].Pos())
 
-	// Highlight the correct argument in the function declaration return types.
-	if resultsList != nil && -1 < index && index < len(resultsList.List) {
-		rng := posRange{
-			start: resultsList.List[index].Pos(),
-			end:   resultsList.List[index].End(),
+		case *ast.FuncLit:
+			funcType = n.Type
+			funcBody = n.Body
+			break findEnclosingFunc
+
+		case *ast.FuncDecl:
+			funcType = n.Type
+			funcBody = n.Body
+			break findEnclosingFunc
+
+		case *ast.ReturnStmt:
+			returnStmt = n
 		}
-		result[rng] = struct{}{}
 	}
-	// Add the "func" part of the func declaration.
-	if highlightAllReturnsAndFunc {
-		r := posRange{
-			start: enclosingFunc.Pos(),
-			end:   enclosingFunc.Pos() + token.Pos(len("func")),
-		}
-		result[r] = struct{}{}
+
+	if funcType == nil {
+		return // cursor is not in a function
 	}
-	ast.Inspect(enclosingFunc, func(n ast.Node) bool {
-		// Don't traverse any other functions.
-		switch n.(type) {
-		case *ast.FuncDecl, *ast.FuncLit:
-			return enclosingFunc == n
+
+	// Helper functions for inspecting the current location.
+	var (
+		pos    = path[0].Pos()
+		inSpan = func(start, end token.Pos) bool { return start <= pos && pos < end }
+		inNode = func(n ast.Node) bool { return inSpan(n.Pos(), n.End()) }
+	)
+
+	inResults := funcType.Results != nil && inNode(funcType.Results)
+
+	// If the cursor is on a "return" or "func" keyword, but not highlighting any
+	// specific field or expression, we should highlight all of the exit points
+	// of the function, including the "return" and "func" keywords.
+	funcEnd := funcType.Func + token.Pos(len("func"))
+	highlightAll := path[0] == returnStmt || inSpan(funcType.Func, funcEnd)
+	var highlightIndexes map[int]bool
+
+	if highlightAll {
+		// Add the "func" part of the func declaration.
+		result[posRange{
+			start: funcType.Func,
+			end:   funcEnd,
+		}] = unit{}
+	} else if returnStmt == nil && !inResults {
+		return // nothing to highlight
+	} else {
+		// If we're not highighting the entire return statement, we need to collect
+		// specific result indexes to highlight. This may be more than one index if
+		// the cursor is on a multi-name result field, but not in any specific name.
+		if !highlightAll {
+			highlightIndexes = make(map[int]bool)
+			if returnStmt != nil {
+				for i, n := range returnStmt.Results {
+					if inNode(n) {
+						highlightIndexes[i] = true
+						break
+					}
+				}
+			}
+
+			// Scan fields, either adding highlights according to the highlightIndexes
+			// computed above, or accounting for the cursor position within the result
+			// list.
+			// (We do both at once to avoid repeating the cumbersome field traversal.)
+			i := 0
+		findField:
+			for _, field := range funcType.Results.List {
+				for j, name := range field.Names {
+					if inNode(name) || highlightIndexes[i+j] {
+						result[posRange{name.Pos(), name.End()}] = unit{}
+						highlightIndexes[i+j] = true
+						break findField // found/highlighted the specific name
+					}
+				}
+				// If the cursor is in a field but not in a name (e.g. in the space, or
+				// the type), highlight the whole field.
+				//
+				// Note that this may not be ideal if we're at e.g.
+				//
+				//  (x,‸y int, z int8)
+				//
+				// ...where it would make more sense to highlight only y. But we don't
+				// reach this function if not in a func, return, ident, or basiclit.
+				if inNode(field) || highlightIndexes[i] {
+					result[posRange{field.Pos(), field.End()}] = unit{}
+					highlightIndexes[i] = true
+					if inNode(field) {
+						for j := range field.Names {
+							highlightIndexes[i+j] = true
+						}
+					}
+					break findField // found/highlighted the field
+				}
+
+				n := len(field.Names)
+				if n == 0 {
+					n = 1
+				}
+				i += n
+			}
 		}
-		ret, ok := n.(*ast.ReturnStmt)
-		if !ok {
+	}
+
+	if funcBody != nil {
+		ast.Inspect(funcBody, func(n ast.Node) bool {
+			switch n := n.(type) {
+			case *ast.FuncDecl, *ast.FuncLit:
+				// Don't traverse into any functions other than enclosingFunc.
+				return false
+			case *ast.ReturnStmt:
+				if highlightAll {
+					// Add the entire return statement.
+					result[posRange{n.Pos(), n.End()}] = unit{}
+				} else {
+					// Add the highlighted indexes.
+					for i, expr := range n.Results {
+						if highlightIndexes[i] {
+							result[posRange{expr.Pos(), expr.End()}] = unit{}
+						}
+					}
+				}
+				return false
+
+			}
 			return true
-		}
-		var toAdd ast.Node
-		// Add the entire return statement, applies when highlight the word "return" or "func".
-		if highlightAllReturnsAndFunc {
-			toAdd = n
-		}
-		// Add the relevant field within the entire return statement.
-		if -1 < index && index < len(ret.Results) {
-			toAdd = ret.Results[index]
-		}
-		if toAdd != nil {
-			result[posRange{start: toAdd.Pos(), end: toAdd.End()}] = struct{}{}
-		}
-		return false
-	})
+		})
+	}
 }
 
 // highlightUnlabeledBreakFlow highlights the innermost enclosing for/range/switch or swlect
diff --git a/gopls/internal/lsp/source/hover.go b/gopls/internal/golang/hover.go
similarity index 79%
rename from gopls/internal/lsp/source/hover.go
rename to gopls/internal/golang/hover.go
index 1da3ab5..ef48601 100644
--- a/gopls/internal/lsp/source/hover.go
+++ b/gopls/internal/golang/hover.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"bytes"
@@ -19,27 +19,34 @@
 	"path/filepath"
 	"strconv"
 	"strings"
+	"text/tabwriter"
 	"time"
 	"unicode/utf8"
 
 	"golang.org/x/text/unicode/runenames"
 	"golang.org/x/tools/go/ast/astutil"
 	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
+	"golang.org/x/tools/gopls/internal/util/slices"
+	"golang.org/x/tools/gopls/internal/util/typesutil"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/tokeninternal"
 )
 
-// HoverJSON contains information used by hover. It is also the JSON returned
-// for the "structured" hover format
-type HoverJSON struct {
+// hoverJSON contains the structured result of a hover query. It is
+// formatted in one of several formats as determined by the HoverKind
+// setting, one of which is JSON.
+//
+// We believe this is used only by govim.
+// TODO(adonovan): see if we can wean all clients of this interface.
+type hoverJSON struct {
 	// Synopsis is a single sentence synopsis of the symbol's documentation.
 	Synopsis string `json:"synopsis"`
 
@@ -63,11 +70,31 @@
 	// LinkAnchor is the pkg.go.dev link anchor for the given symbol.
 	// For example, the "Node" part of "pkg.go.dev/go/ast#Node".
 	LinkAnchor string `json:"linkAnchor"`
+
+	// New fields go below, and are unexported. The existing
+	// exported fields are underspecified and have already
+	// constrained our movements too much. A detailed JSON
+	// interface might be nice, but it needs a design and a
+	// precise specification.
+
+	// typeDecl is the declaration syntax for a type,
+	// or "" for a non-type.
+	typeDecl string
+
+	// methods is the list of descriptions of methods of a type,
+	// omitting any that are obvious from typeDecl.
+	// It is "" for a non-type.
+	methods string
+
+	// promotedFields is the list of descriptions of accessible
+	// fields of a (struct) type that were promoted through an
+	// embedded field.
+	promotedFields string
 }
 
 // Hover implements the "textDocument/hover" RPC for Go files.
 func Hover(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, position protocol.Position) (*protocol.Hover, error) {
-	ctx, done := event.Start(ctx, "source.Hover")
+	ctx, done := event.Start(ctx, "golang.Hover")
 	defer done()
 
 	rng, h, err := hover(ctx, snapshot, fh, position)
@@ -93,7 +120,7 @@
 // hover computes hover information at the given position. If we do not support
 // hovering at the position, it returns _, nil, nil: an error is only returned
 // if the position is valid but we fail to compute hover information.
-func hover(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, pp protocol.Position) (protocol.Range, *HoverJSON, error) {
+func hover(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, pp protocol.Position) (protocol.Range, *hoverJSON, error) {
 	pkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())
 	if err != nil {
 		return protocol.Range{}, nil, err
@@ -169,7 +196,7 @@
 
 	// By convention, we qualify hover information relative to the package
 	// from which the request originated.
-	qf := Qualifier(pgf.File, pkg.GetTypes(), pkg.GetTypesInfo())
+	qf := typesutil.FileQualifier(pgf.File, pkg.GetTypes(), pkg.GetTypesInfo())
 
 	// Handle type switch identifiers as a special case, since they don't have an
 	// object.
@@ -178,7 +205,7 @@
 	if selectedType != nil {
 		fakeObj := types.NewVar(obj.Pos(), obj.Pkg(), obj.Name(), selectedType)
 		signature := types.ObjectString(fakeObj, qf)
-		return rng, &HoverJSON{
+		return rng, &hoverJSON{
 			Signature:  signature,
 			SingleLine: signature,
 			SymbolName: fakeObj.Name(),
@@ -199,7 +226,7 @@
 	if err != nil {
 		return protocol.Range{}, nil, fmt.Errorf("re-parsing declaration of %s: %v", obj.Name(), err)
 	}
-	decl, spec, field := findDeclInfo([]*ast.File{declPGF.File}, declPos)
+	decl, spec, field := findDeclInfo([]*ast.File{declPGF.File}, declPos) // may be nil^3
 	comment := chooseDocComment(decl, spec, field)
 	docText := comment.Text()
 
@@ -214,53 +241,115 @@
 		}
 	}
 
+	var typeDecl, methods, fields string
+
 	// For "objects defined by a type spec", the signature produced by
 	// objectString is insufficient:
 	//  (1) large structs are formatted poorly, with no newlines
 	//  (2) we lose inline comments
-	//
 	// Furthermore, we include a summary of their method set.
-	//
-	// TODO(rfindley): this should use FormatVarType to get proper qualification
-	// of identifiers, and we should revisit the formatting of method set.
-	//
-	// TODO(adonovan): this logic belongs in objectString.
 	_, isTypeName := obj.(*types.TypeName)
 	_, isTypeParam := obj.Type().(*types.TypeParam)
 	if isTypeName && !isTypeParam {
 		spec, ok := spec.(*ast.TypeSpec)
 		if !ok {
-			return protocol.Range{}, nil, bug.Errorf("type name %q without type spec", obj.Name())
-		}
-		spec2 := *spec
-		// Don't duplicate comments when formatting type specs.
-		spec2.Doc = nil
-		spec2.Comment = nil
-		var b strings.Builder
-		b.WriteString("type ")
-		fset := tokeninternal.FileSetFor(declPGF.Tok)
-		if err := format.Node(&b, fset, &spec2); err != nil {
-			return protocol.Range{}, nil, err
+			// We cannot find a TypeSpec for this type or alias declaration
+			// (that is not a type parameter or a built-in).
+			// This should be impossible even for ill-formed trees;
+			// we suspect that AST repair may be creating inconsistent
+			// positions. Don't report a bug in that case. (#64241)
+			errorf := fmt.Errorf
+			if !declPGF.Fixed() {
+				errorf = bug.Errorf
+			}
+			return protocol.Range{}, nil, errorf("type name %q without type spec", obj.Name())
 		}
 
-		// Display the declared methods accessible from the identifier.
+		// Format the type's declaration syntax.
+		{
+			// Don't duplicate comments.
+			spec2 := *spec
+			spec2.Doc = nil
+			spec2.Comment = nil
+
+			var b strings.Builder
+			b.WriteString("type ")
+			fset := tokeninternal.FileSetFor(declPGF.Tok)
+			// TODO(adonovan): use a smarter formatter that omits
+			// inaccessible fields (non-exported ones from other packages).
+			if err := format.Node(&b, fset, &spec2); err != nil {
+				return protocol.Range{}, nil, err
+			}
+			typeDecl = b.String()
+		}
+
+		// Promoted fields
 		//
-		// (The format.Node call above displays any struct fields, public
-		// or private, in syntactic form. We choose not to recursively
-		// enumerate any fields and methods promoted from them.)
-		if !types.IsInterface(obj.Type()) {
-			sep := "\n\n"
-			for _, m := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
-				// Show direct methods that are either exported, or defined in the
-				// current package.
-				if (m.Obj().Exported() || m.Obj().Pkg() == pkg.GetTypes()) && len(m.Index()) == 1 {
-					b.WriteString(sep)
-					sep = "\n"
-					b.WriteString(types.ObjectString(m.Obj(), qf))
+		// Show a table of accessible fields of the (struct)
+		// type that may not be visible in the syntax (above)
+		// due to promotion through embedded fields.
+		//
+		// Example:
+		//
+		//	// Embedded fields:
+		//	foo int	   // through x.y
+		//	z   string // through x.y
+		if prom := promotedFields(obj.Type(), pkg.GetTypes()); len(prom) > 0 {
+			var b strings.Builder
+			b.WriteString("// Embedded fields:\n")
+			w := tabwriter.NewWriter(&b, 0, 8, 1, ' ', 0)
+			for _, f := range prom {
+				fmt.Fprintf(w, "%s\t%s\t// through %s\t\n",
+					f.field.Name(),
+					types.TypeString(f.field.Type(), qf),
+					f.path)
+			}
+			w.Flush()
+			b.WriteByte('\n')
+			fields = b.String()
+		}
+
+		// -- methods --
+
+		// For an interface type, explicit methods will have
+		// already been displayed when the node was formatted
+		// above. Don't list these again.
+		var skip map[string]bool
+		if iface, ok := spec.Type.(*ast.InterfaceType); ok {
+			if iface.Methods.List != nil {
+				for _, m := range iface.Methods.List {
+					if len(m.Names) == 1 {
+						if skip == nil {
+							skip = make(map[string]bool)
+						}
+						skip[m.Names[0].Name] = true
+					}
 				}
 			}
 		}
-		signature = b.String()
+
+		// Display all the type's accessible methods,
+		// including those that require a pointer receiver,
+		// and those promoted from embedded struct fields or
+		// embedded interfaces.
+		var b strings.Builder
+		for _, m := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
+			if !accessibleTo(m.Obj(), pkg.GetTypes()) {
+				continue // inaccessible
+			}
+			if skip[m.Obj().Name()] {
+				continue // redundant with format.Node above
+			}
+			if b.Len() > 0 {
+				b.WriteByte('\n')
+			}
+
+			// Use objectString for its prettier rendering of method receivers.
+			b.WriteString(objectString(m.Obj(), qf, token.NoPos, nil, nil))
+		}
+		methods = b.String()
+
+		signature = typeDecl + "\n" + methods
 	}
 
 	// Compute link data (on pkg.go.dev or other documentation host).
@@ -363,7 +452,7 @@
 		linkPath = strings.Replace(linkPath, mod.Path, mod.Path+"@"+mod.Version, 1)
 	}
 
-	return rng, &HoverJSON{
+	return rng, &hoverJSON{
 		Synopsis:          doc.Synopsis(docText),
 		FullDocumentation: docText,
 		SingleLine:        singleLineSignature,
@@ -371,18 +460,21 @@
 		Signature:         signature,
 		LinkPath:          linkPath,
 		LinkAnchor:        anchor,
+		typeDecl:          typeDecl,
+		methods:           methods,
+		promotedFields:    fields,
 	}, nil
 }
 
 // hoverBuiltin computes hover information when hovering over a builtin
 // identifier.
-func hoverBuiltin(ctx context.Context, snapshot *cache.Snapshot, obj types.Object) (*HoverJSON, error) {
+func hoverBuiltin(ctx context.Context, snapshot *cache.Snapshot, obj types.Object) (*hoverJSON, error) {
 	// Special handling for error.Error, which is the only builtin method.
 	//
 	// TODO(rfindley): can this be unified with the handling below?
 	if obj.Name() == "Error" {
 		signature := obj.String()
-		return &HoverJSON{
+		return &hoverJSON{
 			Signature:  signature,
 			SingleLine: signature,
 			// TODO(rfindley): these are better than the current behavior.
@@ -423,7 +515,7 @@
 	signature = replacer.Replace(signature)
 
 	docText := comment.Text()
-	return &HoverJSON{
+	return &hoverJSON{
 		Synopsis:          doc.Synopsis(docText),
 		FullDocumentation: docText,
 		Signature:         signature,
@@ -438,7 +530,7 @@
 // imp in the file pgf of pkg.
 //
 // If we do not have metadata for the hovered import, it returns _
-func hoverImport(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, pgf *ParsedGoFile, imp *ast.ImportSpec) (protocol.Range, *HoverJSON, error) {
+func hoverImport(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, pgf *ParsedGoFile, imp *ast.ImportSpec) (protocol.Range, *hoverJSON, error) {
 	rng, err := pgf.NodeRange(imp.Path)
 	if err != nil {
 		return protocol.Range{}, nil, err
@@ -481,7 +573,7 @@
 	}
 
 	docText := comment.Text()
-	return rng, &HoverJSON{
+	return rng, &hoverJSON{
 		Synopsis:          doc.Synopsis(docText),
 		FullDocumentation: docText,
 	}, nil
@@ -489,7 +581,7 @@
 
 // hoverPackageName computes hover information for the package name of the file
 // pgf in pkg.
-func hoverPackageName(pkg *cache.Package, pgf *ParsedGoFile) (protocol.Range, *HoverJSON, error) {
+func hoverPackageName(pkg *cache.Package, pgf *ParsedGoFile) (protocol.Range, *hoverJSON, error) {
 	var comment *ast.CommentGroup
 	for _, pgf := range pkg.CompiledGoFiles() {
 		if pgf.File.Doc != nil {
@@ -502,7 +594,7 @@
 		return protocol.Range{}, nil, err
 	}
 	docText := comment.Text()
-	return rng, &HoverJSON{
+	return rng, &hoverJSON{
 		Synopsis:          doc.Synopsis(docText),
 		FullDocumentation: docText,
 		// Note: including a signature is redundant, since the cursor is already on the
@@ -517,7 +609,7 @@
 // For example, hovering over "\u2211" in "foo \u2211 bar" yields:
 //
 //	'∑', U+2211, N-ARY SUMMATION
-func hoverLit(pgf *ParsedGoFile, lit *ast.BasicLit, pos token.Pos) (protocol.Range, *HoverJSON, error) {
+func hoverLit(pgf *ParsedGoFile, lit *ast.BasicLit, pos token.Pos) (protocol.Range, *hoverJSON, error) {
 	var (
 		value      string    // if non-empty, a constant value to format in hover
 		r          rune      // if non-zero, format a description of this rune in hover
@@ -630,7 +722,7 @@
 		fmt.Fprintf(&b, "U+%04X, %s", r, runeName)
 	}
 	hover := b.String()
-	return rng, &HoverJSON{
+	return rng, &hoverJSON{
 		Synopsis:          hover,
 		FullDocumentation: hover,
 	}, nil
@@ -638,7 +730,7 @@
 
 // hoverEmbed computes hover information for a filepath.Match pattern.
 // Assumes that the pattern is relative to the location of fh.
-func hoverEmbed(fh file.Handle, rng protocol.Range, pattern string) (protocol.Range, *HoverJSON, error) {
+func hoverEmbed(fh file.Handle, rng protocol.Range, pattern string) (protocol.Range, *hoverJSON, error) {
 	s := &strings.Builder{}
 
 	dir := filepath.Dir(fh.URI().Path())
@@ -670,7 +762,7 @@
 		fmt.Fprintf(s, "%s\n\n", m)
 	}
 
-	json := &HoverJSON{
+	json := &hoverJSON{
 		Signature:         fmt.Sprintf("Embedding %q", pattern),
 		Synopsis:          s.String(),
 		FullDocumentation: s.String(),
@@ -894,54 +986,67 @@
 	return pgf, fullPos, nil
 }
 
-func formatHover(h *HoverJSON, options *settings.Options) (string, error) {
-	signature := formatSignature(h, options)
+func formatHover(h *hoverJSON, options *settings.Options) (string, error) {
+	maybeMarkdown := func(s string) string {
+		if s != "" && options.PreferredContentFormat == protocol.Markdown {
+			s = fmt.Sprintf("```go\n%s\n```", strings.Trim(s, "\n"))
+		}
+		return s
+	}
 
 	switch options.HoverKind {
 	case settings.SingleLine:
 		return h.SingleLine, nil
+
 	case settings.NoDocumentation:
-		return signature, nil
+		return maybeMarkdown(h.Signature), nil
+
 	case settings.Structured:
 		b, err := json.Marshal(h)
 		if err != nil {
 			return "", err
 		}
 		return string(b), nil
-	}
 
-	link := formatLink(h, options)
-	doc := formatDoc(h, options)
+	case settings.SynopsisDocumentation,
+		settings.FullDocumentation:
+		// For types, we display TypeDecl and Methods,
+		// but not Signature, which is redundant (= TypeDecl + "\n" + Methods).
+		// For all other symbols, we display Signature;
+		// TypeDecl and Methods are empty.
+		// (This awkwardness is to preserve JSON compatibility.)
+		parts := []string{
+			maybeMarkdown(h.Signature),
+			maybeMarkdown(h.typeDecl),
+			formatDoc(h, options),
+			maybeMarkdown(h.promotedFields),
+			maybeMarkdown(h.methods),
+			formatLink(h, options),
+		}
+		if h.typeDecl != "" {
+			parts[0] = "" // type: suppress redundant Signature
+		}
+		parts = slices.Remove(parts, "")
 
-	var b strings.Builder
-	parts := []string{signature, doc, link}
-	for i, el := range parts {
-		if el != "" {
-			b.WriteString(el)
-
-			// If any elements of the remainder of the list are non-empty,
-			// write an extra newline.
-			if anyNonEmpty(parts[i+1:]) {
+		var b strings.Builder
+		for i, part := range parts {
+			if i > 0 {
 				if options.PreferredContentFormat == protocol.Markdown {
 					b.WriteString("\n\n")
 				} else {
-					b.WriteRune('\n')
+					b.WriteByte('\n')
 				}
 			}
+			b.WriteString(part)
 		}
+		return b.String(), nil
+
+	default:
+		return "", fmt.Errorf("invalid HoverKind: %v", options.HoverKind)
 	}
-	return b.String(), nil
 }
 
-func formatSignature(h *HoverJSON, options *settings.Options) string {
-	signature := h.Signature
-	if signature != "" && options.PreferredContentFormat == protocol.Markdown {
-		signature = fmt.Sprintf("```go\n%s\n```", signature)
-	}
-	return signature
-}
-
-func formatLink(h *HoverJSON, options *settings.Options) string {
+func formatLink(h *hoverJSON, options *settings.Options) string {
 	if !options.LinksInHover || options.LinkTarget == "" || h.LinkPath == "" {
 		return ""
 	}
@@ -956,7 +1061,7 @@
 	}
 }
 
-func formatDoc(h *HoverJSON, options *settings.Options) string {
+func formatDoc(h *hoverJSON, options *settings.Options) string {
 	var doc string
 	switch options.HoverKind {
 	case settings.SynopsisDocumentation:
@@ -970,15 +1075,6 @@
 	return doc
 }
 
-func anyNonEmpty(x []string) bool {
-	for _, el := range x {
-		if el != "" {
-			return true
-		}
-	}
-	return false
-}
-
 // findDeclInfo returns the syntax nodes involved in the declaration of the
 // types.Object with position pos, searching the given list of file syntax
 // trees.
@@ -1105,3 +1201,74 @@
 
 	return nil, nil, nil
 }
+
+type promotedField struct {
+	path  string // path (e.g. "x.y" through embedded fields)
+	field *types.Var
+}
+
+// promotedFields returns the list of accessible promoted fields of a struct type t.
+// (Logic plundered from x/tools/cmd/guru/describe.go.)
+func promotedFields(t types.Type, from *types.Package) []promotedField {
+	wantField := func(f *types.Var) bool {
+		if !accessibleTo(f, from) {
+			return false
+		}
+		// Check that the field is not shadowed.
+		obj, _, _ := types.LookupFieldOrMethod(t, true, f.Pkg(), f.Name())
+		return obj == f
+	}
+
+	var fields []promotedField
+	var visit func(t types.Type, stack []*types.Named)
+	visit = func(t types.Type, stack []*types.Named) {
+		tStruct, ok := Deref(t).Underlying().(*types.Struct)
+		if !ok {
+			return
+		}
+	fieldloop:
+		for i := 0; i < tStruct.NumFields(); i++ {
+			f := tStruct.Field(i)
+
+			// Handle recursion through anonymous fields.
+			if f.Anonymous() {
+				tf := f.Type()
+				if ptr, ok := tf.(*types.Pointer); ok {
+					tf = ptr.Elem()
+				}
+				if named, ok := tf.(*types.Named); ok { // (be defensive)
+					// If we've already visited this named type
+					// on this path, break the cycle.
+					for _, x := range stack {
+						if x.Origin() == named.Origin() {
+							continue fieldloop
+						}
+					}
+					visit(f.Type(), append(stack, named))
+				}
+			}
+
+			// Save accessible promoted fields.
+			if len(stack) > 0 && wantField(f) {
+				var path strings.Builder
+				for i, t := range stack {
+					if i > 0 {
+						path.WriteByte('.')
+					}
+					path.WriteString(t.Obj().Name())
+				}
+				fields = append(fields, promotedField{
+					path:  path.String(),
+					field: f,
+				})
+			}
+		}
+	}
+	visit(t, nil)
+
+	return fields
+}
+
+func accessibleTo(obj types.Object, pkg *types.Package) bool {
+	return obj.Exported() || obj.Pkg() == pkg
+}
diff --git a/gopls/internal/lsp/source/identifier.go b/gopls/internal/golang/identifier.go
similarity index 99%
rename from gopls/internal/lsp/source/identifier.go
rename to gopls/internal/golang/identifier.go
index 9e12e3f..28f8975 100644
--- a/gopls/internal/lsp/source/identifier.go
+++ b/gopls/internal/golang/identifier.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"errors"
diff --git a/gopls/internal/lsp/source/identifier_test.go b/gopls/internal/golang/identifier_test.go
similarity index 99%
rename from gopls/internal/lsp/source/identifier_test.go
rename to gopls/internal/golang/identifier_test.go
index 9f5eb7d..b1e6d5a 100644
--- a/gopls/internal/lsp/source/identifier_test.go
+++ b/gopls/internal/golang/identifier_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"bytes"
diff --git a/gopls/internal/lsp/source/implementation.go b/gopls/internal/golang/implementation.go
similarity index 97%
rename from gopls/internal/lsp/source/implementation.go
rename to gopls/internal/golang/implementation.go
index 9d644d1..cb7dadb 100644
--- a/gopls/internal/lsp/source/implementation.go
+++ b/gopls/internal/golang/implementation.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -17,11 +17,11 @@
 	"sync"
 
 	"golang.org/x/sync/errgroup"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/methodsets"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/methodsets"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/event"
@@ -49,7 +49,7 @@
 // If the position denotes a method, the computation is applied to its
 // receiver type and then its corresponding methods are returned.
 func Implementation(ctx context.Context, snapshot *cache.Snapshot, f file.Handle, pp protocol.Position) ([]protocol.Location, error) {
-	ctx, done := event.Start(ctx, "source.Implementation")
+	ctx, done := event.Start(ctx, "golang.Implementation")
 	defer done()
 
 	locs, err := implementations(ctx, snapshot, f, pp)
diff --git a/gopls/internal/lsp/source/inlay_hint.go b/gopls/internal/golang/inlay_hint.go
similarity index 97%
rename from gopls/internal/lsp/source/inlay_hint.go
rename to gopls/internal/golang/inlay_hint.go
index 41dd670..6f35c8e 100644
--- a/gopls/internal/lsp/source/inlay_hint.go
+++ b/gopls/internal/golang/inlay_hint.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -13,9 +13,10 @@
 	"go/types"
 	"strings"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/util/typesutil"
 	"golang.org/x/tools/internal/event"
 )
 
@@ -80,7 +81,7 @@
 }
 
 func InlayHint(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, pRng protocol.Range) ([]protocol.InlayHint, error) {
-	ctx, done := event.Start(ctx, "source.InlayHint")
+	ctx, done := event.Start(ctx, "golang.InlayHint")
 	defer done()
 
 	pkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())
@@ -104,7 +105,7 @@
 	}
 
 	info := pkg.GetTypesInfo()
-	q := Qualifier(pgf.File, pkg.GetTypes(), info)
+	q := typesutil.FileQualifier(pgf.File, pkg.GetTypes(), info)
 
 	// Set the range to the full file if the range is not valid.
 	start, end := pgf.File.Pos(), pgf.File.End()
diff --git a/gopls/internal/lsp/source/inline.go b/gopls/internal/golang/inline.go
similarity index 95%
rename from gopls/internal/lsp/source/inline.go
rename to gopls/internal/golang/inline.go
index 1519ef8..de2a6ef 100644
--- a/gopls/internal/lsp/source/inline.go
+++ b/gopls/internal/golang/inline.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 // This file defines the refactor.inline code action.
 
@@ -16,9 +16,9 @@
 	"golang.org/x/tools/go/analysis"
 	"golang.org/x/tools/go/ast/astutil"
 	"golang.org/x/tools/go/types/typeutil"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/diff"
 	"golang.org/x/tools/internal/event"
diff --git a/gopls/internal/lsp/source/inline_all.go b/gopls/internal/golang/inline_all.go
similarity index 98%
rename from gopls/internal/lsp/source/inline_all.go
rename to gopls/internal/golang/inline_all.go
index 13f61ea..f2bab9d 100644
--- a/gopls/internal/lsp/source/inline_all.go
+++ b/gopls/internal/golang/inline_all.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -13,8 +13,8 @@
 
 	"golang.org/x/tools/go/ast/astutil"
 	"golang.org/x/tools/go/types/typeutil"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/internal/refactor/inline"
 )
diff --git a/gopls/internal/lsp/source/invertifcondition.go b/gopls/internal/golang/invertifcondition.go
similarity index 98%
rename from gopls/internal/lsp/source/invertifcondition.go
rename to gopls/internal/golang/invertifcondition.go
index 75e375a..377e1ce 100644
--- a/gopls/internal/lsp/source/invertifcondition.go
+++ b/gopls/internal/golang/invertifcondition.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"fmt"
@@ -92,7 +92,7 @@
 func endsWithReturn(elseBranch ast.Stmt) (bool, error) {
 	elseBlock, isBlockStatement := elseBranch.(*ast.BlockStmt)
 	if !isBlockStatement {
-		return false, fmt.Errorf("Unable to figure out whether this ends with return: %T", elseBranch)
+		return false, fmt.Errorf("unable to figure out whether this ends with return: %T", elseBranch)
 	}
 
 	if len(elseBlock.List) == 0 {
diff --git a/gopls/internal/lsp/source/known_packages.go b/gopls/internal/golang/known_packages.go
similarity index 97%
rename from gopls/internal/lsp/source/known_packages.go
rename to gopls/internal/golang/known_packages.go
index d6a442e..60a89ca 100644
--- a/gopls/internal/lsp/source/known_packages.go
+++ b/gopls/internal/golang/known_packages.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -13,9 +13,9 @@
 	"sync"
 	"time"
 
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/imports"
 )
diff --git a/gopls/internal/lsp/source/linkname.go b/gopls/internal/golang/linkname.go
similarity index 96%
rename from gopls/internal/lsp/source/linkname.go
rename to gopls/internal/golang/linkname.go
index bcefa10..2578f8d 100644
--- a/gopls/internal/lsp/source/linkname.go
+++ b/gopls/internal/golang/linkname.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -11,9 +11,9 @@
 	"go/token"
 	"strings"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 )
 
diff --git a/gopls/internal/lsp/source/origin.go b/gopls/internal/golang/origin.go
similarity index 97%
rename from gopls/internal/lsp/source/origin.go
rename to gopls/internal/golang/origin.go
index 8ee467e..c5e84db 100644
--- a/gopls/internal/lsp/source/origin.go
+++ b/gopls/internal/golang/origin.go
@@ -5,7 +5,7 @@
 //go:build !go1.19
 // +build !go1.19
 
-package source
+package golang
 
 import "go/types"
 
diff --git a/gopls/internal/lsp/source/origin_119.go b/gopls/internal/golang/origin_119.go
similarity index 97%
rename from gopls/internal/lsp/source/origin_119.go
rename to gopls/internal/golang/origin_119.go
index a249ce4..16f6ca7 100644
--- a/gopls/internal/lsp/source/origin_119.go
+++ b/gopls/internal/golang/origin_119.go
@@ -5,7 +5,7 @@
 //go:build go1.19
 // +build go1.19
 
-package source
+package golang
 
 import "go/types"
 
diff --git a/gopls/internal/lsp/source/references.go b/gopls/internal/golang/references.go
similarity index 98%
rename from gopls/internal/lsp/source/references.go
rename to gopls/internal/golang/references.go
index f93783e..c448830 100644
--- a/gopls/internal/lsp/source/references.go
+++ b/gopls/internal/golang/references.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 // This file defines the 'references' query based on a serializable
 // index constructed during type checking, thus avoiding the need to
@@ -25,11 +25,11 @@
 
 	"golang.org/x/sync/errgroup"
 	"golang.org/x/tools/go/types/objectpath"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/methodsets"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/methodsets"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/event"
@@ -62,7 +62,7 @@
 // definitions before uses) to the object denoted by the identifier at
 // the given file/position, searching the entire workspace.
 func references(ctx context.Context, snapshot *cache.Snapshot, f file.Handle, pp protocol.Position, includeDeclaration bool) ([]reference, error) {
-	ctx, done := event.Start(ctx, "source.references")
+	ctx, done := event.Start(ctx, "golang.references")
 	defer done()
 
 	// Is the cursor within the package name declaration?
diff --git a/gopls/internal/lsp/source/rename.go b/gopls/internal/golang/rename.go
similarity index 98%
rename from gopls/internal/lsp/source/rename.go
rename to gopls/internal/golang/rename.go
index 0bf8cc2..2948541 100644
--- a/gopls/internal/lsp/source/rename.go
+++ b/gopls/internal/golang/rename.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 // TODO(adonovan):
 //
@@ -59,11 +59,11 @@
 	"golang.org/x/tools/go/ast/astutil"
 	"golang.org/x/tools/go/types/objectpath"
 	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/diff"
@@ -98,7 +98,7 @@
 // the prepare fails. Probably we could eliminate the redundancy in returning
 // two errors, but for now this is done defensively.
 func PrepareRename(ctx context.Context, snapshot *cache.Snapshot, f file.Handle, pp protocol.Position) (_ *PrepareItem, usererr, err error) {
-	ctx, done := event.Start(ctx, "source.PrepareRename")
+	ctx, done := event.Start(ctx, "golang.PrepareRename")
 	defer done()
 
 	// Is the cursor within the package name declaration?
@@ -216,7 +216,7 @@
 // given identifier within a package and a boolean value of true for renaming
 // package and false otherwise.
 func Rename(ctx context.Context, snapshot *cache.Snapshot, f file.Handle, pp protocol.Position, newName string) (map[protocol.DocumentURI][]protocol.TextEdit, bool, error) {
-	ctx, done := event.Start(ctx, "source.Rename")
+	ctx, done := event.Start(ctx, "golang.Rename")
 	defer done()
 
 	if !isValidIdentifier(newName) {
@@ -402,7 +402,7 @@
 	// transitive rdeps. (The exportedness of the field's struct
 	// or method's receiver is irrelevant.)
 	transitive := false
-	switch obj.(type) {
+	switch obj := obj.(type) {
 	case *types.TypeName:
 		// Renaming an exported package-level type
 		// requires us to inspect all transitive rdeps
@@ -418,7 +418,7 @@
 		}
 
 	case *types.Var:
-		if obj.(*types.Var).IsField() {
+		if obj.IsField() {
 			transitive = true // field
 		}
 
diff --git a/gopls/internal/lsp/source/rename_check.go b/gopls/internal/golang/rename_check.go
similarity index 99%
rename from gopls/internal/lsp/source/rename_check.go
rename to gopls/internal/golang/rename_check.go
index bc6b7cf..11b154c 100644
--- a/gopls/internal/lsp/source/rename_check.go
+++ b/gopls/internal/golang/rename_check.go
@@ -4,7 +4,7 @@
 //
 // Taken from golang.org/x/tools/refactor/rename.
 
-package source
+package golang
 
 // This file defines the conflict-checking portion of the rename operation.
 //
@@ -43,7 +43,7 @@
 	"unicode"
 
 	"golang.org/x/tools/go/ast/astutil"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/refactor/satisfy"
 )
diff --git a/gopls/internal/golang/semtok.go b/gopls/internal/golang/semtok.go
new file mode 100644
index 0000000..360b3ac
--- /dev/null
+++ b/gopls/internal/golang/semtok.go
@@ -0,0 +1,853 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package golang
+
+// This file defines the Semantic Tokens operation for Go source.
+
+import (
+	"bytes"
+	"context"
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"go/types"
+	"log"
+	"path/filepath"
+	"strings"
+	"time"
+
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/file"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/semtok"
+	"golang.org/x/tools/gopls/internal/util/safetoken"
+	"golang.org/x/tools/internal/event"
+)
+
+// to control comprehensive logging of decisions (gopls semtok foo.go > /dev/null shows log output)
+// semDebug should NEVER be true in checked-in code
+const semDebug = false
+
+// The LSP says that errors for the semantic token requests should only be returned
+// for exceptions (a word not otherwise defined). This code treats a too-large file
+// as an exception. On parse errors, the code does what it can.
+
+// reject full semantic token requests for large files
+const maxFullFileSize int = 100000
+
+func SemanticTokens(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng *protocol.Range) (*protocol.SemanticTokens, error) {
+	pkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())
+	if err != nil {
+		return nil, err
+	}
+
+	// Select range.
+	var start, end token.Pos
+	if rng != nil {
+		var err error
+		start, end, err = pgf.RangePos(*rng)
+		if err != nil {
+			return nil, err // e.g. invalid range
+		}
+	} else {
+		tok := pgf.Tok
+		start, end = tok.Pos(0), tok.Pos(tok.Size()) // entire file
+	}
+	if int(end-start) > maxFullFileSize {
+		err := fmt.Errorf("semantic tokens: range %s too large (%d > %d)",
+			fh.URI().Path(), end-start, maxFullFileSize)
+		return nil, err
+	}
+
+	tv := &tokenVisitor{
+		ctx:            ctx,
+		metadataSource: snapshot,
+		pgf:            pgf,
+		start:          start,
+		end:            end,
+		ti:             pkg.GetTypesInfo(),
+		pkg:            pkg,
+		fset:           pkg.FileSet(),
+	}
+	tv.visit()
+	return &protocol.SemanticTokens{
+		Data: semtok.Encode(
+			tv.items,
+			snapshot.Options().NoSemanticString,
+			snapshot.Options().NoSemanticNumber,
+			snapshot.Options().SemanticTypes,
+			snapshot.Options().SemanticMods),
+		// For delta requests, but we've never seen any.
+		ResultID: time.Now().String(),
+	}, nil
+}
+
+type tokenVisitor struct {
+	items []semtok.Token
+	ctx   context.Context // for event logging
+	// metadataSource is used to resolve imports
+	metadataSource metadata.Source
+	pgf            *ParsedGoFile
+	start, end     token.Pos // range of interest
+	ti             *types.Info
+	pkg            *cache.Package
+	fset           *token.FileSet
+	// path from the root of the parse tree, used for debugging
+	stack []ast.Node
+}
+
+func (tv *tokenVisitor) visit() {
+	f := tv.pgf.File
+	// may not be in range, but harmless
+	tv.token(f.Package, len("package"), semtok.TokKeyword, nil)
+	tv.token(f.Name.NamePos, len(f.Name.Name), semtok.TokNamespace, nil)
+	inspect := func(n ast.Node) bool {
+		return tv.inspector(n)
+	}
+	for _, d := range f.Decls {
+		// only look at the decls that overlap the range
+		start, end := d.Pos(), d.End()
+		if end <= tv.start || start >= tv.end {
+			continue
+		}
+		ast.Inspect(d, inspect)
+	}
+	for _, cg := range f.Comments {
+		for _, c := range cg.List {
+			if strings.HasPrefix(c.Text, "//go:") {
+				tv.godirective(c)
+				continue
+			}
+			if !strings.Contains(c.Text, "\n") {
+				tv.token(c.Pos(), len(c.Text), semtok.TokComment, nil)
+				continue
+			}
+			tv.multiline(c.Pos(), c.End(), c.Text, semtok.TokComment)
+		}
+	}
+}
+
+func (tv *tokenVisitor) token(start token.Pos, leng int, typ semtok.TokenType, mods []string) {
+	if !start.IsValid() {
+		// This is not worth reporting. TODO(pjw): does it still happen?
+		return
+	}
+	if start >= tv.end || start+token.Pos(leng) <= tv.start {
+		return
+	}
+	// want a line and column from start (in LSP coordinates). Ignore line directives.
+	lspRange, err := tv.pgf.PosRange(start, start+token.Pos(leng))
+	if err != nil {
+		event.Error(tv.ctx, "failed to convert to range", err)
+		return
+	}
+	if lspRange.End.Line != lspRange.Start.Line {
+		// this happens if users are typing at the end of the file, but report nothing
+		return
+	}
+	tv.items = append(tv.items, semtok.Token{
+		Line:      lspRange.Start.Line,
+		Start:     lspRange.Start.Character,
+		Len:       lspRange.End.Character - lspRange.Start.Character, // all on one line
+		Type:      typ,
+		Modifiers: mods,
+	})
+}
+
+// convert the stack to a string, for debugging
+func (tv *tokenVisitor) strStack() string {
+	msg := []string{"["}
+	for i := len(tv.stack) - 1; i >= 0; i-- {
+		s := tv.stack[i]
+		msg = append(msg, fmt.Sprintf("%T", s)[5:])
+	}
+	if len(tv.stack) > 0 {
+		loc := tv.stack[len(tv.stack)-1].Pos()
+		if _, err := safetoken.Offset(tv.pgf.Tok, loc); err != nil {
+			msg = append(msg, fmt.Sprintf("invalid position %v for %s", loc, tv.pgf.URI))
+		} else {
+			add := safetoken.Position(tv.pgf.Tok, loc)
+			nm := filepath.Base(add.Filename)
+			msg = append(msg, fmt.Sprintf("(%s:%d,col:%d)", nm, add.Line, add.Column))
+		}
+	}
+	msg = append(msg, "]")
+	return strings.Join(msg, " ")
+}
+
+// find the line in the source
+func (tv *tokenVisitor) srcLine(x ast.Node) string {
+	file := tv.pgf.Tok
+	line := safetoken.Line(file, x.Pos())
+	start, err := safetoken.Offset(file, file.LineStart(line))
+	if err != nil {
+		return ""
+	}
+	end := start
+	for ; end < len(tv.pgf.Src) && tv.pgf.Src[end] != '\n'; end++ {
+
+	}
+	ans := tv.pgf.Src[start:end]
+	return string(ans)
+}
+
+func (tv *tokenVisitor) inspector(n ast.Node) bool {
+	pop := func() {
+		tv.stack = tv.stack[:len(tv.stack)-1]
+	}
+	if n == nil {
+		pop()
+		return true
+	}
+	tv.stack = append(tv.stack, n)
+	switch x := n.(type) {
+	case *ast.ArrayType:
+	case *ast.AssignStmt:
+		tv.token(x.TokPos, len(x.Tok.String()), semtok.TokOperator, nil)
+	case *ast.BasicLit:
+		if strings.Contains(x.Value, "\n") {
+			// has to be a string.
+			tv.multiline(x.Pos(), x.End(), x.Value, semtok.TokString)
+			break
+		}
+		ln := len(x.Value)
+		what := semtok.TokNumber
+		if x.Kind == token.STRING {
+			what = semtok.TokString
+		}
+		tv.token(x.Pos(), ln, what, nil)
+	case *ast.BinaryExpr:
+		tv.token(x.OpPos, len(x.Op.String()), semtok.TokOperator, nil)
+	case *ast.BlockStmt:
+	case *ast.BranchStmt:
+		tv.token(x.TokPos, len(x.Tok.String()), semtok.TokKeyword, nil)
+		// There's no semantic encoding for labels
+	case *ast.CallExpr:
+		if x.Ellipsis != token.NoPos {
+			tv.token(x.Ellipsis, len("..."), semtok.TokOperator, nil)
+		}
+	case *ast.CaseClause:
+		iam := "case"
+		if x.List == nil {
+			iam = "default"
+		}
+		tv.token(x.Case, len(iam), semtok.TokKeyword, nil)
+	case *ast.ChanType:
+		// chan | chan <- | <- chan
+		switch {
+		case x.Arrow == token.NoPos:
+			tv.token(x.Begin, len("chan"), semtok.TokKeyword, nil)
+		case x.Arrow == x.Begin:
+			tv.token(x.Arrow, 2, semtok.TokOperator, nil)
+			pos := tv.findKeyword("chan", x.Begin+2, x.Value.Pos())
+			tv.token(pos, len("chan"), semtok.TokKeyword, nil)
+		case x.Arrow != x.Begin:
+			tv.token(x.Begin, len("chan"), semtok.TokKeyword, nil)
+			tv.token(x.Arrow, 2, semtok.TokOperator, nil)
+		}
+	case *ast.CommClause:
+		iam := len("case")
+		if x.Comm == nil {
+			iam = len("default")
+		}
+		tv.token(x.Case, iam, semtok.TokKeyword, nil)
+	case *ast.CompositeLit:
+	case *ast.DeclStmt:
+	case *ast.DeferStmt:
+		tv.token(x.Defer, len("defer"), semtok.TokKeyword, nil)
+	case *ast.Ellipsis:
+		tv.token(x.Ellipsis, len("..."), semtok.TokOperator, nil)
+	case *ast.EmptyStmt:
+	case *ast.ExprStmt:
+	case *ast.Field:
+	case *ast.FieldList:
+	case *ast.ForStmt:
+		tv.token(x.For, len("for"), semtok.TokKeyword, nil)
+	case *ast.FuncDecl:
+	case *ast.FuncLit:
+	case *ast.FuncType:
+		if x.Func != token.NoPos {
+			tv.token(x.Func, len("func"), semtok.TokKeyword, nil)
+		}
+	case *ast.GenDecl:
+		tv.token(x.TokPos, len(x.Tok.String()), semtok.TokKeyword, nil)
+	case *ast.GoStmt:
+		tv.token(x.Go, len("go"), semtok.TokKeyword, nil)
+	case *ast.Ident:
+		tv.ident(x)
+	case *ast.IfStmt:
+		tv.token(x.If, len("if"), semtok.TokKeyword, nil)
+		if x.Else != nil {
+			// x.Body.End() or x.Body.End()+1, not that it matters
+			pos := tv.findKeyword("else", x.Body.End(), x.Else.Pos())
+			tv.token(pos, len("else"), semtok.TokKeyword, nil)
+		}
+	case *ast.ImportSpec:
+		tv.importSpec(x)
+		pop()
+		return false
+	case *ast.IncDecStmt:
+		tv.token(x.TokPos, len(x.Tok.String()), semtok.TokOperator, nil)
+	case *ast.IndexExpr:
+	case *ast.IndexListExpr:
+	case *ast.InterfaceType:
+		tv.token(x.Interface, len("interface"), semtok.TokKeyword, nil)
+	case *ast.KeyValueExpr:
+	case *ast.LabeledStmt:
+	case *ast.MapType:
+		tv.token(x.Map, len("map"), semtok.TokKeyword, nil)
+	case *ast.ParenExpr:
+	case *ast.RangeStmt:
+		tv.token(x.For, len("for"), semtok.TokKeyword, nil)
+		// x.TokPos == token.NoPos is legal (for range foo {})
+		offset := x.TokPos
+		if offset == token.NoPos {
+			offset = x.For
+		}
+		pos := tv.findKeyword("range", offset, x.X.Pos())
+		tv.token(pos, len("range"), semtok.TokKeyword, nil)
+	case *ast.ReturnStmt:
+		tv.token(x.Return, len("return"), semtok.TokKeyword, nil)
+	case *ast.SelectStmt:
+		tv.token(x.Select, len("select"), semtok.TokKeyword, nil)
+	case *ast.SelectorExpr:
+	case *ast.SendStmt:
+		tv.token(x.Arrow, len("<-"), semtok.TokOperator, nil)
+	case *ast.SliceExpr:
+	case *ast.StarExpr:
+		tv.token(x.Star, len("*"), semtok.TokOperator, nil)
+	case *ast.StructType:
+		tv.token(x.Struct, len("struct"), semtok.TokKeyword, nil)
+	case *ast.SwitchStmt:
+		tv.token(x.Switch, len("switch"), semtok.TokKeyword, nil)
+	case *ast.TypeAssertExpr:
+		if x.Type == nil {
+			pos := tv.findKeyword("type", x.Lparen, x.Rparen)
+			tv.token(pos, len("type"), semtok.TokKeyword, nil)
+		}
+	case *ast.TypeSpec:
+	case *ast.TypeSwitchStmt:
+		tv.token(x.Switch, len("switch"), semtok.TokKeyword, nil)
+	case *ast.UnaryExpr:
+		tv.token(x.OpPos, len(x.Op.String()), semtok.TokOperator, nil)
+	case *ast.ValueSpec:
+	// things only seen with parsing or type errors, so ignore them
+	case *ast.BadDecl, *ast.BadExpr, *ast.BadStmt:
+		return true
+	// not going to see these
+	case *ast.File, *ast.Package:
+		tv.unexpected(fmt.Sprintf("implement %T %s", x, safetoken.Position(tv.pgf.Tok, x.Pos())))
+	// other things we knowingly ignore
+	case *ast.Comment, *ast.CommentGroup:
+		pop()
+		return false
+	default:
+		tv.unexpected(fmt.Sprintf("failed to implement %T", x))
+	}
+	return true
+}
+
+func (tv *tokenVisitor) ident(x *ast.Ident) {
+	if tv.ti == nil {
+		what, mods := tv.unkIdent(x)
+		if what != "" {
+			tv.token(x.Pos(), len(x.String()), what, mods)
+		}
+		if semDebug {
+			log.Printf(" nil %s/nil/nil %q %v %s", x.String(), what, mods, tv.strStack())
+		}
+		return
+	}
+	def := tv.ti.Defs[x]
+	if def != nil {
+		what, mods := tv.definitionFor(x, def)
+		if what != "" {
+			tv.token(x.Pos(), len(x.String()), what, mods)
+		}
+		if semDebug {
+			log.Printf(" for %s/%T/%T got %s %v (%s)", x.String(), def, def.Type(), what, mods, tv.strStack())
+		}
+		return
+	}
+	use := tv.ti.Uses[x]
+	tok := func(pos token.Pos, lng int, tok semtok.TokenType, mods []string) {
+		tv.token(pos, lng, tok, mods)
+		q := "nil"
+		if use != nil {
+			q = fmt.Sprintf("%T", use.Type())
+		}
+		if semDebug {
+			log.Printf(" use %s/%T/%s got %s %v (%s)", x.String(), use, q, tok, mods, tv.strStack())
+		}
+	}
+
+	switch y := use.(type) {
+	case nil:
+		what, mods := tv.unkIdent(x)
+		if what != "" {
+			tok(x.Pos(), len(x.String()), what, mods)
+		} else if semDebug {
+			// tok() wasn't called, so didn't log
+			log.Printf(" nil %s/%T/nil %q %v (%s)", x.String(), use, what, mods, tv.strStack())
+		}
+		return
+	case *types.Builtin:
+		tok(x.NamePos, len(x.Name), semtok.TokFunction, []string{"defaultLibrary"})
+	case *types.Const:
+		mods := []string{"readonly"}
+		tt := y.Type()
+		if _, ok := tt.(*types.Basic); ok {
+			tok(x.Pos(), len(x.String()), semtok.TokVariable, mods)
+			break
+		}
+		if ttx, ok := tt.(*types.Named); ok {
+			if x.String() == "iota" {
+				tv.unexpected(fmt.Sprintf("iota:%T", ttx))
+			}
+			if _, ok := ttx.Underlying().(*types.Basic); ok {
+				tok(x.Pos(), len(x.String()), semtok.TokVariable, mods)
+				break
+			}
+			tv.unexpected(fmt.Sprintf("%q/%T", x.String(), tt))
+		}
+		// can this happen? Don't think so
+		tv.unexpected(fmt.Sprintf("%s %T %#v", x.String(), tt, tt))
+	case *types.Func:
+		tok(x.Pos(), len(x.Name), semtok.TokFunction, nil)
+	case *types.Label:
+		// nothing to map it to
+	case *types.Nil:
+		// nil is a predeclared identifier
+		tok(x.Pos(), len("nil"), semtok.TokVariable, []string{"readonly", "defaultLibrary"})
+	case *types.PkgName:
+		tok(x.Pos(), len(x.Name), semtok.TokNamespace, nil)
+	case *types.TypeName: // could be a TokTypeParam
+		var mods []string
+		if _, ok := y.Type().(*types.Basic); ok {
+			mods = []string{"defaultLibrary"}
+		} else if _, ok := y.Type().(*types.TypeParam); ok {
+			tok(x.Pos(), len(x.String()), semtok.TokTypeParam, mods)
+			break
+		}
+		tok(x.Pos(), len(x.String()), semtok.TokType, mods)
+	case *types.Var:
+		if isSignature(y) {
+			tok(x.Pos(), len(x.Name), semtok.TokFunction, nil)
+		} else if tv.isParam(use.Pos()) {
+			// variable, unless use.pos is the pos of a Field in an ancestor FuncDecl
+			// or FuncLit and then it's a parameter
+			tok(x.Pos(), len(x.Name), semtok.TokParameter, nil)
+		} else {
+			tok(x.Pos(), len(x.Name), semtok.TokVariable, nil)
+		}
+
+	default:
+		// can't happen
+		if use == nil {
+			msg := fmt.Sprintf("%#v %#v %#v", x, tv.ti.Defs[x], tv.ti.Uses[x])
+			tv.unexpected(msg)
+		}
+		if use.Type() != nil {
+			tv.unexpected(fmt.Sprintf("%s %T/%T,%#v", x.String(), use, use.Type(), use))
+		} else {
+			tv.unexpected(fmt.Sprintf("%s %T", x.String(), use))
+		}
+	}
+}
+
+func (tv *tokenVisitor) isParam(pos token.Pos) bool {
+	for i := len(tv.stack) - 1; i >= 0; i-- {
+		switch n := tv.stack[i].(type) {
+		case *ast.FuncDecl:
+			for _, f := range n.Type.Params.List {
+				for _, id := range f.Names {
+					if id.Pos() == pos {
+						return true
+					}
+				}
+			}
+		case *ast.FuncLit:
+			for _, f := range n.Type.Params.List {
+				for _, id := range f.Names {
+					if id.Pos() == pos {
+						return true
+					}
+				}
+			}
+		}
+	}
+	return false
+}
+
+func isSignature(use types.Object) bool {
+	if _, ok := use.(*types.Var); !ok {
+		return false
+	}
+	v := use.Type()
+	if v == nil {
+		return false
+	}
+	if _, ok := v.(*types.Signature); ok {
+		return true
+	}
+	return false
+}
+
+// both tv.ti.Defs and tv.ti.Uses are nil. use the parse stack.
+// a lot of these only happen when the package doesn't compile
+// but in that case it is all best-effort from the parse tree
+func (tv *tokenVisitor) unkIdent(x *ast.Ident) (semtok.TokenType, []string) {
+	def := []string{"definition"}
+	n := len(tv.stack) - 2 // parent of Ident
+	if n < 0 {
+		tv.unexpected("no stack?")
+		return "", nil
+	}
+	switch nd := tv.stack[n].(type) {
+	case *ast.BinaryExpr, *ast.UnaryExpr, *ast.ParenExpr, *ast.StarExpr,
+		*ast.IncDecStmt, *ast.SliceExpr, *ast.ExprStmt, *ast.IndexExpr,
+		*ast.ReturnStmt, *ast.ChanType, *ast.SendStmt,
+		*ast.ForStmt,      // possibly incomplete
+		*ast.IfStmt,       /* condition */
+		*ast.KeyValueExpr, // either key or value
+		*ast.IndexListExpr:
+		return semtok.TokVariable, nil
+	case *ast.Ellipsis:
+		return semtok.TokType, nil
+	case *ast.CaseClause:
+		if n-2 >= 0 {
+			if _, ok := tv.stack[n-2].(*ast.TypeSwitchStmt); ok {
+				return semtok.TokType, nil
+			}
+		}
+		return semtok.TokVariable, nil
+	case *ast.ArrayType:
+		if x == nd.Len {
+			// or maybe a Type Param, but we can't just from the parse tree
+			return semtok.TokVariable, nil
+		} else {
+			return semtok.TokType, nil
+		}
+	case *ast.MapType:
+		return semtok.TokType, nil
+	case *ast.CallExpr:
+		if x == nd.Fun {
+			return semtok.TokFunction, nil
+		}
+		return semtok.TokVariable, nil
+	case *ast.SwitchStmt:
+		return semtok.TokVariable, nil
+	case *ast.TypeAssertExpr:
+		if x == nd.X {
+			return semtok.TokVariable, nil
+		} else if x == nd.Type {
+			return semtok.TokType, nil
+		}
+	case *ast.ValueSpec:
+		for _, p := range nd.Names {
+			if p == x {
+				return semtok.TokVariable, def
+			}
+		}
+		for _, p := range nd.Values {
+			if p == x {
+				return semtok.TokVariable, nil
+			}
+		}
+		return semtok.TokType, nil
+	case *ast.SelectorExpr: // e.ti.Selections[nd] is nil, so no help
+		if n-1 >= 0 {
+			if ce, ok := tv.stack[n-1].(*ast.CallExpr); ok {
+				// ... CallExpr SelectorExpr Ident (_.x())
+				if ce.Fun == nd && nd.Sel == x {
+					return semtok.TokFunction, nil
+				}
+			}
+		}
+		return semtok.TokVariable, nil
+	case *ast.AssignStmt:
+		for _, p := range nd.Lhs {
+			// x := ..., or x = ...
+			if p == x {
+				if nd.Tok != token.DEFINE {
+					def = nil
+				}
+				return semtok.TokVariable, def // '_' in _ = ...
+			}
+		}
+		// RHS, = x
+		return semtok.TokVariable, nil
+	case *ast.TypeSpec: // it's a type if it is either the Name or the Type
+		if x == nd.Type {
+			def = nil
+		}
+		return semtok.TokType, def
+	case *ast.Field:
+		// ident could be type in a field, or a method in an interface type, or a variable
+		if x == nd.Type {
+			return semtok.TokType, nil
+		}
+		if n-2 >= 0 {
+			_, okit := tv.stack[n-2].(*ast.InterfaceType)
+			_, okfl := tv.stack[n-1].(*ast.FieldList)
+			if okit && okfl {
+				return semtok.TokMethod, def
+			}
+		}
+		return semtok.TokVariable, nil
+	case *ast.LabeledStmt, *ast.BranchStmt:
+		// nothing to report
+	case *ast.CompositeLit:
+		if nd.Type == x {
+			return semtok.TokType, nil
+		}
+		return semtok.TokVariable, nil
+	case *ast.RangeStmt:
+		if nd.Tok != token.DEFINE {
+			def = nil
+		}
+		return semtok.TokVariable, def
+	case *ast.FuncDecl:
+		return semtok.TokFunction, def
+	default:
+		msg := fmt.Sprintf("%T undexpected: %s %s%q", nd, x.Name, tv.strStack(), tv.srcLine(x))
+		tv.unexpected(msg)
+	}
+	return "", nil
+}
+
+func isDeprecated(n *ast.CommentGroup) bool {
+	if n == nil {
+		return false
+	}
+	for _, c := range n.List {
+		if strings.HasPrefix(c.Text, "// Deprecated") {
+			return true
+		}
+	}
+	return false
+}
+
+func (tv *tokenVisitor) definitionFor(x *ast.Ident, def types.Object) (semtok.TokenType, []string) {
+	// PJW: def == types.Label? probably a nothing
+	// PJW: look into replacing these syntactic tests with types more generally
+	mods := []string{"definition"}
+	for i := len(tv.stack) - 1; i >= 0; i-- {
+		s := tv.stack[i]
+		switch y := s.(type) {
+		case *ast.AssignStmt, *ast.RangeStmt:
+			if x.Name == "_" {
+				return "", nil // not really a variable
+			}
+			return semtok.TokVariable, mods
+		case *ast.GenDecl:
+			if isDeprecated(y.Doc) {
+				mods = append(mods, "deprecated")
+			}
+			if y.Tok == token.CONST {
+				mods = append(mods, "readonly")
+			}
+			return semtok.TokVariable, mods
+		case *ast.FuncDecl:
+			// If x is immediately under a FuncDecl, it is a function or method
+			if i == len(tv.stack)-2 {
+				if isDeprecated(y.Doc) {
+					mods = append(mods, "deprecated")
+				}
+				if y.Recv != nil {
+					return semtok.TokMethod, mods
+				}
+				return semtok.TokFunction, mods
+			}
+			// if x < ... < FieldList < FuncDecl, this is the receiver, a variable
+			// PJW: maybe not. it might be a typeparameter in the type of the receiver
+			if _, ok := tv.stack[i+1].(*ast.FieldList); ok {
+				if _, ok := def.(*types.TypeName); ok {
+					return semtok.TokTypeParam, mods
+				}
+				return semtok.TokVariable, nil
+			}
+			// if x < ... < FieldList < FuncType < FuncDecl, this is a param
+			return semtok.TokParameter, mods
+		case *ast.FuncType: // is it in the TypeParams?
+			if isTypeParam(x, y) {
+				return semtok.TokTypeParam, mods
+			}
+			return semtok.TokParameter, mods
+		case *ast.InterfaceType:
+			return semtok.TokMethod, mods
+		case *ast.TypeSpec:
+			// GenDecl/Typespec/FuncType/FieldList/Field/Ident
+			// (type A func(b uint64)) (err error)
+			// b and err should not be semtok.TokType, but semtok.TokVariable
+			// and in GenDecl/TpeSpec/StructType/FieldList/Field/Ident
+			// (type A struct{b uint64}
+			// but on type B struct{C}), C is a type, but is not being defined.
+			// GenDecl/TypeSpec/FieldList/Field/Ident is a typeParam
+			if _, ok := tv.stack[i+1].(*ast.FieldList); ok {
+				return semtok.TokTypeParam, mods
+			}
+			fldm := tv.stack[len(tv.stack)-2]
+			if fld, ok := fldm.(*ast.Field); ok {
+				// if len(fld.names) == 0 this is a semtok.TokType, being used
+				if len(fld.Names) == 0 {
+					return semtok.TokType, nil
+				}
+				return semtok.TokVariable, mods
+			}
+			return semtok.TokType, mods
+		}
+	}
+	// can't happen
+	msg := fmt.Sprintf("failed to find the decl for %s", safetoken.Position(tv.pgf.Tok, x.Pos()))
+	tv.unexpected(msg)
+	return "", []string{""}
+}
+
+func isTypeParam(x *ast.Ident, y *ast.FuncType) bool {
+	tp := y.TypeParams
+	if tp == nil {
+		return false
+	}
+	for _, p := range tp.List {
+		for _, n := range p.Names {
+			if x == n {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+func (tv *tokenVisitor) multiline(start, end token.Pos, val string, tok semtok.TokenType) {
+	f := tv.fset.File(start)
+	// the hard part is finding the lengths of lines. include the \n
+	leng := func(line int) int {
+		n := f.LineStart(line)
+		if line >= f.LineCount() {
+			return f.Size() - int(n)
+		}
+		return int(f.LineStart(line+1) - n)
+	}
+	spos := safetoken.StartPosition(tv.fset, start)
+	epos := safetoken.EndPosition(tv.fset, end)
+	sline := spos.Line
+	eline := epos.Line
+	// first line is from spos.Column to end
+	tv.token(start, leng(sline)-spos.Column, tok, nil) // leng(sline)-1 - (spos.Column-1)
+	for i := sline + 1; i < eline; i++ {
+		// intermediate lines are from 1 to end
+		tv.token(f.LineStart(i), leng(i)-1, tok, nil) // avoid the newline
+	}
+	// last line is from 1 to epos.Column
+	tv.token(f.LineStart(eline), epos.Column-1, tok, nil) // columns are 1-based
+}
+
+// findKeyword finds a keyword rather than guessing its location
+func (tv *tokenVisitor) findKeyword(keyword string, start, end token.Pos) token.Pos {
+	offset := int(start) - tv.pgf.Tok.Base()
+	last := int(end) - tv.pgf.Tok.Base()
+	buf := tv.pgf.Src
+	idx := bytes.Index(buf[offset:last], []byte(keyword))
+	if idx != -1 {
+		return start + token.Pos(idx)
+	}
+	//(in unparsable programs: type _ <-<-chan int)
+	tv.unexpected(fmt.Sprintf("not found:%s %v", keyword, safetoken.StartPosition(tv.fset, start)))
+	return token.NoPos
+}
+
+func (tv *tokenVisitor) importSpec(d *ast.ImportSpec) {
+	// a local package name or the last component of the Path
+	if d.Name != nil {
+		nm := d.Name.String()
+		if nm != "_" && nm != "." {
+			tv.token(d.Name.Pos(), len(nm), semtok.TokNamespace, nil)
+		}
+		return // don't mark anything for . or _
+	}
+	importPath := metadata.UnquoteImportPath(d)
+	if importPath == "" {
+		return
+	}
+	// Import strings are implementation defined. Try to match with parse information.
+	depID := tv.pkg.Metadata().DepsByImpPath[importPath]
+	if depID == "" {
+		return
+	}
+	depMD := tv.metadataSource.Metadata(depID)
+	if depMD == nil {
+		// unexpected, but impact is that maybe some import is not colored
+		return
+	}
+	// Check whether the original literal contains the package's declared name.
+	j := strings.LastIndex(d.Path.Value, string(depMD.Name))
+	if j == -1 {
+		// Package name does not match import path, so there is nothing to report.
+		return
+	}
+	// Report virtual declaration at the position of the substring.
+	start := d.Path.Pos() + token.Pos(j)
+	tv.token(start, len(depMD.Name), semtok.TokNamespace, nil)
+}
+
+// log unexpected state
+func (tv *tokenVisitor) unexpected(msg string) {
+	if semDebug {
+		panic(msg)
+	}
+	event.Error(tv.ctx, tv.strStack(), errors.New(msg))
+}
+
+var godirectives = map[string]struct{}{
+	// https://pkg.go.dev/cmd/compile
+	"noescape":       {},
+	"uintptrescapes": {},
+	"noinline":       {},
+	"norace":         {},
+	"nosplit":        {},
+	"linkname":       {},
+
+	// https://pkg.go.dev/go/build
+	"build":               {},
+	"binary-only-package": {},
+	"embed":               {},
+}
+
+// Tokenize godirective at the start of the comment c, if any, and the surrounding comment.
+// If there is any failure, emits the entire comment as a TokComment token.
+// Directives are highlighted as-is, even if used incorrectly. Typically there are
+// dedicated analyzers that will warn about misuse.
+func (tv *tokenVisitor) godirective(c *ast.Comment) {
+	// First check if '//go:directive args...' is a valid directive.
+	directive, args, _ := strings.Cut(c.Text, " ")
+	kind, _ := stringsCutPrefix(directive, "//go:")
+	if _, ok := godirectives[kind]; !ok {
+		// Unknown go: directive.
+		tv.token(c.Pos(), len(c.Text), semtok.TokComment, nil)
+		return
+	}
+
+	// Make the 'go:directive' part stand out, the rest is comments.
+	tv.token(c.Pos(), len("//"), semtok.TokComment, nil)
+
+	directiveStart := c.Pos() + token.Pos(len("//"))
+	tv.token(directiveStart, len(directive[len("//"):]), semtok.TokNamespace, nil)
+
+	if len(args) > 0 {
+		tailStart := c.Pos() + token.Pos(len(directive)+len(" "))
+		tv.token(tailStart, len(args), semtok.TokComment, nil)
+	}
+}
+
+// Go 1.20 strings.CutPrefix.
+func stringsCutPrefix(s, prefix string) (after string, found bool) {
+	if !strings.HasPrefix(s, prefix) {
+		return s, false
+	}
+	return s[len(prefix):], true
+}
diff --git a/gopls/internal/lsp/source/signature_help.go b/gopls/internal/golang/signature_help.go
similarity index 95%
rename from gopls/internal/lsp/source/signature_help.go
rename to gopls/internal/golang/signature_help.go
index 4234bc4..0da1651 100644
--- a/gopls/internal/lsp/source/signature_help.go
+++ b/gopls/internal/golang/signature_help.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -13,16 +13,17 @@
 	"strings"
 
 	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/util/bug"
+	"golang.org/x/tools/gopls/internal/util/typesutil"
 	"golang.org/x/tools/internal/event"
 )
 
 func SignatureHelp(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, position protocol.Position) (*protocol.SignatureInformation, int, error) {
-	ctx, done := event.Start(ctx, "source.SignatureHelp")
+	ctx, done := event.Start(ctx, "golang.SignatureHelp")
 	defer done()
 
 	// We need full type-checking here, as we must type-check function bodies in
@@ -78,7 +79,7 @@
 	}
 	// Inv: sig != nil
 
-	qf := Qualifier(pgf.File, pkg.GetTypes(), info)
+	qf := typesutil.FileQualifier(pgf.File, pkg.GetTypes(), info)
 
 	// Get the object representing the function, if available.
 	// There is no object in certain cases such as calling a function returned by
diff --git a/gopls/internal/lsp/source/snapshot.go b/gopls/internal/golang/snapshot.go
similarity index 84%
rename from gopls/internal/lsp/source/snapshot.go
rename to gopls/internal/golang/snapshot.go
index 72e7d59..adcbfb9 100644
--- a/gopls/internal/lsp/source/snapshot.go
+++ b/gopls/internal/golang/snapshot.go
@@ -2,17 +2,16 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // NarrowestMetadataForFile returns metadata for the narrowest package
@@ -89,16 +88,6 @@
 	return pkg, pgf, err
 }
 
-// A FileSource maps URIs to FileHandles.
-type FileSource interface {
-	// ReadFile returns the FileHandle for a given URI, either by
-	// reading the content of the file or by obtaining it from a cache.
-	//
-	// Invariant: ReadFile must only return an error in the case of context
-	// cancellation. If ctx.Err() is nil, the resulting error must also be nil.
-	ReadFile(ctx context.Context, uri protocol.DocumentURI) (file.Handle, error)
-}
-
 type ParsedGoFile = parsego.File
 
 const (
diff --git a/gopls/internal/lsp/source/stub.go b/gopls/internal/golang/stub.go
similarity index 76%
rename from gopls/internal/lsp/source/stub.go
rename to gopls/internal/golang/stub.go
index ac30aec..6a68ed2 100644
--- a/gopls/internal/lsp/source/stub.go
+++ b/gopls/internal/golang/stub.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"bytes"
@@ -13,15 +13,15 @@
 	"go/token"
 	"go/types"
 	"io"
-	"path"
+	pathpkg "path"
 	"strings"
 
 	"golang.org/x/tools/go/analysis"
 	"golang.org/x/tools/go/ast/astutil"
 	"golang.org/x/tools/gopls/internal/analysis/stubmethods"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/diff"
@@ -56,23 +56,11 @@
 		return nil, nil, fmt.Errorf("file contains parse errors: %s", declPGF.URI)
 	}
 
-	// Build import environment for the declaring file.
-	importEnv := make(map[ImportPath]string) // value is local name
-	for _, imp := range declPGF.File.Imports {
-		importPath := metadata.UnquoteImportPath(imp)
-		var name string
-		if imp.Name != nil {
-			name = imp.Name.Name
-			if name == "_" {
-				continue
-			} else if name == "." {
-				name = "" // see types.Qualifier
-			}
-		} else {
-			// TODO(adonovan): may omit a vendor/ prefix; consult the Metadata.
-			name = path.Base(string(importPath))
-		}
-		importEnv[importPath] = name // latest alias wins
+	// Find metadata for the concrete type's declaring package
+	// as we'll need its import mapping.
+	declMeta := findFileInDeps(snapshot, pkg.Metadata(), declPGF.URI)
+	if declMeta == nil {
+		return nil, nil, bug.Errorf("can't find metadata for file %s among dependencies of %s", declPGF.URI, pkg)
 	}
 
 	// Record all direct methods of the current object
@@ -134,10 +122,36 @@
 		return nil, nil, fmt.Errorf("no missing methods found")
 	}
 
+	// Build import environment for the declaring file.
+	// (typesutil.FileQualifier works only for complete
+	// import mappings, and requires types.)
+	importEnv := make(map[ImportPath]string) // value is local name
+	for _, imp := range declPGF.File.Imports {
+		importPath := metadata.UnquoteImportPath(imp)
+		var name string
+		if imp.Name != nil {
+			name = imp.Name.Name
+			if name == "_" {
+				continue
+			} else if name == "." {
+				name = "" // see types.Qualifier
+			}
+		} else {
+			// Use the correct name from the metadata of the imported
+			// package---not a guess based on the import path.
+			mp := snapshot.Metadata(declMeta.DepsByImpPath[importPath])
+			if mp == nil {
+				continue // can't happen?
+			}
+			name = string(mp.Name)
+		}
+		importEnv[importPath] = name // latest alias wins
+	}
+
 	// Create a package name qualifier that uses the
 	// locally appropriate imported package name.
 	// It records any needed new imports.
-	// TODO(adonovan): factor with source.FormatVarType, stubmethods.RelativeToFiles?
+	// TODO(adonovan): factor with golang.FormatVarType?
 	//
 	// Prior to CL 469155 this logic preserved any renaming
 	// imports from the file that declares the interface
@@ -170,7 +184,7 @@
 			new := newImport{importPath: string(importPath)}
 			// For clarity, use a renaming import whenever the
 			// local name does not match the path's last segment.
-			if name != path.Base(new.importPath) {
+			if name != pathpkg.Base(trimVersionSuffix(new.importPath)) {
 				new.name = name
 			}
 			newImports = append(newImports, new)
@@ -190,17 +204,46 @@
 		star = "*"
 	}
 
+	// If there are any that have named receiver, choose the first one.
+	// Otherwise, use lowercase for the first letter of the object.
+	rn := strings.ToLower(si.Concrete.Obj().Name()[0:1])
+	for i := 0; i < si.Concrete.NumMethods(); i++ {
+		if recv, ok := si.Concrete.Method(i).Type().(*types.Signature); ok && recv.Recv().Name() != "" {
+			rn = recv.Recv().Name()
+			break
+		}
+	}
+
+	// Check for receiver name conflicts
+	checkRecvName := func(tuple *types.Tuple) bool {
+		for i := 0; i < tuple.Len(); i++ {
+			if rn == tuple.At(i).Name() {
+				return true
+			}
+		}
+		return false
+	}
+
 	// Format the new methods.
 	var newMethods bytes.Buffer
+
 	for index := range missing {
+		mrn := rn + " "
+		if sig, ok := missing[index].fn.Type().(*types.Signature); ok {
+			if checkRecvName(sig.Params()) || checkRecvName(sig.Results()) {
+				mrn = ""
+			}
+		}
+
 		fmt.Fprintf(&newMethods, `// %s implements %s.
-%sfunc (%s%s%s) %s%s {
+%sfunc (%s%s%s%s) %s%s {
 	panic("unimplemented")
 }
 `,
 			missing[index].fn.Name(),
 			iface,
 			missing[index].needSubtle,
+			mrn,
 			star,
 			si.Concrete.Obj().Name(),
 			FormatTypeParams(si.Concrete.TypeParams()),
@@ -239,7 +282,7 @@
 
 	// Re-parse the file.
 	fset := token.NewFileSet()
-	newF, err := parser.ParseFile(fset, declPGF.File.Name.Name, buf.Bytes(), parser.ParseComments)
+	newF, err := parser.ParseFile(fset, declPGF.URI.Path(), buf.Bytes(), parser.ParseComments)
 	if err != nil {
 		return nil, nil, fmt.Errorf("could not reparse file: %w", err)
 	}
@@ -274,3 +317,19 @@
 	}
 	return edits
 }
+
+// trimVersionSuffix removes a trailing "/v2" (etc) suffix from a module path.
+//
+// This is only a heuristic as to the package's declared name, and
+// should only be used for stylistic decisions, such as whether it
+// would be clearer to use an explicit local name in the import
+// because the declared name differs from the result of this function.
+// When the name matters for correctness, look up the imported
+// package's Metadata.Name.
+func trimVersionSuffix(path string) string {
+	dir, base := pathpkg.Split(path)
+	if len(base) > 1 && base[0] == 'v' && strings.Trim(base[1:], "0123456789") == "" {
+		return dir // sans "/v2"
+	}
+	return path
+}
diff --git a/gopls/internal/lsp/source/symbols.go b/gopls/internal/golang/symbols.go
similarity index 97%
rename from gopls/internal/lsp/source/symbols.go
rename to gopls/internal/golang/symbols.go
index 6768118..390b827 100644
--- a/gopls/internal/lsp/source/symbols.go
+++ b/gopls/internal/golang/symbols.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -11,14 +11,14 @@
 	"go/token"
 	"go/types"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 )
 
 func DocumentSymbols(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.DocumentSymbol, error) {
-	ctx, done := event.Start(ctx, "source.DocumentSymbols")
+	ctx, done := event.Start(ctx, "golang.DocumentSymbols")
 	defer done()
 
 	pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
diff --git a/gopls/internal/lsp/source/type_definition.go b/gopls/internal/golang/type_definition.go
similarity index 90%
rename from gopls/internal/lsp/source/type_definition.go
rename to gopls/internal/golang/type_definition.go
index c530344..306852c 100644
--- a/gopls/internal/lsp/source/type_definition.go
+++ b/gopls/internal/golang/type_definition.go
@@ -2,23 +2,23 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
 	"fmt"
 	"go/token"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/internal/event"
 )
 
 // TypeDefinition handles the textDocument/typeDefinition request for Go files.
 func TypeDefinition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, position protocol.Position) ([]protocol.Location, error) {
-	ctx, done := event.Start(ctx, "source.TypeDefinition")
+	ctx, done := event.Start(ctx, "golang.TypeDefinition")
 	defer done()
 
 	pkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())
diff --git a/gopls/internal/lsp/source/types_format.go b/gopls/internal/golang/types_format.go
similarity index 98%
rename from gopls/internal/lsp/source/types_format.go
rename to gopls/internal/golang/types_format.go
index b6306b9..428e37f 100644
--- a/gopls/internal/lsp/source/types_format.go
+++ b/gopls/internal/golang/types_format.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"bytes"
@@ -15,8 +15,8 @@
 	"go/types"
 	"strings"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/internal/event"
diff --git a/gopls/internal/lsp/source/util.go b/gopls/internal/golang/util.go
similarity index 91%
rename from gopls/internal/lsp/source/util.go
rename to gopls/internal/golang/util.go
index 66a4856..d6e71a9 100644
--- a/gopls/internal/lsp/source/util.go
+++ b/gopls/internal/golang/util.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -13,13 +13,12 @@
 	"regexp"
 	"strings"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/astutil"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
-	"golang.org/x/tools/gopls/internal/util/typesutil"
 	"golang.org/x/tools/internal/tokeninternal"
 )
 
@@ -139,8 +138,6 @@
 
 // findFileInDeps finds package metadata containing URI in the transitive
 // dependencies of m. When using the Go command, the answer is unique.
-//
-// TODO(rfindley): refactor to share logic with findPackageInDeps?
 func findFileInDeps(s metadata.Source, mp *metadata.Package, uri protocol.DocumentURI) *metadata.Package {
 	seen := make(map[PackageID]bool)
 	var search func(*metadata.Package) *metadata.Package
@@ -191,31 +188,6 @@
 	return scopes
 }
 
-// Qualifier returns a function that appropriately formats a types.PkgName
-// appearing in a *ast.File.
-func Qualifier(f *ast.File, pkg *types.Package, info *types.Info) types.Qualifier {
-	// Construct mapping of import paths to their defined or implicit names.
-	imports := make(map[*types.Package]string)
-	for _, imp := range f.Imports {
-		if pkgname, ok := typesutil.ImportedPkgName(info, imp); ok {
-			imports[pkgname.Imported()] = pkgname.Name()
-		}
-	}
-	// Define qualifier to replace full package paths with names of the imports.
-	return func(p *types.Package) string {
-		if p == pkg {
-			return ""
-		}
-		if name, ok := imports[p]; ok {
-			if name == "." {
-				return ""
-			}
-			return name
-		}
-		return p.Name()
-	}
-}
-
 // requalifier returns a function that re-qualifies identifiers and qualified
 // identifiers contained in targetFile using the given metadata qualifier.
 func requalifier(s metadata.Source, targetFile *ast.File, targetMeta *metadata.Package, mq MetadataQualifier) func(string) string {
diff --git a/gopls/internal/lsp/source/workspace_symbol.go b/gopls/internal/golang/workspace_symbol.go
similarity index 98%
rename from gopls/internal/lsp/source/workspace_symbol.go
rename to gopls/internal/golang/workspace_symbol.go
index ccd6512..4ab5a21 100644
--- a/gopls/internal/lsp/source/workspace_symbol.go
+++ b/gopls/internal/golang/workspace_symbol.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"context"
@@ -13,9 +13,9 @@
 	"strings"
 	"unicode"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/fuzzy"
@@ -43,7 +43,7 @@
 // Session level configuration will define the SymbolMatcher to be used for the
 // WorkspaceSymbols method.
 func WorkspaceSymbols(ctx context.Context, matcher settings.SymbolMatcher, style settings.SymbolStyle, snapshots []*cache.Snapshot, query string) ([]protocol.SymbolInformation, error) {
-	ctx, done := event.Start(ctx, "source.WorkspaceSymbols")
+	ctx, done := event.Start(ctx, "golang.WorkspaceSymbols")
 	defer done()
 	if query == "" {
 		return nil, nil
diff --git a/gopls/internal/lsp/source/workspace_symbol_test.go b/gopls/internal/golang/workspace_symbol_test.go
similarity index 97%
rename from gopls/internal/lsp/source/workspace_symbol_test.go
rename to gopls/internal/golang/workspace_symbol_test.go
index b102a23..4982b76 100644
--- a/gopls/internal/lsp/source/workspace_symbol_test.go
+++ b/gopls/internal/golang/workspace_symbol_test.go
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package source
+package golang
 
 import (
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
+	"golang.org/x/tools/gopls/internal/cache"
 )
 
 func TestParseQuery(t *testing.T) {
diff --git a/gopls/internal/hooks/analysis_119.go b/gopls/internal/hooks/analysis_119.go
index 34c6b93..8fc7b46 100644
--- a/gopls/internal/hooks/analysis_119.go
+++ b/gopls/internal/hooks/analysis_119.go
@@ -1,62 +1,14 @@
-// Copyright 2019 The Go Authors. All rights reserved.
+// Copyright 2021 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build go1.19
-// +build go1.19
+//go:build !go1.20
+// +build !go1.20
 
 package hooks
 
-import (
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/settings"
-	"honnef.co/go/tools/analysis/lint"
-	"honnef.co/go/tools/quickfix"
-	"honnef.co/go/tools/simple"
-	"honnef.co/go/tools/staticcheck"
-	"honnef.co/go/tools/stylecheck"
-)
+import "golang.org/x/tools/gopls/internal/settings"
 
 func updateAnalyzers(options *settings.Options) {
-	options.StaticcheckSupported = true
-
-	mapSeverity := func(severity lint.Severity) protocol.DiagnosticSeverity {
-		switch severity {
-		case lint.SeverityError:
-			return protocol.SeverityError
-		case lint.SeverityDeprecated:
-			// TODO(dh): in LSP, deprecated is a tag, not a severity.
-			//   We'll want to support this once we enable SA5011.
-			return protocol.SeverityWarning
-		case lint.SeverityWarning:
-			return protocol.SeverityWarning
-		case lint.SeverityInfo:
-			return protocol.SeverityInformation
-		case lint.SeverityHint:
-			return protocol.SeverityHint
-		default:
-			return protocol.SeverityWarning
-		}
-	}
-	add := func(analyzers []*lint.Analyzer, skip map[string]struct{}) {
-		for _, a := range analyzers {
-			if _, ok := skip[a.Analyzer.Name]; ok {
-				continue
-			}
-
-			enabled := !a.Doc.NonDefault
-			options.AddStaticcheckAnalyzer(a.Analyzer, enabled, mapSeverity(a.Doc.Severity))
-		}
-	}
-
-	add(simple.Analyzers, nil)
-	add(staticcheck.Analyzers, map[string]struct{}{
-		// This check conflicts with the vet printf check (golang/go#34494).
-		"SA5009": {},
-		// This check relies on facts from dependencies, which
-		// we don't currently compute.
-		"SA5011": {},
-	})
-	add(stylecheck.Analyzers, nil)
-	add(quickfix.Analyzers, nil)
+	options.StaticcheckSupported = false
 }
diff --git a/gopls/internal/hooks/analysis_120.go b/gopls/internal/hooks/analysis_120.go
new file mode 100644
index 0000000..cded05e
--- /dev/null
+++ b/gopls/internal/hooks/analysis_120.go
@@ -0,0 +1,62 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.20
+// +build go1.20
+
+package hooks
+
+import (
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/settings"
+	"honnef.co/go/tools/analysis/lint"
+	"honnef.co/go/tools/quickfix"
+	"honnef.co/go/tools/simple"
+	"honnef.co/go/tools/staticcheck"
+	"honnef.co/go/tools/stylecheck"
+)
+
+func updateAnalyzers(options *settings.Options) {
+	options.StaticcheckSupported = true
+
+	mapSeverity := func(severity lint.Severity) protocol.DiagnosticSeverity {
+		switch severity {
+		case lint.SeverityError:
+			return protocol.SeverityError
+		case lint.SeverityDeprecated:
+			// TODO(dh): in LSP, deprecated is a tag, not a severity.
+			//   We'll want to support this once we enable SA5011.
+			return protocol.SeverityWarning
+		case lint.SeverityWarning:
+			return protocol.SeverityWarning
+		case lint.SeverityInfo:
+			return protocol.SeverityInformation
+		case lint.SeverityHint:
+			return protocol.SeverityHint
+		default:
+			return protocol.SeverityWarning
+		}
+	}
+	add := func(analyzers []*lint.Analyzer, skip map[string]struct{}) {
+		for _, a := range analyzers {
+			if _, ok := skip[a.Analyzer.Name]; ok {
+				continue
+			}
+
+			enabled := !a.Doc.NonDefault
+			options.AddStaticcheckAnalyzer(a.Analyzer, enabled, mapSeverity(a.Doc.Severity))
+		}
+	}
+
+	add(simple.Analyzers, nil)
+	add(staticcheck.Analyzers, map[string]struct{}{
+		// This check conflicts with the vet printf check (golang/go#34494).
+		"SA5009": {},
+		// This check relies on facts from dependencies, which
+		// we don't currently compute.
+		"SA5011": {},
+	})
+	add(stylecheck.Analyzers, nil)
+	add(quickfix.Analyzers, nil)
+}
diff --git a/gopls/internal/hooks/gofumpt_117.go b/gopls/internal/hooks/gofumpt_117.go
deleted file mode 100644
index 7188635..0000000
--- a/gopls/internal/hooks/gofumpt_117.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.18
-// +build !go1.18
-
-package hooks
-
-import "golang.org/x/tools/gopls/internal/lsp/source"
-
-func updateGofumpt(options *source.Options) {
-}
diff --git a/gopls/internal/hooks/analysis_116.go b/gopls/internal/hooks/gofumpt_119.go
similarity index 64%
rename from gopls/internal/hooks/analysis_116.go
rename to gopls/internal/hooks/gofumpt_119.go
index 4ac32f3..d5bc987 100644
--- a/gopls/internal/hooks/analysis_116.go
+++ b/gopls/internal/hooks/gofumpt_119.go
@@ -2,13 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build !go1.19
-// +build !go1.19
+//go:build !go1.20
+// +build !go1.20
 
 package hooks
 
 import "golang.org/x/tools/gopls/internal/settings"
 
-func updateAnalyzers(options *settings.Options) {
-	options.StaticcheckSupported = false
+func updateGofumpt(options *settings.Options) {
 }
diff --git a/gopls/internal/hooks/gofumpt_118.go b/gopls/internal/hooks/gofumpt_120.go
similarity index 97%
rename from gopls/internal/hooks/gofumpt_118.go
rename to gopls/internal/hooks/gofumpt_120.go
index a81444e..9ac2465 100644
--- a/gopls/internal/hooks/gofumpt_118.go
+++ b/gopls/internal/hooks/gofumpt_120.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build go1.18
-// +build go1.18
+//go:build go1.20
+// +build go1.20
 
 package hooks
 
diff --git a/gopls/internal/hooks/gofumpt_118_test.go b/gopls/internal/hooks/gofumpt_120_test.go
similarity index 97%
rename from gopls/internal/hooks/gofumpt_118_test.go
rename to gopls/internal/hooks/gofumpt_120_test.go
index 838ce73..bb67498 100644
--- a/gopls/internal/hooks/gofumpt_118_test.go
+++ b/gopls/internal/hooks/gofumpt_120_test.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build go1.18
-// +build go1.18
+//go:build go1.20
+// +build go1.20
 
 package hooks
 
diff --git a/gopls/internal/lsp/cache/cache.go b/gopls/internal/lsp/cache/cache.go
deleted file mode 100644
index 72fe36e..0000000
--- a/gopls/internal/lsp/cache/cache.go
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package cache
-
-import (
-	"context"
-	"reflect"
-	"strconv"
-	"sync/atomic"
-	"time"
-
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/internal/event"
-	"golang.org/x/tools/internal/gocommand"
-	"golang.org/x/tools/internal/memoize"
-)
-
-// New Creates a new cache for gopls operation results, using the given file
-// set, shared store, and session options.
-//
-// Both the fset and store may be nil, but if store is non-nil so must be fset
-// (and they must always be used together), otherwise it may be possible to get
-// cached data referencing token.Pos values not mapped by the FileSet.
-func New(store *memoize.Store) *Cache {
-	index := atomic.AddInt64(&cacheIndex, 1)
-
-	if store == nil {
-		store = &memoize.Store{}
-	}
-
-	c := &Cache{
-		id:         strconv.FormatInt(index, 10),
-		store:      store,
-		memoizedFS: newMemoizedFS(),
-	}
-	return c
-}
-
-// A Cache holds caching stores that are bundled together for consistency.
-//
-// TODO(rfindley): once fset and store need not be bundled together, the Cache
-// type can be eliminated.
-type Cache struct {
-	id string
-
-	store *memoize.Store
-
-	*memoizedFS // implements source.FileSource
-}
-
-// NewSession creates a new gopls session with the given cache and options overrides.
-//
-// The provided optionsOverrides may be nil.
-//
-// TODO(rfindley): move this to session.go.
-func NewSession(ctx context.Context, c *Cache) *Session {
-	index := atomic.AddInt64(&sessionIndex, 1)
-	s := &Session{
-		id:          strconv.FormatInt(index, 10),
-		cache:       c,
-		gocmdRunner: &gocommand.Runner{},
-		overlayFS:   newOverlayFS(c),
-		parseCache:  newParseCache(1 * time.Minute), // keep recently parsed files for a minute, to optimize typing CPU
-		viewMap:     make(map[protocol.DocumentURI]*View),
-	}
-	event.Log(ctx, "New session", KeyCreateSession.Of(s))
-	return s
-}
-
-var cacheIndex, sessionIndex, viewIndex int64
-
-func (c *Cache) ID() string                     { return c.id }
-func (c *Cache) MemStats() map[reflect.Type]int { return c.store.Stats() }
-
-// FileStats returns information about the set of files stored in the cache.
-// It is intended for debugging only.
-func (c *Cache) FileStats() (files, largest, errs int) {
-	return c.fileStats()
-}
diff --git a/gopls/internal/lsp/cache/imports.go b/gopls/internal/lsp/cache/imports.go
deleted file mode 100644
index 43df10e..0000000
--- a/gopls/internal/lsp/cache/imports.go
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright 2020 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package cache
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"reflect"
-	"strings"
-	"sync"
-	"time"
-
-	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/internal/event"
-	"golang.org/x/tools/internal/event/keys"
-	"golang.org/x/tools/internal/imports"
-)
-
-type importsState struct {
-	ctx context.Context
-
-	mu                     sync.Mutex
-	processEnv             *imports.ProcessEnv
-	cacheRefreshDuration   time.Duration
-	cacheRefreshTimer      *time.Timer
-	cachedModFileHash      file.Hash
-	cachedBuildFlags       []string
-	cachedDirectoryFilters []string
-}
-
-func (s *importsState) runProcessEnvFunc(ctx context.Context, snapshot *Snapshot, fn func(context.Context, *imports.Options) error) error {
-	ctx, done := event.Start(ctx, "cache.importsState.runProcessEnvFunc")
-	defer done()
-
-	s.mu.Lock()
-	defer s.mu.Unlock()
-
-	// Find the hash of active mod files, if any. Using the unsaved content
-	// is slightly wasteful, since we'll drop caches a little too often, but
-	// the mod file shouldn't be changing while people are autocompleting.
-	//
-	// TODO(rfindley): consider instead hashing on-disk modfiles here.
-	var modFileHash file.Hash
-	for m := range snapshot.view.workspaceModFiles {
-		fh, err := snapshot.ReadFile(ctx, m)
-		if err != nil {
-			return err
-		}
-		modFileHash.XORWith(fh.Identity().Hash)
-	}
-
-	// view.goEnv is immutable -- changes make a new view. Options can change.
-	// We can't compare build flags directly because we may add -modfile.
-	localPrefix := snapshot.Options().Local
-	currentBuildFlags := snapshot.Options().BuildFlags
-	currentDirectoryFilters := snapshot.Options().DirectoryFilters
-	changed := !reflect.DeepEqual(currentBuildFlags, s.cachedBuildFlags) ||
-		snapshot.Options().VerboseOutput != (s.processEnv.Logf != nil) ||
-		modFileHash != s.cachedModFileHash ||
-		!reflect.DeepEqual(snapshot.Options().DirectoryFilters, s.cachedDirectoryFilters)
-
-	// If anything relevant to imports has changed, clear caches and
-	// update the processEnv. Clearing caches blocks on any background
-	// scans.
-	if changed {
-		if err := populateProcessEnvFromSnapshot(ctx, s.processEnv, snapshot); err != nil {
-			return err
-		}
-
-		if resolver, err := s.processEnv.GetResolver(); err == nil {
-			if modResolver, ok := resolver.(*imports.ModuleResolver); ok {
-				modResolver.ClearForNewMod()
-			}
-		}
-
-		s.cachedModFileHash = modFileHash
-		s.cachedBuildFlags = currentBuildFlags
-		s.cachedDirectoryFilters = currentDirectoryFilters
-	}
-
-	// Run the user function.
-	opts := &imports.Options{
-		// Defaults.
-		AllErrors:   true,
-		Comments:    true,
-		Fragment:    true,
-		FormatOnly:  false,
-		TabIndent:   true,
-		TabWidth:    8,
-		Env:         s.processEnv,
-		LocalPrefix: localPrefix,
-	}
-
-	if err := fn(ctx, opts); err != nil {
-		return err
-	}
-
-	if s.cacheRefreshTimer == nil {
-		// Don't refresh more than twice per minute.
-		delay := 30 * time.Second
-		// Don't spend more than a couple percent of the time refreshing.
-		if adaptive := 50 * s.cacheRefreshDuration; adaptive > delay {
-			delay = adaptive
-		}
-		s.cacheRefreshTimer = time.AfterFunc(delay, s.refreshProcessEnv)
-	}
-
-	return nil
-}
-
-// populateProcessEnvFromSnapshot sets the dynamically configurable fields for
-// the view's process environment. Assumes that the caller is holding the
-// importsState mutex.
-func populateProcessEnvFromSnapshot(ctx context.Context, pe *imports.ProcessEnv, snapshot *Snapshot) error {
-	ctx, done := event.Start(ctx, "cache.populateProcessEnvFromSnapshot")
-	defer done()
-
-	if snapshot.Options().VerboseOutput {
-		pe.Logf = func(format string, args ...interface{}) {
-			event.Log(ctx, fmt.Sprintf(format, args...))
-		}
-	} else {
-		pe.Logf = nil
-	}
-
-	pe.WorkingDir = snapshot.view.root.Path()
-	pe.ModFlag = "readonly" // processEnv operations should not mutate the modfile
-	pe.Env = map[string]string{}
-	pe.BuildFlags = append([]string{}, snapshot.Options().BuildFlags...)
-	env := append(append(os.Environ(), snapshot.Options().EnvSlice()...), "GO111MODULE="+snapshot.view.adjustedGO111MODULE())
-	for _, kv := range env {
-		split := strings.SplitN(kv, "=", 2)
-		if len(split) != 2 {
-			continue
-		}
-		pe.Env[split[0]] = split[1]
-	}
-	return nil
-}
-
-func (s *importsState) refreshProcessEnv() {
-	ctx, done := event.Start(s.ctx, "cache.importsState.refreshProcessEnv")
-	defer done()
-
-	start := time.Now()
-
-	s.mu.Lock()
-	env := s.processEnv
-	if resolver, err := s.processEnv.GetResolver(); err == nil {
-		resolver.ClearForNewScan()
-	}
-	s.mu.Unlock()
-
-	event.Log(s.ctx, "background imports cache refresh starting")
-	if err := imports.PrimeCache(context.Background(), env); err == nil {
-		event.Log(ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start)))
-	} else {
-		event.Log(ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start)), keys.Err.Of(err))
-	}
-	s.mu.Lock()
-	s.cacheRefreshDuration = time.Since(start)
-	s.cacheRefreshTimer = nil
-	s.mu.Unlock()
-}
diff --git a/gopls/internal/lsp/cache/workspace.go b/gopls/internal/lsp/cache/workspace.go
deleted file mode 100644
index 9e54289..0000000
--- a/gopls/internal/lsp/cache/workspace.go
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2020 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package cache
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	"io/fs"
-	"path/filepath"
-	"strings"
-
-	"golang.org/x/mod/modfile"
-	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-)
-
-// TODO(rfindley): now that experimentalWorkspaceModule is gone, this file can
-// be massively cleaned up and/or removed.
-
-// goWorkModules returns the URIs of go.mod files named by the go.work file.
-func goWorkModules(ctx context.Context, gowork protocol.DocumentURI, fs file.Source) (map[protocol.DocumentURI]unit, error) {
-	fh, err := fs.ReadFile(ctx, gowork)
-	if err != nil {
-		return nil, err // canceled
-	}
-	content, err := fh.Content()
-	if err != nil {
-		return nil, err
-	}
-	filename := gowork.Path()
-	dir := filepath.Dir(filename)
-	workFile, err := modfile.ParseWork(filename, content, nil)
-	if err != nil {
-		return nil, fmt.Errorf("parsing go.work: %w", err)
-	}
-	modFiles := make(map[protocol.DocumentURI]unit)
-	for _, use := range workFile.Use {
-		modDir := filepath.FromSlash(use.Path)
-		if !filepath.IsAbs(modDir) {
-			modDir = filepath.Join(dir, modDir)
-		}
-		modURI := protocol.URIFromPath(filepath.Join(modDir, "go.mod"))
-		modFiles[modURI] = unit{}
-	}
-	return modFiles, nil
-}
-
-// isGoMod reports if uri is a go.mod file.
-func isGoMod(uri protocol.DocumentURI) bool {
-	return filepath.Base(uri.Path()) == "go.mod"
-}
-
-// isGoWork reports if uri is a go.work file.
-func isGoWork(uri protocol.DocumentURI) bool {
-	return filepath.Base(uri.Path()) == "go.work"
-}
-
-// fileExists reports whether the file has a Content (which may be empty).
-// An overlay exists even if it is not reflected in the file system.
-func fileExists(fh file.Handle) bool {
-	_, err := fh.Content()
-	return err == nil
-}
-
-// errExhausted is returned by findModules if the file scan limit is reached.
-var errExhausted = errors.New("exhausted")
-
-// Limit go.mod search to 1 million files. As a point of reference,
-// Kubernetes has 22K files (as of 2020-11-24).
-//
-// Note: per golang/go#56496, the previous limit of 1M files was too slow, at
-// which point this limit was decreased to 100K.
-const fileLimit = 100_000
-
-// findModules recursively walks the root directory looking for go.mod files,
-// returning the set of modules it discovers. If modLimit is non-zero,
-// searching stops once modLimit modules have been found.
-//
-// TODO(rfindley): consider overlays.
-func findModules(root protocol.DocumentURI, excludePath func(string) bool, modLimit int) (map[protocol.DocumentURI]struct{}, error) {
-	// Walk the view's folder to find all modules in the view.
-	modFiles := make(map[protocol.DocumentURI]struct{})
-	searched := 0
-	errDone := errors.New("done")
-	err := filepath.WalkDir(root.Path(), func(path string, info fs.DirEntry, err error) error {
-		if err != nil {
-			// Probably a permission error. Keep looking.
-			return filepath.SkipDir
-		}
-		// For any path that is not the workspace folder, check if the path
-		// would be ignored by the go command. Vendor directories also do not
-		// contain workspace modules.
-		if info.IsDir() && path != root.Path() {
-			suffix := strings.TrimPrefix(path, root.Path())
-			switch {
-			case checkIgnored(suffix),
-				strings.Contains(filepath.ToSlash(suffix), "/vendor/"),
-				excludePath(suffix):
-				return filepath.SkipDir
-			}
-		}
-		// We're only interested in go.mod files.
-		uri := protocol.URIFromPath(path)
-		if isGoMod(uri) {
-			modFiles[uri] = struct{}{}
-		}
-		if modLimit > 0 && len(modFiles) >= modLimit {
-			return errDone
-		}
-		searched++
-		if fileLimit > 0 && searched >= fileLimit {
-			return errExhausted
-		}
-		return nil
-	})
-	if err == errDone {
-		return modFiles, nil
-	}
-	return modFiles, err
-}
diff --git a/gopls/internal/lsp/lsprpc/commandinterceptor.go b/gopls/internal/lsp/lsprpc/commandinterceptor.go
deleted file mode 100644
index 607ee9c..0000000
--- a/gopls/internal/lsp/lsprpc/commandinterceptor.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package lsprpc
-
-import (
-	"context"
-	"encoding/json"
-
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
-)
-
-// HandlerMiddleware is a middleware that only modifies the jsonrpc2 handler.
-type HandlerMiddleware func(jsonrpc2_v2.Handler) jsonrpc2_v2.Handler
-
-// BindHandler transforms a HandlerMiddleware into a Middleware.
-func BindHandler(hmw HandlerMiddleware) Middleware {
-	return Middleware(func(binder jsonrpc2_v2.Binder) jsonrpc2_v2.Binder {
-		return BinderFunc(func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
-			opts := binder.Bind(ctx, conn)
-			opts.Handler = hmw(opts.Handler)
-			return opts
-		})
-	})
-}
-
-func CommandInterceptor(command string, run func(*protocol.ExecuteCommandParams) (interface{}, error)) Middleware {
-	return BindHandler(func(delegate jsonrpc2_v2.Handler) jsonrpc2_v2.Handler {
-		return jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
-			if req.Method == "workspace/executeCommand" {
-				var params protocol.ExecuteCommandParams
-				if err := json.Unmarshal(req.Params, &params); err == nil {
-					if params.Command == command {
-						return run(&params)
-					}
-				}
-			}
-
-			return delegate.Handle(ctx, req)
-		})
-	})
-}
diff --git a/gopls/internal/lsp/lsprpc/commandinterceptor_test.go b/gopls/internal/lsp/lsprpc/commandinterceptor_test.go
deleted file mode 100644
index 555f151..0000000
--- a/gopls/internal/lsp/lsprpc/commandinterceptor_test.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package lsprpc_test
-
-import (
-	"context"
-	"testing"
-
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-
-	. "golang.org/x/tools/gopls/internal/lsp/lsprpc"
-)
-
-func TestCommandInterceptor(t *testing.T) {
-	const command = "foo"
-	caught := false
-	intercept := func(_ *protocol.ExecuteCommandParams) (interface{}, error) {
-		caught = true
-		return map[string]interface{}{}, nil
-	}
-
-	ctx := context.Background()
-	env := new(TestEnv)
-	defer env.Shutdown(t)
-	mw := CommandInterceptor(command, intercept)
-	l, _ := env.serve(ctx, t, mw(noopBinder))
-	conn := env.dial(ctx, t, l.Dialer(), noopBinder, false)
-
-	params := &protocol.ExecuteCommandParams{
-		Command: command,
-	}
-	var res interface{}
-	err := conn.Call(ctx, "workspace/executeCommand", params).Await(ctx, &res)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !caught {
-		t.Errorf("workspace/executeCommand was not intercepted")
-	}
-}
diff --git a/gopls/internal/lsp/lsprpc/goenv.go b/gopls/internal/lsp/lsprpc/goenv.go
deleted file mode 100644
index b771784..0000000
--- a/gopls/internal/lsp/lsprpc/goenv.go
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package lsprpc
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"os"
-
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/internal/event"
-	"golang.org/x/tools/internal/gocommand"
-	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
-)
-
-func GoEnvMiddleware() (Middleware, error) {
-	return BindHandler(func(delegate jsonrpc2_v2.Handler) jsonrpc2_v2.Handler {
-		return jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
-			if req.Method == "initialize" {
-				if err := addGoEnvToInitializeRequestV2(ctx, req); err != nil {
-					event.Error(ctx, "adding go env to initialize", err)
-				}
-			}
-			return delegate.Handle(ctx, req)
-		})
-	}), nil
-}
-
-func addGoEnvToInitializeRequestV2(ctx context.Context, req *jsonrpc2_v2.Request) error {
-	var params protocol.ParamInitialize
-	if err := json.Unmarshal(req.Params, &params); err != nil {
-		return err
-	}
-	var opts map[string]interface{}
-	switch v := params.InitializationOptions.(type) {
-	case nil:
-		opts = make(map[string]interface{})
-	case map[string]interface{}:
-		opts = v
-	default:
-		return fmt.Errorf("unexpected type for InitializationOptions: %T", v)
-	}
-	envOpt, ok := opts["env"]
-	if !ok {
-		envOpt = make(map[string]interface{})
-	}
-	env, ok := envOpt.(map[string]interface{})
-	if !ok {
-		return fmt.Errorf("env option is %T, expected a map", envOpt)
-	}
-	goenv, err := getGoEnv(ctx, env)
-	if err != nil {
-		return err
-	}
-	// We don't want to propagate GOWORK unless explicitly set since that could mess with
-	// path inference during cmd/go invocations, see golang/go#51825.
-	_, goworkSet := os.LookupEnv("GOWORK")
-	for govar, value := range goenv {
-		if govar == "GOWORK" && !goworkSet {
-			continue
-		}
-		env[govar] = value
-	}
-	opts["env"] = env
-	params.InitializationOptions = opts
-	raw, err := json.Marshal(params)
-	if err != nil {
-		return fmt.Errorf("marshaling updated options: %v", err)
-	}
-	req.Params = json.RawMessage(raw)
-	return nil
-}
-
-func getGoEnv(ctx context.Context, env map[string]interface{}) (map[string]string, error) {
-	var runEnv []string
-	for k, v := range env {
-		runEnv = append(runEnv, fmt.Sprintf("%s=%s", k, v))
-	}
-	runner := gocommand.Runner{}
-	output, err := runner.Run(ctx, gocommand.Invocation{
-		Verb: "env",
-		Args: []string{"-json"},
-		Env:  runEnv,
-	})
-	if err != nil {
-		return nil, err
-	}
-	envmap := make(map[string]string)
-	if err := json.Unmarshal(output.Bytes(), &envmap); err != nil {
-		return nil, err
-	}
-	return envmap, nil
-}
diff --git a/gopls/internal/lsp/lsprpc/goenv_test.go b/gopls/internal/lsp/lsprpc/goenv_test.go
deleted file mode 100644
index 3030ef3..0000000
--- a/gopls/internal/lsp/lsprpc/goenv_test.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package lsprpc_test
-
-import (
-	"context"
-	"testing"
-
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/internal/testenv"
-
-	. "golang.org/x/tools/gopls/internal/lsp/lsprpc"
-)
-
-type initServer struct {
-	protocol.Server
-
-	params *protocol.ParamInitialize
-}
-
-func (s *initServer) Initialize(ctx context.Context, params *protocol.ParamInitialize) (*protocol.InitializeResult, error) {
-	s.params = params
-	return &protocol.InitializeResult{}, nil
-}
-
-func TestGoEnvMiddleware(t *testing.T) {
-	testenv.NeedsTool(t, "go")
-
-	ctx := context.Background()
-
-	server := &initServer{}
-	env := new(TestEnv)
-	defer env.Shutdown(t)
-	l, _ := env.serve(ctx, t, staticServerBinder(server))
-	mw, err := GoEnvMiddleware()
-	if err != nil {
-		t.Fatal(err)
-	}
-	binder := mw(NewForwardBinder(l.Dialer()))
-	l, _ = env.serve(ctx, t, binder)
-	conn := env.dial(ctx, t, l.Dialer(), noopBinder, true)
-	dispatch := protocol.ServerDispatcherV2(conn)
-	initParams := &protocol.ParamInitialize{}
-	initParams.InitializationOptions = map[string]interface{}{
-		"env": map[string]interface{}{
-			"GONOPROXY": "example.com",
-		},
-	}
-	if _, err := dispatch.Initialize(ctx, initParams); err != nil {
-		t.Fatal(err)
-	}
-
-	if server.params == nil {
-		t.Fatalf("initialize params are unset")
-	}
-	envOpts := server.params.InitializationOptions.(map[string]interface{})["env"].(map[string]interface{})
-
-	// Check for an arbitrary Go variable. It should be set.
-	if _, ok := envOpts["GOPRIVATE"]; !ok {
-		t.Errorf("Go environment variable GOPRIVATE unset in initialization options")
-	}
-	// Check that the variable present in our user config was not overwritten.
-	if got, want := envOpts["GONOPROXY"], "example.com"; got != want {
-		t.Errorf("GONOPROXY=%q, want %q", got, want)
-	}
-}
diff --git a/gopls/internal/lsp/lsprpc/middleware.go b/gopls/internal/lsp/lsprpc/middleware.go
deleted file mode 100644
index 50089cd..0000000
--- a/gopls/internal/lsp/lsprpc/middleware.go
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package lsprpc
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"sync"
-
-	"golang.org/x/tools/internal/event"
-	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
-)
-
-// Metadata holds arbitrary data transferred between jsonrpc2 peers.
-type Metadata map[string]interface{}
-
-// PeerInfo holds information about a peering between jsonrpc2 servers.
-type PeerInfo struct {
-	// RemoteID is the identity of the current server on its peer.
-	RemoteID int64
-
-	// LocalID is the identity of the peer on the server.
-	LocalID int64
-
-	// IsClient reports whether the peer is a client. If false, the peer is a
-	// server.
-	IsClient bool
-
-	// Metadata holds arbitrary information provided by the peer.
-	Metadata Metadata
-}
-
-// Handshaker handles both server and client handshaking over jsonrpc2. To
-// instrument server-side handshaking, use Handshaker.Middleware. To instrument
-// client-side handshaking, call Handshaker.ClientHandshake for any new
-// client-side connections.
-type Handshaker struct {
-	// Metadata will be shared with peers via handshaking.
-	Metadata Metadata
-
-	mu     sync.Mutex
-	prevID int64
-	peers  map[int64]PeerInfo
-}
-
-// Peers returns the peer info this handshaker knows about by way of either the
-// server-side handshake middleware, or client-side handshakes.
-func (h *Handshaker) Peers() []PeerInfo {
-	h.mu.Lock()
-	defer h.mu.Unlock()
-
-	var c []PeerInfo
-	for _, v := range h.peers {
-		c = append(c, v)
-	}
-	return c
-}
-
-// Middleware is a jsonrpc2 middleware function to augment connection binding
-// to handle the handshake method, and record disconnections.
-func (h *Handshaker) Middleware(inner jsonrpc2_v2.Binder) jsonrpc2_v2.Binder {
-	return BinderFunc(func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
-		opts := inner.Bind(ctx, conn)
-
-		localID := h.nextID()
-		info := &PeerInfo{
-			RemoteID: localID,
-			Metadata: h.Metadata,
-		}
-
-		// Wrap the delegated handler to accept the handshake.
-		delegate := opts.Handler
-		opts.Handler = jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
-			if req.Method == handshakeMethod {
-				var peerInfo PeerInfo
-				if err := json.Unmarshal(req.Params, &peerInfo); err != nil {
-					return nil, fmt.Errorf("%w: unmarshaling client info: %v", jsonrpc2_v2.ErrInvalidParams, err)
-				}
-				peerInfo.LocalID = localID
-				peerInfo.IsClient = true
-				h.recordPeer(peerInfo)
-				return info, nil
-			}
-			return delegate.Handle(ctx, req)
-		})
-
-		// Record the dropped client.
-		go h.cleanupAtDisconnect(conn, localID)
-
-		return opts
-	})
-}
-
-// ClientHandshake performs a client-side handshake with the server at the
-// other end of conn, recording the server's peer info and watching for conn's
-// disconnection.
-func (h *Handshaker) ClientHandshake(ctx context.Context, conn *jsonrpc2_v2.Connection) {
-	localID := h.nextID()
-	info := &PeerInfo{
-		RemoteID: localID,
-		Metadata: h.Metadata,
-	}
-
-	call := conn.Call(ctx, handshakeMethod, info)
-	var serverInfo PeerInfo
-	if err := call.Await(ctx, &serverInfo); err != nil {
-		event.Error(ctx, "performing handshake", err)
-		return
-	}
-	serverInfo.LocalID = localID
-	h.recordPeer(serverInfo)
-
-	go h.cleanupAtDisconnect(conn, localID)
-}
-
-func (h *Handshaker) nextID() int64 {
-	h.mu.Lock()
-	defer h.mu.Unlock()
-
-	h.prevID++
-	return h.prevID
-}
-
-func (h *Handshaker) cleanupAtDisconnect(conn *jsonrpc2_v2.Connection, peerID int64) {
-	conn.Wait()
-
-	h.mu.Lock()
-	defer h.mu.Unlock()
-	delete(h.peers, peerID)
-}
-
-func (h *Handshaker) recordPeer(info PeerInfo) {
-	h.mu.Lock()
-	defer h.mu.Unlock()
-	if h.peers == nil {
-		h.peers = make(map[int64]PeerInfo)
-	}
-	h.peers[info.LocalID] = info
-}
diff --git a/gopls/internal/lsp/lsprpc/middleware_test.go b/gopls/internal/lsp/lsprpc/middleware_test.go
deleted file mode 100644
index c528eae..0000000
--- a/gopls/internal/lsp/lsprpc/middleware_test.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package lsprpc_test
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	"testing"
-	"time"
-
-	. "golang.org/x/tools/gopls/internal/lsp/lsprpc"
-	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
-)
-
-var noopBinder = BinderFunc(func(context.Context, *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
-	return jsonrpc2_v2.ConnectionOptions{}
-})
-
-func TestHandshakeMiddleware(t *testing.T) {
-	sh := &Handshaker{
-		Metadata: Metadata{
-			"answer": 42,
-		},
-	}
-	ctx := context.Background()
-	env := new(TestEnv)
-	defer env.Shutdown(t)
-	l, _ := env.serve(ctx, t, sh.Middleware(noopBinder))
-	conn := env.dial(ctx, t, l.Dialer(), noopBinder, false)
-	ch := &Handshaker{
-		Metadata: Metadata{
-			"question": 6 * 9,
-		},
-	}
-
-	check := func(connected bool) error {
-		clients := sh.Peers()
-		servers := ch.Peers()
-		want := 0
-		if connected {
-			want = 1
-		}
-		if got := len(clients); got != want {
-			return fmt.Errorf("got %d clients on the server, want %d", got, want)
-		}
-		if got := len(servers); got != want {
-			return fmt.Errorf("got %d servers on the client, want %d", got, want)
-		}
-		if !connected {
-			return nil
-		}
-		client := clients[0]
-		server := servers[0]
-		if _, ok := client.Metadata["question"]; !ok {
-			return errors.New("no client metadata")
-		}
-		if _, ok := server.Metadata["answer"]; !ok {
-			return errors.New("no server metadata")
-		}
-		if client.LocalID != server.RemoteID {
-			return fmt.Errorf("client.LocalID == %d, server.PeerID == %d", client.LocalID, server.RemoteID)
-		}
-		if client.RemoteID != server.LocalID {
-			return fmt.Errorf("client.PeerID == %d, server.LocalID == %d", client.RemoteID, server.LocalID)
-		}
-		return nil
-	}
-
-	if err := check(false); err != nil {
-		t.Fatalf("before handshake: %v", err)
-	}
-	ch.ClientHandshake(ctx, conn)
-	if err := check(true); err != nil {
-		t.Fatalf("after handshake: %v", err)
-	}
-	conn.Close()
-	// Wait for up to ~2s for connections to get cleaned up.
-	delay := 25 * time.Millisecond
-	for retries := 3; retries >= 0; retries-- {
-		time.Sleep(delay)
-		err := check(false)
-		if err == nil {
-			return
-		}
-		if retries == 0 {
-			t.Fatalf("after closing connection: %v", err)
-		}
-		delay *= 4
-	}
-}
diff --git a/gopls/internal/lsp/lsprpc/autostart_default.go b/gopls/internal/lsprpc/autostart_default.go
similarity index 100%
rename from gopls/internal/lsp/lsprpc/autostart_default.go
rename to gopls/internal/lsprpc/autostart_default.go
diff --git a/gopls/internal/lsp/lsprpc/autostart_posix.go b/gopls/internal/lsprpc/autostart_posix.go
similarity index 100%
rename from gopls/internal/lsp/lsprpc/autostart_posix.go
rename to gopls/internal/lsprpc/autostart_posix.go
diff --git a/gopls/internal/lsprpc/binder.go b/gopls/internal/lsprpc/binder.go
new file mode 100644
index 0000000..708e0ad
--- /dev/null
+++ b/gopls/internal/lsprpc/binder.go
@@ -0,0 +1,5 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package lsprpc
diff --git a/gopls/internal/lsp/lsprpc/binder_test.go b/gopls/internal/lsprpc/binder_test.go
similarity index 67%
rename from gopls/internal/lsp/lsprpc/binder_test.go
rename to gopls/internal/lsprpc/binder_test.go
index 3315c3e..042056e 100644
--- a/gopls/internal/lsp/lsprpc/binder_test.go
+++ b/gopls/internal/lsprpc/binder_test.go
@@ -11,12 +11,64 @@
 	"testing"
 	"time"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
 
-	. "golang.org/x/tools/gopls/internal/lsp/lsprpc"
+	. "golang.org/x/tools/gopls/internal/lsprpc"
 )
 
+// ServerBinder binds incoming connections to a new server.
+type ServerBinder struct {
+	newServer ServerFunc
+}
+
+func NewServerBinder(newServer ServerFunc) *ServerBinder {
+	return &ServerBinder{newServer: newServer}
+}
+
+// streamServer used to have this method, but it was never used.
+// TODO(adonovan): figure out whether we need any of this machinery
+// and, if not, delete it. In the meantime, it's better that it sit
+// in the test package with all the other mothballed machinery
+// than in the production code where it would couple streamServer
+// and ServerBinder.
+/*
+func (s *streamServer) Binder() *ServerBinder {
+	newServer := func(ctx context.Context, client protocol.ClientCloser) protocol.Server {
+		session := cache.NewSession(ctx, s.cache)
+		svr := s.serverForTest
+		if svr == nil {
+			options := settings.DefaultOptions(s.optionsOverrides)
+			svr = server.New(session, client, options)
+			if instance := debug.GetInstance(ctx); instance != nil {
+				instance.AddService(svr, session)
+			}
+		}
+		return svr
+	}
+	return NewServerBinder(newServer)
+}
+*/
+
+func (b *ServerBinder) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
+	client := protocol.ClientDispatcherV2(conn)
+	server := b.newServer(ctx, client)
+	serverHandler := protocol.ServerHandlerV2(server)
+	// Wrap the server handler to inject the client into each request context, so
+	// that log events are reflected back to the client.
+	wrapped := jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
+		ctx = protocol.WithClient(ctx, client)
+		return serverHandler.Handle(ctx, req)
+	})
+	preempter := &Canceler{
+		Conn: conn,
+	}
+	return jsonrpc2_v2.ConnectionOptions{
+		Handler:   wrapped,
+		Preempter: preempter,
+	}
+}
+
 type TestEnv struct {
 	Conns   []*jsonrpc2_v2.Connection
 	Servers []*jsonrpc2_v2.Server
diff --git a/gopls/internal/lsprpc/commandinterceptor_test.go b/gopls/internal/lsprpc/commandinterceptor_test.go
new file mode 100644
index 0000000..7c83ef9
--- /dev/null
+++ b/gopls/internal/lsprpc/commandinterceptor_test.go
@@ -0,0 +1,61 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package lsprpc_test
+
+import (
+	"context"
+	"encoding/json"
+	"testing"
+
+	"golang.org/x/tools/gopls/internal/protocol"
+	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
+
+	. "golang.org/x/tools/gopls/internal/lsprpc"
+)
+
+func CommandInterceptor(command string, run func(*protocol.ExecuteCommandParams) (interface{}, error)) Middleware {
+	return BindHandler(func(delegate jsonrpc2_v2.Handler) jsonrpc2_v2.Handler {
+		return jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
+			if req.Method == "workspace/executeCommand" {
+				var params protocol.ExecuteCommandParams
+				if err := json.Unmarshal(req.Params, &params); err == nil {
+					if params.Command == command {
+						return run(&params)
+					}
+				}
+			}
+
+			return delegate.Handle(ctx, req)
+		})
+	})
+}
+
+func TestCommandInterceptor(t *testing.T) {
+	const command = "foo"
+	caught := false
+	intercept := func(_ *protocol.ExecuteCommandParams) (interface{}, error) {
+		caught = true
+		return map[string]interface{}{}, nil
+	}
+
+	ctx := context.Background()
+	env := new(TestEnv)
+	defer env.Shutdown(t)
+	mw := CommandInterceptor(command, intercept)
+	l, _ := env.serve(ctx, t, mw(noopBinder))
+	conn := env.dial(ctx, t, l.Dialer(), noopBinder, false)
+
+	params := &protocol.ExecuteCommandParams{
+		Command: command,
+	}
+	var res interface{}
+	err := conn.Call(ctx, "workspace/executeCommand", params).Await(ctx, &res)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !caught {
+		t.Errorf("workspace/executeCommand was not intercepted")
+	}
+}
diff --git a/gopls/internal/lsp/lsprpc/dialer.go b/gopls/internal/lsprpc/dialer.go
similarity index 87%
rename from gopls/internal/lsp/lsprpc/dialer.go
rename to gopls/internal/lsprpc/dialer.go
index e962c60..a5f038d 100644
--- a/gopls/internal/lsp/lsprpc/dialer.go
+++ b/gopls/internal/lsprpc/dialer.go
@@ -16,12 +16,12 @@
 	"golang.org/x/tools/internal/event"
 )
 
-// AutoNetwork is the pseudo network type used to signal that gopls should use
+// autoNetwork is the pseudo network type used to signal that gopls should use
 // automatic discovery to resolve a remote address.
-const AutoNetwork = "auto"
+const autoNetwork = "auto"
 
-// An AutoDialer is a jsonrpc2 dialer that understands the 'auto' network.
-type AutoDialer struct {
+// An autoDialer is a jsonrpc2 dialer that understands the 'auto' network.
+type autoDialer struct {
 	network, addr string // the 'real' network and address
 	isAuto        bool   // whether the server is on the 'auto' network
 
@@ -29,12 +29,12 @@
 	argFunc    func(network, addr string) []string
 }
 
-func NewAutoDialer(rawAddr string, argFunc func(network, addr string) []string) (*AutoDialer, error) {
-	d := AutoDialer{
+func newAutoDialer(rawAddr string, argFunc func(network, addr string) []string) (*autoDialer, error) {
+	d := autoDialer{
 		argFunc: argFunc,
 	}
 	d.network, d.addr = ParseAddr(rawAddr)
-	if d.network == AutoNetwork {
+	if d.network == autoNetwork {
 		d.isAuto = true
 		bin, err := os.Executable()
 		if err != nil {
@@ -47,14 +47,14 @@
 }
 
 // Dial implements the jsonrpc2.Dialer interface.
-func (d *AutoDialer) Dial(ctx context.Context) (io.ReadWriteCloser, error) {
+func (d *autoDialer) Dial(ctx context.Context) (io.ReadWriteCloser, error) {
 	conn, err := d.dialNet(ctx)
 	return conn, err
 }
 
 // TODO(rFindley): remove this once we no longer need to integrate with v1 of
 // the jsonrpc2 package.
-func (d *AutoDialer) dialNet(ctx context.Context) (net.Conn, error) {
+func (d *autoDialer) dialNet(ctx context.Context) (net.Conn, error) {
 	// Attempt to verify that we own the remote. This is imperfect, but if we can
 	// determine that the remote is owned by a different user, we should fail.
 	ok, err := verifyRemoteOwnership(d.network, d.addr)
diff --git a/gopls/internal/lsp/lsprpc/binder.go b/gopls/internal/lsprpc/export_test.go
similarity index 68%
rename from gopls/internal/lsp/lsprpc/binder.go
rename to gopls/internal/lsprpc/export_test.go
index 01e59f7..5091298 100644
--- a/gopls/internal/lsp/lsprpc/binder.go
+++ b/gopls/internal/lsprpc/export_test.go
@@ -1,68 +1,32 @@
-// Copyright 2021 The Go Authors. All rights reserved.
+// Copyright 2024 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
 package lsprpc
 
+// This file defines things (and opens backdoors) needed only by tests.
+
 import (
 	"context"
 	"encoding/json"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
 	"golang.org/x/tools/internal/xcontext"
 )
 
-// The BinderFunc type adapts a bind function to implement the jsonrpc2.Binder
-// interface.
-type BinderFunc func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions
-
-func (f BinderFunc) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
-	return f(ctx, conn)
-}
-
-// Middleware defines a transformation of jsonrpc2 Binders, that may be
-// composed to build jsonrpc2 servers.
-type Middleware func(jsonrpc2_v2.Binder) jsonrpc2_v2.Binder
+const HandshakeMethod = handshakeMethod
 
 // A ServerFunc is used to construct an LSP server for a given client.
 type ServerFunc func(context.Context, protocol.ClientCloser) protocol.Server
 
-// ServerBinder binds incoming connections to a new server.
-type ServerBinder struct {
-	newServer ServerFunc
+type Canceler struct {
+	Conn *jsonrpc2_v2.Connection
 }
 
-func NewServerBinder(newServer ServerFunc) *ServerBinder {
-	return &ServerBinder{newServer: newServer}
-}
-
-func (b *ServerBinder) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
-	client := protocol.ClientDispatcherV2(conn)
-	server := b.newServer(ctx, client)
-	serverHandler := protocol.ServerHandlerV2(server)
-	// Wrap the server handler to inject the client into each request context, so
-	// that log events are reflected back to the client.
-	wrapped := jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
-		ctx = protocol.WithClient(ctx, client)
-		return serverHandler.Handle(ctx, req)
-	})
-	preempter := &canceler{
-		conn: conn,
-	}
-	return jsonrpc2_v2.ConnectionOptions{
-		Handler:   wrapped,
-		Preempter: preempter,
-	}
-}
-
-type canceler struct {
-	conn *jsonrpc2_v2.Connection
-}
-
-func (c *canceler) Preempt(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
+func (c *Canceler) Preempt(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
 	if req.Method != "$/cancelRequest" {
 		return nil, jsonrpc2_v2.ErrNotHandled
 	}
@@ -79,7 +43,7 @@
 	default:
 		return nil, fmt.Errorf("%w: invalid ID type %T", jsonrpc2_v2.ErrParse, params.ID)
 	}
-	c.conn.Cancel(id)
+	c.Conn.Cancel(id)
 	return nil, nil
 }
 
@@ -111,8 +75,8 @@
 		b.onBind(serverConn)
 	}
 	server := protocol.ServerDispatcherV2(serverConn)
-	preempter := &canceler{
-		conn: conn,
+	preempter := &Canceler{
+		Conn: conn,
 	}
 	detached := xcontext.Detach(ctx)
 	go func() {
@@ -127,22 +91,52 @@
 	}
 }
 
+func NewClientBinder(newClient ClientFunc) *clientBinder {
+	return &clientBinder{newClient}
+}
+
 // A ClientFunc is used to construct an LSP client for a given server.
 type ClientFunc func(context.Context, protocol.Server) protocol.Client
 
-// ClientBinder binds an LSP client to an incoming connection.
-type ClientBinder struct {
+// clientBinder binds an LSP client to an incoming connection.
+type clientBinder struct {
 	newClient ClientFunc
 }
 
-func NewClientBinder(newClient ClientFunc) *ClientBinder {
-	return &ClientBinder{newClient}
-}
-
-func (b *ClientBinder) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
+func (b *clientBinder) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
 	server := protocol.ServerDispatcherV2(conn)
 	client := b.newClient(ctx, server)
 	return jsonrpc2_v2.ConnectionOptions{
 		Handler: protocol.ClientHandlerV2(client),
 	}
 }
+
+// HandlerMiddleware is a middleware that only modifies the jsonrpc2 handler.
+type HandlerMiddleware func(jsonrpc2_v2.Handler) jsonrpc2_v2.Handler
+
+// BindHandler transforms a HandlerMiddleware into a Middleware.
+func BindHandler(hmw HandlerMiddleware) Middleware {
+	return Middleware(func(binder jsonrpc2_v2.Binder) jsonrpc2_v2.Binder {
+		return BinderFunc(func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
+			opts := binder.Bind(ctx, conn)
+			opts.Handler = hmw(opts.Handler)
+			return opts
+		})
+	})
+}
+
+// The BinderFunc type adapts a bind function to implement the jsonrpc2.Binder
+// interface.
+type BinderFunc func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions
+
+func (f BinderFunc) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
+	return f(ctx, conn)
+}
+
+// Middleware defines a transformation of jsonrpc2 Binders, that may be
+// composed to build jsonrpc2 servers.
+type Middleware func(jsonrpc2_v2.Binder) jsonrpc2_v2.Binder
+
+var GetGoEnv = getGoEnv
+
+type StreamServer = streamServer
diff --git a/gopls/internal/lsprpc/goenv.go b/gopls/internal/lsprpc/goenv.go
new file mode 100644
index 0000000..52ec08f
--- /dev/null
+++ b/gopls/internal/lsprpc/goenv.go
@@ -0,0 +1,34 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package lsprpc
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+
+	"golang.org/x/tools/internal/gocommand"
+)
+
+func getGoEnv(ctx context.Context, env map[string]interface{}) (map[string]string, error) {
+	var runEnv []string
+	for k, v := range env {
+		runEnv = append(runEnv, fmt.Sprintf("%s=%s", k, v))
+	}
+	runner := gocommand.Runner{}
+	output, err := runner.Run(ctx, gocommand.Invocation{
+		Verb: "env",
+		Args: []string{"-json"},
+		Env:  runEnv,
+	})
+	if err != nil {
+		return nil, err
+	}
+	envmap := make(map[string]string)
+	if err := json.Unmarshal(output.Bytes(), &envmap); err != nil {
+		return nil, err
+	}
+	return envmap, nil
+}
diff --git a/gopls/internal/lsprpc/goenv_test.go b/gopls/internal/lsprpc/goenv_test.go
new file mode 100644
index 0000000..6c41540
--- /dev/null
+++ b/gopls/internal/lsprpc/goenv_test.go
@@ -0,0 +1,133 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package lsprpc_test
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"os"
+	"testing"
+
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/internal/event"
+	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
+	"golang.org/x/tools/internal/testenv"
+
+	. "golang.org/x/tools/gopls/internal/lsprpc"
+)
+
+func GoEnvMiddleware() (Middleware, error) {
+	return BindHandler(func(delegate jsonrpc2_v2.Handler) jsonrpc2_v2.Handler {
+		return jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
+			if req.Method == "initialize" {
+				if err := addGoEnvToInitializeRequestV2(ctx, req); err != nil {
+					event.Error(ctx, "adding go env to initialize", err)
+				}
+			}
+			return delegate.Handle(ctx, req)
+		})
+	}), nil
+}
+
+// This function is almost identical to addGoEnvToInitializeRequest in lsprpc.go.
+// Make changes in parallel.
+func addGoEnvToInitializeRequestV2(ctx context.Context, req *jsonrpc2_v2.Request) error {
+	var params protocol.ParamInitialize
+	if err := json.Unmarshal(req.Params, &params); err != nil {
+		return err
+	}
+	var opts map[string]interface{}
+	switch v := params.InitializationOptions.(type) {
+	case nil:
+		opts = make(map[string]interface{})
+	case map[string]interface{}:
+		opts = v
+	default:
+		return fmt.Errorf("unexpected type for InitializationOptions: %T", v)
+	}
+	envOpt, ok := opts["env"]
+	if !ok {
+		envOpt = make(map[string]interface{})
+	}
+	env, ok := envOpt.(map[string]interface{})
+	if !ok {
+		return fmt.Errorf("env option is %T, expected a map", envOpt)
+	}
+	goenv, err := GetGoEnv(ctx, env)
+	if err != nil {
+		return err
+	}
+	// We don't want to propagate GOWORK unless explicitly set since that could mess with
+	// path inference during cmd/go invocations, see golang/go#51825.
+	_, goworkSet := os.LookupEnv("GOWORK")
+	for govar, value := range goenv {
+		if govar == "GOWORK" && !goworkSet {
+			continue
+		}
+		env[govar] = value
+	}
+	opts["env"] = env
+	params.InitializationOptions = opts
+	raw, err := json.Marshal(params)
+	if err != nil {
+		return fmt.Errorf("marshaling updated options: %v", err)
+	}
+	req.Params = json.RawMessage(raw)
+	return nil
+}
+
+type initServer struct {
+	protocol.Server
+
+	params *protocol.ParamInitialize
+}
+
+func (s *initServer) Initialize(ctx context.Context, params *protocol.ParamInitialize) (*protocol.InitializeResult, error) {
+	s.params = params
+	return &protocol.InitializeResult{}, nil
+}
+
+func TestGoEnvMiddleware(t *testing.T) {
+	testenv.NeedsTool(t, "go")
+
+	ctx := context.Background()
+
+	server := &initServer{}
+	env := new(TestEnv)
+	defer env.Shutdown(t)
+	l, _ := env.serve(ctx, t, staticServerBinder(server))
+	mw, err := GoEnvMiddleware()
+	if err != nil {
+		t.Fatal(err)
+	}
+	binder := mw(NewForwardBinder(l.Dialer()))
+	l, _ = env.serve(ctx, t, binder)
+	conn := env.dial(ctx, t, l.Dialer(), noopBinder, true)
+	dispatch := protocol.ServerDispatcherV2(conn)
+	initParams := &protocol.ParamInitialize{}
+	initParams.InitializationOptions = map[string]interface{}{
+		"env": map[string]interface{}{
+			"GONOPROXY": "example.com",
+		},
+	}
+	if _, err := dispatch.Initialize(ctx, initParams); err != nil {
+		t.Fatal(err)
+	}
+
+	if server.params == nil {
+		t.Fatalf("initialize params are unset")
+	}
+	envOpts := server.params.InitializationOptions.(map[string]interface{})["env"].(map[string]interface{})
+
+	// Check for an arbitrary Go variable. It should be set.
+	if _, ok := envOpts["GOPRIVATE"]; !ok {
+		t.Errorf("Go environment variable GOPRIVATE unset in initialization options")
+	}
+	// Check that the variable present in our user config was not overwritten.
+	if got, want := envOpts["GONOPROXY"], "example.com"; got != want {
+		t.Errorf("GONOPROXY=%q, want %q", got, want)
+	}
+}
diff --git a/gopls/internal/lsp/lsprpc/lsprpc.go b/gopls/internal/lsprpc/lsprpc.go
similarity index 88%
rename from gopls/internal/lsp/lsprpc/lsprpc.go
rename to gopls/internal/lsprpc/lsprpc.go
index 006c98e..0497612 100644
--- a/gopls/internal/lsp/lsprpc/lsprpc.go
+++ b/gopls/internal/lsprpc/lsprpc.go
@@ -19,10 +19,10 @@
 	"sync/atomic"
 	"time"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/debug"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/server"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/internal/event"
@@ -33,9 +33,9 @@
 // Unique identifiers for client/server.
 var serverIndex int64
 
-// The StreamServer type is a jsonrpc2.StreamServer that handles incoming
+// The streamServer type is a jsonrpc2.streamServer that handles incoming
 // streams as a new LSP session, using a shared cache.
-type StreamServer struct {
+type streamServer struct {
 	cache *cache.Cache
 	// daemon controls whether or not to log new connections.
 	daemon bool
@@ -50,29 +50,13 @@
 // NewStreamServer creates a StreamServer using the shared cache. If
 // withTelemetry is true, each session is instrumented with telemetry that
 // records RPC statistics.
-func NewStreamServer(cache *cache.Cache, daemon bool, optionsFunc func(*settings.Options)) *StreamServer {
-	return &StreamServer{cache: cache, daemon: daemon, optionsOverrides: optionsFunc}
-}
-
-func (s *StreamServer) Binder() *ServerBinder {
-	newServer := func(ctx context.Context, client protocol.ClientCloser) protocol.Server {
-		session := cache.NewSession(ctx, s.cache)
-		svr := s.serverForTest
-		if svr == nil {
-			options := settings.DefaultOptions(s.optionsOverrides)
-			svr = server.New(session, client, options)
-			if instance := debug.GetInstance(ctx); instance != nil {
-				instance.AddService(svr, session)
-			}
-		}
-		return svr
-	}
-	return NewServerBinder(newServer)
+func NewStreamServer(cache *cache.Cache, daemon bool, optionsFunc func(*settings.Options)) jsonrpc2.StreamServer {
+	return &streamServer{cache: cache, daemon: daemon, optionsOverrides: optionsFunc}
 }
 
 // ServeStream implements the jsonrpc2.StreamServer interface, by handling
 // incoming streams using a new lsp server.
-func (s *StreamServer) ServeStream(ctx context.Context, conn jsonrpc2.Conn) error {
+func (s *streamServer) ServeStream(ctx context.Context, conn jsonrpc2.Conn) error {
 	client := protocol.ClientDispatcher(conn)
 	session := cache.NewSession(ctx, s.cache)
 	svr := s.serverForTest
@@ -110,14 +94,14 @@
 	return conn.Err()
 }
 
-// A Forwarder is a jsonrpc2.StreamServer that handles an LSP stream by
+// A forwarder is a jsonrpc2.StreamServer that handles an LSP stream by
 // forwarding it to a remote. This is used when the gopls process started by
 // the editor is in the `-remote` mode, which means it finds and connects to a
 // separate gopls daemon. In these cases, we still want the forwarder gopls to
 // be instrumented with telemetry, and want to be able to in some cases hijack
 // the jsonrpc2 connection with the daemon.
-type Forwarder struct {
-	dialer *AutoDialer
+type forwarder struct {
+	dialer *autoDialer
 
 	mu sync.Mutex
 	// Hold on to the server connection so that we can redo the handshake if any
@@ -126,28 +110,29 @@
 	serverID   string
 }
 
-// NewForwarder creates a new Forwarder, ready to forward connections to the
+// NewForwarder creates a new forwarder (a [jsonrpc2.StreamServer]),
+// ready to forward connections to the
 // remote server specified by rawAddr. If provided and rawAddr indicates an
 // 'automatic' address (starting with 'auto;'), argFunc may be used to start a
 // remote server for the auto-discovered address.
-func NewForwarder(rawAddr string, argFunc func(network, address string) []string) (*Forwarder, error) {
-	dialer, err := NewAutoDialer(rawAddr, argFunc)
+func NewForwarder(rawAddr string, argFunc func(network, address string) []string) (jsonrpc2.StreamServer, error) {
+	dialer, err := newAutoDialer(rawAddr, argFunc)
 	if err != nil {
 		return nil, err
 	}
-	fwd := &Forwarder{
+	fwd := &forwarder{
 		dialer: dialer,
 	}
 	return fwd, nil
 }
 
-// QueryServerState queries the server state of the current server.
-func QueryServerState(ctx context.Context, addr string) (*ServerState, error) {
+// QueryServerState returns a JSON-encodable struct describing the state of the named server.
+func QueryServerState(ctx context.Context, addr string) (any, error) {
 	serverConn, err := dialRemote(ctx, addr)
 	if err != nil {
 		return nil, err
 	}
-	var state ServerState
+	var state serverState
 	if err := protocol.Call(ctx, serverConn, sessionsMethod, nil, &state); err != nil {
 		return nil, fmt.Errorf("querying server state: %w", err)
 	}
@@ -159,7 +144,7 @@
 // or auto://...).
 func dialRemote(ctx context.Context, addr string) (jsonrpc2.Conn, error) {
 	network, address := ParseAddr(addr)
-	if network == AutoNetwork {
+	if network == autoNetwork {
 		gp, err := os.Executable()
 		if err != nil {
 			return nil, fmt.Errorf("getting gopls path: %w", err)
@@ -175,7 +160,10 @@
 	return serverConn, nil
 }
 
-func ExecuteCommand(ctx context.Context, addr string, id string, request, result interface{}) error {
+// ExecuteCommand connects to the named server, sends it a
+// workspace/executeCommand request (with command 'id' and arguments
+// JSON encoded in 'request'), and populates the result variable.
+func ExecuteCommand(ctx context.Context, addr string, id string, request, result any) error {
 	serverConn, err := dialRemote(ctx, addr)
 	if err != nil {
 		return err
@@ -193,7 +181,7 @@
 
 // ServeStream dials the forwarder remote and binds the remote to serve the LSP
 // on the incoming stream.
-func (f *Forwarder) ServeStream(ctx context.Context, clientConn jsonrpc2.Conn) error {
+func (f *forwarder) ServeStream(ctx context.Context, clientConn jsonrpc2.Conn) error {
 	client := protocol.ClientDispatcher(clientConn)
 
 	netConn, err := f.dialer.dialNet(ctx)
@@ -243,7 +231,7 @@
 }
 
 // TODO(rfindley): remove this handshaking in favor of middleware.
-func (f *Forwarder) handshake(ctx context.Context) {
+func (f *forwarder) handshake(ctx context.Context) {
 	// This call to os.Executable is redundant, and will be eliminated by the
 	// transition to the V2 API.
 	goplsPath, err := os.Executable()
@@ -280,7 +268,7 @@
 }
 
 func ConnectToRemote(ctx context.Context, addr string) (net.Conn, error) {
-	dialer, err := NewAutoDialer(addr, nil)
+	dialer, err := newAutoDialer(addr, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -289,7 +277,7 @@
 
 // handler intercepts messages to the daemon to enrich them with local
 // information.
-func (f *Forwarder) handler(handler jsonrpc2.Handler) jsonrpc2.Handler {
+func (f *forwarder) handler(handler jsonrpc2.Handler) jsonrpc2.Handler {
 	return func(ctx context.Context, reply jsonrpc2.Replier, r jsonrpc2.Request) error {
 		// Intercept certain messages to add special handling.
 		switch r.Method() {
@@ -374,7 +362,7 @@
 	return jsonrpc2.NewCall(call.ID(), "initialize", params)
 }
 
-func (f *Forwarder) replyWithDebugAddress(outerCtx context.Context, r jsonrpc2.Replier, args command.DebuggingArgs) jsonrpc2.Replier {
+func (f *forwarder) replyWithDebugAddress(outerCtx context.Context, r jsonrpc2.Replier, args command.DebuggingArgs) jsonrpc2.Replier {
 	di := debug.GetInstance(outerCtx)
 	if di == nil {
 		event.Log(outerCtx, "no debug instance to start")
@@ -440,24 +428,24 @@
 	GoplsPath string `json:"goplsPath"`
 }
 
-// ClientSession identifies a current client LSP session on the server. Note
+// clientSession identifies a current client LSP session on the server. Note
 // that it looks similar to handshakeResposne, but in fact 'Logfile' and
 // 'DebugAddr' now refer to the client.
-type ClientSession struct {
+type clientSession struct {
 	SessionID string `json:"sessionID"`
 	Logfile   string `json:"logfile"`
 	DebugAddr string `json:"debugAddr"`
 }
 
-// ServerState holds information about the gopls daemon process, including its
+// serverState holds information about the gopls daemon process, including its
 // debug information and debug information of all of its current connected
 // clients.
-type ServerState struct {
+type serverState struct {
 	Logfile         string          `json:"logfile"`
 	DebugAddr       string          `json:"debugAddr"`
 	GoplsPath       string          `json:"goplsPath"`
 	CurrentClientID string          `json:"currentClientID"`
-	Clients         []ClientSession `json:"clients"`
+	Clients         []clientSession `json:"clients"`
 }
 
 const (
@@ -501,7 +489,7 @@
 			return reply(ctx, resp, nil)
 
 		case sessionsMethod:
-			resp := ServerState{
+			resp := serverState{
 				GoplsPath:       goplsPath,
 				CurrentClientID: session.ID(),
 			}
@@ -509,7 +497,7 @@
 				resp.Logfile = di.Logfile
 				resp.DebugAddr = di.ListenedDebugAddress()
 				for _, c := range di.State.Clients() {
-					resp.Clients = append(resp.Clients, ClientSession{
+					resp.Clients = append(resp.Clients, clientSession{
 						SessionID: c.Session.ID(),
 						Logfile:   c.Logfile,
 						DebugAddr: c.DebugAddress,
@@ -535,8 +523,8 @@
 func ParseAddr(listen string) (network string, address string) {
 	// Allow passing just -remote=auto, as a shorthand for using automatic remote
 	// resolution.
-	if listen == AutoNetwork {
-		return AutoNetwork, ""
+	if listen == autoNetwork {
+		return autoNetwork, ""
 	}
 	if parts := strings.SplitN(listen, ";", 2); len(parts) == 2 {
 		return parts[0], parts[1]
diff --git a/gopls/internal/lsp/lsprpc/lsprpc_test.go b/gopls/internal/lsprpc/lsprpc_test.go
similarity index 95%
rename from gopls/internal/lsp/lsprpc/lsprpc_test.go
rename to gopls/internal/lsprpc/lsprpc_test.go
index 04d1be5..1d643bf 100644
--- a/gopls/internal/lsp/lsprpc/lsprpc_test.go
+++ b/gopls/internal/lsprpc/lsprpc_test.go
@@ -13,9 +13,9 @@
 	"testing"
 	"time"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/debug"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/jsonrpc2"
@@ -58,8 +58,8 @@
 	server := PingServer{}
 	client := FakeClient{Logs: make(chan string, 10)}
 
-	ctx = debug.WithInstance(ctx, "", "")
-	ss := NewStreamServer(cache.New(nil), false, nil)
+	ctx = debug.WithInstance(ctx, "")
+	ss := NewStreamServer(cache.New(nil), false, nil).(*StreamServer)
 	ss.serverForTest = server
 	ts := servertest.NewPipeServer(ss, nil)
 	defer checkClose(t, ts.Close)
@@ -121,8 +121,8 @@
 
 func setupForwarding(ctx context.Context, t *testing.T, s protocol.Server) (direct, forwarded servertest.Connector, cleanup func()) {
 	t.Helper()
-	serveCtx := debug.WithInstance(ctx, "", "")
-	ss := NewStreamServer(cache.New(nil), false, nil)
+	serveCtx := debug.WithInstance(ctx, "")
+	ss := NewStreamServer(cache.New(nil), false, nil).(*StreamServer)
 	ss.serverForTest = s
 	tsDirect := servertest.NewTCPServer(serveCtx, ss, nil)
 
@@ -214,8 +214,8 @@
 
 	baseCtx, cancel := context.WithCancel(context.Background())
 	defer cancel()
-	clientCtx := debug.WithInstance(baseCtx, "", "")
-	serverCtx := debug.WithInstance(baseCtx, "", "")
+	clientCtx := debug.WithInstance(baseCtx, "")
+	serverCtx := debug.WithInstance(baseCtx, "")
 
 	cache := cache.New(nil)
 	ss := NewStreamServer(cache, false, nil)
diff --git a/gopls/internal/lsprpc/middleware_test.go b/gopls/internal/lsprpc/middleware_test.go
new file mode 100644
index 0000000..526c734
--- /dev/null
+++ b/gopls/internal/lsprpc/middleware_test.go
@@ -0,0 +1,223 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package lsprpc_test
+
+import (
+	"context"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"sync"
+	"testing"
+	"time"
+
+	. "golang.org/x/tools/gopls/internal/lsprpc"
+	"golang.org/x/tools/internal/event"
+	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
+)
+
+var noopBinder = BinderFunc(func(context.Context, *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
+	return jsonrpc2_v2.ConnectionOptions{}
+})
+
+func TestHandshakeMiddleware(t *testing.T) {
+	sh := &Handshaker{
+		metadata: metadata{
+			"answer": 42,
+		},
+	}
+	ctx := context.Background()
+	env := new(TestEnv)
+	defer env.Shutdown(t)
+	l, _ := env.serve(ctx, t, sh.Middleware(noopBinder))
+	conn := env.dial(ctx, t, l.Dialer(), noopBinder, false)
+	ch := &Handshaker{
+		metadata: metadata{
+			"question": 6 * 9,
+		},
+	}
+
+	check := func(connected bool) error {
+		clients := sh.Peers()
+		servers := ch.Peers()
+		want := 0
+		if connected {
+			want = 1
+		}
+		if got := len(clients); got != want {
+			return fmt.Errorf("got %d clients on the server, want %d", got, want)
+		}
+		if got := len(servers); got != want {
+			return fmt.Errorf("got %d servers on the client, want %d", got, want)
+		}
+		if !connected {
+			return nil
+		}
+		client := clients[0]
+		server := servers[0]
+		if _, ok := client.Metadata["question"]; !ok {
+			return errors.New("no client metadata")
+		}
+		if _, ok := server.Metadata["answer"]; !ok {
+			return errors.New("no server metadata")
+		}
+		if client.LocalID != server.RemoteID {
+			return fmt.Errorf("client.LocalID == %d, server.PeerID == %d", client.LocalID, server.RemoteID)
+		}
+		if client.RemoteID != server.LocalID {
+			return fmt.Errorf("client.PeerID == %d, server.LocalID == %d", client.RemoteID, server.LocalID)
+		}
+		return nil
+	}
+
+	if err := check(false); err != nil {
+		t.Fatalf("before handshake: %v", err)
+	}
+	ch.ClientHandshake(ctx, conn)
+	if err := check(true); err != nil {
+		t.Fatalf("after handshake: %v", err)
+	}
+	conn.Close()
+	// Wait for up to ~2s for connections to get cleaned up.
+	delay := 25 * time.Millisecond
+	for retries := 3; retries >= 0; retries-- {
+		time.Sleep(delay)
+		err := check(false)
+		if err == nil {
+			return
+		}
+		if retries == 0 {
+			t.Fatalf("after closing connection: %v", err)
+		}
+		delay *= 4
+	}
+}
+
+// Handshaker handles both server and client handshaking over jsonrpc2 v2.
+// To instrument server-side handshaking, use Handshaker.Middleware.
+// To instrument client-side handshaking, call
+// Handshaker.ClientHandshake for any new client-side connections.
+type Handshaker struct {
+	// metadata will be shared with peers via handshaking.
+	metadata metadata
+
+	mu     sync.Mutex
+	prevID int64
+	peers  map[int64]PeerInfo
+}
+
+// metadata holds arbitrary data transferred between jsonrpc2 peers.
+type metadata map[string]any
+
+// PeerInfo holds information about a peering between jsonrpc2 servers.
+type PeerInfo struct {
+	// RemoteID is the identity of the current server on its peer.
+	RemoteID int64
+
+	// LocalID is the identity of the peer on the server.
+	LocalID int64
+
+	// IsClient reports whether the peer is a client. If false, the peer is a
+	// server.
+	IsClient bool
+
+	// Metadata holds arbitrary information provided by the peer.
+	Metadata metadata
+}
+
+// Peers returns the peer info this handshaker knows about by way of either the
+// server-side handshake middleware, or client-side handshakes.
+func (h *Handshaker) Peers() []PeerInfo {
+	h.mu.Lock()
+	defer h.mu.Unlock()
+
+	var c []PeerInfo
+	for _, v := range h.peers {
+		c = append(c, v)
+	}
+	return c
+}
+
+// Middleware is a jsonrpc2 middleware function to augment connection binding
+// to handle the handshake method, and record disconnections.
+func (h *Handshaker) Middleware(inner jsonrpc2_v2.Binder) jsonrpc2_v2.Binder {
+	return BinderFunc(func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {
+		opts := inner.Bind(ctx, conn)
+
+		localID := h.nextID()
+		info := &PeerInfo{
+			RemoteID: localID,
+			Metadata: h.metadata,
+		}
+
+		// Wrap the delegated handler to accept the handshake.
+		delegate := opts.Handler
+		opts.Handler = jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) {
+			if req.Method == HandshakeMethod {
+				var peerInfo PeerInfo
+				if err := json.Unmarshal(req.Params, &peerInfo); err != nil {
+					return nil, fmt.Errorf("%w: unmarshaling client info: %v", jsonrpc2_v2.ErrInvalidParams, err)
+				}
+				peerInfo.LocalID = localID
+				peerInfo.IsClient = true
+				h.recordPeer(peerInfo)
+				return info, nil
+			}
+			return delegate.Handle(ctx, req)
+		})
+
+		// Record the dropped client.
+		go h.cleanupAtDisconnect(conn, localID)
+
+		return opts
+	})
+}
+
+// ClientHandshake performs a client-side handshake with the server at the
+// other end of conn, recording the server's peer info and watching for conn's
+// disconnection.
+func (h *Handshaker) ClientHandshake(ctx context.Context, conn *jsonrpc2_v2.Connection) {
+	localID := h.nextID()
+	info := &PeerInfo{
+		RemoteID: localID,
+		Metadata: h.metadata,
+	}
+
+	call := conn.Call(ctx, HandshakeMethod, info)
+	var serverInfo PeerInfo
+	if err := call.Await(ctx, &serverInfo); err != nil {
+		event.Error(ctx, "performing handshake", err)
+		return
+	}
+	serverInfo.LocalID = localID
+	h.recordPeer(serverInfo)
+
+	go h.cleanupAtDisconnect(conn, localID)
+}
+
+func (h *Handshaker) nextID() int64 {
+	h.mu.Lock()
+	defer h.mu.Unlock()
+
+	h.prevID++
+	return h.prevID
+}
+
+func (h *Handshaker) cleanupAtDisconnect(conn *jsonrpc2_v2.Connection, peerID int64) {
+	conn.Wait()
+
+	h.mu.Lock()
+	defer h.mu.Unlock()
+	delete(h.peers, peerID)
+}
+
+func (h *Handshaker) recordPeer(info PeerInfo) {
+	h.mu.Lock()
+	defer h.mu.Unlock()
+	if h.peers == nil {
+		h.peers = make(map[int64]PeerInfo)
+	}
+	h.peers[info.LocalID] = info
+}
diff --git a/gopls/internal/mod/code_lens.go b/gopls/internal/mod/code_lens.go
index 6feb93e..85d8182 100644
--- a/gopls/internal/mod/code_lens.go
+++ b/gopls/internal/mod/code_lens.go
@@ -11,16 +11,16 @@
 	"path/filepath"
 
 	"golang.org/x/mod/modfile"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 )
 
 // LensFuncs returns the supported lensFuncs for go.mod files.
-func LensFuncs() map[command.Command]source.LensFunc {
-	return map[command.Command]source.LensFunc{
+func LensFuncs() map[command.Command]golang.LensFunc {
+	return map[command.Command]golang.LensFunc{
 		command.UpgradeDependency: upgradeLenses,
 		command.Tidy:              tidyLens,
 		command.Vendor:            vendorLens,
diff --git a/gopls/internal/mod/diagnostics.go b/gopls/internal/mod/diagnostics.go
index c80a56d..655beed 100644
--- a/gopls/internal/mod/diagnostics.go
+++ b/gopls/internal/mod/diagnostics.go
@@ -17,10 +17,10 @@
 	"golang.org/x/mod/modfile"
 	"golang.org/x/mod/semver"
 	"golang.org/x/sync/errgroup"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/vulncheck/govulncheck"
 	"golang.org/x/tools/internal/event"
diff --git a/gopls/internal/mod/format.go b/gopls/internal/mod/format.go
index 8bb4085..1440839 100644
--- a/gopls/internal/mod/format.go
+++ b/gopls/internal/mod/format.go
@@ -7,9 +7,9 @@
 import (
 	"context"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/diff"
 	"golang.org/x/tools/internal/event"
 )
diff --git a/gopls/internal/mod/hover.go b/gopls/internal/mod/hover.go
index 44f32dc..458c5ce 100644
--- a/gopls/internal/mod/hover.go
+++ b/gopls/internal/mod/hover.go
@@ -13,9 +13,9 @@
 
 	"golang.org/x/mod/modfile"
 	"golang.org/x/mod/semver"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/vulncheck"
 	"golang.org/x/tools/gopls/internal/vulncheck/govulncheck"
diff --git a/gopls/internal/mod/inlayhint.go b/gopls/internal/mod/inlayhint.go
index 6c0275e..73286be 100644
--- a/gopls/internal/mod/inlayhint.go
+++ b/gopls/internal/mod/inlayhint.go
@@ -8,9 +8,9 @@
 	"fmt"
 
 	"golang.org/x/mod/modfile"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 func InlayHint(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, _ protocol.Range) ([]protocol.InlayHint, error) {
diff --git a/gopls/internal/lsp/progress/progress.go b/gopls/internal/progress/progress.go
similarity index 83%
rename from gopls/internal/lsp/progress/progress.go
rename to gopls/internal/progress/progress.go
index 6ccf086..0bb17b3 100644
--- a/gopls/internal/lsp/progress/progress.go
+++ b/gopls/internal/progress/progress.go
@@ -2,22 +2,36 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// The progress package defines utilities for reporting the progress
+// of long-running operations using features of the LSP client
+// interface such as Progress and ShowMessage.
 package progress
 
 import (
 	"context"
 	"fmt"
+	"io"
 	"math/rand"
 	"strconv"
 	"strings"
 	"sync"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
 	"golang.org/x/tools/internal/xcontext"
 )
 
+// NewTracker returns a new Tracker that reports progress to the
+// specified client.
+func NewTracker(client protocol.Client) *Tracker {
+	return &Tracker{
+		client:     client,
+		inProgress: make(map[protocol.ProgressToken]*WorkDone),
+	}
+}
+
+// A Tracker reports the progress of a long-running operation to an LSP client.
 type Tracker struct {
 	client                   protocol.Client
 	supportsWorkDoneProgress bool
@@ -26,27 +40,20 @@
 	inProgress map[protocol.ProgressToken]*WorkDone
 }
 
-func NewTracker(client protocol.Client) *Tracker {
-	return &Tracker{
-		client:     client,
-		inProgress: make(map[protocol.ProgressToken]*WorkDone),
-	}
-}
-
-// SetSupportsWorkDoneProgress sets whether the client supports work done
+// SetSupportsWorkDoneProgress sets whether the client supports "work done"
 // progress reporting. It must be set before using the tracker.
 //
 // TODO(rfindley): fix this broken initialization pattern.
 // Also: do we actually need the fall-back progress behavior using ShowMessage?
 // Surely ShowMessage notifications are too noisy to be worthwhile.
-func (tracker *Tracker) SetSupportsWorkDoneProgress(b bool) {
-	tracker.supportsWorkDoneProgress = b
+func (t *Tracker) SetSupportsWorkDoneProgress(b bool) {
+	t.supportsWorkDoneProgress = b
 }
 
 // SupportsWorkDoneProgress reports whether the tracker supports work done
 // progress reporting.
-func (tracker *Tracker) SupportsWorkDoneProgress() bool {
-	return tracker.supportsWorkDoneProgress
+func (t *Tracker) SupportsWorkDoneProgress() bool {
+	return t.supportsWorkDoneProgress
 }
 
 // Start notifies the client of work being done on the server. It uses either
@@ -247,36 +254,38 @@
 	}
 }
 
-// EventWriter writes every incoming []byte to
-// event.Print with the operation=generate tag
-// to distinguish its logs from others.
-type EventWriter struct {
+// NewEventWriter returns an [io.Writer] that calls the context's
+// event printer for each data payload, wrapping it with the
+// operation=generate tag to distinguish its logs from others.
+func NewEventWriter(ctx context.Context, operation string) io.Writer {
+	return &eventWriter{ctx: ctx, operation: operation}
+}
+
+type eventWriter struct {
 	ctx       context.Context
 	operation string
 }
 
-func NewEventWriter(ctx context.Context, operation string) *EventWriter {
-	return &EventWriter{ctx: ctx, operation: operation}
-}
-
-func (ew *EventWriter) Write(p []byte) (n int, err error) {
+func (ew *eventWriter) Write(p []byte) (n int, err error) {
 	event.Log(ew.ctx, string(p), tag.Operation.Of(ew.operation))
 	return len(p), nil
 }
 
-// WorkDoneWriter wraps a workDone handle to provide a Writer interface,
+// NewWorkDoneWriter wraps a WorkDone handle to provide a Writer interface,
 // so that workDone reporting can more easily be hooked into commands.
-type WorkDoneWriter struct {
+func NewWorkDoneWriter(ctx context.Context, wd *WorkDone) io.Writer {
+	return &workDoneWriter{ctx: ctx, wd: wd}
+}
+
+// workDoneWriter wraps a workDone handle to provide a Writer interface,
+// so that workDone reporting can more easily be hooked into commands.
+type workDoneWriter struct {
 	// In order to implement the io.Writer interface, we must close over ctx.
 	ctx context.Context
 	wd  *WorkDone
 }
 
-func NewWorkDoneWriter(ctx context.Context, wd *WorkDone) *WorkDoneWriter {
-	return &WorkDoneWriter{ctx: ctx, wd: wd}
-}
-
-func (wdw *WorkDoneWriter) Write(p []byte) (n int, err error) {
+func (wdw *workDoneWriter) Write(p []byte) (n int, err error) {
 	wdw.wd.Report(wdw.ctx, string(p), 0)
 	// Don't fail just because of a failure to report progress.
 	return len(p), nil
diff --git a/gopls/internal/lsp/progress/progress_test.go b/gopls/internal/progress/progress_test.go
similarity index 94%
rename from gopls/internal/lsp/progress/progress_test.go
rename to gopls/internal/progress/progress_test.go
index ef87eba..642103a 100644
--- a/gopls/internal/lsp/progress/progress_test.go
+++ b/gopls/internal/progress/progress_test.go
@@ -10,7 +10,7 @@
 	"sync"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 type fakeClient struct {
@@ -63,7 +63,7 @@
 	return nil
 }
 
-func setup(token protocol.ProgressToken) (context.Context, *Tracker, *fakeClient) {
+func setup() (context.Context, *Tracker, *fakeClient) {
 	c := &fakeClient{}
 	tracker := NewTracker(c)
 	tracker.SetSupportsWorkDoneProgress(true)
@@ -109,7 +109,7 @@
 	} {
 		test := test
 		t.Run(test.name, func(t *testing.T) {
-			ctx, tracker, client := setup(test.token)
+			ctx, tracker, client := setup()
 			ctx, cancel := context.WithCancel(ctx)
 			defer cancel()
 			tracker.supportsWorkDoneProgress = test.supported
@@ -147,7 +147,7 @@
 
 func TestProgressTracker_Cancellation(t *testing.T) {
 	for _, token := range []protocol.ProgressToken{nil, 1, "a"} {
-		ctx, tracker, _ := setup(token)
+		ctx, tracker, _ := setup()
 		var canceled bool
 		cancel := func() { canceled = true }
 		work := tracker.Start(ctx, "work", "message", token, cancel)
diff --git a/gopls/internal/lsp/protocol/codeactionkind.go b/gopls/internal/protocol/codeactionkind.go
similarity index 100%
rename from gopls/internal/lsp/protocol/codeactionkind.go
rename to gopls/internal/protocol/codeactionkind.go
diff --git a/gopls/internal/lsp/command/command_gen.go b/gopls/internal/protocol/command/command_gen.go
similarity index 98%
rename from gopls/internal/lsp/command/command_gen.go
rename to gopls/internal/protocol/command/command_gen.go
index fb518c7..2ee0a5d 100644
--- a/gopls/internal/lsp/command/command_gen.go
+++ b/gopls/internal/protocol/command/command_gen.go
@@ -15,7 +15,7 @@
 	"context"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // Symbolic names for gopls commands, excluding "gopls." prefix.
@@ -118,13 +118,13 @@
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
-		return nil, s.ApplyFix(ctx, a0)
+		return s.ApplyFix(ctx, a0)
 	case "gopls.change_signature":
 		var a0 ChangeSignatureArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
-		return nil, s.ChangeSignature(ctx, a0)
+		return s.ChangeSignature(ctx, a0)
 	case "gopls.check_upgrades":
 		var a0 CheckUpgradesArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
diff --git a/gopls/internal/lsp/command/commandmeta/meta.go b/gopls/internal/protocol/command/commandmeta/meta.go
similarity index 98%
rename from gopls/internal/lsp/command/commandmeta/meta.go
rename to gopls/internal/protocol/command/commandmeta/meta.go
index bf85c4f..d468534 100644
--- a/gopls/internal/lsp/command/commandmeta/meta.go
+++ b/gopls/internal/protocol/command/commandmeta/meta.go
@@ -17,7 +17,7 @@
 
 	"golang.org/x/tools/go/ast/astutil"
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/gopls/internal/lsp/command"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 )
 
 type Command struct {
@@ -52,7 +52,7 @@
 			Mode:       packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedImports | packages.NeedDeps,
 			BuildFlags: []string{"-tags=generate"},
 		},
-		"golang.org/x/tools/gopls/internal/lsp/command",
+		"golang.org/x/tools/gopls/internal/protocol/command",
 	)
 	if err != nil {
 		return nil, nil, fmt.Errorf("packages.Load: %v", err)
diff --git a/gopls/internal/lsp/command/gen/gen.go b/gopls/internal/protocol/command/gen/gen.go
similarity index 94%
rename from gopls/internal/lsp/command/gen/gen.go
rename to gopls/internal/protocol/command/gen/gen.go
index 3dde354..15ff467 100644
--- a/gopls/internal/lsp/command/gen/gen.go
+++ b/gopls/internal/protocol/command/gen/gen.go
@@ -12,7 +12,7 @@
 	"go/types"
 	"text/template"
 
-	"golang.org/x/tools/gopls/internal/lsp/command/commandmeta"
+	"golang.org/x/tools/gopls/internal/protocol/command/commandmeta"
 	"golang.org/x/tools/internal/imports"
 )
 
@@ -112,10 +112,10 @@
 		Imports: map[string]bool{
 			"context": true,
 			"fmt":     true,
-			"golang.org/x/tools/gopls/internal/lsp/protocol": true,
+			"golang.org/x/tools/gopls/internal/protocol": true,
 		},
 	}
-	const thispkg = "golang.org/x/tools/gopls/internal/lsp/command"
+	const thispkg = "golang.org/x/tools/gopls/internal/protocol/command"
 	for _, c := range d.Commands {
 		for _, arg := range c.Args {
 			pth := pkgPath(arg.Type)
diff --git a/gopls/internal/lsp/command/generate.go b/gopls/internal/protocol/command/generate.go
similarity index 87%
rename from gopls/internal/lsp/command/generate.go
rename to gopls/internal/protocol/command/generate.go
index b7907e6..f63b2e6 100644
--- a/gopls/internal/lsp/command/generate.go
+++ b/gopls/internal/protocol/command/generate.go
@@ -11,7 +11,7 @@
 	"log"
 	"os"
 
-	"golang.org/x/tools/gopls/internal/lsp/command/gen"
+	"golang.org/x/tools/gopls/internal/protocol/command/gen"
 )
 
 func main() {
diff --git a/gopls/internal/lsp/command/interface.go b/gopls/internal/protocol/command/interface.go
similarity index 95%
rename from gopls/internal/lsp/command/interface.go
rename to gopls/internal/protocol/command/interface.go
index 152387c..b0dd060 100644
--- a/gopls/internal/lsp/command/interface.go
+++ b/gopls/internal/protocol/command/interface.go
@@ -17,7 +17,7 @@
 import (
 	"context"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/vulncheck"
 )
 
@@ -44,7 +44,7 @@
 	// ApplyFix: Apply a fix
 	//
 	// Applies a fix to a region of source code.
-	ApplyFix(context.Context, ApplyFixArgs) error
+	ApplyFix(context.Context, ApplyFixArgs) (*protocol.WorkspaceEdit, error)
 
 	// Test: Run test(s) (legacy)
 	//
@@ -216,7 +216,7 @@
 	//
 	// This command is experimental, currently only supporting parameter removal.
 	// Its signature will certainly change in the future (pun intended).
-	ChangeSignature(context.Context, ChangeSignatureArgs) error
+	ChangeSignature(context.Context, ChangeSignatureArgs) (*protocol.WorkspaceEdit, error)
 
 	// DiagnoseFiles: Cause server to publish diagnostics for the specified files.
 	//
@@ -251,12 +251,22 @@
 // TODO(rFindley): document the rest of these once the docgen is fleshed out.
 
 type ApplyFixArgs struct {
-	// The fix to apply.
+	// The name of the fix to apply.
+	//
+	// For fixes suggested by analyzers, this is a string constant
+	// advertised by the analyzer that matches the Category of
+	// the analysis.Diagnostic with a SuggestedFix containing no edits.
+	//
+	// For fixes suggested by code actions, this is a string agreed
+	// upon by the code action and golang.ApplyFix.
 	Fix string
+
 	// The file URI for the document to fix.
 	URI protocol.DocumentURI
 	// The document range to scan for fixes.
 	Range protocol.Range
+	// Whether to resolve and return the edits.
+	ResolveEdits bool
 }
 
 type URIArg struct {
@@ -500,6 +510,8 @@
 // ChangeSignatureArgs specifies a "change signature" refactoring to perform.
 type ChangeSignatureArgs struct {
 	RemoveParameter protocol.Location
+	// Whether to resolve and return the edits.
+	ResolveEdits bool
 }
 
 // DiagnoseFilesArgs specifies a set of files for which diagnostics are wanted.
diff --git a/gopls/internal/lsp/command/interface_test.go b/gopls/internal/protocol/command/interface_test.go
similarity index 91%
rename from gopls/internal/lsp/command/interface_test.go
rename to gopls/internal/protocol/command/interface_test.go
index f81a2aa..4ddc5fa 100644
--- a/gopls/internal/lsp/command/interface_test.go
+++ b/gopls/internal/protocol/command/interface_test.go
@@ -9,7 +9,7 @@
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"golang.org/x/tools/gopls/internal/lsp/command/gen"
+	"golang.org/x/tools/gopls/internal/protocol/command/gen"
 	"golang.org/x/tools/internal/testenv"
 )
 
diff --git a/gopls/internal/lsp/command/util.go b/gopls/internal/protocol/command/util.go
similarity index 100%
rename from gopls/internal/lsp/command/util.go
rename to gopls/internal/protocol/command/util.go
diff --git a/gopls/internal/lsp/protocol/context.go b/gopls/internal/protocol/context.go
similarity index 64%
rename from gopls/internal/lsp/protocol/context.go
rename to gopls/internal/protocol/context.go
index a9ef48d..5f3151c 100644
--- a/gopls/internal/lsp/protocol/context.go
+++ b/gopls/internal/protocol/context.go
@@ -7,6 +7,7 @@
 import (
 	"bytes"
 	"context"
+	"sync"
 
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/core"
@@ -38,8 +39,27 @@
 	if event.IsError(ev) {
 		msg.Type = Error
 	}
-	// TODO(adonovan): the goroutine here could cause log
-	// messages to be delivered out of order! Use a queue.
-	go client.LogMessage(xcontext.Detach(ctx), msg)
+
+	// The background goroutine lives forever once started,
+	// and ensures log messages are sent in order (#61216).
+	startLogSenderOnce.Do(func() {
+		go func() {
+			for f := range logQueue {
+				f()
+			}
+		}()
+	})
+
+	// Add the log item to a queue, rather than sending a
+	// window/logMessage request to the client synchronously,
+	// which would slow down this thread.
+	ctx2 := xcontext.Detach(ctx)
+	logQueue <- func() { client.LogMessage(ctx2, msg) }
+
 	return ctx
 }
+
+var (
+	startLogSenderOnce sync.Once
+	logQueue           = make(chan func(), 100) // big enough for a large transient burst
+)
diff --git a/gopls/internal/lsp/protocol/doc.go b/gopls/internal/protocol/doc.go
similarity index 100%
rename from gopls/internal/lsp/protocol/doc.go
rename to gopls/internal/protocol/doc.go
diff --git a/gopls/internal/lsp/protocol/edits.go b/gopls/internal/protocol/edits.go
similarity index 76%
rename from gopls/internal/lsp/protocol/edits.go
rename to gopls/internal/protocol/edits.go
index 71d4427..53fd4cf 100644
--- a/gopls/internal/lsp/protocol/edits.go
+++ b/gopls/internal/protocol/edits.go
@@ -101,3 +101,28 @@
 	}
 	return result
 }
+
+// TextEditsToDocumentChanges converts a set of edits within the
+// specified (versioned) file to a singleton list of DocumentChanges
+// (as required for a WorkspaceEdit).
+func TextEditsToDocumentChanges(uri DocumentURI, version int32, edits []TextEdit) []DocumentChanges {
+	return []DocumentChanges{{
+		TextDocumentEdit: &TextDocumentEdit{
+			TextDocument: OptionalVersionedTextDocumentIdentifier{
+				Version:                version,
+				TextDocumentIdentifier: TextDocumentIdentifier{URI: uri},
+			},
+			Edits: AsAnnotatedTextEdits(edits),
+		},
+	}}
+}
+
+// TextDocumentEditsToDocumentChanges wraps each TextDocumentEdit in a DocumentChange.
+func TextDocumentEditsToDocumentChanges(edits []TextDocumentEdit) []DocumentChanges {
+	changes := []DocumentChanges{} // non-nil
+	for _, edit := range edits {
+		edit := edit
+		changes = append(changes, DocumentChanges{TextDocumentEdit: &edit})
+	}
+	return changes
+}
diff --git a/gopls/internal/lsp/protocol/enums.go b/gopls/internal/protocol/enums.go
similarity index 86%
rename from gopls/internal/lsp/protocol/enums.go
rename to gopls/internal/protocol/enums.go
index 87c14d8..e3f8b51 100644
--- a/gopls/internal/lsp/protocol/enums.go
+++ b/gopls/internal/protocol/enums.go
@@ -117,7 +117,7 @@
 	namesTextDocumentSaveReason[int(FocusOut)] = "FocusOut"
 }
 
-func formatEnum(f fmt.State, c rune, i int, names []string, unknown string) {
+func formatEnum(f fmt.State, i int, names []string, unknown string) {
 	s := ""
 	if i >= 0 && i < len(names) {
 		s = names[i]
@@ -130,45 +130,45 @@
 }
 
 func (e TextDocumentSyncKind) Format(f fmt.State, c rune) {
-	formatEnum(f, c, int(e), namesTextDocumentSyncKind[:], "TextDocumentSyncKind")
+	formatEnum(f, int(e), namesTextDocumentSyncKind[:], "TextDocumentSyncKind")
 }
 
 func (e MessageType) Format(f fmt.State, c rune) {
-	formatEnum(f, c, int(e), namesMessageType[:], "MessageType")
+	formatEnum(f, int(e), namesMessageType[:], "MessageType")
 }
 
 func (e FileChangeType) Format(f fmt.State, c rune) {
-	formatEnum(f, c, int(e), namesFileChangeType[:], "FileChangeType")
+	formatEnum(f, int(e), namesFileChangeType[:], "FileChangeType")
 }
 
 func (e CompletionTriggerKind) Format(f fmt.State, c rune) {
-	formatEnum(f, c, int(e), namesCompletionTriggerKind[:], "CompletionTriggerKind")
+	formatEnum(f, int(e), namesCompletionTriggerKind[:], "CompletionTriggerKind")
 }
 
 func (e DiagnosticSeverity) Format(f fmt.State, c rune) {
-	formatEnum(f, c, int(e), namesDiagnosticSeverity[:], "DiagnosticSeverity")
+	formatEnum(f, int(e), namesDiagnosticSeverity[:], "DiagnosticSeverity")
 }
 
 func (e DiagnosticTag) Format(f fmt.State, c rune) {
-	formatEnum(f, c, int(e), namesDiagnosticTag[:], "DiagnosticTag")
+	formatEnum(f, int(e), namesDiagnosticTag[:], "DiagnosticTag")
 }
 
 func (e CompletionItemKind) Format(f fmt.State, c rune) {
-	formatEnum(f, c, int(e), namesCompletionItemKind[:], "CompletionItemKind")
+	formatEnum(f, int(e), namesCompletionItemKind[:], "CompletionItemKind")
 }
 
 func (e InsertTextFormat) Format(f fmt.State, c rune) {
-	formatEnum(f, c, int(e), namesInsertTextFormat[:], "InsertTextFormat")
+	formatEnum(f, int(e), namesInsertTextFormat[:], "InsertTextFormat")
 }
 
 func (e DocumentHighlightKind) Format(f fmt.State, c rune) {
-	formatEnum(f, c, int(e), namesDocumentHighlightKind[:], "DocumentHighlightKind")
+	formatEnum(f, int(e), namesDocumentHighlightKind[:], "DocumentHighlightKind")
 }
 
 func (e SymbolKind) Format(f fmt.State, c rune) {
-	formatEnum(f, c, int(e), namesSymbolKind[:], "SymbolKind")
+	formatEnum(f, int(e), namesSymbolKind[:], "SymbolKind")
 }
 
 func (e TextDocumentSaveReason) Format(f fmt.State, c rune) {
-	formatEnum(f, c, int(e), namesTextDocumentSaveReason[:], "TextDocumentSaveReason")
+	formatEnum(f, int(e), namesTextDocumentSaveReason[:], "TextDocumentSaveReason")
 }
diff --git a/gopls/internal/lsp/protocol/generate/README.md b/gopls/internal/protocol/generate/README.md
similarity index 100%
rename from gopls/internal/lsp/protocol/generate/README.md
rename to gopls/internal/protocol/generate/README.md
diff --git a/gopls/internal/lsp/protocol/generate/generate.go b/gopls/internal/protocol/generate/generate.go
similarity index 100%
rename from gopls/internal/lsp/protocol/generate/generate.go
rename to gopls/internal/protocol/generate/generate.go
diff --git a/gopls/internal/lsp/protocol/generate/main.go b/gopls/internal/protocol/generate/main.go
similarity index 96%
rename from gopls/internal/lsp/protocol/generate/main.go
rename to gopls/internal/protocol/generate/main.go
index cf89a52..f70c581 100644
--- a/gopls/internal/lsp/protocol/generate/main.go
+++ b/gopls/internal/protocol/generate/main.go
@@ -100,7 +100,6 @@
 		`import (
 	"context"
 
-	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/internal/jsonrpc2"
 )
 `)
@@ -110,12 +109,7 @@
 	}
 	out.WriteString("}\n\n")
 	out.WriteString(`func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier, r jsonrpc2.Request) (bool, error) {
-	defer func() {
-		if x := recover(); x != nil {
-			bug.Reportf("client panic in %s request", r.Method())
-			panic(x)
-		}
-	}()
+	defer recoverHandlerPanic(r.Method())
 	switch r.Method() {
 `)
 	for _, k := range ccases.keys() {
@@ -144,7 +138,6 @@
 		`import (
 	"context"
 
-	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/internal/jsonrpc2"
 )
 `)
@@ -156,12 +149,7 @@
 }
 
 func serverDispatch(ctx context.Context, server Server, reply jsonrpc2.Replier, r jsonrpc2.Request) (bool, error) {
-	defer func() {
-		if x := recover(); x != nil {
-			bug.Reportf("server panic in %s request", r.Method())
-			panic(x)
-		}
-	}()
+	defer recoverHandlerPanic(r.Method())
 	switch r.Method() {
 `)
 	for _, k := range scases.keys() {
diff --git a/gopls/internal/lsp/protocol/generate/main_test.go b/gopls/internal/protocol/generate/main_test.go
similarity index 100%
rename from gopls/internal/lsp/protocol/generate/main_test.go
rename to gopls/internal/protocol/generate/main_test.go
diff --git a/gopls/internal/lsp/protocol/generate/output.go b/gopls/internal/protocol/generate/output.go
similarity index 99%
rename from gopls/internal/lsp/protocol/generate/output.go
rename to gopls/internal/protocol/generate/output.go
index 18fc85c..fc64677 100644
--- a/gopls/internal/lsp/protocol/generate/output.go
+++ b/gopls/internal/protocol/generate/output.go
@@ -101,7 +101,7 @@
 			nm = "ParamConfiguration" // gopls compatibility
 		}
 		fmt.Fprintf(out, "\t\tvar params %s\n", nm)
-		fmt.Fprintf(out, "\t\tif err := unmarshalParams(r.Params(), &params); err != nil {\n")
+		fmt.Fprintf(out, "\t\tif err := UnmarshalJSON(r.Params(), &params); err != nil {\n")
 		fmt.Fprintf(out, "\t\t\treturn true, sendParseError(ctx, reply, err)\n\t\t}\n")
 		p = ", &params"
 	}
diff --git a/gopls/internal/lsp/protocol/generate/tables.go b/gopls/internal/protocol/generate/tables.go
similarity index 96%
rename from gopls/internal/lsp/protocol/generate/tables.go
rename to gopls/internal/protocol/generate/tables.go
index 2b744a5..ac428b5 100644
--- a/gopls/internal/lsp/protocol/generate/tables.go
+++ b/gopls/internal/protocol/generate/tables.go
@@ -63,6 +63,7 @@
 	{"CancelParams", "id"}:         "interface{}",
 	{"Command", "arguments"}:       "[]json.RawMessage",
 	{"CompletionItem", "textEdit"}: "TextEdit",
+	{"CodeAction", "data"}:         "json.RawMessage", // delay unmarshalling commands
 	{"Diagnostic", "code"}:         "interface{}",
 	{"Diagnostic", "data"}:         "json.RawMessage", // delay unmarshalling quickfixes
 
@@ -132,10 +133,9 @@
 
 	"Or_Declaration": "[]Location",
 	"Or_DidChangeConfigurationRegistrationOptions_section": "OrPSection_workspace_didChangeConfiguration",
-	"Or_GlobPattern":                "string",
-	"Or_InlayHintLabelPart_tooltip": "OrPTooltipPLabel",
-	"Or_InlayHint_tooltip":          "OrPTooltip_textDocument_inlayHint",
-	"Or_LSPAny":                     "interface{}",
+	"Or_InlayHintLabelPart_tooltip":                        "OrPTooltipPLabel",
+	"Or_InlayHint_tooltip":                                 "OrPTooltip_textDocument_inlayHint",
+	"Or_LSPAny":                                            "interface{}",
 
 	"Or_ParameterInformation_documentation":            "string",
 	"Or_ParameterInformation_label":                    "string",
@@ -150,6 +150,7 @@
 	"Or_Result_textDocument_typeDefinition":            "[]Location",
 	"Or_Result_workspace_symbol":                       "[]SymbolInformation",
 	"Or_TextDocumentContentChangeEvent":                "TextDocumentContentChangePartial",
+	"Or_RelativePattern_baseUri":                       "DocumentURI",
 
 	"Or_WorkspaceFoldersServerCapabilities_changeNotifications": "string",
 	"Or_WorkspaceSymbol_location":                               "OrPLocation_workspace_symbol",
diff --git a/gopls/internal/lsp/protocol/generate/typenames.go b/gopls/internal/protocol/generate/typenames.go
similarity index 100%
rename from gopls/internal/lsp/protocol/generate/typenames.go
rename to gopls/internal/protocol/generate/typenames.go
diff --git a/gopls/internal/lsp/protocol/generate/types.go b/gopls/internal/protocol/generate/types.go
similarity index 100%
rename from gopls/internal/lsp/protocol/generate/types.go
rename to gopls/internal/protocol/generate/types.go
diff --git a/gopls/internal/lsp/protocol/json_test.go b/gopls/internal/protocol/json_test.go
similarity index 92%
rename from gopls/internal/lsp/protocol/json_test.go
rename to gopls/internal/protocol/json_test.go
index 2753125..9aac110 100644
--- a/gopls/internal/lsp/protocol/json_test.go
+++ b/gopls/internal/protocol/json_test.go
@@ -12,7 +12,7 @@
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // verify that type errors in Initialize lsp messages don't cause
@@ -30,7 +30,7 @@
 
 // a recent Initialize message taken from a log (at some point
 // some field incompatibly changed from bool to int32)
-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"}]}`
+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/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"}]}`
 
 type DiffReporter struct {
 	path  cmp.Path
diff --git a/gopls/internal/lsp/protocol/log.go b/gopls/internal/protocol/log.go
similarity index 100%
rename from gopls/internal/lsp/protocol/log.go
rename to gopls/internal/protocol/log.go
diff --git a/gopls/internal/lsp/protocol/mapper.go b/gopls/internal/protocol/mapper.go
similarity index 100%
rename from gopls/internal/lsp/protocol/mapper.go
rename to gopls/internal/protocol/mapper.go
diff --git a/gopls/internal/lsp/protocol/mapper_test.go b/gopls/internal/protocol/mapper_test.go
similarity index 99%
rename from gopls/internal/lsp/protocol/mapper_test.go
rename to gopls/internal/protocol/mapper_test.go
index 7725769..8ba611a 100644
--- a/gopls/internal/lsp/protocol/mapper_test.go
+++ b/gopls/internal/protocol/mapper_test.go
@@ -9,7 +9,7 @@
 	"strings"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // This file tests Mapper's logic for converting between offsets,
diff --git a/gopls/internal/lsp/protocol/protocol.go b/gopls/internal/protocol/protocol.go
similarity index 91%
rename from gopls/internal/lsp/protocol/protocol.go
rename to gopls/internal/protocol/protocol.go
index 3ece42b..09bfaca 100644
--- a/gopls/internal/lsp/protocol/protocol.go
+++ b/gopls/internal/protocol/protocol.go
@@ -11,6 +11,8 @@
 	"fmt"
 	"io"
 
+	"golang.org/x/tools/gopls/internal/telemetry"
+	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/jsonrpc2"
 	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
@@ -241,7 +243,7 @@
 			return handler(ctx, replyWithDetachedContext, req)
 		}
 		var params CancelParams
-		if err := unmarshalParams(req.Params(), &params); err != nil {
+		if err := UnmarshalJSON(req.Params(), &params); err != nil {
 			return sendParseError(ctx, reply, err)
 		}
 		if n, ok := params.ID.(float64); ok {
@@ -271,16 +273,14 @@
 	sender.Notify(ctx, "$/cancelRequest", &CancelParams{ID: &id})
 }
 
-// unmarshalParams unmarshals msg into the variable pointed to by
-// params. In JSONRPC, request.params is optional, so msg may may be
+// UnmarshalJSON unmarshals msg into the variable pointed to by
+// params. In JSONRPC, optional messages may be
 // "null", in which case it is a no-op.
-func unmarshalParams(msg json.RawMessage, params any) error {
-	if len(msg) > 0 && !bytes.Equal(msg, []byte("null")) {
-		if err := json.Unmarshal(msg, params); err != nil {
-			return err
-		}
+func UnmarshalJSON(msg json.RawMessage, v any) error {
+	if len(msg) == 0 || bytes.Equal(msg, []byte("null")) {
+		return nil
 	}
-	return nil
+	return json.Unmarshal(msg, v)
 }
 
 func sendParseError(ctx context.Context, reply jsonrpc2.Replier, err error) error {
@@ -297,3 +297,17 @@
 	}
 	return x
 }
+
+func recoverHandlerPanic(method string) {
+	// Report panics in the handler goroutine,
+	// unless we have enabled the monitor,
+	// which reports all crashes.
+	if !telemetry.CrashMonitorSupported() {
+		defer func() {
+			if x := recover(); x != nil {
+				bug.Reportf("panic in %s request", method)
+				panic(x)
+			}
+		}()
+	}
+}
diff --git a/gopls/internal/lsp/protocol/semantic.go b/gopls/internal/protocol/semantic.go
similarity index 100%
rename from gopls/internal/lsp/protocol/semantic.go
rename to gopls/internal/protocol/semantic.go
diff --git a/gopls/internal/protocol/semtok/semtok.go b/gopls/internal/protocol/semtok/semtok.go
new file mode 100644
index 0000000..e69ec82
--- /dev/null
+++ b/gopls/internal/protocol/semtok/semtok.go
@@ -0,0 +1,101 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The semtok package provides an encoder for LSP's semantic tokens.
+package semtok
+
+import "sort"
+
+// A Token provides the extent and semantics of a token.
+type Token struct {
+	Line, Start uint32
+	Len         uint32
+	Type        TokenType
+	Modifiers   []string
+}
+
+type TokenType string
+
+const (
+	TokNamespace TokenType = "namespace"
+	TokType      TokenType = "type"
+	TokInterface TokenType = "interface"
+	TokTypeParam TokenType = "typeParameter"
+	TokParameter TokenType = "parameter"
+	TokVariable  TokenType = "variable"
+	TokMethod    TokenType = "method"
+	TokFunction  TokenType = "function"
+	TokKeyword   TokenType = "keyword"
+	TokComment   TokenType = "comment"
+	TokString    TokenType = "string"
+	TokNumber    TokenType = "number"
+	TokOperator  TokenType = "operator"
+	TokMacro     TokenType = "macro" // for templates
+)
+
+// Encode returns the LSP encoding of a sequence of tokens.
+// The noStrings, noNumbers options cause strings, numbers to be skipped.
+// The lists of types and modifiers determines the bitfield encoding.
+func Encode(
+	tokens []Token,
+	noStrings, noNumbers bool,
+	types, modifiers []string) []uint32 {
+
+	// binary operators, at least, will be out of order
+	sort.Slice(tokens, func(i, j int) bool {
+		if tokens[i].Line != tokens[j].Line {
+			return tokens[i].Line < tokens[j].Line
+		}
+		return tokens[i].Start < tokens[j].Start
+	})
+
+	typeMap := make(map[TokenType]int)
+	for i, t := range types {
+		typeMap[TokenType(t)] = i
+	}
+
+	modMap := make(map[string]int)
+	for i, m := range modifiers {
+		modMap[m] = 1 << uint(i) // go 1.12 compatibility
+	}
+
+	// each semantic token needs five values
+	// (see Integer Encoding for Tokens in the LSP spec)
+	x := make([]uint32, 5*len(tokens))
+	var j int
+	var last Token
+	for i := 0; i < len(tokens); i++ {
+		item := tokens[i]
+		typ, ok := typeMap[item.Type]
+		if !ok {
+			continue // client doesn't want typeStr
+		}
+		if item.Type == TokString && noStrings {
+			continue
+		}
+		if item.Type == TokNumber && noNumbers {
+			continue
+		}
+		if j == 0 {
+			x[0] = tokens[0].Line
+		} else {
+			x[j] = item.Line - last.Line
+		}
+		x[j+1] = item.Start
+		if j > 0 && x[j] == 0 {
+			x[j+1] = item.Start - last.Start
+		}
+		x[j+2] = item.Len
+		x[j+3] = uint32(typ)
+		mask := 0
+		for _, s := range item.Modifiers {
+			// modMap[s] is 0 if the client doesn't want this modifier
+			mask |= modMap[s]
+		}
+		x[j+4] = uint32(mask)
+		j += 5
+		last = item
+	}
+	return x[:j]
+}
diff --git a/gopls/internal/lsp/protocol/span.go b/gopls/internal/protocol/span.go
similarity index 100%
rename from gopls/internal/lsp/protocol/span.go
rename to gopls/internal/protocol/span.go
diff --git a/gopls/internal/lsp/protocol/tsclient.go b/gopls/internal/protocol/tsclient.go
similarity index 91%
rename from gopls/internal/lsp/protocol/tsclient.go
rename to gopls/internal/protocol/tsclient.go
index 6ea20f0..651c679 100644
--- a/gopls/internal/lsp/protocol/tsclient.go
+++ b/gopls/internal/protocol/tsclient.go
@@ -13,7 +13,6 @@
 import (
 	"context"
 
-	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/internal/jsonrpc2"
 )
 
@@ -41,16 +40,11 @@
 }
 
 func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier, r jsonrpc2.Request) (bool, error) {
-	defer func() {
-		if x := recover(); x != nil {
-			bug.Reportf("client panic in %s request", r.Method())
-			panic(x)
-		}
-	}()
+	defer recoverHandlerPanic(r.Method())
 	switch r.Method() {
 	case "$/logTrace":
 		var params LogTraceParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := client.LogTrace(ctx, &params)
@@ -58,7 +52,7 @@
 
 	case "$/progress":
 		var params ProgressParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := client.Progress(ctx, &params)
@@ -66,7 +60,7 @@
 
 	case "client/registerCapability":
 		var params RegistrationParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := client.RegisterCapability(ctx, &params)
@@ -74,7 +68,7 @@
 
 	case "client/unregisterCapability":
 		var params UnregistrationParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := client.UnregisterCapability(ctx, &params)
@@ -82,7 +76,7 @@
 
 	case "telemetry/event":
 		var params interface{}
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := client.Event(ctx, &params)
@@ -90,7 +84,7 @@
 
 	case "textDocument/publishDiagnostics":
 		var params PublishDiagnosticsParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := client.PublishDiagnostics(ctx, &params)
@@ -98,7 +92,7 @@
 
 	case "window/logMessage":
 		var params LogMessageParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := client.LogMessage(ctx, &params)
@@ -106,7 +100,7 @@
 
 	case "window/showDocument":
 		var params ShowDocumentParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := client.ShowDocument(ctx, &params)
@@ -117,7 +111,7 @@
 
 	case "window/showMessage":
 		var params ShowMessageParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := client.ShowMessage(ctx, &params)
@@ -125,7 +119,7 @@
 
 	case "window/showMessageRequest":
 		var params ShowMessageRequestParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := client.ShowMessageRequest(ctx, &params)
@@ -136,7 +130,7 @@
 
 	case "window/workDoneProgress/create":
 		var params WorkDoneProgressCreateParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := client.WorkDoneProgressCreate(ctx, &params)
@@ -144,7 +138,7 @@
 
 	case "workspace/applyEdit":
 		var params ApplyWorkspaceEditParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := client.ApplyEdit(ctx, &params)
@@ -159,7 +153,7 @@
 
 	case "workspace/configuration":
 		var params ParamConfiguration
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := client.Configuration(ctx, &params)
diff --git a/gopls/internal/lsp/protocol/tsdocument_changes.go b/gopls/internal/protocol/tsdocument_changes.go
similarity index 100%
rename from gopls/internal/lsp/protocol/tsdocument_changes.go
rename to gopls/internal/protocol/tsdocument_changes.go
diff --git a/gopls/internal/lsp/protocol/tsjson.go b/gopls/internal/protocol/tsjson.go
similarity index 99%
rename from gopls/internal/lsp/protocol/tsjson.go
rename to gopls/internal/protocol/tsjson.go
index f069e0e..c19c435 100644
--- a/gopls/internal/lsp/protocol/tsjson.go
+++ b/gopls/internal/protocol/tsjson.go
@@ -473,6 +473,36 @@
 	return &UnmarshalError{"unmarshal failed to match one of [NotebookCellTextDocumentFilter TextDocumentFilter]"}
 }
 
+func (t Or_GlobPattern) MarshalJSON() ([]byte, error) {
+	switch x := t.Value.(type) {
+	case Pattern:
+		return json.Marshal(x)
+	case RelativePattern:
+		return json.Marshal(x)
+	case nil:
+		return []byte("null"), nil
+	}
+	return nil, fmt.Errorf("type %T not one of [Pattern RelativePattern]", t)
+}
+
+func (t *Or_GlobPattern) UnmarshalJSON(x []byte) error {
+	if string(x) == "null" {
+		t.Value = nil
+		return nil
+	}
+	var h0 Pattern
+	if err := json.Unmarshal(x, &h0); err == nil {
+		t.Value = h0
+		return nil
+	}
+	var h1 RelativePattern
+	if err := json.Unmarshal(x, &h1); err == nil {
+		t.Value = h1
+		return nil
+	}
+	return &UnmarshalError{"unmarshal failed to match one of [Pattern RelativePattern]"}
+}
+
 func (t Or_Hover_contents) MarshalJSON() ([]byte, error) {
 	switch x := t.Value.(type) {
 	case MarkedString:
@@ -854,36 +884,6 @@
 	return &UnmarshalError{"unmarshal failed to match one of [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]"}
 }
 
-func (t Or_RelativePattern_baseUri) MarshalJSON() ([]byte, error) {
-	switch x := t.Value.(type) {
-	case URI:
-		return json.Marshal(x)
-	case WorkspaceFolder:
-		return json.Marshal(x)
-	case nil:
-		return []byte("null"), nil
-	}
-	return nil, fmt.Errorf("type %T not one of [URI WorkspaceFolder]", t)
-}
-
-func (t *Or_RelativePattern_baseUri) UnmarshalJSON(x []byte) error {
-	if string(x) == "null" {
-		t.Value = nil
-		return nil
-	}
-	var h0 URI
-	if err := json.Unmarshal(x, &h0); err == nil {
-		t.Value = h0
-		return nil
-	}
-	var h1 WorkspaceFolder
-	if err := json.Unmarshal(x, &h1); err == nil {
-		t.Value = h1
-		return nil
-	}
-	return &UnmarshalError{"unmarshal failed to match one of [URI WorkspaceFolder]"}
-}
-
 func (t Or_Result_textDocument_codeAction_Item0_Elem) MarshalJSON() ([]byte, error) {
 	switch x := t.Value.(type) {
 	case CodeAction:
diff --git a/gopls/internal/lsp/protocol/tsprotocol.go b/gopls/internal/protocol/tsprotocol.go
similarity index 99%
rename from gopls/internal/lsp/protocol/tsprotocol.go
rename to gopls/internal/protocol/tsprotocol.go
index 48adb18..7994e66 100644
--- a/gopls/internal/lsp/protocol/tsprotocol.go
+++ b/gopls/internal/protocol/tsprotocol.go
@@ -489,7 +489,7 @@
 	// a `textDocument/codeAction` and a `codeAction/resolve` request.
 	//
 	// @since 3.16.0
-	Data interface{} `json:"data,omitempty"`
+	Data *json.RawMessage `json:"data,omitempty"`
 }
 
 // The Client Capabilities of a {@link CodeActionRequest}.
@@ -2121,7 +2121,7 @@
 // The glob pattern. Either a string pattern or a relative pattern.
 //
 // @since 3.17.0
-type GlobPattern = string // (alias)
+type GlobPattern = Or_GlobPattern // (alias)
 // The result of a hover request.
 type Hover struct {
 	// The hover's content
@@ -3108,6 +3108,11 @@
 	Value interface{} `json:"value"`
 }
 
+// created for Or [Pattern RelativePattern]
+type Or_GlobPattern struct {
+	Value interface{} `json:"value"`
+}
+
 // created for Or [MarkedString MarkupContent []MarkedString]
 type Or_Hover_contents struct {
 	Value interface{} `json:"value"`
@@ -3168,11 +3173,6 @@
 	Value interface{} `json:"value"`
 }
 
-// created for Or [URI WorkspaceFolder]
-type Or_RelativePattern_baseUri struct {
-	Value interface{} `json:"value"`
-}
-
 // created for Or [CodeAction Command]
 type Or_Result_textDocument_codeAction_Item0_Elem struct {
 	Value interface{} `json:"value"`
@@ -3656,7 +3656,7 @@
 type RelativePattern struct {
 	// A workspace folder or a base URI to which this pattern will be matched
 	// against relatively.
-	BaseURI Or_RelativePattern_baseUri `json:"baseUri"`
+	BaseURI DocumentURI `json:"baseUri"`
 	// The actual glob pattern;
 	Pattern Pattern `json:"pattern"`
 }
diff --git a/gopls/internal/lsp/protocol/tsserver.go b/gopls/internal/protocol/tsserver.go
similarity index 90%
rename from gopls/internal/lsp/protocol/tsserver.go
rename to gopls/internal/protocol/tsserver.go
index a928276..f667da4 100644
--- a/gopls/internal/lsp/protocol/tsserver.go
+++ b/gopls/internal/protocol/tsserver.go
@@ -13,7 +13,6 @@
 import (
 	"context"
 
-	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/internal/jsonrpc2"
 )
 
@@ -95,16 +94,11 @@
 }
 
 func serverDispatch(ctx context.Context, server Server, reply jsonrpc2.Replier, r jsonrpc2.Request) (bool, error) {
-	defer func() {
-		if x := recover(); x != nil {
-			bug.Reportf("server panic in %s request", r.Method())
-			panic(x)
-		}
-	}()
+	defer recoverHandlerPanic(r.Method())
 	switch r.Method() {
 	case "$/progress":
 		var params ProgressParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.Progress(ctx, &params)
@@ -112,7 +106,7 @@
 
 	case "$/setTrace":
 		var params SetTraceParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.SetTrace(ctx, &params)
@@ -120,7 +114,7 @@
 
 	case "callHierarchy/incomingCalls":
 		var params CallHierarchyIncomingCallsParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.IncomingCalls(ctx, &params)
@@ -131,7 +125,7 @@
 
 	case "callHierarchy/outgoingCalls":
 		var params CallHierarchyOutgoingCallsParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.OutgoingCalls(ctx, &params)
@@ -142,7 +136,7 @@
 
 	case "codeAction/resolve":
 		var params CodeAction
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.ResolveCodeAction(ctx, &params)
@@ -153,7 +147,7 @@
 
 	case "codeLens/resolve":
 		var params CodeLens
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.ResolveCodeLens(ctx, &params)
@@ -164,7 +158,7 @@
 
 	case "completionItem/resolve":
 		var params CompletionItem
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.ResolveCompletionItem(ctx, &params)
@@ -175,7 +169,7 @@
 
 	case "documentLink/resolve":
 		var params DocumentLink
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.ResolveDocumentLink(ctx, &params)
@@ -190,7 +184,7 @@
 
 	case "initialize":
 		var params ParamInitialize
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Initialize(ctx, &params)
@@ -201,7 +195,7 @@
 
 	case "initialized":
 		var params InitializedParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.Initialized(ctx, &params)
@@ -209,7 +203,7 @@
 
 	case "inlayHint/resolve":
 		var params InlayHint
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Resolve(ctx, &params)
@@ -220,7 +214,7 @@
 
 	case "notebookDocument/didChange":
 		var params DidChangeNotebookDocumentParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidChangeNotebookDocument(ctx, &params)
@@ -228,7 +222,7 @@
 
 	case "notebookDocument/didClose":
 		var params DidCloseNotebookDocumentParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidCloseNotebookDocument(ctx, &params)
@@ -236,7 +230,7 @@
 
 	case "notebookDocument/didOpen":
 		var params DidOpenNotebookDocumentParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidOpenNotebookDocument(ctx, &params)
@@ -244,7 +238,7 @@
 
 	case "notebookDocument/didSave":
 		var params DidSaveNotebookDocumentParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidSaveNotebookDocument(ctx, &params)
@@ -256,7 +250,7 @@
 
 	case "textDocument/codeAction":
 		var params CodeActionParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.CodeAction(ctx, &params)
@@ -267,7 +261,7 @@
 
 	case "textDocument/codeLens":
 		var params CodeLensParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.CodeLens(ctx, &params)
@@ -278,7 +272,7 @@
 
 	case "textDocument/colorPresentation":
 		var params ColorPresentationParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.ColorPresentation(ctx, &params)
@@ -289,7 +283,7 @@
 
 	case "textDocument/completion":
 		var params CompletionParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Completion(ctx, &params)
@@ -300,7 +294,7 @@
 
 	case "textDocument/declaration":
 		var params DeclarationParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Declaration(ctx, &params)
@@ -311,7 +305,7 @@
 
 	case "textDocument/definition":
 		var params DefinitionParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Definition(ctx, &params)
@@ -322,7 +316,7 @@
 
 	case "textDocument/diagnostic":
 		var params string
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Diagnostic(ctx, &params)
@@ -333,7 +327,7 @@
 
 	case "textDocument/didChange":
 		var params DidChangeTextDocumentParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidChange(ctx, &params)
@@ -341,7 +335,7 @@
 
 	case "textDocument/didClose":
 		var params DidCloseTextDocumentParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidClose(ctx, &params)
@@ -349,7 +343,7 @@
 
 	case "textDocument/didOpen":
 		var params DidOpenTextDocumentParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidOpen(ctx, &params)
@@ -357,7 +351,7 @@
 
 	case "textDocument/didSave":
 		var params DidSaveTextDocumentParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidSave(ctx, &params)
@@ -365,7 +359,7 @@
 
 	case "textDocument/documentColor":
 		var params DocumentColorParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.DocumentColor(ctx, &params)
@@ -376,7 +370,7 @@
 
 	case "textDocument/documentHighlight":
 		var params DocumentHighlightParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.DocumentHighlight(ctx, &params)
@@ -387,7 +381,7 @@
 
 	case "textDocument/documentLink":
 		var params DocumentLinkParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.DocumentLink(ctx, &params)
@@ -398,7 +392,7 @@
 
 	case "textDocument/documentSymbol":
 		var params DocumentSymbolParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.DocumentSymbol(ctx, &params)
@@ -409,7 +403,7 @@
 
 	case "textDocument/foldingRange":
 		var params FoldingRangeParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.FoldingRange(ctx, &params)
@@ -420,7 +414,7 @@
 
 	case "textDocument/formatting":
 		var params DocumentFormattingParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Formatting(ctx, &params)
@@ -431,7 +425,7 @@
 
 	case "textDocument/hover":
 		var params HoverParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Hover(ctx, &params)
@@ -442,7 +436,7 @@
 
 	case "textDocument/implementation":
 		var params ImplementationParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Implementation(ctx, &params)
@@ -453,7 +447,7 @@
 
 	case "textDocument/inlayHint":
 		var params InlayHintParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.InlayHint(ctx, &params)
@@ -464,7 +458,7 @@
 
 	case "textDocument/inlineCompletion":
 		var params InlineCompletionParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.InlineCompletion(ctx, &params)
@@ -475,7 +469,7 @@
 
 	case "textDocument/inlineValue":
 		var params InlineValueParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.InlineValue(ctx, &params)
@@ -486,7 +480,7 @@
 
 	case "textDocument/linkedEditingRange":
 		var params LinkedEditingRangeParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.LinkedEditingRange(ctx, &params)
@@ -497,7 +491,7 @@
 
 	case "textDocument/moniker":
 		var params MonikerParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Moniker(ctx, &params)
@@ -508,7 +502,7 @@
 
 	case "textDocument/onTypeFormatting":
 		var params DocumentOnTypeFormattingParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.OnTypeFormatting(ctx, &params)
@@ -519,7 +513,7 @@
 
 	case "textDocument/prepareCallHierarchy":
 		var params CallHierarchyPrepareParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.PrepareCallHierarchy(ctx, &params)
@@ -530,7 +524,7 @@
 
 	case "textDocument/prepareRename":
 		var params PrepareRenameParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.PrepareRename(ctx, &params)
@@ -541,7 +535,7 @@
 
 	case "textDocument/prepareTypeHierarchy":
 		var params TypeHierarchyPrepareParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.PrepareTypeHierarchy(ctx, &params)
@@ -552,7 +546,7 @@
 
 	case "textDocument/rangeFormatting":
 		var params DocumentRangeFormattingParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.RangeFormatting(ctx, &params)
@@ -563,7 +557,7 @@
 
 	case "textDocument/rangesFormatting":
 		var params DocumentRangesFormattingParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.RangesFormatting(ctx, &params)
@@ -574,7 +568,7 @@
 
 	case "textDocument/references":
 		var params ReferenceParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.References(ctx, &params)
@@ -585,7 +579,7 @@
 
 	case "textDocument/rename":
 		var params RenameParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Rename(ctx, &params)
@@ -596,7 +590,7 @@
 
 	case "textDocument/selectionRange":
 		var params SelectionRangeParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.SelectionRange(ctx, &params)
@@ -607,7 +601,7 @@
 
 	case "textDocument/semanticTokens/full":
 		var params SemanticTokensParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.SemanticTokensFull(ctx, &params)
@@ -618,7 +612,7 @@
 
 	case "textDocument/semanticTokens/full/delta":
 		var params SemanticTokensDeltaParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.SemanticTokensFullDelta(ctx, &params)
@@ -629,7 +623,7 @@
 
 	case "textDocument/semanticTokens/range":
 		var params SemanticTokensRangeParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.SemanticTokensRange(ctx, &params)
@@ -640,7 +634,7 @@
 
 	case "textDocument/signatureHelp":
 		var params SignatureHelpParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.SignatureHelp(ctx, &params)
@@ -651,7 +645,7 @@
 
 	case "textDocument/typeDefinition":
 		var params TypeDefinitionParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.TypeDefinition(ctx, &params)
@@ -662,7 +656,7 @@
 
 	case "textDocument/willSave":
 		var params WillSaveTextDocumentParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.WillSave(ctx, &params)
@@ -670,7 +664,7 @@
 
 	case "textDocument/willSaveWaitUntil":
 		var params WillSaveTextDocumentParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.WillSaveWaitUntil(ctx, &params)
@@ -681,7 +675,7 @@
 
 	case "typeHierarchy/subtypes":
 		var params TypeHierarchySubtypesParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Subtypes(ctx, &params)
@@ -692,7 +686,7 @@
 
 	case "typeHierarchy/supertypes":
 		var params TypeHierarchySupertypesParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Supertypes(ctx, &params)
@@ -703,7 +697,7 @@
 
 	case "window/workDoneProgress/cancel":
 		var params WorkDoneProgressCancelParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.WorkDoneProgressCancel(ctx, &params)
@@ -711,7 +705,7 @@
 
 	case "workspace/diagnostic":
 		var params WorkspaceDiagnosticParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.DiagnosticWorkspace(ctx, &params)
@@ -722,7 +716,7 @@
 
 	case "workspace/didChangeConfiguration":
 		var params DidChangeConfigurationParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidChangeConfiguration(ctx, &params)
@@ -730,7 +724,7 @@
 
 	case "workspace/didChangeWatchedFiles":
 		var params DidChangeWatchedFilesParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidChangeWatchedFiles(ctx, &params)
@@ -738,7 +732,7 @@
 
 	case "workspace/didChangeWorkspaceFolders":
 		var params DidChangeWorkspaceFoldersParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidChangeWorkspaceFolders(ctx, &params)
@@ -746,7 +740,7 @@
 
 	case "workspace/didCreateFiles":
 		var params CreateFilesParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidCreateFiles(ctx, &params)
@@ -754,7 +748,7 @@
 
 	case "workspace/didDeleteFiles":
 		var params DeleteFilesParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidDeleteFiles(ctx, &params)
@@ -762,7 +756,7 @@
 
 	case "workspace/didRenameFiles":
 		var params RenameFilesParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		err := server.DidRenameFiles(ctx, &params)
@@ -770,7 +764,7 @@
 
 	case "workspace/executeCommand":
 		var params ExecuteCommandParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.ExecuteCommand(ctx, &params)
@@ -781,7 +775,7 @@
 
 	case "workspace/symbol":
 		var params WorkspaceSymbolParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.Symbol(ctx, &params)
@@ -792,7 +786,7 @@
 
 	case "workspace/willCreateFiles":
 		var params CreateFilesParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.WillCreateFiles(ctx, &params)
@@ -803,7 +797,7 @@
 
 	case "workspace/willDeleteFiles":
 		var params DeleteFilesParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.WillDeleteFiles(ctx, &params)
@@ -814,7 +808,7 @@
 
 	case "workspace/willRenameFiles":
 		var params RenameFilesParams
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.WillRenameFiles(ctx, &params)
@@ -825,7 +819,7 @@
 
 	case "workspaceSymbol/resolve":
 		var params WorkspaceSymbol
-		if err := unmarshalParams(r.Params(), &params); err != nil {
+		if err := UnmarshalJSON(r.Params(), &params); err != nil {
 			return true, sendParseError(ctx, reply, err)
 		}
 		resp, err := server.ResolveWorkspaceSymbol(ctx, &params)
diff --git a/gopls/internal/lsp/protocol/uri.go b/gopls/internal/protocol/uri.go
similarity index 100%
rename from gopls/internal/lsp/protocol/uri.go
rename to gopls/internal/protocol/uri.go
diff --git a/gopls/internal/lsp/protocol/uri_test.go b/gopls/internal/protocol/uri_test.go
similarity index 98%
rename from gopls/internal/lsp/protocol/uri_test.go
rename to gopls/internal/protocol/uri_test.go
index 3c1d7e5..cad71dd 100644
--- a/gopls/internal/lsp/protocol/uri_test.go
+++ b/gopls/internal/protocol/uri_test.go
@@ -10,7 +10,7 @@
 import (
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // TestURIFromPath tests the conversion between URIs and filenames. The test cases
diff --git a/gopls/internal/lsp/protocol/uri_windows_test.go b/gopls/internal/protocol/uri_windows_test.go
similarity index 86%
rename from gopls/internal/lsp/protocol/uri_windows_test.go
rename to gopls/internal/protocol/uri_windows_test.go
index e607468..0847116 100644
--- a/gopls/internal/lsp/protocol/uri_windows_test.go
+++ b/gopls/internal/protocol/uri_windows_test.go
@@ -8,9 +8,10 @@
 package protocol_test
 
 import (
+	"path/filepath"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // TestURIFromPath tests the conversion between URIs and filenames. The test cases
@@ -18,6 +19,15 @@
 // tests by using only forward slashes, assuming that the standard library
 // functions filepath.ToSlash and filepath.FromSlash do not need testing.
 func TestURIFromPath(t *testing.T) {
+	rootPath, err := filepath.Abs("/")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(rootPath) < 2 || rootPath[1] != ':' {
+		t.Fatalf("malformed root path %q", rootPath)
+	}
+	driveLetter := string(rootPath[0])
+
 	for _, test := range []struct {
 		path, wantFile string
 		wantURI        protocol.DocumentURI
@@ -44,13 +54,13 @@
 		},
 		{
 			path:     `\path\to\dir`,
-			wantFile: `C:\path\to\dir`,
-			wantURI:  protocol.DocumentURI("file:///C:/path/to/dir"),
+			wantFile: driveLetter + `:\path\to\dir`,
+			wantURI:  protocol.DocumentURI("file:///" + driveLetter + ":/path/to/dir"),
 		},
 		{
 			path:     `\a\b\c\src\bob.go`,
-			wantFile: `C:\a\b\c\src\bob.go`,
-			wantURI:  protocol.DocumentURI("file:///C:/a/b/c/src/bob.go"),
+			wantFile: driveLetter + `:\a\b\c\src\bob.go`,
+			wantURI:  protocol.DocumentURI("file:///" + driveLetter + ":/a/b/c/src/bob.go"),
 		},
 		{
 			path:     `c:\Go\src\bob george\george\george.go`,
diff --git a/gopls/internal/server/call_hierarchy.go b/gopls/internal/server/call_hierarchy.go
index 8dd1f3e..671d4f8 100644
--- a/gopls/internal/server/call_hierarchy.go
+++ b/gopls/internal/server/call_hierarchy.go
@@ -8,8 +8,8 @@
 	"context"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 )
 
@@ -25,7 +25,7 @@
 	if snapshot.FileKind(fh) != file.Go {
 		return nil, nil // empty result
 	}
-	return source.PrepareCallHierarchy(ctx, snapshot, fh, params.Position)
+	return golang.PrepareCallHierarchy(ctx, snapshot, fh, params.Position)
 }
 
 func (s *server) IncomingCalls(ctx context.Context, params *protocol.CallHierarchyIncomingCallsParams) ([]protocol.CallHierarchyIncomingCall, error) {
@@ -40,7 +40,7 @@
 	if snapshot.FileKind(fh) != file.Go {
 		return nil, nil // empty result
 	}
-	return source.IncomingCalls(ctx, snapshot, fh, params.Item.Range.Start)
+	return golang.IncomingCalls(ctx, snapshot, fh, params.Item.Range.Start)
 }
 
 func (s *server) OutgoingCalls(ctx context.Context, params *protocol.CallHierarchyOutgoingCallsParams) ([]protocol.CallHierarchyOutgoingCall, error) {
@@ -55,5 +55,5 @@
 	if snapshot.FileKind(fh) != file.Go {
 		return nil, nil // empty result
 	}
-	return source.OutgoingCalls(ctx, snapshot, fh, params.Item.Range.Start)
+	return golang.OutgoingCalls(ctx, snapshot, fh, params.Item.Range.Start)
 }
diff --git a/gopls/internal/server/code_action.go b/gopls/internal/server/code_action.go
index 4ec105f..b26f978 100644
--- a/gopls/internal/server/code_action.go
+++ b/gopls/internal/server/code_action.go
@@ -7,26 +7,16 @@
 import (
 	"context"
 	"fmt"
-	"go/ast"
 	"sort"
 	"strings"
 
-	"golang.org/x/tools/go/ast/inspector"
-	"golang.org/x/tools/gopls/internal/analysis/fillstruct"
-	"golang.org/x/tools/gopls/internal/analysis/infertypeargs"
-	"golang.org/x/tools/gopls/internal/analysis/stubmethods"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
 	"golang.org/x/tools/gopls/internal/mod"
-	"golang.org/x/tools/gopls/internal/settings"
-	"golang.org/x/tools/gopls/internal/util/bug"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/internal/event"
-	"golang.org/x/tools/internal/event/tag"
-	"golang.org/x/tools/internal/imports"
 )
 
 func (s *server) CodeAction(ctx context.Context, params *protocol.CodeActionParams) ([]protocol.CodeAction, error) {
@@ -113,165 +103,22 @@
 		return actions, nil
 
 	case file.Go:
-		diagnostics := params.Context.Diagnostics
-
 		// Don't suggest fixes for generated files, since they are generally
 		// not useful and some editors may apply them automatically on save.
-		if source.IsGenerated(ctx, snapshot, uri) {
+		if golang.IsGenerated(ctx, snapshot, uri) {
 			return nil, nil
 		}
 
-		actions, err := s.codeActionsMatchingDiagnostics(ctx, uri, snapshot, diagnostics, want)
+		actions, err := s.codeActionsMatchingDiagnostics(ctx, uri, snapshot, params.Context.Diagnostics, want)
 		if err != nil {
 			return nil, err
 		}
 
-		// Only compute quick fixes if there are any diagnostics to fix.
-		wantQuickFixes := want[protocol.QuickFix] && len(diagnostics) > 0
-
-		// Code actions requiring syntax information alone.
-		if wantQuickFixes || want[protocol.SourceOrganizeImports] || want[protocol.RefactorExtract] {
-			pgf, err := snapshot.ParseGo(ctx, fh, parsego.ParseFull)
-			if err != nil {
-				return nil, err
-			}
-
-			// Process any missing imports and pair them with the diagnostics they
-			// fix.
-			if wantQuickFixes || want[protocol.SourceOrganizeImports] {
-				importEdits, importEditsPerFix, err := source.AllImportsFixes(ctx, snapshot, pgf)
-				if err != nil {
-					event.Error(ctx, "imports fixes", err, tag.File.Of(fh.URI().Path()))
-					importEdits = nil
-					importEditsPerFix = nil
-				}
-
-				// Separate this into a set of codeActions per diagnostic, where
-				// each action is the addition, removal, or renaming of one import.
-				if wantQuickFixes {
-					for _, importFix := range importEditsPerFix {
-						fixed := fixedByImportFix(importFix.Fix, diagnostics)
-						if len(fixed) == 0 {
-							continue
-						}
-						actions = append(actions, protocol.CodeAction{
-							Title: importFixTitle(importFix.Fix),
-							Kind:  protocol.QuickFix,
-							Edit: &protocol.WorkspaceEdit{
-								DocumentChanges: documentChanges(fh, importFix.Edits),
-							},
-							Diagnostics: fixed,
-						})
-					}
-				}
-
-				// Send all of the import edits as one code action if the file is
-				// being organized.
-				if want[protocol.SourceOrganizeImports] && len(importEdits) > 0 {
-					actions = append(actions, protocol.CodeAction{
-						Title: "Organize Imports",
-						Kind:  protocol.SourceOrganizeImports,
-						Edit: &protocol.WorkspaceEdit{
-							DocumentChanges: documentChanges(fh, importEdits),
-						},
-					})
-				}
-			}
-
-			if want[protocol.RefactorExtract] {
-				extractions, err := refactorExtract(pgf, params.Range)
-				if err != nil {
-					return nil, err
-				}
-				actions = append(actions, extractions...)
-			}
+		moreActions, err := golang.CodeActions(ctx, snapshot, fh, params.Range, params.Context.Diagnostics, want)
+		if err != nil {
+			return nil, err
 		}
-
-		var stubMethodsDiagnostics []protocol.Diagnostic
-		if wantQuickFixes && snapshot.Options().IsAnalyzerEnabled(stubmethods.Analyzer.Name) {
-			for _, pd := range diagnostics {
-				if stubmethods.MatchesMessage(pd.Message) {
-					stubMethodsDiagnostics = append(stubMethodsDiagnostics, pd)
-				}
-			}
-		}
-
-		// Code actions requiring type information.
-		if len(stubMethodsDiagnostics) > 0 ||
-			want[protocol.RefactorRewrite] ||
-			want[protocol.RefactorInline] ||
-			want[protocol.GoTest] {
-			pkg, pgf, err := source.NarrowestPackageForFile(ctx, snapshot, fh.URI())
-			if err != nil {
-				return nil, err
-			}
-			for _, pd := range stubMethodsDiagnostics {
-				start, end, err := pgf.RangePos(pd.Range)
-				if err != nil {
-					return nil, err
-				}
-				action, ok, err := func() (_ protocol.CodeAction, _ bool, rerr error) {
-					// golang/go#61693: code actions were refactored to run outside of the
-					// analysis framework, but as a result they lost their panic recovery.
-					//
-					// Stubmethods "should never fail"", but put back the panic recovery as a
-					// defensive measure.
-					defer func() {
-						if r := recover(); r != nil {
-							rerr = bug.Errorf("stubmethods panicked: %v", r)
-						}
-					}()
-					d, ok := stubmethods.DiagnosticForError(pkg.FileSet(), pgf.File, start, end, pd.Message, pkg.GetTypesInfo())
-					if !ok {
-						return protocol.CodeAction{}, false, nil
-					}
-					cmd, err := command.NewApplyFixCommand(d.Message, command.ApplyFixArgs{
-						URI:   pgf.URI,
-						Fix:   string(settings.StubMethods),
-						Range: pd.Range,
-					})
-					if err != nil {
-						return protocol.CodeAction{}, false, err
-					}
-					return protocol.CodeAction{
-						Title:       d.Message,
-						Kind:        protocol.QuickFix,
-						Command:     &cmd,
-						Diagnostics: []protocol.Diagnostic{pd},
-					}, true, nil
-				}()
-				if err != nil {
-					return nil, err
-				}
-				if ok {
-					actions = append(actions, action)
-				}
-			}
-
-			if want[protocol.RefactorRewrite] {
-				rewrites, err := refactorRewrite(snapshot, pkg, pgf, fh, params.Range)
-				if err != nil {
-					return nil, err
-				}
-				actions = append(actions, rewrites...)
-			}
-
-			if want[protocol.RefactorInline] {
-				rewrites, err := refactorInline(pkg, pgf, params.Range)
-				if err != nil {
-					return nil, err
-				}
-				actions = append(actions, rewrites...)
-			}
-
-			if want[protocol.GoTest] {
-				fixes, err := goTest(pkg, pgf, params.Range)
-				if err != nil {
-					return nil, err
-				}
-				actions = append(actions, fixes...)
-			}
-		}
+		actions = append(actions, moreActions...)
 
 		return actions, nil
 
@@ -281,356 +128,53 @@
 	}
 }
 
-func (s *server) findMatchingDiagnostics(uri protocol.DocumentURI, pd protocol.Diagnostic) []*cache.Diagnostic {
-	s.diagnosticsMu.Lock()
-	defer s.diagnosticsMu.Unlock()
-
-	var sds []*cache.Diagnostic
-	for _, viewDiags := range s.diagnostics[uri].byView {
-		for _, sd := range viewDiags.diagnostics {
-			sameDiagnostic := (pd.Message == strings.TrimSpace(sd.Message) && // extra space may have been trimmed when converting to protocol.Diagnostic
-				protocol.CompareRange(pd.Range, sd.Range) == 0 &&
-				pd.Source == string(sd.Source))
-
-			if sameDiagnostic {
-				sds = append(sds, sd)
-			}
-		}
-	}
-	return sds
-}
-
-func (s *server) getSupportedCodeActions() []protocol.CodeActionKind {
-	allCodeActionKinds := make(map[protocol.CodeActionKind]struct{})
-	for _, kinds := range s.Options().SupportedCodeActions {
-		for kind := range kinds {
-			allCodeActionKinds[kind] = struct{}{}
-		}
-	}
-	var result []protocol.CodeActionKind
-	for kind := range allCodeActionKinds {
-		result = append(result, kind)
-	}
-	sort.Slice(result, func(i, j int) bool {
-		return result[i] < result[j]
-	})
-	return result
-}
-
-func importFixTitle(fix *imports.ImportFix) string {
-	var str string
-	switch fix.FixType {
-	case imports.AddImport:
-		str = fmt.Sprintf("Add import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
-	case imports.DeleteImport:
-		str = fmt.Sprintf("Delete import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
-	case imports.SetImportName:
-		str = fmt.Sprintf("Rename import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
-	}
-	return str
-}
-
-// fixedByImportFix filters the provided slice of diagnostics to those that
-// would be fixed by the provided imports fix.
-func fixedByImportFix(fix *imports.ImportFix, diagnostics []protocol.Diagnostic) []protocol.Diagnostic {
-	var results []protocol.Diagnostic
-	for _, diagnostic := range diagnostics {
-		switch {
-		// "undeclared name: X" may be an unresolved import.
-		case strings.HasPrefix(diagnostic.Message, "undeclared name: "):
-			ident := strings.TrimPrefix(diagnostic.Message, "undeclared name: ")
-			if ident == fix.IdentName {
-				results = append(results, diagnostic)
-			}
-		// "undefined: X" may be an unresolved import at Go 1.20+.
-		case strings.HasPrefix(diagnostic.Message, "undefined: "):
-			ident := strings.TrimPrefix(diagnostic.Message, "undefined: ")
-			if ident == fix.IdentName {
-				results = append(results, diagnostic)
-			}
-		// "could not import: X" may be an invalid import.
-		case strings.HasPrefix(diagnostic.Message, "could not import: "):
-			ident := strings.TrimPrefix(diagnostic.Message, "could not import: ")
-			if ident == fix.IdentName {
-				results = append(results, diagnostic)
-			}
-		// "X imported but not used" is an unused import.
-		// "X imported but not used as Y" is an unused import.
-		case strings.Contains(diagnostic.Message, " imported but not used"):
-			idx := strings.Index(diagnostic.Message, " imported but not used")
-			importPath := diagnostic.Message[:idx]
-			if importPath == fmt.Sprintf("%q", fix.StmtInfo.ImportPath) {
-				results = append(results, diagnostic)
-			}
-		}
-	}
-	return results
-}
-
-func refactorExtract(pgf *source.ParsedGoFile, rng protocol.Range) ([]protocol.CodeAction, error) {
-	if rng.Start == rng.End {
-		return nil, nil
-	}
-
-	start, end, err := pgf.RangePos(rng)
-	if err != nil {
-		return nil, err
-	}
-	puri := pgf.URI
-	var commands []protocol.Command
-	if _, ok, methodOk, _ := source.CanExtractFunction(pgf.Tok, start, end, pgf.Src, pgf.File); ok {
-		cmd, err := command.NewApplyFixCommand("Extract function", command.ApplyFixArgs{
-			URI:   puri,
-			Fix:   string(settings.ExtractFunction),
-			Range: rng,
-		})
-		if err != nil {
-			return nil, err
-		}
-		commands = append(commands, cmd)
-		if methodOk {
-			cmd, err := command.NewApplyFixCommand("Extract method", command.ApplyFixArgs{
-				URI:   puri,
-				Fix:   string(settings.ExtractMethod),
-				Range: rng,
-			})
-			if err != nil {
-				return nil, err
-			}
-			commands = append(commands, cmd)
-		}
-	}
-	if _, _, ok, _ := source.CanExtractVariable(start, end, pgf.File); ok {
-		cmd, err := command.NewApplyFixCommand("Extract variable", command.ApplyFixArgs{
-			URI:   puri,
-			Fix:   string(settings.ExtractVariable),
-			Range: rng,
-		})
-		if err != nil {
-			return nil, err
-		}
-		commands = append(commands, cmd)
-	}
-	var actions []protocol.CodeAction
-	for i := range commands {
-		actions = append(actions, protocol.CodeAction{
-			Title:   commands[i].Title,
-			Kind:    protocol.RefactorExtract,
-			Command: &commands[i],
-		})
-	}
-	return actions, nil
-}
-
-func refactorRewrite(snapshot *cache.Snapshot, pkg *cache.Package, pgf *source.ParsedGoFile, fh file.Handle, rng protocol.Range) (_ []protocol.CodeAction, rerr error) {
-	// golang/go#61693: code actions were refactored to run outside of the
-	// analysis framework, but as a result they lost their panic recovery.
-	//
-	// These code actions should never fail, but put back the panic recovery as a
-	// defensive measure.
-	defer func() {
-		if r := recover(); r != nil {
-			rerr = bug.Errorf("refactor.rewrite code actions panicked: %v", r)
-		}
-	}()
-
-	var actions []protocol.CodeAction
-
-	if canRemoveParameter(pkg, pgf, rng) {
-		cmd, err := command.NewChangeSignatureCommand("remove unused parameter", command.ChangeSignatureArgs{
-			RemoveParameter: protocol.Location{
-				URI:   pgf.URI,
-				Range: rng,
-			},
-		})
-		if err != nil {
-			return nil, err
-		}
-		actions = append(actions, protocol.CodeAction{
-			Title:   "Refactor: remove unused parameter",
-			Kind:    protocol.RefactorRewrite,
-			Command: &cmd,
-		})
-	}
-
-	if action, ok := source.ConvertStringLiteral(pgf, fh, rng); ok {
-		actions = append(actions, action)
-	}
-
-	start, end, err := pgf.RangePos(rng)
-	if err != nil {
-		return nil, err
-	}
-
-	var commands []protocol.Command
-	if _, ok, _ := source.CanInvertIfCondition(pgf.File, start, end); ok {
-		cmd, err := command.NewApplyFixCommand("Invert if condition", command.ApplyFixArgs{
-			URI:   pgf.URI,
-			Fix:   string(settings.InvertIfCondition),
-			Range: rng,
-		})
-		if err != nil {
-			return nil, err
-		}
-		commands = append(commands, cmd)
-	}
-
-	// N.B.: an inspector only pays for itself after ~5 passes, which means we're
-	// currently not getting a good deal on this inspection.
-	//
-	// TODO: Consider removing the inspection after convenienceAnalyzers are removed.
-	inspect := inspector.New([]*ast.File{pgf.File})
-	if snapshot.Options().IsAnalyzerEnabled(fillstruct.Analyzer.Name) {
-		for _, d := range fillstruct.DiagnoseFillableStructs(inspect, start, end, pkg.GetTypes(), pkg.GetTypesInfo()) {
-			rng, err := pgf.Mapper.PosRange(pgf.Tok, d.Pos, d.End)
-			if err != nil {
-				return nil, err
-			}
-			cmd, err := command.NewApplyFixCommand(d.Message, command.ApplyFixArgs{
-				URI:   pgf.URI,
-				Fix:   string(settings.FillStruct),
-				Range: rng,
-			})
-			if err != nil {
-				return nil, err
-			}
-			commands = append(commands, cmd)
-		}
-	}
-
-	for i := range commands {
-		actions = append(actions, protocol.CodeAction{
-			Title:   commands[i].Title,
-			Kind:    protocol.RefactorRewrite,
-			Command: &commands[i],
-		})
-	}
-
-	if snapshot.Options().IsAnalyzerEnabled(infertypeargs.Analyzer.Name) {
-		for _, d := range infertypeargs.DiagnoseInferableTypeArgs(pkg.FileSet(), inspect, start, end, pkg.GetTypes(), pkg.GetTypesInfo()) {
-			if len(d.SuggestedFixes) != 1 {
-				panic(fmt.Sprintf("unexpected number of suggested fixes from infertypeargs: %v", len(d.SuggestedFixes)))
-			}
-			fix := d.SuggestedFixes[0]
-			var edits []protocol.TextEdit
-			for _, analysisEdit := range fix.TextEdits {
-				rng, err := pgf.Mapper.PosRange(pgf.Tok, analysisEdit.Pos, analysisEdit.End)
-				if err != nil {
-					return nil, err
-				}
-				edits = append(edits, protocol.TextEdit{
-					Range:   rng,
-					NewText: string(analysisEdit.NewText),
-				})
-			}
-			actions = append(actions, protocol.CodeAction{
-				Title: "Simplify type arguments",
-				Kind:  protocol.RefactorRewrite,
-				Edit: &protocol.WorkspaceEdit{
-					DocumentChanges: documentChanges(fh, edits),
-				},
-			})
-		}
-	}
-
-	return actions, nil
-}
-
-// canRemoveParameter reports whether we can remove the function parameter
-// indicated by the given [start, end) range.
+// ResolveCodeAction resolves missing Edit information (that is, computes the
+// details of the necessary patch) in the given code action using the provided
+// Data field of the CodeAction, which should contain the raw json of a protocol.Command.
 //
-// This is true if:
-//   - [start, end) is contained within an unused field or parameter name
-//   - ... of a non-method function declaration.
-func canRemoveParameter(pkg *cache.Package, pgf *source.ParsedGoFile, rng protocol.Range) bool {
-	info, err := source.FindParam(pgf, rng)
-	if err != nil {
-		return false // e.g. invalid range
-	}
-	if info.Field == nil {
-		return false // range does not span a parameter
-	}
-	if info.Decl.Body == nil {
-		return false // external function
-	}
-	if len(info.Field.Names) == 0 {
-		return true // no names => field is unused
-	}
-	if info.Name == nil {
-		return false // no name is indicated
-	}
-	if info.Name.Name == "_" {
-		return true // trivially unused
-	}
+// This should be called by the client before applying code actions, when the
+// client has code action resolve support.
+//
+// This feature allows capable clients to preview and selectively apply the diff
+// instead of applying the whole thing unconditionally through workspace/applyEdit.
+func (s *server) ResolveCodeAction(ctx context.Context, ca *protocol.CodeAction) (*protocol.CodeAction, error) {
+	ctx, done := event.Start(ctx, "lsp.Server.resolveCodeAction")
+	defer done()
 
-	obj := pkg.GetTypesInfo().Defs[info.Name]
-	if obj == nil {
-		return false // something went wrong
-	}
-
-	used := false
-	ast.Inspect(info.Decl.Body, func(node ast.Node) bool {
-		if n, ok := node.(*ast.Ident); ok && pkg.GetTypesInfo().Uses[n] == obj {
-			used = true
-		}
-		return !used // keep going until we find a use
-	})
-	return !used
-}
-
-// refactorInline returns inline actions available at the specified range.
-func refactorInline(pkg *cache.Package, pgf *source.ParsedGoFile, rng protocol.Range) ([]protocol.CodeAction, error) {
-	start, end, err := pgf.RangePos(rng)
-	if err != nil {
-		return nil, err
-	}
-
-	// If range is within call expression, offer inline action.
-	var commands []protocol.Command
-	if _, fn, err := source.EnclosingStaticCall(pkg, pgf, start, end); err == nil {
-		cmd, err := command.NewApplyFixCommand(fmt.Sprintf("Inline call to %s", fn.Name()), command.ApplyFixArgs{
-			URI:   pgf.URI,
-			Fix:   string(settings.InlineCall),
-			Range: rng,
-		})
-		if err != nil {
+	// Only resolve the code action if there is Data provided.
+	var cmd protocol.Command
+	if ca.Data != nil {
+		if err := protocol.UnmarshalJSON(*ca.Data, &cmd); err != nil {
 			return nil, err
 		}
-		commands = append(commands, cmd)
 	}
+	if cmd.Command != "" {
+		params := &protocol.ExecuteCommandParams{
+			Command:   cmd.Command,
+			Arguments: cmd.Arguments,
+		}
 
-	// Convert commands to actions.
-	var actions []protocol.CodeAction
-	for i := range commands {
-		actions = append(actions, protocol.CodeAction{
-			Title:   commands[i].Title,
-			Kind:    protocol.RefactorInline,
-			Command: &commands[i],
-		})
-	}
-	return actions, nil
-}
+		handler := &commandHandler{
+			s:      s,
+			params: params,
+		}
+		edit, err := command.Dispatch(ctx, params, handler)
+		if err != nil {
 
-func documentChanges(fh file.Handle, edits []protocol.TextEdit) []protocol.DocumentChanges {
-	return []protocol.DocumentChanges{
-		{
-			TextDocumentEdit: &protocol.TextDocumentEdit{
-				TextDocument: protocol.OptionalVersionedTextDocumentIdentifier{
-					Version: fh.Version(),
-					TextDocumentIdentifier: protocol.TextDocumentIdentifier{
-						URI: fh.URI(),
-					},
-				},
-				Edits: protocol.AsAnnotatedTextEdits(edits),
-			},
-		},
+			return nil, err
+		}
+		var ok bool
+		if ca.Edit, ok = edit.(*protocol.WorkspaceEdit); !ok {
+			return nil, fmt.Errorf("unable to resolve code action %q", ca.Title)
+		}
 	}
+	return ca, nil
 }
 
 // codeActionsMatchingDiagnostics fetches code actions for the provided
 // diagnostics, by first attempting to unmarshal code actions directly from the
 // bundled protocol.Diagnostic.Data field, and failing that by falling back on
-// fetching a matching source.Diagnostic from the set of stored diagnostics for
+// fetching a matching Diagnostic from the set of stored diagnostics for
 // this file.
 func (s *server) codeActionsMatchingDiagnostics(ctx context.Context, uri protocol.DocumentURI, snapshot *cache.Snapshot, pds []protocol.Diagnostic, want map[protocol.CodeActionKind]bool) ([]protocol.CodeAction, error) {
 	var actions []protocol.CodeAction
@@ -675,53 +219,57 @@
 			}
 			changes = append(changes, documentChanges(fh, edits)...)
 		}
-		action := protocol.CodeAction{
+		actions = append(actions, protocol.CodeAction{
 			Title: fix.Title,
 			Kind:  fix.ActionKind,
 			Edit: &protocol.WorkspaceEdit{
 				DocumentChanges: changes,
 			},
-			Command: fix.Command,
-		}
-		action.Diagnostics = []protocol.Diagnostic{*pd}
-		actions = append(actions, action)
+			Command:     fix.Command,
+			Diagnostics: []protocol.Diagnostic{*pd},
+		})
 	}
 	return actions, nil
 }
 
-func goTest(pkg *cache.Package, pgf *source.ParsedGoFile, rng protocol.Range) ([]protocol.CodeAction, error) {
-	fns, err := source.TestsAndBenchmarks(pkg, pgf)
-	if err != nil {
-		return nil, err
-	}
+func (s *server) findMatchingDiagnostics(uri protocol.DocumentURI, pd protocol.Diagnostic) []*cache.Diagnostic {
+	s.diagnosticsMu.Lock()
+	defer s.diagnosticsMu.Unlock()
 
-	var tests, benchmarks []string
-	for _, fn := range fns.Tests {
-		if !protocol.Intersect(fn.Rng, rng) {
-			continue
+	var sds []*cache.Diagnostic
+	for _, viewDiags := range s.diagnostics[uri].byView {
+		for _, sd := range viewDiags.diagnostics {
+			sameDiagnostic := (pd.Message == strings.TrimSpace(sd.Message) && // extra space may have been trimmed when converting to protocol.Diagnostic
+				protocol.CompareRange(pd.Range, sd.Range) == 0 &&
+				pd.Source == string(sd.Source))
+
+			if sameDiagnostic {
+				sds = append(sds, sd)
+			}
 		}
-		tests = append(tests, fn.Name)
 	}
-	for _, fn := range fns.Benchmarks {
-		if !protocol.Intersect(fn.Rng, rng) {
-			continue
+	return sds
+}
+
+func (s *server) getSupportedCodeActions() []protocol.CodeActionKind {
+	allCodeActionKinds := make(map[protocol.CodeActionKind]struct{})
+	for _, kinds := range s.Options().SupportedCodeActions {
+		for kind := range kinds {
+			allCodeActionKinds[kind] = struct{}{}
 		}
-		benchmarks = append(benchmarks, fn.Name)
 	}
-
-	if len(tests) == 0 && len(benchmarks) == 0 {
-		return nil, nil
+	var result []protocol.CodeActionKind
+	for kind := range allCodeActionKinds {
+		result = append(result, kind)
 	}
-
-	cmd, err := command.NewTestCommand("Run tests and benchmarks", pgf.URI, tests, benchmarks)
-	if err != nil {
-		return nil, err
-	}
-	return []protocol.CodeAction{{
-		Title:   cmd.Title,
-		Kind:    protocol.GoTest,
-		Command: &cmd,
-	}}, nil
+	sort.Slice(result, func(i, j int) bool {
+		return result[i] < result[j]
+	})
+	return result
 }
 
 type unit = struct{}
+
+func documentChanges(fh file.Handle, edits []protocol.TextEdit) []protocol.DocumentChanges {
+	return protocol.TextEditsToDocumentChanges(fh.URI(), fh.Version(), edits)
+}
diff --git a/gopls/internal/server/code_lens.go b/gopls/internal/server/code_lens.go
index e8d7f2b..7e6506c 100644
--- a/gopls/internal/server/code_lens.go
+++ b/gopls/internal/server/code_lens.go
@@ -10,10 +10,10 @@
 	"sort"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
 	"golang.org/x/tools/gopls/internal/mod"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
 )
@@ -28,12 +28,12 @@
 	}
 	defer release()
 
-	var lenses map[command.Command]source.LensFunc
+	var lenses map[command.Command]golang.LensFunc
 	switch snapshot.FileKind(fh) {
 	case file.Mod:
 		lenses = mod.LensFuncs()
 	case file.Go:
-		lenses = source.LensFuncs()
+		lenses = golang.LensFuncs()
 	default:
 		// Unsupported file kind for a code lens.
 		return nil, nil
diff --git a/gopls/internal/server/command.go b/gopls/internal/server/command.go
index 330f0a8..8681db7 100644
--- a/gopls/internal/server/command.go
+++ b/gopls/internal/server/command.go
@@ -22,19 +22,18 @@
 
 	"golang.org/x/mod/modfile"
 	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
 	"golang.org/x/tools/gopls/internal/debug"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/progress"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/progress"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/telemetry"
 	"golang.org/x/tools/gopls/internal/util/bug"
-	"golang.org/x/tools/gopls/internal/util/maps"
 	"golang.org/x/tools/gopls/internal/vulncheck"
 	"golang.org/x/tools/gopls/internal/vulncheck/scan"
 	"golang.org/x/tools/internal/diff"
@@ -200,12 +199,13 @@
 	return runcmd()
 }
 
-func (c *commandHandler) ApplyFix(ctx context.Context, args command.ApplyFixArgs) error {
-	return c.run(ctx, commandConfig{
+func (c *commandHandler) ApplyFix(ctx context.Context, args command.ApplyFixArgs) (*protocol.WorkspaceEdit, error) {
+	var result *protocol.WorkspaceEdit
+	err := c.run(ctx, commandConfig{
 		// Note: no progress here. Applying fixes should be quick.
 		forURI: args.URI,
 	}, func(ctx context.Context, deps commandDeps) error {
-		edits, err := source.ApplyFix(ctx, settings.Fix(args.Fix), deps.snapshot, deps.fh, args.Range)
+		edits, err := golang.ApplyFix(ctx, args.Fix, deps.snapshot, deps.fh, args.Range)
 		if err != nil {
 			return err
 		}
@@ -216,10 +216,15 @@
 				TextDocumentEdit: &edit,
 			})
 		}
+		edit := protocol.WorkspaceEdit{
+			DocumentChanges: changes,
+		}
+		if args.ResolveEdits {
+			result = &edit
+			return nil
+		}
 		r, err := c.s.client.ApplyEdit(ctx, &protocol.ApplyWorkspaceEditParams{
-			Edit: protocol.WorkspaceEdit{
-				DocumentChanges: changes,
-			},
+			Edit: edit,
 		})
 		if err != nil {
 			return err
@@ -229,6 +234,7 @@
 		}
 		return nil
 	})
+	return result, err
 }
 
 func (c *commandHandler) RegenerateCgo(ctx context.Context, args command.URIArg) error {
@@ -285,10 +291,9 @@
 			if err != nil {
 				return nil, nil, err
 			}
-			snapshot, release, _ := deps.snapshot.View().Invalidate(ctx, cache.StateChange{
+			return c.s.session.InvalidateView(ctx, deps.snapshot.View(), cache.StateChange{
 				ModuleUpgrades: map[protocol.DocumentURI]map[string]string{args.URI: upgrades},
 			})
-			return snapshot, release, nil
 		})
 	})
 }
@@ -306,7 +311,7 @@
 		forURI: args.URI,
 	}, func(ctx context.Context, deps commandDeps) error {
 		return c.modifyState(ctx, FromResetGoModDiagnostics, func() (*cache.Snapshot, func(), error) {
-			snapshot, release, _ := deps.snapshot.View().Invalidate(ctx, cache.StateChange{
+			return c.s.session.InvalidateView(ctx, deps.snapshot.View(), cache.StateChange{
 				ModuleUpgrades: map[protocol.DocumentURI]map[string]string{
 					deps.fh.URI(): nil,
 				},
@@ -314,7 +319,6 @@
 					deps.fh.URI(): nil,
 				},
 			})
-			return snapshot, release, nil
 		})
 	})
 }
@@ -443,25 +447,13 @@
 		if err != nil {
 			return err
 		}
-		edits, err := dropDependency(deps.snapshot, pm, args.ModulePath)
+		edits, err := dropDependency(pm, args.ModulePath)
 		if err != nil {
 			return err
 		}
 		response, err := c.s.client.ApplyEdit(ctx, &protocol.ApplyWorkspaceEditParams{
 			Edit: protocol.WorkspaceEdit{
-				DocumentChanges: []protocol.DocumentChanges{
-					{
-						TextDocumentEdit: &protocol.TextDocumentEdit{
-							TextDocument: protocol.OptionalVersionedTextDocumentIdentifier{
-								Version: deps.fh.Version(),
-								TextDocumentIdentifier: protocol.TextDocumentIdentifier{
-									URI: deps.fh.URI(),
-								},
-							},
-							Edits: protocol.AsAnnotatedTextEdits(edits),
-						},
-					},
-				},
+				DocumentChanges: documentChanges(deps.fh, edits),
 			},
 		})
 		if err != nil {
@@ -476,7 +468,7 @@
 
 // dropDependency returns the edits to remove the given require from the go.mod
 // file.
-func dropDependency(snapshot *cache.Snapshot, pm *cache.ParsedModule, modulePath string) ([]protocol.TextEdit, error) {
+func dropDependency(pm *cache.ParsedModule, modulePath string) ([]protocol.TextEdit, error) {
 	// We need a private copy of the parsed go.mod file, since we're going to
 	// modify it.
 	copied, err := modfile.Parse("", pm.Mapper.Content, nil)
@@ -517,7 +509,7 @@
 
 func (c *commandHandler) runTests(ctx context.Context, snapshot *cache.Snapshot, work *progress.WorkDone, uri protocol.DocumentURI, tests, benchmarks []string) error {
 	// TODO: fix the error reporting when this runs async.
-	meta, err := source.NarrowestMetadataForFile(ctx, snapshot, uri)
+	meta, err := golang.NarrowestMetadataForFile(ctx, snapshot, uri)
 	if err != nil {
 		return err
 	}
@@ -715,16 +707,9 @@
 	if len(edits) == 0 {
 		return nil
 	}
-	documentChanges := []protocol.DocumentChanges{} // must be a slice
-	for _, change := range edits {
-		change := change
-		documentChanges = append(documentChanges, protocol.DocumentChanges{
-			TextDocumentEdit: &change,
-		})
-	}
 	response, err := cli.ApplyEdit(ctx, &protocol.ApplyWorkspaceEditParams{
 		Edit: protocol.WorkspaceEdit{
-			DocumentChanges: documentChanges,
+			DocumentChanges: protocol.TextDocumentEditsToDocumentChanges(edits),
 		},
 	})
 	if err != nil {
@@ -791,17 +776,16 @@
 		forURI:      args.URI,
 	}, func(ctx context.Context, deps commandDeps) error {
 		return c.modifyState(ctx, FromToggleGCDetails, func() (*cache.Snapshot, func(), error) {
-			meta, err := source.NarrowestMetadataForFile(ctx, deps.snapshot, deps.fh.URI())
+			meta, err := golang.NarrowestMetadataForFile(ctx, deps.snapshot, deps.fh.URI())
 			if err != nil {
 				return nil, nil, err
 			}
 			wantDetails := !deps.snapshot.WantGCDetails(meta.ID) // toggle the gc details state
-			snapshot, release, _ := deps.snapshot.View().Invalidate(ctx, cache.StateChange{
+			return c.s.session.InvalidateView(ctx, deps.snapshot.View(), cache.StateChange{
 				GCDetails: map[metadata.PackageID]bool{
 					meta.ID: wantDetails,
 				},
 			})
-			return snapshot, release, nil
 		})
 	})
 }
@@ -812,7 +796,7 @@
 		progress: "Listing packages",
 		forURI:   args.URI,
 	}, func(ctx context.Context, deps commandDeps) error {
-		pkgs, err := source.KnownPackagePaths(ctx, deps.snapshot, deps.fh)
+		pkgs, err := golang.KnownPackagePaths(ctx, deps.snapshot, deps.fh)
 		for _, pkg := range pkgs {
 			result.Packages = append(result.Packages, string(pkg))
 		}
@@ -850,7 +834,7 @@
 				})
 			}
 		}
-		meta, err := source.NarrowestMetadataForFile(ctx, deps.snapshot, args.URI)
+		meta, err := golang.NarrowestMetadataForFile(ctx, deps.snapshot, args.URI)
 		if err != nil {
 			return err // e.g. cancelled
 		}
@@ -871,7 +855,7 @@
 		progress: "Adding import",
 		forURI:   args.URI,
 	}, func(ctx context.Context, deps commandDeps) error {
-		edits, err := source.AddImport(ctx, deps.snapshot, deps.fh, args.ImportPath)
+		edits, err := golang.AddImport(ctx, deps.snapshot, deps.fh, args.ImportPath)
 		if err != nil {
 			return fmt.Errorf("could not add import: %v", err)
 		}
@@ -995,9 +979,12 @@
 			return err
 		}
 
-		snapshot, release, _ := deps.snapshot.View().Invalidate(ctx, cache.StateChange{
+		snapshot, release, err := c.s.session.InvalidateView(ctx, deps.snapshot.View(), cache.StateChange{
 			Vulns: map[protocol.DocumentURI]*vulncheck.Result{args.URI: result},
 		})
+		if err != nil {
+			return err
+		}
 		defer release()
 		c.s.diagnoseSnapshot(snapshot, nil, 0)
 
@@ -1052,7 +1039,7 @@
 // about the current state of the loaded workspace for the current session.
 func (c *commandHandler) WorkspaceStats(ctx context.Context) (command.WorkspaceStatsResult, error) {
 	var res command.WorkspaceStatsResult
-	res.Files.Total, res.Files.Largest, res.Files.Errs = c.s.session.Cache().FileStats()
+	res.Files = c.s.session.Cache().FileStats()
 
 	for _, view := range c.s.session.Views() {
 		vs, err := collectViewStats(ctx, view)
@@ -1083,7 +1070,7 @@
 	}
 	workspacePackages := collectPackageStats(wsMD)
 
-	var ids []source.PackageID
+	var ids []golang.PackageID
 	for _, mp := range wsMD {
 		ids = append(ids, mp.ID)
 	}
@@ -1267,19 +1254,25 @@
 	}
 }
 
-func (c *commandHandler) ChangeSignature(ctx context.Context, args command.ChangeSignatureArgs) error {
-	return c.run(ctx, commandConfig{
+func (c *commandHandler) ChangeSignature(ctx context.Context, args command.ChangeSignatureArgs) (*protocol.WorkspaceEdit, error) {
+	var result *protocol.WorkspaceEdit
+	err := c.run(ctx, commandConfig{
 		forURI: args.RemoveParameter.URI,
 	}, func(ctx context.Context, deps commandDeps) error {
 		// For now, gopls only supports removing unused parameters.
-		changes, err := source.RemoveUnusedParameter(ctx, deps.fh, args.RemoveParameter.Range, deps.snapshot)
+		changes, err := golang.RemoveUnusedParameter(ctx, deps.fh, args.RemoveParameter.Range, deps.snapshot)
 		if err != nil {
 			return err
 		}
+		edit := protocol.WorkspaceEdit{
+			DocumentChanges: changes,
+		}
+		if args.ResolveEdits {
+			result = &edit
+			return nil
+		}
 		r, err := c.s.client.ApplyEdit(ctx, &protocol.ApplyWorkspaceEditParams{
-			Edit: protocol.WorkspaceEdit{
-				DocumentChanges: changes,
-			},
+			Edit: edit,
 		})
 		if !r.Applied {
 			return fmt.Errorf("failed to apply edits: %v", r.FailureReason)
@@ -1287,12 +1280,13 @@
 
 		return nil
 	})
+	return result, err
 }
 
 func (c *commandHandler) DiagnoseFiles(ctx context.Context, args command.DiagnoseFilesArgs) error {
 	return c.run(ctx, commandConfig{
 		progress: "Diagnose files",
-	}, func(ctx context.Context, deps commandDeps) error {
+	}, func(ctx context.Context, _ commandDeps) error {
 
 		// TODO(rfindley): even better would be textDocument/diagnostics (golang/go#60122).
 		// Though note that implementing pull diagnostics may cause some servers to
@@ -1301,47 +1295,31 @@
 		ctx, done := event.Start(ctx, "lsp.server.DiagnoseFiles")
 		defer done()
 
-		// TODO(adonovan): opt: parallelize the loop,
-		// grouping file URIs by package and making a
-		// single call to source.Analyze.
+		snapshots := make(map[*cache.Snapshot]bool)
 		for _, uri := range args.Files {
 			fh, snapshot, release, err := c.s.fileOf(ctx, uri)
 			if err != nil {
 				return err
 			}
-			defer release()
-			if snapshot.FileKind(fh) != file.Go {
+			if snapshots[snapshot] || snapshot.FileKind(fh) != file.Go {
+				release()
 				continue
 			}
-			pkg, _, err := source.NarrowestPackageForFile(ctx, snapshot, uri)
-			if err != nil {
-				return err
-			}
-			pkgDiags, err := pkg.DiagnosticsForFile(ctx, uri)
-			if err != nil {
-				return err
-			}
-			adiags, err := source.Analyze(ctx, snapshot, map[source.PackageID]unit{pkg.Metadata().ID: {}}, nil /* progress tracker */)
-			if err != nil {
-				return err
-			}
-
-			// combine load/parse/type + analysis diagnostics
-			var td, ad []*cache.Diagnostic
-			combineDiagnostics(pkgDiags, adiags[uri], &td, &ad)
-			diags := append(td, ad...)
-			byURI := func(d *cache.Diagnostic) protocol.DocumentURI { return d.URI }
-			c.s.updateDiagnostics(ctx, c.s.session.Views(), snapshot, maps.Group(diags, byURI), false)
-			diagnostics := append(td, ad...)
-
-			if err := c.s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{
-				URI:         fh.URI(),
-				Version:     fh.Version(),
-				Diagnostics: toProtocolDiagnostics(diagnostics),
-			}); err != nil {
-				return err
-			}
+			defer release()
+			snapshots[snapshot] = true
 		}
+
+		var wg sync.WaitGroup
+		for snapshot := range snapshots {
+			snapshot := snapshot
+			wg.Add(1)
+			go func() {
+				defer wg.Done()
+				c.s.diagnoseSnapshot(snapshot, nil, 0)
+			}()
+		}
+		wg.Wait()
+
 		return nil
 	})
 }
diff --git a/gopls/internal/server/completion.go b/gopls/internal/server/completion.go
index 6e49d5f..3e019df 100644
--- a/gopls/internal/server/completion.go
+++ b/gopls/internal/server/completion.go
@@ -10,9 +10,9 @@
 	"strings"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
-	"golang.org/x/tools/gopls/internal/lsp/source/completion"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/golang/completion"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/telemetry"
 	"golang.org/x/tools/gopls/internal/template"
@@ -116,7 +116,7 @@
 		doc := &protocol.Or_CompletionItem_documentation{
 			Value: protocol.MarkupContent{
 				Kind:  protocol.Markdown,
-				Value: source.CommentToMarkdown(candidate.Documentation, options),
+				Value: golang.CommentToMarkdown(candidate.Documentation, options),
 			},
 		}
 		if options.PreferredContentFormat != protocol.Markdown {
diff --git a/gopls/internal/server/definition.go b/gopls/internal/server/definition.go
index 7409620..7a0eb25 100644
--- a/gopls/internal/server/definition.go
+++ b/gopls/internal/server/definition.go
@@ -9,8 +9,8 @@
 	"fmt"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/telemetry"
 	"golang.org/x/tools/gopls/internal/template"
 	"golang.org/x/tools/internal/event"
@@ -36,7 +36,7 @@
 	case file.Tmpl:
 		return template.Definition(snapshot, fh, params.Position)
 	case file.Go:
-		return source.Definition(ctx, snapshot, fh, params.Position)
+		return golang.Definition(ctx, snapshot, fh, params.Position)
 	default:
 		return nil, fmt.Errorf("can't find definitions for file type %s", kind)
 	}
@@ -54,7 +54,7 @@
 	defer release()
 	switch kind := snapshot.FileKind(fh); kind {
 	case file.Go:
-		return source.TypeDefinition(ctx, snapshot, fh, params.Position)
+		return golang.TypeDefinition(ctx, snapshot, fh, params.Position)
 	default:
 		return nil, fmt.Errorf("can't find type definitions for file type %s", kind)
 	}
diff --git a/gopls/internal/server/diagnostics.go b/gopls/internal/server/diagnostics.go
index 460e119..6aa01ab 100644
--- a/gopls/internal/server/diagnostics.go
+++ b/gopls/internal/server/diagnostics.go
@@ -16,12 +16,12 @@
 	"sync"
 	"time"
 
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
 	"golang.org/x/tools/gopls/internal/mod"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/template"
 	"golang.org/x/tools/gopls/internal/util/maps"
@@ -263,7 +263,7 @@
 		}
 
 		// Find all packages that include this file and diagnose them in parallel.
-		meta, err := source.NarrowestMetadataForFile(ctx, snapshot, uri)
+		meta, err := golang.NarrowestMetadataForFile(ctx, snapshot, uri)
 		if err != nil {
 			if ctx.Err() != nil {
 				return nil, ctx.Err()
@@ -364,7 +364,7 @@
 	store("diagnosing vulnerabilities", vulnReports, vulnErr)
 
 	workspacePkgs, err := snapshot.WorkspaceMetadata(ctx)
-	if s.shouldIgnoreError(ctx, snapshot, err) {
+	if s.shouldIgnoreError(snapshot, err) {
 		return diagnostics, ctx.Err()
 	}
 
@@ -415,9 +415,30 @@
 	}()
 
 	// Run type checking and go/analysis diagnosis of packages in parallel.
+	//
+	// For analysis, we use the *widest* package for each open file,
+	// for two reasons:
+	//
+	// - Correctness: some analyzers (e.g. unusedparam) depend
+	//   on it. If applied to a non-test package for which a
+	//   corresponding test package exists, they make assumptions
+	//   that are falsified in the test package, for example that
+	//   all references to unexported symbols are visible to the
+	//   analysis.
+	//
+	// - Efficiency: it may yield a smaller covering set of
+	//   PackageIDs for a given set of files. For example, {x.go,
+	//   x_test.go} is covered by the single package x_test using
+	//   "widest". (Using "narrowest", it would be covered only by
+	//   the pair of packages {x, x_test}, Originally we used all
+	//   covering packages, so {x.go} alone would be analyzed
+	//   twice.)
 	var (
 		toDiagnose = make(map[metadata.PackageID]*metadata.Package)
-		toAnalyze  = make(map[metadata.PackageID]unit)
+		toAnalyze  = make(map[metadata.PackageID]*metadata.Package)
+
+		// secondary index, used to eliminate narrower packages.
+		toAnalyzeWidest = make(map[golang.PackagePath]*metadata.Package)
 	)
 	for _, mp := range workspacePkgs {
 		var hasNonIgnored, hasOpenFile bool
@@ -432,7 +453,16 @@
 		if hasNonIgnored {
 			toDiagnose[mp.ID] = mp
 			if hasOpenFile {
-				toAnalyze[mp.ID] = unit{}
+				if prev, ok := toAnalyzeWidest[mp.PkgPath]; ok {
+					if len(prev.CompiledGoFiles) >= len(mp.CompiledGoFiles) {
+						// Previous entry is not narrower; keep it.
+						continue
+					}
+					// Evict previous (narrower) entry.
+					delete(toAnalyze, prev.ID)
+				}
+				toAnalyze[mp.ID] = mp
+				toAnalyzeWidest[mp.PkgPath] = mp
 			}
 		}
 	}
@@ -466,7 +496,7 @@
 		var err error
 		// TODO(rfindley): here and above, we should avoid using the first result
 		// if err is non-nil (though as of today it's OK).
-		analysisDiags, err = source.Analyze(ctx, snapshot, toAnalyze, s.progress)
+		analysisDiags, err = golang.Analyze(ctx, snapshot, toAnalyze, s.progress)
 		if err != nil {
 			event.Error(ctx, "warning: analyzing package", err, append(snapshot.Labels(), tag.Package.Of(keys.Join(maps.Keys(toDiagnose))))...)
 			return
@@ -512,7 +542,7 @@
 
 	diagnostics := make(diagMap)
 	for _, mp := range toGCDetail {
-		gcReports, err := source.GCOptimizationDetails(ctx, snapshot, mp)
+		gcReports, err := golang.GCOptimizationDetails(ctx, snapshot, mp)
 		if err != nil {
 			event.Error(ctx, "warning: gc details", err, append(snapshot.Labels(), tag.Package.Of(string(mp.ID)))...)
 			continue
@@ -674,7 +704,15 @@
 	// views.
 	updateAndPublish := func(uri protocol.DocumentURI, f *fileDiagnostics, diags []*cache.Diagnostic) error {
 		current, ok := f.byView[snapshot.View()]
-		if !ok || current.snapshot <= snapshot.SequenceID() {
+		// Update the stored diagnostics if:
+		//  1. we've never seen diagnostics for this view,
+		//  2. diagnostics are for an older snapshot, or
+		//  3. we're overwriting with final diagnostics
+		//
+		// In other words, we shouldn't overwrite existing diagnostics for a
+		// snapshot with non-final diagnostics. This avoids the race described at
+		// https://github.com/golang/go/issues/64765#issuecomment-1890144575.
+		if !ok || current.snapshot < snapshot.SequenceID() || (current.snapshot == snapshot.SequenceID() && final) {
 			fh, err := snapshot.ReadFile(ctx, uri)
 			if err != nil {
 				return err
@@ -855,7 +893,7 @@
 	return reports
 }
 
-func (s *server) shouldIgnoreError(ctx context.Context, snapshot *cache.Snapshot, err error) bool {
+func (s *server) shouldIgnoreError(snapshot *cache.Snapshot, err error) bool {
 	if err == nil { // if there is no error at all
 		return false
 	}
diff --git a/gopls/internal/server/folding_range.go b/gopls/internal/server/folding_range.go
index 4f47165..cb9d0cb 100644
--- a/gopls/internal/server/folding_range.go
+++ b/gopls/internal/server/folding_range.go
@@ -8,8 +8,8 @@
 	"context"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
 )
@@ -26,14 +26,14 @@
 	if snapshot.FileKind(fh) != file.Go {
 		return nil, nil // empty result
 	}
-	ranges, err := source.FoldingRange(ctx, snapshot, fh, snapshot.Options().LineFoldingOnly)
+	ranges, err := golang.FoldingRange(ctx, snapshot, fh, snapshot.Options().LineFoldingOnly)
 	if err != nil {
 		return nil, err
 	}
 	return toProtocolFoldingRanges(ranges)
 }
 
-func toProtocolFoldingRanges(ranges []*source.FoldingRangeInfo) ([]protocol.FoldingRange, error) {
+func toProtocolFoldingRanges(ranges []*golang.FoldingRangeInfo) ([]protocol.FoldingRange, error) {
 	result := make([]protocol.FoldingRange, 0, len(ranges))
 	for _, info := range ranges {
 		rng := info.MappedRange.Range()
diff --git a/gopls/internal/server/format.go b/gopls/internal/server/format.go
index 19b6b62..0e6cfdc 100644
--- a/gopls/internal/server/format.go
+++ b/gopls/internal/server/format.go
@@ -8,9 +8,9 @@
 	"context"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
 	"golang.org/x/tools/gopls/internal/mod"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/work"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
@@ -30,7 +30,7 @@
 	case file.Mod:
 		return mod.Format(ctx, snapshot, fh)
 	case file.Go:
-		return source.Format(ctx, snapshot, fh)
+		return golang.Format(ctx, snapshot, fh)
 	case file.Work:
 		return work.Format(ctx, snapshot, fh)
 	}
diff --git a/gopls/internal/server/general.go b/gopls/internal/server/general.go
index 141fed9..9f5e2b0 100644
--- a/gopls/internal/server/general.go
+++ b/gopls/internal/server/general.go
@@ -20,14 +20,15 @@
 	"strings"
 	"sync"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/debug"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/telemetry"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/goversion"
+	"golang.org/x/tools/gopls/internal/util/maps"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/jsonrpc2"
 )
@@ -36,7 +37,11 @@
 	ctx, done := event.Start(ctx, "lsp.Server.initialize")
 	defer done()
 
-	telemetry.RecordClientInfo(params)
+	var clientName string
+	if params != nil && params.ClientInfo != nil {
+		clientName = params.ClientInfo.Name
+	}
+	telemetry.RecordClientInfo(clientName)
 
 	s.stateMu.Lock()
 	if s.state >= serverInitializing {
@@ -114,6 +119,7 @@
 		// Using CodeActionOptions is only valid if codeActionLiteralSupport is set.
 		codeActionProvider = &protocol.CodeActionOptions{
 			CodeActionKinds: s.getSupportedCodeActions(),
+			ResolveProvider: true,
 		}
 	}
 	var renameOpts interface{} = true
@@ -361,7 +367,7 @@
 	defer s.watchedGlobPatternsMu.Unlock()
 
 	// Nothing to do if the set of workspace directories is unchanged.
-	if equalURISet(s.watchedGlobPatterns, patterns) {
+	if maps.SameKeys(s.watchedGlobPatterns, patterns) {
 		return nil
 	}
 
@@ -389,32 +395,32 @@
 	return fmt.Sprintf("workspace/didChangeWatchedFiles-%d", id)
 }
 
-func equalURISet(m1, m2 map[string]struct{}) bool {
-	if len(m1) != len(m2) {
-		return false
-	}
-	for k := range m1 {
-		_, ok := m2[k]
-		if !ok {
-			return false
-		}
-	}
-	return true
-}
-
 // registerWatchedDirectoriesLocked sends the workspace/didChangeWatchedFiles
 // registrations to the client and updates s.watchedDirectories.
 // The caller must not subsequently mutate patterns.
-func (s *server) registerWatchedDirectoriesLocked(ctx context.Context, patterns map[string]struct{}) error {
+func (s *server) registerWatchedDirectoriesLocked(ctx context.Context, patterns map[protocol.RelativePattern]unit) error {
 	if !s.Options().DynamicWatchedFilesSupported {
 		return nil
 	}
+
+	supportsRelativePatterns := s.Options().RelativePatternsSupported
+
 	s.watchedGlobPatterns = patterns
 	watchers := make([]protocol.FileSystemWatcher, 0, len(patterns)) // must be a slice
 	val := protocol.WatchChange | protocol.WatchDelete | protocol.WatchCreate
 	for pattern := range patterns {
+		var value any
+		if supportsRelativePatterns && pattern.BaseURI != "" {
+			value = pattern
+		} else {
+			p := pattern.Pattern
+			if pattern.BaseURI != "" {
+				p = path.Join(filepath.ToSlash(pattern.BaseURI.Path()), p)
+			}
+			value = p
+		}
 		watchers = append(watchers, protocol.FileSystemWatcher{
-			GlobPattern: pattern,
+			GlobPattern: protocol.GlobPattern{Value: value},
 			Kind:        &val,
 		})
 	}
diff --git a/gopls/internal/server/highlight.go b/gopls/internal/server/highlight.go
index 5d02564..45eeba7 100644
--- a/gopls/internal/server/highlight.go
+++ b/gopls/internal/server/highlight.go
@@ -8,8 +8,8 @@
 	"context"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/template"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
@@ -29,7 +29,7 @@
 	case file.Tmpl:
 		return template.Highlight(ctx, snapshot, fh, params.Position)
 	case file.Go:
-		rngs, err := source.Highlight(ctx, snapshot, fh, params.Position)
+		rngs, err := golang.Highlight(ctx, snapshot, fh, params.Position)
 		if err != nil {
 			event.Error(ctx, "no highlight", err)
 		}
diff --git a/gopls/internal/server/hover.go b/gopls/internal/server/hover.go
index 1a25c43..1ceede2 100644
--- a/gopls/internal/server/hover.go
+++ b/gopls/internal/server/hover.go
@@ -8,9 +8,9 @@
 	"context"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
 	"golang.org/x/tools/gopls/internal/mod"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/telemetry"
 	"golang.org/x/tools/gopls/internal/template"
 	"golang.org/x/tools/gopls/internal/work"
@@ -37,7 +37,7 @@
 	case file.Mod:
 		return mod.Hover(ctx, snapshot, fh, params.Position)
 	case file.Go:
-		return source.Hover(ctx, snapshot, fh, params.Position)
+		return golang.Hover(ctx, snapshot, fh, params.Position)
 	case file.Tmpl:
 		return template.Hover(ctx, snapshot, fh, params.Position)
 	case file.Work:
diff --git a/gopls/internal/server/implementation.go b/gopls/internal/server/implementation.go
index 51156f9..b462eac 100644
--- a/gopls/internal/server/implementation.go
+++ b/gopls/internal/server/implementation.go
@@ -8,8 +8,8 @@
 	"context"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/telemetry"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
@@ -32,5 +32,5 @@
 	if snapshot.FileKind(fh) != file.Go {
 		return nil, nil // empty result
 	}
-	return source.Implementation(ctx, snapshot, fh, params.Position)
+	return golang.Implementation(ctx, snapshot, fh, params.Position)
 }
diff --git a/gopls/internal/server/inlay_hint.go b/gopls/internal/server/inlay_hint.go
index e696df6..88ec783 100644
--- a/gopls/internal/server/inlay_hint.go
+++ b/gopls/internal/server/inlay_hint.go
@@ -8,9 +8,9 @@
 	"context"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
 	"golang.org/x/tools/gopls/internal/mod"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
 )
@@ -29,7 +29,7 @@
 	case file.Mod:
 		return mod.InlayHint(ctx, snapshot, fh, params.Range)
 	case file.Go:
-		return source.InlayHint(ctx, snapshot, fh, params.Range)
+		return golang.InlayHint(ctx, snapshot, fh, params.Range)
 	}
 	return nil, nil // empty result
 }
diff --git a/gopls/internal/server/link.go b/gopls/internal/server/link.go
index 511e50b..6ac3976 100644
--- a/gopls/internal/server/link.go
+++ b/gopls/internal/server/link.go
@@ -16,12 +16,12 @@
 	"sync"
 
 	"golang.org/x/mod/modfile"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/cache/metadata"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
@@ -121,9 +121,9 @@
 
 		// If links are to pkg.go.dev, append module version suffixes.
 		// This requires the import map from the package metadata. Ignore errors.
-		var depsByImpPath map[source.ImportPath]source.PackageID
+		var depsByImpPath map[golang.ImportPath]golang.PackageID
 		if strings.ToLower(snapshot.Options().LinkTarget) == "pkg.go.dev" {
-			if meta, err := source.NarrowestMetadataForFile(ctx, snapshot, fh.URI()); err == nil {
+			if meta, err := golang.NarrowestMetadataForFile(ctx, snapshot, fh.URI()); err == nil {
 				depsByImpPath = meta.DepsByImpPath
 			}
 		}
diff --git a/gopls/internal/server/prompt.go b/gopls/internal/server/prompt.go
index e5b5442..72c5113 100644
--- a/gopls/internal/server/prompt.go
+++ b/gopls/internal/server/prompt.go
@@ -11,7 +11,7 @@
 	"path/filepath"
 	"time"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/telemetry"
 	"golang.org/x/tools/internal/event"
 )
diff --git a/gopls/internal/server/references.go b/gopls/internal/server/references.go
index 1bdd85d..cc02d6f 100644
--- a/gopls/internal/server/references.go
+++ b/gopls/internal/server/references.go
@@ -8,8 +8,8 @@
 	"context"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/telemetry"
 	"golang.org/x/tools/gopls/internal/template"
 	"golang.org/x/tools/internal/event"
@@ -34,7 +34,7 @@
 	case file.Tmpl:
 		return template.References(ctx, snapshot, fh, params)
 	case file.Go:
-		return source.References(ctx, snapshot, fh, params.Position, params.Context.IncludeDeclaration)
+		return golang.References(ctx, snapshot, fh, params.Position, params.Context.IncludeDeclaration)
 	}
 	return nil, nil // empty result
 }
diff --git a/gopls/internal/server/rename.go b/gopls/internal/server/rename.go
index c4b28eb..946cf50 100644
--- a/gopls/internal/server/rename.go
+++ b/gopls/internal/server/rename.go
@@ -10,8 +10,8 @@
 	"path/filepath"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
 )
@@ -30,10 +30,10 @@
 		return nil, fmt.Errorf("cannot rename in file of type %s", kind)
 	}
 
-	// Because we don't handle directory renaming within source.Rename, source.Rename returns
+	// Because we don't handle directory renaming within golang.Rename, golang.Rename returns
 	// boolean value isPkgRenaming to determine whether an DocumentChanges of type RenameFile should
 	// be added to the return protocol.WorkspaceEdit value.
-	edits, isPkgRenaming, err := source.Rename(ctx, snapshot, fh, params.Position, params.NewName)
+	edits, isPkgRenaming, err := golang.Rename(ctx, snapshot, fh, params.Position, params.NewName)
 	if err != nil {
 		return nil, err
 	}
@@ -85,7 +85,7 @@
 
 	// Do not return errors here, as it adds clutter.
 	// Returning a nil result means there is not a valid rename.
-	item, usererr, err := source.PrepareRename(ctx, snapshot, fh, params.Position)
+	item, usererr, err := golang.PrepareRename(ctx, snapshot, fh, params.Position)
 	if err != nil {
 		// Return usererr here rather than err, to avoid cluttering the UI with
 		// internal error details.
diff --git a/gopls/internal/server/selection_range.go b/gopls/internal/server/selection_range.go
index 6090f4d..89142f4 100644
--- a/gopls/internal/server/selection_range.go
+++ b/gopls/internal/server/selection_range.go
@@ -9,9 +9,9 @@
 	"fmt"
 
 	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/gopls/internal/cache/parsego"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache/parsego"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 )
 
diff --git a/gopls/internal/server/semantic.go b/gopls/internal/server/semantic.go
index 161c111..646f9b3 100644
--- a/gopls/internal/server/semantic.go
+++ b/gopls/internal/server/semantic.go
@@ -5,41 +5,17 @@
 package server
 
 import (
-	"bytes"
 	"context"
-	"errors"
 	"fmt"
-	"go/ast"
-	"go/token"
-	"go/types"
-	"log"
-	"path/filepath"
-	"sort"
-	"strings"
-	"time"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/cache/metadata"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/template"
-	"golang.org/x/tools/gopls/internal/util/safetoken"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
 )
 
-// The LSP says that errors for the semantic token requests should only be returned
-// for exceptions (a word not otherwise defined). This code treats a too-large file
-// as an exception. On parse errors, the code does what it can.
-
-// reject full semantic token requests for large files
-const maxFullFileSize int = 100000
-
-// to control comprehensive logging of decisions (gopls semtok foo.go > /dev/null shows log output)
-// semDebug should NEVER be true in checked-in code
-const semDebug = false
-
 func (s *server) SemanticTokensFull(ctx context.Context, params *protocol.SemanticTokensParams) (*protocol.SemanticTokens, error) {
 	return s.semanticTokens(ctx, params.TextDocument, nil)
 }
@@ -63,931 +39,15 @@
 		return nil, fmt.Errorf("semantictokens are disabled")
 	}
 
-	kind := snapshot.FileKind(fh)
-	if kind == file.Tmpl {
-		// this is a little cumbersome to avoid both exporting 'encoded' and its methods
-		// and to avoid import cycles
-		e := &encoded{
-			ctx:            ctx,
-			metadataSource: snapshot,
-			tokTypes:       snapshot.Options().SemanticTypes,
-			tokMods:        snapshot.Options().SemanticMods,
-		}
-		add := func(line, start uint32, len uint32) {
-			// TODO(adonovan): don't ignore the rng restriction, if any.
-			e.add(line, start, len, tokMacro, nil)
-		}
-		data := func() []uint32 {
-			return e.Data()
-		}
-		return template.SemanticTokens(ctx, snapshot, fh.URI(), add, data)
-	}
-	if kind != file.Go {
+	switch snapshot.FileKind(fh) {
+	case file.Tmpl:
+		return template.SemanticTokens(ctx, snapshot, fh.URI())
+
+	case file.Go:
+		return golang.SemanticTokens(ctx, snapshot, fh, rng)
+
+	default:
+		// TODO(adonovan): should return an error!
 		return nil, nil // empty result
 	}
-	pkg, pgf, err := source.NarrowestPackageForFile(ctx, snapshot, fh.URI())
-	if err != nil {
-		return nil, err
-	}
-
-	// Select range.
-	var start, end token.Pos
-	if rng != nil {
-		var err error
-		start, end, err = pgf.RangePos(*rng)
-		if err != nil {
-			return nil, err // e.g. invalid range
-		}
-	} else {
-		tok := pgf.Tok
-		start, end = tok.Pos(0), tok.Pos(tok.Size()) // entire file
-	}
-	if int(end-start) > maxFullFileSize {
-		err := fmt.Errorf("semantic tokens: range %s too large (%d > %d)",
-			fh.URI().Path(), end-start, maxFullFileSize)
-		return nil, err
-	}
-
-	e := &encoded{
-		ctx:            ctx,
-		metadataSource: snapshot,
-		pgf:            pgf,
-		start:          start,
-		end:            end,
-		ti:             pkg.GetTypesInfo(),
-		pkg:            pkg,
-		fset:           pkg.FileSet(),
-		tokTypes:       snapshot.Options().SemanticTypes,
-		tokMods:        snapshot.Options().SemanticMods,
-		noStrings:      snapshot.Options().NoSemanticString,
-		noNumbers:      snapshot.Options().NoSemanticNumber,
-	}
-	e.semantics()
-	return &protocol.SemanticTokens{
-		Data: e.Data(),
-		// For delta requests, but we've never seen any.
-		ResultID: fmt.Sprintf("%v", time.Now()),
-	}, nil
-}
-
-func (e *encoded) semantics() {
-	f := e.pgf.File
-	// may not be in range, but harmless
-	e.token(f.Package, len("package"), tokKeyword, nil)
-	e.token(f.Name.NamePos, len(f.Name.Name), tokNamespace, nil)
-	inspect := func(n ast.Node) bool {
-		return e.inspector(n)
-	}
-	for _, d := range f.Decls {
-		// only look at the decls that overlap the range
-		start, end := d.Pos(), d.End()
-		if end <= e.start || start >= e.end {
-			continue
-		}
-		ast.Inspect(d, inspect)
-	}
-	for _, cg := range f.Comments {
-		for _, c := range cg.List {
-			if strings.HasPrefix(c.Text, "//go:") {
-				e.godirective(c)
-				continue
-			}
-			if !strings.Contains(c.Text, "\n") {
-				e.token(c.Pos(), len(c.Text), tokComment, nil)
-				continue
-			}
-			e.multiline(c.Pos(), c.End(), c.Text, tokComment)
-		}
-	}
-}
-
-type tokenType string
-
-const (
-	tokNamespace tokenType = "namespace"
-	tokType      tokenType = "type"
-	tokInterface tokenType = "interface"
-	tokTypeParam tokenType = "typeParameter"
-	tokParameter tokenType = "parameter"
-	tokVariable  tokenType = "variable"
-	tokMethod    tokenType = "method"
-	tokFunction  tokenType = "function"
-	tokKeyword   tokenType = "keyword"
-	tokComment   tokenType = "comment"
-	tokString    tokenType = "string"
-	tokNumber    tokenType = "number"
-	tokOperator  tokenType = "operator"
-
-	tokMacro tokenType = "macro" // for templates
-)
-
-func (e *encoded) token(start token.Pos, leng int, typ tokenType, mods []string) {
-	if !start.IsValid() {
-		// This is not worth reporting. TODO(pjw): does it still happen?
-		return
-	}
-	if start >= e.end || start+token.Pos(leng) <= e.start {
-		return
-	}
-	// want a line and column from start (in LSP coordinates). Ignore line directives.
-	lspRange, err := e.pgf.PosRange(start, start+token.Pos(leng))
-	if err != nil {
-		event.Error(e.ctx, "failed to convert to range", err)
-		return
-	}
-	if lspRange.End.Line != lspRange.Start.Line {
-		// this happens if users are typing at the end of the file, but report nothing
-		return
-	}
-	// token is all on one line
-	length := lspRange.End.Character - lspRange.Start.Character
-	e.add(lspRange.Start.Line, lspRange.Start.Character, length, typ, mods)
-}
-
-func (e *encoded) add(line, start uint32, len uint32, tok tokenType, mod []string) {
-	x := semItem{line, start, len, tok, mod}
-	e.items = append(e.items, x)
-}
-
-// semItem represents a token found walking the parse tree
-type semItem struct {
-	line, start uint32
-	len         uint32
-	typeStr     tokenType
-	mods        []string
-}
-
-type encoded struct {
-	// the generated data
-	items []semItem
-
-	noStrings bool
-	noNumbers bool
-
-	ctx context.Context
-	// metadataSource is used to resolve imports
-	metadataSource    metadata.Source
-	tokTypes, tokMods []string
-	pgf               *source.ParsedGoFile
-	start, end        token.Pos // range of interest
-	ti                *types.Info
-	pkg               *cache.Package
-	fset              *token.FileSet
-	// path from the root of the parse tree, used for debugging
-	stack []ast.Node
-}
-
-// convert the stack to a string, for debugging
-func (e *encoded) strStack() string {
-	msg := []string{"["}
-	for i := len(e.stack) - 1; i >= 0; i-- {
-		s := e.stack[i]
-		msg = append(msg, fmt.Sprintf("%T", s)[5:])
-	}
-	if len(e.stack) > 0 {
-		loc := e.stack[len(e.stack)-1].Pos()
-		if _, err := safetoken.Offset(e.pgf.Tok, loc); err != nil {
-			msg = append(msg, fmt.Sprintf("invalid position %v for %s", loc, e.pgf.URI))
-		} else {
-			add := safetoken.Position(e.pgf.Tok, loc)
-			nm := filepath.Base(add.Filename)
-			msg = append(msg, fmt.Sprintf("(%s:%d,col:%d)", nm, add.Line, add.Column))
-		}
-	}
-	msg = append(msg, "]")
-	return strings.Join(msg, " ")
-}
-
-// find the line in the source
-func (e *encoded) srcLine(x ast.Node) string {
-	file := e.pgf.Tok
-	line := safetoken.Line(file, x.Pos())
-	start, err := safetoken.Offset(file, file.LineStart(line))
-	if err != nil {
-		return ""
-	}
-	end := start
-	for ; end < len(e.pgf.Src) && e.pgf.Src[end] != '\n'; end++ {
-
-	}
-	ans := e.pgf.Src[start:end]
-	return string(ans)
-}
-
-func (e *encoded) inspector(n ast.Node) bool {
-	pop := func() {
-		e.stack = e.stack[:len(e.stack)-1]
-	}
-	if n == nil {
-		pop()
-		return true
-	}
-	e.stack = append(e.stack, n)
-	switch x := n.(type) {
-	case *ast.ArrayType:
-	case *ast.AssignStmt:
-		e.token(x.TokPos, len(x.Tok.String()), tokOperator, nil)
-	case *ast.BasicLit:
-		if strings.Contains(x.Value, "\n") {
-			// has to be a string.
-			e.multiline(x.Pos(), x.End(), x.Value, tokString)
-			break
-		}
-		ln := len(x.Value)
-		what := tokNumber
-		if x.Kind == token.STRING {
-			what = tokString
-		}
-		e.token(x.Pos(), ln, what, nil)
-	case *ast.BinaryExpr:
-		e.token(x.OpPos, len(x.Op.String()), tokOperator, nil)
-	case *ast.BlockStmt:
-	case *ast.BranchStmt:
-		e.token(x.TokPos, len(x.Tok.String()), tokKeyword, nil)
-		// There's no semantic encoding for labels
-	case *ast.CallExpr:
-		if x.Ellipsis != token.NoPos {
-			e.token(x.Ellipsis, len("..."), tokOperator, nil)
-		}
-	case *ast.CaseClause:
-		iam := "case"
-		if x.List == nil {
-			iam = "default"
-		}
-		e.token(x.Case, len(iam), tokKeyword, nil)
-	case *ast.ChanType:
-		// chan | chan <- | <- chan
-		switch {
-		case x.Arrow == token.NoPos:
-			e.token(x.Begin, len("chan"), tokKeyword, nil)
-		case x.Arrow == x.Begin:
-			e.token(x.Arrow, 2, tokOperator, nil)
-			pos := e.findKeyword("chan", x.Begin+2, x.Value.Pos())
-			e.token(pos, len("chan"), tokKeyword, nil)
-		case x.Arrow != x.Begin:
-			e.token(x.Begin, len("chan"), tokKeyword, nil)
-			e.token(x.Arrow, 2, tokOperator, nil)
-		}
-	case *ast.CommClause:
-		iam := len("case")
-		if x.Comm == nil {
-			iam = len("default")
-		}
-		e.token(x.Case, iam, tokKeyword, nil)
-	case *ast.CompositeLit:
-	case *ast.DeclStmt:
-	case *ast.DeferStmt:
-		e.token(x.Defer, len("defer"), tokKeyword, nil)
-	case *ast.Ellipsis:
-		e.token(x.Ellipsis, len("..."), tokOperator, nil)
-	case *ast.EmptyStmt:
-	case *ast.ExprStmt:
-	case *ast.Field:
-	case *ast.FieldList:
-	case *ast.ForStmt:
-		e.token(x.For, len("for"), tokKeyword, nil)
-	case *ast.FuncDecl:
-	case *ast.FuncLit:
-	case *ast.FuncType:
-		if x.Func != token.NoPos {
-			e.token(x.Func, len("func"), tokKeyword, nil)
-		}
-	case *ast.GenDecl:
-		e.token(x.TokPos, len(x.Tok.String()), tokKeyword, nil)
-	case *ast.GoStmt:
-		e.token(x.Go, len("go"), tokKeyword, nil)
-	case *ast.Ident:
-		e.ident(x)
-	case *ast.IfStmt:
-		e.token(x.If, len("if"), tokKeyword, nil)
-		if x.Else != nil {
-			// x.Body.End() or x.Body.End()+1, not that it matters
-			pos := e.findKeyword("else", x.Body.End(), x.Else.Pos())
-			e.token(pos, len("else"), tokKeyword, nil)
-		}
-	case *ast.ImportSpec:
-		e.importSpec(x)
-		pop()
-		return false
-	case *ast.IncDecStmt:
-		e.token(x.TokPos, len(x.Tok.String()), tokOperator, nil)
-	case *ast.IndexExpr:
-	case *ast.IndexListExpr:
-	case *ast.InterfaceType:
-		e.token(x.Interface, len("interface"), tokKeyword, nil)
-	case *ast.KeyValueExpr:
-	case *ast.LabeledStmt:
-	case *ast.MapType:
-		e.token(x.Map, len("map"), tokKeyword, nil)
-	case *ast.ParenExpr:
-	case *ast.RangeStmt:
-		e.token(x.For, len("for"), tokKeyword, nil)
-		// x.TokPos == token.NoPos is legal (for range foo {})
-		offset := x.TokPos
-		if offset == token.NoPos {
-			offset = x.For
-		}
-		pos := e.findKeyword("range", offset, x.X.Pos())
-		e.token(pos, len("range"), tokKeyword, nil)
-	case *ast.ReturnStmt:
-		e.token(x.Return, len("return"), tokKeyword, nil)
-	case *ast.SelectStmt:
-		e.token(x.Select, len("select"), tokKeyword, nil)
-	case *ast.SelectorExpr:
-	case *ast.SendStmt:
-		e.token(x.Arrow, len("<-"), tokOperator, nil)
-	case *ast.SliceExpr:
-	case *ast.StarExpr:
-		e.token(x.Star, len("*"), tokOperator, nil)
-	case *ast.StructType:
-		e.token(x.Struct, len("struct"), tokKeyword, nil)
-	case *ast.SwitchStmt:
-		e.token(x.Switch, len("switch"), tokKeyword, nil)
-	case *ast.TypeAssertExpr:
-		if x.Type == nil {
-			pos := e.findKeyword("type", x.Lparen, x.Rparen)
-			e.token(pos, len("type"), tokKeyword, nil)
-		}
-	case *ast.TypeSpec:
-	case *ast.TypeSwitchStmt:
-		e.token(x.Switch, len("switch"), tokKeyword, nil)
-	case *ast.UnaryExpr:
-		e.token(x.OpPos, len(x.Op.String()), tokOperator, nil)
-	case *ast.ValueSpec:
-	// things only seen with parsing or type errors, so ignore them
-	case *ast.BadDecl, *ast.BadExpr, *ast.BadStmt:
-		return true
-	// not going to see these
-	case *ast.File, *ast.Package:
-		e.unexpected(fmt.Sprintf("implement %T %s", x, safetoken.Position(e.pgf.Tok, x.Pos())))
-	// other things we knowingly ignore
-	case *ast.Comment, *ast.CommentGroup:
-		pop()
-		return false
-	default:
-		e.unexpected(fmt.Sprintf("failed to implement %T", x))
-	}
-	return true
-}
-
-func (e *encoded) ident(x *ast.Ident) {
-	if e.ti == nil {
-		what, mods := e.unkIdent(x)
-		if what != "" {
-			e.token(x.Pos(), len(x.String()), what, mods)
-		}
-		if semDebug {
-			log.Printf(" nil %s/nil/nil %q %v %s", x.String(), what, mods, e.strStack())
-		}
-		return
-	}
-	def := e.ti.Defs[x]
-	if def != nil {
-		what, mods := e.definitionFor(x, def)
-		if what != "" {
-			e.token(x.Pos(), len(x.String()), what, mods)
-		}
-		if semDebug {
-			log.Printf(" for %s/%T/%T got %s %v (%s)", x.String(), def, def.Type(), what, mods, e.strStack())
-		}
-		return
-	}
-	use := e.ti.Uses[x]
-	tok := func(pos token.Pos, lng int, tok tokenType, mods []string) {
-		e.token(pos, lng, tok, mods)
-		q := "nil"
-		if use != nil {
-			q = fmt.Sprintf("%T", use.Type())
-		}
-		if semDebug {
-			log.Printf(" use %s/%T/%s got %s %v (%s)", x.String(), use, q, tok, mods, e.strStack())
-		}
-	}
-
-	switch y := use.(type) {
-	case nil:
-		what, mods := e.unkIdent(x)
-		if what != "" {
-			tok(x.Pos(), len(x.String()), what, mods)
-		} else if semDebug {
-			// tok() wasn't called, so didn't log
-			log.Printf(" nil %s/%T/nil %q %v (%s)", x.String(), use, what, mods, e.strStack())
-		}
-		return
-	case *types.Builtin:
-		tok(x.NamePos, len(x.Name), tokFunction, []string{"defaultLibrary"})
-	case *types.Const:
-		mods := []string{"readonly"}
-		tt := y.Type()
-		if _, ok := tt.(*types.Basic); ok {
-			tok(x.Pos(), len(x.String()), tokVariable, mods)
-			break
-		}
-		if ttx, ok := tt.(*types.Named); ok {
-			if x.String() == "iota" {
-				e.unexpected(fmt.Sprintf("iota:%T", ttx))
-			}
-			if _, ok := ttx.Underlying().(*types.Basic); ok {
-				tok(x.Pos(), len(x.String()), tokVariable, mods)
-				break
-			}
-			e.unexpected(fmt.Sprintf("%q/%T", x.String(), tt))
-		}
-		// can this happen? Don't think so
-		e.unexpected(fmt.Sprintf("%s %T %#v", x.String(), tt, tt))
-	case *types.Func:
-		tok(x.Pos(), len(x.Name), tokFunction, nil)
-	case *types.Label:
-		// nothing to map it to
-	case *types.Nil:
-		// nil is a predeclared identifier
-		tok(x.Pos(), len("nil"), tokVariable, []string{"readonly", "defaultLibrary"})
-	case *types.PkgName:
-		tok(x.Pos(), len(x.Name), tokNamespace, nil)
-	case *types.TypeName: // could be a tokTpeParam
-		var mods []string
-		if _, ok := y.Type().(*types.Basic); ok {
-			mods = []string{"defaultLibrary"}
-		} else if _, ok := y.Type().(*types.TypeParam); ok {
-			tok(x.Pos(), len(x.String()), tokTypeParam, mods)
-			break
-		}
-		tok(x.Pos(), len(x.String()), tokType, mods)
-	case *types.Var:
-		if isSignature(y) {
-			tok(x.Pos(), len(x.Name), tokFunction, nil)
-		} else if e.isParam(use.Pos()) {
-			// variable, unless use.pos is the pos of a Field in an ancestor FuncDecl
-			// or FuncLit and then it's a parameter
-			tok(x.Pos(), len(x.Name), tokParameter, nil)
-		} else {
-			tok(x.Pos(), len(x.Name), tokVariable, nil)
-		}
-
-	default:
-		// can't happen
-		if use == nil {
-			msg := fmt.Sprintf("%#v %#v %#v", x, e.ti.Defs[x], e.ti.Uses[x])
-			e.unexpected(msg)
-		}
-		if use.Type() != nil {
-			e.unexpected(fmt.Sprintf("%s %T/%T,%#v", x.String(), use, use.Type(), use))
-		} else {
-			e.unexpected(fmt.Sprintf("%s %T", x.String(), use))
-		}
-	}
-}
-
-func (e *encoded) isParam(pos token.Pos) bool {
-	for i := len(e.stack) - 1; i >= 0; i-- {
-		switch n := e.stack[i].(type) {
-		case *ast.FuncDecl:
-			for _, f := range n.Type.Params.List {
-				for _, id := range f.Names {
-					if id.Pos() == pos {
-						return true
-					}
-				}
-			}
-		case *ast.FuncLit:
-			for _, f := range n.Type.Params.List {
-				for _, id := range f.Names {
-					if id.Pos() == pos {
-						return true
-					}
-				}
-			}
-		}
-	}
-	return false
-}
-
-func isSignature(use types.Object) bool {
-	if _, ok := use.(*types.Var); !ok {
-		return false
-	}
-	v := use.Type()
-	if v == nil {
-		return false
-	}
-	if _, ok := v.(*types.Signature); ok {
-		return true
-	}
-	return false
-}
-
-// both e.ti.Defs and e.ti.Uses are nil. use the parse stack.
-// a lot of these only happen when the package doesn't compile
-// but in that case it is all best-effort from the parse tree
-func (e *encoded) unkIdent(x *ast.Ident) (tokenType, []string) {
-	def := []string{"definition"}
-	n := len(e.stack) - 2 // parent of Ident
-	if n < 0 {
-		e.unexpected("no stack?")
-		return "", nil
-	}
-	switch nd := e.stack[n].(type) {
-	case *ast.BinaryExpr, *ast.UnaryExpr, *ast.ParenExpr, *ast.StarExpr,
-		*ast.IncDecStmt, *ast.SliceExpr, *ast.ExprStmt, *ast.IndexExpr,
-		*ast.ReturnStmt, *ast.ChanType, *ast.SendStmt,
-		*ast.ForStmt,      // possibly incomplete
-		*ast.IfStmt,       /* condition */
-		*ast.KeyValueExpr, // either key or value
-		*ast.IndexListExpr:
-		return tokVariable, nil
-	case *ast.Ellipsis:
-		return tokType, nil
-	case *ast.CaseClause:
-		if n-2 >= 0 {
-			if _, ok := e.stack[n-2].(*ast.TypeSwitchStmt); ok {
-				return tokType, nil
-			}
-		}
-		return tokVariable, nil
-	case *ast.ArrayType:
-		if x == nd.Len {
-			// or maybe a Type Param, but we can't just from the parse tree
-			return tokVariable, nil
-		} else {
-			return tokType, nil
-		}
-	case *ast.MapType:
-		return tokType, nil
-	case *ast.CallExpr:
-		if x == nd.Fun {
-			return tokFunction, nil
-		}
-		return tokVariable, nil
-	case *ast.SwitchStmt:
-		return tokVariable, nil
-	case *ast.TypeAssertExpr:
-		if x == nd.X {
-			return tokVariable, nil
-		} else if x == nd.Type {
-			return tokType, nil
-		}
-	case *ast.ValueSpec:
-		for _, p := range nd.Names {
-			if p == x {
-				return tokVariable, def
-			}
-		}
-		for _, p := range nd.Values {
-			if p == x {
-				return tokVariable, nil
-			}
-		}
-		return tokType, nil
-	case *ast.SelectorExpr: // e.ti.Selections[nd] is nil, so no help
-		if n-1 >= 0 {
-			if ce, ok := e.stack[n-1].(*ast.CallExpr); ok {
-				// ... CallExpr SelectorExpr Ident (_.x())
-				if ce.Fun == nd && nd.Sel == x {
-					return tokFunction, nil
-				}
-			}
-		}
-		return tokVariable, nil
-	case *ast.AssignStmt:
-		for _, p := range nd.Lhs {
-			// x := ..., or x = ...
-			if p == x {
-				if nd.Tok != token.DEFINE {
-					def = nil
-				}
-				return tokVariable, def // '_' in _ = ...
-			}
-		}
-		// RHS, = x
-		return tokVariable, nil
-	case *ast.TypeSpec: // it's a type if it is either the Name or the Type
-		if x == nd.Type {
-			def = nil
-		}
-		return tokType, def
-	case *ast.Field:
-		// ident could be type in a field, or a method in an interface type, or a variable
-		if x == nd.Type {
-			return tokType, nil
-		}
-		if n-2 >= 0 {
-			_, okit := e.stack[n-2].(*ast.InterfaceType)
-			_, okfl := e.stack[n-1].(*ast.FieldList)
-			if okit && okfl {
-				return tokMethod, def
-			}
-		}
-		return tokVariable, nil
-	case *ast.LabeledStmt, *ast.BranchStmt:
-		// nothing to report
-	case *ast.CompositeLit:
-		if nd.Type == x {
-			return tokType, nil
-		}
-		return tokVariable, nil
-	case *ast.RangeStmt:
-		if nd.Tok != token.DEFINE {
-			def = nil
-		}
-		return tokVariable, def
-	case *ast.FuncDecl:
-		return tokFunction, def
-	default:
-		msg := fmt.Sprintf("%T undexpected: %s %s%q", nd, x.Name, e.strStack(), e.srcLine(x))
-		e.unexpected(msg)
-	}
-	return "", nil
-}
-
-func isDeprecated(n *ast.CommentGroup) bool {
-	if n == nil {
-		return false
-	}
-	for _, c := range n.List {
-		if strings.HasPrefix(c.Text, "// Deprecated") {
-			return true
-		}
-	}
-	return false
-}
-
-func (e *encoded) definitionFor(x *ast.Ident, def types.Object) (tokenType, []string) {
-	// PJW: def == types.Label? probably a nothing
-	// PJW: look into replacing these syntactic tests with types more generally
-	mods := []string{"definition"}
-	for i := len(e.stack) - 1; i >= 0; i-- {
-		s := e.stack[i]
-		switch y := s.(type) {
-		case *ast.AssignStmt, *ast.RangeStmt:
-			if x.Name == "_" {
-				return "", nil // not really a variable
-			}
-			return tokVariable, mods
-		case *ast.GenDecl:
-			if isDeprecated(y.Doc) {
-				mods = append(mods, "deprecated")
-			}
-			if y.Tok == token.CONST {
-				mods = append(mods, "readonly")
-			}
-			return tokVariable, mods
-		case *ast.FuncDecl:
-			// If x is immediately under a FuncDecl, it is a function or method
-			if i == len(e.stack)-2 {
-				if isDeprecated(y.Doc) {
-					mods = append(mods, "deprecated")
-				}
-				if y.Recv != nil {
-					return tokMethod, mods
-				}
-				return tokFunction, mods
-			}
-			// if x < ... < FieldList < FuncDecl, this is the receiver, a variable
-			// PJW: maybe not. it might be a typeparameter in the type of the receiver
-			if _, ok := e.stack[i+1].(*ast.FieldList); ok {
-				if _, ok := def.(*types.TypeName); ok {
-					return tokTypeParam, mods
-				}
-				return tokVariable, nil
-			}
-			// if x < ... < FieldList < FuncType < FuncDecl, this is a param
-			return tokParameter, mods
-		case *ast.FuncType: // is it in the TypeParams?
-			if isTypeParam(x, y) {
-				return tokTypeParam, mods
-			}
-			return tokParameter, mods
-		case *ast.InterfaceType:
-			return tokMethod, mods
-		case *ast.TypeSpec:
-			// GenDecl/Typespec/FuncType/FieldList/Field/Ident
-			// (type A func(b uint64)) (err error)
-			// b and err should not be tokType, but tokVaraible
-			// and in GenDecl/TpeSpec/StructType/FieldList/Field/Ident
-			// (type A struct{b uint64}
-			// but on type B struct{C}), C is a type, but is not being defined.
-			// GenDecl/TypeSpec/FieldList/Field/Ident is a typeParam
-			if _, ok := e.stack[i+1].(*ast.FieldList); ok {
-				return tokTypeParam, mods
-			}
-			fldm := e.stack[len(e.stack)-2]
-			if fld, ok := fldm.(*ast.Field); ok {
-				// if len(fld.names) == 0 this is a tokType, being used
-				if len(fld.Names) == 0 {
-					return tokType, nil
-				}
-				return tokVariable, mods
-			}
-			return tokType, mods
-		}
-	}
-	// can't happen
-	msg := fmt.Sprintf("failed to find the decl for %s", safetoken.Position(e.pgf.Tok, x.Pos()))
-	e.unexpected(msg)
-	return "", []string{""}
-}
-
-func isTypeParam(x *ast.Ident, y *ast.FuncType) bool {
-	tp := y.TypeParams
-	if tp == nil {
-		return false
-	}
-	for _, p := range tp.List {
-		for _, n := range p.Names {
-			if x == n {
-				return true
-			}
-		}
-	}
-	return false
-}
-
-func (e *encoded) multiline(start, end token.Pos, val string, tok tokenType) {
-	f := e.fset.File(start)
-	// the hard part is finding the lengths of lines. include the \n
-	leng := func(line int) int {
-		n := f.LineStart(line)
-		if line >= f.LineCount() {
-			return f.Size() - int(n)
-		}
-		return int(f.LineStart(line+1) - n)
-	}
-	spos := safetoken.StartPosition(e.fset, start)
-	epos := safetoken.EndPosition(e.fset, end)
-	sline := spos.Line
-	eline := epos.Line
-	// first line is from spos.Column to end
-	e.token(start, leng(sline)-spos.Column, tok, nil) // leng(sline)-1 - (spos.Column-1)
-	for i := sline + 1; i < eline; i++ {
-		// intermediate lines are from 1 to end
-		e.token(f.LineStart(i), leng(i)-1, tok, nil) // avoid the newline
-	}
-	// last line is from 1 to epos.Column
-	e.token(f.LineStart(eline), epos.Column-1, tok, nil) // columns are 1-based
-}
-
-// findKeyword finds a keyword rather than guessing its location
-func (e *encoded) findKeyword(keyword string, start, end token.Pos) token.Pos {
-	offset := int(start) - e.pgf.Tok.Base()
-	last := int(end) - e.pgf.Tok.Base()
-	buf := e.pgf.Src
-	idx := bytes.Index(buf[offset:last], []byte(keyword))
-	if idx != -1 {
-		return start + token.Pos(idx)
-	}
-	//(in unparsable programs: type _ <-<-chan int)
-	e.unexpected(fmt.Sprintf("not found:%s %v", keyword, safetoken.StartPosition(e.fset, start)))
-	return token.NoPos
-}
-
-func (e *encoded) Data() []uint32 {
-	// binary operators, at least, will be out of order
-	sort.Slice(e.items, func(i, j int) bool {
-		if e.items[i].line != e.items[j].line {
-			return e.items[i].line < e.items[j].line
-		}
-		return e.items[i].start < e.items[j].start
-	})
-	typeMap, modMap := e.maps()
-	// each semantic token needs five values
-	// (see Integer Encoding for Tokens in the LSP spec)
-	x := make([]uint32, 5*len(e.items))
-	var j int
-	var last semItem
-	for i := 0; i < len(e.items); i++ {
-		item := e.items[i]
-		typ, ok := typeMap[item.typeStr]
-		if !ok {
-			continue // client doesn't want typeStr
-		}
-		if item.typeStr == tokString && e.noStrings {
-			continue
-		}
-		if item.typeStr == tokNumber && e.noNumbers {
-			continue
-		}
-		if j == 0 {
-			x[0] = e.items[0].line
-		} else {
-			x[j] = item.line - last.line
-		}
-		x[j+1] = item.start
-		if j > 0 && x[j] == 0 {
-			x[j+1] = item.start - last.start
-		}
-		x[j+2] = item.len
-		x[j+3] = uint32(typ)
-		mask := 0
-		for _, s := range item.mods {
-			// modMap[s] is 0 if the client doesn't want this modifier
-			mask |= modMap[s]
-		}
-		x[j+4] = uint32(mask)
-		j += 5
-		last = item
-	}
-	return x[:j]
-}
-
-func (e *encoded) importSpec(d *ast.ImportSpec) {
-	// a local package name or the last component of the Path
-	if d.Name != nil {
-		nm := d.Name.String()
-		if nm != "_" && nm != "." {
-			e.token(d.Name.Pos(), len(nm), tokNamespace, nil)
-		}
-		return // don't mark anything for . or _
-	}
-	importPath := metadata.UnquoteImportPath(d)
-	if importPath == "" {
-		return
-	}
-	// Import strings are implementation defined. Try to match with parse information.
-	depID := e.pkg.Metadata().DepsByImpPath[importPath]
-	if depID == "" {
-		return
-	}
-	depMD := e.metadataSource.Metadata(depID)
-	if depMD == nil {
-		// unexpected, but impact is that maybe some import is not colored
-		return
-	}
-	// Check whether the original literal contains the package's declared name.
-	j := strings.LastIndex(d.Path.Value, string(depMD.Name))
-	if j == -1 {
-		// Package name does not match import path, so there is nothing to report.
-		return
-	}
-	// Report virtual declaration at the position of the substring.
-	start := d.Path.Pos() + token.Pos(j)
-	e.token(start, len(depMD.Name), tokNamespace, nil)
-}
-
-// log unexpected state
-func (e *encoded) unexpected(msg string) {
-	if semDebug {
-		panic(msg)
-	}
-	event.Error(e.ctx, e.strStack(), errors.New(msg))
-}
-
-func (e *encoded) maps() (map[tokenType]int, map[string]int) {
-	tmap := make(map[tokenType]int)
-	mmap := make(map[string]int)
-	for i, t := range e.tokTypes {
-		tmap[tokenType(t)] = i
-	}
-	for i, m := range e.tokMods {
-		mmap[m] = 1 << uint(i) // go 1.12 compatibility
-	}
-	return tmap, mmap
-}
-
-var godirectives = map[string]struct{}{
-	// https://pkg.go.dev/cmd/compile
-	"noescape":       {},
-	"uintptrescapes": {},
-	"noinline":       {},
-	"norace":         {},
-	"nosplit":        {},
-	"linkname":       {},
-
-	// https://pkg.go.dev/go/build
-	"build":               {},
-	"binary-only-package": {},
-	"embed":               {},
-}
-
-// Tokenize godirective at the start of the comment c, if any, and the surrounding comment.
-// If there is any failure, emits the entire comment as a tokComment token.
-// Directives are highlighted as-is, even if used incorrectly. Typically there are
-// dedicated analyzers that will warn about misuse.
-func (e *encoded) godirective(c *ast.Comment) {
-	// First check if '//go:directive args...' is a valid directive.
-	directive, args, _ := strings.Cut(c.Text, " ")
-	kind, _ := stringsCutPrefix(directive, "//go:")
-	if _, ok := godirectives[kind]; !ok {
-		// Unknown go: directive.
-		e.token(c.Pos(), len(c.Text), tokComment, nil)
-		return
-	}
-
-	// Make the 'go:directive' part stand out, the rest is comments.
-	e.token(c.Pos(), len("//"), tokComment, nil)
-
-	directiveStart := c.Pos() + token.Pos(len("//"))
-	e.token(directiveStart, len(directive[len("//"):]), tokNamespace, nil)
-
-	if len(args) > 0 {
-		tailStart := c.Pos() + token.Pos(len(directive)+len(" "))
-		e.token(tailStart, len(args), tokComment, nil)
-	}
-}
-
-// Go 1.20 strings.CutPrefix.
-func stringsCutPrefix(s, prefix string) (after string, found bool) {
-	if !strings.HasPrefix(s, prefix) {
-		return s, false
-	}
-	return s[len(prefix):], true
 }
diff --git a/gopls/internal/server/server.go b/gopls/internal/server/server.go
index 3b80769..ff0c268 100644
--- a/gopls/internal/server/server.go
+++ b/gopls/internal/server/server.go
@@ -12,9 +12,9 @@
 	"os"
 	"sync"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/progress"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/progress"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/internal/event"
 )
@@ -89,7 +89,7 @@
 	// that the server should watch changes.
 	// The map field may be reassigned but the map is immutable.
 	watchedGlobPatternsMu  sync.Mutex
-	watchedGlobPatterns    map[string]unit
+	watchedGlobPatterns    map[protocol.RelativePattern]unit
 	watchRegistrationCount int
 
 	diagnosticsMu sync.Mutex
diff --git a/gopls/internal/server/signature_help.go b/gopls/internal/server/signature_help.go
index fb2262a..712c35b 100644
--- a/gopls/internal/server/signature_help.go
+++ b/gopls/internal/server/signature_help.go
@@ -8,8 +8,8 @@
 	"context"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
 )
@@ -28,7 +28,7 @@
 		return nil, nil // empty result
 	}
 
-	info, activeParameter, err := source.SignatureHelp(ctx, snapshot, fh, params.Position)
+	info, activeParameter, err := golang.SignatureHelp(ctx, snapshot, fh, params.Position)
 	if err != nil {
 		event.Error(ctx, "no signature help", err, tag.Position.Of(params.Position))
 		return nil, nil // sic? There could be many reasons for failure.
diff --git a/gopls/internal/server/symbols.go b/gopls/internal/server/symbols.go
index 6eb0057..3442318 100644
--- a/gopls/internal/server/symbols.go
+++ b/gopls/internal/server/symbols.go
@@ -8,8 +8,8 @@
 	"context"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/template"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
@@ -30,7 +30,7 @@
 	case file.Tmpl:
 		docSymbols, err = template.DocumentSymbols(snapshot, fh)
 	case file.Go:
-		docSymbols, err = source.DocumentSymbols(ctx, snapshot, fh)
+		docSymbols, err = golang.DocumentSymbols(ctx, snapshot, fh)
 	default:
 		return nil, nil // empty result
 	}
diff --git a/gopls/internal/server/text_synchronization.go b/gopls/internal/server/text_synchronization.go
index 30385d0..ae35394 100644
--- a/gopls/internal/server/text_synchronization.go
+++ b/gopls/internal/server/text_synchronization.go
@@ -12,10 +12,10 @@
 	"path/filepath"
 	"sync"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/event/tag"
 	"golang.org/x/tools/internal/jsonrpc2"
@@ -162,7 +162,7 @@
 	if err != nil {
 		return err
 	}
-	isGenerated := source.IsGenerated(ctx, snapshot, uri)
+	isGenerated := golang.IsGenerated(ctx, snapshot, uri)
 	release()
 
 	if isGenerated {
diff --git a/gopls/internal/server/unimplemented.go b/gopls/internal/server/unimplemented.go
index 6f897ad..c293ee1 100644
--- a/gopls/internal/server/unimplemented.go
+++ b/gopls/internal/server/unimplemented.go
@@ -10,7 +10,7 @@
 	"context"
 	"fmt"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/jsonrpc2"
 )
 
@@ -102,10 +102,6 @@
 	return nil, notImplemented("Resolve")
 }
 
-func (s *server) ResolveCodeAction(context.Context, *protocol.CodeAction) (*protocol.CodeAction, error) {
-	return nil, notImplemented("ResolveCodeAction")
-}
-
 func (s *server) ResolveCodeLens(context.Context, *protocol.CodeLens) (*protocol.CodeLens, error) {
 	return nil, notImplemented("ResolveCodeLens")
 }
diff --git a/gopls/internal/server/workspace.go b/gopls/internal/server/workspace.go
index aa9eed1..1a3c086 100644
--- a/gopls/internal/server/workspace.go
+++ b/gopls/internal/server/workspace.go
@@ -9,8 +9,8 @@
 	"fmt"
 	"sync"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 )
 
diff --git a/gopls/internal/server/workspace_symbol.go b/gopls/internal/server/workspace_symbol.go
index 3b96a38..9eafeb0 100644
--- a/gopls/internal/server/workspace_symbol.go
+++ b/gopls/internal/server/workspace_symbol.go
@@ -7,9 +7,9 @@
 import (
 	"context"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/golang"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/telemetry"
 	"golang.org/x/tools/internal/event"
 )
@@ -37,5 +37,5 @@
 		defer release()
 		snapshots = append(snapshots, snapshot)
 	}
-	return source.WorkspaceSymbols(ctx, matcher, style, snapshots, params.Query)
+	return golang.WorkspaceSymbols(ctx, matcher, style, snapshots, params.Query)
 }
diff --git a/gopls/internal/settings/analyzer.go b/gopls/internal/settings/analyzer.go
index f937693..d855aa2 100644
--- a/gopls/internal/settings/analyzer.go
+++ b/gopls/internal/settings/analyzer.go
@@ -6,23 +6,7 @@
 
 import (
 	"golang.org/x/tools/go/analysis"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-)
-
-// A Fix identifies kinds of suggested fix, both in Analyzer.Fix and in the
-// ApplyFix subcommand (see ExecuteCommand and ApplyFixArgs.Fix).
-type Fix string
-
-const (
-	FillStruct        Fix = "fill_struct"
-	StubMethods       Fix = "stub_methods"
-	UndeclaredName    Fix = "undeclared_name"
-	ExtractVariable   Fix = "extract_variable"
-	ExtractFunction   Fix = "extract_function"
-	ExtractMethod     Fix = "extract_method"
-	InlineCall        Fix = "inline_call"
-	InvertIfCondition Fix = "invert_if_condition"
-	AddEmbedImport    Fix = "add_embed_import"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // Analyzer augments a go/analysis analyzer with additional LSP configuration.
@@ -36,18 +20,15 @@
 	// Most clients should use the IsEnabled method.
 	Enabled bool
 
-	// Fix is the name of the suggested fix name used to invoke the suggested
-	// fixes for the analyzer. It is non-empty if we expect this analyzer to
-	// provide its fix separately from its diagnostics. That is, we should apply
-	// the analyzer's suggested fixes through a Command, not a TextEdit.
-	Fix Fix
-
-	// ActionKind is the set of kinds of code action this analyzer produces.
+	// ActionKinds is the set of kinds of code action this analyzer produces.
 	// If empty, the set is just QuickFix.
-	ActionKind []protocol.CodeActionKind
+	ActionKinds []protocol.CodeActionKind
 
 	// Severity is the severity set for diagnostics reported by this
 	// analyzer. If left unset it defaults to Warning.
+	//
+	// Note: diagnostics with severity protocol.SeverityHint do not show up in
+	// the VS Code "problems" tab.
 	Severity protocol.DiagnosticSeverity
 
 	// Tag is extra tags (unnecessary, deprecated, etc) for diagnostics
diff --git a/gopls/internal/settings/api_json.go b/gopls/internal/settings/api_json.go
index 7f67609..9324992 100644
--- a/gopls/internal/settings/api_json.go
+++ b/gopls/internal/settings/api_json.go
@@ -214,7 +214,7 @@
 			{
 				Name: "analyses",
 				Type: "map[string]bool",
-				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",
+				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  \"unusedvariable\": true  // Enable the unusedvariable analyzer.\n}\n...\n```\n",
 				EnumKeys: EnumKeys{
 					ValueType: "bool",
 					Keys: []EnumKey{
@@ -304,6 +304,11 @@
 							Default: "false",
 						},
 						{
+							Name:    "\"fillreturns\"",
+							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\n\tfunc m() (int, string, *bool, error) {\n\t\treturn\n\t}\n\nwill turn into\n\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.",
+							Default: "true",
+						},
+						{
 							Name:    "\"httpresponse\"",
 							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.",
 							Default: "true",
@@ -314,6 +319,11 @@
 							Default: "true",
 						},
 						{
+							Name:    "\"infertypeargs\"",
+							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",
+							Default: "true",
+						},
+						{
 							Name:    "\"loopclosure\"",
 							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\nNote: An iteration variable can only outlive a loop iteration in Go versions <=1.21.\nIn Go 1.22 and later, the loop variable lifetimes changed to create a new\niteration variable per loop iteration. (See go.dev/issue/60078.)\n\nIn this example, all the deferred functions run after the loop has\ncompleted, so all observe the final value of v [<go1.22].\n\n\tfor _, v := range list {\n\t    defer func() {\n\t        use(v) // incorrect\n\t    }()\n\t}\n\nOne fix is to create a new variable for each iteration of the loop:\n\n\tfor _, v := range list {\n\t    v := v // new var per iteration\n\t    defer func() {\n\t        use(v) // ok\n\t    }()\n\t}\n\nAfter Go version 1.22, the previous two for loops are equivalent\nand both are correct.\n\nThe next example uses a go statement and has a similar problem [<go1.22].\nIn addition, it has a data race because the loop updates v\nconcurrent with the goroutines accessing it.\n\n\tfor _, v := range elem {\n\t    go func() {\n\t        use(v)  // incorrect, and a data race\n\t    }()\n\t}\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\tfunc Test(t *testing.T) {\n\t    for _, test := range tests {\n\t        t.Run(test.name, func(t *testing.T) {\n\t            t.Parallel()\n\t            use(test) // incorrect, and a data race\n\t        })\n\t    }\n\t}\n\nThe t.Parallel() call causes the rest of the function to execute\nconcurrent with the loop [<go1.22].\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",
 							Default: "true",
@@ -334,6 +344,16 @@
 							Default: "true",
 						},
 						{
+							Name:    "\"nonewvars\"",
+							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\n\tz := 1\n\tz := 2\n\nwill turn into\n\n\tz := 1\n\tz = 2",
+							Default: "true",
+						},
+						{
+							Name:    "\"noresultvalues\"",
+							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\n\tfunc z() { return nil }\n\nwill turn into\n\n\tfunc z() { return }",
+							Default: "true",
+						},
+						{
 							Name:    "\"printf\"",
 							Doc:     "check consistency of Printf format strings and arguments\n\nThe check applies to calls of the formatting functions such as\n[fmt.Printf] and [fmt.Sprintf], as well as any detected wrappers of\nthose functions.\n\nIn this example, the %d format operator requires an integer operand:\n\n\tfmt.Printf(\"%d\", \"hello\") // fmt.Printf format %d has arg \"hello\" of wrong type string\n\nSee the documentation of the fmt package for the complete set of\nformat operators and their operand types.\n\nTo enable printf checking on a function that is not found by this\nanalyzer's heuristics (for example, because control is obscured by\ndynamic method calls), insert a bogus call:\n\n\tfunc MyPrintf(format string, args ...any) {\n\t\tif false {\n\t\t\t_ = fmt.Sprintf(format, args...) // enable printf checker\n\t\t}\n\t\t...\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.",
 							Default: "true",
@@ -389,6 +409,11 @@
 							Default: "true",
 						},
 						{
+							Name:    "\"stubmethods\"",
+							Doc:     "detect missing methods and fix with stub implementations\n\nThis analyzer detects type-checking errors due to missing methods\nin assignments from concrete types to interface types, and offers\na suggested fix that will create a set of stub methods so that\nthe concrete type satisfies the interface.\n\nFor example, this function will not compile because the value\nNegativeErr{} does not implement the \"error\" interface:\n\n\tfunc sqrt(x float64) (float64, error) {\n\t\tif x < 0 {\n\t\t\treturn 0, NegativeErr{} // error: missing method\n\t\t}\n\t\t...\n\t}\n\n\ttype NegativeErr struct{}\n\nThis analyzer will suggest a fix to declare this method:\n\n\t// Error implements error.Error.\n\tfunc (NegativeErr) Error() string {\n\t\tpanic(\"unimplemented\")\n\t}\n\n(At least, it appears to behave that way, but technically it\ndoesn't use the SuggestedFix mechanism and the stub is created by\nlogic in gopls's golang.stub function.)",
+							Default: "true",
+						},
+						{
 							Name:    "\"testinggoroutine\"",
 							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\n\tfunc TestFoo(t *testing.T) {\n\t    go func() {\n\t        t.Fatal(\"oops\") // error: (*T).Fatal called from non-test goroutine\n\t    }()\n\t}",
 							Default: "true",
@@ -404,6 +429,11 @@
 							Default: "true",
 						},
 						{
+							Name:    "\"undeclaredname\"",
+							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\t<> :=\n\nor a new function declaration, such as:\n\n\tfunc <>(inferred parameters) {\n\t\tpanic(\"implement me!\")\n\t}",
+							Default: "true",
+						},
+						{
 							Name:    "\"unmarshal\"",
 							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.",
 							Default: "true",
@@ -420,8 +450,8 @@
 						},
 						{
 							Name:    "\"unusedparams\"",
-							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 have the name '_' (the blank identifier)\n- functions in test files\n- functions with empty bodies or those with just a return stmt",
-							Default: "false",
+							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 ensure soundness, it ignores:\n  - \"address-taken\" functions, that is, functions that are used as\n    a value rather than being called directly; their signatures may\n    be required to conform to a func type.\n  - exported functions or methods, since they may be address-taken\n    in another package.\n  - unexported methods whose name matches an interface method\n    declared in the same package, since the method's signature\n    may be required to conform to the interface type.\n  - functions with empty bodies, or containing just a call to panic.\n  - parameters that are unnamed, or named \"_\", the blank identifier.\n\nThe analyzer suggests a fix of replacing the parameter name by \"_\",\nbut in such cases a deeper fix can be obtained by invoking the\n\"Refactor: remove unused parameter\" code action, which will\neliminate the parameter entirely, along with all corresponding\narguments at call sites, while taking care to preserve any side\neffects in the argument expressions; see\nhttps://github.com/golang/tools/releases/tag/gopls%2Fv0.14.",
+							Default: "true",
 						},
 						{
 							Name:    "\"unusedresult\"",
@@ -429,6 +459,11 @@
 							Default: "true",
 						},
 						{
+							Name:    "\"unusedvariable\"",
+							Doc:     "check for unused variables and suggest fixes",
+							Default: "false",
+						},
+						{
 							Name:    "\"unusedwrite\"",
 							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\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\n\tfunc (t T) f() {  // t is a copy\n\t\tt.x = i  // unused write to field x\n\t}",
 							Default: "false",
@@ -438,46 +473,6 @@
 							Doc:     "check for constraints that could be simplified to \"any\"",
 							Default: "false",
 						},
-						{
-							Name:    "\"fillreturns\"",
-							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\n\tfunc m() (int, string, *bool, error) {\n\t\treturn\n\t}\n\nwill turn into\n\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.",
-							Default: "true",
-						},
-						{
-							Name:    "\"nonewvars\"",
-							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\n\tz := 1\n\tz := 2\n\nwill turn into\n\n\tz := 1\n\tz = 2",
-							Default: "true",
-						},
-						{
-							Name:    "\"noresultvalues\"",
-							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\n\tfunc z() { return nil }\n\nwill turn into\n\n\tfunc z() { return }",
-							Default: "true",
-						},
-						{
-							Name:    "\"undeclaredname\"",
-							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\t<> :=\n\nor a new function declaration, such as:\n\n\tfunc <>(inferred parameters) {\n\t\tpanic(\"implement me!\")\n\t}",
-							Default: "true",
-						},
-						{
-							Name:    "\"unusedvariable\"",
-							Doc:     "check for unused variables and suggest fixes",
-							Default: "false",
-						},
-						{
-							Name:    "\"fillstruct\"",
-							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",
-							Default: "true",
-						},
-						{
-							Name:    "\"infertypeargs\"",
-							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",
-							Default: "true",
-						},
-						{
-							Name:    "\"stubmethods\"",
-							Doc:     "detect missing methods and fix with stub implementations\n\nThis analyzer detects type-checking errors due to missing methods\nin assignments from concrete types to interface types, and offers\na suggested fix that will create a set of stub methods so that\nthe concrete type satisfies the interface.\n\nFor example, this function will not compile because the value\nNegativeErr{} does not implement the \"error\" interface:\n\n\tfunc sqrt(x float64) (float64, error) {\n\t\tif x < 0 {\n\t\t\treturn 0, NegativeErr{} // error: missing method\n\t\t}\n\t\t...\n\t}\n\n\ttype NegativeErr struct{}\n\nThis analyzer will suggest a fix to declare this method:\n\n\t// Error implements error.Error.\n\tfunc (NegativeErr) Error() string {\n\t\tpanic(\"unimplemented\")\n\t}\n\n(At least, it appears to behave that way, but technically it\ndoesn't use the SuggestedFix mechanism and the stub is created by\nlogic in gopls's source.stub function.)",
-							Default: "true",
-						},
 					},
 				},
 				Default:   "{}",
@@ -739,16 +734,18 @@
 			ArgDoc:  "{\n\t// Names and Values must have the same length.\n\t\"Names\": []string,\n\t\"Values\": []int64,\n}",
 		},
 		{
-			Command: "gopls.apply_fix",
-			Title:   "Apply a fix",
-			Doc:     "Applies a fix to a region of source code.",
-			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}",
+			Command:   "gopls.apply_fix",
+			Title:     "Apply a fix",
+			Doc:       "Applies a fix to a region of source code.",
+			ArgDoc:    "{\n\t// The name of the fix to apply.\n\t//\n\t// For fixes suggested by analyzers, this is a string constant\n\t// advertised by the analyzer that matches the Category of\n\t// the analysis.Diagnostic with a SuggestedFix containing no edits.\n\t//\n\t// For fixes suggested by code actions, this is a string agreed\n\t// upon by the code action and golang.ApplyFix.\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\t// Whether to resolve and return the edits.\n\t\"ResolveEdits\": bool,\n}",
+			ResultDoc: "{\n\t// Holds changes to existing resources.\n\t\"changes\": map[golang.org/x/tools/gopls/internal/protocol.DocumentURI][]golang.org/x/tools/gopls/internal/protocol.TextEdit,\n\t// Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes\n\t// are either an array of `TextDocumentEdit`s to express changes to n different text documents\n\t// where each text document edit addresses a specific version of a text document. Or it can contain\n\t// above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations.\n\t//\n\t// Whether a client supports versioned document edits is expressed via\n\t// `workspace.workspaceEdit.documentChanges` client capability.\n\t//\n\t// If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then\n\t// only plain `TextEdit`s using the `changes` property are supported.\n\t\"documentChanges\": []{\n\t\t\"TextDocumentEdit\": {\n\t\t\t\"textDocument\": { ... },\n\t\t\t\"edits\": { ... },\n\t\t},\n\t\t\"RenameFile\": {\n\t\t\t\"kind\": string,\n\t\t\t\"oldUri\": string,\n\t\t\t\"newUri\": string,\n\t\t\t\"options\": { ... },\n\t\t\t\"ResourceOperation\": { ... },\n\t\t},\n\t},\n\t// A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and\n\t// delete file / folder operations.\n\t//\n\t// Whether clients honor this property depends on the client capability `workspace.changeAnnotationSupport`.\n\t//\n\t// @since 3.16.0\n\t\"changeAnnotations\": map[string]golang.org/x/tools/gopls/internal/protocol.ChangeAnnotation,\n}",
 		},
 		{
-			Command: "gopls.change_signature",
-			Title:   "Perform a \"change signature\" refactoring",
-			Doc:     "This command is experimental, currently only supporting parameter removal.\nIts signature will certainly change in the future (pun intended).",
-			ArgDoc:  "{\n\t\"RemoveParameter\": {\n\t\t\"uri\": string,\n\t\t\"range\": {\n\t\t\t\"start\": { ... },\n\t\t\t\"end\": { ... },\n\t\t},\n\t},\n}",
+			Command:   "gopls.change_signature",
+			Title:     "Perform a \"change signature\" refactoring",
+			Doc:       "This command is experimental, currently only supporting parameter removal.\nIts signature will certainly change in the future (pun intended).",
+			ArgDoc:    "{\n\t\"RemoveParameter\": {\n\t\t\"uri\": string,\n\t\t\"range\": {\n\t\t\t\"start\": { ... },\n\t\t\t\"end\": { ... },\n\t\t},\n\t},\n\t// Whether to resolve and return the edits.\n\t\"ResolveEdits\": bool,\n}",
+			ResultDoc: "{\n\t// Holds changes to existing resources.\n\t\"changes\": map[golang.org/x/tools/gopls/internal/protocol.DocumentURI][]golang.org/x/tools/gopls/internal/protocol.TextEdit,\n\t// Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes\n\t// are either an array of `TextDocumentEdit`s to express changes to n different text documents\n\t// where each text document edit addresses a specific version of a text document. Or it can contain\n\t// above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations.\n\t//\n\t// Whether a client supports versioned document edits is expressed via\n\t// `workspace.workspaceEdit.documentChanges` client capability.\n\t//\n\t// If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then\n\t// only plain `TextEdit`s using the `changes` property are supported.\n\t\"documentChanges\": []{\n\t\t\"TextDocumentEdit\": {\n\t\t\t\"textDocument\": { ... },\n\t\t\t\"edits\": { ... },\n\t\t},\n\t\t\"RenameFile\": {\n\t\t\t\"kind\": string,\n\t\t\t\"oldUri\": string,\n\t\t\t\"newUri\": string,\n\t\t\t\"options\": { ... },\n\t\t\t\"ResourceOperation\": { ... },\n\t\t},\n\t},\n\t// A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and\n\t// delete file / folder operations.\n\t//\n\t// Whether clients honor this property depends on the client capability `workspace.changeAnnotationSupport`.\n\t//\n\t// @since 3.16.0\n\t\"changeAnnotations\": map[string]golang.org/x/tools/gopls/internal/protocol.ChangeAnnotation,\n}",
 		},
 		{
 			Command: "gopls.check_upgrades",
@@ -773,7 +770,7 @@
 			Title:     "Get known vulncheck result",
 			Doc:       "Fetch the result of latest vulnerability check (`govulncheck`).",
 			ArgDoc:    "{\n\t// The file URI.\n\t\"URI\": string,\n}",
-			ResultDoc: "map[golang.org/x/tools/gopls/internal/lsp/protocol.DocumentURI]*golang.org/x/tools/gopls/internal/vulncheck.Result",
+			ResultDoc: "map[golang.org/x/tools/gopls/internal/protocol.DocumentURI]*golang.org/x/tools/gopls/internal/vulncheck.Result",
 		},
 		{
 			Command: "gopls.gc_details",
@@ -1070,6 +1067,12 @@
 			URL:  "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/fieldalignment",
 		},
 		{
+			Name:    "fillreturns",
+			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\n\tfunc m() (int, string, *bool, error) {\n\t\treturn\n\t}\n\nwill turn into\n\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.",
+			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillreturns",
+			Default: true,
+		},
+		{
 			Name:    "httpresponse",
 			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.",
 			URL:     "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/httpresponse",
@@ -1082,6 +1085,12 @@
 			Default: true,
 		},
 		{
+			Name:    "infertypeargs",
+			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",
+			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/infertypeargs",
+			Default: true,
+		},
+		{
 			Name:    "loopclosure",
 			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\nNote: An iteration variable can only outlive a loop iteration in Go versions <=1.21.\nIn Go 1.22 and later, the loop variable lifetimes changed to create a new\niteration variable per loop iteration. (See go.dev/issue/60078.)\n\nIn this example, all the deferred functions run after the loop has\ncompleted, so all observe the final value of v [<go1.22].\n\n\tfor _, v := range list {\n\t    defer func() {\n\t        use(v) // incorrect\n\t    }()\n\t}\n\nOne fix is to create a new variable for each iteration of the loop:\n\n\tfor _, v := range list {\n\t    v := v // new var per iteration\n\t    defer func() {\n\t        use(v) // ok\n\t    }()\n\t}\n\nAfter Go version 1.22, the previous two for loops are equivalent\nand both are correct.\n\nThe next example uses a go statement and has a similar problem [<go1.22].\nIn addition, it has a data race because the loop updates v\nconcurrent with the goroutines accessing it.\n\n\tfor _, v := range elem {\n\t    go func() {\n\t        use(v)  // incorrect, and a data race\n\t    }()\n\t}\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\tfunc Test(t *testing.T) {\n\t    for _, test := range tests {\n\t        t.Run(test.name, func(t *testing.T) {\n\t            t.Parallel()\n\t            use(test) // incorrect, and a data race\n\t        })\n\t    }\n\t}\n\nThe t.Parallel() call causes the rest of the function to execute\nconcurrent with the loop [<go1.22].\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",
 			URL:     "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/loopclosure",
@@ -1106,6 +1115,18 @@
 			Default: true,
 		},
 		{
+			Name:    "nonewvars",
+			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\n\tz := 1\n\tz := 2\n\nwill turn into\n\n\tz := 1\n\tz = 2",
+			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/nonewvars",
+			Default: true,
+		},
+		{
+			Name:    "noresultvalues",
+			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\n\tfunc z() { return nil }\n\nwill turn into\n\n\tfunc z() { return }",
+			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/noresultvars",
+			Default: true,
+		},
+		{
 			Name:    "printf",
 			Doc:     "check consistency of Printf format strings and arguments\n\nThe check applies to calls of the formatting functions such as\n[fmt.Printf] and [fmt.Sprintf], as well as any detected wrappers of\nthose functions.\n\nIn this example, the %d format operator requires an integer operand:\n\n\tfmt.Printf(\"%d\", \"hello\") // fmt.Printf format %d has arg \"hello\" of wrong type string\n\nSee the documentation of the fmt package for the complete set of\nformat operators and their operand types.\n\nTo enable printf checking on a function that is not found by this\nanalyzer's heuristics (for example, because control is obscured by\ndynamic method calls), insert a bogus call:\n\n\tfunc MyPrintf(format string, args ...any) {\n\t\tif false {\n\t\t\t_ = fmt.Sprintf(format, args...) // enable printf checker\n\t\t}\n\t\t...\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.",
 			URL:     "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/printf",
@@ -1171,6 +1192,12 @@
 			Default: true,
 		},
 		{
+			Name:    "stubmethods",
+			Doc:     "detect missing methods and fix with stub implementations\n\nThis analyzer detects type-checking errors due to missing methods\nin assignments from concrete types to interface types, and offers\na suggested fix that will create a set of stub methods so that\nthe concrete type satisfies the interface.\n\nFor example, this function will not compile because the value\nNegativeErr{} does not implement the \"error\" interface:\n\n\tfunc sqrt(x float64) (float64, error) {\n\t\tif x < 0 {\n\t\t\treturn 0, NegativeErr{} // error: missing method\n\t\t}\n\t\t...\n\t}\n\n\ttype NegativeErr struct{}\n\nThis analyzer will suggest a fix to declare this method:\n\n\t// Error implements error.Error.\n\tfunc (NegativeErr) Error() string {\n\t\tpanic(\"unimplemented\")\n\t}\n\n(At least, it appears to behave that way, but technically it\ndoesn't use the SuggestedFix mechanism and the stub is created by\nlogic in gopls's golang.stub function.)",
+			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/stubmethods",
+			Default: true,
+		},
+		{
 			Name:    "testinggoroutine",
 			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\n\tfunc TestFoo(t *testing.T) {\n\t    go func() {\n\t        t.Fatal(\"oops\") // error: (*T).Fatal called from non-test goroutine\n\t    }()\n\t}",
 			URL:     "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/testinggoroutine",
@@ -1189,6 +1216,12 @@
 			Default: true,
 		},
 		{
+			Name:    "undeclaredname",
+			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\t<> :=\n\nor a new function declaration, such as:\n\n\tfunc <>(inferred parameters) {\n\t\tpanic(\"implement me!\")\n\t}",
+			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/undeclaredname",
+			Default: true,
+		},
+		{
 			Name:    "unmarshal",
 			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.",
 			URL:     "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unmarshal",
@@ -1207,9 +1240,10 @@
 			Default: true,
 		},
 		{
-			Name: "unusedparams",
-			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 have the name '_' (the blank identifier)\n- functions in test files\n- functions with empty bodies or those with just a return stmt",
-			URL:  "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedparams",
+			Name:    "unusedparams",
+			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 ensure soundness, it ignores:\n  - \"address-taken\" functions, that is, functions that are used as\n    a value rather than being called directly; their signatures may\n    be required to conform to a func type.\n  - exported functions or methods, since they may be address-taken\n    in another package.\n  - unexported methods whose name matches an interface method\n    declared in the same package, since the method's signature\n    may be required to conform to the interface type.\n  - functions with empty bodies, or containing just a call to panic.\n  - parameters that are unnamed, or named \"_\", the blank identifier.\n\nThe analyzer suggests a fix of replacing the parameter name by \"_\",\nbut in such cases a deeper fix can be obtained by invoking the\n\"Refactor: remove unused parameter\" code action, which will\neliminate the parameter entirely, along with all corresponding\narguments at call sites, while taking care to preserve any side\neffects in the argument expressions; see\nhttps://github.com/golang/tools/releases/tag/gopls%2Fv0.14.",
+			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedparams",
+			Default: true,
 		},
 		{
 			Name:    "unusedresult",
@@ -1218,6 +1252,11 @@
 			Default: true,
 		},
 		{
+			Name: "unusedvariable",
+			Doc:  "check for unused variables and suggest fixes",
+			URL:  "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedvariable",
+		},
+		{
 			Name: "unusedwrite",
 			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\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\n\tfunc (t T) f() {  // t is a copy\n\t\tt.x = i  // unused write to field x\n\t}",
 			URL:  "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unusedwrite",
@@ -1227,53 +1266,6 @@
 			Doc:  "check for constraints that could be simplified to \"any\"",
 			URL:  "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/useany",
 		},
-		{
-			Name:    "fillreturns",
-			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\n\tfunc m() (int, string, *bool, error) {\n\t\treturn\n\t}\n\nwill turn into\n\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.",
-			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillreturns",
-			Default: true,
-		},
-		{
-			Name:    "nonewvars",
-			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\n\tz := 1\n\tz := 2\n\nwill turn into\n\n\tz := 1\n\tz = 2",
-			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/nonewvars",
-			Default: true,
-		},
-		{
-			Name:    "noresultvalues",
-			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\n\tfunc z() { return nil }\n\nwill turn into\n\n\tfunc z() { return }",
-			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/noresultvars",
-			Default: true,
-		},
-		{
-			Name:    "undeclaredname",
-			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\t<> :=\n\nor a new function declaration, such as:\n\n\tfunc <>(inferred parameters) {\n\t\tpanic(\"implement me!\")\n\t}",
-			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/undeclaredname",
-			Default: true,
-		},
-		{
-			Name: "unusedvariable",
-			Doc:  "check for unused variables and suggest fixes",
-			URL:  "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedvariable",
-		},
-		{
-			Name:    "fillstruct",
-			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",
-			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillstruct",
-			Default: true,
-		},
-		{
-			Name:    "infertypeargs",
-			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",
-			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/infertypeargs",
-			Default: true,
-		},
-		{
-			Name:    "stubmethods",
-			Doc:     "detect missing methods and fix with stub implementations\n\nThis analyzer detects type-checking errors due to missing methods\nin assignments from concrete types to interface types, and offers\na suggested fix that will create a set of stub methods so that\nthe concrete type satisfies the interface.\n\nFor example, this function will not compile because the value\nNegativeErr{} does not implement the \"error\" interface:\n\n\tfunc sqrt(x float64) (float64, error) {\n\t\tif x < 0 {\n\t\t\treturn 0, NegativeErr{} // error: missing method\n\t\t}\n\t\t...\n\t}\n\n\ttype NegativeErr struct{}\n\nThis analyzer will suggest a fix to declare this method:\n\n\t// Error implements error.Error.\n\tfunc (NegativeErr) Error() string {\n\t\tpanic(\"unimplemented\")\n\t}\n\n(At least, it appears to behave that way, but technically it\ndoesn't use the SuggestedFix mechanism and the stub is created by\nlogic in gopls's source.stub function.)",
-			URL:     "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/stubmethods",
-			Default: true,
-		},
 	},
 	Hints: []*HintJSON{
 		{
diff --git a/gopls/internal/settings/default.go b/gopls/internal/settings/default.go
index 0f8b4f3..74b98c8 100644
--- a/gopls/internal/settings/default.go
+++ b/gopls/internal/settings/default.go
@@ -9,8 +9,8 @@
 	"time"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 )
 
 var (
@@ -118,9 +118,7 @@
 			},
 			Hooks: Hooks{
 				URLRegexp:            urlRegexp(),
-				DefaultAnalyzers:     defaultAnalyzers(),
-				TypeErrorAnalyzers:   typeErrorAnalyzers(),
-				ConvenienceAnalyzers: convenienceAnalyzers(),
+				DefaultAnalyzers:     analyzers(),
 				StaticcheckAnalyzers: map[string]*Analyzer{},
 			},
 		}
diff --git a/gopls/internal/settings/settings.go b/gopls/internal/settings/settings.go
index a5afc6f..0f1f177 100644
--- a/gopls/internal/settings/settings.go
+++ b/gopls/internal/settings/settings.go
@@ -54,7 +54,6 @@
 	"golang.org/x/tools/gopls/internal/analysis/deprecated"
 	"golang.org/x/tools/gopls/internal/analysis/embeddirective"
 	"golang.org/x/tools/gopls/internal/analysis/fillreturns"
-	"golang.org/x/tools/gopls/internal/analysis/fillstruct"
 	"golang.org/x/tools/gopls/internal/analysis/infertypeargs"
 	"golang.org/x/tools/gopls/internal/analysis/nonewvars"
 	"golang.org/x/tools/gopls/internal/analysis/noresultvalues"
@@ -67,8 +66,8 @@
 	"golang.org/x/tools/gopls/internal/analysis/unusedvariable"
 	"golang.org/x/tools/gopls/internal/analysis/useany"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 )
 
 type Annotation string
@@ -103,7 +102,7 @@
 // TODO(rfindley): refactor to simplify this function. We no longer need the
 // different categories of analyzer.
 func (opts *Options) IsAnalyzerEnabled(name string) bool {
-	for _, amap := range []map[string]*Analyzer{opts.DefaultAnalyzers, opts.TypeErrorAnalyzers, opts.ConvenienceAnalyzers, opts.StaticcheckAnalyzers} {
+	for _, amap := range []map[string]*Analyzer{opts.DefaultAnalyzers, opts.StaticcheckAnalyzers} {
 		for _, analyzer := range amap {
 			if analyzer.Analyzer.Name == name && analyzer.IsEnabled(opts) {
 				return true
@@ -122,6 +121,7 @@
 	DynamicConfigurationSupported              bool
 	DynamicRegistrationSemanticTokensSupported bool
 	DynamicWatchedFilesSupported               bool
+	RelativePatternsSupported                  bool
 	PreferredContentFormat                     protocol.MarkupKind
 	LineFoldingOnly                            bool
 	HierarchicalDocumentSymbolSupport          bool
@@ -131,6 +131,7 @@
 	CompletionTags                             bool
 	CompletionDeprecated                       bool
 	SupportedResourceOperations                []protocol.ResourceOperationKind
+	CodeActionResolveOptions                   []string
 }
 
 // ServerOptions holds LSP-specific configuration that is provided by the
@@ -326,7 +327,7 @@
 	// ...
 	// "analyses": {
 	//   "unreachable": false, // Disable the unreachable analyzer.
-	//   "unusedparams": true  // Enable the unusedparams analyzer.
+	//   "unusedvariable": true  // Enable the unusedvariable analyzer.
 	// }
 	// ...
 	// ```
@@ -456,8 +457,6 @@
 	GofumptFormat func(ctx context.Context, langVersion, modulePath string, src []byte) ([]byte, error)
 
 	DefaultAnalyzers     map[string]*Analyzer
-	TypeErrorAnalyzers   map[string]*Analyzer
-	ConvenienceAnalyzers map[string]*Analyzer
 	StaticcheckAnalyzers map[string]*Analyzer
 }
 
@@ -720,6 +719,7 @@
 	o.DynamicConfigurationSupported = caps.Workspace.DidChangeConfiguration.DynamicRegistration
 	o.DynamicRegistrationSemanticTokensSupported = caps.TextDocument.SemanticTokens.DynamicRegistration
 	o.DynamicWatchedFilesSupported = caps.Workspace.DidChangeWatchedFiles.DynamicRegistration
+	o.RelativePatternsSupported = caps.Workspace.DidChangeWatchedFiles.RelativePatternSupport
 
 	// Check which types of content format are supported by this client.
 	if hover := caps.TextDocument.Hover; hover != nil && len(hover.ContentFormat) > 0 {
@@ -748,6 +748,11 @@
 	} else if caps.TextDocument.Completion.CompletionItem.DeprecatedSupport {
 		o.CompletionDeprecated = true
 	}
+
+	// Check if the client supports code actions resolving.
+	if caps.TextDocument.CodeAction.DataSupport && caps.TextDocument.CodeAction.ResolveSupport != nil {
+		o.CodeActionResolveOptions = caps.TextDocument.CodeAction.ResolveSupport.Properties
+	}
 }
 
 func (o *Options) Clone() *Options {
@@ -794,8 +799,6 @@
 		return dst
 	}
 	result.DefaultAnalyzers = copyAnalyzerMap(o.DefaultAnalyzers)
-	result.TypeErrorAnalyzers = copyAnalyzerMap(o.TypeErrorAnalyzers)
-	result.ConvenienceAnalyzers = copyAnalyzerMap(o.ConvenienceAnalyzers)
 	result.StaticcheckAnalyzers = copyAnalyzerMap(o.StaticcheckAnalyzers)
 	return result
 }
@@ -822,9 +825,6 @@
 	if _, ok := o.Codelenses[string(command.RunGovulncheck)]; !ok {
 		o.Codelenses[string(command.RunGovulncheck)] = true
 	}
-	if _, ok := o.Analyses[unusedparams.Analyzer.Name]; !ok {
-		o.Analyses[unusedparams.Analyzer.Name] = true
-	}
 	if _, ok := o.Analyses[unusedvariable.Analyzer.Name]; !ok {
 		o.Analyses[unusedvariable.Analyzer.Name] = true
 	}
@@ -1113,6 +1113,7 @@
 		result.deprecated("")
 
 	case "allowModfileModifications":
+		result.softErrorf("gopls setting \"allowModfileModifications\" is deprecated.\nPlease comment on https://go.dev/issue/65546 if this impacts your workflow.")
 		result.setBool(&o.AllowModfileModifications)
 
 	case "allowImplicitNetworkAccess":
@@ -1377,71 +1378,25 @@
 	}
 }
 
-func typeErrorAnalyzers() map[string]*Analyzer {
-	return map[string]*Analyzer{
-		fillreturns.Analyzer.Name: {
-			Analyzer: fillreturns.Analyzer,
-			// TODO(rfindley): is SourceFixAll even necessary here? Is that not implied?
-			ActionKind: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},
-			Enabled:    true,
-		},
-		nonewvars.Analyzer.Name: {
-			Analyzer: nonewvars.Analyzer,
-			Enabled:  true,
-		},
-		noresultvalues.Analyzer.Name: {
-			Analyzer: noresultvalues.Analyzer,
-			Enabled:  true,
-		},
-		undeclaredname.Analyzer.Name: {
-			Analyzer: undeclaredname.Analyzer,
-			Fix:      UndeclaredName,
-			Enabled:  true,
-		},
-		unusedvariable.Analyzer.Name: {
-			Analyzer: unusedvariable.Analyzer,
-			Enabled:  false,
-		},
-	}
-}
-
-// TODO(golang/go#61559): remove convenience analyzers now that they are not
-// used from the analysis framework.
-func convenienceAnalyzers() map[string]*Analyzer {
-	return map[string]*Analyzer{
-		fillstruct.Analyzer.Name: {
-			Analyzer:   fillstruct.Analyzer,
-			Fix:        FillStruct,
-			Enabled:    true,
-			ActionKind: []protocol.CodeActionKind{protocol.RefactorRewrite},
-		},
-		stubmethods.Analyzer.Name: {
-			Analyzer: stubmethods.Analyzer,
-			Fix:      StubMethods,
-			Enabled:  true,
-		},
-		infertypeargs.Analyzer.Name: {
-			Analyzer:   infertypeargs.Analyzer,
-			Enabled:    true,
-			ActionKind: []protocol.CodeActionKind{protocol.RefactorRewrite},
-		},
-	}
-}
-
-func defaultAnalyzers() map[string]*Analyzer {
+func analyzers() map[string]*Analyzer {
 	return map[string]*Analyzer{
 		// The traditional vet suite:
-		appends.Analyzer.Name:       {Analyzer: appends.Analyzer, Enabled: true},
-		asmdecl.Analyzer.Name:       {Analyzer: asmdecl.Analyzer, Enabled: true},
-		assign.Analyzer.Name:        {Analyzer: assign.Analyzer, Enabled: true},
-		atomic.Analyzer.Name:        {Analyzer: atomic.Analyzer, Enabled: true},
-		bools.Analyzer.Name:         {Analyzer: bools.Analyzer, Enabled: true},
-		buildtag.Analyzer.Name:      {Analyzer: buildtag.Analyzer, Enabled: true},
-		cgocall.Analyzer.Name:       {Analyzer: cgocall.Analyzer, Enabled: true},
-		composite.Analyzer.Name:     {Analyzer: composite.Analyzer, Enabled: true},
-		copylock.Analyzer.Name:      {Analyzer: copylock.Analyzer, Enabled: true},
-		defers.Analyzer.Name:        {Analyzer: defers.Analyzer, Enabled: true},
-		deprecated.Analyzer.Name:    {Analyzer: deprecated.Analyzer, Enabled: true, Severity: protocol.SeverityHint, Tag: []protocol.DiagnosticTag{protocol.Deprecated}},
+		appends.Analyzer.Name:   {Analyzer: appends.Analyzer, Enabled: true},
+		asmdecl.Analyzer.Name:   {Analyzer: asmdecl.Analyzer, Enabled: true},
+		assign.Analyzer.Name:    {Analyzer: assign.Analyzer, Enabled: true},
+		atomic.Analyzer.Name:    {Analyzer: atomic.Analyzer, Enabled: true},
+		bools.Analyzer.Name:     {Analyzer: bools.Analyzer, Enabled: true},
+		buildtag.Analyzer.Name:  {Analyzer: buildtag.Analyzer, Enabled: true},
+		cgocall.Analyzer.Name:   {Analyzer: cgocall.Analyzer, Enabled: true},
+		composite.Analyzer.Name: {Analyzer: composite.Analyzer, Enabled: true},
+		copylock.Analyzer.Name:  {Analyzer: copylock.Analyzer, Enabled: true},
+		defers.Analyzer.Name:    {Analyzer: defers.Analyzer, Enabled: true},
+		deprecated.Analyzer.Name: {
+			Analyzer: deprecated.Analyzer,
+			Enabled:  true,
+			Severity: protocol.SeverityHint,
+			Tag:      []protocol.DiagnosticTag{protocol.Deprecated},
+		},
 		directive.Analyzer.Name:     {Analyzer: directive.Analyzer, Enabled: true},
 		errorsas.Analyzer.Name:      {Analyzer: errorsas.Analyzer, Enabled: true},
 		httpresponse.Analyzer.Name:  {Analyzer: httpresponse.Analyzer, Enabled: true},
@@ -1469,32 +1424,48 @@
 		shadow.Analyzer.Name:           {Analyzer: shadow.Analyzer, Enabled: false},
 		sortslice.Analyzer.Name:        {Analyzer: sortslice.Analyzer, Enabled: true},
 		testinggoroutine.Analyzer.Name: {Analyzer: testinggoroutine.Analyzer, Enabled: true},
-		unusedparams.Analyzer.Name:     {Analyzer: unusedparams.Analyzer, Enabled: false},
+		unusedparams.Analyzer.Name:     {Analyzer: unusedparams.Analyzer, Enabled: true},
 		unusedwrite.Analyzer.Name:      {Analyzer: unusedwrite.Analyzer, Enabled: false},
 		useany.Analyzer.Name:           {Analyzer: useany.Analyzer, Enabled: false},
-		timeformat.Analyzer.Name:       {Analyzer: timeformat.Analyzer, Enabled: true},
-		embeddirective.Analyzer.Name: {
-			Analyzer: embeddirective.Analyzer,
+		infertypeargs.Analyzer.Name: {
+			Analyzer: infertypeargs.Analyzer,
 			Enabled:  true,
-			Fix:      AddEmbedImport,
+			Severity: protocol.SeverityHint,
 		},
+		timeformat.Analyzer.Name:     {Analyzer: timeformat.Analyzer, Enabled: true},
+		embeddirective.Analyzer.Name: {Analyzer: embeddirective.Analyzer, Enabled: true},
 
 		// gofmt -s suite:
 		simplifycompositelit.Analyzer.Name: {
-			Analyzer:   simplifycompositelit.Analyzer,
-			Enabled:    true,
-			ActionKind: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},
+			Analyzer:    simplifycompositelit.Analyzer,
+			Enabled:     true,
+			ActionKinds: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},
 		},
 		simplifyrange.Analyzer.Name: {
-			Analyzer:   simplifyrange.Analyzer,
-			Enabled:    true,
-			ActionKind: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},
+			Analyzer:    simplifyrange.Analyzer,
+			Enabled:     true,
+			ActionKinds: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},
 		},
 		simplifyslice.Analyzer.Name: {
-			Analyzer:   simplifyslice.Analyzer,
-			Enabled:    true,
-			ActionKind: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},
+			Analyzer:    simplifyslice.Analyzer,
+			Enabled:     true,
+			ActionKinds: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},
 		},
+
+		// Type error analyzers.
+		// These analyzers enrich go/types errors with suggested fixes.
+		fillreturns.Analyzer.Name:    {Analyzer: fillreturns.Analyzer, Enabled: true},
+		nonewvars.Analyzer.Name:      {Analyzer: nonewvars.Analyzer, Enabled: true},
+		noresultvalues.Analyzer.Name: {Analyzer: noresultvalues.Analyzer, Enabled: true},
+		stubmethods.Analyzer.Name:    {Analyzer: stubmethods.Analyzer, Enabled: true},
+		undeclaredname.Analyzer.Name: {Analyzer: undeclaredname.Analyzer, Enabled: true},
+		// TODO(rfindley): why isn't the 'unusedvariable' analyzer enabled, if it
+		// is only enhancing type errors with suggested fixes?
+		//
+		// In particular, enabling this analyzer could cause unused variables to be
+		// greyed out, (due to the 'deletions only' fix). That seems like a nice UI
+		// feature.
+		unusedvariable.Analyzer.Name: {Analyzer: unusedvariable.Analyzer, Enabled: false},
 	}
 }
 
diff --git a/gopls/internal/telemetry/cmd/stacks/stacks.go b/gopls/internal/telemetry/cmd/stacks/stacks.go
index 9234afe..7123b3d 100644
--- a/gopls/internal/telemetry/cmd/stacks/stacks.go
+++ b/gopls/internal/telemetry/cmd/stacks/stacks.go
@@ -17,6 +17,7 @@
 	"log"
 	"net/http"
 	"net/url"
+	"sort"
 	"strings"
 	"time"
 
@@ -72,15 +73,30 @@
 				if prog.Program == "golang.org/x/tools/gopls" && len(prog.Stacks) > 0 {
 					total++
 
+					// Include applicable client names (e.g. vscode, eglot).
+					var clients []string
+					var clientSuffix string
+					for key := range prog.Counters {
+						client := strings.TrimPrefix(key, "gopls/client:")
+						if client != key {
+							clients = append(clients, client)
+						}
+					}
+					sort.Strings(clients)
+					if len(clients) > 0 {
+						clientSuffix = " " + strings.Join(clients, ",")
+					}
+
 					// Ignore @devel versions as they correspond to
 					// ephemeral (and often numerous) variations of
 					// the program as we work on a fix to a bug.
 					if prog.Version == "devel" {
 						continue
 					}
-					info := fmt.Sprintf("%s@%s %s %s/%s",
+					info := fmt.Sprintf("%s@%s %s %s/%s%s",
 						prog.Program, prog.Version,
-						prog.GoVersion, prog.GOOS, prog.GOARCH)
+						prog.GoVersion, prog.GOOS, prog.GOARCH,
+						clientSuffix)
 					for stack, count := range prog.Stacks {
 						counts := stacks[stack]
 						if counts == nil {
diff --git a/gopls/internal/telemetry/telemetry.go b/gopls/internal/telemetry/telemetry.go
index 2ce284c..deab5d2 100644
--- a/gopls/internal/telemetry/telemetry.go
+++ b/gopls/internal/telemetry/telemetry.go
@@ -12,10 +12,30 @@
 
 	"golang.org/x/telemetry"
 	"golang.org/x/telemetry/counter"
+	"golang.org/x/telemetry/crashmonitor"
 	"golang.org/x/telemetry/upload"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
 )
 
+// CounterOpen calls [counter.Open].
+func CounterOpen() {
+	counter.Open()
+}
+
+// StartCrashMonitor calls [crashmonitor.Start].
+func StartCrashMonitor() {
+	crashmonitor.Start()
+}
+
+// CrashMonitorSupported calls [crashmonitor.Supported].
+func CrashMonitorSupported() bool {
+	return crashmonitor.Supported()
+}
+
+// NewStackCounter calls [counter.NewStack].
+func NewStackCounter(name string, depth int) *counter.StackCounter {
+	return counter.NewStack(name, depth)
+}
+
 // Mode calls x/telemetry.Mode.
 func Mode() string {
 	return telemetry.Mode()
@@ -32,41 +52,42 @@
 }
 
 // RecordClientInfo records gopls client info.
-func RecordClientInfo(params *protocol.ParamInitialize) {
-	client := "gopls/client:other"
-	if params != nil && params.ClientInfo != nil {
-		switch params.ClientInfo.Name {
-		case "Visual Studio Code":
-			client = "gopls/client:vscode"
-		case "Visual Studio Code - Insiders":
-			client = "gopls/client:vscode-insiders"
-		case "VSCodium":
-			client = "gopls/client:vscodium"
-		case "code-server":
-			// https://github.com/coder/code-server/blob/3cb92edc76ecc2cfa5809205897d93d4379b16a6/ci/build/build-vscode.sh#L19
-			client = "gopls/client:code-server"
-		case "Eglot":
-			// https://lists.gnu.org/archive/html/bug-gnu-emacs/2023-03/msg00954.html
-			client = "gopls/client:eglot"
-		case "govim":
-			// https://github.com/govim/govim/pull/1189
-			client = "gopls/client:govim"
-		case "Neovim":
-			// https://github.com/neovim/neovim/blob/42333ea98dfcd2994ee128a3467dfe68205154cd/runtime/lua/vim/lsp.lua#L1361
-			client = "gopls/client:neovim"
-		case "coc.nvim":
-			// https://github.com/neoclide/coc.nvim/blob/3dc6153a85ed0f185abec1deb972a66af3fbbfb4/src/language-client/client.ts#L994
-			client = "gopls/client:coc.nvim"
-		case "Sublime Text LSP":
-			// https://github.com/sublimelsp/LSP/blob/e608f878e7e9dd34aabe4ff0462540fadcd88fcc/plugin/core/sessions.py#L493
-			client = "gopls/client:sublimetext"
-		default:
-			// at least accumulate the client name locally
-			counter.New(fmt.Sprintf("gopls/client-other:%s", params.ClientInfo.Name)).Inc()
-			// but also record client:other
+func RecordClientInfo(clientName string) {
+	key := "gopls/client:other"
+	switch clientName {
+	case "Visual Studio Code":
+		key = "gopls/client:vscode"
+	case "Visual Studio Code - Insiders":
+		key = "gopls/client:vscode-insiders"
+	case "VSCodium":
+		key = "gopls/client:vscodium"
+	case "code-server":
+		// https://github.com/coder/code-server/blob/3cb92edc76ecc2cfa5809205897d93d4379b16a6/ci/build/build-vscode.sh#L19
+		key = "gopls/client:code-server"
+	case "Eglot":
+		// https://lists.gnu.org/archive/html/bug-gnu-emacs/2023-03/msg00954.html
+		key = "gopls/client:eglot"
+	case "govim":
+		// https://github.com/govim/govim/pull/1189
+		key = "gopls/client:govim"
+	case "Neovim":
+		// https://github.com/neovim/neovim/blob/42333ea98dfcd2994ee128a3467dfe68205154cd/runtime/lua/vim/lsp.lua#L1361
+		key = "gopls/client:neovim"
+	case "coc.nvim":
+		// https://github.com/neoclide/coc.nvim/blob/3dc6153a85ed0f185abec1deb972a66af3fbbfb4/src/language-client/client.ts#L994
+		key = "gopls/client:coc.nvim"
+	case "Sublime Text LSP":
+		// https://github.com/sublimelsp/LSP/blob/e608f878e7e9dd34aabe4ff0462540fadcd88fcc/plugin/core/sessions.py#L493
+		key = "gopls/client:sublimetext"
+	default:
+		// Accumulate at least a local counter for an unknown
+		// client name, but also fall through to count it as
+		// ":other" for collection.
+		if clientName != "" {
+			counter.New(fmt.Sprintf("gopls/client-other:%s", clientName)).Inc()
 		}
 	}
-	counter.Inc(client)
+	counter.Inc(key)
 }
 
 // RecordViewGoVersion records the Go minor version number (1.x) used for a view.
diff --git a/gopls/internal/telemetry/telemetry_go118.go b/gopls/internal/telemetry/telemetry_go118.go
index 7d0f11c..12b7803 100644
--- a/gopls/internal/telemetry/telemetry_go118.go
+++ b/gopls/internal/telemetry/telemetry_go118.go
@@ -7,7 +7,22 @@
 
 package telemetry
 
-import "golang.org/x/tools/gopls/internal/lsp/protocol"
+// This file defines dummy implementations of telemetry operations to
+// permit building with go1.18. Until we drop support for go1.18,
+// gopls may not refer to the telemetry module directly, but must go
+// through this file.
+
+func CounterOpen() {}
+
+func StartCrashMonitor() {}
+
+func CrashMonitorSupported() bool { return false }
+
+func NewStackCounter(string, int) dummyCounter { return dummyCounter{} }
+
+type dummyCounter struct{}
+
+func (dummyCounter) Inc() {}
 
 func Mode() string {
 	return "local"
@@ -20,8 +35,7 @@
 func Upload() {
 }
 
-func RecordClientInfo(params *protocol.ParamInitialize) {
-}
+func RecordClientInfo(string) {}
 
 func RecordViewGoVersion(x int) {
 }
diff --git a/gopls/internal/telemetry/telemetry_test.go b/gopls/internal/telemetry/telemetry_test.go
index 9cb5612..b52ac70 100644
--- a/gopls/internal/telemetry/telemetry_test.go
+++ b/gopls/internal/telemetry/telemetry_test.go
@@ -19,8 +19,8 @@
 	"golang.org/x/telemetry/counter"
 	"golang.org/x/telemetry/counter/countertest" // requires go1.21+
 	"golang.org/x/tools/gopls/internal/hooks"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/telemetry"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/util/bug"
diff --git a/gopls/internal/template/completion.go b/gopls/internal/template/completion.go
index 06ad2e5..dfacefc 100644
--- a/gopls/internal/template/completion.go
+++ b/gopls/internal/template/completion.go
@@ -12,9 +12,9 @@
 	"go/token"
 	"strings"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // information needed for completion
diff --git a/gopls/internal/template/completion_test.go b/gopls/internal/template/completion_test.go
index 0fc4788..8e1bdbf 100644
--- a/gopls/internal/template/completion_test.go
+++ b/gopls/internal/template/completion_test.go
@@ -10,7 +10,7 @@
 	"strings"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 func init() {
diff --git a/gopls/internal/template/highlight.go b/gopls/internal/template/highlight.go
index ba61f0c..39812cf 100644
--- a/gopls/internal/template/highlight.go
+++ b/gopls/internal/template/highlight.go
@@ -9,9 +9,9 @@
 	"fmt"
 	"regexp"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 func Highlight(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, loc protocol.Position) ([]protocol.DocumentHighlight, error) {
diff --git a/gopls/internal/template/implementations.go b/gopls/internal/template/implementations.go
index d82f027..430a337 100644
--- a/gopls/internal/template/implementations.go
+++ b/gopls/internal/template/implementations.go
@@ -11,9 +11,10 @@
 	"strconv"
 	"time"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/semtok"
 )
 
 // line number (1-based) and message
@@ -155,7 +156,7 @@
 	return ans, nil
 }
 
-func SemanticTokens(ctx context.Context, snapshot *cache.Snapshot, spn protocol.DocumentURI, add func(line, start, len uint32), d func() []uint32) (*protocol.SemanticTokens, error) {
+func SemanticTokens(ctx context.Context, snapshot *cache.Snapshot, spn protocol.DocumentURI) (*protocol.SemanticTokens, error) {
 	fh, err := snapshot.ReadFile(ctx, spn)
 	if err != nil {
 		return nil, err
@@ -166,6 +167,17 @@
 	}
 	p := parseBuffer(buf)
 
+	var items []semtok.Token
+	add := func(line, start, len uint32) {
+		// TODO(adonovan): don't ignore the rng restriction, if any.
+		items = append(items, semtok.Token{
+			Line:  line,
+			Start: start,
+			Len:   len,
+			Type:  semtok.TokMacro,
+		})
+	}
+
 	for _, t := range p.Tokens() {
 		if t.Multiline {
 			la, ca := p.LineCol(t.Start)
@@ -184,9 +196,15 @@
 		line, col := p.LineCol(t.Start)
 		add(line, col, uint32(sz))
 	}
-	data := d()
+	const noStrings = false
+	const noNumbers = false
 	ans := &protocol.SemanticTokens{
-		Data: data,
+		Data: semtok.Encode(
+			items,
+			noStrings,
+			noNumbers,
+			snapshot.Options().SemanticTypes,
+			snapshot.Options().SemanticMods),
 		// for small cache, some day. for now, the LSP client ignores this
 		// (that is, when the LSP client starts returning these, we can cache)
 		ResultID: fmt.Sprintf("%v", time.Now()),
diff --git a/gopls/internal/template/parse.go b/gopls/internal/template/parse.go
index f9ef18f..448a5ab 100644
--- a/gopls/internal/template/parse.go
+++ b/gopls/internal/template/parse.go
@@ -22,7 +22,7 @@
 	"unicode/utf8"
 
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 )
 
diff --git a/gopls/internal/template/symbols.go b/gopls/internal/template/symbols.go
index e0fcab8..fcbaec4 100644
--- a/gopls/internal/template/symbols.go
+++ b/gopls/internal/template/symbols.go
@@ -11,9 +11,9 @@
 	"text/template/parse"
 	"unicode/utf8"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 )
 
diff --git a/gopls/internal/test/integration/bench/bench_test.go b/gopls/internal/test/integration/bench/bench_test.go
index 67ef025..5ae46c9 100644
--- a/gopls/internal/test/integration/bench/bench_test.go
+++ b/gopls/internal/test/integration/bench/bench_test.go
@@ -22,7 +22,7 @@
 
 	"golang.org/x/tools/gopls/internal/cmd"
 	"golang.org/x/tools/gopls/internal/hooks"
-	"golang.org/x/tools/gopls/internal/lsp/command"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 	"golang.org/x/tools/gopls/internal/util/bug"
@@ -57,7 +57,7 @@
 func TestMain(m *testing.M) {
 	bug.PanicOnBugs = true
 	if os.Getenv(runAsGopls) == "true" {
-		tool.Main(context.Background(), cmd.New("gopls", "", nil, hooks.Options), os.Args[1:])
+		tool.Main(context.Background(), cmd.New(hooks.Options), os.Args[1:])
 		os.Exit(0)
 	}
 	event.SetExporter(nil) // don't log to stderr
diff --git a/gopls/internal/test/integration/bench/codeaction_test.go b/gopls/internal/test/integration/bench/codeaction_test.go
index 8f1660b..fe89500 100644
--- a/gopls/internal/test/integration/bench/codeaction_test.go
+++ b/gopls/internal/test/integration/bench/codeaction_test.go
@@ -9,7 +9,7 @@
 	"sync/atomic"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 func BenchmarkCodeAction(b *testing.B) {
diff --git a/gopls/internal/test/integration/bench/completion_test.go b/gopls/internal/test/integration/bench/completion_test.go
index 9492a9c..bbbba0e 100644
--- a/gopls/internal/test/integration/bench/completion_test.go
+++ b/gopls/internal/test/integration/bench/completion_test.go
@@ -10,12 +10,12 @@
 	"sync/atomic"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 )
 
-// TODO(rfindley): update these completion tests to run on multiple repos.
+var completionGOPATH = flag.String("completion_gopath", "", "if set, use this GOPATH for BenchmarkCompletion")
 
 type completionBenchOptions struct {
 	file, locationRegexp string
@@ -25,6 +25,7 @@
 	beforeCompletion func(*Env) // run before each completion
 }
 
+// Deprecated: new tests should be expressed in BenchmarkCompletion.
 func benchmarkCompletion(options completionBenchOptions, b *testing.B) {
 	repo := getRepo(b, "tools")
 	_ = repo.sharedEnv(b) // ensure cache is warm
@@ -146,7 +147,7 @@
 	}, b)
 }
 
-type completionFollowingEditTest struct {
+type completionTest struct {
 	repo           string
 	name           string
 	file           string // repo-relative file to create
@@ -154,7 +155,7 @@
 	locationRegexp string // regexp for completion
 }
 
-var completionFollowingEditTests = []completionFollowingEditTest{
+var completionTests = []completionTest{
 	{
 		"tools",
 		"selector",
@@ -169,6 +170,32 @@
 		`func \(c \*completer\) _\(\) {\n\tc\.inference\.kindMatches\((c)`,
 	},
 	{
+		"tools",
+		"unimportedident",
+		"internal/lsp/source/completion/completion2.go",
+		`
+package completion
+
+func (c *completer) _() {
+	lo
+}
+`,
+		`lo()`,
+	},
+	{
+		"tools",
+		"unimportedselector",
+		"internal/lsp/source/completion/completion2.go",
+		`
+package completion
+
+func (c *completer) _() {
+	log.
+}
+`,
+		`log\.()`,
+	},
+	{
 		"kubernetes",
 		"selector",
 		"pkg/kubelet/kubelet2.go",
@@ -213,14 +240,18 @@
 //
 // Edits force type-checked packages to be invalidated, so we want to measure
 // how long it takes before completion results are available.
-func BenchmarkCompletionFollowingEdit(b *testing.B) {
-	for _, test := range completionFollowingEditTests {
+func BenchmarkCompletion(b *testing.B) {
+	for _, test := range completionTests {
 		b.Run(fmt.Sprintf("%s_%s", test.repo, test.name), func(b *testing.B) {
-			for _, completeUnimported := range []bool{true, false} {
-				b.Run(fmt.Sprintf("completeUnimported=%v", completeUnimported), func(b *testing.B) {
-					for _, budget := range []string{"0s", "100ms"} {
-						b.Run(fmt.Sprintf("budget=%s", budget), func(b *testing.B) {
-							runCompletionFollowingEdit(b, test, completeUnimported, budget)
+			for _, followingEdit := range []bool{true, false} {
+				b.Run(fmt.Sprintf("edit=%v", followingEdit), func(b *testing.B) {
+					for _, completeUnimported := range []bool{true, false} {
+						b.Run(fmt.Sprintf("unimported=%v", completeUnimported), func(b *testing.B) {
+							for _, budget := range []string{"0s", "100ms"} {
+								b.Run(fmt.Sprintf("budget=%s", budget), func(b *testing.B) {
+									runCompletion(b, test, followingEdit, completeUnimported, budget)
+								})
+							}
 						})
 					}
 				})
@@ -229,13 +260,20 @@
 	}
 }
 
+// For optimizing unimported completion, it can be useful to benchmark with a
+// huge GOMODCACHE.
 var gomodcache = flag.String("gomodcache", "", "optional GOMODCACHE for unimported completion benchmarks")
 
-func runCompletionFollowingEdit(b *testing.B, test completionFollowingEditTest, completeUnimported bool, budget string) {
+func runCompletion(b *testing.B, test completionTest, followingEdit, completeUnimported bool, budget string) {
 	repo := getRepo(b, test.repo)
-	sharedEnv := repo.sharedEnv(b) // ensure cache is warm
+	gopath := *completionGOPATH
+	if gopath == "" {
+		// use a warm GOPATH
+		sharedEnv := repo.sharedEnv(b)
+		gopath = sharedEnv.Sandbox.GOPATH()
+	}
 	envvars := map[string]string{
-		"GOPATH": sharedEnv.Sandbox.GOPATH(), // use the warm cache
+		"GOPATH": gopath,
 	}
 
 	if *gomodcache != "" {
@@ -248,7 +286,7 @@
 			"completeUnimported": completeUnimported,
 			"completionBudget":   budget,
 		},
-	}, "completionFollowingEdit", false)
+	}, "completion", false)
 	defer env.Close()
 
 	env.CreateBuffer(test.file, "// __TEST_PLACEHOLDER_0__\n"+test.content)
@@ -278,12 +316,14 @@
 
 	b.ResetTimer()
 
-	if stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, "completionFollowingEdit")); stopAndRecord != nil {
+	if stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, "completion")); stopAndRecord != nil {
 		defer stopAndRecord()
 	}
 
 	for i := 0; i < b.N; i++ {
-		editPlaceholder()
+		if followingEdit {
+			editPlaceholder()
+		}
 		loc := env.RegexpSearch(test.file, test.locationRegexp)
 		env.Completion(loc)
 	}
diff --git a/gopls/internal/test/integration/bench/didchange_test.go b/gopls/internal/test/integration/bench/didchange_test.go
index f006a5a..22e7ca2 100644
--- a/gopls/internal/test/integration/bench/didchange_test.go
+++ b/gopls/internal/test/integration/bench/didchange_test.go
@@ -10,7 +10,7 @@
 	"testing"
 	"time"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 )
 
diff --git a/gopls/internal/test/integration/bench/iwl_test.go b/gopls/internal/test/integration/bench/iwl_test.go
index 2fa9724..07a5d90 100644
--- a/gopls/internal/test/integration/bench/iwl_test.go
+++ b/gopls/internal/test/integration/bench/iwl_test.go
@@ -7,8 +7,8 @@
 import (
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 )
@@ -16,24 +16,20 @@
 // BenchmarkInitialWorkspaceLoad benchmarks the initial workspace load time for
 // a new editing session.
 func BenchmarkInitialWorkspaceLoad(b *testing.B) {
-	tests := []struct {
-		repo string
-		file string
-	}{
-		{"google-cloud-go", "httpreplay/httpreplay.go"},
-		{"istio", "pkg/fuzz/util.go"},
-		{"kubernetes", "pkg/controller/lookup_cache.go"},
-		{"kuma", "api/generic/insights.go"},
-		{"oracle", "dataintegration/data_type.go"},
-		{"pkgsite", "internal/frontend/server.go"},
-		{"starlark", "starlark/eval.go"},
-		{"tools", "internal/lsp/cache/snapshot.go"},
-		{"hashiform", "internal/provider/provider.go"},
+	repoNames := []string{
+		"google-cloud-go",
+		"istio",
+		"kubernetes",
+		"kuma",
+		"oracle",
+		"pkgsite",
+		"starlark",
+		"tools",
+		"hashiform",
 	}
-
-	for _, test := range tests {
-		b.Run(test.repo, func(b *testing.B) {
-			repo := getRepo(b, test.repo)
+	for _, repoName := range repoNames {
+		b.Run(repoName, func(b *testing.B) {
+			repo := getRepo(b, repoName)
 			// get the (initialized) shared env to ensure the cache is warm.
 			// Reuse its GOPATH so that we get cache hits for things in the module
 			// cache.
@@ -41,13 +37,13 @@
 			b.ResetTimer()
 
 			for i := 0; i < b.N; i++ {
-				doIWL(b, sharedEnv.Sandbox.GOPATH(), repo, test.file)
+				doIWL(b, sharedEnv.Sandbox.GOPATH(), repo)
 			}
 		})
 	}
 }
 
-func doIWL(b *testing.B, gopath string, repo *repo, file string) {
+func doIWL(b *testing.B, gopath string, repo *repo) {
 	// Exclude the time to set up the env from the benchmark time, as this may
 	// involve installing gopls and/or checking out the repo dir.
 	b.StopTimer()
diff --git a/gopls/internal/test/integration/bench/stress_test.go b/gopls/internal/test/integration/bench/stress_test.go
index af72739..4ec272f 100644
--- a/gopls/internal/test/integration/bench/stress_test.go
+++ b/gopls/internal/test/integration/bench/stress_test.go
@@ -11,9 +11,9 @@
 	"testing"
 	"time"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/hooks"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
+	"golang.org/x/tools/gopls/internal/lsprpc"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 	"golang.org/x/tools/internal/jsonrpc2"
 	"golang.org/x/tools/internal/jsonrpc2/servertest"
diff --git a/gopls/internal/test/integration/bench/typing_test.go b/gopls/internal/test/integration/bench/typing_test.go
index 2d8aed6..78bd16c 100644
--- a/gopls/internal/test/integration/bench/typing_test.go
+++ b/gopls/internal/test/integration/bench/typing_test.go
@@ -10,7 +10,7 @@
 	"testing"
 	"time"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // BenchmarkTyping simulates typing steadily in a single file at different
diff --git a/gopls/internal/test/integration/codelens/codelens_test.go b/gopls/internal/test/integration/codelens/codelens_test.go
index d0eecdc..07ad3b9 100644
--- a/gopls/internal/test/integration/codelens/codelens_test.go
+++ b/gopls/internal/test/integration/codelens/codelens_test.go
@@ -14,8 +14,8 @@
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/util/bug"
 
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/internal/testenv"
 )
 
diff --git a/gopls/internal/test/integration/codelens/gcdetails_test.go b/gopls/internal/test/integration/codelens/gcdetails_test.go
index 486f865..4d3024d 100644
--- a/gopls/internal/test/integration/codelens/gcdetails_test.go
+++ b/gopls/internal/test/integration/codelens/gcdetails_test.go
@@ -9,8 +9,8 @@
 	"strings"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/server"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
diff --git a/gopls/internal/test/integration/completion/completion18_test.go b/gopls/internal/test/integration/completion/completion18_test.go
index 8e10707..0ca8377 100644
--- a/gopls/internal/test/integration/completion/completion18_test.go
+++ b/gopls/internal/test/integration/completion/completion18_test.go
@@ -10,7 +10,7 @@
 import (
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 )
 
diff --git a/gopls/internal/test/integration/completion/completion_test.go b/gopls/internal/test/integration/completion/completion_test.go
index 3c50a0c..b8d866b 100644
--- a/gopls/internal/test/integration/completion/completion_test.go
+++ b/gopls/internal/test/integration/completion/completion_test.go
@@ -13,7 +13,7 @@
 
 	"github.com/google/go-cmp/cmp"
 	"golang.org/x/tools/gopls/internal/hooks"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 	"golang.org/x/tools/gopls/internal/util/bug"
diff --git a/gopls/internal/test/integration/completion/postfix_snippet_test.go b/gopls/internal/test/integration/completion/postfix_snippet_test.go
index 0677280..31ea2e0 100644
--- a/gopls/internal/test/integration/completion/postfix_snippet_test.go
+++ b/gopls/internal/test/integration/completion/postfix_snippet_test.go
@@ -306,6 +306,7 @@
 	${1:}, ${2:} := foo()
 }
 `,
+			allowMultipleItem: true,
 		},
 		{
 			name: "var_single_value",
@@ -318,6 +319,7 @@
 	foo().var
 }
 `,
+			allowMultipleItem: true,
 			after: `
 package foo
 
diff --git a/gopls/internal/test/integration/debug/debug_test.go b/gopls/internal/test/integration/debug/debug_test.go
index 9aba51f..255a8e1 100644
--- a/gopls/internal/test/integration/debug/debug_test.go
+++ b/gopls/internal/test/integration/debug/debug_test.go
@@ -13,8 +13,8 @@
 	"testing"
 
 	"golang.org/x/tools/gopls/internal/hooks"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/util/bug"
 )
@@ -65,7 +65,7 @@
 		if err != nil {
 			t.Fatalf("reading HTTP response body: %v", err)
 		}
-		const want = "<title>GoPls"
+		const want = "<title>Gopls"
 		if !strings.Contains(string(data), want) {
 			t.Errorf("GET %s response does not contain %q: <<%s>>", debugURL, want, data)
 		}
diff --git a/gopls/internal/test/integration/diagnostics/analysis_test.go b/gopls/internal/test/integration/diagnostics/analysis_test.go
index 403dc16..8cb86f8 100644
--- a/gopls/internal/test/integration/diagnostics/analysis_test.go
+++ b/gopls/internal/test/integration/diagnostics/analysis_test.go
@@ -8,8 +8,8 @@
 	"fmt"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/protocol"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 )
 
diff --git a/gopls/internal/test/integration/diagnostics/diagnostics_test.go b/gopls/internal/test/integration/diagnostics/diagnostics_test.go
index 81720e7..dba9532 100644
--- a/gopls/internal/test/integration/diagnostics/diagnostics_test.go
+++ b/gopls/internal/test/integration/diagnostics/diagnostics_test.go
@@ -11,7 +11,7 @@
 	"testing"
 
 	"golang.org/x/tools/gopls/internal/hooks"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/server"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
@@ -1672,12 +1672,17 @@
 		env.OpenFile("b/b.go")
 		env.AfterChange(
 			// The Go command sometimes tells us about only one of the import cycle
-			// errors below. For robustness of this test, succeed if we get either.
+			// errors below. Also, sometimes we get an error during type checking
+			// instead of during list, due to missing metadata. This is likely due to
+			// a race.
+			// For robustness of this test, succeed if we get any reasonable error.
 			//
 			// TODO(golang/go#52904): we should get *both* of these errors.
+			// TODO(golang/go#64899): we should always get an import cycle error
+			// rather than a missing metadata error.
 			AnyOf(
-				Diagnostics(env.AtRegexp("a/a.go", `"mod.test/b"`), WithMessage("import cycle")),
-				Diagnostics(env.AtRegexp("b/b.go", `"mod.test/a"`), WithMessage("import cycle")),
+				Diagnostics(env.AtRegexp("a/a.go", `"mod.test/b"`)),
+				Diagnostics(env.AtRegexp("b/b.go", `"mod.test/a"`)),
 			),
 		)
 		env.RegexpReplace("b/b.go", `const B = a\.B`, "")
diff --git a/gopls/internal/test/integration/diagnostics/golist_test.go b/gopls/internal/test/integration/diagnostics/golist_test.go
index 91b9848..8c11246 100644
--- a/gopls/internal/test/integration/diagnostics/golist_test.go
+++ b/gopls/internal/test/integration/diagnostics/golist_test.go
@@ -7,7 +7,7 @@
 import (
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
+	"golang.org/x/tools/gopls/internal/cache"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/internal/testenv"
 )
diff --git a/gopls/internal/test/integration/diagnostics/invalidation_test.go b/gopls/internal/test/integration/diagnostics/invalidation_test.go
index 795ec80..395e761 100644
--- a/gopls/internal/test/integration/diagnostics/invalidation_test.go
+++ b/gopls/internal/test/integration/diagnostics/invalidation_test.go
@@ -8,7 +8,7 @@
 	"fmt"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 )
 
diff --git a/gopls/internal/test/integration/diagnostics/undeclared_test.go b/gopls/internal/test/integration/diagnostics/undeclared_test.go
index e6e826f..5579c07 100644
--- a/gopls/internal/test/integration/diagnostics/undeclared_test.go
+++ b/gopls/internal/test/integration/diagnostics/undeclared_test.go
@@ -7,7 +7,7 @@
 import (
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 )
 
diff --git a/gopls/internal/test/integration/env.go b/gopls/internal/test/integration/env.go
index 7c290ab..8dab7d7 100644
--- a/gopls/internal/test/integration/env.go
+++ b/gopls/internal/test/integration/env.go
@@ -11,7 +11,7 @@
 	"sync"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 	"golang.org/x/tools/internal/jsonrpc2/servertest"
 )
diff --git a/gopls/internal/test/integration/env_test.go b/gopls/internal/test/integration/env_test.go
index 31a7ebf..02bacd0 100644
--- a/gopls/internal/test/integration/env_test.go
+++ b/gopls/internal/test/integration/env_test.go
@@ -9,7 +9,7 @@
 	"encoding/json"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 func TestProgressUpdating(t *testing.T) {
diff --git a/gopls/internal/test/integration/expectation.go b/gopls/internal/test/integration/expectation.go
index eee7473..c4f91c8 100644
--- a/gopls/internal/test/integration/expectation.go
+++ b/gopls/internal/test/integration/expectation.go
@@ -11,7 +11,7 @@
 	"strings"
 
 	"github.com/google/go-cmp/cmp"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/server"
 )
 
diff --git a/gopls/internal/test/integration/fake/client.go b/gopls/internal/test/integration/fake/client.go
index 127a3fa..2859d9b 100644
--- a/gopls/internal/test/integration/fake/client.go
+++ b/gopls/internal/test/integration/fake/client.go
@@ -8,8 +8,10 @@
 	"context"
 	"encoding/json"
 	"fmt"
+	"path"
+	"path/filepath"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/test/integration/fake/glob"
 )
 
@@ -130,8 +132,15 @@
 			}
 			var globs []*glob.Glob
 			for _, watcher := range opts.Watchers {
+				var globPattern string
+				switch pattern := watcher.GlobPattern.Value.(type) {
+				case protocol.Pattern:
+					globPattern = pattern
+				case protocol.RelativePattern:
+					globPattern = path.Join(filepath.ToSlash(pattern.BaseURI.Path()), pattern.Pattern)
+				}
 				// TODO(rfindley): honor the watch kind.
-				g, err := glob.Parse(watcher.GlobPattern)
+				g, err := glob.Parse(globPattern)
 				if err != nil {
 					return fmt.Errorf("error parsing glob pattern %q: %v", watcher.GlobPattern, err)
 				}
diff --git a/gopls/internal/test/integration/fake/edit.go b/gopls/internal/test/integration/fake/edit.go
index 93fe236..b06984b 100644
--- a/gopls/internal/test/integration/fake/edit.go
+++ b/gopls/internal/test/integration/fake/edit.go
@@ -5,7 +5,7 @@
 package fake
 
 import (
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/diff"
 )
 
diff --git a/gopls/internal/test/integration/fake/edit_test.go b/gopls/internal/test/integration/fake/edit_test.go
index 97e2c73..0d7ac18 100644
--- a/gopls/internal/test/integration/fake/edit_test.go
+++ b/gopls/internal/test/integration/fake/edit_test.go
@@ -7,7 +7,7 @@
 import (
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 func TestApplyEdits(t *testing.T) {
diff --git a/gopls/internal/test/integration/fake/editor.go b/gopls/internal/test/integration/fake/editor.go
index 6958564..e2eec07 100644
--- a/gopls/internal/test/integration/fake/editor.go
+++ b/gopls/internal/test/integration/fake/editor.go
@@ -17,10 +17,11 @@
 	"strings"
 	"sync"
 
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/test/integration/fake/glob"
 	"golang.org/x/tools/gopls/internal/util/pathutil"
+	"golang.org/x/tools/gopls/internal/util/slices"
 	"golang.org/x/tools/internal/jsonrpc2"
 	"golang.org/x/tools/internal/jsonrpc2/servertest"
 	"golang.org/x/tools/internal/xcontext"
@@ -72,7 +73,7 @@
 }
 
 // EditorConfig configures the editor's LSP session. This is similar to
-// source.UserOptions, but we use a separate type here so that we expose only
+// golang.UserOptions, but we use a separate type here so that we expose only
 // that configuration which we support.
 //
 // The zero value for EditorConfig is the default configuration.
@@ -263,42 +264,11 @@
 	params.InitializationOptions = makeSettings(e.sandbox, config)
 	params.WorkspaceFolders = makeWorkspaceFolders(e.sandbox, config.WorkspaceFolders)
 
-	// Set various client capabilities that are sought by gopls.
-	params.Capabilities.Workspace.Configuration = true // support workspace/configuration
-	params.Capabilities.Window.WorkDoneProgress = true // support window/workDoneProgress
-	params.Capabilities.TextDocument.Completion.CompletionItem.TagSupport = &protocol.CompletionItemTagOptions{}
-	params.Capabilities.TextDocument.Completion.CompletionItem.TagSupport.ValueSet = []protocol.CompletionItemTag{protocol.ComplDeprecated}
-	params.Capabilities.TextDocument.Completion.CompletionItem.SnippetSupport = true
-	params.Capabilities.TextDocument.SemanticTokens.Requests.Full = &protocol.Or_ClientSemanticTokensRequestOptions_full{Value: true}
-	params.Capabilities.TextDocument.SemanticTokens.TokenTypes = []string{
-		"namespace", "type", "class", "enum", "interface",
-		"struct", "typeParameter", "parameter", "variable", "property", "enumMember",
-		"event", "function", "method", "macro", "keyword", "modifier", "comment",
-		"string", "number", "regexp", "operator",
+	capabilities, err := clientCapabilities(config)
+	if err != nil {
+		return fmt.Errorf("unmarshalling EditorConfig.CapabilitiesJSON: %v", err)
 	}
-	params.Capabilities.TextDocument.SemanticTokens.TokenModifiers = []string{
-		"declaration", "definition", "readonly", "static",
-		"deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary",
-	}
-	// The LSP tests have historically enabled this flag,
-	// but really we should test both ways for older editors.
-	params.Capabilities.TextDocument.DocumentSymbol.HierarchicalDocumentSymbolSupport = true
-	// Glob pattern watching is enabled.
-	params.Capabilities.Workspace.DidChangeWatchedFiles.DynamicRegistration = true
-	// "rename" operations are used for package renaming.
-	//
-	// TODO(rfindley): add support for other resource operations (create, delete, ...)
-	params.Capabilities.Workspace.WorkspaceEdit = &protocol.WorkspaceEditClientCapabilities{
-		ResourceOperations: []protocol.ResourceOperationKind{
-			"rename",
-		},
-	}
-	// Apply capabilities overlay.
-	if config.CapabilitiesJSON != nil {
-		if err := json.Unmarshal(config.CapabilitiesJSON, &params.Capabilities); err != nil {
-			return fmt.Errorf("unmarshalling EditorConfig.CapabilitiesJSON: %v", err)
-		}
-	}
+	params.Capabilities = capabilities
 
 	trace := protocol.TraceValues("messages")
 	params.Trace = &trace
@@ -325,6 +295,48 @@
 	return nil
 }
 
+func clientCapabilities(cfg EditorConfig) (protocol.ClientCapabilities, error) {
+	var capabilities protocol.ClientCapabilities
+	// Set various client capabilities that are sought by gopls.
+	capabilities.Workspace.Configuration = true // support workspace/configuration
+	capabilities.TextDocument.Completion.CompletionItem.TagSupport = &protocol.CompletionItemTagOptions{}
+	capabilities.TextDocument.Completion.CompletionItem.TagSupport.ValueSet = []protocol.CompletionItemTag{protocol.ComplDeprecated}
+	capabilities.TextDocument.Completion.CompletionItem.SnippetSupport = true
+	capabilities.TextDocument.SemanticTokens.Requests.Full = &protocol.Or_ClientSemanticTokensRequestOptions_full{Value: true}
+	capabilities.Window.WorkDoneProgress = true // support window/workDoneProgress
+	capabilities.TextDocument.SemanticTokens.TokenTypes = []string{
+		"namespace", "type", "class", "enum", "interface",
+		"struct", "typeParameter", "parameter", "variable", "property", "enumMember",
+		"event", "function", "method", "macro", "keyword", "modifier", "comment",
+		"string", "number", "regexp", "operator",
+	}
+	capabilities.TextDocument.SemanticTokens.TokenModifiers = []string{
+		"declaration", "definition", "readonly", "static",
+		"deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary",
+	}
+	// The LSP tests have historically enabled this flag,
+	// but really we should test both ways for older editors.
+	capabilities.TextDocument.DocumentSymbol.HierarchicalDocumentSymbolSupport = true
+	// Glob pattern watching is enabled.
+	capabilities.Workspace.DidChangeWatchedFiles.DynamicRegistration = true
+	// "rename" operations are used for package renaming.
+	//
+	// TODO(rfindley): add support for other resource operations (create, delete, ...)
+	capabilities.Workspace.WorkspaceEdit = &protocol.WorkspaceEditClientCapabilities{
+		ResourceOperations: []protocol.ResourceOperationKind{
+			"rename",
+		},
+	}
+
+	// Apply capabilities overlay.
+	if cfg.CapabilitiesJSON != nil {
+		if err := json.Unmarshal(cfg.CapabilitiesJSON, &capabilities); err != nil {
+			return protocol.ClientCapabilities{}, fmt.Errorf("unmarshalling EditorConfig.CapabilitiesJSON: %v", err)
+		}
+	}
+	return capabilities, nil
+}
+
 // marshalUnmarshal is a helper to json Marshal and then Unmarshal as a
 // different type. Used to work around cases where our protocol types are not
 // specific.
@@ -902,6 +914,21 @@
 
 // ApplyCodeAction applies the given code action.
 func (e *Editor) ApplyCodeAction(ctx context.Context, action protocol.CodeAction) error {
+	// Resolve the code actions if necessary and supported.
+	if action.Edit == nil {
+		editSupport, err := e.EditResolveSupport()
+		if err != nil {
+			return err
+		}
+		if editSupport {
+			ca, err := e.Server.ResolveCodeAction(ctx, &action)
+			if err != nil {
+				return err
+			}
+			action.Edit = ca.Edit
+		}
+	}
+
 	if action.Edit != nil {
 		for _, change := range action.Edit.DocumentChanges {
 			if change.TextDocumentEdit != nil {
@@ -932,11 +959,11 @@
 
 // GetQuickFixes returns the available quick fix code actions.
 func (e *Editor) GetQuickFixes(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic) ([]protocol.CodeAction, error) {
-	return e.getCodeActions(ctx, loc, diagnostics, protocol.QuickFix, protocol.SourceFixAll)
+	return e.CodeActions(ctx, loc, diagnostics, protocol.QuickFix, protocol.SourceFixAll)
 }
 
 func (e *Editor) applyCodeActions(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic, only ...protocol.CodeActionKind) (int, error) {
-	actions, err := e.getCodeActions(ctx, loc, diagnostics, only...)
+	actions, err := e.CodeActions(ctx, loc, diagnostics, only...)
 	if err != nil {
 		return 0, err
 	}
@@ -963,7 +990,7 @@
 	return applied, nil
 }
 
-func (e *Editor) getCodeActions(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic, only ...protocol.CodeActionKind) ([]protocol.CodeAction, error) {
+func (e *Editor) CodeActions(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic, only ...protocol.CodeActionKind) ([]protocol.CodeAction, error) {
 	if e.Server == nil {
 		return nil, nil
 	}
@@ -1264,7 +1291,7 @@
 }
 
 func (e *Editor) RenameFile(ctx context.Context, oldPath, newPath string) error {
-	closed, opened, err := e.renameBuffers(ctx, oldPath, newPath)
+	closed, opened, err := e.renameBuffers(oldPath, newPath)
 	if err != nil {
 		return err
 	}
@@ -1290,7 +1317,7 @@
 // renameBuffers renames in-memory buffers affected by the renaming of
 // oldPath->newPath, returning the resulting text documents that must be closed
 // and opened over the LSP.
-func (e *Editor) renameBuffers(ctx context.Context, oldPath, newPath string) (closed []protocol.TextDocumentIdentifier, opened []protocol.TextDocumentItem, _ error) {
+func (e *Editor) renameBuffers(oldPath, newPath string) (closed []protocol.TextDocumentIdentifier, opened []protocol.TextDocumentItem, _ error) {
 	e.mu.Lock()
 	defer e.mu.Unlock()
 
@@ -1471,6 +1498,14 @@
 	return lens, nil
 }
 
+func (e *Editor) EditResolveSupport() (bool, error) {
+	capabilities, err := clientCapabilities(e.Config())
+	if err != nil {
+		return false, err
+	}
+	return capabilities.TextDocument.CodeAction.ResolveSupport != nil && slices.Contains(capabilities.TextDocument.CodeAction.ResolveSupport.Properties, "edit"), nil
+}
+
 // Hover triggers a hover at the given position in an open buffer.
 func (e *Editor) Hover(ctx context.Context, loc protocol.Location) (*protocol.MarkupContent, protocol.Location, error) {
 	if err := e.checkBufferLocation(loc); err != nil {
diff --git a/gopls/internal/test/integration/fake/editor_test.go b/gopls/internal/test/integration/fake/editor_test.go
index cc8a147..68983bd 100644
--- a/gopls/internal/test/integration/fake/editor_test.go
+++ b/gopls/internal/test/integration/fake/editor_test.go
@@ -8,7 +8,7 @@
 	"context"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 const exampleProgram = `
diff --git a/gopls/internal/test/integration/fake/workdir.go b/gopls/internal/test/integration/fake/workdir.go
index 3e18e97..4d21554 100644
--- a/gopls/internal/test/integration/fake/workdir.go
+++ b/gopls/internal/test/integration/fake/workdir.go
@@ -18,7 +18,7 @@
 	"sync"
 	"time"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/robustio"
 )
 
diff --git a/gopls/internal/test/integration/fake/workdir_test.go b/gopls/internal/test/integration/fake/workdir_test.go
index b45b533..153a357 100644
--- a/gopls/internal/test/integration/fake/workdir_test.go
+++ b/gopls/internal/test/integration/fake/workdir_test.go
@@ -11,7 +11,7 @@
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 const sharedData = `
diff --git a/gopls/internal/test/integration/inlayhints/inlayhints_test.go b/gopls/internal/test/integration/inlayhints/inlayhints_test.go
index c56fae5..eab430f 100644
--- a/gopls/internal/test/integration/inlayhints/inlayhints_test.go
+++ b/gopls/internal/test/integration/inlayhints/inlayhints_test.go
@@ -6,9 +6,9 @@
 import (
 	"testing"
 
+	"golang.org/x/tools/gopls/internal/golang"
 	"golang.org/x/tools/gopls/internal/hooks"
 	. "golang.org/x/tools/gopls/internal/test/integration"
-	"golang.org/x/tools/gopls/internal/lsp/source"
 	"golang.org/x/tools/gopls/internal/util/bug"
 )
 
@@ -42,12 +42,12 @@
 		},
 		{
 			label:         "enable const",
-			enabled:       map[string]bool{source.ConstantValues: true},
+			enabled:       map[string]bool{golang.ConstantValues: true},
 			wantInlayHint: true,
 		},
 		{
 			label:         "enable parameter names",
-			enabled:       map[string]bool{source.ParameterNames: true},
+			enabled:       map[string]bool{golang.ParameterNames: true},
 			wantInlayHint: false,
 		},
 	}
diff --git a/gopls/internal/test/integration/misc/call_hierarchy_test.go b/gopls/internal/test/integration/misc/call_hierarchy_test.go
index 4587e41..ebe4d55 100644
--- a/gopls/internal/test/integration/misc/call_hierarchy_test.go
+++ b/gopls/internal/test/integration/misc/call_hierarchy_test.go
@@ -6,7 +6,7 @@
 import (
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 )
 
diff --git a/gopls/internal/test/integration/misc/configuration_test.go b/gopls/internal/test/integration/misc/configuration_test.go
index c8cdc53..2d39dc9 100644
--- a/gopls/internal/test/integration/misc/configuration_test.go
+++ b/gopls/internal/test/integration/misc/configuration_test.go
@@ -18,7 +18,7 @@
 	// Staticcheck only supports Go versions >= 1.19.
 	// Note: keep this in sync with TestStaticcheckWarning. Below this version we
 	// should get an error when setting staticcheck configuration.
-	testenv.NeedsGo1Point(t, 19)
+	testenv.NeedsGo1Point(t, 20)
 
 	const files = `
 -- go.mod --
@@ -55,7 +55,7 @@
 //
 // Gopls should not get confused about buffer content when recreating the view.
 func TestMajorOptionsChange(t *testing.T) {
-	testenv.NeedsGo1Point(t, 19) // needs staticcheck
+	testenv.NeedsGo1Point(t, 20) // needs staticcheck
 
 	const files = `
 -- go.mod --
@@ -96,7 +96,7 @@
 
 func TestStaticcheckWarning(t *testing.T) {
 	// Note: keep this in sync with TestChangeConfiguration.
-	testenv.SkipAfterGo1Point(t, 16)
+	testenv.SkipAfterGo1Point(t, 19)
 
 	const files = `
 -- go.mod --
@@ -142,6 +142,7 @@
 			"experimentalWatchedFileDelay":   "1s",
 			"experimentalWorkspaceModule":    true,
 			"tempModfile":                    true,
+			"allowModfileModifications":      true,
 		},
 	).Run(t, "", func(t *testing.T, env *Env) {
 		env.OnceMet(
@@ -150,6 +151,7 @@
 			ShownMessage("experimentalUseInvalidMetadata"),
 			ShownMessage("experimentalWatchedFileDelay"),
 			ShownMessage("tempModfile"),
+			ShownMessage("allowModfileModifications"),
 		)
 	})
 }
diff --git a/gopls/internal/test/integration/misc/debugserver_test.go b/gopls/internal/test/integration/misc/debugserver_test.go
index b9c684f..d1ce21b 100644
--- a/gopls/internal/test/integration/misc/debugserver_test.go
+++ b/gopls/internal/test/integration/misc/debugserver_test.go
@@ -8,8 +8,8 @@
 	"net/http"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 
 	. "golang.org/x/tools/gopls/internal/test/integration"
 )
diff --git a/gopls/internal/test/integration/misc/definition_test.go b/gopls/internal/test/integration/misc/definition_test.go
index 9a6d1af..b7394b8 100644
--- a/gopls/internal/test/integration/misc/definition_test.go
+++ b/gopls/internal/test/integration/misc/definition_test.go
@@ -11,9 +11,9 @@
 	"strings"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	. "golang.org/x/tools/gopls/internal/test/integration"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/test/compare"
+	. "golang.org/x/tools/gopls/internal/test/integration"
 )
 
 const internalDefinition = `
diff --git a/gopls/internal/test/integration/misc/extract_test.go b/gopls/internal/test/integration/misc/extract_test.go
index d2be705..5d6c2c5 100644
--- a/gopls/internal/test/integration/misc/extract_test.go
+++ b/gopls/internal/test/integration/misc/extract_test.go
@@ -6,10 +6,10 @@
 import (
 	"testing"
 
-	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/test/compare"
+	. "golang.org/x/tools/gopls/internal/test/integration"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 func TestExtractFunction(t *testing.T) {
diff --git a/gopls/internal/test/integration/misc/fix_test.go b/gopls/internal/test/integration/misc/fix_test.go
index 81b8559..9daf5ad 100644
--- a/gopls/internal/test/integration/misc/fix_test.go
+++ b/gopls/internal/test/integration/misc/fix_test.go
@@ -7,14 +7,24 @@
 import (
 	"testing"
 
-	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/test/compare"
+	. "golang.org/x/tools/gopls/internal/test/integration"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
-// A basic test for fillstruct, now that it uses a command.
+// A basic test for fillstruct, now that it uses a command and supports resolve edits.
 func TestFillStruct(t *testing.T) {
+	tc := []struct {
+		name         string
+		capabilities string
+		wantCommand  bool
+	}{
+		{"default", "{}", true},
+		{"no data", `{ "textDocument": {"codeAction": {	"resolveSupport": { "properties": ["edit"] } } } }`, true},
+		{"resolve support", `{ "textDocument": {"codeAction": {	"dataSupport": true, "resolveSupport": { "properties": ["edit"] } } } }`, false},
+	}
+
 	const basic = `
 -- go.mod --
 module mod.com
@@ -32,12 +42,35 @@
 	_ = Info{}
 }
 `
-	Run(t, basic, func(t *testing.T, env *Env) {
-		env.OpenFile("main.go")
-		if err := env.Editor.RefactorRewrite(env.Ctx, env.RegexpSearch("main.go", "Info{}")); err != nil {
-			t.Fatal(err)
-		}
-		want := `package main
+
+	for _, tt := range tc {
+		t.Run(tt.name, func(t *testing.T) {
+			runner := WithOptions(CapabilitiesJSON([]byte(tt.capabilities)))
+
+			runner.Run(t, basic, func(t *testing.T, env *Env) {
+				env.OpenFile("main.go")
+				fixes, err := env.Editor.CodeActions(env.Ctx, env.RegexpSearch("main.go", "Info{}"), nil, protocol.RefactorRewrite)
+				if err != nil {
+					t.Fatal(err)
+				}
+				if len(fixes) != 1 {
+					t.Fatalf("expected 1 code action, got %v", len(fixes))
+				}
+				if tt.wantCommand {
+					if fixes[0].Command == nil || fixes[0].Data != nil {
+						t.Errorf("expected code action to have command not data, got %v", fixes[0])
+					}
+				} else {
+					if fixes[0].Command != nil || fixes[0].Data == nil {
+						t.Errorf("expected code action to have command not data, got %v", fixes[0])
+					}
+				}
+
+				// Apply the code action (handles resolving the code action), and check that the result is correct.
+				if err := env.Editor.RefactorRewrite(env.Ctx, env.RegexpSearch("main.go", "Info{}")); err != nil {
+					t.Fatal(err)
+				}
+				want := `package main
 
 type Info struct {
 	WordCounts map[string]int
@@ -51,10 +84,12 @@
 	}
 }
 `
-		if got := env.BufferText("main.go"); got != want {
-			t.Fatalf("TestFillStruct failed:\n%s", compare.Text(want, got))
-		}
-	})
+				if got := env.BufferText("main.go"); got != want {
+					t.Fatalf("TestFillStruct failed:\n%s", compare.Text(want, got))
+				}
+			})
+		})
+	}
 }
 
 func TestFillReturns(t *testing.T) {
@@ -79,24 +114,18 @@
 			ReadDiagnostics("main.go", &d),
 		)
 		codeActions := env.CodeAction("main.go", d.Diagnostics)
-		if len(codeActions) != 2 {
-			t.Fatalf("expected 2 code actions, got %v", len(codeActions))
+		if len(codeActions) != 1 {
+			t.Fatalf("expected 1 code actions, got %v\n%v", len(codeActions), codeActions)
 		}
-		var foundQuickFix, foundFixAll bool
+		var foundQuickFix bool
 		for _, a := range codeActions {
 			if a.Kind == protocol.QuickFix {
 				foundQuickFix = true
 			}
-			if a.Kind == protocol.SourceFixAll {
-				foundFixAll = true
-			}
 		}
 		if !foundQuickFix {
 			t.Fatalf("expected quickfix code action, got none")
 		}
-		if !foundFixAll {
-			t.Fatalf("expected fixall code action, got none")
-		}
 		env.ApplyQuickFixes("main.go", d.Diagnostics)
 		env.AfterChange(NoDiagnostics(ForFile("main.go")))
 	})
diff --git a/gopls/internal/test/integration/misc/formatting_test.go b/gopls/internal/test/integration/misc/formatting_test.go
index 8fb3ac6..1808dbc 100644
--- a/gopls/internal/test/integration/misc/formatting_test.go
+++ b/gopls/internal/test/integration/misc/formatting_test.go
@@ -8,8 +8,8 @@
 	"strings"
 	"testing"
 
-	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/test/compare"
+	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/internal/testenv"
 )
 
@@ -303,6 +303,7 @@
 }
 
 func TestGofumptFormatting(t *testing.T) {
+	testenv.NeedsGo1Point(t, 20) // gofumpt requires go 1.20+
 	// Exercise some gofumpt formatting rules:
 	//  - No empty lines following an assignment operator
 	//  - Octal integer literals should use the 0o prefix on modules using Go
diff --git a/gopls/internal/test/integration/misc/highlight_test.go b/gopls/internal/test/integration/misc/highlight_test.go
index 9d992fb..9e3dd98 100644
--- a/gopls/internal/test/integration/misc/highlight_test.go
+++ b/gopls/internal/test/integration/misc/highlight_test.go
@@ -8,7 +8,7 @@
 	"sort"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 )
 
diff --git a/gopls/internal/test/integration/misc/hover_test.go b/gopls/internal/test/integration/misc/hover_test.go
index d246814..3853938 100644
--- a/gopls/internal/test/integration/misc/hover_test.go
+++ b/gopls/internal/test/integration/misc/hover_test.go
@@ -9,7 +9,7 @@
 	"strings"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 	"golang.org/x/tools/internal/testenv"
@@ -491,3 +491,26 @@
 		}
 	})
 }
+
+func TestHoverBrokenImport_Issue60592(t *testing.T) {
+	const files = `
+-- go.mod --
+module testdata
+go 1.18
+
+-- p.go --
+package main
+
+import foo "a"
+
+func _() {
+	foo.Print()
+}
+
+`
+	Run(t, files, func(t *testing.T, env *Env) {
+		env.OpenFile("p.go")
+		// This request should not crash gopls.
+		_, _, _ = env.Editor.Hover(env.Ctx, env.RegexpSearch("p.go", "foo[.]"))
+	})
+}
diff --git a/gopls/internal/test/integration/misc/import_test.go b/gopls/internal/test/integration/misc/import_test.go
index 5e46792..0df3f8d 100644
--- a/gopls/internal/test/integration/misc/import_test.go
+++ b/gopls/internal/test/integration/misc/import_test.go
@@ -8,10 +8,10 @@
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	. "golang.org/x/tools/gopls/internal/test/integration"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/test/compare"
+	. "golang.org/x/tools/gopls/internal/test/integration"
 )
 
 func TestAddImport(t *testing.T) {
diff --git a/gopls/internal/test/integration/misc/imports_test.go b/gopls/internal/test/integration/misc/imports_test.go
index 4fa7d9d..34ccaf7 100644
--- a/gopls/internal/test/integration/misc/imports_test.go
+++ b/gopls/internal/test/integration/misc/imports_test.go
@@ -10,10 +10,10 @@
 	"strings"
 	"testing"
 
-	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/test/compare"
+	. "golang.org/x/tools/gopls/internal/test/integration"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 // Tests golang/go#38815.
diff --git a/gopls/internal/test/integration/misc/misc_test.go b/gopls/internal/test/integration/misc/misc_test.go
index bca00bd..1567044 100644
--- a/gopls/internal/test/integration/misc/misc_test.go
+++ b/gopls/internal/test/integration/misc/misc_test.go
@@ -9,7 +9,7 @@
 	"testing"
 
 	"golang.org/x/tools/gopls/internal/hooks"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/test/integration"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/util/bug"
diff --git a/gopls/internal/test/integration/misc/prompt_test.go b/gopls/internal/test/integration/misc/prompt_test.go
index e2c4f1b..26c0e93 100644
--- a/gopls/internal/test/integration/misc/prompt_test.go
+++ b/gopls/internal/test/integration/misc/prompt_test.go
@@ -11,10 +11,10 @@
 	"regexp"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	. "golang.org/x/tools/gopls/internal/test/integration"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/server"
+	. "golang.org/x/tools/gopls/internal/test/integration"
 )
 
 // Test that gopls prompts for telemetry only when it is supposed to.
diff --git a/gopls/internal/test/integration/misc/references_test.go b/gopls/internal/test/integration/misc/references_test.go
index df19804..fcd72d8 100644
--- a/gopls/internal/test/integration/misc/references_test.go
+++ b/gopls/internal/test/integration/misc/references_test.go
@@ -14,7 +14,7 @@
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/test/integration"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 )
diff --git a/gopls/internal/test/integration/misc/rename_test.go b/gopls/internal/test/integration/misc/rename_test.go
index fe23448..e3116e1 100644
--- a/gopls/internal/test/integration/misc/rename_test.go
+++ b/gopls/internal/test/integration/misc/rename_test.go
@@ -9,9 +9,9 @@
 	"strings"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	. "golang.org/x/tools/gopls/internal/test/integration"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/test/compare"
+	. "golang.org/x/tools/gopls/internal/test/integration"
 )
 
 func TestPrepareRenameMainPackage(t *testing.T) {
diff --git a/gopls/internal/test/integration/misc/semantictokens_test.go b/gopls/internal/test/integration/misc/semantictokens_test.go
index b0b49ec..34a8200 100644
--- a/gopls/internal/test/integration/misc/semantictokens_test.go
+++ b/gopls/internal/test/integration/misc/semantictokens_test.go
@@ -10,7 +10,7 @@
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 )
diff --git a/gopls/internal/test/integration/misc/signature_help_test.go b/gopls/internal/test/integration/misc/signature_help_test.go
index dcfb416..8dffedf 100644
--- a/gopls/internal/test/integration/misc/signature_help_test.go
+++ b/gopls/internal/test/integration/misc/signature_help_test.go
@@ -8,7 +8,7 @@
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 )
 
diff --git a/gopls/internal/test/integration/misc/staticcheck_test.go b/gopls/internal/test/integration/misc/staticcheck_test.go
index 535458e..6c7a156 100644
--- a/gopls/internal/test/integration/misc/staticcheck_test.go
+++ b/gopls/internal/test/integration/misc/staticcheck_test.go
@@ -13,7 +13,7 @@
 )
 
 func TestStaticcheckGenerics(t *testing.T) {
-	testenv.NeedsGo1Point(t, 19) // generics were introduced in Go 1.18, staticcheck requires go1.19+
+	testenv.NeedsGo1Point(t, 20) // staticcheck requires go1.20+
 
 	const files = `
 -- go.mod --
@@ -78,7 +78,7 @@
 // Test for golang/go#56270: an analysis with related info should not panic if
 // analysis.RelatedInformation.End is not set.
 func TestStaticcheckRelatedInfo(t *testing.T) {
-	testenv.NeedsGo1Point(t, 19) // staticcheck is only supported at Go 1.19+
+	testenv.NeedsGo1Point(t, 20) // staticcheck is only supported at Go 1.20+
 	const files = `
 -- go.mod --
 module mod.test
diff --git a/gopls/internal/test/integration/misc/vendor_test.go b/gopls/internal/test/integration/misc/vendor_test.go
index 18b08f6..f3bed90 100644
--- a/gopls/internal/test/integration/misc/vendor_test.go
+++ b/gopls/internal/test/integration/misc/vendor_test.go
@@ -9,7 +9,7 @@
 
 	. "golang.org/x/tools/gopls/internal/test/integration"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 const basicProxy = `
@@ -51,8 +51,7 @@
 	).Run(t, pkgThatUsesVendoring, func(t *testing.T, env *Env) {
 		env.OpenFile("a/a1.go")
 		d := &protocol.PublishDiagnosticsParams{}
-		env.OnceMet(
-			InitialWorkspaceLoad,
+		env.AfterChange(
 			Diagnostics(env.AtRegexp("go.mod", "module mod.com"), WithMessage("Inconsistent vendoring")),
 			ReadDiagnostics("go.mod", d),
 		)
diff --git a/gopls/internal/test/integration/misc/vuln_test.go b/gopls/internal/test/integration/misc/vuln_test.go
index a0d260c..f74c1c3 100644
--- a/gopls/internal/test/integration/misc/vuln_test.go
+++ b/gopls/internal/test/integration/misc/vuln_test.go
@@ -17,9 +17,9 @@
 
 	"github.com/google/go-cmp/cmp"
 
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/test/compare"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/vulncheck"
@@ -434,7 +434,7 @@
 func (v VulnData) Vuln2() {}
 `
 
-func vulnTestEnv(vulnsDB, proxyData string) (*vulntest.DB, []RunOption, error) {
+func vulnTestEnv(proxyData string) (*vulntest.DB, []RunOption, error) {
 	db, err := vulntest.NewDatabase(context.Background(), []byte(vulnsData))
 	if err != nil {
 		return nil, nil, nil
@@ -458,7 +458,7 @@
 }
 
 func TestRunVulncheckPackageDiagnostics(t *testing.T) {
-	db, opts0, err := vulnTestEnv(vulnsData, proxy1)
+	db, opts0, err := vulnTestEnv(proxy1)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -606,7 +606,7 @@
 	}(cache.MaxGovulncheckResultAge)
 	cache.MaxGovulncheckResultAge = 99 * time.Millisecond
 
-	db, opts0, err := vulnTestEnv(vulnsData, proxy1)
+	db, opts0, err := vulnTestEnv(proxy1)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -638,7 +638,7 @@
 }
 
 func TestRunVulncheckWarning(t *testing.T) {
-	db, opts, err := vulnTestEnv(vulnsData, proxy1)
+	db, opts, err := vulnTestEnv(proxy1)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -793,7 +793,7 @@
 `
 
 func TestGovulncheckInfo(t *testing.T) {
-	db, opts, err := vulnTestEnv(vulnsData, proxy2)
+	db, opts, err := vulnTestEnv(proxy2)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/gopls/internal/test/integration/modfile/modfile_test.go b/gopls/internal/test/integration/modfile/modfile_test.go
index 92d91b1..a71caae 100644
--- a/gopls/internal/test/integration/modfile/modfile_test.go
+++ b/gopls/internal/test/integration/modfile/modfile_test.go
@@ -15,7 +15,7 @@
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/util/bug"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 )
 
 func TestMain(m *testing.M) {
@@ -492,8 +492,8 @@
 		env.AfterChange(
 			// We would like for the error to appear in the v2 module, but
 			// as of writing non-workspace packages are not diagnosed.
-			Diagnostics(env.AtRegexp("a/main.go", `"example.com/blah/v2"`), WithMessage("cannot find module providing")),
-			Diagnostics(env.AtRegexp("a/go.mod", `require example.com/blah/v2`), WithMessage("cannot find module providing")),
+			Diagnostics(env.AtRegexp("a/main.go", `"example.com/blah/v2"`), WithMessage("no required module provides")),
+			Diagnostics(env.AtRegexp("a/go.mod", `require example.com/blah/v2`), WithMessage("no required module provides")),
 			ReadDiagnostics("a/go.mod", &modDiags),
 		)
 
diff --git a/gopls/internal/test/integration/options.go b/gopls/internal/test/integration/options.go
index ded09b4..274b9e4 100644
--- a/gopls/internal/test/integration/options.go
+++ b/gopls/internal/test/integration/options.go
@@ -5,7 +5,7 @@
 package integration
 
 import (
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 )
 
@@ -73,6 +73,13 @@
 	})
 }
 
+// CapabilitiesJSON sets the capabalities json.
+func CapabilitiesJSON(capabilities []byte) RunOption {
+	return optionSetter(func(opts *runConfig) {
+		opts.editor.CapabilitiesJSON = capabilities
+	})
+}
+
 // Settings sets user-provided configuration for the LSP server.
 //
 // As a special case, the env setting must not be provided via Settings: use
diff --git a/gopls/internal/test/integration/regtest.go b/gopls/internal/test/integration/regtest.go
index 560f520..4e26fd7 100644
--- a/gopls/internal/test/integration/regtest.go
+++ b/gopls/internal/test/integration/regtest.go
@@ -13,8 +13,8 @@
 	"testing"
 	"time"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/cmd"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/internal/gocommand"
 	"golang.org/x/tools/internal/memoize"
@@ -114,7 +114,7 @@
 	// If this magic environment variable is set, run gopls instead of the test
 	// suite. See the documentation for runTestAsGoplsEnvvar for more details.
 	if os.Getenv(runTestAsGoplsEnvvar) == "true" {
-		tool.Main(context.Background(), cmd.New("gopls", "", nil, hook), os.Args[1:])
+		tool.Main(context.Background(), cmd.New(hook), os.Args[1:])
 		os.Exit(0)
 	}
 
diff --git a/gopls/internal/test/integration/runner.go b/gopls/internal/test/integration/runner.go
index 39ca479..7696b34 100644
--- a/gopls/internal/test/integration/runner.go
+++ b/gopls/internal/test/integration/runner.go
@@ -20,10 +20,10 @@
 	"testing"
 	"time"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/debug"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/lsprpc"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 	"golang.org/x/tools/internal/jsonrpc2"
@@ -182,7 +182,7 @@
 			}
 
 			// TODO(rfindley): do we need an instance at all? Can it be removed?
-			ctx = debug.WithInstance(ctx, "", "off")
+			ctx = debug.WithInstance(ctx, "off")
 
 			rootDir := filepath.Join(r.tempDir, filepath.FromSlash(t.Name()))
 			if err := os.MkdirAll(rootDir, 0755); err != nil {
@@ -349,7 +349,7 @@
 func (r *Runner) forwardedServer(optsHook func(*settings.Options)) jsonrpc2.StreamServer {
 	r.tsOnce.Do(func() {
 		ctx := context.Background()
-		ctx = debug.WithInstance(ctx, "", "off")
+		ctx = debug.WithInstance(ctx, "off")
 		ss := lsprpc.NewStreamServer(cache.New(nil), false, optsHook)
 		r.ts = servertest.NewTCPServer(ctx, ss, nil)
 	})
@@ -403,7 +403,7 @@
 	return newForwarder("unix", r.remoteSocket)
 }
 
-func newForwarder(network, address string) *lsprpc.Forwarder {
+func newForwarder(network, address string) jsonrpc2.StreamServer {
 	server, err := lsprpc.NewForwarder(network+";"+address, nil)
 	if err != nil {
 		// This should never happen, as we are passing an explicit address.
diff --git a/gopls/internal/test/integration/template/template_test.go b/gopls/internal/test/integration/template/template_test.go
index ae6a3a6..28ea918 100644
--- a/gopls/internal/test/integration/template/template_test.go
+++ b/gopls/internal/test/integration/template/template_test.go
@@ -9,7 +9,7 @@
 	"testing"
 
 	"golang.org/x/tools/gopls/internal/hooks"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/util/bug"
 )
diff --git a/gopls/internal/test/integration/watch/watch_test.go b/gopls/internal/test/integration/watch/watch_test.go
index c401d96..fab302f 100644
--- a/gopls/internal/test/integration/watch/watch_test.go
+++ b/gopls/internal/test/integration/watch/watch_test.go
@@ -11,7 +11,7 @@
 	. "golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/util/bug"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 )
 
@@ -258,7 +258,7 @@
 }
 
 // Add a new method to an interface and implement it.
-// Inspired by the structure of internal/lsp/source and internal/lsp/cache.
+// Inspired by the structure of internal/golang and internal/cache.
 func TestCreateImplementation(t *testing.T) {
 	const pkg = `
 -- go.mod --
diff --git a/gopls/internal/test/integration/workspace/quickfix_test.go b/gopls/internal/test/integration/workspace/quickfix_test.go
index 0304233..6f7c8e8 100644
--- a/gopls/internal/test/integration/workspace/quickfix_test.go
+++ b/gopls/internal/test/integration/workspace/quickfix_test.go
@@ -8,7 +8,7 @@
 	"strings"
 	"testing"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/test/compare"
 
 	. "golang.org/x/tools/gopls/internal/test/integration"
diff --git a/gopls/internal/test/integration/workspace/standalone_test.go b/gopls/internal/test/integration/workspace/standalone_test.go
index e50ead3..d837899 100644
--- a/gopls/internal/test/integration/workspace/standalone_test.go
+++ b/gopls/internal/test/integration/workspace/standalone_test.go
@@ -9,7 +9,7 @@
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	. "golang.org/x/tools/gopls/internal/test/integration"
 )
 
diff --git a/gopls/internal/test/integration/workspace/workspace_test.go b/gopls/internal/test/integration/workspace/workspace_test.go
index baad7bd..28b3978 100644
--- a/gopls/internal/test/integration/workspace/workspace_test.go
+++ b/gopls/internal/test/integration/workspace/workspace_test.go
@@ -11,11 +11,12 @@
 	"testing"
 
 	"golang.org/x/tools/gopls/internal/hooks"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 	"golang.org/x/tools/gopls/internal/util/bug"
 	"golang.org/x/tools/gopls/internal/util/goversion"
 	"golang.org/x/tools/internal/gocommand"
+	"golang.org/x/tools/internal/testenv"
 
 	. "golang.org/x/tools/gopls/internal/test/integration"
 )
@@ -248,6 +249,25 @@
 	})
 }
 
+func TestWorkspaceVendoring(t *testing.T) {
+	testenv.NeedsGo1Point(t, 22)
+	WithOptions(
+		ProxyFiles(workspaceModuleProxy),
+	).Run(t, multiModule, func(t *testing.T, env *Env) {
+		env.RunGoCommand("work", "init")
+		env.RunGoCommand("work", "use", "moda/a")
+		env.AfterChange()
+		env.OpenFile("moda/a/a.go")
+		env.RunGoCommand("work", "vendor")
+		env.AfterChange()
+		loc := env.GoToDefinition(env.RegexpSearch("moda/a/a.go", "b.(Hello)"))
+		const want = "vendor/b.com/b/b.go"
+		if got := env.Sandbox.Workdir.URIToPath(loc.URI); got != want {
+			t.Errorf("Definition: got location %q, want %q", got, want)
+		}
+	})
+}
+
 func TestModuleWithExclude(t *testing.T) {
 	const proxy = `
 -- c.com@v1.2.3/go.mod --
@@ -798,6 +818,51 @@
 	})
 }
 
+func TestInnerGoWork(t *testing.T) {
+	// This test checks that gopls honors a go.work file defined
+	// inside a go module (golang/go#63917).
+	const workspace = `
+-- go.mod --
+module a.com
+
+require b.com v1.2.3
+-- a/go.work --
+go 1.18
+
+use (
+	..
+	../b
+)
+-- a/a.go --
+package a
+
+import "b.com/b"
+
+var _ = b.B
+-- b/go.mod --
+module b.com/b
+
+-- b/b.go --
+package b
+
+const B = 0
+`
+	WithOptions(
+		// This doesn't work if we open the outer module. I'm not sure it should,
+		// since the go.work file does not apply to the entire module, just a
+		// subdirectory.
+		WorkspaceFolders("a"),
+	).Run(t, workspace, func(t *testing.T, env *Env) {
+		env.OpenFile("a/a.go")
+		loc := env.GoToDefinition(env.RegexpSearch("a/a.go", "b.(B)"))
+		got := env.Sandbox.Workdir.URIToPath(loc.URI)
+		want := "b/b.go"
+		if got != want {
+			t.Errorf("Definition(b.B): got %q, want %q", got, want)
+		}
+	})
+}
+
 func TestNonWorkspaceFileCreation(t *testing.T) {
 	const files = `
 -- work/go.mod --
diff --git a/gopls/internal/test/integration/workspace/zero_config_test.go b/gopls/internal/test/integration/workspace/zero_config_test.go
index dd75c59..51fd9a7 100644
--- a/gopls/internal/test/integration/workspace/zero_config_test.go
+++ b/gopls/internal/test/integration/workspace/zero_config_test.go
@@ -8,8 +8,8 @@
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/command"
+	"golang.org/x/tools/gopls/internal/cache"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 
 	. "golang.org/x/tools/gopls/internal/test/integration"
 )
diff --git a/gopls/internal/test/integration/wrappers.go b/gopls/internal/test/integration/wrappers.go
index ebe25b6..cc4a66d 100644
--- a/gopls/internal/test/integration/wrappers.go
+++ b/gopls/internal/test/integration/wrappers.go
@@ -8,8 +8,8 @@
 	"encoding/json"
 	"path"
 
-	"golang.org/x/tools/gopls/internal/lsp/command"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
+	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
 	"golang.org/x/tools/internal/xcontext"
 )
diff --git a/gopls/internal/test/marker/doc.go b/gopls/internal/test/marker/doc.go
index bf8b363..212f09c 100644
--- a/gopls/internal/test/marker/doc.go
+++ b/gopls/internal/test/marker/doc.go
@@ -204,7 +204,7 @@
     signatureHelp at the given location should match the provided string, with
     the active parameter (an index) highlighted.
 
-  - suggestedfix(location, regexp, kind, golden): like diag, the location and
+  - suggestedfix(location, regexp, golden): like diag, the location and
     regexp identify an expected diagnostic. This diagnostic must
     to have exactly one associated code action of the specified kind.
     This action is executed for its editing effects on the source files.
diff --git a/gopls/internal/test/marker/marker_test.go b/gopls/internal/test/marker/marker_test.go
index ecdabd4..1652eec 100644
--- a/gopls/internal/test/marker/marker_test.go
+++ b/gopls/internal/test/marker/marker_test.go
@@ -30,11 +30,11 @@
 	"github.com/google/go-cmp/cmp"
 
 	"golang.org/x/tools/go/expect"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/debug"
 	"golang.org/x/tools/gopls/internal/hooks"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/lsprpc"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/test/compare"
 	"golang.org/x/tools/gopls/internal/test/integration"
 	"golang.org/x/tools/gopls/internal/test/integration/fake"
@@ -85,6 +85,16 @@
 //   - The old tests lacked documentation, and often had failures that were hard
 //     to understand. By starting from scratch, we can revisit these aspects.
 func Test(t *testing.T) {
+	if testing.Short() {
+		builder := os.Getenv("GO_BUILDER_NAME")
+		// Note that HasPrefix(builder, "darwin-" only matches legacy builders.
+		// LUCI builder names start with x_tools-goN.NN.
+		// We want to exclude solaris on both legacy and LUCI builders, as
+		// it is timing out.
+		if strings.HasPrefix(builder, "darwin-") || strings.Contains(builder, "solaris") {
+			t.Skip("golang/go#64473: skipping with -short: this test is too slow on darwin and solaris builders")
+		}
+	}
 	// The marker tests must be able to run go/packages.Load.
 	testenv.NeedsGoPackages(t)
 
@@ -692,6 +702,15 @@
 				return nil, fmt.Errorf("%s:%d: unwanted space before marker (// @)", file.Name, line)
 			}
 
+			// The 'go list' command doesn't work correct with modules named
+			// testdata", so don't allow it as a module name (golang/go#65406).
+			// (Otherwise files within it will end up in an ad hoc
+			// package, "command-line-arguments/$TMPDIR/...".)
+			if filepath.Base(file.Name) == "go.mod" &&
+				bytes.Contains(file.Data, []byte("module testdata")) {
+				return nil, fmt.Errorf("'testdata' is not a valid module name")
+			}
+
 			test.notes = append(test.notes, notes...)
 			test.files[file.Name] = file.Data
 		}
@@ -786,7 +805,7 @@
 	// Put a debug instance in the context to prevent logging to stderr.
 	// See associated TODO in runner.go: we should revisit this pattern.
 	ctx := context.Background()
-	ctx = debug.WithInstance(ctx, "", "off")
+	ctx = debug.WithInstance(ctx, "off")
 
 	awaiter := integration.NewAwaiter(sandbox.Workdir)
 	ss := lsprpc.NewStreamServer(cache, false, hooks.Options)
@@ -1913,6 +1932,23 @@
 	// applied in that order. But since applyDocumentChanges(env,
 	// action.Edit.DocumentChanges) doesn't compose, for now we
 	// assert that actions return one or the other.
+
+	// Resolve code action edits first if the client has resolve support
+	// and the code action has no edits.
+	if action.Edit == nil {
+		editSupport, err := env.Editor.EditResolveSupport()
+		if err != nil {
+			return nil, err
+		}
+		if editSupport {
+			resolved, err := env.Editor.Server.ResolveCodeAction(env.Ctx, &action)
+			if err != nil {
+				return nil, err
+			}
+			action.Edit = resolved.Edit
+		}
+	}
+
 	if action.Edit != nil {
 		if action.Edit.Changes != nil {
 			env.T.Errorf("internal error: discarding unexpected CodeAction{Kind=%s, Title=%q}.Edit.Changes", action.Kind, action.Title)
diff --git a/gopls/internal/test/marker/testdata/codeaction/extract-variadic-63287.txt b/gopls/internal/test/marker/testdata/codeaction/extract-variadic-63287.txt
new file mode 100644
index 0000000..d5dbe93
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/codeaction/extract-variadic-63287.txt
@@ -0,0 +1,28 @@
+This test exercises extract on a variadic function.
+It is a regression test for bug #63287 in which
+the final paramater's "..." would go missing.
+
+-- go.mod --
+module example.com
+go 1.18
+
+-- a/a.go --
+package a
+
+//@codeactionedit(block, "refactor.extract", out, "Extract function")
+
+func _() {
+	var logf func(string, ...any)
+	{ println(logf) } //@loc(block, re`{.*}`)
+}
+
+-- @out/a/a.go --
+@@ -7 +7 @@
+-	{ println(logf) } //@loc(block, re`{.*}`)
++	{ newFunction(logf) } //@loc(block, re`{.*}`)
+@@ -10 +10,4 @@
++func newFunction(logf func( string,  ...any)) {
++	println(logf)
++}
++
+-- end --
diff --git a/gopls/internal/test/marker/testdata/codeaction/extract_variable.txt b/gopls/internal/test/marker/testdata/codeaction/extract_variable.txt
index c10b818..685b4ff 100644
--- a/gopls/internal/test/marker/testdata/codeaction/extract_variable.txt
+++ b/gopls/internal/test/marker/testdata/codeaction/extract_variable.txt
@@ -1,4 +1,5 @@
 This test checks the behavior of the 'extract variable' code action.
+See extract_variable_resolve.txt for the same test with resolve support.
 
 -- flags --
 -ignore_extra_diags
diff --git a/gopls/internal/test/marker/testdata/codeaction/extract_variable_resolve.txt b/gopls/internal/test/marker/testdata/codeaction/extract_variable_resolve.txt
new file mode 100644
index 0000000..dc6ad78
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/codeaction/extract_variable_resolve.txt
@@ -0,0 +1,81 @@
+This test checks the behavior of the 'extract variable' code action, with resolve support.
+See extract_variable.txt for the same test without resolve support.
+
+-- capabilities.json --
+{
+	"textDocument": {
+		"codeAction": {
+			"dataSupport": true,
+			"resolveSupport": {
+				"properties": ["edit"]
+			}
+		}
+	}
+}
+-- flags --
+-ignore_extra_diags
+
+-- basic_lit.go --
+package extract
+
+func _() {
+	var _ = 1 + 2 //@codeactionedit("1", "refactor.extract", basic_lit1)
+	var _ = 3 + 4 //@codeactionedit("3 + 4", "refactor.extract", basic_lit2)
+}
+
+-- @basic_lit1/basic_lit.go --
+@@ -4 +4,2 @@
+-	var _ = 1 + 2 //@codeactionedit("1", "refactor.extract", basic_lit1)
++	x := 1
++	var _ = x + 2 //@codeactionedit("1", "refactor.extract", basic_lit1)
+-- @basic_lit2/basic_lit.go --
+@@ -5 +5,2 @@
+-	var _ = 3 + 4 //@codeactionedit("3 + 4", "refactor.extract", basic_lit2)
++	x := 3 + 4
++	var _ = x //@codeactionedit("3 + 4", "refactor.extract", basic_lit2)
+-- func_call.go --
+package extract
+
+import "strconv"
+
+func _() {
+	x0 := append([]int{}, 1) //@codeactionedit("append([]int{}, 1)", "refactor.extract", func_call1)
+	str := "1"
+	b, err := strconv.Atoi(str) //@codeactionedit("strconv.Atoi(str)", "refactor.extract", func_call2)
+}
+
+-- @func_call1/func_call.go --
+@@ -6 +6,2 @@
+-	x0 := append([]int{}, 1) //@codeactionedit("append([]int{}, 1)", "refactor.extract", func_call1)
++	x := append([]int{}, 1)
++	x0 := x //@codeactionedit("append([]int{}, 1)", "refactor.extract", func_call1)
+-- @func_call2/func_call.go --
+@@ -8 +8,2 @@
+-	b, err := strconv.Atoi(str) //@codeactionedit("strconv.Atoi(str)", "refactor.extract", func_call2)
++	x, x1 := strconv.Atoi(str)
++	b, err := x, x1 //@codeactionedit("strconv.Atoi(str)", "refactor.extract", func_call2)
+-- scope.go --
+package extract
+
+import "go/ast"
+
+func _() {
+	x0 := 0
+	if true {
+		y := ast.CompositeLit{} //@codeactionedit("ast.CompositeLit{}", "refactor.extract", scope1)
+	}
+	if true {
+		x1 := !false //@codeactionedit("!false", "refactor.extract", scope2)
+	}
+}
+
+-- @scope1/scope.go --
+@@ -8 +8,2 @@
+-		y := ast.CompositeLit{} //@codeactionedit("ast.CompositeLit{}", "refactor.extract", scope1)
++		x := ast.CompositeLit{}
++		y := x //@codeactionedit("ast.CompositeLit{}", "refactor.extract", scope1)
+-- @scope2/scope.go --
+@@ -11 +11,2 @@
+-		x1 := !false //@codeactionedit("!false", "refactor.extract", scope2)
++		x := !false
++		x1 := x //@codeactionedit("!false", "refactor.extract", scope2)
diff --git a/gopls/internal/test/marker/testdata/codeaction/fill_struct.txt b/gopls/internal/test/marker/testdata/codeaction/fill_struct.txt
index 092a427..deac1d7 100644
--- a/gopls/internal/test/marker/testdata/codeaction/fill_struct.txt
+++ b/gopls/internal/test/marker/testdata/codeaction/fill_struct.txt
@@ -1,4 +1,5 @@
 This test checks the behavior of the 'fill struct' code action.
+See fill_struct_resolve.txt for same test with resolve support.
 
 -- flags --
 -ignore_extra_diags
@@ -89,11 +90,11 @@
 
 var _ = funStruct{} //@codeactionedit("}", "refactor.rewrite", a22)
 
-type funStructCompex struct {
+type funStructComplex struct {
 	fn func(i int, s string) (string, int)
 }
 
-var _ = funStructCompex{} //@codeactionedit("}", "refactor.rewrite", a23)
+var _ = funStructComplex{} //@codeactionedit("}", "refactor.rewrite", a23)
 
 type funStructEmpty struct {
 	fn func()
@@ -120,8 +121,8 @@
 +} //@codeactionedit("}", "refactor.rewrite", a22)
 -- @a23/a2.go --
 @@ -23 +23,4 @@
--var _ = funStructCompex{} //@codeactionedit("}", "refactor.rewrite", a23)
-+var _ = funStructCompex{
+-var _ = funStructComplex{} //@codeactionedit("}", "refactor.rewrite", a23)
++var _ = funStructComplex{
 +	fn: func(i int, s string) (string, int) {
 +	},
 +} //@codeactionedit("}", "refactor.rewrite", a23)
diff --git a/gopls/internal/test/marker/testdata/codeaction/fill_struct_resolve.txt b/gopls/internal/test/marker/testdata/codeaction/fill_struct_resolve.txt
new file mode 100644
index 0000000..e553d1c
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/codeaction/fill_struct_resolve.txt
@@ -0,0 +1,586 @@
+This test checks the behavior of the 'fill struct' code action, with resolve support.
+See fill_struct.txt for same test without resolve support.
+
+-- capabilities.json --
+{
+	"textDocument": {
+		"codeAction": {
+			"dataSupport": true,
+			"resolveSupport": {
+				"properties": ["edit"]
+			}
+		}
+	}
+}
+-- flags --
+-ignore_extra_diags
+
+-- go.mod --
+module golang.org/lsptests/fillstruct
+
+go 1.18
+
+-- data/data.go --
+package data
+
+type B struct {
+	ExportedInt   int
+	unexportedInt int
+}
+
+-- a.go --
+package fillstruct
+
+import (
+	"golang.org/lsptests/fillstruct/data"
+)
+
+type basicStruct struct {
+	foo int
+}
+
+var _ = basicStruct{} //@codeactionedit("}", "refactor.rewrite", a1)
+
+type twoArgStruct struct {
+	foo int
+	bar string
+}
+
+var _ = twoArgStruct{} //@codeactionedit("}", "refactor.rewrite", a2)
+
+type nestedStruct struct {
+	bar   string
+	basic basicStruct
+}
+
+var _ = nestedStruct{} //@codeactionedit("}", "refactor.rewrite", a3)
+
+var _ = data.B{} //@codeactionedit("}", "refactor.rewrite", a4)
+-- @a1/a.go --
+@@ -11 +11,3 @@
+-var _ = basicStruct{} //@codeactionedit("}", "refactor.rewrite", a1)
++var _ = basicStruct{
++	foo: 0,
++} //@codeactionedit("}", "refactor.rewrite", a1)
+-- @a2/a.go --
+@@ -18 +18,4 @@
+-var _ = twoArgStruct{} //@codeactionedit("}", "refactor.rewrite", a2)
++var _ = twoArgStruct{
++	foo: 0,
++	bar: "",
++} //@codeactionedit("}", "refactor.rewrite", a2)
+-- @a3/a.go --
+@@ -25 +25,4 @@
+-var _ = nestedStruct{} //@codeactionedit("}", "refactor.rewrite", a3)
++var _ = nestedStruct{
++	bar:   "",
++	basic: basicStruct{},
++} //@codeactionedit("}", "refactor.rewrite", a3)
+-- @a4/a.go --
+@@ -27 +27,3 @@
+-var _ = data.B{} //@codeactionedit("}", "refactor.rewrite", a4)
++var _ = data.B{
++	ExportedInt: 0,
++} //@codeactionedit("}", "refactor.rewrite", a4)
+-- a2.go --
+package fillstruct
+
+type typedStruct struct {
+	m  map[string]int
+	s  []int
+	c  chan int
+	c1 <-chan int
+	a  [2]string
+}
+
+var _ = typedStruct{} //@codeactionedit("}", "refactor.rewrite", a21)
+
+type funStruct struct {
+	fn func(i int) int
+}
+
+var _ = funStruct{} //@codeactionedit("}", "refactor.rewrite", a22)
+
+type funStructComplex struct {
+	fn func(i int, s string) (string, int)
+}
+
+var _ = funStructComplex{} //@codeactionedit("}", "refactor.rewrite", a23)
+
+type funStructEmpty struct {
+	fn func()
+}
+
+var _ = funStructEmpty{} //@codeactionedit("}", "refactor.rewrite", a24)
+
+-- @a21/a2.go --
+@@ -11 +11,7 @@
+-var _ = typedStruct{} //@codeactionedit("}", "refactor.rewrite", a21)
++var _ = typedStruct{
++	m:  map[string]int{},
++	s:  []int{},
++	c:  make(chan int),
++	c1: make(<-chan int),
++	a:  [2]string{},
++} //@codeactionedit("}", "refactor.rewrite", a21)
+-- @a22/a2.go --
+@@ -17 +17,4 @@
+-var _ = funStruct{} //@codeactionedit("}", "refactor.rewrite", a22)
++var _ = funStruct{
++	fn: func(i int) int {
++	},
++} //@codeactionedit("}", "refactor.rewrite", a22)
+-- @a23/a2.go --
+@@ -23 +23,4 @@
+-var _ = funStructComplex{} //@codeactionedit("}", "refactor.rewrite", a23)
++var _ = funStructComplex{
++	fn: func(i int, s string) (string, int) {
++	},
++} //@codeactionedit("}", "refactor.rewrite", a23)
+-- @a24/a2.go --
+@@ -29 +29,4 @@
+-var _ = funStructEmpty{} //@codeactionedit("}", "refactor.rewrite", a24)
++var _ = funStructEmpty{
++	fn: func() {
++	},
++} //@codeactionedit("}", "refactor.rewrite", a24)
+-- a3.go --
+package fillstruct
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+type Foo struct {
+	A int
+}
+
+type Bar struct {
+	X *Foo
+	Y *Foo
+}
+
+var _ = Bar{} //@codeactionedit("}", "refactor.rewrite", a31)
+
+type importedStruct struct {
+	m  map[*ast.CompositeLit]ast.Field
+	s  []ast.BadExpr
+	a  [3]token.Token
+	c  chan ast.EmptyStmt
+	fn func(ast_decl ast.DeclStmt) ast.Ellipsis
+	st ast.CompositeLit
+}
+
+var _ = importedStruct{} //@codeactionedit("}", "refactor.rewrite", a32)
+
+type pointerBuiltinStruct struct {
+	b *bool
+	s *string
+	i *int
+}
+
+var _ = pointerBuiltinStruct{} //@codeactionedit("}", "refactor.rewrite", a33)
+
+var _ = []ast.BasicLit{
+	{}, //@codeactionedit("}", "refactor.rewrite", a34)
+}
+
+var _ = []ast.BasicLit{{}} //@codeactionedit("}", "refactor.rewrite", a35)
+-- @a31/a3.go --
+@@ -17 +17,4 @@
+-var _ = Bar{} //@codeactionedit("}", "refactor.rewrite", a31)
++var _ = Bar{
++	X: &Foo{},
++	Y: &Foo{},
++} //@codeactionedit("}", "refactor.rewrite", a31)
+-- @a32/a3.go --
+@@ -28 +28,9 @@
+-var _ = importedStruct{} //@codeactionedit("}", "refactor.rewrite", a32)
++var _ = importedStruct{
++	m: map[*ast.CompositeLit]ast.Field{},
++	s: []ast.BadExpr{},
++	a: [3]token.Token{},
++	c: make(chan ast.EmptyStmt),
++	fn: func(ast_decl ast.DeclStmt) ast.Ellipsis {
++	},
++	st: ast.CompositeLit{},
++} //@codeactionedit("}", "refactor.rewrite", a32)
+-- @a33/a3.go --
+@@ -36 +36,5 @@
+-var _ = pointerBuiltinStruct{} //@codeactionedit("}", "refactor.rewrite", a33)
++var _ = pointerBuiltinStruct{
++	b: new(bool),
++	s: new(string),
++	i: new(int),
++} //@codeactionedit("}", "refactor.rewrite", a33)
+-- @a34/a3.go --
+@@ -39 +39,5 @@
+-	{}, //@codeactionedit("}", "refactor.rewrite", a34)
++	{
++		ValuePos: 0,
++		Kind:     0,
++		Value:    "",
++	}, //@codeactionedit("}", "refactor.rewrite", a34)
+-- @a35/a3.go --
+@@ -42 +42,5 @@
+-var _ = []ast.BasicLit{{}} //@codeactionedit("}", "refactor.rewrite", a35)
++var _ = []ast.BasicLit{{
++	ValuePos: 0,
++	Kind:     0,
++	Value:    "",
++}} //@codeactionedit("}", "refactor.rewrite", a35)
+-- a4.go --
+package fillstruct
+
+import "go/ast"
+
+type iStruct struct {
+	X int
+}
+
+type sStruct struct {
+	str string
+}
+
+type multiFill struct {
+	num   int
+	strin string
+	arr   []int
+}
+
+type assignStruct struct {
+	n ast.Node
+}
+
+func fill() {
+	var x int
+	var _ = iStruct{} //@codeactionedit("}", "refactor.rewrite", a41)
+
+	var s string
+	var _ = sStruct{} //@codeactionedit("}", "refactor.rewrite", a42)
+
+	var n int
+	_ = []int{}
+	if true {
+		arr := []int{1, 2}
+	}
+	var _ = multiFill{} //@codeactionedit("}", "refactor.rewrite", a43)
+
+	var node *ast.CompositeLit
+	var _ = assignStruct{} //@codeactionedit("}", "refactor.rewrite", a45)
+}
+
+-- @a41/a4.go --
+@@ -25 +25,3 @@
+-	var _ = iStruct{} //@codeactionedit("}", "refactor.rewrite", a41)
++	var _ = iStruct{
++		X: x,
++	} //@codeactionedit("}", "refactor.rewrite", a41)
+-- @a42/a4.go --
+@@ -28 +28,3 @@
+-	var _ = sStruct{} //@codeactionedit("}", "refactor.rewrite", a42)
++	var _ = sStruct{
++		str: s,
++	} //@codeactionedit("}", "refactor.rewrite", a42)
+-- @a43/a4.go --
+@@ -35 +35,5 @@
+-	var _ = multiFill{} //@codeactionedit("}", "refactor.rewrite", a43)
++	var _ = multiFill{
++		num:   n,
++		strin: s,
++		arr:   []int{},
++	} //@codeactionedit("}", "refactor.rewrite", a43)
+-- @a45/a4.go --
+@@ -38 +38,3 @@
+-	var _ = assignStruct{} //@codeactionedit("}", "refactor.rewrite", a45)
++	var _ = assignStruct{
++		n: node,
++	} //@codeactionedit("}", "refactor.rewrite", a45)
+-- fill_struct.go --
+package fillstruct
+
+type StructA struct {
+	unexportedIntField int
+	ExportedIntField   int
+	MapA               map[int]string
+	Array              []int
+	StructB
+}
+
+type StructA2 struct {
+	B *StructB
+}
+
+type StructA3 struct {
+	B StructB
+}
+
+func fill() {
+	a := StructA{}  //@codeactionedit("}", "refactor.rewrite", fill_struct1)
+	b := StructA2{} //@codeactionedit("}", "refactor.rewrite", fill_struct2)
+	c := StructA3{} //@codeactionedit("}", "refactor.rewrite", fill_struct3)
+	if true {
+		_ = StructA3{} //@codeactionedit("}", "refactor.rewrite", fill_struct4)
+	}
+}
+
+-- @fill_struct1/fill_struct.go --
+@@ -20 +20,7 @@
+-	a := StructA{}  //@codeactionedit("}", "refactor.rewrite", fill_struct1)
++	a := StructA{
++		unexportedIntField: 0,
++		ExportedIntField:   0,
++		MapA:               map[int]string{},
++		Array:              []int{},
++		StructB:            StructB{},
++	}  //@codeactionedit("}", "refactor.rewrite", fill_struct1)
+-- @fill_struct2/fill_struct.go --
+@@ -21 +21,3 @@
+-	b := StructA2{} //@codeactionedit("}", "refactor.rewrite", fill_struct2)
++	b := StructA2{
++		B: &StructB{},
++	} //@codeactionedit("}", "refactor.rewrite", fill_struct2)
+-- @fill_struct3/fill_struct.go --
+@@ -22 +22,3 @@
+-	c := StructA3{} //@codeactionedit("}", "refactor.rewrite", fill_struct3)
++	c := StructA3{
++		B: StructB{},
++	} //@codeactionedit("}", "refactor.rewrite", fill_struct3)
+-- @fill_struct4/fill_struct.go --
+@@ -24 +24,3 @@
+-		_ = StructA3{} //@codeactionedit("}", "refactor.rewrite", fill_struct4)
++		_ = StructA3{
++			B: StructB{},
++		} //@codeactionedit("}", "refactor.rewrite", fill_struct4)
+-- fill_struct_anon.go --
+package fillstruct
+
+type StructAnon struct {
+	a struct{}
+	b map[string]interface{}
+	c map[string]struct {
+		d int
+		e bool
+	}
+}
+
+func fill() {
+	_ := StructAnon{} //@codeactionedit("}", "refactor.rewrite", fill_struct_anon)
+}
+-- @fill_struct_anon/fill_struct_anon.go --
+@@ -13 +13,5 @@
+-	_ := StructAnon{} //@codeactionedit("}", "refactor.rewrite", fill_struct_anon)
++	_ := StructAnon{
++		a: struct{}{},
++		b: map[string]interface{}{},
++		c: map[string]struct{d int; e bool}{},
++	} //@codeactionedit("}", "refactor.rewrite", fill_struct_anon)
+-- fill_struct_nested.go --
+package fillstruct
+
+type StructB struct {
+	StructC
+}
+
+type StructC struct {
+	unexportedInt int
+}
+
+func nested() {
+	c := StructB{
+		StructC: StructC{}, //@codeactionedit("}", "refactor.rewrite", fill_nested)
+	}
+}
+
+-- @fill_nested/fill_struct_nested.go --
+@@ -13 +13,3 @@
+-		StructC: StructC{}, //@codeactionedit("}", "refactor.rewrite", fill_nested)
++		StructC: StructC{
++			unexportedInt: 0,
++		}, //@codeactionedit("}", "refactor.rewrite", fill_nested)
+-- fill_struct_package.go --
+package fillstruct
+
+import (
+	h2 "net/http"
+
+	"golang.org/lsptests/fillstruct/data"
+)
+
+func unexported() {
+	a := data.B{}   //@codeactionedit("}", "refactor.rewrite", fill_struct_package1)
+	_ = h2.Client{} //@codeactionedit("}", "refactor.rewrite", fill_struct_package2)
+}
+-- @fill_struct_package1/fill_struct_package.go --
+@@ -10 +10,3 @@
+-	a := data.B{}   //@codeactionedit("}", "refactor.rewrite", fill_struct_package1)
++	a := data.B{
++		ExportedInt: 0,
++	}   //@codeactionedit("}", "refactor.rewrite", fill_struct_package1)
+-- @fill_struct_package2/fill_struct_package.go --
+@@ -11 +11,7 @@
+-	_ = h2.Client{} //@codeactionedit("}", "refactor.rewrite", fill_struct_package2)
++	_ = h2.Client{
++		Transport: nil,
++		CheckRedirect: func(req *h2.Request, via []*h2.Request) error {
++		},
++		Jar:     nil,
++		Timeout: 0,
++	} //@codeactionedit("}", "refactor.rewrite", fill_struct_package2)
+-- fill_struct_partial.go --
+package fillstruct
+
+type StructPartialA struct {
+	PrefilledInt int
+	UnfilledInt  int
+	StructPartialB
+}
+
+type StructPartialB struct {
+	PrefilledInt int
+	UnfilledInt  int
+}
+
+func fill() {
+	a := StructPartialA{
+		PrefilledInt: 5,
+	} //@codeactionedit("}", "refactor.rewrite", fill_struct_partial1)
+	b := StructPartialB{
+		/* this comment should disappear */
+		PrefilledInt: 7, // This comment should be blown away.
+		/* As should
+		this one */
+	} //@codeactionedit("}", "refactor.rewrite", fill_struct_partial2)
+}
+
+-- @fill_struct_partial1/fill_struct_partial.go --
+@@ -16 +16,3 @@
+-		PrefilledInt: 5,
++		PrefilledInt:   5,
++		UnfilledInt:    0,
++		StructPartialB: StructPartialB{},
+-- @fill_struct_partial2/fill_struct_partial.go --
+@@ -19,4 +19,2 @@
+-		/* this comment should disappear */
+-		PrefilledInt: 7, // This comment should be blown away.
+-		/* As should
+-		this one */
++		PrefilledInt: 7,
++		UnfilledInt:  0,
+-- fill_struct_spaces.go --
+package fillstruct
+
+type StructD struct {
+	ExportedIntField int
+}
+
+func spaces() {
+	d := StructD{} //@codeactionedit("}", "refactor.rewrite", fill_struct_spaces)
+}
+
+-- @fill_struct_spaces/fill_struct_spaces.go --
+@@ -8 +8,3 @@
+-	d := StructD{} //@codeactionedit("}", "refactor.rewrite", fill_struct_spaces)
++	d := StructD{
++		ExportedIntField: 0,
++	} //@codeactionedit("}", "refactor.rewrite", fill_struct_spaces)
+-- fill_struct_unsafe.go --
+package fillstruct
+
+import "unsafe"
+
+type unsafeStruct struct {
+	x int
+	p unsafe.Pointer
+}
+
+func fill() {
+	_ := unsafeStruct{} //@codeactionedit("}", "refactor.rewrite", fill_struct_unsafe)
+}
+
+-- @fill_struct_unsafe/fill_struct_unsafe.go --
+@@ -11 +11,4 @@
+-	_ := unsafeStruct{} //@codeactionedit("}", "refactor.rewrite", fill_struct_unsafe)
++	_ := unsafeStruct{
++		x: 0,
++		p: nil,
++	} //@codeactionedit("}", "refactor.rewrite", fill_struct_unsafe)
+-- typeparams.go --
+package fillstruct
+
+type emptyStructWithTypeParams[A any] struct{}
+
+var _ = emptyStructWithTypeParams[int]{} // no suggested fix
+
+type basicStructWithTypeParams[T any] struct {
+	foo T
+}
+
+var _ = basicStructWithTypeParams[int]{} //@codeactionedit("}", "refactor.rewrite", typeparams1)
+
+type twoArgStructWithTypeParams[F, B any] struct {
+	foo F
+	bar B
+}
+
+var _ = twoArgStructWithTypeParams[string, int]{} //@codeactionedit("}", "refactor.rewrite", typeparams2)
+
+var _ = twoArgStructWithTypeParams[int, string]{
+	bar: "bar",
+} //@codeactionedit("}", "refactor.rewrite", typeparams3)
+
+type nestedStructWithTypeParams struct {
+	bar   string
+	basic basicStructWithTypeParams[int]
+}
+
+var _ = nestedStructWithTypeParams{} //@codeactionedit("}", "refactor.rewrite", typeparams4)
+
+func _[T any]() {
+	type S struct{ t T }
+	_ = S{} //@codeactionedit("}", "refactor.rewrite", typeparams5)
+}
+-- @typeparams1/typeparams.go --
+@@ -11 +11,3 @@
+-var _ = basicStructWithTypeParams[int]{} //@codeactionedit("}", "refactor.rewrite", typeparams1)
++var _ = basicStructWithTypeParams[int]{
++	foo: 0,
++} //@codeactionedit("}", "refactor.rewrite", typeparams1)
+-- @typeparams2/typeparams.go --
+@@ -18 +18,4 @@
+-var _ = twoArgStructWithTypeParams[string, int]{} //@codeactionedit("}", "refactor.rewrite", typeparams2)
++var _ = twoArgStructWithTypeParams[string, int]{
++	foo: "",
++	bar: 0,
++} //@codeactionedit("}", "refactor.rewrite", typeparams2)
+-- @typeparams3/typeparams.go --
+@@ -21 +21 @@
++	foo: 0,
+-- @typeparams4/typeparams.go --
+@@ -29 +29,4 @@
+-var _ = nestedStructWithTypeParams{} //@codeactionedit("}", "refactor.rewrite", typeparams4)
++var _ = nestedStructWithTypeParams{
++	bar:   "",
++	basic: basicStructWithTypeParams{},
++} //@codeactionedit("}", "refactor.rewrite", typeparams4)
+-- @typeparams5/typeparams.go --
+@@ -33 +33,3 @@
+-	_ = S{} //@codeactionedit("}", "refactor.rewrite", typeparams5)
++	_ = S{
++		t: *new(T),
++	} //@codeactionedit("}", "refactor.rewrite", typeparams5)
+-- issue63921.go --
+package fillstruct
+
+// Test for golang/go#63921: fillstruct panicked with invalid fields.
+type invalidStruct struct {
+  F int
+  Undefined
+}
+
+func _() {
+  // Note: the golden content for issue63921 is empty: fillstruct produces no
+  // edits, but does not panic.
+  invalidStruct{} //@codeactionedit("}", "refactor.rewrite", issue63921)
+}
diff --git a/gopls/internal/test/marker/testdata/codeaction/import-shadows-builtin.txt b/gopls/internal/test/marker/testdata/codeaction/import-shadows-builtin.txt
new file mode 100644
index 0000000..aeb86a2
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/codeaction/import-shadows-builtin.txt
@@ -0,0 +1,55 @@
+This is a regression test for bug #63592 in "organize imports" whereby
+the new imports would shadow predeclared names.
+
+In the original example, the conflict was between predeclared error
+type and the unfortunately named package github.com/coreos/etcd/error,
+but this example uses a package with the ludicrous name of complex128.
+
+The new behavior is that we will not attempt to import packages
+that shadow predeclared names. (Ideally we would do that only if
+the predeclared name is actually referenced in the file, which
+complex128 happens to be in this example, but that's a trickier
+analysis than the internal/imports package is game for.)
+
+The name complex127 works as usual.
+
+-- go.mod --
+module example.com
+go 1.18
+
+-- complex128/a.go --
+package complex128
+
+var V int
+
+-- complex127/a.go --
+package complex127
+
+var V int
+
+-- main.go --
+package main
+
+import () //@codeaction("import", "", "source.organizeImports", out)
+
+func main() {
+	complex128.V() //@diag("V", re"type complex128 has no field")
+	complex127.V() //@diag("complex127", re"(undeclared|undefined)")
+}
+
+func _() {
+	var _ complex128 = 1 + 2i
+}
+-- @out/main.go --
+package main
+
+import "example.com/complex127" //@codeaction("import", "", "source.organizeImports", out)
+
+func main() {
+	complex128.V() //@diag("V", re"type complex128 has no field")
+	complex127.V() //@diag("complex127", re"(undeclared|undefined)")
+}
+
+func _() {
+	var _ complex128 = 1 + 2i
+}
diff --git a/gopls/internal/test/marker/testdata/codeaction/infertypeargs.txt b/gopls/internal/test/marker/testdata/codeaction/infertypeargs.txt
index aa42e87..b622efd 100644
--- a/gopls/internal/test/marker/testdata/codeaction/infertypeargs.txt
+++ b/gopls/internal/test/marker/testdata/codeaction/infertypeargs.txt
@@ -15,21 +15,11 @@
 func _() {
 	_ = app[[]int]
 	_ = app[[]int, int]
-	_ = app[[]int]([]int{}, 0) //@codeaction("app", ")", "refactor.rewrite", infer)
+	_ = app[[]int]([]int{}, 0) //@suggestedfix("[[]int]", re"unnecessary type arguments", infer)
 	_ = app([]int{}, 0)
 }
 
 -- @infer/p.go --
-package infertypeargs
-
-func app[S interface{ ~[]E }, E interface{}](s S, e E) S {
-	return append(s, e)
-}
-
-func _() {
-	_ = app[[]int]
-	_ = app[[]int, int]
-	_ = app([]int{}, 0) //@codeaction("app", ")", "refactor.rewrite", infer)
-	_ = app([]int{}, 0)
-}
-
+@@ -10 +10 @@
+-	_ = app[[]int]([]int{}, 0) //@suggestedfix("[[]int]", re"unnecessary type arguments", infer)
++	_ = app([]int{}, 0) //@suggestedfix("[[]int]", re"unnecessary type arguments", infer)
diff --git a/gopls/internal/test/marker/testdata/codeaction/inline.txt b/gopls/internal/test/marker/testdata/codeaction/inline.txt
index 813a69c..339a05b 100644
--- a/gopls/internal/test/marker/testdata/codeaction/inline.txt
+++ b/gopls/internal/test/marker/testdata/codeaction/inline.txt
@@ -1,7 +1,7 @@
 This is a minimal test of the refactor.inline code action.
 
 -- go.mod --
-module testdata/codeaction
+module example.com/codeaction
 go 1.18
 
 -- a/a.go --
diff --git a/gopls/internal/test/marker/testdata/codeaction/issue64558.txt b/gopls/internal/test/marker/testdata/codeaction/issue64558.txt
index 71d9661..59aaffb 100644
--- a/gopls/internal/test/marker/testdata/codeaction/issue64558.txt
+++ b/gopls/internal/test/marker/testdata/codeaction/issue64558.txt
@@ -1,7 +1,7 @@
 Test of an inlining failure due to an ill-typed input program (#64558).
 
 -- go.mod --
-module testdata
+module example.com
 go 1.18
 
 -- a/a.go --
diff --git a/gopls/internal/test/marker/testdata/codeaction/removeparam.txt b/gopls/internal/test/marker/testdata/codeaction/removeparam.txt
index ad22892..17a058f 100644
--- a/gopls/internal/test/marker/testdata/codeaction/removeparam.txt
+++ b/gopls/internal/test/marker/testdata/codeaction/removeparam.txt
@@ -1,4 +1,5 @@
 This test exercises the refactoring to remove unused parameters.
+See removeparam_resolve.txt for same test with resolve support.
 
 -- go.mod --
 module unused.mod
@@ -202,7 +203,7 @@
 -- effects/effects.go --
 package effects
 
-func effects(x, y int) int { //@codeaction("y", "y", "refactor.rewrite", effects)
+func effects(x, y int) int { //@ diag("y", re"unused"), codeaction("y", "y", "refactor.rewrite", effects)
 	return x
 }
 
@@ -216,7 +217,7 @@
 -- @effects/effects/effects.go --
 package effects
 
-func effects(x int) int { //@codeaction("y", "y", "refactor.rewrite", effects)
+func effects(x int) int { //@ diag("y", re"unused"), codeaction("y", "y", "refactor.rewrite", effects)
 	return x
 }
 
diff --git a/gopls/internal/test/marker/testdata/codeaction/removeparam_resolve.txt b/gopls/internal/test/marker/testdata/codeaction/removeparam_resolve.txt
new file mode 100644
index 0000000..1c04aa0
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/codeaction/removeparam_resolve.txt
@@ -0,0 +1,258 @@
+This test exercises the refactoring to remove unused parameters, with resolve support.
+See removeparam.txt for same test without resolve support.
+
+-- capabilities.json --
+{
+	"textDocument": {
+		"codeAction": {
+			"dataSupport": true,
+			"resolveSupport": {
+				"properties": ["edit"]
+			}
+		}
+	}
+}
+-- go.mod --
+module unused.mod
+
+go 1.18
+
+-- a/a.go --
+package a
+
+func A(x, unused int) int { //@codeaction("unused", "unused", "refactor.rewrite", a)
+	return x
+}
+
+-- @a/a/a.go --
+package a
+
+func A(x int) int { //@codeaction("unused", "unused", "refactor.rewrite", a)
+	return x
+}
+
+-- a/a2.go --
+package a
+
+func _() {
+	A(1, 2)
+}
+
+-- a/a_test.go --
+package a
+
+func _() {
+	A(1, 2)
+}
+
+-- a/a_x_test.go --
+package a_test
+
+import "unused.mod/a"
+
+func _() {
+	a.A(1, 2)
+}
+
+-- b/b.go --
+package b
+
+import "unused.mod/a"
+
+func f() int {
+	return 1
+}
+
+func g() int {
+	return 2
+}
+
+func _() {
+	a.A(f(), 1)
+}
+
+-- @a/a/a2.go --
+package a
+
+func _() {
+	A(1)
+}
+-- @a/a/a_test.go --
+package a
+
+func _() {
+	A(1)
+}
+-- @a/a/a_x_test.go --
+package a_test
+
+import "unused.mod/a"
+
+func _() {
+	a.A(1)
+}
+-- @a/b/b.go --
+package b
+
+import "unused.mod/a"
+
+func f() int {
+	return 1
+}
+
+func g() int {
+	return 2
+}
+
+func _() {
+	a.A(f())
+}
+-- field/field.go --
+package field
+
+func Field(x int, field int) { //@codeaction("int", "int", "refactor.rewrite", field)
+}
+
+func _() {
+	Field(1, 2)
+}
+-- @field/field/field.go --
+package field
+
+func Field(field int) { //@codeaction("int", "int", "refactor.rewrite", field)
+}
+
+func _() {
+	Field(2)
+}
+-- ellipsis/ellipsis.go --
+package ellipsis
+
+func Ellipsis(...any) { //@codeaction("any", "any", "refactor.rewrite", ellipsis)
+}
+
+func _() {
+	// TODO(rfindley): investigate the broken formatting resulting from these inlinings.
+	Ellipsis()
+	Ellipsis(1)
+	Ellipsis(1, 2)
+	Ellipsis(1, f(), g())
+	Ellipsis(h())
+	Ellipsis(i()...)
+}
+
+func f() int
+func g() int
+func h() (int, int)
+func i() []any
+
+-- @ellipsis/ellipsis/ellipsis.go --
+package ellipsis
+
+func Ellipsis() { //@codeaction("any", "any", "refactor.rewrite", ellipsis)
+}
+
+func _() {
+	// TODO(rfindley): investigate the broken formatting resulting from these inlinings.
+	Ellipsis()
+	Ellipsis()
+	Ellipsis()
+	var _ []any = []any{1, f(), g()}
+	Ellipsis()
+	func(_ ...any) {
+		Ellipsis()
+	}(h())
+	var _ []any = i()
+	Ellipsis()
+}
+
+func f() int
+func g() int
+func h() (int, int)
+func i() []any
+-- ellipsis2/ellipsis2.go --
+package ellipsis2
+
+func Ellipsis2(_, _ int, rest ...int) { //@codeaction("_", "_", "refactor.rewrite", ellipsis2)
+}
+
+func _() {
+	Ellipsis2(1,2,3)
+	Ellipsis2(h())
+	Ellipsis2(1,2, []int{3, 4}...)
+}
+
+func h() (int, int)
+
+-- @ellipsis2/ellipsis2/ellipsis2.go --
+package ellipsis2
+
+func Ellipsis2(_ int, rest ...int) { //@codeaction("_", "_", "refactor.rewrite", ellipsis2)
+}
+
+func _() {
+	Ellipsis2(2, []int{3}...)
+	func(_, blank0 int, rest ...int) {
+		Ellipsis2(blank0, rest...)
+	}(h())
+	Ellipsis2(2, []int{3, 4}...)
+}
+
+func h() (int, int)
+-- overlapping/overlapping.go --
+package overlapping
+
+func Overlapping(i int) int { //@codeactionerr(re"(i) int", re"(i) int", "refactor.rewrite", re"overlapping")
+	return 0
+}
+
+func _() {
+	x := Overlapping(Overlapping(0))
+	_ = x
+}
+
+-- effects/effects.go --
+package effects
+
+func effects(x, y int) int { //@codeaction("y", "y", "refactor.rewrite", effects), diag("y", re"unused")
+	return x
+}
+
+func f() int
+func g() int
+
+func _() {
+	effects(f(), g())
+	effects(f(), g())
+}
+-- @effects/effects/effects.go --
+package effects
+
+func effects(x int) int { //@codeaction("y", "y", "refactor.rewrite", effects), diag("y", re"unused")
+	return x
+}
+
+func f() int
+func g() int
+
+func _() {
+	var x, _ int = f(), g()
+	effects(x)
+	{
+		var x, _ int = f(), g()
+		effects(x)
+	}
+}
+-- recursive/recursive.go --
+package recursive
+
+func Recursive(x int) int { //@codeaction("x", "x", "refactor.rewrite", recursive)
+	return Recursive(1)
+}
+
+-- @recursive/recursive/recursive.go --
+package recursive
+
+func Recursive() int { //@codeaction("x", "x", "refactor.rewrite", recursive)
+	return Recursive()
+}
diff --git a/gopls/internal/test/marker/testdata/codelens/test.txt b/gopls/internal/test/marker/testdata/codelens/test.txt
index 90782bd..ba68cf0 100644
--- a/gopls/internal/test/marker/testdata/codelens/test.txt
+++ b/gopls/internal/test/marker/testdata/codelens/test.txt
@@ -22,7 +22,8 @@
 func TestFuncWithCodeLens(t *testing.T) { //@codelens(re"()func", "run test")
 }
 
-func thisShouldNotHaveACodeLens(t *testing.T) {
+func thisShouldNotHaveACodeLens(t *testing.T) { //@diag("t ", re"unused parameter")
+	println() // nonempty body => "unused parameter"
 }
 
 func BenchmarkFuncWithCodeLens(b *testing.B) { //@codelens(re"()func", "run benchmark")
diff --git a/gopls/internal/test/marker/testdata/completion/func_snippets.txt b/gopls/internal/test/marker/testdata/completion/func_snippets.txt
index efbc393..0131634 100644
--- a/gopls/internal/test/marker/testdata/completion/func_snippets.txt
+++ b/gopls/internal/test/marker/testdata/completion/func_snippets.txt
@@ -28,5 +28,5 @@
 
 func _() {
 	_ = NewSyncM //@snippet(" //", NewSyncMap, "NewSyncMap[${1:K comparable}, ${2:V any}]()")
-	_ = Identi //@snippet(" //", Identity, "Identity[${1:P ~int}](${2:p P})")
+	_ = Identi //@snippet(" //", Identity, "Identity(${1:p P})")
 }
diff --git a/gopls/internal/test/marker/testdata/completion/issue51783.txt b/gopls/internal/test/marker/testdata/completion/issue51783.txt
new file mode 100644
index 0000000..074259c
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/completion/issue51783.txt
@@ -0,0 +1,47 @@
+Regression test for "completion gives unneeded generic type
+instantiation snippet", #51783.
+
+Type parameters that can be inferred from the arguments
+are not part of the offered completion snippet.
+
+-- flags --
+-ignore_extra_diags
+
+-- a.go --
+package a
+
+// identity has a single simple type parameter.
+// The completion omits the instantiation.
+func identity[T any](x T) T
+
+// clone has a second type parameter that is nonetheless constrained by the parameter.
+// The completion omits the instantiation.
+func clone[S ~[]E, E any](s S) S
+
+// unconstrained has a type parameter constrained only by the result.
+// The completion suggests instantiation.
+func unconstrained[X, Y any](x X) Y
+
+// partial has three type parameters,
+// only the last two of which may be omitted as they
+// are constrained by the arguments.
+func partial[R any, S ~[]E, E any](s S) R
+
+//@item(identity, "identity", "details", "kind")
+//@item(clone, "clone", "details", "kind")
+//@item(unconstrained, "unconstrained", "details", "kind")
+//@item(partial, "partial", "details", "kind")
+
+func _() {
+	_ = identity //@snippet("identity", identity, "identity(${1:})")
+
+	_ = clone //@snippet("clone", clone, "clone(${1:})")
+
+	_ = unconstrained //@snippet("unconstrained", unconstrained, "unconstrained[${1:}](${2:})")
+
+	_ = partial //@snippet("partial", partial, "partial[${1:}](${2:})")
+
+	// Result-type inference permits us to omit Y in this (rare) case,
+	// but completion doesn't support that.
+	var _ int = unconstrained //@snippet("unconstrained", unconstrained, "unconstrained[${1:}](${2:})")
+}
diff --git a/gopls/internal/test/marker/testdata/completion/nested_complit.txt b/gopls/internal/test/marker/testdata/completion/nested_complit.txt
index f3a148d..264ae77 100644
--- a/gopls/internal/test/marker/testdata/completion/nested_complit.txt
+++ b/gopls/internal/test/marker/testdata/completion/nested_complit.txt
@@ -1,9 +1,11 @@
 This test checks completion of nested composite literals;
 
-TODO(rfindley): investigate an un-skip the disabled test below.
+Parser recovery changed in Go 1.20, so this test requires at least that
+version for consistency.
 
 -- flags --
 -ignore_extra_diags
+-min_go=go1.20
 
 -- nested_complit.go --
 package nested_complit
@@ -15,9 +17,10 @@
 }
 
 func _() {
-	[]ncFoo{} //@item(litNCFoo, "[]ncFoo{}", "", "var")
+	_ = []ncFoo{} //@item(litNCFoo, "[]ncFoo{}", "", "var")
+	_ = make([]ncFoo, 0) //@item(makeNCFoo, "make([]ncFoo, 0)", "", "func")
+
 	_ := ncBar{
-		// disabled - see issue #54822
-		baz: [] // complete(" //", structNCFoo, structNCBar)
+		baz: [] //@complete(" //", litNCFoo, makeNCFoo, structNCBar, structNCFoo)
 	}
 }
diff --git a/gopls/internal/test/marker/testdata/completion/postfix.txt b/gopls/internal/test/marker/testdata/completion/postfix.txt
index 63661ee..cab0974 100644
--- a/gopls/internal/test/marker/testdata/completion/postfix.txt
+++ b/gopls/internal/test/marker/testdata/completion/postfix.txt
@@ -13,6 +13,10 @@
 -- postfix.go --
 package snippets
 
+import (
+	"strconv"
+)
+
 func _() {
 	var foo []int
 	foo.append //@rank(" //", postfixAppend)
@@ -96,3 +100,32 @@
 	foo.fo //@snippet(" //", postfixForChannel, "for ${1:} := range foo {\n\t$0\n}")
 	foo.rang //@snippet(" //", postfixRangeChannel, "for ${1:} := range foo {\n\t$0\n}")
 }
+
+type T struct {
+	Name string
+}
+
+func _() (string, T, map[string]string, error) {
+	/* iferr! */ //@item(postfixIfErr, "iferr!", "check error and return", "snippet")
+	/* variferr! */ //@item(postfixVarIfErr, "variferr!", "assign variables and check error", "snippet")
+	/* var! */ //@item(postfixVars, "var!", "assign to variables", "snippet")
+
+	strconv.Atoi("32"). //@complete(" //", postfixIfErr, postfixPrint, postfixVars, postfixVarIfErr)
+
+	var err error
+	err.iferr //@snippet(" //", postfixIfErr, "if err != nil {\n\treturn \"\", T{}, nil, ${1:}\n}\n")
+
+	strconv.Atoi("32").iferr //@snippet(" //", postfixIfErr, "if _, err := strconv.Atoi(\"32\"); err != nil {\n\treturn \"\", T{}, nil, ${1:}\n}\n")
+
+	strconv.Atoi("32").variferr //@snippet(" //", postfixVarIfErr, "${1:}, ${2:} := strconv.Atoi(\"32\")\nif ${2:} != nil {\n\treturn \"\", T{}, nil, ${3:}\n}\n")
+
+	// test function return multiple errors
+	var foo func() (error, error)
+	foo().iferr //@snippet(" //", postfixIfErr, "if _, err := foo(); err != nil {\n\treturn \"\", T{}, nil, ${1:}\n}\n")
+	foo().variferr //@snippet(" //", postfixVarIfErr, "${1:}, ${2:} := foo()\nif ${2:} != nil {\n\treturn \"\", T{}, nil, ${3:}\n}\n")
+
+	// test function just return error
+	var bar func() error
+	bar().iferr //@snippet(" //", postfixIfErr, "if err := bar(); err != nil {\n\treturn \"\", T{}, nil, ${1:}\n}\n")
+	bar().variferr //@snippet(" //", postfixVarIfErr, "${1:} := bar()\nif ${1:} != nil {\n\treturn \"\", T{}, nil, ${2:}\n}\n")
+}
diff --git a/gopls/internal/test/marker/testdata/completion/postfix_placeholder.txt b/gopls/internal/test/marker/testdata/completion/postfix_placeholder.txt
index 44dfbc9..7569f13 100644
--- a/gopls/internal/test/marker/testdata/completion/postfix_placeholder.txt
+++ b/gopls/internal/test/marker/testdata/completion/postfix_placeholder.txt
@@ -16,6 +16,10 @@
 -- postfix.go --
 package snippets
 
+import (
+	"strconv"
+)
+
 func _() {
 	/* for! */ //@item(postfixFor, "for!", "range over slice by index", "snippet")
 	/* forr! */ //@item(postfixForr, "forr!", "range over slice by index and value", "snippet")
@@ -51,3 +55,29 @@
 	foo.fo //@snippet(" //", postfixForChannel, "for ${1:e} := range foo {\n\t$0\n}")
 	foo.rang //@snippet(" //", postfixRangeChannel, "for ${1:e} := range foo {\n\t$0\n}")
 }
+
+type T struct {
+	Name string
+}
+
+func _() (string, T, map[string]string, error) {
+	/* iferr! */ //@item(postfixIfErr, "iferr!", "check error and return", "snippet")
+	/* variferr! */ //@item(postfixVarIfErr, "variferr!", "assign variables and check error", "snippet")
+	/* var! */ //@item(postfixVars, "var!", "assign to variables", "snippet")
+
+
+	var err error
+	err.iferr //@snippet(" //", postfixIfErr, "if err != nil {\n\treturn \"\", T{}, nil, ${1:err}\n}\n")
+	strconv.Atoi("32").iferr //@snippet(" //", postfixIfErr, "if _, err := strconv.Atoi(\"32\"); err != nil {\n\treturn \"\", T{}, nil, ${1:err}\n}\n")
+	strconv.Atoi("32").variferr //@snippet(" //", postfixVarIfErr, "${1:i}, ${2:err} := strconv.Atoi(\"32\")\nif ${2:err} != nil {\n\treturn \"\", T{}, nil, ${3:${2:err}}\n}\n")
+
+	// test function return multiple errors
+	var foo func() (error, error)
+	foo().iferr //@snippet(" //", postfixIfErr, "if _, err := foo(); err != nil {\n\treturn \"\", T{}, nil, ${1:err}\n}\n")
+	foo().variferr //@snippet(" //", postfixVarIfErr, "${1:err2}, ${2:err} := foo()\nif ${2:err} != nil {\n\treturn \"\", T{}, nil, ${3:${2:err}}\n}\n")
+
+	// test function just return error
+	var bar func() error
+	bar().iferr //@snippet(" //", postfixIfErr, "if err := bar(); err != nil {\n\treturn \"\", T{}, nil, ${1:err}\n}\n")
+	bar().variferr //@snippet(" //", postfixVarIfErr, "${1:err2} := bar()\nif ${1:err2} != nil {\n\treturn \"\", T{}, nil, ${2:${1:err2}}\n}\n")
+}
diff --git a/gopls/internal/test/marker/testdata/completion/type_params.txt b/gopls/internal/test/marker/testdata/completion/type_params.txt
index 185d77f..8e2f5d7 100644
--- a/gopls/internal/test/marker/testdata/completion/type_params.txt
+++ b/gopls/internal/test/marker/testdata/completion/type_params.txt
@@ -52,8 +52,7 @@
 }
 
 func _() {
-	// disabled - see issue #54822
-	var _ int = returnTP // snippet(" //", returnTP, "returnTP[${1:}](${2:})")
+	var _ int = returnTP //@snippet(" //", returnTP, "returnTP(${1:})")
 
 	var aa int //@item(tpInt, "aa", "int", "var")
 	var ab float64 //@item(tpFloat, "ab", "float64", "var")
diff --git a/gopls/internal/test/marker/testdata/definition/embed.txt b/gopls/internal/test/marker/testdata/definition/embed.txt
index 3212c14..9842c37 100644
--- a/gopls/internal/test/marker/testdata/definition/embed.txt
+++ b/gopls/internal/test/marker/testdata/definition/embed.txt
@@ -182,6 +182,11 @@
 }
 ```
 
+```go
+// Embedded fields:
+F2 int // through S2 
+```
+
 [`b.S1` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S1)
 -- @S1F1 --
 ```go
@@ -210,6 +215,10 @@
 }
 ```
 
+```go
+func (a.A) Hi()
+```
+
 [`b.S2` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S2)
 -- @S2F1 --
 ```go
@@ -241,19 +250,24 @@
 -- @aA --
 ```go
 type A string
-
-func (a.A).Hi()
 ```
 
 @loc(AString, "A")
 
 
+```go
+func (a.A) Hi()
+```
+
 [`a.A` on pkg.go.dev](https://pkg.go.dev/mod.com/a#A)
 -- @aAlias --
 ```go
 type aAlias = a.A
-
-func (a.A).Hi()
 ```
 
 @loc(aAlias, "aAlias")
+
+
+```go
+func (a.A) Hi()
+```
diff --git a/gopls/internal/test/marker/testdata/definition/misc.txt b/gopls/internal/test/marker/testdata/definition/misc.txt
index 2ab637a..c7147a6 100644
--- a/gopls/internal/test/marker/testdata/definition/misc.txt
+++ b/gopls/internal/test/marker/testdata/definition/misc.txt
@@ -177,6 +177,10 @@
 }
 ```
 
+```go
+func (J) Hello()
+```
+
 [`a.I` on pkg.go.dev](https://pkg.go.dev/mod.com#I)
 -- @hoverJ --
 ```go
diff --git a/gopls/internal/test/marker/testdata/definition/standalone.txt b/gopls/internal/test/marker/testdata/definition/standalone.txt
new file mode 100644
index 0000000..6af1149
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/definition/standalone.txt
@@ -0,0 +1,42 @@
+This test checks the behavior of standalone packages, in particular documenting
+our failure to support test files as standalone packages (golang/go#64233).
+
+-- go.mod --
+module golang.org/lsptests/a
+
+go 1.20
+
+-- a.go --
+package a
+
+func F() {} //@loc(F, "F")
+
+-- standalone.go --
+//go:build ignore
+package main
+
+import "golang.org/lsptests/a"
+
+func main() {
+	a.F() //@def("F", F)
+}
+
+-- standalone_test.go --
+//go:build ignore
+package main //@diag("main", re"No packages found")
+
+import "golang.org/lsptests/a"
+
+func main() {
+	a.F() //@hovererr("F", "no package")
+}
+
+-- standalone_x_test.go --
+//go:build ignore
+package main_test //@diag("main", re"No packages found")
+
+import "golang.org/lsptests/a"
+
+func main() {
+	a.F() //@hovererr("F", "no package")
+}
diff --git a/gopls/internal/test/marker/testdata/diagnostics/addgowork.txt b/gopls/internal/test/marker/testdata/diagnostics/addgowork.txt
index 729547a..5fbd890 100644
--- a/gopls/internal/test/marker/testdata/diagnostics/addgowork.txt
+++ b/gopls/internal/test/marker/testdata/diagnostics/addgowork.txt
@@ -5,9 +5,13 @@
 TODO(rfindley): improve the "cannot find package" import errors.
 
 -- skip --
-Skipping due to go.dev/issue/60584#issuecomment-1622238115.
-There appears to be a real race in the critical error logic causing this test
-to flake with high frequency.
+These diagnostics are no longer produced, because in golang/go#57979
+(zero-config gopls) we made gopls function independent of a go.work file.
+Preserving this test as we may want to re-enable the code actions go manage
+a go.work file.
+
+Note that in go.dev/issue/60584#issuecomment-1622238115, this test was flaky.
+However, critical error logic has since been rewritten.
 
 -- a/go.mod --
 module mod.com/a
diff --git a/gopls/internal/test/marker/testdata/diagnostics/issue64547.txt b/gopls/internal/test/marker/testdata/diagnostics/issue64547.txt
new file mode 100644
index 0000000..3f3e13b
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/diagnostics/issue64547.txt
@@ -0,0 +1,14 @@
+This test checks the fix for golang/go#64547: the lostcancel analyzer reports
+diagnostics that overflow the file.
+
+-- p.go --
+package p
+
+import "context"
+
+func _() {
+	_, cancel := context.WithCancel(context.Background()) //@diag("_, cancel", re"not used on all paths")
+	if false {
+		cancel()
+	}
+} //@diag("}", re"may be reached without using the cancel")
diff --git a/gopls/internal/test/marker/testdata/format/issue59554.txt b/gopls/internal/test/marker/testdata/format/issue59554.txt
index aa6c2aa..816c9d1 100644
--- a/gopls/internal/test/marker/testdata/format/issue59554.txt
+++ b/gopls/internal/test/marker/testdata/format/issue59554.txt
@@ -4,7 +4,10 @@
 Note that gofumpt is needed for this test case, as it reformats var decls into
 short var decls.
 
-Note that gofumpt requires Go 1.18.
+Note that gofumpt requires Go 1.20.
+
+-- flags --
+-min_go=go1.20
 
 -- settings.json --
 {
diff --git a/gopls/internal/test/marker/testdata/highlight/issue60589.txt b/gopls/internal/test/marker/testdata/highlight/issue60589.txt
new file mode 100644
index 0000000..afa4335
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/highlight/issue60589.txt
@@ -0,0 +1,30 @@
+This test verifies that control flow lighlighting correctly accounts for
+multi-name result parameters. In golang/go#60589, it did not.
+
+-- go.mod --
+module mod.com
+
+go 1.18
+
+-- p.go --
+package p
+
+func _() (foo int, bar, baz string) { //@ loc(func, "func"), loc(foo, "foo"), loc(fooint, "foo int"), loc(int, "int"), loc(bar, "bar"), loc(beforebaz, " baz"), loc(baz, "baz"), loc(barbazstring, "bar, baz string"), loc(beforestring, re`() string`), loc(string, "string")
+	return 0, "1", "2" //@ loc(return, `return 0, "1", "2"`), loc(l0, "0"), loc(l1, `"1"`), loc(l2, `"2"`)
+}
+
+// Assertions, expressed here to avoid clutter above.
+// Note that when the cursor is over the field type, there is some
+// (likely harmless) redundancy.
+
+//@ highlight(func, func, return)
+//@ highlight(foo, foo, l0)
+//@ highlight(int, fooint, int, l0)
+//@ highlight(bar, bar, l1)
+//@ highlight(beforebaz)
+//@ highlight(baz, baz, l2)
+//@ highlight(beforestring, baz, l2)
+//@ highlight(string, barbazstring, string, l1, l2)
+//@ highlight(l0, foo, l0)
+//@ highlight(l1, bar, l1)
+//@ highlight(l2, baz, l2)
diff --git a/gopls/internal/test/marker/testdata/highlight/issue65516.txt b/gopls/internal/test/marker/testdata/highlight/issue65516.txt
new file mode 100644
index 0000000..3fc3be2
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/highlight/issue65516.txt
@@ -0,0 +1,7 @@
+This test checks that gopls doesn't crash while highlighting functions with no
+body (golang/go#65516).
+
+-- p.go --
+package p
+
+func Foo() (int, string) //@highlight("int", "int"), highlight("func", "func")
diff --git a/gopls/internal/test/marker/testdata/hover/embed.txt b/gopls/internal/test/marker/testdata/hover/embed.txt
new file mode 100644
index 0000000..1dc3fcb
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/hover/embed.txt
@@ -0,0 +1,57 @@
+This test checks that hover reports accessible embedded fields
+(after the doc comment  and before the accessible methods).
+
+-- go.mod --
+module example.com
+
+go 1.18
+
+-- q/q.go --
+package q
+
+type Q struct {
+	One int
+	two string
+	q2[chan int]
+}
+
+type q2[T any] struct {
+	Three *T
+	four string
+}
+
+-- p.go --
+package p
+
+import "example.com/q"
+
+// doc
+type P struct {
+	q.Q
+}
+
+func (P) m() {}
+
+var p P //@hover("P", "P", P)
+
+-- @P --
+```go
+type P struct {
+	q.Q
+}
+```
+
+doc
+
+
+```go
+// Embedded fields:
+One   int       // through Q    
+Three *chan int // through Q.q2 
+```
+
+```go
+func (P) m()
+```
+
+[`p.P` on pkg.go.dev](https://pkg.go.dev/example.com#P)
diff --git a/gopls/internal/test/marker/testdata/hover/generics.txt b/gopls/internal/test/marker/testdata/hover/generics.txt
index da10425..76c258f 100644
--- a/gopls/internal/test/marker/testdata/hover/generics.txt
+++ b/gopls/internal/test/marker/testdata/hover/generics.txt
@@ -1,9 +1,10 @@
 This file contains tests for hovering over generic Go code.
 
-Requires go1.19+ for the new go/doc/comment package.
+Requires go1.20+ for the new go/doc/comment package, and a change in Go 1.20
+that affected the formatting of constraint interfaces.
 
 -- flags --
--min_go=go1.19
+-min_go=go1.20
 
 -- go.mod --
 // A go.mod is require for correct pkgsite links.
@@ -25,10 +26,8 @@
 	Q   int //@hover("Q", "Q", ValueQ)
 }
 
-// disabled - see issue #54822
-func F[P interface{ ~int | string }]() { // hover("P","P",Ptparam)
-	// disabled - see issue #54822
-	var _ P // hover("P","P",Pvar)
+func F[P interface{ ~int | string }]() { //@hover("P", "P", Ptparam)
+	var _ P //@hover("P","P",Pvar)
 }
 
 -- inferred.go --
@@ -41,7 +40,7 @@
 func _() {
 	_ = app[[]int]             //@hover("app", "app", appint)
 	_ = app[[]int, int]        //@hover("app", "app", appint)
-	_ = app[[]int]([]int{}, 0) //@hover("app", "app", appint)
+	_ = app[[]int]([]int{}, 0) //@hover("app", "app", appint), diag("[[]int]", re"unnecessary")
 	_ = app([]int{}, 0)        //@hover("app", "app", appint)
 }
 
@@ -76,3 +75,11 @@
 ```go
 type parameter T any
 ```
+-- @Ptparam --
+```go
+type parameter P interface{~int | string}
+```
+-- @Pvar --
+```go
+type parameter P interface{~int | string}
+```
diff --git a/gopls/internal/test/marker/testdata/hover/godef.txt b/gopls/internal/test/marker/testdata/hover/godef.txt
index 9a3af00..2d82ab0 100644
--- a/gopls/internal/test/marker/testdata/hover/godef.txt
+++ b/gopls/internal/test/marker/testdata/hover/godef.txt
@@ -114,11 +114,13 @@
 type Thing struct {
 	Member string //@loc(Member, "Member")
 }
+```
 
-func (Thing).Method(i int) string
-func (*Thing).Method2(i int, j int) (error, string)
-func (Thing).Method3()
-func (*Thing).private()
+```go
+func (t Thing) Method(i int) string
+func (t *Thing) Method2(i int, j int) (error, string)
+func (t Thing) Method3()
+func (t *Thing) private()
 ```
 
 [`a.Thing` on pkg.go.dev](https://pkg.go.dev/godef.test/a#Thing)
@@ -128,9 +130,19 @@
 	Thing
 	Value int
 }
+```
 
-func (*NextThing).Method3() int
-func (NextThing).another() string
+```go
+// Embedded fields:
+Member string // through Thing 
+```
+
+```go
+func (t Thing) Method(i int) string
+func (t *Thing) Method2(i int, j int) (error, string)
+func (n *NextThing) Method3() int
+func (n NextThing) another() string
+func (t *Thing) private()
 ```
 
 [`a.NextThing` on pkg.go.dev](https://pkg.go.dev/godef.test/a#NextThing)
diff --git a/gopls/internal/test/marker/testdata/hover/linkable.txt b/gopls/internal/test/marker/testdata/hover/linkable.txt
index 2664bd5..b77b9e8 100644
--- a/gopls/internal/test/marker/testdata/hover/linkable.txt
+++ b/gopls/internal/test/marker/testdata/hover/linkable.txt
@@ -83,6 +83,12 @@
 ```
 
 Local types should not be linkable, even if they are capitalized.
+
+
+```go
+// Embedded fields:
+Embed int // through E 
+```
 -- @Nested --
 ```go
 field Nested int
@@ -103,14 +109,21 @@
 		Nested int //@hover("Nested", "Nested", Nested)
 	}
 }
-
-func (T).M()
-func (T).m()
 ```
 
 T is in the package scope, and so should be linkable.
 
 
+```go
+// Embedded fields:
+Embed int // through E 
+```
+
+```go
+func (T) M()
+func (T) m()
+```
+
 [`p.T` on pkg.go.dev](https://pkg.go.dev/mod.com#T)
 -- @X --
 ```go
diff --git a/gopls/internal/test/marker/testdata/hover/linkable_generics.txt b/gopls/internal/test/marker/testdata/hover/linkable_generics.txt
index 0f9f0f0..1ea009e 100644
--- a/gopls/internal/test/marker/testdata/hover/linkable_generics.txt
+++ b/gopls/internal/test/marker/testdata/hover/linkable_generics.txt
@@ -66,8 +66,6 @@
 type GT[P any] struct {
 	F P //@hover("F", "F", F),hover("P", "P", FP)
 }
-
-func (GT[P]).M(p P)
 ```
 
 Hovering over type parameters should link to documentation.
@@ -75,6 +73,10 @@
 TODO(rfindley): should it? We should probably link to the type.
 
 
+```go
+func (GT[P]) M(p P)
+```
+
 [`generic.GT` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT)
 -- @GTP --
 ```go
@@ -85,8 +87,6 @@
 type GT[P any] struct {
 	F P //@hover("F", "F", F),hover("P", "P", FP)
 }
-
-func (GT[P]).M(p P)
 ```
 
 Hovering over type parameters should link to documentation.
@@ -94,6 +94,10 @@
 TODO(rfindley): should it? We should probably link to the type.
 
 
+```go
+func (GT[P]) M(p P)
+```
+
 [`generic.GT` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT)
 -- @M --
 ```go
@@ -135,8 +139,6 @@
 type GT[P any] struct {
 	F P //@hover("F", "F", F),hover("P", "P", FP)
 }
-
-func (generic.GT[P]).M(p P)
 ```
 
 Hovering over type parameters should link to documentation.
@@ -144,4 +146,8 @@
 TODO(rfindley): should it? We should probably link to the type.
 
 
+```go
+func (generic.GT[P]) M(p P)
+```
+
 [`generic.GT` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT)
diff --git a/gopls/internal/test/marker/testdata/hover/methods.txt b/gopls/internal/test/marker/testdata/hover/methods.txt
new file mode 100644
index 0000000..8af2249
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/hover/methods.txt
@@ -0,0 +1,71 @@
+This test checks the formatting of the list of accessible methods.
+
+Observe that:
+- interface methods that appear in the syntax are not repeated
+  in the method set of the type;
+- promoted methods of structs are shown;
+- receiver variables are correctly named;
+- receiver variables have a pointer type if appropriate;
+- only accessible methods are shown.
+
+-- go.mod --
+module example.com
+
+-- lib/lib.go --
+package lib
+
+type I interface {
+	A()
+	b()
+	J
+}
+
+type J interface { C() }
+
+type S struct { I }
+func (s S) A() {}
+func (s S) b() {}
+func (s *S) PA() {}
+func (s *S) pb() {}
+
+-- a/a.go --
+package a
+
+import "example.com/lib"
+
+var _ lib.I //@hover("I", "I", I)
+var _ lib.J //@hover("J", "J", J)
+var _ lib.S //@hover("S", "S", S)
+
+-- @I --
+```go
+type I interface {
+	A()
+	b()
+	J
+}
+```
+
+```go
+func (lib.J) C()
+```
+
+[`lib.I` on pkg.go.dev](https://pkg.go.dev/example.com/lib#I)
+-- @J --
+```go
+type J interface{ C() }
+```
+
+[`lib.J` on pkg.go.dev](https://pkg.go.dev/example.com/lib#J)
+-- @S --
+```go
+type S struct{ I }
+```
+
+```go
+func (s lib.S) A()
+func (lib.J) C()
+func (s *lib.S) PA()
+```
+
+[`lib.S` on pkg.go.dev](https://pkg.go.dev/example.com/lib#S)
diff --git a/gopls/internal/test/marker/testdata/rename/doclink.txt b/gopls/internal/test/marker/testdata/rename/doclink.txt
index 1461f6f..d4e9f96 100644
--- a/gopls/internal/test/marker/testdata/rename/doclink.txt
+++ b/gopls/internal/test/marker/testdata/rename/doclink.txt
@@ -1,7 +1,7 @@
 This test checks that doc links are also handled correctly (golang/go#64495).
 
 -- go.mod --
-module testdata
+module example.com
 
 go 1.21
 
@@ -35,7 +35,7 @@
 -- b/b.go --
 package b
 
-import aa "testdata/a" //@rename("aa", "a", pkgRename)
+import aa "example.com/a" //@rename("aa", "a", pkgRename)
 
 // FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.C] [aa.C.F] [aa.C.PF]
 // reference pointer type [*aa.D]
@@ -124,8 +124,8 @@
 +// FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.C] [aa.C.F] [aa.C.PFF]
 -- @pkgRename/b/b.go --
 @@ -3 +3 @@
--import aa "testdata/a" //@rename("aa", "a", pkgRename)
-+import "testdata/a" //@rename("aa", "a", pkgRename)
+-import aa "example.com/a" //@rename("aa", "a", pkgRename)
++import "example.com/a" //@rename("aa", "a", pkgRename)
 @@ -5,3 +5,3 @@
 -// FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.C] [aa.C.F] [aa.C.PF]
 -// reference pointer type [*aa.D]
diff --git a/gopls/internal/test/marker/testdata/rename/issue42134.txt b/gopls/internal/test/marker/testdata/rename/issue42134.txt
index 6a83762..05fee50 100644
--- a/gopls/internal/test/marker/testdata/rename/issue42134.txt
+++ b/gopls/internal/test/marker/testdata/rename/issue42134.txt
@@ -1,3 +1,5 @@
+Regression test for #42134,
+"rename fails to update doc comment for local variable of function type"
 
 -- 1.go --
 package issue42134
@@ -29,7 +31,7 @@
 	fmt.Println(minNumber) //@rename("minNumber", "res", minNumberTores)
 }
 
-func min(a, b int) int { return a }
+func min(a, b int) int { return a + b }
 -- @minNumberTores/2.go --
 @@ -6 +6 @@
 -	// minNumber is a min number.
diff --git a/gopls/internal/regtest/marker/testdata/rename/issue60752.txt b/gopls/internal/test/marker/testdata/rename/issue60752.txt
similarity index 100%
rename from gopls/internal/regtest/marker/testdata/rename/issue60752.txt
rename to gopls/internal/test/marker/testdata/rename/issue60752.txt
diff --git a/gopls/internal/test/marker/testdata/signature/issue63804.txt b/gopls/internal/test/marker/testdata/signature/issue63804.txt
index 4ed9529..b651833 100644
--- a/gopls/internal/test/marker/testdata/signature/issue63804.txt
+++ b/gopls/internal/test/marker/testdata/signature/issue63804.txt
@@ -4,7 +4,7 @@
 so the best we can assert is that there is no result.
 
 -- go.mod --
-module testdata
+module example.com
 go 1.18
 
 -- a/a.go --
diff --git a/gopls/internal/test/marker/testdata/stubmethods/basic.txt b/gopls/internal/test/marker/testdata/stubmethods/basic.txt
index 5f87d13..e4cfb6d0 100644
--- a/gopls/internal/test/marker/testdata/stubmethods/basic.txt
+++ b/gopls/internal/test/marker/testdata/stubmethods/basic.txt
@@ -1,4 +1,5 @@
 This test exercises basic 'stub methods' functionality.
+See basic_resolve.txt for the same test with resolve support.
 
 -- go.mod --
 module example.com
@@ -13,7 +14,7 @@
 -- @stub/a/a.go --
 @@ -5 +5,5 @@
 +// Error implements error.
-+func (C) Error() string {
++func (c C) Error() string {
 +	panic("unimplemented")
 +}
 +
diff --git a/gopls/internal/test/marker/testdata/stubmethods/basic_resolve.txt b/gopls/internal/test/marker/testdata/stubmethods/basic_resolve.txt
new file mode 100644
index 0000000..183b7d5
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/stubmethods/basic_resolve.txt
@@ -0,0 +1,31 @@
+This test exercises basic 'stub methods' functionality, with resolve support.
+See basic.txt for the same test without resolve support.
+
+-- capabilities.json --
+{
+	"textDocument": {
+		"codeAction": {
+			"dataSupport": true,
+			"resolveSupport": {
+				"properties": ["edit"]
+			}
+		}
+	}
+}
+-- go.mod --
+module example.com
+go 1.12
+
+-- a/a.go --
+package a
+
+type C int
+
+var _ error = C(0) //@suggestedfix(re"C.0.", re"missing method Error", stub)
+-- @stub/a/a.go --
+@@ -5 +5,5 @@
++// Error implements error.
++func (c C) Error() string {
++	panic("unimplemented")
++}
++
diff --git a/gopls/internal/test/marker/testdata/stubmethods/issue61693.txt b/gopls/internal/test/marker/testdata/stubmethods/issue61693.txt
index 40596da..387b494 100644
--- a/gopls/internal/test/marker/testdata/stubmethods/issue61693.txt
+++ b/gopls/internal/test/marker/testdata/stubmethods/issue61693.txt
@@ -20,7 +20,7 @@
 -- @stub/main.go --
 @@ -5 +5,5 @@
 +// Error implements error.
-+func (C) Error() string {
++func (c C) Error() string {
 +	panic("unimplemented")
 +}
 +
diff --git a/gopls/internal/test/marker/testdata/stubmethods/issue61830.txt b/gopls/internal/test/marker/testdata/stubmethods/issue61830.txt
index 0f23ffb..bf5bcc5 100644
--- a/gopls/internal/test/marker/testdata/stubmethods/issue61830.txt
+++ b/gopls/internal/test/marker/testdata/stubmethods/issue61830.txt
@@ -18,7 +18,7 @@
 -- @stub/p.go --
 @@ -13 +13,5 @@
 +// M implements I.
-+func (*A) M(io.Reader, B) {
++func (a *A) M(io.Reader, B) {
 +	panic("unimplemented")
 +}
 +
diff --git a/gopls/internal/test/marker/testdata/stubmethods/issue64078.txt b/gopls/internal/test/marker/testdata/stubmethods/issue64078.txt
new file mode 100644
index 0000000..50db6f2
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/stubmethods/issue64078.txt
@@ -0,0 +1,36 @@
+This test verifies that the named receiver is generated.
+
+-- p.go --
+package p
+
+type A struct{}
+
+func (aa *A) M1() {
+	panic("unimplemented")
+}
+
+type I interface {
+	M1()
+	M2(aa string)
+	M3(bb string)
+	M4() (aa string)
+}
+
+var _ I = &A{} //@suggestedfix(re"&A..", re"missing method M", stub)
+-- @stub/p.go --
+@@ -5 +5,15 @@
++// M2 implements I.
++func (*A) M2(aa string) {
++	panic("unimplemented")
++}
++
++// M3 implements I.
++func (aa *A) M3(bb string) {
++	panic("unimplemented")
++}
++
++// M4 implements I.
++func (*A) M4() (aa string) {
++	panic("unimplemented")
++}
++
diff --git a/gopls/internal/test/marker/testdata/stubmethods/issue64114.txt b/gopls/internal/test/marker/testdata/stubmethods/issue64114.txt
index bf4d875..35f6db7 100644
--- a/gopls/internal/test/marker/testdata/stubmethods/issue64114.txt
+++ b/gopls/internal/test/marker/testdata/stubmethods/issue64114.txt
@@ -27,11 +27,11 @@
 +
 +// RRRR implements WriteTest.
 +// Subtle: this method shadows the method (WriterTwoStruct).RRRR of WriteStruct.WriterTwoStruct.
-+func (*WriteStruct) RRRR() {
++func (w *WriteStruct) RRRR() {
 +	panic("unimplemented")
 +}
 +
 +// WWWW implements WriteTest.
-+func (*WriteStruct) WWWW() {
++func (w *WriteStruct) WWWW() {
 +	panic("unimplemented")
 +}
diff --git a/gopls/internal/test/marker/testdata/suggestedfix/issue65024.txt b/gopls/internal/test/marker/testdata/suggestedfix/issue65024.txt
new file mode 100644
index 0000000..afdfce9
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/suggestedfix/issue65024.txt
@@ -0,0 +1,78 @@
+Regression example.com for #65024, "incorrect package qualification when
+stubbing method in v2 module".
+
+The second test (a-a) ensures that we don't use path-based heuristics
+to guess the PkgName of an import.
+
+-- a/v2/go.mod --
+module example.com/a/v2
+go 1.18
+
+-- a/v2/a.go --
+package a
+
+type I interface { F() T }
+
+type T struct {}
+
+-- a/v2/b/b.go --
+package b
+
+import "example.com/a/v2"
+
+type B struct{}
+
+var _ a.I = &B{} //@ suggestedfix("&B{}", re"does not implement", out)
+
+// This line makes the diff tidier.
+
+-- @out/a/v2/b/b.go --
+@@ -7 +7,5 @@
++// F implements a.I.
++func (b *B) F() a.T {
++	panic("unimplemented")
++}
++
+@@ -10 +15 @@
+-
+-- a-a/v2/go.mod --
+// This module has a hyphenated name--how posh.
+// It won't do to use it as an identifier.
+// The correct name is the one in the package decl,
+// which in this case is not what the path heuristic would guess.
+module example.com/a-a/v2
+go 1.18
+
+-- a-a/v2/a.go --
+package a
+type I interface { F() T }
+type T struct {}
+
+-- a-a/v2/b/b.go --
+package b
+
+// Note: no existing import of a.
+
+type B struct{}
+
+var _ I = &B{} //@ suggestedfix("&B{}", re"does not implement", out2)
+
+// This line makes the diff tidier.
+
+-- a-a/v2/b/import-a-I.go --
+package b
+import "example.com/a-a/v2"
+type I = a.I
+
+-- @out2/a-a/v2/b/b.go --
+@@ -3 +3,2 @@
++import a "example.com/a-a/v2"
++
+@@ -7 +9,5 @@
++// F implements a.I.
++func (b *B) F() a.T {
++	panic("unimplemented")
++}
++
+@@ -10 +17 @@
+-
diff --git a/gopls/internal/test/marker/testdata/suggestedfix/stub.txt b/gopls/internal/test/marker/testdata/suggestedfix/stub.txt
index 514a293..e31494a 100644
--- a/gopls/internal/test/marker/testdata/suggestedfix/stub.txt
+++ b/gopls/internal/test/marker/testdata/suggestedfix/stub.txt
@@ -53,7 +53,7 @@
 @@ -12 +12,5 @@
 +
 +// WriteByte implements io.ByteWriter.
-+func (*byteWriter) WriteByte(c byte) error {
++func (b *byteWriter) WriteByte(c byte) error {
 +	panic("unimplemented")
 +}
 -- assign_multivars.go --
@@ -73,7 +73,7 @@
 @@ -13 +13,5 @@
 +
 +// WriteByte implements io.ByteWriter.
-+func (*multiByteWriter) WriteByte(c byte) error {
++func (m *multiByteWriter) WriteByte(c byte) error {
 +	panic("unimplemented")
 +}
 -- call_expr.go --
@@ -94,7 +94,7 @@
 @@ -14 +14,5 @@
 +
 +// Error implements error.
-+func (*callExpr) Error() string {
++func (c *callExpr) Error() string {
 +	panic("unimplemented")
 +}
 -- embedded.go --
@@ -116,22 +116,22 @@
 -- @embedded/embedded.go --
 @@ -12 +12,20 @@
 +// Len implements embeddedInterface.
-+func (*embeddedConcrete) Len() int {
++func (e *embeddedConcrete) Len() int {
 +	panic("unimplemented")
 +}
 +
 +// Less implements embeddedInterface.
-+func (*embeddedConcrete) Less(i int, j int) bool {
++func (e *embeddedConcrete) Less(i int, j int) bool {
 +	panic("unimplemented")
 +}
 +
 +// Read implements embeddedInterface.
-+func (*embeddedConcrete) Read(p []byte) (n int, err error) {
++func (e *embeddedConcrete) Read(p []byte) (n int, err error) {
 +	panic("unimplemented")
 +}
 +
 +// Swap implements embeddedInterface.
-+func (*embeddedConcrete) Swap(i int, j int) {
++func (e *embeddedConcrete) Swap(i int, j int) {
 +	panic("unimplemented")
 +}
 +
@@ -148,7 +148,7 @@
 @@ -9 +9,5 @@
 +
 +// Error implements error.
-+func (*customErr) Error() string {
++func (c *customErr) Error() string {
 +	panic("unimplemented")
 +}
 -- function_return.go --
@@ -167,7 +167,7 @@
 @@ -12 +12,5 @@
 +
 +// Close implements io.Closer.
-+func (closer) Close() error {
++func (c closer) Close() error {
 +	panic("unimplemented")
 +}
 -- generic_receiver.go --
@@ -187,7 +187,7 @@
 @@ -13 +13,5 @@
 +
 +// ReadFrom implements io.ReaderFrom.
-+func (*genReader[T, Y]) ReadFrom(r io.Reader) (n int64, err error) {
++func (g *genReader[T, Y]) ReadFrom(r io.Reader) (n int64, err error) {
 +	panic("unimplemented")
 +}
 -- ignored_imports.go --
@@ -213,7 +213,7 @@
 @@ -19 +19,5 @@
 +
 +// Reset implements zlib.Resetter.
-+func (*ignoredResetter) Reset(r Reader, dict []byte) error {
++func (i *ignoredResetter) Reset(r Reader, dict []byte) error {
 +	panic("unimplemented")
 +}
 -- issue2606.go --
@@ -227,7 +227,7 @@
 -- @issue2606/issue2606.go --
 @@ -7 +7,5 @@
 +// Error implements I.
-+func (C) Error() string {
++func (c C) Error() string {
 +	panic("unimplemented")
 +}
 +
@@ -247,7 +247,7 @@
 @@ -12 +12,5 @@
 +
 +// Read implements io.Reader.
-+func (*multiVar) Read(p []byte) (n int, err error) {
++func (m *multiVar) Read(p []byte) (n int, err error) {
 +	panic("unimplemented")
 +}
 -- pointer.go --
@@ -264,7 +264,7 @@
 @@ -10 +10,5 @@
 +
 +// ReadFrom implements io.ReaderFrom.
-+func (*pointerImpl) ReadFrom(r io.Reader) (n int64, err error) {
++func (p *pointerImpl) ReadFrom(r io.Reader) (n int64, err error) {
 +	panic("unimplemented")
 +}
 -- renamed_import.go --
@@ -283,7 +283,7 @@
 @@ -12 +12,5 @@
 +
 +// Reset implements zlib.Resetter.
-+func (*myIO) Reset(r myio.Reader, dict []byte) error {
++func (m *myIO) Reset(r myio.Reader, dict []byte) error {
 +	panic("unimplemented")
 +}
 -- renamed_import_iface.go --
@@ -307,7 +307,7 @@
 @@ -14 +16,5 @@
 +
 +// Get implements other.Interface.
-+func (*otherInterfaceImpl) Get(context.Context) *bytes.Buffer {
++func (o *otherInterfaceImpl) Get(context.Context) *bytes.Buffer {
 +	panic("unimplemented")
 +}
 -- stdlib.go --
@@ -324,7 +324,7 @@
 @@ -10 +10,5 @@
 +
 +// Write implements io.Writer.
-+func (writer) Write(p []byte) (n int, err error) {
++func (w writer) Write(p []byte) (n int, err error) {
 +	panic("unimplemented")
 +}
 -- typedecl_group.go --
@@ -354,12 +354,12 @@
 -- @typedecl_group/typedecl_group.go --
 @@ -18 +18,10 @@
 +// Close implements io.ReadCloser.
-+func (rdcloser) Close() error {
++func (r rdcloser) Close() error {
 +	panic("unimplemented")
 +}
 +
 +// Read implements io.ReadCloser.
-+func (rdcloser) Read(p []byte) (n int, err error) {
++func (r rdcloser) Read(p []byte) (n int, err error) {
 +	panic("unimplemented")
 +}
 +
diff --git a/gopls/internal/test/marker/testdata/suggestedfix/undeclaredfunc.txt b/gopls/internal/test/marker/testdata/suggestedfix/undeclaredfunc.txt
new file mode 100644
index 0000000..d54dcae
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/suggestedfix/undeclaredfunc.txt
@@ -0,0 +1,19 @@
+This test checks the quick fix for "undeclared: f" that declares the
+missing function. See #47558.
+
+TODO(adonovan): infer the result variables from the context (int, in this case).
+
+-- a.go --
+package a
+
+func _() int { return f(1, "") } //@suggestedfix(re"f.1", re"unde(fined|clared name): f", x)
+
+-- @x/a.go --
+@@ -3 +3 @@
+-func _() int { return f(1, "") } //@suggestedfix(re"f.1", re"unde(fined|clared name): f", x)
++func _() int { return f(1, "") }
+@@ -5 +5,4 @@
++func f(i int, s string) {
++	panic("unimplemented")
++} //@suggestedfix(re"f.1", re"unde(fined|clared name): f", x)
++
diff --git a/gopls/internal/util/bug/bug.go b/gopls/internal/util/bug/bug.go
index 7c290b0..e04b753 100644
--- a/gopls/internal/util/bug/bug.go
+++ b/gopls/internal/util/bug/bug.go
@@ -19,12 +19,15 @@
 	"sync"
 	"time"
 
-	"golang.org/x/telemetry/counter"
+	"golang.org/x/tools/gopls/internal/telemetry"
 )
 
 // PanicOnBugs controls whether to panic when bugs are reported.
 //
 // It may be set to true during testing.
+//
+// TODO(adonovan): should we make the default true, and
+// suppress it only in the product (gopls/main.go)?
 var PanicOnBugs = false
 
 var (
@@ -66,7 +69,7 @@
 }
 
 // BugReportCount is a telemetry counter that tracks # of bug reports.
-var BugReportCount = counter.NewStack("gopls/bug", 16)
+var BugReportCount = telemetry.NewStackCounter("gopls/bug", 16)
 
 func report(description string) {
 	_, file, line, ok := runtime.Caller(2) // all exported reporting functions call report directly
diff --git a/gopls/internal/util/slices/slices.go b/gopls/internal/util/slices/slices.go
index db53e1d..4c4fa4d 100644
--- a/gopls/internal/util/slices/slices.go
+++ b/gopls/internal/util/slices/slices.go
@@ -4,6 +4,14 @@
 
 package slices
 
+// Clone returns a copy of the slice.
+// The elements are copied using assignment, so this is a shallow clone.
+// TODO(rfindley): use go1.19 slices.Clone.
+func Clone[S ~[]E, E any](s S) S {
+	// The s[:0:0] preserves nil in case it matters.
+	return append(s[:0:0], s...)
+}
+
 // Contains reports whether x is present in slice.
 // TODO(adonovan): use go1.19 slices.Contains.
 func Contains[S ~[]E, E comparable](slice S, x E) bool {
@@ -35,7 +43,7 @@
 }
 
 // Concat returns a new slice concatenating the passed in slices.
-// TODO(rfindley): use go1.22 slices.Contains.
+// TODO(rfindley): use go1.22 slices.Concat.
 func Concat[S ~[]E, E any](slices ...S) S {
 	size := 0
 	for _, s := range slices {
@@ -65,3 +73,18 @@
 	}
 	return s
 }
+
+// Remove removes all values equal to elem from slice.
+//
+// The closest equivalent in the standard slices package is:
+//
+//	DeleteFunc(func(x T) bool { return x == elem })
+func Remove[T comparable](slice []T, elem T) []T {
+	out := slice[:0]
+	for _, v := range slice {
+		if v != elem {
+			out = append(out, v)
+		}
+	}
+	return out
+}
diff --git a/gopls/internal/util/typesutil/typesutil.go b/gopls/internal/util/typesutil/typesutil.go
index 137dbf3..3597b4b 100644
--- a/gopls/internal/util/typesutil/typesutil.go
+++ b/gopls/internal/util/typesutil/typesutil.go
@@ -21,3 +21,29 @@
 	pkgname, ok := obj.(*types.PkgName)
 	return pkgname, ok
 }
+
+// FileQualifier returns a [types.Qualifier] function that qualifies
+// imported symbols appropriately based on the import environment of a
+// given file.
+func FileQualifier(f *ast.File, pkg *types.Package, info *types.Info) types.Qualifier {
+	// Construct mapping of import paths to their defined or implicit names.
+	imports := make(map[*types.Package]string)
+	for _, imp := range f.Imports {
+		if pkgname, ok := ImportedPkgName(info, imp); ok {
+			imports[pkgname.Imported()] = pkgname.Name()
+		}
+	}
+	// Define qualifier to replace full package paths with names of the imports.
+	return func(p *types.Package) string {
+		if p == pkg {
+			return ""
+		}
+		if name, ok := imports[p]; ok {
+			if name == "." {
+				return ""
+			}
+			return name
+		}
+		return p.Name()
+	}
+}
diff --git a/gopls/internal/version/version.go b/gopls/internal/version/version.go
new file mode 100644
index 0000000..96f1819
--- /dev/null
+++ b/gopls/internal/version/version.go
@@ -0,0 +1,29 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package version manages the gopls version.
+//
+// The VersionOverride variable may be used to set the gopls version at link
+// time.
+package version
+
+import "runtime/debug"
+
+var VersionOverride = ""
+
+// Version returns the gopls version.
+//
+// By default, this is read from runtime/debug.ReadBuildInfo, but may be
+// overridden by the [VersionOverride] variable.
+func Version() string {
+	if VersionOverride != "" {
+		return VersionOverride
+	}
+	if info, ok := debug.ReadBuildInfo(); ok {
+		if info.Main.Version != "" {
+			return info.Main.Version
+		}
+	}
+	return "(unknown)"
+}
diff --git a/gopls/internal/vulncheck/scan/command.go b/gopls/internal/vulncheck/scan/command.go
index f8d84e3..1f53d8b 100644
--- a/gopls/internal/vulncheck/scan/command.go
+++ b/gopls/internal/vulncheck/scan/command.go
@@ -18,7 +18,7 @@
 	"time"
 
 	"golang.org/x/sync/errgroup"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/vulncheck"
 	"golang.org/x/tools/gopls/internal/vulncheck/govulncheck"
 	"golang.org/x/tools/gopls/internal/vulncheck/osv"
diff --git a/gopls/internal/vulncheck/vulntest/db.go b/gopls/internal/vulncheck/vulntest/db.go
index 7b637ab..659d2f1 100644
--- a/gopls/internal/vulncheck/vulntest/db.go
+++ b/gopls/internal/vulncheck/vulntest/db.go
@@ -19,7 +19,7 @@
 	"strings"
 	"time"
 
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/vulncheck/osv"
 	"golang.org/x/tools/txtar"
 )
diff --git a/gopls/internal/vulncheck/vulntest/db_test.go b/gopls/internal/vulncheck/vulntest/db_test.go
index bfab8ca..2228124 100644
--- a/gopls/internal/vulncheck/vulntest/db_test.go
+++ b/gopls/internal/vulncheck/vulntest/db_test.go
@@ -17,7 +17,7 @@
 	"time"
 
 	"github.com/google/go-cmp/cmp"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/vulncheck/osv"
 )
 
diff --git a/gopls/internal/work/completion.go b/gopls/internal/work/completion.go
index f8aa20d..194721e 100644
--- a/gopls/internal/work/completion.go
+++ b/gopls/internal/work/completion.go
@@ -14,9 +14,9 @@
 	"sort"
 	"strings"
 
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 )
 
diff --git a/gopls/internal/work/diagnostics.go b/gopls/internal/work/diagnostics.go
index 70147d6..f1acd4d 100644
--- a/gopls/internal/work/diagnostics.go
+++ b/gopls/internal/work/diagnostics.go
@@ -11,9 +11,9 @@
 	"path/filepath"
 
 	"golang.org/x/mod/modfile"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 )
 
diff --git a/gopls/internal/work/format.go b/gopls/internal/work/format.go
index 8ef81f3..162bc8c 100644
--- a/gopls/internal/work/format.go
+++ b/gopls/internal/work/format.go
@@ -8,9 +8,9 @@
 	"context"
 
 	"golang.org/x/mod/modfile"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/diff"
 	"golang.org/x/tools/internal/event"
 )
diff --git a/gopls/internal/work/hover.go b/gopls/internal/work/hover.go
index 66c40a8..c59c147 100644
--- a/gopls/internal/work/hover.go
+++ b/gopls/internal/work/hover.go
@@ -10,9 +10,9 @@
 	"fmt"
 
 	"golang.org/x/mod/modfile"
+	"golang.org/x/tools/gopls/internal/cache"
 	"golang.org/x/tools/gopls/internal/file"
-	"golang.org/x/tools/gopls/internal/lsp/cache"
-	"golang.org/x/tools/gopls/internal/lsp/protocol"
+	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/internal/event"
 )
 
diff --git a/gopls/main.go b/gopls/main.go
index 8163266..e3fb386 100644
--- a/gopls/main.go
+++ b/gopls/main.go
@@ -17,14 +17,20 @@
 	"context"
 	"os"
 
-	"golang.org/x/telemetry/counter"
 	"golang.org/x/tools/gopls/internal/cmd"
 	"golang.org/x/tools/gopls/internal/hooks"
+	"golang.org/x/tools/gopls/internal/telemetry"
+	versionpkg "golang.org/x/tools/gopls/internal/version"
 	"golang.org/x/tools/internal/tool"
 )
 
+var version = "" // if set by the linker, overrides the gopls version
+
 func main() {
-	counter.Open() // Enable telemetry counter writing.
+	versionpkg.VersionOverride = version
+
+	telemetry.CounterOpen()
+	telemetry.StartCrashMonitor()
 	ctx := context.Background()
-	tool.Main(ctx, cmd.New("gopls", "", nil, hooks.Options), os.Args[1:])
+	tool.Main(ctx, cmd.New(hooks.Options), os.Args[1:])
 }
diff --git a/internal/aliases/aliases.go b/internal/aliases/aliases.go
new file mode 100644
index 0000000..f89112c
--- /dev/null
+++ b/internal/aliases/aliases.go
@@ -0,0 +1,28 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package aliases
+
+import (
+	"go/token"
+	"go/types"
+)
+
+// Package aliases defines backward compatible shims
+// for the types.Alias type representation added in 1.22.
+// This defines placeholders for x/tools until 1.26.
+
+// NewAlias creates a new TypeName in Package pkg that
+// is an alias for the type rhs.
+//
+// When GoVersion>=1.22 and GODEBUG=gotypesalias=1,
+// the Type() of the return value is a *types.Alias.
+func NewAlias(pos token.Pos, pkg *types.Package, name string, rhs types.Type) *types.TypeName {
+	if enabled() {
+		tname := types.NewTypeName(pos, pkg, name, nil)
+		newAlias(tname, rhs)
+		return tname
+	}
+	return types.NewTypeName(pos, pkg, name, rhs)
+}
diff --git a/internal/aliases/aliases_go121.go b/internal/aliases/aliases_go121.go
new file mode 100644
index 0000000..1872b56
--- /dev/null
+++ b/internal/aliases/aliases_go121.go
@@ -0,0 +1,30 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !go1.22
+// +build !go1.22
+
+package aliases
+
+import (
+	"go/types"
+)
+
+// Alias is a placeholder for a go/types.Alias for <=1.21.
+// It will never be created by go/types.
+type Alias struct{}
+
+func (*Alias) String() string { panic("unreachable") }
+
+func (*Alias) Underlying() types.Type { panic("unreachable") }
+
+func (*Alias) Obj() *types.TypeName { panic("unreachable") }
+
+// Unalias returns the type t for go <=1.21.
+func Unalias(t types.Type) types.Type { return t }
+
+// Always false for go <=1.21. Ignores GODEBUG.
+func enabled() bool { return false }
+
+func newAlias(name *types.TypeName, rhs types.Type) *Alias { panic("unreachable") }
diff --git a/internal/aliases/aliases_go122.go b/internal/aliases/aliases_go122.go
new file mode 100644
index 0000000..8b92116
--- /dev/null
+++ b/internal/aliases/aliases_go122.go
@@ -0,0 +1,72 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.22
+// +build go1.22
+
+package aliases
+
+import (
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"go/types"
+	"os"
+	"strings"
+	"sync"
+)
+
+// Alias is an alias of types.Alias.
+type Alias = types.Alias
+
+// Unalias is a wrapper of types.Unalias.
+func Unalias(t types.Type) types.Type { return types.Unalias(t) }
+
+// newAlias is an internal alias around types.NewAlias.
+// Direct usage is discouraged as the moment.
+// Try to use NewAlias instead.
+func newAlias(tname *types.TypeName, rhs types.Type) *Alias {
+	a := types.NewAlias(tname, rhs)
+	// TODO(go.dev/issue/65455): Remove kludgy workaround to set a.actual as a side-effect.
+	Unalias(a)
+	return a
+}
+
+// enabled returns true when types.Aliases are enabled.
+func enabled() bool {
+	// Use the gotypesalias value in GODEBUG if set.
+	godebug := os.Getenv("GODEBUG")
+	value := -1 // last set value.
+	for _, f := range strings.Split(godebug, ",") {
+		switch f {
+		case "gotypesalias=1":
+			value = 1
+		case "gotypesalias=0":
+			value = 0
+		}
+	}
+	switch value {
+	case 0:
+		return false
+	case 1:
+		return true
+	default:
+		return aliasesDefault()
+	}
+}
+
+// aliasesDefault reports if aliases are enabled by default.
+func aliasesDefault() bool {
+	// Dynamically check if Aliases will be produced from go/types.
+	aliasesDefaultOnce.Do(func() {
+		fset := token.NewFileSet()
+		f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", 0)
+		pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil)
+		_, gotypesaliasDefault = pkg.Scope().Lookup("A").Type().(*types.Alias)
+	})
+	return gotypesaliasDefault
+}
+
+var gotypesaliasDefault bool
+var aliasesDefaultOnce sync.Once
diff --git a/internal/aliases/aliases_test.go b/internal/aliases/aliases_test.go
new file mode 100644
index 0000000..fc4efb2
--- /dev/null
+++ b/internal/aliases/aliases_test.go
@@ -0,0 +1,75 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package aliases_test
+
+import (
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"go/types"
+	"os"
+	"testing"
+
+	"golang.org/x/tools/internal/aliases"
+	"golang.org/x/tools/internal/testenv"
+)
+
+// Assert that Obj exists on Alias.
+var _ func(*aliases.Alias) *types.TypeName = (*aliases.Alias).Obj
+
+// TestNewAlias tests that alias.NewAlias creates an alias of a type
+// whose underlying and Unaliased type is *Named.
+// When gotypesalias=1 and GoVersion >= 1.22, the type will
+// be an *aliases.Alias.
+func TestNewAlias(t *testing.T) {
+	const source = `
+	package P
+
+	type Named int
+	`
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "hello.go", source, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var conf types.Config
+	pkg, err := conf.Check("P", fset, []*ast.File{f}, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expr := `*Named`
+	tv, err := types.Eval(fset, pkg, 0, expr)
+	if err != nil {
+		t.Fatalf("Eval(%s) failed: %v", expr, err)
+	}
+
+	for _, godebug := range []string{"", "gotypesalias=1"} {
+		t.Run(godebug, func(t *testing.T) {
+			saved := os.Getenv("GODEBUG")
+			defer os.Setenv("GODEBUG", saved)
+			os.Setenv("GODEBUG", godebug) // non parallel.
+
+			A := aliases.NewAlias(token.NoPos, pkg, "A", tv.Type)
+			if got, want := A.Name(), "A"; got != want {
+				t.Errorf("Expected A.Name()==%q. got %q", want, got)
+			}
+
+			if got, want := A.Type().Underlying(), tv.Type; got != want {
+				t.Errorf("Expected A.Type().Underlying()==%q. got %q", want, got)
+			}
+			if got, want := aliases.Unalias(A.Type()), tv.Type; got != want {
+				t.Errorf("Expected Unalias(A)==%q. got %q", want, got)
+			}
+
+			if testenv.Go1Point() >= 22 && godebug == "gotypesalias=1" {
+				if _, ok := A.Type().(*aliases.Alias); !ok {
+					t.Errorf("Expected A.Type() to be a types.Alias(). got %q", A.Type())
+				}
+			}
+		})
+	}
+}
diff --git a/internal/analysisinternal/analysis.go b/internal/analysisinternal/analysis.go
index 2b29168..b24a0fb 100644
--- a/internal/analysisinternal/analysis.go
+++ b/internal/analysisinternal/analysis.go
@@ -151,6 +151,10 @@
 				},
 			})
 		}
+		if t.Variadic() {
+			last := params[len(params)-1]
+			last.Type = &ast.Ellipsis{Elt: last.Type.(*ast.ArrayType).Elt}
+		}
 		var returns []*ast.Field
 		for i := 0; i < t.Results().Len(); i++ {
 			r := TypeExpr(f, pkg, t.Results().At(i).Type())
diff --git a/internal/apidiff/apidiff.go b/internal/apidiff/apidiff.go
index 873ee85..087e112 100644
--- a/internal/apidiff/apidiff.go
+++ b/internal/apidiff/apidiff.go
@@ -19,6 +19,8 @@
 	"go/constant"
 	"go/token"
 	"go/types"
+
+	"golang.org/x/tools/internal/aliases"
 )
 
 // Changes reports on the differences between the APIs of the old and new packages.
@@ -206,7 +208,7 @@
 // Since these can change without affecting compatibility, we don't want users to
 // be distracted by them, so we remove them.
 func removeNamesFromSignature(t types.Type) types.Type {
-	sig, ok := t.(*types.Signature)
+	sig, ok := aliases.Unalias(t).(*types.Signature)
 	if !ok {
 		return t
 	}
diff --git a/internal/apidiff/compatibility.go b/internal/apidiff/compatibility.go
index 2e32748..0d2d2b3 100644
--- a/internal/apidiff/compatibility.go
+++ b/internal/apidiff/compatibility.go
@@ -8,9 +8,13 @@
 	"fmt"
 	"go/types"
 	"reflect"
+
+	"golang.org/x/tools/internal/aliases"
 )
 
 func (d *differ) checkCompatible(otn *types.TypeName, old, new types.Type) {
+	old = aliases.Unalias(old)
+	new = aliases.Unalias(new)
 	switch old := old.(type) {
 	case *types.Interface:
 		if new, ok := new.(*types.Interface); ok {
@@ -268,7 +272,7 @@
 		return
 	}
 	// Interface method sets are checked in checkCompatibleInterface.
-	if _, ok := old.Underlying().(*types.Interface); ok {
+	if types.IsInterface(old) {
 		return
 	}
 
@@ -287,7 +291,7 @@
 	oldMethodSet := exportedMethods(oldt)
 	newMethodSet := exportedMethods(newt)
 	msname := otn.Name()
-	if _, ok := oldt.(*types.Pointer); ok {
+	if _, ok := aliases.Unalias(oldt).(*types.Pointer); ok {
 		msname = "*" + msname
 	}
 	for name, oldMethod := range oldMethodSet {
@@ -349,9 +353,9 @@
 }
 
 func receiverNamedType(method types.Object) *types.Named {
-	switch t := receiverType(method).(type) {
+	switch t := aliases.Unalias(receiverType(method)).(type) {
 	case *types.Pointer:
-		return t.Elem().(*types.Named)
+		return aliases.Unalias(t.Elem()).(*types.Named)
 	case *types.Named:
 		return t
 	default:
@@ -360,6 +364,6 @@
 }
 
 func hasPointerReceiver(method types.Object) bool {
-	_, ok := receiverType(method).(*types.Pointer)
+	_, ok := aliases.Unalias(receiverType(method)).(*types.Pointer)
 	return ok
 }
diff --git a/internal/apidiff/correspondence.go b/internal/apidiff/correspondence.go
index 0d7b4c5..dd2f517 100644
--- a/internal/apidiff/correspondence.go
+++ b/internal/apidiff/correspondence.go
@@ -7,6 +7,8 @@
 import (
 	"go/types"
 	"sort"
+
+	"golang.org/x/tools/internal/aliases"
 )
 
 // Two types are correspond if they are identical except for defined types,
@@ -31,6 +33,8 @@
 // Compare this to the implementation of go/types.Identical.
 func (d *differ) corr(old, new types.Type, p *ifacePair) bool {
 	// Structure copied from types.Identical.
+	old = aliases.Unalias(old)
+	new = aliases.Unalias(new)
 	switch old := old.(type) {
 	case *types.Basic:
 		return types.Identical(old, new)
diff --git a/internal/diff/lcs/git.sh b/internal/diff/lcs/git.sh
index 6856f84..b25ba4a 100644
--- a/internal/diff/lcs/git.sh
+++ b/internal/diff/lcs/git.sh
@@ -14,9 +14,9 @@
 
 # WARNING: This script will install the latest version of $file
 # The largest real source file in the x/tools repo.
-# file=internal/lsp/source/completion/completion.go
-# file=internal/lsp/source/diagnostics.go
-file=internal/lsp/protocol/tsprotocol.go
+# file=internal/golang/completion/completion.go
+# file=internal/golang/diagnostics.go
+file=internal/protocol/tsprotocol.go
 
 tmp=$(mktemp -d)
 git log $file |
diff --git a/internal/gcimporter/iimport.go b/internal/gcimporter/iimport.go
index 9bde15e..9fffa9a 100644
--- a/internal/gcimporter/iimport.go
+++ b/internal/gcimporter/iimport.go
@@ -224,6 +224,7 @@
 
 	// Gather the relevant packages from the manifest.
 	items := make([]GetPackagesItem, r.uint64())
+	uniquePkgPaths := make(map[string]bool)
 	for i := range items {
 		pkgPathOff := r.uint64()
 		pkgPath := p.stringAt(pkgPathOff)
@@ -248,6 +249,12 @@
 		}
 
 		items[i].nameIndex = nameIndex
+
+		uniquePkgPaths[pkgPath] = true
+	}
+	// Debugging #63822; hypothesis: there are duplicate PkgPaths.
+	if len(uniquePkgPaths) != len(items) {
+		reportf("found duplicate PkgPaths while reading export data manifest: %v", items)
 	}
 
 	// Request packages all at once from the client,
diff --git a/internal/gopathwalk/walk.go b/internal/gopathwalk/walk.go
index 52f74e6..8361515 100644
--- a/internal/gopathwalk/walk.go
+++ b/internal/gopathwalk/walk.go
@@ -9,11 +9,13 @@
 import (
 	"bufio"
 	"bytes"
+	"io"
 	"io/fs"
-	"log"
 	"os"
 	"path/filepath"
+	"runtime"
 	"strings"
+	"sync"
 	"time"
 )
 
@@ -21,8 +23,13 @@
 type Options struct {
 	// If Logf is non-nil, debug logging is enabled through this function.
 	Logf func(format string, args ...interface{})
+
 	// Search module caches. Also disables legacy goimports ignore rules.
 	ModulesEnabled bool
+
+	// Maximum number of concurrent calls to user-provided callbacks,
+	// or 0 for GOMAXPROCS.
+	Concurrency int
 }
 
 // RootType indicates the type of a Root.
@@ -43,19 +50,28 @@
 	Type RootType
 }
 
-// Walk walks Go source directories ($GOROOT, $GOPATH, etc) to find packages.
+// Walk concurrently walks Go source directories ($GOROOT, $GOPATH, etc) to find packages.
+//
 // For each package found, add will be called with the absolute
 // paths of the containing source directory and the package directory.
+//
+// Unlike filepath.WalkDir, Walk follows symbolic links
+// (while guarding against cycles).
 func Walk(roots []Root, add func(root Root, dir string), opts Options) {
 	WalkSkip(roots, add, func(Root, string) bool { return false }, opts)
 }
 
-// WalkSkip walks Go source directories ($GOROOT, $GOPATH, etc) to find packages.
+// WalkSkip concurrently walks Go source directories ($GOROOT, $GOPATH, etc) to
+// find packages.
+//
 // For each package found, add will be called with the absolute
 // paths of the containing source directory and the package directory.
 // For each directory that will be scanned, skip will be called
 // with the absolute paths of the containing source directory and the directory.
 // If skip returns false on a directory it will be processed.
+//
+// Unlike filepath.WalkDir, WalkSkip follows symbolic links
+// (while guarding against cycles).
 func WalkSkip(roots []Root, add func(root Root, dir string), skip func(root Root, dir string) bool, opts Options) {
 	for _, root := range roots {
 		walkDir(root, add, skip, opts)
@@ -64,45 +80,51 @@
 
 // walkDir creates a walker and starts fastwalk with this walker.
 func walkDir(root Root, add func(Root, string), skip func(root Root, dir string) bool, opts Options) {
+	if opts.Logf == nil {
+		opts.Logf = func(format string, args ...interface{}) {}
+	}
 	if _, err := os.Stat(root.Path); os.IsNotExist(err) {
-		if opts.Logf != nil {
-			opts.Logf("skipping nonexistent directory: %v", root.Path)
-		}
+		opts.Logf("skipping nonexistent directory: %v", root.Path)
 		return
 	}
 	start := time.Now()
-	if opts.Logf != nil {
-		opts.Logf("scanning %s", root.Path)
-	}
+	opts.Logf("scanning %s", root.Path)
 
+	concurrency := opts.Concurrency
+	if concurrency == 0 {
+		// The walk be either CPU-bound or I/O-bound, depending on what the
+		// caller-supplied add function does and the details of the user's platform
+		// and machine. Rather than trying to fine-tune the concurrency level for a
+		// specific environment, we default to GOMAXPROCS: it is likely to be a good
+		// choice for a CPU-bound add function, and if it is instead I/O-bound, then
+		// dealing with I/O saturation is arguably the job of the kernel and/or
+		// runtime. (Oversaturating I/O seems unlikely to harm performance as badly
+		// as failing to saturate would.)
+		concurrency = runtime.GOMAXPROCS(0)
+	}
 	w := &walker{
-		root:  root,
-		add:   add,
-		skip:  skip,
-		opts:  opts,
-		added: make(map[string]bool),
+		root: root,
+		add:  add,
+		skip: skip,
+		opts: opts,
+		sem:  make(chan struct{}, concurrency),
 	}
 	w.init()
 
-	// Add a trailing path separator to cause filepath.WalkDir to traverse symlinks.
+	w.sem <- struct{}{}
 	path := root.Path
-	if len(path) == 0 {
-		path = "." + string(filepath.Separator)
-	} else if !os.IsPathSeparator(path[len(path)-1]) {
-		path = path + string(filepath.Separator)
+	if path == "" {
+		path = "."
 	}
+	if fi, err := os.Lstat(path); err == nil {
+		w.walk(path, nil, fs.FileInfoToDirEntry(fi))
+	} else {
+		w.opts.Logf("scanning directory %v: %v", root.Path, err)
+	}
+	<-w.sem
+	w.walking.Wait()
 
-	if err := filepath.WalkDir(path, w.walk); err != nil {
-		logf := opts.Logf
-		if logf == nil {
-			logf = log.Printf
-		}
-		logf("scanning directory %v: %v", root.Path, err)
-	}
-
-	if opts.Logf != nil {
-		opts.Logf("scanned %s in %v", root.Path, time.Since(start))
-	}
+	opts.Logf("scanned %s in %v", root.Path, time.Since(start))
 }
 
 // walker is the callback for fastwalk.Walk.
@@ -112,10 +134,18 @@
 	skip func(Root, string) bool // The callback that will be invoked for every dir. dir is skipped if it returns true.
 	opts Options                 // Options passed to Walk by the user.
 
-	pathSymlinks []os.FileInfo
-	ignoredDirs  []string
+	walking     sync.WaitGroup
+	sem         chan struct{} // Channel of semaphore tokens; send to acquire, receive to release.
+	ignoredDirs []string
 
-	added map[string]bool
+	added sync.Map // map[string]bool
+}
+
+// A symlinkList is a linked list of os.FileInfos for parent directories
+// reached via symlinks.
+type symlinkList struct {
+	info os.FileInfo
+	prev *symlinkList
 }
 
 // init initializes the walker based on its Options
@@ -132,9 +162,7 @@
 	for _, p := range ignoredPaths {
 		full := filepath.Join(w.root.Path, p)
 		w.ignoredDirs = append(w.ignoredDirs, full)
-		if w.opts.Logf != nil {
-			w.opts.Logf("Directory added to ignore list: %s", full)
-		}
+		w.opts.Logf("Directory added to ignore list: %s", full)
 	}
 }
 
@@ -144,12 +172,10 @@
 func (w *walker) getIgnoredDirs(path string) []string {
 	file := filepath.Join(path, ".goimportsignore")
 	slurp, err := os.ReadFile(file)
-	if w.opts.Logf != nil {
-		if err != nil {
-			w.opts.Logf("%v", err)
-		} else {
-			w.opts.Logf("Read %s", file)
-		}
+	if err != nil {
+		w.opts.Logf("%v", err)
+	} else {
+		w.opts.Logf("Read %s", file)
 	}
 	if err != nil {
 		return nil
@@ -183,63 +209,22 @@
 
 // walk walks through the given path.
 //
-// Errors are logged if w.opts.Logf is non-nil, but otherwise ignored:
-// walk returns only nil or fs.SkipDir.
-func (w *walker) walk(path string, d fs.DirEntry, err error) error {
-	if err != nil {
-		// We have no way to report errors back through Walk or WalkSkip,
-		// so just log and ignore them.
-		if w.opts.Logf != nil {
-			w.opts.Logf("%v", err)
-		}
-		if d == nil {
-			// Nothing more to do: the error prevents us from knowing
-			// what path even represents.
-			return nil
-		}
-	}
-
-	if d.Type().IsRegular() {
-		if !strings.HasSuffix(path, ".go") {
-			return nil
-		}
-
-		dir := filepath.Dir(path)
-		if dir == w.root.Path && (w.root.Type == RootGOROOT || w.root.Type == RootGOPATH) {
-			// Doesn't make sense to have regular files
-			// directly in your $GOPATH/src or $GOROOT/src.
-			return nil
-		}
-
-		if !w.added[dir] {
-			w.add(w.root, dir)
-			w.added[dir] = true
-		}
-		return nil
-	}
-
-	if d.IsDir() {
-		base := filepath.Base(path)
-		if base == "" || base[0] == '.' || base[0] == '_' ||
-			base == "testdata" ||
-			(w.root.Type == RootGOROOT && w.opts.ModulesEnabled && base == "vendor") ||
-			(!w.opts.ModulesEnabled && base == "node_modules") {
-			return fs.SkipDir
-		}
-		if w.shouldSkipDir(path) {
-			return fs.SkipDir
-		}
-		return nil
-	}
-
+// Errors are logged if w.opts.Logf is non-nil, but otherwise ignored.
+func (w *walker) walk(path string, pathSymlinks *symlinkList, d fs.DirEntry) {
 	if d.Type()&os.ModeSymlink != 0 {
+		// Walk the symlink's target rather than the symlink itself.
+		//
+		// (Note that os.Stat, unlike the lower-lever os.Readlink,
+		// follows arbitrarily many layers of symlinks, so it will eventually
+		// reach either a non-symlink or a nonexistent target.)
+		//
 		// TODO(bcmills): 'go list all' itself ignores symlinks within GOROOT/src
 		// and GOPATH/src. Do we really need to traverse them here? If so, why?
 
 		fi, err := os.Stat(path)
-		if err != nil || !fi.IsDir() {
-			// Not a directory. Just walk the file (or broken link) and be done.
-			return w.walk(path, fs.FileInfoToDirEntry(fi), err)
+		if err != nil {
+			w.opts.Logf("%v", err)
+			return
 		}
 
 		// Avoid walking symlink cycles: if we have already followed a symlink to
@@ -249,83 +234,104 @@
 		// the number of extra stat calls we make if we *don't* encounter a cycle.
 		// Since we don't actually expect to encounter symlink cycles in practice,
 		// this seems like the right tradeoff.
-		for _, parent := range w.pathSymlinks {
-			if os.SameFile(fi, parent) {
-				return nil
+		for parent := pathSymlinks; parent != nil; parent = parent.prev {
+			if os.SameFile(fi, parent.info) {
+				return
 			}
 		}
 
-		w.pathSymlinks = append(w.pathSymlinks, fi)
-		defer func() {
-			w.pathSymlinks = w.pathSymlinks[:len(w.pathSymlinks)-1]
-		}()
+		pathSymlinks = &symlinkList{
+			info: fi,
+			prev: pathSymlinks,
+		}
+		d = fs.FileInfoToDirEntry(fi)
+	}
 
-		// On some platforms the OS (or the Go os package) sometimes fails to
-		// resolve directory symlinks before a trailing slash
-		// (even though POSIX requires it to do so).
-		//
-		// On macOS that failure may be caused by a known libc/kernel bug;
-		// see https://go.dev/issue/59586.
-		//
-		// On Windows before Go 1.21, it may be caused by a bug in
-		// os.Lstat (fixed in https://go.dev/cl/463177).
-		//
-		// Since we need to handle this explicitly on broken platforms anyway,
-		// it is simplest to just always do that and not rely on POSIX pathname
-		// resolution to walk the directory (such as by calling WalkDir with
-		// a trailing slash appended to the path).
-		//
-		// Instead, we make a sequence of walk calls — directly and through
-		// recursive calls to filepath.WalkDir — simulating what WalkDir would do
-		// if the symlink were a regular directory.
-
-		// First we call walk on the path as a directory
-		// (instead of a symlink).
-		err = w.walk(path, fs.FileInfoToDirEntry(fi), nil)
-		if err == fs.SkipDir {
-			return nil
-		} else if err != nil {
-			// This should be impossible, but handle it anyway in case
-			// walk is changed to return other errors.
-			return err
+	if d.Type().IsRegular() {
+		if !strings.HasSuffix(path, ".go") {
+			return
 		}
 
-		// Now read the directory and walk its entries.
-		ents, err := os.ReadDir(path)
+		dir := filepath.Dir(path)
+		if dir == w.root.Path && (w.root.Type == RootGOROOT || w.root.Type == RootGOPATH) {
+			// Doesn't make sense to have regular files
+			// directly in your $GOPATH/src or $GOROOT/src.
+			//
+			// TODO(bcmills): there are many levels of directory within
+			// RootModuleCache where this also wouldn't make sense,
+			// Can we generalize this to any directory without a corresponding
+			// import path?
+			return
+		}
+
+		if _, dup := w.added.LoadOrStore(dir, true); !dup {
+			w.add(w.root, dir)
+		}
+	}
+
+	if !d.IsDir() {
+		return
+	}
+
+	base := filepath.Base(path)
+	if base == "" || base[0] == '.' || base[0] == '_' ||
+		base == "testdata" ||
+		(w.root.Type == RootGOROOT && w.opts.ModulesEnabled && base == "vendor") ||
+		(!w.opts.ModulesEnabled && base == "node_modules") ||
+		w.shouldSkipDir(path) {
+		return
+	}
+
+	// Read the directory and walk its entries.
+
+	f, err := os.Open(path)
+	if err != nil {
+		w.opts.Logf("%v", err)
+		return
+	}
+	defer f.Close()
+
+	for {
+		// We impose an arbitrary limit on the number of ReadDir results per
+		// directory to limit the amount of memory consumed for stale or upcoming
+		// directory entries. The limit trades off CPU (number of syscalls to read
+		// the whole directory) against RAM (reachable directory entries other than
+		// the one currently being processed).
+		//
+		// Since we process the directories recursively, we will end up maintaining
+		// a slice of entries for each level of the directory tree.
+		// (Compare https://go.dev/issue/36197.)
+		ents, err := f.ReadDir(1024)
 		if err != nil {
-			// Report the ReadDir error, as filepath.WalkDir would do.
-			err = w.walk(path, fs.FileInfoToDirEntry(fi), err)
-			if err == fs.SkipDir {
-				return nil
-			} else if err != nil {
-				return err // Again, should be impossible.
+			if err != io.EOF {
+				w.opts.Logf("%v", err)
 			}
-			// Fall through and iterate over whatever entries we did manage to get.
+			break
 		}
 
 		for _, d := range ents {
 			nextPath := filepath.Join(path, d.Name())
 			if d.IsDir() {
-				// We want to walk the whole directory tree rooted at nextPath,
-				// not just the single entry for the directory.
-				err := filepath.WalkDir(nextPath, w.walk)
-				if err != nil && w.opts.Logf != nil {
-					w.opts.Logf("%v", err)
-				}
-			} else {
-				err := w.walk(nextPath, d, nil)
-				if err == fs.SkipDir {
-					// Skip the rest of the entries in the parent directory of nextPath
-					// (that is, path itself).
-					break
-				} else if err != nil {
-					return err // Again, should be impossible.
+				select {
+				case w.sem <- struct{}{}:
+					// Got a new semaphore token, so we can traverse the directory concurrently.
+					d := d
+					w.walking.Add(1)
+					go func() {
+						defer func() {
+							<-w.sem
+							w.walking.Done()
+						}()
+						w.walk(nextPath, pathSymlinks, d)
+					}()
+					continue
+
+				default:
+					// No tokens available, so traverse serially.
 				}
 			}
-		}
-		return nil
-	}
 
-	// Not a file, regular directory, or symlink; skip.
-	return nil
+			w.walk(nextPath, pathSymlinks, d)
+		}
+	}
 }
diff --git a/internal/gopathwalk/walk_test.go b/internal/gopathwalk/walk_test.go
index 51719db..8028f81 100644
--- a/internal/gopathwalk/walk_test.go
+++ b/internal/gopathwalk/walk_test.go
@@ -37,17 +37,19 @@
 		t.Fatal(err)
 	}
 
-	pkgs := []string{}
+	pkgc := make(chan []string, 1)
+	pkgc <- nil
 	add := func(root Root, dir string) {
 		rel, err := filepath.Rel(filepath.Join(root.Path, "src"), dir)
 		if err != nil {
 			t.Error(err)
 		}
-		pkgs = append(pkgs, filepath.ToSlash(rel))
+		pkgc <- append(<-pkgc, filepath.ToSlash(rel))
 	}
 
 	Walk([]Root{{Path: gopath, Type: RootGOPATH}}, add, Options{Logf: t.Logf})
 
+	pkgs := <-pkgc
 	sort.Strings(pkgs)
 	t.Logf("Found packages:\n\t%s", strings.Join(pkgs, "\n\t"))
 
diff --git a/internal/imports/fix.go b/internal/imports/fix.go
index dd369c0..6a18f63 100644
--- a/internal/imports/fix.go
+++ b/internal/imports/fix.go
@@ -13,6 +13,7 @@
 	"go/build"
 	"go/parser"
 	"go/token"
+	"go/types"
 	"io/fs"
 	"io/ioutil"
 	"os"
@@ -700,20 +701,21 @@
 	return result, nil
 }
 
-func PrimeCache(ctx context.Context, env *ProcessEnv) error {
+func PrimeCache(ctx context.Context, resolver Resolver) error {
 	// Fully scan the disk for directories, but don't actually read any Go files.
 	callback := &scanCallback{
-		rootFound: func(gopathwalk.Root) bool {
-			return true
+		rootFound: func(root gopathwalk.Root) bool {
+			// See getCandidatePkgs: walking GOROOT is apparently expensive and
+			// unnecessary.
+			return root.Type != gopathwalk.RootGOROOT
 		},
 		dirFound: func(pkg *pkg) bool {
 			return false
 		},
-		packageNameLoaded: func(pkg *pkg) bool {
-			return false
-		},
+		// packageNameLoaded and exportsLoaded must never be called.
 	}
-	return getCandidatePkgs(ctx, callback, "", "", env)
+
+	return resolver.scan(ctx, callback)
 }
 
 func candidateImportName(pkg *pkg) string {
@@ -827,16 +829,45 @@
 	return getCandidatePkgs(ctx, callback, filename, filePkg, env)
 }
 
-var requiredGoEnvVars = []string{"GO111MODULE", "GOFLAGS", "GOINSECURE", "GOMOD", "GOMODCACHE", "GONOPROXY", "GONOSUMDB", "GOPATH", "GOPROXY", "GOROOT", "GOSUMDB", "GOWORK"}
+// TODO(rfindley): we should depend on GOOS and GOARCH, to provide accurate
+// imports when doing cross-platform development.
+var requiredGoEnvVars = []string{
+	"GO111MODULE",
+	"GOFLAGS",
+	"GOINSECURE",
+	"GOMOD",
+	"GOMODCACHE",
+	"GONOPROXY",
+	"GONOSUMDB",
+	"GOPATH",
+	"GOPROXY",
+	"GOROOT",
+	"GOSUMDB",
+	"GOWORK",
+}
 
 // ProcessEnv contains environment variables and settings that affect the use of
 // the go command, the go/build package, etc.
+//
+// ...a ProcessEnv *also* overwrites its Env along with derived state in the
+// form of the resolver. And because it is lazily initialized, an env may just
+// be broken and unusable, but there is no way for the caller to detect that:
+// all queries will just fail.
+//
+// TODO(rfindley): refactor this package so that this type (perhaps renamed to
+// just Env or Config) is an immutable configuration struct, to be exchanged
+// for an initialized object via a constructor that returns an error. Perhaps
+// the signature should be `func NewResolver(*Env) (*Resolver, error)`, where
+// resolver is a concrete type used for resolving imports. Via this
+// refactoring, we can avoid the need to call ProcessEnv.init and
+// ProcessEnv.GoEnv everywhere, and implicitly fix all the places where this
+// these are misused. Also, we'd delegate the caller the decision of how to
+// handle a broken environment.
 type ProcessEnv struct {
 	GocmdRunner *gocommand.Runner
 
 	BuildFlags []string
 	ModFlag    string
-	ModFile    string
 
 	// SkipPathInScan returns true if the path should be skipped from scans of
 	// the RootCurrentModule root type. The function argument is a clean,
@@ -846,7 +877,7 @@
 	// Env overrides the OS environment, and can be used to specify
 	// GOPROXY, GO111MODULE, etc. PATH cannot be set here, because
 	// exec.Command will not honor it.
-	// Specifying all of RequiredGoEnvVars avoids a call to `go env`.
+	// Specifying all of requiredGoEnvVars avoids a call to `go env`.
 	Env map[string]string
 
 	WorkingDir string
@@ -854,9 +885,17 @@
 	// If Logf is non-nil, debug logging is enabled through this function.
 	Logf func(format string, args ...interface{})
 
-	initialized bool
+	// If set, ModCache holds a shared cache of directory info to use across
+	// multiple ProcessEnvs.
+	ModCache *DirInfoCache
 
-	resolver Resolver
+	initialized bool // see TODO above
+
+	// resolver and resolverErr are lazily evaluated (see GetResolver).
+	// This is unclean, but see the big TODO in the docstring for ProcessEnv
+	// above: for now, we can't be sure that the ProcessEnv is fully initialized.
+	resolver    Resolver
+	resolverErr error
 }
 
 func (e *ProcessEnv) goEnv() (map[string]string, error) {
@@ -936,20 +975,31 @@
 }
 
 func (e *ProcessEnv) GetResolver() (Resolver, error) {
-	if e.resolver != nil {
-		return e.resolver, nil
-	}
 	if err := e.init(); err != nil {
 		return nil, err
 	}
-	if len(e.Env["GOMOD"]) == 0 && len(e.Env["GOWORK"]) == 0 {
-		e.resolver = newGopathResolver(e)
-		return e.resolver, nil
+
+	if e.resolver == nil && e.resolverErr == nil {
+		// TODO(rfindley): we should only use a gopathResolver here if the working
+		// directory is actually *in* GOPATH. (I seem to recall an open gopls issue
+		// for this behavior, but I can't find it).
+		//
+		// For gopls, we can optionally explicitly choose a resolver type, since we
+		// already know the view type.
+		if len(e.Env["GOMOD"]) == 0 && len(e.Env["GOWORK"]) == 0 {
+			e.resolver = newGopathResolver(e)
+		} else {
+			e.resolver, e.resolverErr = newModuleResolver(e, e.ModCache)
+		}
 	}
-	e.resolver = newModuleResolver(e)
-	return e.resolver, nil
+
+	return e.resolver, e.resolverErr
 }
 
+// buildContext returns the build.Context to use for matching files.
+//
+// TODO(rfindley): support dynamic GOOS, GOARCH here, when doing cross-platform
+// development.
 func (e *ProcessEnv) buildContext() (*build.Context, error) {
 	ctx := build.Default
 	goenv, err := e.goEnv()
@@ -1029,15 +1079,23 @@
 type Resolver interface {
 	// loadPackageNames loads the package names in importPaths.
 	loadPackageNames(importPaths []string, srcDir string) (map[string]string, error)
+
 	// scan works with callback to search for packages. See scanCallback for details.
 	scan(ctx context.Context, callback *scanCallback) error
+
 	// loadExports returns the set of exported symbols in the package at dir.
 	// loadExports may be called concurrently.
 	loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error)
+
 	// scoreImportPath returns the relevance for an import path.
 	scoreImportPath(ctx context.Context, path string) float64
 
-	ClearForNewScan()
+	// ClearForNewScan returns a new Resolver based on the receiver that has
+	// cleared its internal caches of directory contents.
+	//
+	// The new resolver should be primed and then set via
+	// [ProcessEnv.UpdateResolver].
+	ClearForNewScan() Resolver
 }
 
 // A scanCallback controls a call to scan and receives its results.
@@ -1120,7 +1178,7 @@
 		go func(pkgName string, symbols map[string]bool) {
 			defer wg.Done()
 
-			found, err := findImport(ctx, pass, found[pkgName], pkgName, symbols, filename)
+			found, err := findImport(ctx, pass, found[pkgName], pkgName, symbols)
 
 			if err != nil {
 				firstErrOnce.Do(func() {
@@ -1151,6 +1209,17 @@
 	}()
 
 	for result := range results {
+		// Don't offer completions that would shadow predeclared
+		// names, such as github.com/coreos/etcd/error.
+		if types.Universe.Lookup(result.pkg.name) != nil { // predeclared
+			// Ideally we would skip this candidate only
+			// if the predeclared name is actually
+			// referenced by the file, but that's a lot
+			// trickier to compute and would still create
+			// an import that is likely to surprise the
+			// user before long.
+			continue
+		}
 		pass.addCandidate(result.imp, result.pkg)
 	}
 	return firstErr
@@ -1193,31 +1262,22 @@
 type gopathResolver struct {
 	env      *ProcessEnv
 	walked   bool
-	cache    *dirInfoCache
+	cache    *DirInfoCache
 	scanSema chan struct{} // scanSema prevents concurrent scans.
 }
 
 func newGopathResolver(env *ProcessEnv) *gopathResolver {
 	r := &gopathResolver{
-		env: env,
-		cache: &dirInfoCache{
-			dirs:      map[string]*directoryPackageInfo{},
-			listeners: map[*int]cacheListener{},
-		},
+		env:      env,
+		cache:    NewDirInfoCache(),
 		scanSema: make(chan struct{}, 1),
 	}
 	r.scanSema <- struct{}{}
 	return r
 }
 
-func (r *gopathResolver) ClearForNewScan() {
-	<-r.scanSema
-	r.cache = &dirInfoCache{
-		dirs:      map[string]*directoryPackageInfo{},
-		listeners: map[*int]cacheListener{},
-	}
-	r.walked = false
-	r.scanSema <- struct{}{}
+func (r *gopathResolver) ClearForNewScan() Resolver {
+	return newGopathResolver(r.env)
 }
 
 func (r *gopathResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) {
@@ -1538,7 +1598,7 @@
 
 // findImport searches for a package with the given symbols.
 // If no package is found, findImport returns ("", false, nil)
-func findImport(ctx context.Context, pass *pass, candidates []pkgDistance, pkgName string, symbols map[string]bool, filename string) (*pkg, error) {
+func findImport(ctx context.Context, pass *pass, candidates []pkgDistance, pkgName string, symbols map[string]bool) (*pkg, error) {
 	// Sort the candidates by their import package length,
 	// assuming that shorter package names are better than long
 	// ones.  Note that this sorts by the de-vendored name, so
diff --git a/internal/imports/imports.go b/internal/imports/imports.go
index 58e637b..6604075 100644
--- a/internal/imports/imports.go
+++ b/internal/imports/imports.go
@@ -236,7 +236,7 @@
 			src = src[:len(src)-len("}\n")]
 			// Gofmt has also indented the function body one level.
 			// Remove that indent.
-			src = bytes.Replace(src, []byte("\n\t"), []byte("\n"), -1)
+			src = bytes.ReplaceAll(src, []byte("\n\t"), []byte("\n"))
 			return matchSpace(orig, src)
 		}
 		return file, adjust, nil
diff --git a/internal/imports/mod.go b/internal/imports/mod.go
index 5f4d435..3d0f38f 100644
--- a/internal/imports/mod.go
+++ b/internal/imports/mod.go
@@ -23,49 +23,88 @@
 	"golang.org/x/tools/internal/gopathwalk"
 )
 
-// ModuleResolver implements resolver for modules using the go command as little
-// as feasible.
+// Notes(rfindley): ModuleResolver appears to be heavily optimized for scanning
+// as fast as possible, which is desirable for a call to goimports from the
+// command line, but it doesn't work as well for gopls, where it suffers from
+// slow startup (golang/go#44863) and intermittent hanging (golang/go#59216),
+// both caused by populating the cache, albeit in slightly different ways.
+//
+// A high level list of TODOs:
+//  - Optimize the scan itself, as there is some redundancy statting and
+//    reading go.mod files.
+//  - Invert the relationship between ProcessEnv and Resolver (see the
+//    docstring of ProcessEnv).
+//  - Make it easier to use an external resolver implementation.
+//
+// Smaller TODOs are annotated in the code below.
+
+// ModuleResolver implements the Resolver interface for a workspace using
+// modules.
+//
+// A goal of the ModuleResolver is to invoke the Go command as little as
+// possible. To this end, it runs the Go command only for listing module
+// information (i.e. `go list -m -e -json ...`). Package scanning, the process
+// of loading package information for the modules, is implemented internally
+// via the scan method.
+//
+// It has two types of state: the state derived from the go command, which
+// is populated by init, and the state derived from scans, which is populated
+// via scan. A root is considered scanned if it has been walked to discover
+// directories. However, if the scan did not require additional information
+// from the directory (such as package name or exports), the directory
+// information itself may be partially populated. It will be lazily filled in
+// as needed by scans, using the scanCallback.
 type ModuleResolver struct {
-	env            *ProcessEnv
-	moduleCacheDir string
-	dummyVendorMod *gocommand.ModuleJSON // If vendoring is enabled, the pseudo-module that represents the /vendor directory.
-	roots          []gopathwalk.Root
-	scanSema       chan struct{} // scanSema prevents concurrent scans and guards scannedRoots.
-	scannedRoots   map[gopathwalk.Root]bool
+	env *ProcessEnv
 
-	initialized   bool
-	mains         []*gocommand.ModuleJSON
-	mainByDir     map[string]*gocommand.ModuleJSON
-	modsByModPath []*gocommand.ModuleJSON // All modules, ordered by # of path components in module Path...
-	modsByDir     []*gocommand.ModuleJSON // ...or number of path components in their Dir.
+	// Module state, populated during construction
+	dummyVendorMod *gocommand.ModuleJSON            // if vendoring is enabled, a pseudo-module to represent the /vendor directory
+	moduleCacheDir string                           // GOMODCACHE, inferred from GOPATH if unset
+	roots          []gopathwalk.Root                // roots to scan, in approximate order of importance
+	mains          []*gocommand.ModuleJSON          // main modules
+	mainByDir      map[string]*gocommand.ModuleJSON // module information by dir, to join with roots
+	modsByModPath  []*gocommand.ModuleJSON          // all modules, ordered by # of path components in their module path
+	modsByDir      []*gocommand.ModuleJSON          // ...or by the number of path components in their Dir.
 
-	// moduleCacheCache stores information about the module cache.
-	moduleCacheCache *dirInfoCache
-	otherCache       *dirInfoCache
+	// Scanning state, populated by scan
+
+	// scanSema prevents concurrent scans, and guards scannedRoots and the cache
+	// fields below (though the caches themselves are concurrency safe).
+	// Receive to acquire, send to release.
+	scanSema     chan struct{}
+	scannedRoots map[gopathwalk.Root]bool // if true, root has been walked
+
+	// Caches of directory info, populated by scans and scan callbacks
+	//
+	// moduleCacheCache stores cached information about roots in the module
+	// cache, which are immutable and therefore do not need to be invalidated.
+	//
+	// otherCache stores information about all other roots (even GOROOT), which
+	// may change.
+	moduleCacheCache *DirInfoCache
+	otherCache       *DirInfoCache
 }
 
-func newModuleResolver(e *ProcessEnv) *ModuleResolver {
+// newModuleResolver returns a new module-aware goimports resolver.
+//
+// Note: use caution when modifying this constructor: changes must also be
+// reflected in ModuleResolver.ClearForNewScan.
+func newModuleResolver(e *ProcessEnv, moduleCacheCache *DirInfoCache) (*ModuleResolver, error) {
 	r := &ModuleResolver{
 		env:      e,
 		scanSema: make(chan struct{}, 1),
 	}
-	r.scanSema <- struct{}{}
-	return r
-}
-
-func (r *ModuleResolver) init() error {
-	if r.initialized {
-		return nil
-	}
+	r.scanSema <- struct{}{} // release
 
 	goenv, err := r.env.goEnv()
 	if err != nil {
-		return err
+		return nil, err
 	}
+
+	// TODO(rfindley): can we refactor to share logic with r.env.invokeGo?
 	inv := gocommand.Invocation{
 		BuildFlags: r.env.BuildFlags,
 		ModFlag:    r.env.ModFlag,
-		ModFile:    r.env.ModFile,
 		Env:        r.env.env(),
 		Logf:       r.env.Logf,
 		WorkingDir: r.env.WorkingDir,
@@ -77,9 +116,12 @@
 	// Module vendor directories are ignored in workspace mode:
 	// https://go.googlesource.com/proposal/+/master/design/45713-workspace.md
 	if len(r.env.Env["GOWORK"]) == 0 {
+		// TODO(rfindley): VendorEnabled runs the go command to get GOFLAGS, but
+		// they should be available from the ProcessEnv. Can we avoid the redundant
+		// invocation?
 		vendorEnabled, mainModVendor, err = gocommand.VendorEnabled(context.TODO(), inv, r.env.GocmdRunner)
 		if err != nil {
-			return err
+			return nil, err
 		}
 	}
 
@@ -100,19 +142,14 @@
 		// GO111MODULE=on. Other errors are fatal.
 		if err != nil {
 			if errMsg := err.Error(); !strings.Contains(errMsg, "working directory is not part of a module") && !strings.Contains(errMsg, "go.mod file not found") {
-				return err
+				return nil, err
 			}
 		}
 	}
 
-	if gmc := r.env.Env["GOMODCACHE"]; gmc != "" {
-		r.moduleCacheDir = gmc
-	} else {
-		gopaths := filepath.SplitList(goenv["GOPATH"])
-		if len(gopaths) == 0 {
-			return fmt.Errorf("empty GOPATH")
-		}
-		r.moduleCacheDir = filepath.Join(gopaths[0], "/pkg/mod")
+	r.moduleCacheDir = gomodcacheForEnv(goenv)
+	if r.moduleCacheDir == "" {
+		return nil, fmt.Errorf("cannot resolve GOMODCACHE")
 	}
 
 	sort.Slice(r.modsByModPath, func(i, j int) bool {
@@ -141,7 +178,11 @@
 	} else {
 		addDep := func(mod *gocommand.ModuleJSON) {
 			if mod.Replace == nil {
-				// This is redundant with the cache, but we'll skip it cheaply enough.
+				// This is redundant with the cache, but we'll skip it cheaply enough
+				// when we encounter it in the module cache scan.
+				//
+				// Including it at a lower index in r.roots than the module cache dir
+				// helps prioritize matches from within existing dependencies.
 				r.roots = append(r.roots, gopathwalk.Root{Path: mod.Dir, Type: gopathwalk.RootModuleCache})
 			} else {
 				r.roots = append(r.roots, gopathwalk.Root{Path: mod.Dir, Type: gopathwalk.RootOther})
@@ -158,24 +199,40 @@
 				addDep(mod)
 			}
 		}
+		// If provided, share the moduleCacheCache.
+		//
+		// TODO(rfindley): The module cache is immutable. However, the loaded
+		// exports do depend on GOOS and GOARCH. Fortunately, the
+		// ProcessEnv.buildContext does not adjust these from build.DefaultContext
+		// (even though it should). So for now, this is OK to share, but we need to
+		// add logic for handling GOOS/GOARCH.
+		r.moduleCacheCache = moduleCacheCache
 		r.roots = append(r.roots, gopathwalk.Root{Path: r.moduleCacheDir, Type: gopathwalk.RootModuleCache})
 	}
 
 	r.scannedRoots = map[gopathwalk.Root]bool{}
 	if r.moduleCacheCache == nil {
-		r.moduleCacheCache = &dirInfoCache{
-			dirs:      map[string]*directoryPackageInfo{},
-			listeners: map[*int]cacheListener{},
-		}
+		r.moduleCacheCache = NewDirInfoCache()
 	}
-	if r.otherCache == nil {
-		r.otherCache = &dirInfoCache{
-			dirs:      map[string]*directoryPackageInfo{},
-			listeners: map[*int]cacheListener{},
-		}
+	r.otherCache = NewDirInfoCache()
+	return r, nil
+}
+
+// gomodcacheForEnv returns the GOMODCACHE value to use based on the given env
+// map, which must have GOMODCACHE and GOPATH populated.
+//
+// TODO(rfindley): this is defensive refactoring.
+//  1. Is this even relevant anymore? Can't we just read GOMODCACHE.
+//  2. Use this to separate module cache scanning from other scanning.
+func gomodcacheForEnv(goenv map[string]string) string {
+	if gmc := goenv["GOMODCACHE"]; gmc != "" {
+		return gmc
 	}
-	r.initialized = true
-	return nil
+	gopaths := filepath.SplitList(goenv["GOPATH"])
+	if len(gopaths) == 0 {
+		return ""
+	}
+	return filepath.Join(gopaths[0], "/pkg/mod")
 }
 
 func (r *ModuleResolver) initAllMods() error {
@@ -206,30 +263,82 @@
 	return nil
 }
 
-func (r *ModuleResolver) ClearForNewScan() {
-	<-r.scanSema
-	r.scannedRoots = map[gopathwalk.Root]bool{}
-	r.otherCache = &dirInfoCache{
-		dirs:      map[string]*directoryPackageInfo{},
-		listeners: map[*int]cacheListener{},
-	}
-	r.scanSema <- struct{}{}
-}
+// ClearForNewScan invalidates the last scan.
+//
+// It preserves the set of roots, but forgets about the set of directories.
+// Though it forgets the set of module cache directories, it remembers their
+// contents, since they are assumed to be immutable.
+func (r *ModuleResolver) ClearForNewScan() Resolver {
+	<-r.scanSema // acquire r, to guard scannedRoots
+	r2 := &ModuleResolver{
+		env:            r.env,
+		dummyVendorMod: r.dummyVendorMod,
+		moduleCacheDir: r.moduleCacheDir,
+		roots:          r.roots,
+		mains:          r.mains,
+		mainByDir:      r.mainByDir,
+		modsByModPath:  r.modsByModPath,
 
-func (r *ModuleResolver) ClearForNewMod() {
-	<-r.scanSema
-	*r = ModuleResolver{
-		env:              r.env,
+		scanSema:         make(chan struct{}, 1),
+		scannedRoots:     make(map[gopathwalk.Root]bool),
+		otherCache:       NewDirInfoCache(),
 		moduleCacheCache: r.moduleCacheCache,
-		otherCache:       r.otherCache,
-		scanSema:         r.scanSema,
 	}
-	r.init()
-	r.scanSema <- struct{}{}
+	r2.scanSema <- struct{}{} // r2 must start released
+	// Invalidate root scans. We don't need to invalidate module cache roots,
+	// because they are immutable.
+	// (We don't support a use case where GOMODCACHE is cleaned in the middle of
+	// e.g. a gopls session: the user must restart gopls to get accurate
+	// imports.)
+	//
+	// Scanning for new directories in GOMODCACHE should be handled elsewhere,
+	// via a call to ScanModuleCache.
+	for _, root := range r.roots {
+		if root.Type == gopathwalk.RootModuleCache && r.scannedRoots[root] {
+			r2.scannedRoots[root] = true
+		}
+	}
+	r.scanSema <- struct{}{} // release r
+	return r2
 }
 
-// findPackage returns the module and directory that contains the package at
-// the given import path, or returns nil, "" if no module is in scope.
+// ClearModuleInfo invalidates resolver state that depends on go.mod file
+// contents (essentially, the output of go list -m -json ...).
+//
+// Notably, it does not forget directory contents, which are reset
+// asynchronously via ClearForNewScan.
+//
+// If the ProcessEnv is a GOPATH environment, ClearModuleInfo is a no op.
+//
+// TODO(rfindley): move this to a new env.go, consolidating ProcessEnv methods.
+func (e *ProcessEnv) ClearModuleInfo() {
+	if r, ok := e.resolver.(*ModuleResolver); ok {
+		resolver, resolverErr := newModuleResolver(e, e.ModCache)
+		if resolverErr == nil {
+			<-r.scanSema // acquire (guards caches)
+			resolver.moduleCacheCache = r.moduleCacheCache
+			resolver.otherCache = r.otherCache
+			r.scanSema <- struct{}{} // release
+		}
+		e.resolver = resolver
+		e.resolverErr = resolverErr
+	}
+}
+
+// UpdateResolver sets the resolver for the ProcessEnv to use in imports
+// operations. Only for use with the result of [Resolver.ClearForNewScan].
+//
+// TODO(rfindley): this awkward API is a result of the (arguably) inverted
+// relationship between configuration and state described in the doc comment
+// for [ProcessEnv].
+func (e *ProcessEnv) UpdateResolver(r Resolver) {
+	e.resolver = r
+	e.resolverErr = nil
+}
+
+// findPackage returns the module and directory from within the main modules
+// and their dependencies that contains the package at the given import path,
+// or returns nil, "" if no module is in scope.
 func (r *ModuleResolver) findPackage(importPath string) (*gocommand.ModuleJSON, string) {
 	// This can't find packages in the stdlib, but that's harmless for all
 	// the existing code paths.
@@ -295,10 +404,6 @@
 	}
 }
 
-func (r *ModuleResolver) cacheKeys() []string {
-	return append(r.moduleCacheCache.Keys(), r.otherCache.Keys()...)
-}
-
 // cachePackageName caches the package name for a dir already in the cache.
 func (r *ModuleResolver) cachePackageName(info directoryPackageInfo) (string, error) {
 	if info.rootType == gopathwalk.RootModuleCache {
@@ -367,15 +472,15 @@
 	return modDir != mod.Dir
 }
 
-func (r *ModuleResolver) modInfo(dir string) (modDir string, modName string) {
-	readModName := func(modFile string) string {
-		modBytes, err := os.ReadFile(modFile)
-		if err != nil {
-			return ""
-		}
-		return modulePath(modBytes)
+func readModName(modFile string) string {
+	modBytes, err := os.ReadFile(modFile)
+	if err != nil {
+		return ""
 	}
+	return modulePath(modBytes)
+}
 
+func (r *ModuleResolver) modInfo(dir string) (modDir, modName string) {
 	if r.dirInModuleCache(dir) {
 		if matches := modCacheRegexp.FindStringSubmatch(dir); len(matches) == 3 {
 			index := strings.Index(dir, matches[1]+"@"+matches[2])
@@ -409,11 +514,9 @@
 }
 
 func (r *ModuleResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) {
-	if err := r.init(); err != nil {
-		return nil, err
-	}
 	names := map[string]string{}
 	for _, path := range importPaths {
+		// TODO(rfindley): shouldn't this use the dirInfoCache?
 		_, packageDir := r.findPackage(path)
 		if packageDir == "" {
 			continue
@@ -431,10 +534,6 @@
 	ctx, done := event.Start(ctx, "imports.ModuleResolver.scan")
 	defer done()
 
-	if err := r.init(); err != nil {
-		return err
-	}
-
 	processDir := func(info directoryPackageInfo) {
 		// Skip this directory if we were not able to get the package information successfully.
 		if scanned, err := info.reachedStatus(directoryScanned); !scanned || err != nil {
@@ -444,18 +543,18 @@
 		if err != nil {
 			return
 		}
-
 		if !callback.dirFound(pkg) {
 			return
 		}
+
 		pkg.packageName, err = r.cachePackageName(info)
 		if err != nil {
 			return
 		}
-
 		if !callback.packageNameLoaded(pkg) {
 			return
 		}
+
 		_, exports, err := r.loadExports(ctx, pkg, false)
 		if err != nil {
 			return
@@ -494,7 +593,6 @@
 		return packageScanned
 	}
 
-	// Add anything new to the cache, and process it if we're still listening.
 	add := func(root gopathwalk.Root, dir string) {
 		r.cacheStore(r.scanDirForPackage(root, dir))
 	}
@@ -509,9 +607,9 @@
 		select {
 		case <-ctx.Done():
 			return
-		case <-r.scanSema:
+		case <-r.scanSema: // acquire
 		}
-		defer func() { r.scanSema <- struct{}{} }()
+		defer func() { r.scanSema <- struct{}{} }() // release
 		// We have the lock on r.scannedRoots, and no other scans can run.
 		for _, root := range roots {
 			if ctx.Err() != nil {
@@ -613,9 +711,6 @@
 }
 
 func (r *ModuleResolver) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error) {
-	if err := r.init(); err != nil {
-		return "", nil, err
-	}
 	if info, ok := r.cacheLoad(pkg.dir); ok && !includeTest {
 		return r.cacheExports(ctx, r.env, info)
 	}
diff --git a/internal/imports/mod_cache.go b/internal/imports/mod_cache.go
index 45690ab..cfc5465 100644
--- a/internal/imports/mod_cache.go
+++ b/internal/imports/mod_cache.go
@@ -7,8 +7,12 @@
 import (
 	"context"
 	"fmt"
+	"path"
+	"path/filepath"
+	"strings"
 	"sync"
 
+	"golang.org/x/mod/module"
 	"golang.org/x/tools/internal/gopathwalk"
 )
 
@@ -39,6 +43,8 @@
 	exportsLoaded
 )
 
+// directoryPackageInfo holds (possibly incomplete) information about packages
+// contained in a given directory.
 type directoryPackageInfo struct {
 	// status indicates the extent to which this struct has been filled in.
 	status directoryPackageStatus
@@ -63,7 +69,10 @@
 	packageName string // the package name, as declared in the source.
 
 	// Set when status >= exportsLoaded.
-
+	// TODO(rfindley): it's hard to see this, but exports depend implicitly on
+	// the default build context GOOS and GOARCH.
+	//
+	// We can make this explicit, and key exports by GOOS, GOARCH.
 	exports []string
 }
 
@@ -79,7 +88,7 @@
 	return true, nil
 }
 
-// dirInfoCache is a concurrency safe map for storing information about
+// DirInfoCache is a concurrency-safe map for storing information about
 // directories that may contain packages.
 //
 // The information in this cache is built incrementally. Entries are initialized in scan.
@@ -92,21 +101,26 @@
 // The information in the cache is not expected to change for the cache's
 // lifetime, so there is no protection against competing writes. Users should
 // take care not to hold the cache across changes to the underlying files.
-//
-// TODO(suzmue): consider other concurrency strategies and data structures (RWLocks, sync.Map, etc)
-type dirInfoCache struct {
+type DirInfoCache struct {
 	mu sync.Mutex
 	// dirs stores information about packages in directories, keyed by absolute path.
 	dirs      map[string]*directoryPackageInfo
 	listeners map[*int]cacheListener
 }
 
+func NewDirInfoCache() *DirInfoCache {
+	return &DirInfoCache{
+		dirs:      make(map[string]*directoryPackageInfo),
+		listeners: make(map[*int]cacheListener),
+	}
+}
+
 type cacheListener func(directoryPackageInfo)
 
 // ScanAndListen calls listener on all the items in the cache, and on anything
 // newly added. The returned stop function waits for all in-flight callbacks to
 // finish and blocks new ones.
-func (d *dirInfoCache) ScanAndListen(ctx context.Context, listener cacheListener) func() {
+func (d *DirInfoCache) ScanAndListen(ctx context.Context, listener cacheListener) func() {
 	ctx, cancel := context.WithCancel(ctx)
 
 	// Flushing out all the callbacks is tricky without knowing how many there
@@ -162,8 +176,10 @@
 }
 
 // Store stores the package info for dir.
-func (d *dirInfoCache) Store(dir string, info directoryPackageInfo) {
+func (d *DirInfoCache) Store(dir string, info directoryPackageInfo) {
 	d.mu.Lock()
+	// TODO(rfindley, golang/go#59216): should we overwrite an existing entry?
+	// That seems incorrect as the cache should be idempotent.
 	_, old := d.dirs[dir]
 	d.dirs[dir] = &info
 	var listeners []cacheListener
@@ -180,7 +196,7 @@
 }
 
 // Load returns a copy of the directoryPackageInfo for absolute directory dir.
-func (d *dirInfoCache) Load(dir string) (directoryPackageInfo, bool) {
+func (d *DirInfoCache) Load(dir string) (directoryPackageInfo, bool) {
 	d.mu.Lock()
 	defer d.mu.Unlock()
 	info, ok := d.dirs[dir]
@@ -191,7 +207,7 @@
 }
 
 // Keys returns the keys currently present in d.
-func (d *dirInfoCache) Keys() (keys []string) {
+func (d *DirInfoCache) Keys() (keys []string) {
 	d.mu.Lock()
 	defer d.mu.Unlock()
 	for key := range d.dirs {
@@ -200,7 +216,7 @@
 	return keys
 }
 
-func (d *dirInfoCache) CachePackageName(info directoryPackageInfo) (string, error) {
+func (d *DirInfoCache) CachePackageName(info directoryPackageInfo) (string, error) {
 	if loaded, err := info.reachedStatus(nameLoaded); loaded {
 		return info.packageName, err
 	}
@@ -213,7 +229,7 @@
 	return info.packageName, info.err
 }
 
-func (d *dirInfoCache) CacheExports(ctx context.Context, env *ProcessEnv, info directoryPackageInfo) (string, []string, error) {
+func (d *DirInfoCache) CacheExports(ctx context.Context, env *ProcessEnv, info directoryPackageInfo) (string, []string, error) {
 	if reached, _ := info.reachedStatus(exportsLoaded); reached {
 		return info.packageName, info.exports, info.err
 	}
@@ -234,3 +250,81 @@
 	d.Store(info.dir, info)
 	return info.packageName, info.exports, info.err
 }
+
+// ScanModuleCache walks the given directory, which must be a GOMODCACHE value,
+// for directory package information, storing the results in cache.
+func ScanModuleCache(dir string, cache *DirInfoCache, logf func(string, ...any)) {
+	// Note(rfindley): it's hard to see, but this function attempts to implement
+	// just the side effects on cache of calling PrimeCache with a ProcessEnv
+	// that has the given dir as its GOMODCACHE.
+	//
+	// Teasing out the control flow, we see that we can avoid any handling of
+	// vendor/ and can infer module info entirely from the path, simplifying the
+	// logic here.
+
+	root := gopathwalk.Root{
+		Path: filepath.Clean(dir),
+		Type: gopathwalk.RootModuleCache,
+	}
+
+	directoryInfo := func(root gopathwalk.Root, dir string) directoryPackageInfo {
+		// This is a copy of ModuleResolver.scanDirForPackage, trimmed down to
+		// logic that applies to a module cache directory.
+
+		subdir := ""
+		if dir != root.Path {
+			subdir = dir[len(root.Path)+len("/"):]
+		}
+
+		matches := modCacheRegexp.FindStringSubmatch(subdir)
+		if len(matches) == 0 {
+			return directoryPackageInfo{
+				status: directoryScanned,
+				err:    fmt.Errorf("invalid module cache path: %v", subdir),
+			}
+		}
+		modPath, err := module.UnescapePath(filepath.ToSlash(matches[1]))
+		if err != nil {
+			if logf != nil {
+				logf("decoding module cache path %q: %v", subdir, err)
+			}
+			return directoryPackageInfo{
+				status: directoryScanned,
+				err:    fmt.Errorf("decoding module cache path %q: %v", subdir, err),
+			}
+		}
+		importPath := path.Join(modPath, filepath.ToSlash(matches[3]))
+		index := strings.Index(dir, matches[1]+"@"+matches[2])
+		modDir := filepath.Join(dir[:index], matches[1]+"@"+matches[2])
+		modName := readModName(filepath.Join(modDir, "go.mod"))
+		return directoryPackageInfo{
+			status:                 directoryScanned,
+			dir:                    dir,
+			rootType:               root.Type,
+			nonCanonicalImportPath: importPath,
+			moduleDir:              modDir,
+			moduleName:             modName,
+		}
+	}
+
+	add := func(root gopathwalk.Root, dir string) {
+		info := directoryInfo(root, dir)
+		cache.Store(info.dir, info)
+	}
+
+	skip := func(_ gopathwalk.Root, dir string) bool {
+		// Skip directories that have already been scanned.
+		//
+		// Note that gopathwalk only adds "package" directories, which must contain
+		// a .go file, and all such package directories in the module cache are
+		// immutable. So if we can load a dir, it can be skipped.
+		info, ok := cache.Load(dir)
+		if !ok {
+			return false
+		}
+		packageScanned, _ := info.reachedStatus(directoryScanned)
+		return packageScanned
+	}
+
+	gopathwalk.WalkSkip([]gopathwalk.Root{root}, add, skip, gopathwalk.Options{Logf: logf, ModulesEnabled: true})
+}
diff --git a/internal/imports/mod_cache_test.go b/internal/imports/mod_cache_test.go
index 39c691e..3af85fb 100644
--- a/internal/imports/mod_cache_test.go
+++ b/internal/imports/mod_cache_test.go
@@ -6,9 +6,12 @@
 
 import (
 	"fmt"
+	"os/exec"
 	"reflect"
 	"sort"
+	"strings"
 	"testing"
+	"time"
 )
 
 func TestDirectoryPackageInfoReachedStatus(t *testing.T) {
@@ -58,9 +61,7 @@
 }
 
 func TestModCacheInfo(t *testing.T) {
-	m := &dirInfoCache{
-		dirs: make(map[string]*directoryPackageInfo),
-	}
+	m := NewDirInfoCache()
 
 	dirInfo := []struct {
 		dir  string
@@ -124,3 +125,20 @@
 		}
 	}
 }
+
+func BenchmarkScanModuleCache(b *testing.B) {
+	output, err := exec.Command("go", "env", "GOMODCACHE").Output()
+	if err != nil {
+		b.Fatal(err)
+	}
+	gomodcache := strings.TrimSpace(string(output))
+	cache := NewDirInfoCache()
+	start := time.Now()
+	ScanModuleCache(gomodcache, cache, nil)
+	b.Logf("initial scan took %v", time.Since(start))
+	b.ResetTimer()
+
+	for i := 0; i < b.N; i++ {
+		ScanModuleCache(gomodcache, cache, nil)
+	}
+}
diff --git a/internal/imports/mod_test.go b/internal/imports/mod_test.go
index 26dac63..c624463 100644
--- a/internal/imports/mod_test.go
+++ b/internal/imports/mod_test.go
@@ -17,6 +17,7 @@
 	"strings"
 	"sync"
 	"testing"
+	"time"
 
 	"golang.org/x/mod/module"
 	"golang.org/x/tools/internal/gocommand"
@@ -93,7 +94,7 @@
 
 	mt.assertFound("y", "y")
 
-	scan, err := scanToSlice(mt.resolver, nil)
+	scan, err := scanToSlice(mt.env.resolver, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -212,7 +213,7 @@
 	}
 
 	// Uninitialize the go.mod dependent cached information and make sure it still finds the package.
-	mt.resolver.ClearForNewMod()
+	mt.env.ClearModuleInfo()
 	mt.assertScanFinds("rsc.io/quote", "quote")
 }
 
@@ -241,8 +242,9 @@
 	}
 
 	// Clear out the resolver's cache, since we've changed the environment.
-	mt.resolver = newModuleResolver(mt.env)
 	mt.env.Env["GOFLAGS"] = "-mod=vendor"
+	mt.env.ClearModuleInfo()
+	mt.env.UpdateResolver(mt.env.resolver.ClearForNewScan())
 	mt.assertModuleFoundInDir("rsc.io/sampler", "sampler", `/vendor/`)
 }
 
@@ -269,6 +271,10 @@
 	if testenv.Go1Point() >= 14 {
 		wantDir = `/vendor/`
 	}
+
+	// Clear out the resolver's module info, since we've changed the environment.
+	// (the presence of a /vendor directory affects `go list -m`).
+	mt.env.ClearModuleInfo()
 	mt.assertModuleFoundInDir("rsc.io/sampler", "sampler", wantDir)
 }
 
@@ -900,7 +906,7 @@
 func (t *modTest) assertFound(importPath, pkgName string) (string, *pkg) {
 	t.Helper()
 
-	names, err := t.resolver.loadPackageNames([]string{importPath}, t.env.WorkingDir)
+	names, err := t.env.resolver.loadPackageNames([]string{importPath}, t.env.WorkingDir)
 	if err != nil {
 		t.Errorf("loading package name for %v: %v", importPath, err)
 	}
@@ -909,13 +915,13 @@
 	}
 	pkg := t.assertScanFinds(importPath, pkgName)
 
-	_, foundDir := t.resolver.findPackage(importPath)
+	_, foundDir := t.env.resolver.(*ModuleResolver).findPackage(importPath)
 	return foundDir, pkg
 }
 
 func (t *modTest) assertScanFinds(importPath, pkgName string) *pkg {
 	t.Helper()
-	scan, err := scanToSlice(t.resolver, nil)
+	scan, err := scanToSlice(t.env.resolver, nil)
 	if err != nil {
 		t.Errorf("scan failed: %v", err)
 	}
@@ -983,10 +989,9 @@
 
 type modTest struct {
 	*testing.T
-	env      *ProcessEnv
-	gopath   string
-	resolver *ModuleResolver
-	cleanup  func()
+	env     *ProcessEnv
+	gopath  string
+	cleanup func()
 }
 
 // setup builds a test environment from a txtar and supporting modules
@@ -1046,16 +1051,20 @@
 		}
 	}
 
-	resolver, err := env.GetResolver()
-	if err != nil {
+	// Ensure the resolver is set for tests that (unsafely) access env.resolver
+	// directly.
+	//
+	// TODO(rfindley): fix this after addressing the TODO in the ProcessEnv
+	// docstring.
+	if _, err := env.GetResolver(); err != nil {
 		t.Fatal(err)
 	}
+
 	return &modTest{
-		T:        t,
-		gopath:   env.Env["GOPATH"],
-		env:      env,
-		resolver: resolver.(*ModuleResolver),
-		cleanup:  func() { removeDir(dir) },
+		T:       t,
+		gopath:  env.Env["GOPATH"],
+		env:     env,
+		cleanup: func() { removeDir(dir) },
 	}
 }
 
@@ -1098,7 +1107,7 @@
 	arName := filepath.Base(arPath)
 	i := strings.LastIndex(arName, "_v")
 	ver := strings.TrimSuffix(arName[i+1:], ".txt")
-	modDir := strings.Replace(arName[:i], "_", "/", -1)
+	modDir := strings.ReplaceAll(arName[:i], "_", "/")
 	modPath, err := module.UnescapePath(modDir)
 	if err != nil {
 		return err
@@ -1183,7 +1192,7 @@
 	want := filepath.Join(mt.gopath, "pkg/mod", "rsc.io/quote@v1.5.2")
 
 	found := mt.assertScanFinds("rsc.io/quote", "quote")
-	modDir, _ := mt.resolver.modInfo(found.dir)
+	modDir, _ := mt.env.resolver.(*ModuleResolver).modInfo(found.dir)
 	if modDir != want {
 		t.Errorf("expected: %s, got: %s", want, modDir)
 	}
@@ -1288,20 +1297,37 @@
 	}
 }
 
-func BenchmarkScanModCache(b *testing.B) {
+func BenchmarkModuleResolver_RescanModCache(b *testing.B) {
 	env := &ProcessEnv{
 		GocmdRunner: &gocommand.Runner{},
-		Logf:        b.Logf,
+		// Uncomment for verbose logging (too verbose to enable by default).
+		// Logf:        b.Logf,
 	}
 	exclude := []gopathwalk.RootType{gopathwalk.RootGOROOT}
 	resolver, err := env.GetResolver()
 	if err != nil {
 		b.Fatal(err)
 	}
+	start := time.Now()
 	scanToSlice(resolver, exclude)
+	b.Logf("warming the mod cache took %v", time.Since(start))
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		scanToSlice(resolver, exclude)
-		resolver.(*ModuleResolver).ClearForNewScan()
+		resolver = resolver.ClearForNewScan()
+	}
+}
+
+func BenchmarkModuleResolver_InitialScan(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		env := &ProcessEnv{
+			GocmdRunner: &gocommand.Runner{},
+		}
+		exclude := []gopathwalk.RootType{gopathwalk.RootGOROOT}
+		resolver, err := env.GetResolver()
+		if err != nil {
+			b.Fatal(err)
+		}
+		scanToSlice(resolver, exclude)
 	}
 }
diff --git a/internal/refactor/inline/inline.go b/internal/refactor/inline/inline.go
index 06f6401..7eaa6bf 100644
--- a/internal/refactor/inline/inline.go
+++ b/internal/refactor/inline/inline.go
@@ -485,7 +485,7 @@
 			// check not shadowed at caller.
 			found := caller.lookup(obj.Name) // always finds something
 			if found.Pos().IsValid() {
-				return nil, fmt.Errorf("cannot inline because built-in %q is shadowed in caller by a %s (line %d)",
+				return nil, fmt.Errorf("cannot inline, because the callee refers to built-in %q, which in the caller is shadowed by a %s (declared at line %d)",
 					obj.Name, objectKind(found),
 					caller.Fset.PositionFor(found.Pos(), false).Line)
 			}
@@ -505,8 +505,9 @@
 					// around the refactored signature.
 					found := caller.lookup(obj.Name)
 					if found != nil && !isPkgLevel(found) {
-						return nil, fmt.Errorf("cannot inline because %q is shadowed in caller by a %s (line %d)",
-							obj.Name, objectKind(found),
+						return nil, fmt.Errorf("cannot inline, because the callee refers to %s %q, which in the caller is shadowed by a %s (declared at line %d)",
+							obj.Kind, obj.Name,
+							objectKind(found),
 							caller.Fset.PositionFor(found.Pos(), false).Line)
 					}
 				} else {
diff --git a/internal/refactor/inline/testdata/err-shadow-builtin.txtar b/internal/refactor/inline/testdata/err-shadow-builtin.txtar
index 543d38f..34ea586 100644
--- a/internal/refactor/inline/testdata/err-shadow-builtin.txtar
+++ b/internal/refactor/inline/testdata/err-shadow-builtin.txtar
@@ -10,7 +10,7 @@
 
 func _() {
 	const nil = 1
-	_ = f() //@ inline(re"f", re"nil.*shadowed.*by.*const .line 4")
+	_ = f() //@ inline(re"f", re"nil.*shadowed.*by.*const.*line 4")
 }
 
 func f() *int { return nil }
@@ -20,7 +20,7 @@
 
 func _() {
 	type append int
-	g(nil) //@ inline(re"g", re"append.*shadowed.*by.*typename .line 4")
+	g(nil) //@ inline(re"g", re"append.*shadowed.*by.*typename.*line 4")
 }
 
 func g(x []int) { _ = append(x, x...) }
@@ -30,7 +30,7 @@
 
 func _() {
 	type int uint8
-	_ = h(0) //@ inline(re"h", re"int.*shadowed.*by.*typename .line 4")
+	_ = h(0) //@ inline(re"h", re"int.*shadowed.*by.*typename.*line 4")
 }
 
 func h(x int) int { return x + 1 }
diff --git a/internal/refactor/inline/testdata/err-shadow-pkg.txtar b/internal/refactor/inline/testdata/err-shadow-pkg.txtar
index 4338b8b..792418d 100644
--- a/internal/refactor/inline/testdata/err-shadow-pkg.txtar
+++ b/internal/refactor/inline/testdata/err-shadow-pkg.txtar
@@ -15,7 +15,7 @@
 func _() {
 	f() //@ inline(re"f", result)
 	const v = 1
-	f() //@ inline(re"f", re"v.*shadowed.*by.*const .line 5")
+	f() //@ inline(re"f", re"v.*shadowed.*by.*const.*line 5")
 }
 
 func f() int { return v }
@@ -28,7 +28,7 @@
 func _() {
 	_ = v //@ inline(re"f", result)
 	const v = 1
-	f() //@ inline(re"f", re"v.*shadowed.*by.*const .line 5")
+	f() //@ inline(re"f", re"v.*shadowed.*by.*const.*line 5")
 }
 
 func f() int { return v }
diff --git a/refactor/eg/eg_test.go b/refactor/eg/eg_test.go
index 4154e9a..36fd3ad 100644
--- a/refactor/eg/eg_test.go
+++ b/refactor/eg/eg_test.go
@@ -12,6 +12,7 @@
 import (
 	"bytes"
 	"flag"
+	"go/build"
 	"go/constant"
 	"go/parser"
 	"go/token"
@@ -47,9 +48,12 @@
 		t.Skipf("skipping test on %q (no /usr/bin/diff)", runtime.GOOS)
 	}
 
+	ctx := build.Default   // copy
+	ctx.CgoEnabled = false // don't use cgo
 	conf := loader.Config{
 		Fset:       token.NewFileSet(),
 		ParserMode: parser.ParseComments,
+		Build:      &ctx,
 	}
 
 	// Each entry is a single-file package.