golang.org/x/tools/gopls@v0.15.3/internal/test/integration/misc/configuration_test.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package misc 6 7 import ( 8 "testing" 9 10 . "golang.org/x/tools/gopls/internal/test/integration" 11 12 "golang.org/x/tools/internal/testenv" 13 ) 14 15 // Test that enabling and disabling produces the expected results of showing 16 // and hiding staticcheck analysis results. 17 func TestChangeConfiguration(t *testing.T) { 18 // Staticcheck only supports Go versions >= 1.19. 19 // Note: keep this in sync with TestStaticcheckWarning. Below this version we 20 // should get an error when setting staticcheck configuration. 21 testenv.NeedsGo1Point(t, 20) 22 23 const files = ` 24 -- go.mod -- 25 module mod.com 26 27 go 1.12 28 -- a/a.go -- 29 package a 30 31 import "errors" 32 33 // FooErr should be called ErrFoo (ST1012) 34 var FooErr = errors.New("foo") 35 ` 36 Run(t, files, func(t *testing.T, env *Env) { 37 env.OpenFile("a/a.go") 38 env.AfterChange( 39 NoDiagnostics(ForFile("a/a.go")), 40 ) 41 cfg := env.Editor.Config() 42 cfg.Settings = map[string]any{ 43 "staticcheck": true, 44 } 45 env.ChangeConfiguration(cfg) 46 env.AfterChange( 47 Diagnostics(env.AtRegexp("a/a.go", "var (FooErr)")), 48 ) 49 }) 50 } 51 52 func TestIdenticalConfiguration(t *testing.T) { 53 // This test checks that changing configuration does not cause views to be 54 // recreated if there is no configuration change. 55 const files = ` 56 -- a.go -- 57 package p 58 59 func _() { 60 var x *int 61 y := *x 62 _ = y 63 } 64 ` 65 Run(t, files, func(t *testing.T, env *Env) { 66 // Sanity check: before disabling the nilness analyzer, we should have a 67 // diagnostic for the nil dereference. 68 env.OpenFile("a.go") 69 env.AfterChange( 70 Diagnostics( 71 ForFile("a.go"), 72 WithMessage("nil dereference"), 73 ), 74 ) 75 76 // Collect the view ID before changing configuration. 77 viewID := func() string { 78 t.Helper() 79 views := env.Views() 80 if len(views) != 1 { 81 t.Fatalf("got %d views, want 1", len(views)) 82 } 83 return views[0].ID 84 } 85 before := viewID() 86 87 // Now disable the nilness analyzer. 88 cfg := env.Editor.Config() 89 cfg.Settings = map[string]any{ 90 "analyses": map[string]any{ 91 "nilness": false, 92 }, 93 } 94 95 // This should cause the diagnostic to disappear... 96 env.ChangeConfiguration(cfg) 97 env.AfterChange( 98 NoDiagnostics(), 99 ) 100 // ...and we should be on the second view. 101 after := viewID() 102 if after == before { 103 t.Errorf("after configuration change, got view %q (same as before), want new view", after) 104 } 105 106 // Now change configuration again, this time with the same configuration as 107 // before. We should still have no diagnostics... 108 env.ChangeConfiguration(cfg) 109 env.AfterChange( 110 NoDiagnostics(), 111 ) 112 // ...and we should still be on the second view. 113 if got := viewID(); got != after { 114 t.Errorf("after second configuration change, got view %q, want %q", got, after) 115 } 116 }) 117 } 118 119 // Test that clients can configure per-workspace configuration, which is 120 // queried via the scopeURI of a workspace/configuration request. 121 // (this was broken in golang/go#65519). 122 func TestWorkspaceConfiguration(t *testing.T) { 123 const files = ` 124 -- go.mod -- 125 module example.com/config 126 127 go 1.18 128 129 -- a/a.go -- 130 package a 131 132 import "example.com/config/b" 133 134 func _() { 135 _ = b.B{2} 136 } 137 138 -- b/b.go -- 139 package b 140 141 type B struct { 142 F int 143 } 144 ` 145 146 WithOptions( 147 WorkspaceFolders("a"), 148 FolderSettings{ 149 "a": { 150 "analyses": map[string]bool{ 151 "composites": false, 152 }, 153 }, 154 }, 155 ).Run(t, files, func(t *testing.T, env *Env) { 156 env.OpenFile("a/a.go") 157 env.AfterChange(NoDiagnostics()) 158 }) 159 } 160 161 // TestMajorOptionsChange is like TestChangeConfiguration, but modifies an 162 // an open buffer before making a major (but inconsequential) change that 163 // causes gopls to recreate the view. 164 // 165 // Gopls should not get confused about buffer content when recreating the view. 166 func TestMajorOptionsChange(t *testing.T) { 167 testenv.NeedsGo1Point(t, 20) // needs staticcheck 168 169 const files = ` 170 -- go.mod -- 171 module mod.com 172 173 go 1.12 174 -- a/a.go -- 175 package a 176 177 import "errors" 178 179 var ErrFoo = errors.New("foo") 180 ` 181 Run(t, files, func(t *testing.T, env *Env) { 182 env.OpenFile("a/a.go") 183 // Introduce a staticcheck diagnostic. It should be detected when we enable 184 // staticcheck later. 185 env.RegexpReplace("a/a.go", "ErrFoo", "FooErr") 186 env.AfterChange( 187 NoDiagnostics(ForFile("a/a.go")), 188 ) 189 cfg := env.Editor.Config() 190 // Any change to environment recreates the view, but this should not cause 191 // gopls to get confused about the content of a/a.go: we should get the 192 // staticcheck diagnostic below. 193 cfg.Env = map[string]string{ 194 "AN_ARBITRARY_VAR": "FOO", 195 } 196 cfg.Settings = map[string]interface{}{ 197 "staticcheck": true, 198 } 199 env.ChangeConfiguration(cfg) 200 env.AfterChange( 201 Diagnostics(env.AtRegexp("a/a.go", "var (FooErr)")), 202 ) 203 }) 204 } 205 206 func TestStaticcheckWarning(t *testing.T) { 207 // Note: keep this in sync with TestChangeConfiguration. 208 testenv.SkipAfterGo1Point(t, 19) 209 210 const files = ` 211 -- go.mod -- 212 module mod.com 213 214 go 1.12 215 -- a/a.go -- 216 package a 217 218 import "errors" 219 220 // FooErr should be called ErrFoo (ST1012) 221 var FooErr = errors.New("foo") 222 ` 223 224 WithOptions( 225 Settings{"staticcheck": true}, 226 ).Run(t, files, func(t *testing.T, env *Env) { 227 env.OnceMet( 228 InitialWorkspaceLoad, 229 ShownMessage("staticcheck is not supported"), 230 ) 231 }) 232 } 233 234 func TestGofumptWarning(t *testing.T) { 235 testenv.SkipAfterGo1Point(t, 17) 236 237 WithOptions( 238 Settings{"gofumpt": true}, 239 ).Run(t, "", func(t *testing.T, env *Env) { 240 env.OnceMet( 241 InitialWorkspaceLoad, 242 ShownMessage("gofumpt is not supported"), 243 ) 244 }) 245 } 246 247 func TestDeprecatedSettings(t *testing.T) { 248 WithOptions( 249 Settings{ 250 "experimentalUseInvalidMetadata": true, 251 "experimentalWatchedFileDelay": "1s", 252 "experimentalWorkspaceModule": true, 253 "tempModfile": true, 254 "allowModfileModifications": true, 255 }, 256 ).Run(t, "", func(t *testing.T, env *Env) { 257 env.OnceMet( 258 InitialWorkspaceLoad, 259 ShownMessage("experimentalWorkspaceModule"), 260 ShownMessage("experimentalUseInvalidMetadata"), 261 ShownMessage("experimentalWatchedFileDelay"), 262 ShownMessage("tempModfile"), 263 ShownMessage("allowModfileModifications"), 264 ) 265 }) 266 }