.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools / gopls@v0.6.9 / internal / regtest / completion / completion_test.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools/gopls@v0.6.9/internal/regtest/completion/completion_test.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools/gopls@v0.6.9/internal/regtest/completion/completion_test.go
new file mode 100644 (file)
index 0000000..6e89c4f
--- /dev/null
@@ -0,0 +1,376 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package completion
+
+import (
+       "fmt"
+       "strings"
+       "testing"
+
+       . "golang.org/x/tools/gopls/internal/regtest"
+
+       "golang.org/x/tools/internal/lsp/fake"
+       "golang.org/x/tools/internal/lsp/protocol"
+       "golang.org/x/tools/internal/testenv"
+)
+
+func TestMain(m *testing.M) {
+       Main(m)
+}
+
+const proxy = `
+-- example.com@v1.2.3/go.mod --
+module example.com
+
+go 1.12
+-- example.com@v1.2.3/blah/blah.go --
+package blah
+
+const Name = "Blah"
+-- random.org@v1.2.3/go.mod --
+module random.org
+
+go 1.12
+-- random.org@v1.2.3/blah/blah.go --
+package hello
+
+const Name = "Hello"
+`
+
+func TestPackageCompletion(t *testing.T) {
+       testenv.NeedsGo1Point(t, 14)
+       const files = `
+-- go.mod --
+module mod.com
+
+go 1.12
+-- fruits/apple.go --
+package apple
+
+fun apple() int {
+       return 0
+}
+
+-- fruits/testfile.go --
+// this is a comment
+
+/*
+ this is a multiline comment
+*/
+
+import "fmt"
+
+func test() {}
+
+-- fruits/testfile2.go --
+package
+
+-- fruits/testfile3.go --
+pac
+`
+       var (
+               testfile4 = ""
+               testfile5 = "/*a comment*/ "
+               testfile6 = "/*a comment*/\n"
+       )
+       for _, tc := range []struct {
+               name          string
+               filename      string
+               content       *string
+               triggerRegexp string
+               want          []string
+               editRegexp    string
+       }{
+               {
+                       name:          "package completion at valid position",
+                       filename:      "fruits/testfile.go",
+                       triggerRegexp: "\n()",
+                       want:          []string{"package apple", "package apple_test", "package fruits", "package fruits_test", "package main"},
+                       editRegexp:    "\n()",
+               },
+               {
+                       name:          "package completion in a comment",
+                       filename:      "fruits/testfile.go",
+                       triggerRegexp: "th(i)s",
+                       want:          nil,
+               },
+               {
+                       name:          "package completion in a multiline comment",
+                       filename:      "fruits/testfile.go",
+                       triggerRegexp: `\/\*\n()`,
+                       want:          nil,
+               },
+               {
+                       name:          "package completion at invalid position",
+                       filename:      "fruits/testfile.go",
+                       triggerRegexp: "import \"fmt\"\n()",
+                       want:          nil,
+               },
+               {
+                       name:          "package completion after keyword 'package'",
+                       filename:      "fruits/testfile2.go",
+                       triggerRegexp: "package()",
+                       want:          []string{"package apple", "package apple_test", "package fruits", "package fruits_test", "package main"},
+                       editRegexp:    "package\n",
+               },
+               {
+                       name:          "package completion with 'pac' prefix",
+                       filename:      "fruits/testfile3.go",
+                       triggerRegexp: "pac()",
+                       want:          []string{"package apple", "package apple_test", "package fruits", "package fruits_test", "package main"},
+                       editRegexp:    "pac",
+               },
+               {
+                       name:          "package completion for empty file",
+                       filename:      "fruits/testfile4.go",
+                       triggerRegexp: "^$",
+                       content:       &testfile4,
+                       want:          []string{"package apple", "package apple_test", "package fruits", "package fruits_test", "package main"},
+                       editRegexp:    "^$",
+               },
+               {
+                       name:          "package completion without terminal newline",
+                       filename:      "fruits/testfile5.go",
+                       triggerRegexp: `\*\/ ()`,
+                       content:       &testfile5,
+                       want:          []string{"package apple", "package apple_test", "package fruits", "package fruits_test", "package main"},
+                       editRegexp:    `\*\/ ()`,
+               },
+               {
+                       name:          "package completion on terminal newline",
+                       filename:      "fruits/testfile6.go",
+                       triggerRegexp: `\*\/\n()`,
+                       content:       &testfile6,
+                       want:          []string{"package apple", "package apple_test", "package fruits", "package fruits_test", "package main"},
+                       editRegexp:    `\*\/\n()`,
+               },
+       } {
+               t.Run(tc.name, func(t *testing.T) {
+                       Run(t, files, func(t *testing.T, env *Env) {
+                               if tc.content != nil {
+                                       env.WriteWorkspaceFile(tc.filename, *tc.content)
+                                       env.Await(
+                                               env.DoneWithChangeWatchedFiles(),
+                                       )
+                               }
+                               env.OpenFile(tc.filename)
+                               completions := env.Completion(tc.filename, env.RegexpSearch(tc.filename, tc.triggerRegexp))
+
+                               // Check that the completion item suggestions are in the range
+                               // of the file.
+                               lineCount := len(strings.Split(env.Editor.BufferText(tc.filename), "\n"))
+                               for _, item := range completions.Items {
+                                       if start := int(item.TextEdit.Range.Start.Line); start >= lineCount {
+                                               t.Fatalf("unexpected text edit range start line number: got %d, want less than %d", start, lineCount)
+                                       }
+                                       if end := int(item.TextEdit.Range.End.Line); end >= lineCount {
+                                               t.Fatalf("unexpected text edit range end line number: got %d, want less than %d", end, lineCount)
+                                       }
+                               }
+
+                               if tc.want != nil {
+                                       start, end := env.RegexpRange(tc.filename, tc.editRegexp)
+                                       expectedRng := protocol.Range{
+                                               Start: fake.Pos.ToProtocolPosition(start),
+                                               End:   fake.Pos.ToProtocolPosition(end),
+                                       }
+                                       for _, item := range completions.Items {
+                                               gotRng := item.TextEdit.Range
+                                               if expectedRng != gotRng {
+                                                       t.Errorf("unexpected completion range for completion item %s: got %v, want %v",
+                                                               item.Label, gotRng, expectedRng)
+                                               }
+                                       }
+                               }
+
+                               diff := compareCompletionResults(tc.want, completions.Items)
+                               if diff != "" {
+                                       t.Error(diff)
+                               }
+                       })
+               })
+       }
+}
+
+func TestPackageNameCompletion(t *testing.T) {
+       const files = `
+-- go.mod --
+module mod.com
+
+go 1.12
+-- math/add.go --
+package ma
+`
+
+       want := []string{"ma", "ma_test", "main", "math", "math_test"}
+       Run(t, files, func(t *testing.T, env *Env) {
+               env.OpenFile("math/add.go")
+               completions := env.Completion("math/add.go", fake.Pos{
+                       Line:   0,
+                       Column: 10,
+               })
+
+               diff := compareCompletionResults(want, completions.Items)
+               if diff != "" {
+                       t.Fatal(diff)
+               }
+       })
+}
+
+func compareCompletionResults(want []string, gotItems []protocol.CompletionItem) string {
+       if len(gotItems) != len(want) {
+               return fmt.Sprintf("got %v completion(s), want %v", len(gotItems), len(want))
+       }
+
+       var got []string
+       for _, item := range gotItems {
+               got = append(got, item.Label)
+       }
+
+       for i, v := range got {
+               if v != want[i] {
+                       return fmt.Sprintf("completion results are not the same: got %v, want %v", got, want)
+               }
+       }
+
+       return ""
+}
+
+func TestUnimportedCompletion(t *testing.T) {
+       testenv.NeedsGo1Point(t, 14)
+
+       const mod = `
+-- go.mod --
+module mod.com
+
+go 1.14
+
+require example.com v1.2.3
+-- go.sum --
+example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
+example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
+-- main.go --
+package main
+
+func main() {
+       _ = blah
+}
+-- main2.go --
+package main
+
+import "example.com/blah"
+
+func _() {
+       _ = blah.Hello
+}
+`
+       WithOptions(
+               ProxyFiles(proxy),
+       ).Run(t, mod, func(t *testing.T, env *Env) {
+               // Make sure the dependency is in the module cache and accessible for
+               // unimported completions, and then remove it before proceeding.
+               env.RemoveWorkspaceFile("main2.go")
+               env.RunGoCommand("mod", "tidy")
+               env.Await(env.DoneWithChangeWatchedFiles())
+
+               // Trigger unimported completions for the example.com/blah package.
+               env.OpenFile("main.go")
+               env.Await(env.DoneWithOpen())
+               pos := env.RegexpSearch("main.go", "ah")
+               completions := env.Completion("main.go", pos)
+               if len(completions.Items) == 0 {
+                       t.Fatalf("no completion items")
+               }
+               env.AcceptCompletion("main.go", pos, completions.Items[0])
+               env.Await(env.DoneWithChange())
+
+               // Trigger completions once again for the blah.<> selector.
+               env.RegexpReplace("main.go", "_ = blah", "_ = blah.")
+               env.Await(env.DoneWithChange())
+               pos = env.RegexpSearch("main.go", "\n}")
+               completions = env.Completion("main.go", pos)
+               if len(completions.Items) != 1 {
+                       t.Fatalf("expected 1 completion item, got %v", len(completions.Items))
+               }
+               item := completions.Items[0]
+               if item.Label != "Name" {
+                       t.Fatalf("expected completion item blah.Name, got %v", item.Label)
+               }
+               env.AcceptCompletion("main.go", pos, item)
+
+               // Await the diagnostics to add example.com/blah to the go.mod file.
+               env.SaveBufferWithoutActions("main.go")
+               env.Await(
+                       env.DiagnosticAtRegexp("main.go", `"example.com/blah"`),
+               )
+       })
+}
+
+// Test that completions still work with an undownloaded module, golang/go#43333.
+func TestUndownloadedModule(t *testing.T) {
+       // mod.com depends on example.com, but only in a file that's hidden by a
+       // build tag, so the IWL won't download example.com. That will cause errors
+       // in the go list -m call performed by the imports package.
+       const files = `
+-- go.mod --
+module mod.com
+
+go 1.14
+
+require example.com v1.2.3
+-- go.sum --
+example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
+example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
+-- useblah.go --
+// +build hidden
+
+package pkg
+import "example.com/blah"
+var _ = blah.Name
+-- mainmod/mainmod.go --
+package mainmod
+
+const Name = "mainmod"
+`
+       WithOptions(ProxyFiles(proxy)).Run(t, files, func(t *testing.T, env *Env) {
+               env.CreateBuffer("import.go", "package pkg\nvar _ = mainmod.Name\n")
+               env.SaveBuffer("import.go")
+               content := env.ReadWorkspaceFile("import.go")
+               if !strings.Contains(content, `import "mod.com/mainmod`) {
+                       t.Errorf("expected import of mod.com/mainmod in %q", content)
+               }
+       })
+}
+
+// Test that we can doctor the source code enough so the file is
+// parseable and completion works as expected.
+func TestSourceFixup(t *testing.T) {
+       const files = `
+-- go.mod --
+module mod.com
+
+go 1.12
+-- foo.go --
+package foo
+
+func _() {
+       var s S
+       if s.
+}
+
+type S struct {
+       i int
+}
+`
+
+       Run(t, files, func(t *testing.T, env *Env) {
+               env.OpenFile("foo.go")
+               completions := env.Completion("foo.go", env.RegexpSearch("foo.go", `if s\.()`))
+               diff := compareCompletionResults([]string{"i"}, completions.Items)
+               if diff != "" {
+                       t.Fatal(diff)
+               }
+       })
+}