Commit Graph

14 Commits

Author SHA1 Message Date
Robert Findley 98aef77998 internal/lsp/cache: track explicit go.work files outside the workspace
In order to correctly process changes to the go.work file, the workspace
must know about GOWORK settings configured in the users environment.
Compute this when initializing the view, and thread this through to the
workspace.

At this point, workspace information is spread around in a few places.
Add some TODOs to clean this up.

Also remove some module data that was not used in
TestBrokenWorkspace_DuplicateModules.

Updates golang/go#53631

Change-Id: Ie0577d702c8a229304387bc7fe53a8befb544acb
Reviewed-on: https://go-review.googlesource.com/c/tools/+/421500
Reviewed-by: Suzy Mueller <suzmue@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
2022-08-08 18:11:01 +00:00
Robert Findley b52794acc2 internal/lsp/cache: simplify snapshot.Clone reinitialization logic
The logic to detect whether the snapshot should be reinitialized is
complicated, and had at least a couple latent bugs:
 - It depends on workspace.Clone to learn whether relevant mod/work
   files have been saved.
 - It naively checks for changes in vendor directories, and
   reinitializes if there was an initialization failure.
 - It copies the initializeOnce field. Pragmatically this may not matter
   (due to context cancellation, for example), but as a matter of best
   practices we should not copy this field. It could lead to missing an
   initialization on the new snapshot.
 - Writing initializeOnce was technically racy.

Furthermore, due to vendored file handling being interleaved with other
changes, it was possible that we detect that the snapshot should be
reinitialied only after we have processed other changes, and that
processing of other changes depended on knowing whether the snapshot
will be reinitialized.

Simplify this by
- Replacing 'initializeOnce' with an 'initialized' bool, which is
  guarded with snapshot.mu. We were relying on the view initialization
  semaphore to prevent races anyway, so there is no need for a sync.Once
  to prevent multiple in-flight initializations.
- Removing the 'changed' result from workspace.Clone: it shouldn't
  actualy matter for snapshot.Clone (only reinit matters), and in any
  case can be derived by comparing the new workspace with the old.
- Detect changes to vendored files before processing the rest of the
  changes.

Change-Id: I3624a46d4be9c054a6f719f20549599986b64cbd
Reviewed-on: https://go-review.googlesource.com/c/tools/+/419499
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-27 19:27:52 +00:00
Robert Findley f1bb5ca08f internal/lsp/cache: report a critical error when go.work is invalid
When a go.work file fails to validate, the workspace is left in an
invalid state: we will detect that the workspace is defined by the
go.work, but will not actually parse any active modules. This should be
a critical error.

Fix this by adding allowing the workspace to surface critical errors via
a new cache.workspace.criticalError method.

Additionally:
 - only build the workspace mod file in workspace.build if the mode is
   fileSystemWorkspace (in all other modes the modfile is already
   determined)
 - rename workspace.invalidate to workspace.Clone, to be consistent with
   other data structures
 - rename CriticalError.DiagList to CriticalError.Diagnostics
 - add several TODOs for observations while reading the code
 - create a new file for regtests related to broken workspaces
 - make the regtest sandbox panic when duplicate paths are present in
   the sandbox file set (an error I made while writing the test)

Updates golang/go#53933

Change-Id: If8625ab190129bc9c57e784314bc9cc92644c955
Reviewed-on: https://go-review.googlesource.com/c/tools/+/417593
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>
2022-07-27 18:59:40 +00:00
Michael Matloob 3286927895 internal/lsp/cache: construct workspace even when go.work has error
Before this change, newWorkspace would fall back to other workspace
types if there was an error parsing go.work files, or one of the
workspace modules did not exist. Instead, in those cases, newWorkspace
now successfully builds a *workspace with an error set.

This respects the user's intent when working with a go.work file so that
gopls can surface a diagnostic with the error.

Change-Id: Icfc2cad270111c03d53137fa8f1b2ee9b75093c8
Reviewed-on: https://go-review.googlesource.com/c/tools/+/389314
Trust: Michael Matloob <matloob@golang.org>
Run-TryBot: Michael Matloob <matloob@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
2022-03-03 21:30:30 +00:00
Rebecca Stambler da404b52bc internal/lsp: start parsing go.work file like gopls.mod file
Allow users to experiment with golang/go#45713 by adding experimental
support for the go.work file. We handle it like a special case, very
similar to the current gopls.mod file mechanism. The behavior is
undefined if both a gopls.mod and go.work file exist. Ultimately, we
will deprecate support for the gopls.mod file if the go.work file
proposal is accepted, so I don't think it's important to be careful
about handling both simultaneously.

Change-Id: Id822aeec953fc1d4acca343b742afea899dc70ff
Reviewed-on: https://go-review.googlesource.com/c/tools/+/328334
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
2021-06-24 04:20:31 +00:00
Rob Findley cd1be5dbec gopls/internal/regtest: add a failing regtest for vscode-go#1489
Unimported completion computes invalid text edits with windows line
endings.

To enable this test, add support for windows line endings in the regtest
framework. Doing this required decoupling the txtar encoding from the
sandbox, which was a good change anyway.

For golang/vscode-go#1489

Change-Id: I6c1075fd38d24090271a7a7f33b11ddd8f9decf5
Reviewed-on: https://go-review.googlesource.com/c/tools/+/319089
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2021-05-13 13:20:04 +00:00
Rob Findley f618651c09 internal/lsp/cache: compare file size when invalidating file cache
Our filesystem caching layer uses file modification time to invalidate
file contents. This is an imperfect heuristic, and on certain operating
systems with low resolution filesystem clocks (such as WSL), this can be
broken in practice.

A proper fix would be to just read the file contents directly and rely
on the snapshot to optimize file access, but we don't know that this is
a safe change. Instead, try to reduce the likelihood of false cache hits
by also checking the file size reported by Stat.

For golang/go#43554

Change-Id: I1af384db532725e84fa6f3a2e5469d10b43fee92
Reviewed-on: https://go-review.googlesource.com/c/tools/+/283053
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
Trust: Robert Findley <rfindley@google.com>
2021-01-12 21:35:00 +00:00
Rob Findley bdbb3c917f internal/lsp/cache: only reload the workspace on saved changes
Invalidating the workspace on any change to a go.mod can render a
workspace unusable. Only invalidate when changes are saved.

Additionally, invalidate the workspace if there is a saved change to
tracked go.sum changes.

Fixes golang/go#42529
Fixes golang/go#42815

Change-Id: I5d903013b33b932eca4998513e3d0a534b2e5a61
Reviewed-on: https://go-review.googlesource.com/c/tools/+/279720
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Robert Findley <rfindley@google.com>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-12-23 22:53:30 +00:00
Heschi Kreinick cc330816fc internal/lsp: support directory inclusion/exclusion filters
Users working in large repositories may want to include only selected
directories in their workspace to avoid memory usage and performance
slowdowns. Add support for inclusion/exclusion filters that control what
directories are searched for workspace packages and modules. Packages
that are excluded by the filter may still be loaded as non-workspace
packages if other things depend on them.

For a description of the option's syntax, see the documentation.

Note that because we don't have any way to communicate the filters to
packages.Load, we still run go list on the unfiltered workspace scope,
then throw away the irrelevant packages. That may cost us, especially in
workspaces with many files.

Comments on the naming welcome. Also, if you know any places I may have
missed applying the filter, please do tell. One thing I thought of is
file watching, but that's covered because allKnownSubdirs works off of
workspace files and those are already filtered.

Possible enhancements:
 - Support glob patterns.
 - Apply filters during the goimports scan.
 - Figure out how to apply the filters to packages.Load. I don't know
 how to do it while still being build system neutral though.

Closes golang/go#42473, assuming none of the enhancements are required.

Change-Id: I9006a7a361dc3bb3c11f78b05ff84981813035a0
Reviewed-on: https://go-review.googlesource.com/c/tools/+/275253
Trust: Heschi Kreinick <heschi@google.com>
Run-TryBot: Heschi Kreinick <heschi@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
2020-12-08 18:36:58 +00:00
Rob Findley 9a3a6c5f63 internal/lsp/cache: build a go.sum file for multi-module workspaces
When running with -mod=readonly, we need a go.sum to be present for go
command invocations. Achieve this by merging the go.sum of tracked
modules.

Fixes golang/go#42509

Change-Id: I36dd084f865ebcee0ba6e1e542fdf51031b1487e
Reviewed-on: https://go-review.googlesource.com/c/tools/+/272886
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Trust: Robert Findley <rfindley@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2020-12-07 18:57:29 +00:00
Rebecca Stambler 545788942d internal/lsp: separate the environment's value of GO111MODULE out
We adjust the value of GO111MODULE to "auto" when running the go
command, since it handles more edge cases. However, in some cases, we
may want to know the environment's actual value of GO111MODULE, so
separate out these two concepts.

Also, as of Go 1.13, `go env` reports GO111MODULE, so add it to the
environmentVariables, but only for Go versions >= 1.13.

Removed a regression test that doesn't seem very important--looks like
even `go env` will fail with GO111MODULE=on and a malformed GOPATH.
I don't think that it's important that `gopls` continue working in such
a case, since the go command will also fail.

Change-Id: I8147782222261a190d0f1017fe9f6043f2ac0cdb
Reviewed-on: https://go-review.googlesource.com/c/tools/+/275013
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2020-12-04 06:28:50 +00:00
Rebecca Stambler a1b87a1c0d internal/lsp: track all go.mod changes no matter the workspace mode
In some cases (such as presenting more helpful error messages), we need
to know the number of go.mod files in the workspace--not just the
active go.mod files. Track both known and active mod files separately.

Change-Id: I068f76c2930c90cd0fdf5ce637e5934210880f65
Reviewed-on: https://go-review.googlesource.com/c/tools/+/273047
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
2020-12-01 19:22:19 +00:00
Rebecca Stambler f0400ba216 internal/lsp: check the value of GO111MODULE before collecting modules
We don't check the value of GO111MODULE before finding all of the
modules in the workspace, meaning we treat the workspace as if it has
modules even if modules are disabled. Before creating a workspace,
we now do check this.

Change-Id: I36b9d13f3b8382e65de36b4b4deed68f5b59e21d
Reviewed-on: https://go-review.googlesource.com/c/tools/+/273309
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
2020-12-01 06:27:05 +00:00
Rob Findley d463eb0e41 internal/lsp/cache: introduce a workspace abstraction
When incorporating the gopls.mod file, the invalidation logic for
workspace module information becomes quite complicated. For example:
 + if a modfile changes we should only invalidate if it is in the set of
   active modules
 + the set of active modules can be provided by either the filesystem or
   gopls.mod
 + if gopls.mod changes, we may gain or lose active modules in the
   workspace
 + if gopls.mod is *deleted*, we may need to walk the filesystem to
   actually find all active modules

Doing this with only concrete changes to the snapshot proved
prohibitively complex (at least for me), so a new workspace type is
introduced to manage the module state. This new abstraction is
responsible for tracking the set of active modules, the workspace
modfile, and the set of workspace directories. Its invalidation logic is
factored out of snapshot.clone, so that it can be tested and to
alleviate some of the growing complexity of snapshot.clone.

The workspace type is idempotent, allowing it to be shared across
snapshots without needing to use the cache. There is little benefit to
the cache in this case, since workspace module computation should be
infrequent, and the type itself consumes little memory.

This is made possible because the workspace type itself depends only on
file state, and therefore may be invalidated independently of the
snapshot. The new source.FileState interface is used in testing, and so
that the workspace module may be computed based on both the session file
state as well as the snapshot file state.

As a result of this change, the following improvements in functionality
are possible:
 + in the presence of a gopls.mod file, we avoid walking the filesystem
   to detect modules. This could be helpful for working in large
   monorepos or in GOPATH, when discovering all modules would be
   expensive.
 + The set of active modules should always be consistent with the
   gopls.mod file, likely fixing some bugs (for example, computing
   diagnostics for modfiles that shouldn't be loaded)

For golang/go#41837

Change-Id: I2da888c097748b659ee892ca2d6b3fbe29c1942e
Reviewed-on: https://go-review.googlesource.com/c/tools/+/261237
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Trust: Robert Findley <rfindley@google.com>
2020-10-30 19:58:30 +00:00