golang.org/x/tools/gopls@v0.15.3/internal/test/integration/workspace/metadata_test.go (about) 1 // Copyright 2022 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 workspace 6 7 import ( 8 "strings" 9 "testing" 10 11 . "golang.org/x/tools/gopls/internal/test/integration" 12 ) 13 14 // TODO(rfindley): move workspace tests related to metadata bugs into this 15 // file. 16 17 func TestFixImportDecl(t *testing.T) { 18 const src = ` 19 -- go.mod -- 20 module mod.test 21 22 go 1.12 23 -- p.go -- 24 package p 25 26 import ( 27 _ "fmt" 28 29 const C = 42 30 ` 31 32 Run(t, src, func(t *testing.T, env *Env) { 33 env.OpenFile("p.go") 34 env.RegexpReplace("p.go", "\"fmt\"", "\"fmt\"\n)") 35 env.AfterChange( 36 NoDiagnostics(ForFile("p.go")), 37 ) 38 }) 39 } 40 41 // Test that moving ignoring a file via build constraints causes diagnostics to 42 // be resolved. 43 func TestIgnoreFile(t *testing.T) { 44 const src = ` 45 -- go.mod -- 46 module mod.test 47 48 go 1.12 49 -- foo.go -- 50 package main 51 52 func main() {} 53 -- bar.go -- 54 package main 55 56 func main() {} 57 ` 58 59 Run(t, src, func(t *testing.T, env *Env) { 60 env.OpenFile("foo.go") 61 env.OpenFile("bar.go") 62 env.OnceMet( 63 env.DoneWithOpen(), 64 Diagnostics(env.AtRegexp("foo.go", "func (main)")), 65 Diagnostics(env.AtRegexp("bar.go", "func (main)")), 66 ) 67 68 // Ignore bar.go. This should resolve diagnostics. 69 env.RegexpReplace("bar.go", "package main", "//go:build ignore\n\npackage main") 70 71 // To make this test pass with experimentalUseInvalidMetadata, we could make 72 // an arbitrary edit that invalidates the snapshot, at which point the 73 // orphaned diagnostics will be invalidated. 74 // 75 // But of course, this should not be necessary: we should invalidate stale 76 // information when fresh metadata arrives. 77 // env.RegexpReplace("foo.go", "package main", "package main // test") 78 env.AfterChange( 79 NoDiagnostics(ForFile("foo.go")), 80 NoDiagnostics(ForFile("bar.go")), 81 ) 82 83 // If instead of 'ignore' (which gopls treats as a standalone package) we 84 // used a different build tag, we should get a warning about having no 85 // packages for bar.go 86 env.RegexpReplace("bar.go", "ignore", "excluded") 87 env.AfterChange( 88 Diagnostics(env.AtRegexp("bar.go", "package (main)"), WithMessage("excluded due to its build tags")), 89 ) 90 }) 91 } 92 93 func TestReinitializeRepeatedly(t *testing.T) { 94 const multiModule = ` 95 -- go.work -- 96 go 1.18 97 98 use ( 99 moda/a 100 modb 101 ) 102 -- moda/a/go.mod -- 103 module a.com 104 105 require b.com v1.2.3 106 -- moda/a/go.sum -- 107 b.com v1.2.3 h1:tXrlXP0rnjRpKNmkbLYoWBdq0ikb3C3bKK9//moAWBI= 108 b.com v1.2.3/go.mod h1:D+J7pfFBZK5vdIdZEFquR586vKKIkqG7Qjw9AxG5BQ8= 109 -- moda/a/a.go -- 110 package a 111 112 import ( 113 "b.com/b" 114 ) 115 116 func main() { 117 var x int 118 _ = b.Hello() 119 // AAA 120 } 121 -- modb/go.mod -- 122 module b.com 123 124 -- modb/b/b.go -- 125 package b 126 127 func Hello() int { 128 var x int 129 } 130 ` 131 WithOptions( 132 ProxyFiles(workspaceModuleProxy), 133 Settings{ 134 // For this test, we want workspace diagnostics to start immediately 135 // during change processing. 136 "diagnosticsDelay": "0", 137 }, 138 ).Run(t, multiModule, func(t *testing.T, env *Env) { 139 env.OpenFile("moda/a/a.go") 140 env.AfterChange() 141 142 // This test verifies that we fully process workspace reinitialization 143 // (which allows GOPROXY), even when the reinitialized snapshot is 144 // invalidated by subsequent changes. 145 // 146 // First, update go.work to remove modb. This will cause reinitialization 147 // to fetch b.com from the proxy. 148 env.WriteWorkspaceFile("go.work", "go 1.18\nuse moda/a") 149 // Next, wait for gopls to start processing the change. Because we've set 150 // diagnosticsDelay to zero, this will start diagnosing the workspace (and 151 // try to reinitialize on the snapshot context). 152 env.Await(env.StartedChangeWatchedFiles()) 153 // Finally, immediately make a file change to cancel the previous 154 // operation. This is racy, but will usually cause initialization to be 155 // canceled. 156 env.RegexpReplace("moda/a/a.go", "AAA", "BBB") 157 env.AfterChange() 158 // Now, to satisfy a definition request, gopls will try to reload moda. But 159 // without access to the proxy (because this is no longer a 160 // reinitialization), this loading will fail. 161 loc := env.GoToDefinition(env.RegexpSearch("moda/a/a.go", "Hello")) 162 got := env.Sandbox.Workdir.URIToPath(loc.URI) 163 if want := "b.com@v1.2.3/b/b.go"; !strings.HasSuffix(got, want) { 164 t.Errorf("expected %s, got %v", want, got) 165 } 166 }) 167 } 168 169 // Test for golang/go#59458. With lazy module loading, we may not need 170 // transitively required modules. 171 func TestNestedModuleLoading_Issue59458(t *testing.T) { 172 // In this test, module b.com/nested requires b.com/other, which in turn 173 // requires b.com, but b.com/nested does not reach b.com through the package 174 // graph. Therefore, b.com/nested does not need b.com on 1.17 and later, 175 // thanks to graph pruning. 176 // 177 // We verify that we can load b.com/nested successfully. Previously, we 178 // couldn't, because loading the pattern b.com/nested/... matched the module 179 // b.com, which exists in the module graph but does not have a go.sum entry. 180 181 const proxy = ` 182 -- b.com@v1.2.3/go.mod -- 183 module b.com 184 185 go 1.18 186 -- b.com@v1.2.3/b/b.go -- 187 package b 188 189 func Hello() {} 190 191 -- b.com/other@v1.4.6/go.mod -- 192 module b.com/other 193 194 go 1.18 195 196 require b.com v1.2.3 197 -- b.com/other@v1.4.6/go.sun -- 198 b.com v1.2.3 h1:AGjCxWRJLUuJiZ21IUTByr9buoa6+B6Qh5LFhVLKpn4= 199 -- b.com/other@v1.4.6/bar/bar.go -- 200 package bar 201 202 import "b.com/b" 203 204 func _() { 205 b.Hello() 206 } 207 -- b.com/other@v1.4.6/foo/foo.go -- 208 package foo 209 210 const Foo = 0 211 ` 212 213 const files = ` 214 -- go.mod -- 215 module b.com/nested 216 217 go 1.18 218 219 require b.com/other v1.4.6 220 -- go.sum -- 221 b.com/other v1.4.6 h1:pHXSzGsk6DamYXp9uRdDB9A/ZQqAN9it+JudU0sBf94= 222 b.com/other v1.4.6/go.mod h1:T0TYuGdAHw4p/l0+1P/yhhYHfZRia7PaadNVDu58OWM= 223 -- nested.go -- 224 package nested 225 226 import "b.com/other/foo" 227 228 const C = foo.Foo 229 ` 230 WithOptions( 231 ProxyFiles(proxy), 232 ).Run(t, files, func(t *testing.T, env *Env) { 233 env.OnceMet( 234 InitialWorkspaceLoad, 235 NoDiagnostics(), 236 ) 237 }) 238 }