mirror of https://github.com/golang/go.git
214 lines
5.7 KiB
Go
214 lines
5.7 KiB
Go
// 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 regtest
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"golang.org/x/tools/internal/lsp"
|
|
"golang.org/x/tools/internal/lsp/fake"
|
|
"golang.org/x/tools/internal/lsp/protocol"
|
|
"golang.org/x/tools/internal/testenv"
|
|
)
|
|
|
|
func TestPackageCompletion(t *testing.T) {
|
|
testenv.NeedsGo1Point(t, 14)
|
|
const files = `
|
|
-- go.mod --
|
|
module mod.com
|
|
|
|
-- 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(
|
|
CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChangeWatchedFiles), 1),
|
|
)
|
|
}
|
|
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
|
|
|
|
-- 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 ""
|
|
}
|