mirror of
https://github.com/golang/go
synced 2024-11-18 15:04:44 -07:00
internal/lsp: add more testdata for completion and diagnostics
Change-Id: I2a73e51b60f76a2af0f8ff4d34220b551e0cd378 Reviewed-on: https://go-review.googlesource.com/c/150041 Run-TryBot: Rebecca Stambler <rstambler@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Cottrell <iancottrell@google.com>
This commit is contained in:
parent
89e258047f
commit
fc4f04983f
@ -7,11 +7,12 @@ package packagestest
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/expect"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -131,11 +132,18 @@ func (e *Exported) getNotes() error {
|
||||
return nil
|
||||
}
|
||||
notes := []*expect.Note{}
|
||||
var dirs []string
|
||||
for _, module := range e.written {
|
||||
for _, filename := range module {
|
||||
if !strings.HasSuffix(filename, ".go") {
|
||||
continue
|
||||
}
|
||||
dirs = append(dirs, filepath.Dir(filename))
|
||||
}
|
||||
}
|
||||
pkgs, err := packages.Load(e.Config, dirs...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to load packages for directories %s: %v", dirs, err)
|
||||
}
|
||||
for _, pkg := range pkgs {
|
||||
for _, filename := range pkg.GoFiles {
|
||||
l, err := expect.Parse(e.fset, filename, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to extract expectations: %v", err)
|
||||
|
@ -5,6 +5,8 @@
|
||||
package lsp
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/protocol"
|
||||
"golang.org/x/tools/internal/lsp/source"
|
||||
)
|
||||
@ -36,3 +38,15 @@ func toProtocolSeverity(severity source.DiagnosticSeverity) protocol.DiagnosticS
|
||||
}
|
||||
return protocol.SeverityError // default
|
||||
}
|
||||
|
||||
func sorted(d []protocol.Diagnostic) {
|
||||
sort.Slice(d, func(i int, j int) bool {
|
||||
if d[i].Range.Start.Line == d[j].Range.Start.Line {
|
||||
if d[i].Range.Start.Character == d[j].Range.End.Character {
|
||||
return d[i].Message < d[j].Message
|
||||
}
|
||||
return d[i].Range.Start.Character < d[j].Range.End.Character
|
||||
}
|
||||
return d[i].Range.Start.Line < d[j].Range.Start.Line
|
||||
})
|
||||
}
|
||||
|
7
internal/lsp/lsp110_test.go
Normal file
7
internal/lsp/lsp110_test.go
Normal file
@ -0,0 +1,7 @@
|
||||
//+build !go1.11
|
||||
|
||||
package lsp
|
||||
|
||||
func init() {
|
||||
goVersion111 = false
|
||||
}
|
@ -12,7 +12,6 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -22,14 +21,18 @@ import (
|
||||
"golang.org/x/tools/internal/lsp/source"
|
||||
)
|
||||
|
||||
// TODO(rstambler): Remove this once Go 1.12 is released as we will end support
|
||||
// for versions of Go <= 1.10.
|
||||
var goVersion111 = true
|
||||
|
||||
func TestLSP(t *testing.T) {
|
||||
packagestest.TestAll(t, testLSP)
|
||||
}
|
||||
|
||||
func testLSP(t *testing.T, exporter packagestest.Exporter) {
|
||||
const dir = "testdata"
|
||||
const expectedCompletionsCount = 4
|
||||
const expectedDiagnosticsCount = 9
|
||||
const expectedCompletionsCount = 43
|
||||
const expectedDiagnosticsCount = 14
|
||||
const expectedFormatCount = 3
|
||||
const expectedDefinitionsCount = 16
|
||||
|
||||
@ -49,8 +52,6 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) {
|
||||
exported := packagestest.Export(t, exporter, modules)
|
||||
defer exported.Cleanup()
|
||||
|
||||
dirs := make(map[string]bool)
|
||||
|
||||
// collect results for certain tests
|
||||
expectedDiagnostics := make(diagnostics)
|
||||
completionItems := make(completionItems)
|
||||
@ -67,16 +68,6 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) {
|
||||
cfg.Mode = packages.LoadSyntax
|
||||
s.view.Config = &cfg
|
||||
|
||||
for _, module := range modules {
|
||||
for fragment := range module.Files {
|
||||
if !strings.HasSuffix(fragment, ".go") {
|
||||
continue
|
||||
}
|
||||
filename := exporter.Filename(exported, module.Name, fragment)
|
||||
expectedDiagnostics[filename] = []protocol.Diagnostic{}
|
||||
dirs[filepath.Dir(filename)] = true
|
||||
}
|
||||
}
|
||||
// Do a first pass to collect special markers
|
||||
if err := exported.Expect(map[string]interface{}{
|
||||
"item": func(name string, r packagestest.Range, _, _ string) {
|
||||
@ -98,32 +89,40 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) {
|
||||
|
||||
t.Run("Completion", func(t *testing.T) {
|
||||
t.Helper()
|
||||
if len(expectedCompletions) != expectedCompletionsCount {
|
||||
t.Errorf("got %v completions expected %v", len(expectedCompletions), expectedCompletionsCount)
|
||||
if goVersion111 { // TODO(rstambler): Remove this when we no longer support Go 1.10.
|
||||
if len(expectedCompletions) != expectedCompletionsCount {
|
||||
t.Errorf("got %v completions expected %v", len(expectedCompletions), expectedCompletionsCount)
|
||||
}
|
||||
}
|
||||
expectedCompletions.test(t, exported, s, completionItems)
|
||||
})
|
||||
|
||||
t.Run("Diagnostics", func(t *testing.T) {
|
||||
t.Helper()
|
||||
diagnosticsCount := expectedDiagnostics.test(t, exported, s.view, dirs)
|
||||
if diagnosticsCount != expectedDiagnosticsCount {
|
||||
t.Errorf("got %v diagnostics expected %v", diagnosticsCount, expectedDiagnosticsCount)
|
||||
diagnosticsCount := expectedDiagnostics.test(t, exported, s.view)
|
||||
if goVersion111 { // TODO(rstambler): Remove this when we no longer support Go 1.10.
|
||||
if diagnosticsCount != expectedDiagnosticsCount {
|
||||
t.Errorf("got %v diagnostics expected %v", diagnosticsCount, expectedDiagnosticsCount)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Format", func(t *testing.T) {
|
||||
t.Helper()
|
||||
if len(expectedFormat) != expectedFormatCount {
|
||||
t.Errorf("got %v formats expected %v", len(expectedFormat), expectedFormatCount)
|
||||
if goVersion111 { // TODO(rstambler): Remove this when we no longer support Go 1.10.
|
||||
if len(expectedFormat) != expectedFormatCount {
|
||||
t.Errorf("got %v formats expected %v", len(expectedFormat), expectedFormatCount)
|
||||
}
|
||||
}
|
||||
expectedFormat.test(t, s)
|
||||
})
|
||||
|
||||
t.Run("Definitions", func(t *testing.T) {
|
||||
t.Helper()
|
||||
if len(expectedDefinitions) != expectedDefinitionsCount {
|
||||
t.Errorf("got %v definitions expected %v", len(expectedDefinitions), expectedDefinitionsCount)
|
||||
if goVersion111 { // TODO(rstambler): Remove this when we no longer support Go 1.10.
|
||||
if len(expectedDefinitions) != expectedDefinitionsCount {
|
||||
t.Errorf("got %v definitions expected %v", len(expectedDefinitions), expectedDefinitionsCount)
|
||||
}
|
||||
}
|
||||
expectedDefinitions.test(t, s)
|
||||
})
|
||||
@ -153,11 +152,11 @@ func (c completions) test(t *testing.T, exported *packagestest.Exported, s *serv
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
t.Fatalf("completion failed for %s:%v:%v: %v", filepath.Base(src.Filename), src.Line, src.Column, err)
|
||||
}
|
||||
got := list.Items
|
||||
if equal := reflect.DeepEqual(want, got); !equal {
|
||||
t.Errorf("completion failed for %s:%v:%v: (expected: %v), (got: %v)", filepath.Base(src.Filename), src.Line, src.Column, want, got)
|
||||
t.Errorf(diffC(src, want, got))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,6 +184,8 @@ func (i completionItems) collect(pos token.Pos, label, detail, kind string) {
|
||||
k = protocol.ConstantCompletion
|
||||
case "method":
|
||||
k = protocol.MethodCompletion
|
||||
case "package":
|
||||
k = protocol.ModuleCompletion
|
||||
}
|
||||
i[pos] = &protocol.CompletionItem{
|
||||
Label: label,
|
||||
@ -193,50 +194,33 @@ func (i completionItems) collect(pos token.Pos, label, detail, kind string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (d diagnostics) test(t *testing.T, exported *packagestest.Exported, v *source.View, dirs map[string]bool) int {
|
||||
// first trigger a load to get the diagnostics
|
||||
var dirList []string
|
||||
for dir := range dirs {
|
||||
dirList = append(dirList, dir)
|
||||
}
|
||||
exported.Config.Mode = packages.LoadFiles
|
||||
pkgs, err := packages.Load(exported.Config, dirList...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// and now see if they match the expected ones
|
||||
func (d diagnostics) test(t *testing.T, exported *packagestest.Exported, v *source.View) int {
|
||||
count := 0
|
||||
for _, pkg := range pkgs {
|
||||
for _, filename := range pkg.GoFiles {
|
||||
f := v.GetFile(source.ToURI(filename))
|
||||
diagnostics, err := source.Diagnostics(context.Background(), v, f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := toProtocolDiagnostics(v, diagnostics[filename])
|
||||
sort.Slice(got, func(i int, j int) bool {
|
||||
return got[i].Range.Start.Line < got[j].Range.Start.Line
|
||||
})
|
||||
want := d[filename]
|
||||
if equal := reflect.DeepEqual(want, got); !equal {
|
||||
msg := &bytes.Buffer{}
|
||||
fmt.Fprintf(msg, "diagnostics failed for %s: expected:\n", filepath.Base(filename))
|
||||
for _, d := range want {
|
||||
fmt.Fprintf(msg, " %v\n", d)
|
||||
}
|
||||
fmt.Fprintf(msg, "got:\n")
|
||||
for _, d := range got {
|
||||
fmt.Fprintf(msg, " %v\n", d)
|
||||
}
|
||||
t.Error(msg.String())
|
||||
}
|
||||
count += len(want)
|
||||
for filename, want := range d {
|
||||
f := v.GetFile(source.ToURI(filename))
|
||||
sourceDiagnostics, err := source.Diagnostics(context.Background(), v, f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := toProtocolDiagnostics(v, sourceDiagnostics[filename])
|
||||
sorted(got)
|
||||
if equal := reflect.DeepEqual(want, got); !equal {
|
||||
t.Error(diffD(filename, want, got))
|
||||
}
|
||||
count += len(want)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func (d diagnostics) collect(pos token.Position, msg string) {
|
||||
if _, ok := d[pos.Filename]; !ok {
|
||||
d[pos.Filename] = []protocol.Diagnostic{}
|
||||
}
|
||||
// If a file has an empty diagnostics, mark that and return. This allows us
|
||||
// to avoid testing diagnostics in files that may have a lot of them.
|
||||
if msg == "" {
|
||||
return
|
||||
}
|
||||
line := float64(pos.Line - 1)
|
||||
col := float64(pos.Column - 1)
|
||||
want := protocol.Diagnostic{
|
||||
@ -268,7 +252,7 @@ func (f formats) test(t *testing.T, s *server) {
|
||||
if gofmted != "" {
|
||||
t.Error(err)
|
||||
}
|
||||
return
|
||||
continue
|
||||
}
|
||||
edit := edits[0]
|
||||
if edit.NewText != gofmted {
|
||||
@ -312,3 +296,31 @@ func (d definitions) collect(fset *token.FileSet, src, target packagestest.Range
|
||||
tLoc := toProtocolLocation(fset, tRange)
|
||||
d[sLoc] = tLoc
|
||||
}
|
||||
|
||||
// diffD prints the diff between expected and actual diagnostics test results.
|
||||
func diffD(filename string, want, got []protocol.Diagnostic) string {
|
||||
msg := &bytes.Buffer{}
|
||||
fmt.Fprintf(msg, "diagnostics failed for %s:\nexpected:\n", filename)
|
||||
for _, d := range want {
|
||||
fmt.Fprintf(msg, " %v\n", d)
|
||||
}
|
||||
fmt.Fprintf(msg, "got:\n")
|
||||
for _, d := range got {
|
||||
fmt.Fprintf(msg, " %v\n", d)
|
||||
}
|
||||
return msg.String()
|
||||
}
|
||||
|
||||
// diffC prints the diff between expected and actual completion test results.
|
||||
func diffC(pos token.Position, want, got []protocol.CompletionItem) string {
|
||||
msg := &bytes.Buffer{}
|
||||
fmt.Fprintf(msg, "completion failed for %s:%v:%v:\nexpected:\n", filepath.Base(pos.Filename), pos.Line, pos.Column)
|
||||
for _, d := range want {
|
||||
fmt.Fprintf(msg, " %v\n", d)
|
||||
}
|
||||
fmt.Fprintf(msg, "got:\n")
|
||||
for _, d := range got {
|
||||
fmt.Fprintf(msg, " %v\n", d)
|
||||
}
|
||||
return msg.String()
|
||||
}
|
||||
|
@ -54,3 +54,30 @@ func (s DiagnosticSeverity) Format(f fmt.State, c rune) {
|
||||
func (d Diagnostic) Format(f fmt.State, c rune) {
|
||||
fmt.Fprintf(f, "%v:%v from %v at %v: %v", d.Severity, d.Code, d.Source, d.Range, d.Message)
|
||||
}
|
||||
|
||||
func (i CompletionItem) Format(f fmt.State, c rune) {
|
||||
fmt.Fprintf(f, "%v %v %v", i.Label, i.Detail, CompletionItemKind(i.Kind))
|
||||
}
|
||||
|
||||
func (k CompletionItemKind) Format(f fmt.State, c rune) {
|
||||
switch k {
|
||||
case StructCompletion:
|
||||
fmt.Fprintf(f, "struct")
|
||||
case FunctionCompletion:
|
||||
fmt.Fprintf(f, "func")
|
||||
case VariableCompletion:
|
||||
fmt.Fprintf(f, "var")
|
||||
case TypeParameterCompletion:
|
||||
fmt.Fprintf(f, "type")
|
||||
case FieldCompletion:
|
||||
fmt.Fprintf(f, "field")
|
||||
case InterfaceCompletion:
|
||||
fmt.Fprintf(f, "interface")
|
||||
case ConstantCompletion:
|
||||
fmt.Fprintf(f, "const")
|
||||
case MethodCompletion:
|
||||
fmt.Fprintf(f, "method")
|
||||
case ModuleCompletion:
|
||||
fmt.Fprintf(f, "package")
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
type CompletionItem struct {
|
||||
Label, Detail string
|
||||
Kind CompletionItemKind
|
||||
Score int
|
||||
Score float64
|
||||
}
|
||||
|
||||
type CompletionItemKind int
|
||||
@ -47,6 +47,8 @@ func Completion(ctx context.Context, f *File, pos token.Pos) ([]CompletionItem,
|
||||
return items, err
|
||||
}
|
||||
|
||||
const stdScore float64 = 1.0
|
||||
|
||||
type finder func(types.Object, float64, []CompletionItem) []CompletionItem
|
||||
|
||||
// completions returns the map of possible candidates for completion, given a
|
||||
@ -89,7 +91,7 @@ func completions(file *ast.File, pos token.Pos, fset *token.FileSet, pkg *types.
|
||||
if !seen[obj] {
|
||||
seen[obj] = true
|
||||
if typ != nil && matchingTypes(typ, obj.Type()) {
|
||||
weight *= 10
|
||||
weight *= 10.0
|
||||
}
|
||||
if !strings.HasPrefix(obj.Name(), prefix) {
|
||||
return items
|
||||
@ -160,7 +162,7 @@ func selector(sel *ast.SelectorExpr, info *types.Info, found finder) (items []Co
|
||||
scope := pkgname.Imported().Scope()
|
||||
// TODO testcase: bad import
|
||||
for _, name := range scope.Names() {
|
||||
items = found(scope.Lookup(name), 1, items)
|
||||
items = found(scope.Lookup(name), stdScore, items)
|
||||
}
|
||||
return items, prefix, nil
|
||||
}
|
||||
@ -175,20 +177,20 @@ func selector(sel *ast.SelectorExpr, info *types.Info, found finder) (items []Co
|
||||
// methods of T
|
||||
mset := types.NewMethodSet(tv.Type)
|
||||
for i := 0; i < mset.Len(); i++ {
|
||||
items = found(mset.At(i).Obj(), 1, items)
|
||||
items = found(mset.At(i).Obj(), stdScore, items)
|
||||
}
|
||||
|
||||
// methods of *T
|
||||
if tv.Addressable() && !types.IsInterface(tv.Type) && !isPointer(tv.Type) {
|
||||
mset := types.NewMethodSet(types.NewPointer(tv.Type))
|
||||
for i := 0; i < mset.Len(); i++ {
|
||||
items = found(mset.At(i).Obj(), 1, items)
|
||||
items = found(mset.At(i).Obj(), stdScore, items)
|
||||
}
|
||||
}
|
||||
|
||||
// fields of T
|
||||
for _, f := range fieldSelections(tv.Type) {
|
||||
items = found(f, 1, items)
|
||||
items = found(f, stdScore, items)
|
||||
}
|
||||
|
||||
return items, prefix, nil
|
||||
@ -236,7 +238,7 @@ func lexical(path []ast.Node, pos token.Pos, pkg *types.Package, info *types.Inf
|
||||
}
|
||||
}
|
||||
|
||||
score := 1.0
|
||||
score := stdScore
|
||||
// Rank builtins significantly lower than other results.
|
||||
if scope == types.Universe {
|
||||
score *= 0.1
|
||||
@ -342,7 +344,7 @@ func complit(path []ast.Node, pos token.Pos, pkg *types.Package, info *types.Inf
|
||||
structPkg = field.Pkg()
|
||||
}
|
||||
if !addedFields[field] {
|
||||
items = found(field, 10, items)
|
||||
items = found(field, 10.0, items)
|
||||
}
|
||||
}
|
||||
// Add lexical completions if the user hasn't typed a key value expression
|
||||
@ -418,6 +420,7 @@ func formatCompletion(obj types.Object, qualifier types.Qualifier, score float64
|
||||
Label: label,
|
||||
Detail: detail,
|
||||
Kind: kind,
|
||||
Score: score,
|
||||
}
|
||||
}
|
||||
|
||||
|
19
internal/lsp/testdata/assign_rank/assign_rank.go.in
vendored
Normal file
19
internal/lsp/testdata/assign_rank/assign_rank.go.in
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
package assign_rank
|
||||
|
||||
var (
|
||||
apple int = 3 //@item(apple, "apple", "int", "var")
|
||||
pear string = "hello" //@item(pear, "pear", "string", "var")
|
||||
)
|
||||
|
||||
func _() {
|
||||
orange := 1 //@item(orange, "orange", "int", "var")
|
||||
grape := "hello" //@item(grape, "grape", "string", "var")
|
||||
orange, grape = 2, "hello" //@complete(" \"", grape, pear, orange, apple)
|
||||
}
|
||||
|
||||
func _() {
|
||||
var pineapple int //@item(pineapple, "pineapple", "int", "var")
|
||||
pineapple = //@complete(" /", pineapple, apple, pear)
|
||||
|
||||
y := //@complete(" /", pineapple, apple, pear)
|
||||
}
|
13
internal/lsp/testdata/bad/bad.go
vendored
13
internal/lsp/testdata/bad/bad.go
vendored
@ -1,18 +1,21 @@
|
||||
// +build go1.11
|
||||
|
||||
package bad
|
||||
|
||||
func stuff() {
|
||||
func stuff() { //@item(stuff, "stuff()", "", "func")
|
||||
x := "heeeeyyyy"
|
||||
random2(x) //@diag("x", "cannot use x (variable of type string) as int value in argument to random2")
|
||||
random2(1)
|
||||
y := 3 //@diag("y", "y declared but not used")
|
||||
random2(1) //@complete("dom", random, random2, random3)
|
||||
y := 3 //@diag("y", "y declared but not used")
|
||||
}
|
||||
|
||||
type bob struct {
|
||||
type bob struct { //@item(bob, "bob", "struct{...}", "struct")
|
||||
x int
|
||||
}
|
||||
|
||||
func _() {
|
||||
var q int
|
||||
_ = &bob{
|
||||
f: 0, //@diag("f", "unknown field f in struct literal")
|
||||
f: q, //@diag("f", "unknown field f in struct literal")
|
||||
}
|
||||
}
|
||||
|
25
internal/lsp/testdata/bad/bad_util.go
vendored
25
internal/lsp/testdata/bad/bad_util.go
vendored
@ -1,6 +1,27 @@
|
||||
// +build go1.11
|
||||
|
||||
package bad
|
||||
|
||||
func random2(y int) int {
|
||||
x := 6 //@diag("x", "x declared but not used")
|
||||
// import (
|
||||
// "github.com/bob/pkg" //@diag("\"github.com/bob/pkg\"", "unable to import "\"github.com/bob/pkg\"")
|
||||
// )
|
||||
|
||||
var a unknown //@item(global_a, "a", "unknown", "var"),diag("unknown", "undeclared name: unknown")
|
||||
|
||||
func random() int { //@item(random, "random()", "int", "func")
|
||||
//@complete("", global_a, bob, random, random2, random3, stuff)
|
||||
return 0
|
||||
}
|
||||
|
||||
func random2(y int) int { //@item(random2, "random2(y int)", "int", "func"),item(bad_y_param, "y", "int", "var")
|
||||
x := 6 //@item(x, "x", "int", "var"),diag("x", "x declared but not used")
|
||||
var q blah //@item(q, "q", "blah", "var"),diag("q", "q declared but not used"),diag("blah", "undeclared name: blah")
|
||||
var t blob //@item(t, "t", "blob", "var"),diag("t", "t declared but not used"),diag("blob", "undeclared name: blob")
|
||||
//@complete("", q, t, x, bad_y_param, global_a, bob, random, random2, random3, stuff)
|
||||
|
||||
return y
|
||||
}
|
||||
|
||||
func random3(y ...int) { //@item(random3, "random3(y ...int)", "", "func"),item(y_variadic_param, "y", "[]int", "var")
|
||||
//@complete("", y_variadic_param, global_a, bob, random, random2, random3, stuff)
|
||||
}
|
||||
|
7
internal/lsp/testdata/bar/bar.go
vendored
7
internal/lsp/testdata/bar/bar.go
vendored
@ -1,7 +0,0 @@
|
||||
package bar
|
||||
|
||||
import "golang.org/x/tools/internal/lsp/foo"
|
||||
|
||||
func Bar() {
|
||||
foo.Foo()
|
||||
}
|
43
internal/lsp/testdata/bar/bar.go.in
vendored
Normal file
43
internal/lsp/testdata/bar/bar.go.in
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
// +build go1.11
|
||||
|
||||
package bar
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/internal/lsp/foo" //@item(foo, "foo", "\"golang.org/x/tools/internal/lsp/foo\"", "package")
|
||||
)
|
||||
|
||||
func _() {
|
||||
_ = foo.StructFoo{} //@complete("S", Foo, IntFoo, StructFoo)
|
||||
}
|
||||
|
||||
func Bar() { //@item(Bar, "Bar()", "", "func")
|
||||
foo.Foo() //@complete("F", Foo, IntFoo, StructFoo)
|
||||
var _ foo.IntFoo //@complete("I", Foo, IntFoo, StructFoo)
|
||||
foo.() //@complete("(", Foo, IntFoo, StructFoo)
|
||||
}
|
||||
|
||||
func _() {
|
||||
var Valentine int //@item(Valentine, "Valentine", "int", "var")
|
||||
|
||||
_ = foo.StructFoo{
|
||||
Val //@complete("l", Value)
|
||||
}
|
||||
_ = foo.StructFoo{
|
||||
Va //@complete("a", Value)
|
||||
}
|
||||
_ = foo.StructFoo{
|
||||
Value: 5, //@complete("a", Value)
|
||||
}
|
||||
_ = foo.StructFoo{
|
||||
//@complete("", Value)
|
||||
}
|
||||
_ = foo.StructFoo{
|
||||
Value: Valen //@complete("le", Valentine)
|
||||
}
|
||||
_ = foo.StructFoo{
|
||||
Value: //@complete(re"$", Valentine, foo, Bar)
|
||||
}
|
||||
_ = foo.StructFoo{
|
||||
Value: //@complete(" ", Valentine, foo, Bar)
|
||||
}
|
||||
}
|
7
internal/lsp/testdata/baz/baz.go
vendored
7
internal/lsp/testdata/baz/baz.go
vendored
@ -1,7 +0,0 @@
|
||||
package baz
|
||||
|
||||
import "golang.org/x/tools/internal/lsp/bar"
|
||||
|
||||
func Baz() {
|
||||
bar.Bar()
|
||||
}
|
31
internal/lsp/testdata/baz/baz.go.in
vendored
Normal file
31
internal/lsp/testdata/baz/baz.go.in
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
// +build go1.11
|
||||
|
||||
package baz
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/internal/lsp/bar"
|
||||
|
||||
f "golang.org/x/tools/internal/lsp/foo"
|
||||
)
|
||||
|
||||
func Baz() {
|
||||
defer bar.Bar() //@complete("B", Bar)
|
||||
// TODO(rstambler): Test completion here.
|
||||
defer bar.B
|
||||
var _ f.IntFoo //@complete("n", IntFoo)
|
||||
bar.Bar() //@complete("B", Bar)
|
||||
}
|
||||
|
||||
func _() {
|
||||
bob := f.StructFoo{Value: 5}
|
||||
if x := bob. //@complete(re"$", Value)
|
||||
switch true == false {
|
||||
case true:
|
||||
if x := bob. //@complete(re"$", Value)
|
||||
case false:
|
||||
}
|
||||
if x := bob.Va //@complete("a", Value)
|
||||
switch true == true {
|
||||
default:
|
||||
}
|
||||
}
|
11
internal/lsp/testdata/cast/cast.go.in
vendored
Normal file
11
internal/lsp/testdata/cast/cast.go.in
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
package cast
|
||||
|
||||
func _() {
|
||||
foo := struct{x int}{x: 1} //@item(x_field, "x", "int", "field")
|
||||
_ = float64(foo.x) //@complete("x", x_field)
|
||||
}
|
||||
|
||||
func _() {
|
||||
foo := struct{x int}{x: 1}
|
||||
_ = float64(foo. //@complete(" /", x_field)
|
||||
}
|
4
internal/lsp/testdata/good/good.go
vendored
4
internal/lsp/testdata/good/good.go
vendored
@ -1,6 +1,6 @@
|
||||
package good
|
||||
package good //@diag("package", "")
|
||||
|
||||
func stuff() {
|
||||
func stuff() { //@item(good_stuff, "stuff()", "", "func")
|
||||
x := 5
|
||||
random2(x)
|
||||
}
|
||||
|
15
internal/lsp/testdata/good/good_util.go
vendored
15
internal/lsp/testdata/good/good_util.go
vendored
@ -1,10 +1,19 @@
|
||||
package good
|
||||
package good //@diag("package", "")
|
||||
|
||||
func random() int {
|
||||
import (
|
||||
"golang.org/x/tools/internal/lsp/types" //@item(types_import, "types", "\"golang.org/x/tools/internal/lsp/types\"", "package")
|
||||
)
|
||||
|
||||
func random() int { //@item(good_random, "random()", "int", "func")
|
||||
y := 6 + 7
|
||||
return y
|
||||
}
|
||||
|
||||
func random2(y int) int {
|
||||
func random2(y int) int { //@item(good_random2, "random2(y int)", "int", "func"),item(good_y_param, "y", "int", "var")
|
||||
//@complete("", good_y_param, types_import, good_random, good_random2, good_stuff)
|
||||
var b types.Bob = &types.X{}
|
||||
if _, ok := b.(*types.X); ok { //@complete("X", Bob_interface, X_struct, Y_struct)
|
||||
}
|
||||
|
||||
return y
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
// +build !go1.11
|
||||
|
||||
// This file does not actually test anything
|
||||
// on 1.10 the errors are different
|
||||
package noparse_format
|
||||
|
||||
func what() {
|
||||
// we need a diagnostic below so we have the same count as the main file
|
||||
var b int //@diag("b", "b declared but not used")
|
||||
if true {}
|
||||
}
|
66
internal/lsp/testdata/selector/selector.go.in
vendored
Normal file
66
internal/lsp/testdata/selector/selector.go.in
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
// +build go1.11
|
||||
|
||||
package selector
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/internal/lsp/bar"
|
||||
)
|
||||
|
||||
type S struct {
|
||||
B, A, C int //@item(Bf, "B", "int", "field"),item(Af, "A", "int", "field"),item(Cf, "C", "int", "field")
|
||||
}
|
||||
|
||||
func _() {
|
||||
_ = S{}.; //@complete(";", Bf, Af, Cf)
|
||||
}
|
||||
|
||||
type bob struct { a int } //@item(a, "a", "int", "field")
|
||||
type george struct { b int }
|
||||
type jack struct { c int } //@item(c, "c", "int", "field")
|
||||
type jill struct { d int }
|
||||
|
||||
func (b *bob) george() *george {} //@item(george, "george()", "*george", "method")
|
||||
func (g *george) jack() *jack {}
|
||||
func (j *jack) jill() *jill {} //@item(jill, "jill()", "*jill", "method")
|
||||
|
||||
func _() {
|
||||
b := &bob{}
|
||||
y := b.george().
|
||||
jack();
|
||||
y.; //@complete(";", jill, c)
|
||||
}
|
||||
|
||||
func _() {
|
||||
bar. //@complete(" /", Bar)
|
||||
x := 5
|
||||
|
||||
var b *bob
|
||||
b. //@complete(" /", george, a)
|
||||
y, z := 5, 6
|
||||
|
||||
b. //@complete(" /", george, a)
|
||||
y, z, a, b, c := 5, 6
|
||||
}
|
||||
|
||||
func _() {
|
||||
bar. //@complete(" /", Bar)
|
||||
bar.Bar()
|
||||
|
||||
bar. //@complete(" /", Bar)
|
||||
go f()
|
||||
}
|
||||
|
||||
func _() {
|
||||
var b *bob
|
||||
if y != b. //@complete(" /", george, a)
|
||||
z := 5
|
||||
|
||||
if z + y + 1 + b. //@complete(" /", george, a)
|
||||
r, s, t := 4, 5
|
||||
|
||||
if y != b. //@complete(" /", george, a)
|
||||
z = 5
|
||||
|
||||
if z + y + 1 + b. //@complete(" /", george, a)
|
||||
r = 4
|
||||
}
|
16
internal/lsp/testdata/types/types.go
vendored
Normal file
16
internal/lsp/testdata/types/types.go
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
package types
|
||||
|
||||
type X struct { //@item(X_struct, "X", "struct{...}", "struct")
|
||||
x int
|
||||
}
|
||||
|
||||
type Y struct { //@item(Y_struct, "Y", "struct{...}", "struct")
|
||||
y int
|
||||
}
|
||||
|
||||
type Bob interface { //@item(Bob_interface, "Bob", "interface{...}", "interface")
|
||||
Bobby()
|
||||
}
|
||||
|
||||
func (*X) Bobby() {}
|
||||
func (*Y) Bobby() {}
|
Loading…
Reference in New Issue
Block a user