The Metadata type was mutated in exactly one place: when setting the
ShouldLoad bit after package loading completes. Address this by cloning
the metadata graph when clearing ShouldLoad. After this change, metadata
graphs and the data within them are immutable.
This also fixes a range-variable capture bug in load.go: previously we
were deferring a call to clearShouldLoad for the range variable scope.
After this change, we properly clear the ShouldLoad bit for all scopes.
Change-Id: I8f9140a490f81fbabacfc9e0102d9c638c7fbb37
Reviewed-on: https://go-review.googlesource.com/c/tools/+/400821
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Rather than updating metadata directly in snapshot.clone, build a set of
updates to apply and call metadata.Clone.
After this change, metadata is only updated by cloning, so we can
eliminate some code that works with mutable metadata.
In the next CL we'll only update the metadata if something changed, but
this is intentionally left out of this CL to isolate the change.
Benchmark (didChange in kubernetes): ~55ms->65ms, because it is now more
work to compute uris.
For golang/go#45686
Change-Id: I048bed65760b266a209f67111c57fae29bd3e6f0
Reviewed-on: https://go-review.googlesource.com/c/tools/+/340852
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
Introduce a metadataGraph.Clone method that can be used to clone a
metadata graph, applying a set of updates. During clone, ids and imports
are recomputed from scratch based on the known metadata.
Also refine the check for "real" packages when determining whether a
command-line-arguments package should be kept as a workspace package: if
all other packages are invalid, but the command-line-arguments package
is valid, we should keep the command-line-arguments package.
Updates golang/go#45686
Change-Id: Iea8d4f19c1d1c5a2b0582b9dda5f9143482a34af
Reviewed-on: https://go-review.googlesource.com/c/tools/+/340851
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Now that we preserve stale metadata, we can derive workspace packages
entirely from known metadata and files. This consolidates the logic to
compute workspace packages into a single location, which can be invoked
whenever metadata changes (via load or invalidation in clone).
Additionally:
- Precompute 'HasWorkspaceFiles' when loading metadata. This value
should never change for a given Metadata, and our view.contains func
is actually quite slow due to evaluating symlinks.
- Track 'PkgFilesChanged' on KnownMetadata, since we don't include
packages whose package name has changed in our workspace.
Also introduce a few debug helpers, so that we can leave some
instrumentation in critical functions.
For golang/go#45686
Change-Id: I2c994a1e8ca05c3c42f67bd2f4519bea5095c54c
Reviewed-on: https://go-review.googlesource.com/c/tools/+/340735
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
This reverts commit 654a14b527.
Reason for revert: my flawed understanding of the concurrency
Change-Id: I31a35267323bb1ff4dff1d9244d3ce69c36cdda4
Reviewed-on: https://go-review.googlesource.com/c/tools/+/412694
Run-TryBot: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
This info is still useful to tell users that some required modules
have known vulnerabilities, but the analyzed packages/workspaces
are not affected.
Those vulnerabilities are missing Symbol/PkgPath/CallStacks.
Change-Id: I94ea0d8f9ebcb1270e05f055caff2a18ebacd034
Reviewed-on: https://go-review.googlesource.com/c/tools/+/412457
Reviewed-by: Jonathan Amsterdam <jba@google.com>
This change reduces the sizes of the critical sections
in traces.ProcessEvent and Generation.Bind, in particular
moving allocations ahead of Lock. This reduces the contention
according to the trace profiler.
See https://go-review.googlesource.com/c/go/+/411909 for
another reduction in contention. The largest remaining
contention is Handle.Get, which thousands of goroutines
wait for because we initiate typechecking top down.
Also, add a couple of possible optimization TODO comments,
and delete a stale comment re: Bind.
Change-Id: I995a0bb46e8c9bf0c23492fb62b56f4539bc32f8
Reviewed-on: https://go-review.googlesource.com/c/tools/+/411910
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Known subdirs change rarely and it's quite expensive to compute
a glob pattern derived from them, so cache computation result
and inherit it across generations.
Computation cost is divided ≈evenly between `sort.Sort` and
`span.URI.Filename` calls, and there is no trivial way to optimize
them away besides caching.
Benchmark (didChange in kubernetes): ~37ms->30ms
Change-Id: Idb1691c76b8ff163dc61f637f07229498888606c
GitHub-Last-Rev: cd99a9ce5c797afb5aaa9b478fcf433edd0dc03c
GitHub-Pull-Request: golang/tools#383
Reviewed-on: https://go-review.googlesource.com/c/tools/+/411636
Reviewed-by: Alan Donovan <adonovan@google.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
The change to implement inlay hints has been merged, so we need to
enable the tests.
Change-Id: I47e7ab343d0ab10283caac0a3d6677dd69c7504a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/411898
Run-TryBot: Suzy Mueller <suzmue@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
I had hoped to see a reduction in total allocation, but it does not
appear to be significant according to the included crude benchmark.
Nonetheless this is a slight code clarity improvement.
Change-Id: I94a503b377dd1146eb371ff11222a351cb5a43b7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/411655
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
The marker tests are updated to include padding values
when mapping inlay hints to text edits.
Change-Id: Ieb421088238c65b07abdad12763816d3d1e757c8
Reviewed-on: https://go-review.googlesource.com/c/tools/+/411654
Run-TryBot: Jamal Carvalho <jamal@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Suzy Mueller <suzmue@golang.org>
This change implements support for textDocument/inlayHint and
adds inlay hints for parameter names.
For golang/go#52343.
For golang/vscode-go#1631.
Change-Id: I3f989838b86cef4fd2b4076cb6340010fff7c24c
Reviewed-on: https://go-review.googlesource.com/c/tools/+/411094
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Reviewed-by: Suzy Mueller <suzmue@golang.org>
Run-TryBot: Jamal Carvalho <jamal@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
This change replaces the single large map used for snapshot.goFiles
by a map of 256 stripes, each of which becomes immutable once shared.
This optimizes the common case in which the copy is nearly identical
to the original.
We still need to visit each map entry to see whether it needs to be
deleted (which is rare) and to inherit the handle in the usual case.
This is now done concurrently.
Also, share the (logically immutable) []PackageIDs slices across
old and new snapshots. This was worth 5% of CPU and 1/3 of allocations
(all small).
Benchmark on darwin/arm64 shows a 29% reduction for DidChange.
$ go test -v ./gopls/internal/regtest/bench -run=TestBenchmarkDidChange -didchange_dir=$HOME/w/kubernetes -didchange_file=pkg/util/hash/hash.go
Before:
BenchmarkStatistics 100 22955469 ns/op 11308095 B/op 47412 allocs/op
BenchmarkStatistics 100 23454630 ns/op 11226742 B/op 46882 allocs/op
BenchmarkStatistics 100 23618532 ns/op 11258619 B/op 47068 allocs/op
After goFilesMap:
BenchmarkStatistics 100 16643972 ns/op 8770787 B/op 46238 allocs/op
BenchmarkStatistics 100 17805864 ns/op 8862926 B/op 46762 allocs/op
BenchmarkStatistics 100 18618255 ns/op 9308864 B/op 49776 allocs/op
After goFilesMap and ids sharing:
BenchmarkStatistics 100 16703623 ns/op 8772626 B/op 33812 allocs/op
BenchmarkStatistics 100 16927378 ns/op 8529491 B/op 32328 allocs/op
BenchmarkStatistics 100 16632762 ns/op 8557533 B/op 32497 allocs/op
Also:
- Add comments documenting findings of profiling.
- preallocate slice for knownSubdirs.
- remove unwanted loop over slice in Generation.Inherit
Updates golang/go#45686
Change-Id: Id953699191b8404cf36ba3a7ab9cd78b1d19c0a2
Reviewed-on: https://go-review.googlesource.com/c/tools/+/410176
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Alan Donovan <adonovan@google.com>
When test awaiting fails, we often fail to shut down the server because
the pipe is closed. Fix this by using a detached context for running the
connection.
Also clean up some unnecessary context arguments.
Change-Id: I535c1cc1606e44df5f8e2177c92293d57836f992
Reviewed-on: https://go-review.googlesource.com/c/tools/+/340850
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
Set up the tests for inlay hints. We test inlay hints by converting them to text edits
and verifying the output is as we expected it.
This change does not yet deal with making sure the server
settings are correct.
Change-Id: I136f971a87bf9936fd44047d45fe0a3f03c9164e
Reviewed-on: https://go-review.googlesource.com/c/tools/+/411095
Run-TryBot: Suzy Mueller <suzmue@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jamal Carvalho <jamal@golang.org>
It is inconsistent to only compute IsIntermediateTestVariant for
workspace packages, and could be a source of bugs. Always compute it.
Change-Id: I16f40fe44a1145a74ef77fee4b7fd813abe603cb
Reviewed-on: https://go-review.googlesource.com/c/tools/+/340732
Reviewed-by: Alan Donovan <adonovan@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
In preparation for making metadata immutable, move metadata-related
fields to a new MetadataGraph type. Other than instantiating this type
when cloning, this CL contains no functional changes.
For golang/go#45686
Change-Id: I7ad29d1f331ba7e53dad3f012ad7ecdae4f7d4b7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/340730
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
When using go.work, the go command packs module-specific errors into
synthetic results corresponding to the module query ("modulepath/...").
Extract these for use in diagnostics, by packing them into a new
moduleErrorMap error type.
Fixesgolang/go#50862
Change-Id: I68bf9cf4e9ebf4595acdc4da0347ed97171d637f
Reviewed-on: https://go-review.googlesource.com/c/tools/+/405259
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
This reverts commit 5ca4cc8b9a.
Reason for revert: appears insufficient to land CL 410955.
Change-Id: If7029c9a43568e210e89d473b738400f5155715e
Reviewed-on: https://go-review.googlesource.com/c/tools/+/410995
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
1. Avoid unnecessary intermediate map updates.
2. Avoid accumulating defers in a loop when the control is simple.
Yield: -10% CPU, -37% allocs.
Typical results:
$ go test -v ./gopls/internal/regtest/bench -run=TestBenchmarkDidChange -didchange_dir=$HOME/w/kubernetes -didchange_file=pkg/util/hash/hash.go
Before:
BenchmarkStatistics 100 25932206 ns/op 11684109 B/op 75458 allocs/op
After:
BenchmarkStatistics 100 23294195 ns/op 11293472 B/op 47299 allocs/op
Also, move profiling logic outside the loop so that later runs
don't overwrite earlier runs. (This doesn't appear to be a problem
in practice, presumably because the last run is the big one.)
Updates golang/go#45686
Change-Id: I538ca6bb88cc18f1eefe35d2db29a62e5190280e
Reviewed-on: https://go-review.googlesource.com/c/tools/+/410697
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This change replaces various uses of FileSet with either
nothing (when the parameter wasn't really needed) or token.File.
Notably, astutil.Imports was being used to extract the imports
of a file (available at ast.File.Imports), forcing a number
of wrappers to have a FileSet parameter.
Also, simplify various expressions file.Position().Line to file.Line().
Change-Id: I19fe86a18aba50352275f77ed737513744d3930c
Reviewed-on: https://go-review.googlesource.com/c/tools/+/410366
Run-TryBot: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Like `go list -test`, allow users to control inclusion/exclusion of test files.
Default is to include test files.
Change-Id: I1af3077f087089ad2201571b4a2f781d936d0102
Reviewed-on: https://go-review.googlesource.com/c/tools/+/410365
Reviewed-by: Alan Donovan <adonovan@google.com>
This should have been included in
https://go-review.googlesource.com/c/tools/+/410138
Change-Id: Ic8a4f1b5dbcdb320fb872b24484b830dcb56fd41
Reviewed-on: https://go-review.googlesource.com/c/tools/+/410123
Run-TryBot: Alan Donovan <adonovan@google.com>
Reviewed-by: Tim King <taking@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
Use a detached Context for all progress notifications. In particular,
using a detached Context for the window/workDoneProgress/create
notification avoids races where the $/cancelRequest notification and
create response cross paths, such that the client has created a progress
dialog but the server thinks that starting progress failed.
Also, as a matter of best practice don't store a context on the WorkDone
type, despite the fact that this Context is detached. Instead, only
close over a Context in the WorkDoneWriter, which requires a Context in
order to function but which implements the io.Writer interface.
The TestProgressBarErrors test should now pass reliably.
Fixesgolang/go#46930
Change-Id: I0d115ed3a62de97fe545c8dc0403e7bb55f6e481
Reviewed-on: https://go-review.googlesource.com/c/tools/+/409936
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
This option uses Variable Type Analysis, a refinement of CHA
suitable for partial programs.
Change-Id: I6c8b074e915d29eb9425656f345e8160417ba594
Reviewed-on: https://go-review.googlesource.com/c/tools/+/410138
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Alan Donovan <adonovan@google.com>
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Logic in mod.Hover relied upon ColumnMapper.TokFile being the only file
in its FileSet. Fix this to compare offsets with offsets.
Also use safetoken.InRange in semantic.go, to fix an incorrect bounds
check.
Change-Id: Ia18a0799fea1120674e3772efdf0bdb724e554e7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/409934
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
It turns out PointSpan was only ever used as part of an oft repeated
pattern to get a token.Pos from a protocol position. Cut out the
middle.
Change-Id: I0b2c0fc3d335e6bbd3c1ac72c6f75e2c40c60ca5
Reviewed-on: https://go-review.googlesource.com/c/tools/+/408717
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
This eliminates some duplication, and lays the groundwork for removing
the use of token.File within ColumnMapper.
Change-Id: I54fe570bfc4f7bca0da643b8727e890dc6343208
Reviewed-on: https://go-review.googlesource.com/c/tools/+/406135
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
The TokenConverter has been trimmed down to a thin wrapper around
token.File, and can now be removed.
Change-Id: I9985492274c88e6a13e6d62dadab5595c75c7840
Reviewed-on: https://go-review.googlesource.com/c/tools/+/406134
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
Eliminate the need to work around newline terminated files in
completion, by storing selection ranges as token.Pos and using an
lsppos.TokenMapper derived from the file content, which does not have
problems with newline termination.
This simplifies the completion logic, and removes the last use of
MappedRange.SpanRange, which is an inconisitent API in that it returns
positions in the compiled source, rather than edited source.
Change-Id: I65232787956325172b48fd42d85cbb598039ee5a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/407889
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Due to not having a pointer receiver, memoization of the computed
MappedRange.protocolRange had no effect.
Rather than fix the memoization, just remove it since it has apparently
not affected performance significantly.
Change-Id: Ib34becef44dca4074dcc7c8af93883d9a1060f8d
Reviewed-on: https://go-review.googlesource.com/c/tools/+/408716
Reviewed-by: Alan Donovan <adonovan@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
CL 405546 introduced a latent bug in MappedRange, because it naively
used the wrong TokenConverter to convert mapped positions to offsets.
This was detected via related clean-up work in another CL. Fix this by
passing the correct converter from MappedRange.Range. Add a test that
would have demonstrated the breakage.
More cleanup is needed here. It is subtle that MappedRange.Converter
maps the adjusted position for its start and end, and there may be some
places where this invariant has been broken over the years.
Add additional documentation and bug reports.
Change-Id: If7f177894bac1242ddcc1786e79c7559455e9291
Reviewed-on: https://go-review.googlesource.com/c/tools/+/407887
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
Copy the x/vuln/cmd/govulncheck/internal/govulncheck package
and use it in internal/vulncheck.
Fixesgolang/go#52985.
Change-Id: I3fb16b3d486ac462fca36aa53fd46e576041102d
Reviewed-on: https://go-review.googlesource.com/c/tools/+/407114
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Add additional bug reporting related to position invariants, and update
marker test runners to panic on encountered bugs.
This revealed a panic on older Go versions, where we try to create a
range for a missing package name span. Lift the check into the caller
for this case, and leave a big comment explaining that
checkForOrphanedFile probably shouldn't be so tolerant of invalid calls.
Change-Id: Ie16a07afba0f8a5682cca50ad8f04450bfa2da65
Reviewed-on: https://go-review.googlesource.com/c/tools/+/407885
Reviewed-by: Alan Donovan <adonovan@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Package loading (at least via go list) fails when the import header
doesn't parse, so we need to invalidate metadata upon a state change
from non parsing->parsing. Refactor metadata invalidation to implement
this feature, add additional documentation, and avoid unnecessary work.
This change revealed a latent bug (via TestDeleteDirectory): when
statting a deleted directory failed, we could fail to invalidate any
package IDs, even those we already knew about. This bug was masked by
the somewhat complicated semantics of pkgNameChanged. The semantics of
pkgNameChanged are simplified to encapsulate any change to a
package->file association.
Also refactor the parsing API somewhat, and add a bug report if we don't
get a ParseGoFile while inspecting for metadata changes.
Update most regtests to panic upon receiving bug reports.
Fixesgolang/go#52981
Change-Id: I1838963ecc9c01e316f887aa9d8f1260662281ab
Reviewed-on: https://go-review.googlesource.com/c/tools/+/407501
Reviewed-by: Alan Donovan <adonovan@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
Was "f[[int]]", now "f[int]".
Change-Id: I361d2386cffbabd0a4eca180b49c6da2b42cb28a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/407094
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Tim King <taking@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Alan Donovan <adonovan@google.com>