mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
internal/lsp: lift the test loops out into the testing framework
The loops are common to all the testing layers, so lift them. This prepares for more test improvements, without any funcitonal changes. Change-Id: Ib750c8a7bb4c424a185cb0bd841674a69db1385b Reviewed-on: https://go-review.googlesource.com/c/tools/+/197717 Run-TryBot: Ian Cottrell <iancottrell@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
69890759d9
commit
c7cf430b80
@ -11,60 +11,58 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/tools/internal/lsp/cmd"
|
"golang.org/x/tools/internal/lsp/cmd"
|
||||||
"golang.org/x/tools/internal/lsp/tests"
|
"golang.org/x/tools/internal/lsp/source"
|
||||||
"golang.org/x/tools/internal/span"
|
"golang.org/x/tools/internal/span"
|
||||||
"golang.org/x/tools/internal/tool"
|
"golang.org/x/tools/internal/tool"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *runner) Diagnostics(t *testing.T, data tests.Diagnostics) {
|
func (r *runner) Diagnostics(t *testing.T, uri span.URI, want []source.Diagnostic) {
|
||||||
for uri, want := range data {
|
if len(want) == 1 && want[0].Message == "" {
|
||||||
if len(want) == 1 && want[0].Message == "" {
|
return
|
||||||
|
}
|
||||||
|
fname := uri.Filename()
|
||||||
|
args := []string{"-remote=internal", "check", fname}
|
||||||
|
app := cmd.New("gopls-test", r.data.Config.Dir, r.data.Exported.Config.Env)
|
||||||
|
out := CaptureStdOut(t, func() {
|
||||||
|
_ = tool.Run(r.ctx, app, args)
|
||||||
|
})
|
||||||
|
// parse got into a collection of reports
|
||||||
|
got := map[string]struct{}{}
|
||||||
|
for _, l := range strings.Split(out, "\n") {
|
||||||
|
if len(l) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fname := uri.Filename()
|
// parse and reprint to normalize the span
|
||||||
args := []string{"-remote=internal", "check", fname}
|
bits := strings.SplitN(l, ": ", 2)
|
||||||
app := cmd.New("gopls-test", r.data.Config.Dir, r.data.Exported.Config.Env)
|
if len(bits) == 2 {
|
||||||
out := CaptureStdOut(t, func() {
|
spn := span.Parse(strings.TrimSpace(bits[0]))
|
||||||
_ = tool.Run(r.ctx, app, args)
|
spn = span.New(spn.URI(), spn.Start(), span.Point{})
|
||||||
})
|
data, err := ioutil.ReadFile(fname)
|
||||||
// parse got into a collection of reports
|
if err != nil {
|
||||||
got := map[string]struct{}{}
|
t.Fatal(err)
|
||||||
for _, l := range strings.Split(out, "\n") {
|
|
||||||
if len(l) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
// parse and reprint to normalize the span
|
converter := span.NewContentConverter(fname, data)
|
||||||
bits := strings.SplitN(l, ": ", 2)
|
s, err := spn.WithPosition(converter)
|
||||||
if len(bits) == 2 {
|
if err != nil {
|
||||||
spn := span.Parse(strings.TrimSpace(bits[0]))
|
t.Fatal(err)
|
||||||
spn = span.New(spn.URI(), spn.Start(), span.Point{})
|
|
||||||
data, err := ioutil.ReadFile(fname)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
converter := span.NewContentConverter(fname, data)
|
|
||||||
s, err := spn.WithPosition(converter)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
l = fmt.Sprintf("%s: %s", s, strings.TrimSpace(bits[1]))
|
|
||||||
}
|
}
|
||||||
got[l] = struct{}{}
|
l = fmt.Sprintf("%s: %s", s, strings.TrimSpace(bits[1]))
|
||||||
}
|
}
|
||||||
for _, diag := range want {
|
got[l] = struct{}{}
|
||||||
expect := fmt.Sprintf("%v:%v:%v: %v", diag.URI.Filename(), diag.Range.Start.Line+1, diag.Range.Start.Character+1, diag.Message)
|
}
|
||||||
if diag.Range.Start.Character == 0 {
|
for _, diag := range want {
|
||||||
expect = fmt.Sprintf("%v:%v: %v", diag.URI.Filename(), diag.Range.Start.Line+1, diag.Message)
|
expect := fmt.Sprintf("%v:%v:%v: %v", diag.URI.Filename(), diag.Range.Start.Line+1, diag.Range.Start.Character+1, diag.Message)
|
||||||
}
|
if diag.Range.Start.Character == 0 {
|
||||||
_, found := got[expect]
|
expect = fmt.Sprintf("%v:%v: %v", diag.URI.Filename(), diag.Range.Start.Line+1, diag.Message)
|
||||||
if !found {
|
|
||||||
t.Errorf("missing diagnostic %q", expect)
|
|
||||||
} else {
|
|
||||||
delete(got, expect)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for extra, _ := range got {
|
_, found := got[expect]
|
||||||
t.Errorf("extra diagnostic %q", extra)
|
if !found {
|
||||||
|
t.Errorf("missing diagnostic %q", expect)
|
||||||
|
} else {
|
||||||
|
delete(got, expect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for extra, _ := range got {
|
||||||
|
t.Errorf("extra diagnostic %q", extra)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,10 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/tools/go/packages/packagestest"
|
"golang.org/x/tools/go/packages/packagestest"
|
||||||
|
"golang.org/x/tools/internal/lsp/protocol"
|
||||||
|
"golang.org/x/tools/internal/lsp/source"
|
||||||
"golang.org/x/tools/internal/lsp/tests"
|
"golang.org/x/tools/internal/lsp/tests"
|
||||||
|
"golang.org/x/tools/internal/span"
|
||||||
)
|
)
|
||||||
|
|
||||||
type runner struct {
|
type runner struct {
|
||||||
@ -33,67 +36,67 @@ func NewRunner(exporter packagestest.Exporter, data *tests.Data, ctx context.Con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) Completion(t *testing.T, data tests.Completions, items tests.CompletionItems) {
|
func (r *runner) Completion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
|
||||||
//TODO: add command line completions tests when it works
|
//TODO: add command line completions tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) CompletionSnippets(t *testing.T, data tests.CompletionSnippets, items tests.CompletionItems) {
|
func (r *runner) CompletionSnippet(t *testing.T, src span.Span, expected tests.CompletionSnippet, placeholders bool, items tests.CompletionItems) {
|
||||||
//TODO: add command line completions tests when it works
|
//TODO: add command line completions tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) UnimportedCompletions(t *testing.T, data tests.UnimportedCompletions, items tests.CompletionItems) {
|
func (r *runner) UnimportedCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
|
||||||
//TODO: add command line completions tests when it works
|
//TODO: add command line completions tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) DeepCompletions(t *testing.T, data tests.DeepCompletions, items tests.CompletionItems) {
|
func (r *runner) DeepCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
|
||||||
//TODO: add command line completions tests when it works
|
//TODO: add command line completions tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) FuzzyCompletions(t *testing.T, data tests.FuzzyCompletions, items tests.CompletionItems) {
|
func (r *runner) FuzzyCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
|
||||||
//TODO: add command line completions tests when it works
|
//TODO: add command line completions tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) CaseSensitiveCompletions(t *testing.T, data tests.CaseSensitiveCompletions, items tests.CompletionItems) {
|
func (r *runner) CaseSensitiveCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
|
||||||
//TODO: add command line completions tests when it works
|
//TODO: add command line completions tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) RankCompletions(t *testing.T, data tests.RankCompletions, items tests.CompletionItems) {
|
func (r *runner) RankCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
|
||||||
//TODO: add command line completions tests when it works
|
//TODO: add command line completions tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) FoldingRange(t *testing.T, data tests.FoldingRanges) {
|
func (r *runner) FoldingRange(t *testing.T, spn span.Span) {
|
||||||
//TODO: add command line folding range tests when it works
|
//TODO: add command line folding range tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) Highlight(t *testing.T, data tests.Highlights) {
|
func (r *runner) Highlight(t *testing.T, name string, locations []span.Span) {
|
||||||
//TODO: add command line highlight tests when it works
|
//TODO: add command line highlight tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) Reference(t *testing.T, data tests.References) {
|
func (r *runner) Reference(t *testing.T, src span.Span, itemList []span.Span) {
|
||||||
//TODO: add command line references tests when it works
|
//TODO: add command line references tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) PrepareRename(t *testing.T, data tests.PrepareRenames) {
|
func (r *runner) PrepareRename(t *testing.T, src span.Span, want *source.PrepareItem) {
|
||||||
//TODO: add command line prepare rename tests when it works
|
//TODO: add command line prepare rename tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) Symbol(t *testing.T, data tests.Symbols) {
|
func (r *runner) Symbol(t *testing.T, uri span.URI, expectedSymbols []protocol.DocumentSymbol) {
|
||||||
//TODO: add command line symbol tests when it works
|
//TODO: add command line symbol tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) SignatureHelp(t *testing.T, data tests.Signatures) {
|
func (r *runner) SignatureHelp(t *testing.T, spn span.Span, expectedSignature *source.SignatureInformation) {
|
||||||
//TODO: add command line signature tests when it works
|
//TODO: add command line signature tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) Link(t *testing.T, data tests.Links) {
|
func (r *runner) Link(t *testing.T, uri span.URI, wantLinks []tests.Link) {
|
||||||
//TODO: add command line link tests when it works
|
//TODO: add command line link tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) Import(t *testing.T, data tests.Imports) {
|
func (r *runner) Import(t *testing.T, spn span.Span) {
|
||||||
//TODO: add command line imports tests when it works
|
//TODO: add command line imports tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) SuggestedFix(t *testing.T, data tests.SuggestedFixes) {
|
func (r *runner) SuggestedFix(t *testing.T, spn span.Span) {
|
||||||
//TODO: add suggested fix tests when it works
|
//TODO: add suggested fix tests when it works
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,41 +33,39 @@ var godefModes = []godefMode{
|
|||||||
jsonGoDef,
|
jsonGoDef,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) Definition(t *testing.T, data tests.Definitions) {
|
func (r *runner) Definition(t *testing.T, spn span.Span, d tests.Definition) {
|
||||||
// TODO: https://golang.org/issue/32794.
|
// TODO: https://golang.org/issue/32794.
|
||||||
if !*tests.UpdateGolden {
|
if !*tests.UpdateGolden {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
for _, d := range data {
|
if d.IsType || d.OnlyHover {
|
||||||
if d.IsType || d.OnlyHover {
|
// TODO: support type definition, hover queries
|
||||||
// TODO: support type definition, hover queries
|
return
|
||||||
continue
|
}
|
||||||
|
d.Src = span.New(d.Src.URI(), span.NewPoint(0, 0, d.Src.Start().Offset()), span.Point{})
|
||||||
|
for _, mode := range godefModes {
|
||||||
|
args := []string{"-remote=internal", "query"}
|
||||||
|
tag := d.Name + "-definition"
|
||||||
|
if mode&jsonGoDef != 0 {
|
||||||
|
tag += "-json"
|
||||||
|
args = append(args, "-json")
|
||||||
}
|
}
|
||||||
d.Src = span.New(d.Src.URI(), span.NewPoint(0, 0, d.Src.Start().Offset()), span.Point{})
|
args = append(args, "definition")
|
||||||
for _, mode := range godefModes {
|
uri := d.Src.URI()
|
||||||
args := []string{"-remote=internal", "query"}
|
args = append(args, fmt.Sprint(d.Src))
|
||||||
tag := d.Name + "-definition"
|
got := CaptureStdOut(t, func() {
|
||||||
if mode&jsonGoDef != 0 {
|
app := cmd.New("gopls-test", r.data.Config.Dir, r.data.Exported.Config.Env)
|
||||||
tag += "-json"
|
_ = tool.Run(r.ctx, app, args)
|
||||||
args = append(args, "-json")
|
})
|
||||||
}
|
got = normalizePaths(r.data, got)
|
||||||
args = append(args, "definition")
|
if mode&jsonGoDef != 0 && runtime.GOOS == "windows" {
|
||||||
uri := d.Src.URI()
|
got = strings.Replace(got, "file:///", "file://", -1)
|
||||||
args = append(args, fmt.Sprint(d.Src))
|
}
|
||||||
got := CaptureStdOut(t, func() {
|
expect := strings.TrimSpace(string(r.data.Golden(tag, uri.Filename(), func() ([]byte, error) {
|
||||||
app := cmd.New("gopls-test", r.data.Config.Dir, r.data.Exported.Config.Env)
|
return []byte(got), nil
|
||||||
_ = tool.Run(r.ctx, app, args)
|
})))
|
||||||
})
|
if expect != "" && !strings.HasPrefix(got, expect) {
|
||||||
got = normalizePaths(r.data, got)
|
t.Errorf("definition %v failed with %#v expected:\n%q\ngot:\n%q", tag, args, expect, got)
|
||||||
if mode&jsonGoDef != 0 && runtime.GOOS == "windows" {
|
|
||||||
got = strings.Replace(got, "file:///", "file://", -1)
|
|
||||||
}
|
|
||||||
expect := strings.TrimSpace(string(r.data.Golden(tag, uri.Filename(), func() ([]byte, error) {
|
|
||||||
return []byte(got), nil
|
|
||||||
})))
|
|
||||||
if expect != "" && !strings.HasPrefix(got, expect) {
|
|
||||||
t.Errorf("definition %v failed with %#v expected:\n%q\ngot:\n%q", tag, args, expect, got)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/tools/internal/lsp/cmd"
|
"golang.org/x/tools/internal/lsp/cmd"
|
||||||
"golang.org/x/tools/internal/lsp/tests"
|
"golang.org/x/tools/internal/span"
|
||||||
"golang.org/x/tools/internal/tool"
|
"golang.org/x/tools/internal/tool"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,32 +20,30 @@ var formatModes = [][]string{
|
|||||||
[]string{"-d"},
|
[]string{"-d"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) Format(t *testing.T, data tests.Formats) {
|
func (r *runner) Format(t *testing.T, spn span.Span) {
|
||||||
for _, spn := range data {
|
for _, mode := range formatModes {
|
||||||
for _, mode := range formatModes {
|
tag := "gofmt" + strings.Join(mode, "")
|
||||||
tag := "gofmt" + strings.Join(mode, "")
|
uri := spn.URI()
|
||||||
uri := spn.URI()
|
filename := uri.Filename()
|
||||||
filename := uri.Filename()
|
args := append(mode, filename)
|
||||||
args := append(mode, filename)
|
expect := string(r.data.Golden(tag, filename, func() ([]byte, error) {
|
||||||
expect := string(r.data.Golden(tag, filename, func() ([]byte, error) {
|
cmd := exec.Command("gofmt", args...)
|
||||||
cmd := exec.Command("gofmt", args...)
|
contents, _ := cmd.Output() // ignore error, sometimes we have intentionally ungofmt-able files
|
||||||
contents, _ := cmd.Output() // ignore error, sometimes we have intentionally ungofmt-able files
|
contents = []byte(normalizePaths(r.data, fixFileHeader(string(contents))))
|
||||||
contents = []byte(normalizePaths(r.data, fixFileHeader(string(contents))))
|
return contents, nil
|
||||||
return contents, nil
|
}))
|
||||||
}))
|
if expect == "" {
|
||||||
if expect == "" {
|
//TODO: our error handling differs, for now just skip unformattable files
|
||||||
//TODO: our error handling differs, for now just skip unformattable files
|
continue
|
||||||
continue
|
}
|
||||||
}
|
app := cmd.New("gopls-test", r.data.Config.Dir, r.data.Config.Env)
|
||||||
app := cmd.New("gopls-test", r.data.Config.Dir, r.data.Config.Env)
|
got := CaptureStdOut(t, func() {
|
||||||
got := CaptureStdOut(t, func() {
|
_ = tool.Run(r.ctx, app, append([]string{"-remote=internal", "format"}, args...))
|
||||||
_ = tool.Run(r.ctx, app, append([]string{"-remote=internal", "format"}, args...))
|
})
|
||||||
})
|
got = normalizePaths(r.data, got)
|
||||||
got = normalizePaths(r.data, got)
|
// check the first two lines are the expected file header
|
||||||
// check the first two lines are the expected file header
|
if expect != got {
|
||||||
if expect != got {
|
t.Errorf("format failed with %#v expected:\n%s\ngot:\n%s", args, expect, got)
|
||||||
t.Errorf("format failed with %#v expected:\n%s\ngot:\n%s", args, expect, got)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,10 @@ package cmdtest
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/tools/internal/lsp/cmd"
|
"golang.org/x/tools/internal/lsp/cmd"
|
||||||
"golang.org/x/tools/internal/lsp/tests"
|
|
||||||
"golang.org/x/tools/internal/span"
|
"golang.org/x/tools/internal/span"
|
||||||
"golang.org/x/tools/internal/tool"
|
"golang.org/x/tools/internal/tool"
|
||||||
)
|
)
|
||||||
@ -21,45 +19,30 @@ var renameModes = [][]string{
|
|||||||
[]string{"-d"},
|
[]string{"-d"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) Rename(t *testing.T, data tests.Renames) {
|
func (r *runner) Rename(t *testing.T, spn span.Span, newText string) {
|
||||||
sortedSpans := sortSpans(data) // run the tests in a repeatable order
|
filename := spn.URI().Filename()
|
||||||
for _, spn := range sortedSpans {
|
for _, mode := range renameModes {
|
||||||
tag := data[spn]
|
goldenTag := newText + strings.Join(mode, "") + "-rename"
|
||||||
filename := spn.URI().Filename()
|
app := cmd.New("gopls-test", r.data.Config.Dir, r.data.Config.Env)
|
||||||
for _, mode := range renameModes {
|
loc := fmt.Sprintf("%v", spn)
|
||||||
goldenTag := data[spn] + strings.Join(mode, "") + "-rename"
|
args := []string{"-remote=internal", "rename"}
|
||||||
app := cmd.New("gopls-test", r.data.Config.Dir, r.data.Config.Env)
|
if strings.Join(mode, "") != "" {
|
||||||
loc := fmt.Sprintf("%v", spn)
|
args = append(args, strings.Join(mode, ""))
|
||||||
args := []string{"-remote=internal", "rename"}
|
}
|
||||||
if strings.Join(mode, "") != "" {
|
args = append(args, loc, newText)
|
||||||
args = append(args, strings.Join(mode, ""))
|
var err error
|
||||||
}
|
got := CaptureStdOut(t, func() {
|
||||||
args = append(args, loc, tag)
|
err = tool.Run(r.ctx, app, args)
|
||||||
var err error
|
})
|
||||||
got := CaptureStdOut(t, func() {
|
if err != nil {
|
||||||
err = tool.Run(r.ctx, app, args)
|
got = err.Error()
|
||||||
})
|
}
|
||||||
if err != nil {
|
got = normalizePaths(r.data, got)
|
||||||
got = err.Error()
|
expect := string(r.data.Golden(goldenTag, filename, func() ([]byte, error) {
|
||||||
}
|
return []byte(got), nil
|
||||||
got = normalizePaths(r.data, got)
|
}))
|
||||||
expect := string(r.data.Golden(goldenTag, filename, func() ([]byte, error) {
|
if expect != got {
|
||||||
return []byte(got), nil
|
t.Errorf("rename failed with %#v expected:\n%s\ngot:\n%s", args, expect, got)
|
||||||
}))
|
|
||||||
if expect != got {
|
|
||||||
t.Errorf("rename failed with %#v expected:\n%s\ngot:\n%s", args, expect, got)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortSpans(data map[span.Span]string) []span.Span {
|
|
||||||
spans := make([]span.Span, 0, len(data))
|
|
||||||
for spn, _ := range data {
|
|
||||||
spans = append(spans, spn)
|
|
||||||
}
|
|
||||||
sort.Slice(spans, func(i, j int) bool {
|
|
||||||
return span.Compare(spans[i], spans[j]) < 0
|
|
||||||
})
|
|
||||||
return spans
|
|
||||||
}
|
|
||||||
|
@ -11,119 +11,103 @@ import (
|
|||||||
"golang.org/x/tools/internal/span"
|
"golang.org/x/tools/internal/span"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *runner) Completion(t *testing.T, data tests.Completions, items tests.CompletionItems) {
|
func (r *runner) Completion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
|
||||||
for src, test := range data {
|
got := r.callCompletion(t, src, source.CompletionOptions{
|
||||||
got := r.callCompletion(t, src, source.CompletionOptions{
|
Deep: false,
|
||||||
Deep: false,
|
FuzzyMatching: false,
|
||||||
FuzzyMatching: false,
|
Documentation: true,
|
||||||
Documentation: true,
|
})
|
||||||
})
|
if !strings.Contains(string(src.URI()), "builtins") {
|
||||||
if !strings.Contains(string(src.URI()), "builtins") {
|
got = tests.FilterBuiltins(got)
|
||||||
got = tests.FilterBuiltins(got)
|
}
|
||||||
}
|
want := expected(t, test, items)
|
||||||
want := expected(t, test, items)
|
if diff := tests.DiffCompletionItems(want, got); diff != "" {
|
||||||
if diff := tests.DiffCompletionItems(want, got); diff != "" {
|
t.Errorf("%s: %s", src, diff)
|
||||||
t.Errorf("%s: %s", src, diff)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) CompletionSnippets(t *testing.T, data tests.CompletionSnippets, items tests.CompletionItems) {
|
func (r *runner) CompletionSnippet(t *testing.T, src span.Span, expected tests.CompletionSnippet, placeholders bool, items tests.CompletionItems) {
|
||||||
for _, placeholders := range []bool{true, false} {
|
list := r.callCompletion(t, src, source.CompletionOptions{
|
||||||
for src, expected := range data {
|
Placeholders: placeholders,
|
||||||
list := r.callCompletion(t, src, source.CompletionOptions{
|
Deep: true,
|
||||||
Placeholders: placeholders,
|
Budget: 5 * time.Second,
|
||||||
Deep: true,
|
FuzzyMatching: true,
|
||||||
Budget: 5 * time.Second,
|
})
|
||||||
FuzzyMatching: true,
|
got := tests.FindItem(list, *items[expected.CompletionItem])
|
||||||
})
|
want := expected.PlainSnippet
|
||||||
got := tests.FindItem(list, *items[expected.CompletionItem])
|
if placeholders {
|
||||||
want := expected.PlainSnippet
|
want = expected.PlaceholderSnippet
|
||||||
if placeholders {
|
}
|
||||||
want = expected.PlaceholderSnippet
|
if diff := tests.DiffSnippets(want, got); diff != "" {
|
||||||
}
|
t.Errorf("%s: %v", src, diff)
|
||||||
if diff := tests.DiffSnippets(want, got); diff != "" {
|
|
||||||
t.Errorf("%s: %v", src, diff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) UnimportedCompletions(t *testing.T, data tests.UnimportedCompletions, items tests.CompletionItems) {
|
func (r *runner) UnimportedCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
|
||||||
for src, test := range data {
|
got := r.callCompletion(t, src, source.CompletionOptions{
|
||||||
got := r.callCompletion(t, src, source.CompletionOptions{
|
Unimported: true,
|
||||||
Unimported: true,
|
})
|
||||||
})
|
if !strings.Contains(string(src.URI()), "builtins") {
|
||||||
if !strings.Contains(string(src.URI()), "builtins") {
|
got = tests.FilterBuiltins(got)
|
||||||
got = tests.FilterBuiltins(got)
|
}
|
||||||
}
|
want := expected(t, test, items)
|
||||||
want := expected(t, test, items)
|
if diff := tests.DiffCompletionItems(want, got); diff != "" {
|
||||||
if diff := tests.DiffCompletionItems(want, got); diff != "" {
|
t.Errorf("%s: %s", src, diff)
|
||||||
t.Errorf("%s: %s", src, diff)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) DeepCompletions(t *testing.T, data tests.DeepCompletions, items tests.CompletionItems) {
|
func (r *runner) DeepCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
|
||||||
for src, test := range data {
|
got := r.callCompletion(t, src, source.CompletionOptions{
|
||||||
got := r.callCompletion(t, src, source.CompletionOptions{
|
Deep: true,
|
||||||
Deep: true,
|
Budget: 5 * time.Second,
|
||||||
Budget: 5 * time.Second,
|
Documentation: true,
|
||||||
Documentation: true,
|
})
|
||||||
})
|
if !strings.Contains(string(src.URI()), "builtins") {
|
||||||
if !strings.Contains(string(src.URI()), "builtins") {
|
got = tests.FilterBuiltins(got)
|
||||||
got = tests.FilterBuiltins(got)
|
}
|
||||||
}
|
want := expected(t, test, items)
|
||||||
want := expected(t, test, items)
|
if msg := tests.DiffCompletionItems(want, got); msg != "" {
|
||||||
if msg := tests.DiffCompletionItems(want, got); msg != "" {
|
t.Errorf("%s: %s", src, msg)
|
||||||
t.Errorf("%s: %s", src, msg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) FuzzyCompletions(t *testing.T, data tests.FuzzyCompletions, items tests.CompletionItems) {
|
func (r *runner) FuzzyCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
|
||||||
for src, test := range data {
|
got := r.callCompletion(t, src, source.CompletionOptions{
|
||||||
got := r.callCompletion(t, src, source.CompletionOptions{
|
FuzzyMatching: true,
|
||||||
FuzzyMatching: true,
|
Deep: true,
|
||||||
Deep: true,
|
Budget: 5 * time.Second,
|
||||||
Budget: 5 * time.Second,
|
})
|
||||||
})
|
if !strings.Contains(string(src.URI()), "builtins") {
|
||||||
if !strings.Contains(string(src.URI()), "builtins") {
|
got = tests.FilterBuiltins(got)
|
||||||
got = tests.FilterBuiltins(got)
|
}
|
||||||
}
|
want := expected(t, test, items)
|
||||||
want := expected(t, test, items)
|
if msg := tests.DiffCompletionItems(want, got); msg != "" {
|
||||||
if msg := tests.DiffCompletionItems(want, got); msg != "" {
|
t.Errorf("%s: %s", src, msg)
|
||||||
t.Errorf("%s: %s", src, msg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) CaseSensitiveCompletions(t *testing.T, data tests.CaseSensitiveCompletions, items tests.CompletionItems) {
|
func (r *runner) CaseSensitiveCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
|
||||||
for src, test := range data {
|
got := r.callCompletion(t, src, source.CompletionOptions{
|
||||||
got := r.callCompletion(t, src, source.CompletionOptions{
|
CaseSensitive: true,
|
||||||
CaseSensitive: true,
|
})
|
||||||
})
|
if !strings.Contains(string(src.URI()), "builtins") {
|
||||||
if !strings.Contains(string(src.URI()), "builtins") {
|
got = tests.FilterBuiltins(got)
|
||||||
got = tests.FilterBuiltins(got)
|
}
|
||||||
}
|
want := expected(t, test, items)
|
||||||
want := expected(t, test, items)
|
if msg := tests.DiffCompletionItems(want, got); msg != "" {
|
||||||
if msg := tests.DiffCompletionItems(want, got); msg != "" {
|
t.Errorf("%s: %s", src, msg)
|
||||||
t.Errorf("%s: %s", src, msg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) RankCompletions(t *testing.T, data tests.RankCompletions, items tests.CompletionItems) {
|
func (r *runner) RankCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
|
||||||
for src, test := range data {
|
got := r.callCompletion(t, src, source.CompletionOptions{
|
||||||
got := r.callCompletion(t, src, source.CompletionOptions{
|
FuzzyMatching: true,
|
||||||
FuzzyMatching: true,
|
Deep: true,
|
||||||
Deep: true,
|
Budget: 5 * time.Second,
|
||||||
Budget: 5 * time.Second,
|
})
|
||||||
})
|
want := expected(t, test, items)
|
||||||
want := expected(t, test, items)
|
if msg := tests.CheckCompletionOrder(want, got); msg != "" {
|
||||||
if msg := tests.CheckCompletionOrder(want, got); msg != "" {
|
t.Errorf("%s: %s", src, msg)
|
||||||
t.Errorf("%s: %s", src, msg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -96,26 +96,26 @@ type Data struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Tests interface {
|
type Tests interface {
|
||||||
Diagnostics(*testing.T, Diagnostics)
|
Diagnostics(*testing.T, span.URI, []source.Diagnostic)
|
||||||
Completion(*testing.T, Completions, CompletionItems)
|
Completion(*testing.T, span.Span, Completion, CompletionItems)
|
||||||
CompletionSnippets(*testing.T, CompletionSnippets, CompletionItems)
|
CompletionSnippet(*testing.T, span.Span, CompletionSnippet, bool, CompletionItems)
|
||||||
UnimportedCompletions(*testing.T, UnimportedCompletions, CompletionItems)
|
UnimportedCompletion(*testing.T, span.Span, Completion, CompletionItems)
|
||||||
DeepCompletions(*testing.T, DeepCompletions, CompletionItems)
|
DeepCompletion(*testing.T, span.Span, Completion, CompletionItems)
|
||||||
FuzzyCompletions(*testing.T, FuzzyCompletions, CompletionItems)
|
FuzzyCompletion(*testing.T, span.Span, Completion, CompletionItems)
|
||||||
CaseSensitiveCompletions(*testing.T, CaseSensitiveCompletions, CompletionItems)
|
CaseSensitiveCompletion(*testing.T, span.Span, Completion, CompletionItems)
|
||||||
RankCompletions(*testing.T, RankCompletions, CompletionItems)
|
RankCompletion(*testing.T, span.Span, Completion, CompletionItems)
|
||||||
FoldingRange(*testing.T, FoldingRanges)
|
FoldingRange(*testing.T, span.Span)
|
||||||
Format(*testing.T, Formats)
|
Format(*testing.T, span.Span)
|
||||||
Import(*testing.T, Imports)
|
Import(*testing.T, span.Span)
|
||||||
SuggestedFix(*testing.T, SuggestedFixes)
|
SuggestedFix(*testing.T, span.Span)
|
||||||
Definition(*testing.T, Definitions)
|
Definition(*testing.T, span.Span, Definition)
|
||||||
Highlight(*testing.T, Highlights)
|
Highlight(*testing.T, string, []span.Span)
|
||||||
Reference(*testing.T, References)
|
Reference(*testing.T, span.Span, []span.Span)
|
||||||
Rename(*testing.T, Renames)
|
Rename(*testing.T, span.Span, string)
|
||||||
PrepareRename(*testing.T, PrepareRenames)
|
PrepareRename(*testing.T, span.Span, *source.PrepareItem)
|
||||||
Symbol(*testing.T, Symbols)
|
Symbol(*testing.T, span.URI, []protocol.DocumentSymbol)
|
||||||
SignatureHelp(*testing.T, Signatures)
|
SignatureHelp(*testing.T, span.Span, *source.SignatureInformation)
|
||||||
Link(*testing.T, Links)
|
Link(*testing.T, span.URI, []Link)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Definition struct {
|
type Definition struct {
|
||||||
@ -327,102 +327,144 @@ func Run(t *testing.T, tests Tests, data *Data) {
|
|||||||
|
|
||||||
t.Run("Completion", func(t *testing.T) {
|
t.Run("Completion", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.Completion(t, data.Completions, data.CompletionItems)
|
for src, test := range data.Completions {
|
||||||
|
tests.Completion(t, src, test, data.CompletionItems)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("CompletionSnippets", func(t *testing.T) {
|
t.Run("CompletionSnippets", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.CompletionSnippets(t, data.CompletionSnippets, data.CompletionItems)
|
for _, placeholders := range []bool{true, false} {
|
||||||
|
for src, expected := range data.CompletionSnippets {
|
||||||
|
tests.CompletionSnippet(t, src, expected, placeholders, data.CompletionItems)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("UnimportedCompletion", func(t *testing.T) {
|
t.Run("UnimportedCompletion", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.UnimportedCompletions(t, data.UnimportedCompletions, data.CompletionItems)
|
for src, test := range data.UnimportedCompletions {
|
||||||
|
tests.UnimportedCompletion(t, src, test, data.CompletionItems)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("DeepCompletion", func(t *testing.T) {
|
t.Run("DeepCompletion", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.DeepCompletions(t, data.DeepCompletions, data.CompletionItems)
|
for src, test := range data.DeepCompletions {
|
||||||
|
tests.DeepCompletion(t, src, test, data.CompletionItems)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("FuzzyCompletion", func(t *testing.T) {
|
t.Run("FuzzyCompletion", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.FuzzyCompletions(t, data.FuzzyCompletions, data.CompletionItems)
|
for src, test := range data.FuzzyCompletions {
|
||||||
|
tests.FuzzyCompletion(t, src, test, data.CompletionItems)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("CaseSensitiveCompletion", func(t *testing.T) {
|
t.Run("CaseSensitiveCompletion", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.CaseSensitiveCompletions(t, data.CaseSensitiveCompletions, data.CompletionItems)
|
for src, test := range data.CaseSensitiveCompletions {
|
||||||
|
tests.CaseSensitiveCompletion(t, src, test, data.CompletionItems)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("RankCompletions", func(t *testing.T) {
|
t.Run("RankCompletions", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.RankCompletions(t, data.RankCompletions, data.CompletionItems)
|
for src, test := range data.RankCompletions {
|
||||||
|
tests.RankCompletion(t, src, test, data.CompletionItems)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Diagnostics", func(t *testing.T) {
|
t.Run("Diagnostics", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.Diagnostics(t, data.Diagnostics)
|
for uri, want := range data.Diagnostics {
|
||||||
|
tests.Diagnostics(t, uri, want)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("FoldingRange", func(t *testing.T) {
|
t.Run("FoldingRange", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.FoldingRange(t, data.FoldingRanges)
|
for _, spn := range data.FoldingRanges {
|
||||||
|
tests.FoldingRange(t, spn)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Format", func(t *testing.T) {
|
t.Run("Format", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.Format(t, data.Formats)
|
for _, spn := range data.Formats {
|
||||||
|
tests.Format(t, spn)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Import", func(t *testing.T) {
|
t.Run("Import", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.Import(t, data.Imports)
|
for _, spn := range data.Imports {
|
||||||
|
tests.Import(t, spn)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("SuggestedFix", func(t *testing.T) {
|
t.Run("SuggestedFix", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.SuggestedFix(t, data.SuggestedFixes)
|
for _, spn := range data.SuggestedFixes {
|
||||||
|
tests.SuggestedFix(t, spn)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Definition", func(t *testing.T) {
|
t.Run("Definition", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.Definition(t, data.Definitions)
|
for spn, d := range data.Definitions {
|
||||||
|
tests.Definition(t, spn, d)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Highlight", func(t *testing.T) {
|
t.Run("Highlight", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.Highlight(t, data.Highlights)
|
for name, locations := range data.Highlights {
|
||||||
|
tests.Highlight(t, name, locations)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("References", func(t *testing.T) {
|
t.Run("References", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.Reference(t, data.References)
|
for src, itemList := range data.References {
|
||||||
|
tests.Reference(t, src, itemList)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Renames", func(t *testing.T) {
|
t.Run("Renames", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.Rename(t, data.Renames)
|
for spn, newText := range data.Renames {
|
||||||
|
tests.Rename(t, spn, newText)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("PrepareRenames", func(t *testing.T) {
|
t.Run("PrepareRenames", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.PrepareRename(t, data.PrepareRenames)
|
for src, want := range data.PrepareRenames {
|
||||||
|
tests.PrepareRename(t, src, want)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Symbols", func(t *testing.T) {
|
t.Run("Symbols", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.Symbol(t, data.Symbols)
|
for uri, expectedSymbols := range data.Symbols {
|
||||||
|
tests.Symbol(t, uri, expectedSymbols)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("SignatureHelp", func(t *testing.T) {
|
t.Run("SignatureHelp", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.SignatureHelp(t, data.Signatures)
|
for spn, expectedSignature := range data.Signatures {
|
||||||
|
tests.SignatureHelp(t, spn, expectedSignature)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Link", func(t *testing.T) {
|
t.Run("Link", func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tests.Link(t, data.Links)
|
for uri, wantLinks := range data.Links {
|
||||||
|
tests.Link(t, uri, wantLinks)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if *UpdateGolden {
|
if *UpdateGolden {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user