Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools / gopls@v0.5.2 / internal / regtest / diagnostics_test.go
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 regtest
6
7 import (
8         "context"
9         "fmt"
10         "log"
11         "os"
12         "testing"
13         "time"
14
15         "golang.org/x/tools/internal/lsp"
16         "golang.org/x/tools/internal/lsp/fake"
17         "golang.org/x/tools/internal/lsp/protocol"
18         "golang.org/x/tools/internal/lsp/tests"
19         "golang.org/x/tools/internal/testenv"
20 )
21
22 // Use mod.com for all go.mod files due to golang/go#35230.
23 const exampleProgram = `
24 -- go.mod --
25 module mod.com
26
27 go 1.12
28 -- main.go --
29 package main
30
31 import "fmt"
32
33 func main() {
34         fmt.Println("Hello World.")
35 }`
36
37 func TestDiagnosticErrorInEditedFile(t *testing.T) {
38         // This test is very basic: start with a clean Go program, make an error, and
39         // get a diagnostic for that error. However, it also demonstrates how to
40         // combine Expectations to await more complex state in the editor.
41         runner.Run(t, exampleProgram, func(t *testing.T, env *Env) {
42                 // Deleting the 'n' at the end of Println should generate a single error
43                 // diagnostic.
44                 env.OpenFile("main.go")
45                 env.RegexpReplace("main.go", "Printl(n)", "")
46                 env.Await(
47                         // Once we have gotten diagnostics for the change above, we should
48                         // satisfy the DiagnosticAtRegexp assertion.
49                         OnceMet(
50                                 CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 1),
51                                 env.DiagnosticAtRegexp("main.go", "Printl"),
52                         ),
53                         // Assert that this test has sent no error logs to the client. This is not
54                         // strictly necessary for testing this regression, but is included here
55                         // as an example of using the NoErrorLogs() expectation. Feel free to
56                         // delete.
57                         NoErrorLogs(),
58                 )
59         })
60 }
61
62 func TestMissingImportDiagsClearOnFirstFile(t *testing.T) {
63         const onlyMod = `
64 -- go.mod --
65 module mod.com
66
67 go 1.12
68 `
69         runner.Run(t, onlyMod, func(t *testing.T, env *Env) {
70                 env.CreateBuffer("main.go", `package main
71
72 func m() {
73         log.Println()
74 }
75 `)
76                 env.Await(
77                         env.DiagnosticAtRegexp("main.go", "log"),
78                 )
79                 env.SaveBuffer("main.go")
80                 env.Await(
81                         EmptyDiagnostics("main.go"),
82                 )
83         })
84 }
85
86 func TestDiagnosticErrorInNewFile(t *testing.T) {
87         const brokenFile = `package main
88
89 const Foo = "abc
90 `
91         runner.Run(t, brokenFile, func(t *testing.T, env *Env) {
92                 env.CreateBuffer("broken.go", brokenFile)
93                 env.Await(env.DiagnosticAtRegexp("broken.go", "\"abc"))
94         })
95 }
96
97 // badPackage contains a duplicate definition of the 'a' const.
98 const badPackage = `
99 -- go.mod --
100 module mod.com
101
102 go 1.12
103 -- a.go --
104 package consts
105
106 const a = 1
107 -- b.go --
108 package consts
109
110 const a = 2
111 `
112
113 func TestDiagnosticClearingOnEdit(t *testing.T) {
114         runner.Run(t, badPackage, func(t *testing.T, env *Env) {
115                 env.OpenFile("b.go")
116                 env.Await(env.DiagnosticAtRegexp("a.go", "a = 1"), env.DiagnosticAtRegexp("b.go", "a = 2"))
117
118                 // Fix the error by editing the const name in b.go to `b`.
119                 env.RegexpReplace("b.go", "(a) = 2", "b")
120                 env.Await(
121                         EmptyDiagnostics("a.go"),
122                         EmptyDiagnostics("b.go"),
123                 )
124         })
125 }
126
127 func TestDiagnosticClearingOnDelete_Issue37049(t *testing.T) {
128         runner.Run(t, badPackage, func(t *testing.T, env *Env) {
129                 env.OpenFile("a.go")
130                 env.Await(env.DiagnosticAtRegexp("a.go", "a = 1"), env.DiagnosticAtRegexp("b.go", "a = 2"))
131                 env.RemoveWorkspaceFile("b.go")
132
133                 env.Await(EmptyDiagnostics("a.go"), EmptyDiagnostics("b.go"))
134         })
135 }
136
137 func TestDiagnosticClearingOnClose(t *testing.T) {
138         runner.Run(t, badPackage, func(t *testing.T, env *Env) {
139                 env.CreateBuffer("c.go", `package consts
140
141 const a = 3`)
142                 env.Await(
143                         env.DiagnosticAtRegexp("a.go", "a = 1"),
144                         env.DiagnosticAtRegexp("b.go", "a = 2"),
145                         env.DiagnosticAtRegexp("c.go", "a = 3"))
146                 env.CloseBuffer("c.go")
147                 env.Await(
148                         env.DiagnosticAtRegexp("a.go", "a = 1"),
149                         env.DiagnosticAtRegexp("b.go", "a = 2"),
150                         EmptyDiagnostics("c.go"))
151         })
152 }
153
154 // Tests golang/go#37978.
155 func TestIssue37978(t *testing.T) {
156         runner.Run(t, exampleProgram, func(t *testing.T, env *Env) {
157                 // Create a new workspace-level directory and empty file.
158                 env.CreateBuffer("c/c.go", "")
159
160                 // Write the file contents with a missing import.
161                 env.EditBuffer("c/c.go", fake.Edit{
162                         Text: `package c
163
164 const a = http.MethodGet
165 `,
166                 })
167                 env.Await(
168                         env.DiagnosticAtRegexp("c/c.go", "http.MethodGet"),
169                 )
170                 // Save file, which will organize imports, adding the expected import.
171                 // Expect the diagnostics to clear.
172                 env.SaveBuffer("c/c.go")
173                 env.Await(
174                         EmptyDiagnostics("c/c.go"),
175                 )
176         })
177 }
178
179 // Tests golang/go#38878: good a.go, bad a_test.go, remove a_test.go but its errors remain
180 // If the file is open in the editor, this is working as intended
181 // If the file is not open in the editor, the errors go away
182 const test38878 = `
183 -- go.mod --
184 module foo
185
186 -- a.go --
187 package x
188
189 func f() {}
190
191 -- a_test.go --
192 package x
193
194 import "testing"
195
196 func TestA(t *testing.T) {
197         f(3)
198 }
199 `
200
201 func TestRmTest38878Close(t *testing.T) {
202         runner.Run(t, test38878, func(t *testing.T, env *Env) {
203                 env.OpenFile("a_test.go")
204                 env.Await(DiagnosticAt("a_test.go", 5, 3))
205                 env.CloseBuffer("a_test.go")
206                 env.RemoveWorkspaceFile("a_test.go")
207                 // diagnostics go away
208                 env.Await(EmptyDiagnostics("a_test.go"))
209         })
210 }
211
212 func TestRmTest38878(t *testing.T) {
213         log.SetFlags(log.Lshortfile)
214         runner.Run(t, test38878, func(t *testing.T, env *Env) {
215                 env.OpenFile("a_test.go")
216                 env.Await(DiagnosticAt("a_test.go", 5, 3))
217                 env.Sandbox.Workdir.RemoveFile(context.Background(), "a_test.go")
218                 // diagnostics remain after giving gopls a chance to do something
219                 // (there is not yet a better way to decide gopls isn't going
220                 // to do anything)
221                 time.Sleep(time.Second)
222                 env.Await(DiagnosticAt("a_test.go", 5, 3))
223         })
224 }
225
226 // TestNoMod confirms that gopls continues to work when a user adds a go.mod
227 // file to their workspace.
228 func TestNoMod(t *testing.T) {
229         const noMod = `
230 -- main.go --
231 package main
232
233 import "mod.com/bob"
234
235 func main() {
236         bob.Hello()
237 }
238 -- bob/bob.go --
239 package bob
240
241 func Hello() {
242         var x int
243 }
244 `
245
246         t.Run("manual", func(t *testing.T) {
247                 runner.Run(t, noMod, func(t *testing.T, env *Env) {
248                         env.Await(
249                                 env.DiagnosticAtRegexp("main.go", `"mod.com/bob"`),
250                         )
251                         env.CreateBuffer("go.mod", `module mod.com
252
253         go 1.12
254 `)
255                         env.SaveBuffer("go.mod")
256                         env.Await(
257                                 EmptyDiagnostics("main.go"),
258                         )
259                         var d protocol.PublishDiagnosticsParams
260                         env.Await(
261                                 OnceMet(
262                                         env.DiagnosticAtRegexp("bob/bob.go", "x"),
263                                         ReadDiagnostics("bob/bob.go", &d),
264                                 ),
265                         )
266                         if len(d.Diagnostics) != 1 {
267                                 t.Fatalf("expected 1 diagnostic, got %v", len(d.Diagnostics))
268                         }
269                 })
270         })
271         t.Run("initialized", func(t *testing.T) {
272                 runner.Run(t, noMod, func(t *testing.T, env *Env) {
273                         env.Await(
274                                 env.DiagnosticAtRegexp("main.go", `"mod.com/bob"`),
275                         )
276                         env.RunGoCommand("mod", "init", "mod.com")
277                         env.Await(
278                                 EmptyDiagnostics("main.go"),
279                                 env.DiagnosticAtRegexp("bob/bob.go", "x"),
280                         )
281                 })
282         })
283
284         t.Run("without workspace module", func(t *testing.T) {
285                 withOptions(
286                         WithModes(WithoutExperiments),
287                 ).run(t, noMod, func(t *testing.T, env *Env) {
288                         env.Await(
289                                 env.DiagnosticAtRegexp("main.go", `"mod.com/bob"`),
290                         )
291                         if err := env.Sandbox.RunGoCommand(env.Ctx, "", "mod", []string{"init", "mod.com"}); err != nil {
292                                 t.Fatal(err)
293                         }
294                         env.Await(
295                                 EmptyDiagnostics("main.go"),
296                                 env.DiagnosticAtRegexp("bob/bob.go", "x"),
297                         )
298                 })
299         })
300 }
301
302 // Tests golang/go#38267.
303 func TestIssue38267(t *testing.T) {
304         const testPackage = `
305 -- go.mod --
306 module mod.com
307
308 go 1.12
309 -- lib.go --
310 package lib
311
312 func Hello(x string) {
313         _ = x
314 }
315 -- lib_test.go --
316 package lib
317
318 import "testing"
319
320 type testStruct struct{
321         name string
322 }
323
324 func TestHello(t *testing.T) {
325         testStructs := []*testStruct{
326                 &testStruct{"hello"},
327                 &testStruct{"goodbye"},
328         }
329         for y := range testStructs {
330                 _ = y
331         }
332 }
333 `
334
335         runner.Run(t, testPackage, func(t *testing.T, env *Env) {
336                 env.OpenFile("lib_test.go")
337                 env.Await(
338                         DiagnosticAt("lib_test.go", 10, 2),
339                         DiagnosticAt("lib_test.go", 11, 2),
340                 )
341                 env.OpenFile("lib.go")
342                 env.RegexpReplace("lib.go", "_ = x", "var y int")
343                 env.Await(
344                         env.DiagnosticAtRegexp("lib.go", "y int"),
345                         EmptyDiagnostics("lib_test.go"),
346                 )
347         })
348 }
349
350 // Tests golang/go#38328.
351 func TestPackageChange_Issue38328(t *testing.T) {
352         const packageChange = `
353 -- go.mod --
354 module fake
355 -- a.go --
356 package foo
357 func main() {}
358 `
359         runner.Run(t, packageChange, func(t *testing.T, env *Env) {
360                 env.OpenFile("a.go")
361                 env.RegexpReplace("a.go", "foo", "foox")
362                 env.Await(
363                         // When the bug reported in #38328 was present, we didn't get erroneous
364                         // file diagnostics until after the didChange message generated by the
365                         // package renaming was fully processed. Therefore, in order for this
366                         // test to actually exercise the bug, we must wait until that work has
367                         // completed.
368                         OnceMet(
369                                 CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 1),
370                                 NoDiagnostics("a.go"),
371                         ),
372                 )
373         })
374 }
375
376 const testPackageWithRequire = `
377 -- go.mod --
378 module mod.com
379
380 go 1.12
381
382 require (
383         foo.test v1.2.3
384 )
385 -- print.go --
386 package lib
387
388 import (
389         "fmt"
390
391         "foo.test/bar"
392 )
393
394 func PrintAnswer() {
395         fmt.Printf("answer: %s", bar.Answer)
396 }
397 `
398
399 const testPackageWithRequireProxy = `
400 -- foo.test@v1.2.3/go.mod --
401 module foo.test
402
403 go 1.12
404 -- foo.test@v1.2.3/bar/const.go --
405 package bar
406
407 const Answer = 42
408 `
409
410 func TestResolveDiagnosticWithDownload(t *testing.T) {
411         runner.Run(t, testPackageWithRequire, func(t *testing.T, env *Env) {
412                 env.OpenFile("print.go")
413                 // Check that gopackages correctly loaded this dependency. We should get a
414                 // diagnostic for the wrong formatting type.
415                 // TODO: we should be able to easily also match the diagnostic message.
416                 env.Await(env.DiagnosticAtRegexp("print.go", "fmt.Printf"))
417         }, WithProxyFiles(testPackageWithRequireProxy))
418 }
419
420 func TestMissingDependency(t *testing.T) {
421         runner.Run(t, testPackageWithRequire, func(t *testing.T, env *Env) {
422                 env.OpenFile("print.go")
423                 env.Await(LogMatching(protocol.Error, "initial workspace load failed", 1))
424         })
425 }
426
427 // Tests golang/go#36951.
428 func TestAdHocPackages_Issue36951(t *testing.T) {
429         const adHoc = `
430 -- b/b.go --
431 package b
432
433 func Hello() {
434         var x int
435 }
436 `
437         runner.Run(t, adHoc, func(t *testing.T, env *Env) {
438                 env.OpenFile("b/b.go")
439                 env.Await(env.DiagnosticAtRegexp("b/b.go", "x"))
440         })
441 }
442
443 // Tests golang/go#37984: GOPATH should be read from the go command.
444 func TestNoGOPATH_Issue37984(t *testing.T) {
445         const files = `
446 -- main.go --
447 package main
448
449 func _() {
450         fmt.Println("Hello World")
451 }
452 `
453         editorConfig := EditorConfig{Env: map[string]string{"GOPATH": ""}}
454         withOptions(editorConfig).run(t, files, func(t *testing.T, env *Env) {
455                 env.OpenFile("main.go")
456                 env.Await(env.DiagnosticAtRegexp("main.go", "fmt"))
457                 env.SaveBuffer("main.go")
458                 env.Await(EmptyDiagnostics("main.go"))
459         })
460 }
461
462 // Tests golang/go#38669.
463 func TestEqualInEnv_Issue38669(t *testing.T) {
464         const files = `
465 -- go.mod --
466 module mod.com
467
468 -- main.go --
469 package main
470
471 var _ = x.X
472 -- x/x.go --
473 package x
474
475 var X = 0
476 `
477         editorConfig := EditorConfig{Env: map[string]string{"GOFLAGS": "-tags=foo"}}
478         withOptions(editorConfig).run(t, files, func(t *testing.T, env *Env) {
479                 env.OpenFile("main.go")
480                 env.OrganizeImports("main.go")
481                 env.Await(EmptyDiagnostics("main.go"))
482         })
483 }
484
485 // Tests golang/go#38467.
486 func TestNoSuggestedFixesForGeneratedFiles_Issue38467(t *testing.T) {
487         const generated = `
488 -- go.mod --
489 module mod.com
490
491 -- main.go --
492 package main
493
494 // Code generated by generator.go. DO NOT EDIT.
495
496 func _() {
497         for i, _ := range []string{} {
498                 _ = i
499         }
500 }
501 `
502         runner.Run(t, generated, func(t *testing.T, env *Env) {
503                 env.OpenFile("main.go")
504                 original := env.ReadWorkspaceFile("main.go")
505                 var d protocol.PublishDiagnosticsParams
506                 env.Await(
507                         OnceMet(
508                                 DiagnosticAt("main.go", 5, 8),
509                                 ReadDiagnostics("main.go", &d),
510                         ),
511                 )
512                 // Apply fixes and save the buffer.
513                 env.ApplyQuickFixes("main.go", d.Diagnostics)
514                 env.SaveBuffer("main.go")
515                 fixed := env.ReadWorkspaceFile("main.go")
516                 if original != fixed {
517                         t.Fatalf("generated file was changed by quick fixes:\n%s", tests.Diff(original, fixed))
518                 }
519         })
520 }
521
522 // Expect a module/GOPATH error if there is an error in the file at startup.
523 // Tests golang/go#37279.
524 func TestShowMessage_Issue37279(t *testing.T) {
525         const noModule = `
526 -- a.go --
527 package foo
528
529 func f() {
530         fmt.Printl()
531 }
532 `
533         runner.Run(t, noModule, func(t *testing.T, env *Env) {
534                 env.OpenFile("a.go")
535                 env.Await(env.DiagnosticAtRegexp("a.go", "fmt.Printl"), ShownMessage(""))
536         })
537 }
538
539 // Expect no module/GOPATH error if there is no error in the file.
540 // Tests golang/go#37279.
541 func TestNoShowMessage_Issue37279(t *testing.T) {
542         const noModule = `
543 -- a.go --
544 package foo
545
546 func f() {
547 }
548 `
549         runner.Run(t, noModule, func(t *testing.T, env *Env) {
550                 env.OpenFile("a.go")
551                 env.Await(
552                         OnceMet(
553                                 CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1),
554                                 NoDiagnostics("a.go"),
555                         ),
556                         NoShowMessage(),
557                 )
558                 // introduce an error, expect no Show Message
559                 env.RegexpReplace("a.go", "func", "fun")
560                 env.Await(env.DiagnosticAtRegexp("a.go", "fun"), NoShowMessage())
561         })
562 }
563
564 func TestNonGoFolder(t *testing.T) {
565         const files = `
566 -- hello.txt --
567 hi mom
568 `
569         for _, go111module := range []string{"on", "off", ""} {
570                 t.Run(fmt.Sprintf("GO111MODULE_%v", go111module), func(t *testing.T) {
571                         withOptions(EditorConfig{
572                                 Env: map[string]string{"GO111MODULE": go111module},
573                         }).run(t, files, func(t *testing.T, env *Env) {
574                                 env.OpenFile("hello.txt")
575                                 env.Await(
576                                         OnceMet(
577                                                 CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1),
578                                                 NoShowMessage(),
579                                         ),
580                                 )
581                         })
582                 })
583         }
584 }
585
586 // Tests golang/go#38602.
587 func TestNonexistentFileDiagnostics_Issue38602(t *testing.T) {
588         const collision = `
589 -- x/x.go --
590 package x
591
592 import "x/hello"
593
594 func Hello() {
595         hello.HiThere()
596 }
597 -- x/main.go --
598 package main
599
600 func main() {
601         fmt.Println("")
602 }
603 `
604         runner.Run(t, collision, func(t *testing.T, env *Env) {
605                 env.OpenFile("x/main.go")
606                 env.Await(
607                         env.DiagnosticAtRegexp("x/main.go", "fmt.Println"),
608                 )
609                 env.OrganizeImports("x/main.go")
610                 // span.Parse misparses the error message when multiple packages are
611                 // defined in the same directory, creating a garbage filename.
612                 // Previously, we would send diagnostics for this nonexistent file.
613                 // This test checks that we don't send diagnostics for this file.
614                 dir, err := os.Getwd()
615                 if err != nil {
616                         t.Fatal(err)
617                 }
618                 badFile := fmt.Sprintf("%s/found packages main (main.go) and x (x.go) in %s/src/x", dir, env.Sandbox.GOPATH())
619                 env.Await(
620                         OnceMet(
621                                 CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 1),
622                                 EmptyDiagnostics("x/main.go"),
623                         ),
624                         NoDiagnostics(badFile),
625                 )
626         }, InGOPATH())
627 }
628
629 const ardanLabsProxy = `
630 -- github.com/ardanlabs/conf@v1.2.3/go.mod --
631 module github.com/ardanlabs/conf
632
633 go 1.12
634 -- github.com/ardanlabs/conf@v1.2.3/conf.go --
635 package conf
636
637 var ErrHelpWanted error
638 `
639
640 // Test for golang/go#38211.
641 func Test_Issue38211(t *testing.T) {
642         testenv.NeedsGo1Point(t, 14)
643         const ardanLabs = `
644 -- go.mod --
645 module mod.com
646
647 go 1.14
648 -- main.go --
649 package main
650
651 import "github.com/ardanlabs/conf"
652
653 func main() {
654         _ = conf.ErrHelpWanted
655 }
656 `
657         withOptions(
658                 WithProxyFiles(ardanLabsProxy),
659         ).run(t, ardanLabs, func(t *testing.T, env *Env) {
660                 // Expect a diagnostic with a suggested fix to add
661                 // "github.com/ardanlabs/conf" to the go.mod file.
662                 env.OpenFile("go.mod")
663                 env.OpenFile("main.go")
664                 var d protocol.PublishDiagnosticsParams
665                 env.Await(
666                         OnceMet(
667                                 env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`),
668                                 ReadDiagnostics("main.go", &d),
669                         ),
670                 )
671                 env.ApplyQuickFixes("main.go", d.Diagnostics)
672                 env.SaveBuffer("go.mod")
673                 env.Await(
674                         EmptyDiagnostics("main.go"),
675                 )
676                 // Comment out the line that depends on conf and expect a
677                 // diagnostic and a fix to remove the import.
678                 env.RegexpReplace("main.go", "_ = conf.ErrHelpWanted", "//_ = conf.ErrHelpWanted")
679                 env.Await(
680                         env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`),
681                 )
682                 env.SaveBuffer("main.go")
683                 // Expect a diagnostic and fix to remove the dependency in the go.mod.
684                 env.Await(EmptyDiagnostics("main.go"))
685                 env.Await(
686                         OnceMet(
687                                 env.DiagnosticAtRegexp("go.mod", "require github.com/ardanlabs/conf"),
688                                 ReadDiagnostics("go.mod", &d),
689                         ),
690                 )
691                 env.ApplyQuickFixes("go.mod", d.Diagnostics)
692                 env.SaveBuffer("go.mod")
693                 env.Await(
694                         EmptyDiagnostics("go.mod"),
695                 )
696                 // Uncomment the lines and expect a new diagnostic for the import.
697                 env.RegexpReplace("main.go", "//_ = conf.ErrHelpWanted", "_ = conf.ErrHelpWanted")
698                 env.SaveBuffer("main.go")
699                 env.Await(
700                         env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`),
701                 )
702         })
703 }
704
705 // Test for golang/go#38207.
706 func TestNewModule_Issue38207(t *testing.T) {
707         testenv.NeedsGo1Point(t, 14)
708         const emptyFile = `
709 -- go.mod --
710 module mod.com
711
712 go 1.12
713 -- main.go --
714 `
715         withOptions(
716                 WithProxyFiles(ardanLabsProxy),
717         ).run(t, emptyFile, func(t *testing.T, env *Env) {
718                 env.OpenFile("main.go")
719                 env.OpenFile("go.mod")
720                 env.EditBuffer("main.go", fake.NewEdit(0, 0, 0, 0, `package main
721
722 import "github.com/ardanlabs/conf"
723
724 func main() {
725         _ = conf.ErrHelpWanted
726 }
727 `))
728                 env.SaveBuffer("main.go")
729                 var d protocol.PublishDiagnosticsParams
730                 env.Await(
731                         OnceMet(
732                                 env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`),
733                                 ReadDiagnostics("main.go", &d),
734                         ),
735                 )
736                 env.ApplyQuickFixes("main.go", d.Diagnostics)
737                 env.Await(
738                         EmptyDiagnostics("main.go"),
739                 )
740         })
741 }
742
743 // Test for golang/go#36960.
744 func TestNewFileBadImports_Issue36960(t *testing.T) {
745         testenv.NeedsGo1Point(t, 14)
746         const simplePackage = `
747 -- go.mod --
748 module mod.com
749
750 go 1.14
751 -- a/a1.go --
752 package a
753
754 import "fmt"
755
756 func _() {
757         fmt.Println("hi")
758 }
759 `
760         runner.Run(t, simplePackage, func(t *testing.T, env *Env) {
761                 env.OpenFile("a/a1.go")
762                 env.CreateBuffer("a/a2.go", ``)
763                 if err := env.Editor.SaveBufferWithoutActions(env.Ctx, "a/a2.go"); err != nil {
764                         t.Fatal(err)
765                 }
766                 env.Await(
767                         OnceMet(
768                                 CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidSave), 1),
769                                 NoDiagnostics("a/a1.go"),
770                         ),
771                 )
772                 env.EditBuffer("a/a2.go", fake.NewEdit(0, 0, 0, 0, `package a`))
773                 env.Await(
774                         OnceMet(
775                                 CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 1),
776                                 NoDiagnostics("a/a1.go"),
777                         ),
778                 )
779         })
780 }
781
782 // This test tries to replicate the workflow of a user creating a new x test.
783 // It also tests golang/go#39315.
784 func TestManuallyCreatingXTest(t *testing.T) {
785         // Only for 1.15 because of golang/go#37971.
786         testenv.NeedsGo1Point(t, 15)
787
788         // Create a package that already has a test variant (in-package test).
789         const testVariant = `
790 -- go.mod --
791 module mod.com
792
793 go 1.15
794 -- hello/hello.go --
795 package hello
796
797 func Hello() {
798         var x int
799 }
800 -- hello/hello_test.go --
801 package hello
802
803 import "testing"
804
805 func TestHello(t *testing.T) {
806         var x int
807         Hello()
808 }
809 `
810         runner.Run(t, testVariant, func(t *testing.T, env *Env) {
811                 // Open the file, triggering the workspace load.
812                 // There are errors in the code to ensure all is working as expected.
813                 env.OpenFile("hello/hello.go")
814                 env.Await(
815                         env.DiagnosticAtRegexp("hello/hello.go", "x"),
816                         env.DiagnosticAtRegexp("hello/hello_test.go", "x"),
817                 )
818
819                 // Create an empty file with the intention of making it an x test.
820                 // This resembles a typical flow in an editor like VS Code, in which
821                 // a user would create an empty file and add content, saving
822                 // intermittently.
823                 // TODO(rstambler): There might be more edge cases here, as file
824                 // content can be added incrementally.
825                 env.CreateBuffer("hello/hello_x_test.go", ``)
826
827                 // Save the empty file (no actions since formatting will fail).
828                 env.Editor.SaveBufferWithoutActions(env.Ctx, "hello/hello_x_test.go")
829
830                 // Add the content. The missing import is for the package under test.
831                 env.EditBuffer("hello/hello_x_test.go", fake.NewEdit(0, 0, 0, 0, `package hello_test
832
833 import (
834         "testing"
835 )
836
837 func TestHello(t *testing.T) {
838         hello.Hello()
839 }
840 `))
841                 // Expect a diagnostic for the missing import. Save, which should
842                 // trigger import organization. The diagnostic should clear.
843                 env.Await(
844                         env.DiagnosticAtRegexp("hello/hello_x_test.go", "hello.Hello"),
845                 )
846                 env.SaveBuffer("hello/hello_x_test.go")
847                 env.Await(
848                         EmptyDiagnostics("hello/hello_x_test.go"),
849                 )
850         })
851 }
852
853 // Reproduce golang/go#40690.
854 func TestCreateOnlyXTest(t *testing.T) {
855         t.Skip("golang/go#40690 is not resolved yet.")
856
857         const mod = `
858         -- go.mod --
859         module mod.com
860         -- foo/foo.go --
861         package foo
862         -- foo/bar_test.go --
863         `
864         run(t, mod, func(t *testing.T, env *Env) {
865                 env.OpenFile("foo/bar_test.go")
866                 env.EditBuffer("foo/bar_test.go", fake.NewEdit(0, 0, 0, 0, `package foo
867         `))
868                 env.Await(
869                         CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 1),
870                 )
871                 env.RegexpReplace("foo/bar_test.go", "package foo", "package foo_test")
872                 env.Await(
873                         OnceMet(
874                                 CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 2),
875                                 NoErrorLogs(),
876                         ),
877                 )
878         })
879 }
880
881 func TestChangePackageName(t *testing.T) {
882         t.Skip("This issue hasn't been fixed yet. See golang.org/issue/41061.")
883
884         const mod = `
885 -- go.mod --
886 module mod.com
887 -- foo/foo.go --
888 package foo
889 -- foo/bar_test.go --
890 package foo_
891 `
892         run(t, mod, func(t *testing.T, env *Env) {
893                 env.OpenFile("foo/bar_test.go")
894                 env.RegexpReplace("foo/bar_test.go", "package foo_", "package foo_test")
895                 env.SaveBuffer("foo/bar_test.go")
896                 env.Await(
897                         OnceMet(
898                                 CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidSave), 1),
899                                 NoDiagnostics("foo/bar_test.go"),
900                         ),
901                         OnceMet(
902                                 CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidSave), 1),
903                                 NoDiagnostics("foo/foo.go"),
904                         ),
905                 )
906         })
907 }
908
909 // Reproduces golang/go#40825.
910 func TestEmptyGOPATHXTest_40825(t *testing.T) {
911         const files = `
912 -- x.go --
913 package x
914 -- x_test.go --
915 `
916
917         withOptions(InGOPATH()).run(t, files, func(t *testing.T, env *Env) {
918                 env.OpenFile("x_test.go")
919                 env.EditBuffer("x_test.go", fake.NewEdit(0, 0, 0, 0, "pack"))
920                 env.Await(
921                         CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 1),
922                         NoShowMessage(),
923                 )
924         })
925 }
926
927 func TestIgnoredFiles(t *testing.T) {
928         const ws = `
929 -- go.mod --
930 module mod.com
931
932 go 1.15
933 -- _foo/x.go --
934 package x
935
936 var _ = foo.Bar
937 `
938         runner.Run(t, ws, func(t *testing.T, env *Env) {
939                 env.OpenFile("_foo/x.go")
940                 env.Await(
941                         OnceMet(
942                                 CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1),
943                                 NoDiagnostics("_foo/x.go"),
944                         ))
945         })
946 }
947
948 // Partially reproduces golang/go#38977, moving a file between packages.
949 // It also gets hit by some go command bug fixed in 1.15, but we don't
950 // care about that so much here.
951 func TestDeletePackage(t *testing.T) {
952         const ws = `
953 -- go.mod --
954 module mod.com
955
956 go 1.15
957 -- a/a.go --
958 package a
959
960 const A = 1
961
962 -- b/b.go --
963 package b
964
965 import "mod.com/a"
966
967 const B = a.A
968
969 -- c/c.go --
970 package c
971
972 import "mod.com/a"
973
974 const C = a.A
975 `
976         runner.Run(t, ws, func(t *testing.T, env *Env) {
977                 env.OpenFile("b/b.go")
978                 env.Await(CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1))
979                 // Delete c/c.go, the only file in package c.
980                 env.RemoveWorkspaceFile("c/c.go")
981
982                 // We should still get diagnostics for files that exist.
983                 env.RegexpReplace("b/b.go", `a.A`, "a.Nonexistant")
984                 env.Await(env.DiagnosticAtRegexp("b/b.go", `Nonexistant`))
985         })
986 }
987
988 // This is a copy of the scenario_default/quickfix_empty_files.txt test from
989 // govim. Reproduces golang/go#39646.
990 func TestQuickFixEmptyFiles(t *testing.T) {
991         testenv.NeedsGo1Point(t, 15)
992
993         const mod = `
994 -- go.mod --
995 module mod.com
996
997 go 1.12
998 `
999         // To fully recreate the govim tests, we create files by inserting
1000         // a newline, adding to the file, and then deleting the newline.
1001         // Wait for each event to process to avoid cancellations and force
1002         // package loads.
1003         writeGoVim := func(env *Env, name, content string) {
1004                 env.WriteWorkspaceFile(name, "")
1005                 env.Await(CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChangeWatchedFiles), 1))
1006
1007                 env.CreateBuffer(name, "\n")
1008                 env.Await(CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1))
1009
1010                 env.EditBuffer(name, fake.NewEdit(1, 0, 1, 0, content))
1011                 env.Await(CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 1))
1012
1013                 env.EditBuffer(name, fake.NewEdit(0, 0, 1, 0, ""))
1014                 env.Await(CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 1))
1015         }
1016
1017         const p = `package p; func DoIt(s string) {};`
1018         const main = `package main
1019
1020 import "mod.com/p"
1021
1022 func main() {
1023         p.DoIt(5)
1024 }
1025 `
1026         // A simple version of the test that reproduces most of the problems it
1027         // exposes.
1028         t.Run("short", func(t *testing.T) {
1029                 runner.Run(t, mod, func(t *testing.T, env *Env) {
1030                         writeGoVim(env, "p/p.go", p)
1031                         writeGoVim(env, "main.go", main)
1032                         env.Await(env.DiagnosticAtRegexp("main.go", "5"))
1033                 })
1034         })
1035
1036         // A full version that replicates the whole flow of the test.
1037         t.Run("full", func(t *testing.T) {
1038                 runner.Run(t, mod, func(t *testing.T, env *Env) {
1039                         writeGoVim(env, "p/p.go", p)
1040                         writeGoVim(env, "main.go", main)
1041                         writeGoVim(env, "p/p_test.go", `package p
1042
1043 import "testing"
1044
1045 func TestDoIt(t *testing.T) {
1046         DoIt(5)
1047 }
1048 `)
1049                         writeGoVim(env, "p/x_test.go", `package p_test
1050
1051 import (
1052         "testing"
1053
1054         "mod.com/p"
1055 )
1056
1057 func TestDoIt(t *testing.T) {
1058         p.DoIt(5)
1059 }
1060 `)
1061                         env.Await(
1062                                 env.DiagnosticAtRegexp("main.go", "5"),
1063                                 env.DiagnosticAtRegexp("p/p_test.go", "5"),
1064                                 env.DiagnosticAtRegexp("p/x_test.go", "5"),
1065                         )
1066                         env.RegexpReplace("p/p.go", "s string", "i int")
1067                         env.Await(
1068                                 EmptyDiagnostics("main.go"),
1069                                 EmptyDiagnostics("p/p_test.go"),
1070                                 EmptyDiagnostics("p/x_test.go"),
1071                         )
1072                 })
1073         })
1074 }
1075
1076 func TestSingleFile(t *testing.T) {
1077         const mod = `
1078 -- go.mod --
1079 module mod.com
1080
1081 go 1.13
1082 -- a/a.go --
1083 package a
1084
1085 func _() {
1086         var x int
1087 }
1088 `
1089         runner.Run(t, mod, func(t *testing.T, env *Env) {
1090                 env.OpenFile("a/a.go")
1091                 env.Await(
1092                         env.DiagnosticAtRegexp("a/a.go", "x"),
1093                 )
1094         }, WithoutWorkspaceFolders())
1095 }
1096
1097 // Reproduces the case described in
1098 // https://github.com/golang/go/issues/39296#issuecomment-652058883.
1099 func TestPkgm(t *testing.T) {
1100         const basic = `
1101 -- go.mod --
1102 module mod.com
1103
1104 go 1.15
1105 -- foo/foo.go --
1106 package foo
1107
1108 import "fmt"
1109
1110 func Foo() {
1111         fmt.Println("")
1112 }
1113 `
1114         runner.Run(t, basic, func(t *testing.T, env *Env) {
1115                 testenv.NeedsGo1Point(t, 15)
1116
1117                 env.WriteWorkspaceFile("foo/foo_test.go", `package main
1118
1119 func main() {
1120
1121 }`)
1122                 env.OpenFile("foo/foo_test.go")
1123                 env.RegexpReplace("foo/foo_test.go", `package main`, `package foo`)
1124                 env.Await(
1125                         OnceMet(
1126                                 CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 1),
1127                                 NoDiagnostics("foo/foo.go"),
1128                         ),
1129                 )
1130         })
1131 }
1132
1133 func TestClosingBuffer(t *testing.T) {
1134         const basic = `
1135 -- go.mod --
1136 module mod.com
1137
1138 go 1.14
1139 -- main.go --
1140 package main
1141
1142 func main() {}
1143 `
1144         runner.Run(t, basic, func(t *testing.T, env *Env) {
1145                 env.Editor.CreateBuffer(env.Ctx, "foo.go", `package main`)
1146                 env.Await(
1147                         CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1),
1148                 )
1149                 env.CloseBuffer("foo.go")
1150                 env.Await(
1151                         OnceMet(
1152                                 CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidClose), 1),
1153                                 NoLogMatching(protocol.Info, "packages=0"),
1154                         ),
1155                 )
1156         })
1157 }
1158
1159 // Reproduces golang/go#38424.
1160 func TestCutAndPaste(t *testing.T) {
1161         const basic = `
1162 -- go.mod --
1163 module mod.com
1164
1165 go 1.14
1166 -- main2.go --
1167 package main
1168 `
1169         runner.Run(t, basic, func(t *testing.T, env *Env) {
1170                 env.CreateBuffer("main.go", "")
1171                 env.Await(CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1))
1172
1173                 env.Editor.SaveBufferWithoutActions(env.Ctx, "main.go")
1174                 env.Await(
1175                         CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidSave), 1),
1176                         CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChangeWatchedFiles), 1),
1177                 )
1178
1179                 env.EditBuffer("main.go", fake.NewEdit(0, 0, 0, 0, `package main
1180
1181 func main() {
1182 }
1183 `))
1184                 env.Await(CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 1))
1185
1186                 env.SaveBuffer("main.go")
1187                 env.Await(
1188                         CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidSave), 2),
1189                         CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChangeWatchedFiles), 2),
1190                 )
1191
1192                 env.EditBuffer("main.go", fake.NewEdit(0, 0, 4, 0, ""))
1193                 env.Await(CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 2))
1194
1195                 env.EditBuffer("main.go", fake.NewEdit(0, 0, 0, 0, `package main
1196
1197 func main() {
1198         var x int
1199 }
1200 `))
1201                 env.Await(
1202                         env.DiagnosticAtRegexp("main.go", "x"),
1203                 )
1204         })
1205 }
1206
1207 // Reproduces golang/go#39763.
1208 func TestInvalidPackageName(t *testing.T) {
1209         testenv.NeedsGo1Point(t, 15)
1210
1211         const pkgDefault = `
1212 -- go.mod --
1213 module mod.com
1214 -- main.go --
1215 package default
1216
1217 func main() {}
1218 `
1219         runner.Run(t, pkgDefault, func(t *testing.T, env *Env) {
1220                 env.OpenFile("main.go")
1221                 env.Await(
1222                         env.DiagnosticAtRegexp("main.go", "default"),
1223                 )
1224         })
1225 }
1226
1227 // This tests the functionality of the "limitWorkspaceScope"
1228 func TestLimitWorkspaceScope(t *testing.T) {
1229         const mod = `
1230 -- go.mod --
1231 module mod.com
1232 -- a/main.go --
1233 package main
1234
1235 func main() {}
1236 -- main.go --
1237 package main
1238
1239 func main() {
1240         var x int
1241 }
1242 `
1243         withOptions(WithRootPath("a")).run(t, mod, func(t *testing.T, env *Env) {
1244                 env.OpenFile("a/main.go")
1245                 env.Await(
1246                         env.DiagnosticAtRegexp("main.go", "x"),
1247                 )
1248         })
1249         withOptions(WithRootPath("a"), WithLimitWorkspaceScope()).run(t, mod, func(t *testing.T, env *Env) {
1250                 env.OpenFile("a/main.go")
1251                 env.Await(
1252                         NoDiagnostics("main.go"),
1253                 )
1254         })
1255 }
1256
1257 func TestStaticcheckDiagnostic(t *testing.T) {
1258         const files = `
1259 -- go.mod --
1260 module mod.com
1261 -- main.go --
1262 package main
1263
1264 import "fmt"
1265
1266 type t struct {
1267         msg string
1268 }
1269
1270 func main() {
1271         x := []t{t{"msg"}}
1272         fmt.Println(x)
1273 }
1274 `
1275
1276         withOptions(
1277                 EditorConfig{EnableStaticcheck: true},
1278         ).run(t, files, func(t *testing.T, env *Env) {
1279                 env.OpenFile("main.go")
1280                 // Staticcheck should generate a diagnostic to simplify this literal.
1281                 env.Await(env.DiagnosticAtRegexp("main.go", `t{"msg"}`))
1282         })
1283 }
1284
1285 // Test some secondary diagnostics
1286 func TestSecondaryDiagnostics(t *testing.T) {
1287         const dir = `
1288 -- go.mod --
1289 module mod.com
1290 -- main.go --
1291 package main
1292 func main() {
1293         panic("not here")
1294 }
1295 -- other.go --
1296 package main
1297 func main() {}
1298 `
1299         runner.Run(t, dir, func(t *testing.T, env *Env) {
1300                 log.SetFlags(log.Lshortfile)
1301                 env.OpenFile("main.go")
1302                 env.OpenFile("other.go")
1303                 x := env.DiagnosticsFor("main.go")
1304                 if x == nil {
1305                         t.Fatalf("expected 1 diagnostic, got none")
1306                 }
1307                 if len(x.Diagnostics) != 1 {
1308                         t.Fatalf("main.go, got %d diagnostics, expected 1", len(x.Diagnostics))
1309                 }
1310                 keep := x.Diagnostics[0]
1311                 y := env.DiagnosticsFor("other.go")
1312                 if len(y.Diagnostics) != 1 {
1313                         t.Fatalf("other.go: got %d diagnostics, expected 1", len(y.Diagnostics))
1314                 }
1315                 if len(y.Diagnostics[0].RelatedInformation) != 1 {
1316                         t.Fatalf("got %d RelatedInformations, expected 1", len(y.Diagnostics[0].RelatedInformation))
1317                 }
1318                 // check that the RelatedInformation matches the error from main.go
1319                 c := y.Diagnostics[0].RelatedInformation[0]
1320                 if c.Location.Range != keep.Range {
1321                         t.Errorf("locations don't match. Got %v expected %v", c.Location.Range, keep.Range)
1322                 }
1323         })
1324 }
1325
1326 func TestNotifyOrphanedFiles(t *testing.T) {
1327         // Need GO111MODULE=on for this test to work with Go 1.12.
1328         testenv.NeedsGo1Point(t, 13)
1329
1330         const files = `
1331 -- go.mod --
1332 module mod.com
1333
1334 go 1.12
1335 -- a/a.go --
1336 package a
1337
1338 func main() {
1339         var x int
1340 }
1341 -- a/a_ignore.go --
1342 // +build ignore
1343
1344 package a
1345
1346 func _() {
1347         var x int
1348 }
1349 `
1350         run(t, files, func(t *testing.T, env *Env) {
1351                 env.OpenFile("a/a.go")
1352                 env.Await(
1353                         env.DiagnosticAtRegexp("a/a.go", "x"),
1354                 )
1355                 env.OpenFile("a/a_ignore.go")
1356                 env.Await(
1357                         DiagnosticAt("a/a_ignore.go", 2, 8),
1358                 )
1359         })
1360 }
1361
1362 func TestEnableAllExperiments(t *testing.T) {
1363         const mod = `
1364 -- go.mod --
1365 module mod.com
1366
1367 -- main.go --
1368 package main
1369
1370 import "bytes"
1371
1372 func b(c bytes.Buffer) {
1373         _ = 1
1374 }
1375 `
1376         withOptions(
1377                 EditorConfig{
1378                         AllExperiments: true,
1379                 },
1380         ).run(t, mod, func(t *testing.T, env *Env) {
1381                 // Confirm that the setting doesn't cause any warnings.
1382                 env.Await(NoShowMessage())
1383         })
1384 }
1385
1386 func TestSwig(t *testing.T) {
1387         t.Skipf("skipped until golang/go#37098 is resolved")
1388
1389         const mod = `
1390 -- go.mod --
1391 module mod.com
1392 -- pkg/simple/export_swig.go --
1393 package simple
1394
1395 func ExportSimple(x, y int) int {
1396         return Gcd(x, y)
1397 }
1398 -- pkg/simple/simple.swigcxx --
1399 %module simple
1400
1401 %inline %{
1402 extern int gcd(int x, int y)
1403 {
1404   int g;
1405   g = y;
1406   while (x > 0) {
1407     g = x;
1408     x = y % x;
1409     y = g;
1410   }
1411   return g;
1412 }
1413 %}
1414 -- main.go --
1415 package a
1416
1417 func main() {
1418         var x int
1419 }
1420 `
1421         run(t, mod, func(t *testing.T, env *Env) {
1422                 env.Await(
1423                         OnceMet(
1424                                 InitialWorkspaceLoad,
1425                                 NoDiagnosticWithMessage("illegal character U+0023 '#'"),
1426                         ),
1427                 )
1428         })
1429 }
1430
1431 // When foo_test.go is opened, gopls will object to the borked package name.
1432 // This test asserts that when the package name is fixed, gopls will soon after
1433 // have no more complaints about it.
1434 // https://github.com/golang/go/issues/41061
1435 func TestRenamePackage(t *testing.T) {
1436         t.Skip("Waiting for the fix that makes this pass: https://github.com/golang/go/issues/41061")
1437
1438         const contents = `
1439 -- go.mod --
1440 module mod.com
1441 -- foo.go --
1442 package foo
1443 -- foo_test.go --
1444 package foo_`
1445
1446         runner.Run(t, contents, func(t *testing.T, env *Env) {
1447                 env.OpenFile("foo_test.go")
1448                 env.RegexpReplace("foo_test.go", "foo_", "foo_test")
1449                 env.SaveBuffer("foo_test.go")
1450                 env.Await(
1451                         EmptyDiagnostics("foo_test.go"),
1452                 )
1453         })
1454 }