Skip to content

Commit c7ed4b3

Browse files
committed
gopls/internal/lsp/cache: clean up tracking of GO111MODULE
Gopls views stored at least 4 copies of GO111MODULE: - the value in view.environmentVariables - the value in view.goEnv - the value in view.userGo111Module - the value in view.effectiveGo111Module All of these values may differ from eachother, depending on the user's environment and go version, and their meaning is not clearly documented. Try to clean this up, by having environmentVariables track precisely the variables output by `go env`, and providing a method to implement the derived logic of userGo111Module and effectiveGo111Module. Ignore view.goEnv for now, but leave a TODO. Confusingly, the name 'effectiveGO111MODULE' turned out to be a more appropriate name for what was formerly 'userGo111Module', so the naming has switched. This change is intended to be a no-op cleanup. Change-Id: I529cc005c1875915483ef119a465bf17a96dec3c Reviewed-on: https://go-review.googlesource.com/c/tools/+/451355 TryBot-Result: Gopher Robot <[email protected]> gopls-CI: kokoro <[email protected]> Run-TryBot: Robert Findley <[email protected]> Reviewed-by: Alan Donovan <[email protected]>
1 parent 23056f6 commit c7ed4b3

File tree

4 files changed

+51
-42
lines changed

4 files changed

+51
-42
lines changed

gopls/internal/lsp/cache/load.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ func (s *snapshot) workspaceLayoutError(ctx context.Context) *source.CriticalErr
307307
}
308308

309309
// TODO(rfindley): both of the checks below should be delegated to the workspace.
310-
if s.view.userGo111Module == off {
310+
if s.view.effectiveGO111MODULE() == off {
311311
return nil
312312
}
313313
if s.workspace.moduleSource != legacyWorkspace {

gopls/internal/lsp/cache/session.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ func (s *Session) createView(ctx context.Context, name string, folder span.URI,
219219
goworkURI := span.URIFromPath(explicitGowork)
220220

221221
// Build the gopls workspace, collecting active modules in the view.
222-
workspace, err := newWorkspace(ctx, root, goworkURI, s, pathExcludedByFilterFunc(root.Filename(), wsInfo.gomodcache, options), wsInfo.userGo111Module == off, options.ExperimentalWorkspaceModule)
222+
workspace, err := newWorkspace(ctx, root, goworkURI, s, pathExcludedByFilterFunc(root.Filename(), wsInfo.gomodcache, options), wsInfo.effectiveGO111MODULE() == off, options.ExperimentalWorkspaceModule)
223223
if err != nil {
224224
return nil, nil, func() {}, err
225225
}

gopls/internal/lsp/cache/snapshot.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ func (s *snapshot) goCommandInvocation(ctx context.Context, flags source.Invocat
453453
// this with a non-empty inv.Env?
454454
//
455455
// We should refactor to make it clearer that the correct env is being used.
456-
inv.Env = append(append(append(os.Environ(), s.view.options.EnvSlice()...), inv.Env...), "GO111MODULE="+s.view.effectiveGo111Module)
456+
inv.Env = append(append(append(os.Environ(), s.view.options.EnvSlice()...), inv.Env...), "GO111MODULE="+s.view.GO111MODULE())
457457
inv.BuildFlags = append([]string{}, s.view.options.BuildFlags...)
458458
s.view.optionsMu.Unlock()
459459
cleanup = func() {} // fallback

gopls/internal/lsp/cache/view.go

+48-39
Original file line numberDiff line numberDiff line change
@@ -125,22 +125,48 @@ type workspaceInformation struct {
125125
hasGopackagesDriver bool
126126

127127
// `go env` variables that need to be tracked by gopls.
128-
environmentVariables
129-
130-
// userGo111Module is the user's value of GO111MODULE.
131128
//
132-
// TODO(rfindley): is there really value in memoizing this variable? It seems
133-
// simpler to make this a function/method.
134-
userGo111Module go111module
135-
136-
// The value of GO111MODULE we want to run with.
137-
effectiveGo111Module string
129+
// TODO(rfindley): eliminate this in favor of goEnv, or vice-versa.
130+
environmentVariables
138131

139132
// goEnv is the `go env` output collected when a view is created.
140133
// It includes the values of the environment variables above.
141134
goEnv map[string]string
142135
}
143136

137+
// effectiveGO111MODULE reports the value of GO111MODULE effective in the go
138+
// command at this go version, accounting for default values at different go
139+
// versions.
140+
func (w workspaceInformation) effectiveGO111MODULE() go111module {
141+
// Off by default until Go 1.12.
142+
go111module := w.GO111MODULE()
143+
if go111module == "off" || (w.goversion < 12 && go111module == "") {
144+
return off
145+
}
146+
// On by default as of Go 1.16.
147+
if go111module == "on" || (w.goversion >= 16 && go111module == "") {
148+
return on
149+
}
150+
return auto
151+
}
152+
153+
// GO111MODULE returns the value of GO111MODULE to use for running the go
154+
// command. It differs from the user's environment in order to allow for the
155+
// more forgiving default value "auto" when using recent go versions.
156+
//
157+
// TODO(rfindley): it is probably not worthwhile diverging from the go command
158+
// here. The extra forgiveness may be nice, but breaks the invariant that
159+
// running the go command from the command line produces the same build list.
160+
//
161+
// Put differently: we shouldn't go out of our way to make GOPATH work, when
162+
// the go command does not.
163+
func (w workspaceInformation) GO111MODULE() string {
164+
if w.goversion >= 16 && w.go111module == "" {
165+
return "auto"
166+
}
167+
return w.go111module
168+
}
169+
144170
type go111module int
145171

146172
const (
@@ -149,8 +175,15 @@ const (
149175
on
150176
)
151177

178+
// environmentVariables holds important environment variables captured by a
179+
// call to `go env`.
152180
type environmentVariables struct {
153-
gocache, gopath, goroot, goprivate, gomodcache, go111module string
181+
gocache, gopath, goroot, goprivate, gomodcache string
182+
183+
// Don't use go111module directly, because we choose to use a different
184+
// default (auto) on Go 1.16 and later, to avoid spurious errors. Use
185+
// the workspaceInformation.GO111MODULE method instead.
186+
go111module string
154187
}
155188

156189
// workspaceMode holds various flags defining how the gopls workspace should
@@ -804,20 +837,11 @@ func (s *Session) getWorkspaceInformation(ctx context.Context, folder span.URI,
804837
return nil, err
805838
}
806839

807-
go111module := os.Getenv("GO111MODULE")
808-
if v, ok := options.Env["GO111MODULE"]; ok {
809-
go111module = v
810-
}
811840
// Make sure to get the `go env` before continuing with initialization.
812-
envVars, env, err := s.getGoEnv(ctx, folder.Filename(), goversion, go111module, options.EnvSlice())
841+
envVars, env, err := s.getGoEnv(ctx, folder.Filename(), goversion, options.EnvSlice())
813842
if err != nil {
814843
return nil, err
815844
}
816-
// If using 1.16, change the default back to auto. The primary effect of
817-
// GO111MODULE=on is to break GOPATH, which we aren't too interested in.
818-
if goversion >= 16 && go111module == "" {
819-
go111module = "auto"
820-
}
821845
// The value of GOPACKAGESDRIVER is not returned through the go command.
822846
gopackagesdriver := os.Getenv("GOPACKAGESDRIVER")
823847
// TODO(rfindley): this looks wrong, or at least overly defensive. If the
@@ -838,26 +862,12 @@ func (s *Session) getWorkspaceInformation(ctx context.Context, folder span.URI,
838862

839863
return &workspaceInformation{
840864
hasGopackagesDriver: hasGopackagesDriver,
841-
effectiveGo111Module: go111module,
842-
userGo111Module: go111moduleForVersion(go111module, goversion),
843865
goversion: goversion,
844866
environmentVariables: envVars,
845867
goEnv: env,
846868
}, nil
847869
}
848870

849-
func go111moduleForVersion(go111module string, goversion int) go111module {
850-
// Off by default until Go 1.12.
851-
if go111module == "off" || (goversion < 12 && go111module == "") {
852-
return off
853-
}
854-
// On by default as of Go 1.16.
855-
if go111module == "on" || (goversion >= 16 && go111module == "") {
856-
return on
857-
}
858-
return auto
859-
}
860-
861871
// findWorkspaceRoot searches for the best workspace root according to the
862872
// following heuristics:
863873
// - First, look for a parent directory containing a gopls.mod file
@@ -938,7 +948,7 @@ func defaultCheckPathCase(path string) error {
938948
}
939949

940950
// getGoEnv gets the view's various GO* values.
941-
func (s *Session) getGoEnv(ctx context.Context, folder string, goversion int, go111module string, configEnv []string) (environmentVariables, map[string]string, error) {
951+
func (s *Session) getGoEnv(ctx context.Context, folder string, goversion int, configEnv []string) (environmentVariables, map[string]string, error) {
942952
envVars := environmentVariables{}
943953
vars := map[string]*string{
944954
"GOCACHE": &envVars.gocache,
@@ -984,13 +994,12 @@ func (s *Session) getGoEnv(ctx context.Context, folder string, goversion int, go
984994
}
985995

986996
// Old versions of Go don't have GOMODCACHE, so emulate it.
997+
//
998+
// TODO(rfindley): consistent with the treatment of go111module, we should
999+
// provide a wrapper method rather than mutating this value.
9871000
if envVars.gomodcache == "" && envVars.gopath != "" {
9881001
envVars.gomodcache = filepath.Join(filepath.SplitList(envVars.gopath)[0], "pkg/mod")
9891002
}
990-
// GO111MODULE does not appear in `go env` output until Go 1.13.
991-
if goversion < 13 {
992-
envVars.go111module = go111module
993-
}
9941003
return envVars, env, err
9951004
}
9961005

0 commit comments

Comments
 (0)