Skip to content

Commit

Permalink
cmd/govim: add config for defining the gopls environment
Browse files Browse the repository at this point in the history
gopls can be configured with an environment, an environment which is
passed to go/packages. For example, setting GOOS and GOARCH, or setting
GOFLAGS=-tags=other to set a build tag.

Therefore we define a govim config key, "GoplsEnv", for setting this
environment.

For example:

  govim#config#Set("GoplsEnv", {"GOFLAGS": "-mod=readonly"})

As part of this add a test that verifies the behaviour of the above
setting. Setting of build tags does not current work; that is blocked on
golang/go#35548 and will be tested in a follow
up PR.

Fixes #555
  • Loading branch information
myitcv committed Jan 26, 2020
1 parent 913d73d commit e79b68f
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 12 deletions.
13 changes: 13 additions & 0 deletions autoload/govim/config.vim
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,18 @@ function! s:validExperimentalTempModfile(v)
return s:validBool(a:v)
endfunction

function! s:validGoplsEnv(v)
if type(a:v) != 4
return [v:false, "value must be a dict"]
endif
for [key, value] in items(a:v)
if type(value) != 1
return [v:false, "value for key ".key." must be a string"]
endif
endfor
return [v:true, ""]
endfunction

function! s:validExperimentalMouseTriggeredHoverPopupOptions(v)
if has_key(a:v, "line")
if type(a:v["line"]) != 0
Expand Down Expand Up @@ -135,6 +147,7 @@ let s:validators = {
\ "GoImportsLocalPrefix": function("s:validGoImportsLocalPrefix"),
\ "CompletionBudget": function("s:validCompletionBudget"),
\ "ExperimentalTempModfile": function("s:validExperimentalTempModfile"),
\ "GoplsEnv": function("s:validGoplsEnv"),
\ "ExperimentalMouseTriggeredHoverPopupOptions": function("s:validExperimentalMouseTriggeredHoverPopupOptions"),
\ "ExperimentalCursorTriggeredHoverPopupOptions": function("s:validExperimentalCursorTriggeredHoverPopupOptions"),
\ }
7 changes: 7 additions & 0 deletions cmd/govim/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ type Config struct {
// Default: false
ExperimentalTempModfile *bool `json:",omitempty"`

// GoplsEnv configures the set of environment variables gopls is using in
// calls to go/packages. This is most easily understood in the context of
// build tags/constraints, where GOOS/GOARCH could be set for example, or
// GOFLAGS set to "-mod=readonly" in order to prevent changes being
// automatically made to go.mod.
GoplsEnv *map[string]string `json:",omitempty"`

// ExperimentalMouseTriggeredHoverPopupOptions is a map of options to apply
// when creating hover-based popup windows triggered by the mouse hovering
// over an identifier. It corresponds to the second argument to popup_create
Expand Down
3 changes: 3 additions & 0 deletions cmd/govim/config/gen_applygen.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ func (r *Config) Apply(v *Config) {
if v.ExperimentalTempModfile != nil {
r.ExperimentalTempModfile = v.ExperimentalTempModfile
}
if v.GoplsEnv != nil {
r.GoplsEnv = v.GoplsEnv
}
if v.ExperimentalMouseTriggeredHoverPopupOptions != nil {
r.ExperimentalMouseTriggeredHoverPopupOptions = v.ExperimentalMouseTriggeredHoverPopupOptions
}
Expand Down
6 changes: 6 additions & 0 deletions cmd/govim/gopls_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const (
goplsCompletionBudget = "completionBudget"
goplsTempModfile = "tempModfile"
goplsVerboseOutput = "verboseOutput"
goplsEnv = "env"
)

var _ protocol.Client = (*govimplugin)(nil)
Expand Down Expand Up @@ -155,6 +156,11 @@ func (g *govimplugin) Configuration(ctxt context.Context, params *protocol.Param
if os.Getenv(string(config.EnvVarGoplsVerbose)) == "true" {
goplsConfig[goplsVerboseOutput] = true
}
if g.vimstate.config.GoplsEnv != nil {
// It is safe not to copy the map here because a new config setting from
// Vim creates a new map.
goplsConfig[goplsEnv] = *conf.GoplsEnv
}
res[0] = goplsConfig

g.logGoplsClientf("Configuration response: %v", pretty.Sprint(res))
Expand Down
41 changes: 29 additions & 12 deletions cmd/govim/internal/vimconfig/vimconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,26 @@ type VimConfig struct {
GoImportsLocalPrefix *string
CompletionBudget *string
ExperimentalTempModfile *int
GoplsEnv *map[string]string
ExperimentalMouseTriggeredHoverPopupOptions *map[string]interface{}
ExperimentalCursorTriggeredHoverPopupOptions *map[string]interface{}
}

func (c *VimConfig) ToConfig(d config.Config) config.Config {
v := config.Config{
FormatOnSave: c.FormatOnSave,
QuickfixSigns: boolVal(c.QuickfixSigns, d.QuickfixSigns),
QuickfixAutoDiagnostics: boolVal(c.QuickfixAutoDiagnostics, d.QuickfixAutoDiagnostics),
HighlightDiagnostics: boolVal(c.HighlightDiagnostics, d.HighlightDiagnostics),
HoverDiagnostics: boolVal(c.HoverDiagnostics, d.HoverDiagnostics),
CompletionDeepCompletions: boolVal(c.CompletionDeepCompletions, d.CompletionDeepCompletions),
CompletionMatcher: c.CompletionMatcher,
Staticcheck: boolVal(c.Staticcheck, d.Staticcheck),
CompleteUnimported: boolVal(c.CompleteUnimported, d.CompleteUnimported),
GoImportsLocalPrefix: stringVal(c.GoImportsLocalPrefix, d.GoImportsLocalPrefix),
CompletionBudget: stringVal(c.CompletionBudget, d.CompletionBudget),
ExperimentalTempModfile: boolVal(c.ExperimentalTempModfile, d.ExperimentalTempModfile),
FormatOnSave: c.FormatOnSave,
QuickfixSigns: boolVal(c.QuickfixSigns, d.QuickfixSigns),
QuickfixAutoDiagnostics: boolVal(c.QuickfixAutoDiagnostics, d.QuickfixAutoDiagnostics),
HighlightDiagnostics: boolVal(c.HighlightDiagnostics, d.HighlightDiagnostics),
HoverDiagnostics: boolVal(c.HoverDiagnostics, d.HoverDiagnostics),
CompletionDeepCompletions: boolVal(c.CompletionDeepCompletions, d.CompletionDeepCompletions),
CompletionMatcher: c.CompletionMatcher,
Staticcheck: boolVal(c.Staticcheck, d.Staticcheck),
CompleteUnimported: boolVal(c.CompleteUnimported, d.CompleteUnimported),
GoImportsLocalPrefix: stringVal(c.GoImportsLocalPrefix, d.GoImportsLocalPrefix),
CompletionBudget: stringVal(c.CompletionBudget, d.CompletionBudget),
ExperimentalTempModfile: boolVal(c.ExperimentalTempModfile, d.ExperimentalTempModfile),
GoplsEnv: copyStringValMap(c.GoplsEnv, d.GoplsEnv),
ExperimentalMouseTriggeredHoverPopupOptions: copyMap(c.ExperimentalMouseTriggeredHoverPopupOptions, d.ExperimentalMouseTriggeredHoverPopupOptions),
ExperimentalCursorTriggeredHoverPopupOptions: copyMap(c.ExperimentalCursorTriggeredHoverPopupOptions, d.ExperimentalCursorTriggeredHoverPopupOptions),
}
Expand Down Expand Up @@ -64,6 +66,21 @@ func stringVal(i, j *string) *string {
return i
}

func copyStringValMap(i, j *map[string]string) *map[string]string {
toCopy := i
if i == nil {
toCopy = j
if j == nil {
return nil
}
}
res := make(map[string]string)
for ck, cv := range *toCopy {
res[ck] = cv
}
return &res
}

func copyMap(i, j *map[string]interface{}) *map[string]interface{} {
toCopy := i
if i == nil {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Test that calling govim#config#Set with a value for GoplsEnv of GOFLAGS
# does the right thing. This will necessarily involve a number of checks
# for the various build flags that can be set via GOFLAGS.

[short] skip 'Skip short because we sleep for GOVIM_ERRLOGMATCH_WAIT to ensure we don''t have any errors'

vim ex 'e main.go'
vimexprwait pre.golden getqflist()
vim ex 'w'

# We have to sleep here because there is no event we are waiting for
sleep $GOVIM_ERRLOGMATCH_WAIT

# Verify go.mod has not changed
cmp go.mod go.mod.golden.pre

# Change go.mod from outside Vim
exec go get example.com/blah@v1.0.0
exec go mod tidy
cmp go.mod go.mod.golden.post

# Verify the diagnostic has been updated
vimexprwait post.golden getqflist()

# Disabled pending resolution to https://github.com/golang/go/issues/34103
# errlogmatch -count=0 'LogMessage callback: &protocol\.LogMessageParams\{Type:(1|2), Message:".*'

-- go.mod --
module mod.com

go 1.13
-- go.mod.golden.pre --
module mod.com

go 1.13
-- go.mod.golden.post --
module mod.com

go 1.13

require example.com/blah v1.0.0
-- main.go --
package main

import "example.com/blah"

func main() {
println(blah.Name)
}
-- pre.golden --
[
{
"bufnr": 1,
"col": 8,
"lnum": 3,
"module": "",
"nr": 0,
"pattern": "",
"text": "could not import example.com/blah (no package for import example.com/blah)",
"type": "",
"valid": 1,
"vcol": 0
}
]
-- post.golden --
[]
3 changes: 3 additions & 0 deletions cmd/govim/testdata/scenario_modreadonly/user_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"GoplsEnv": {"GOFLAGS": "-mod=readonly"}
}

0 comments on commit e79b68f

Please sign in to comment.