mirror of
https://github.com/golang/go
synced 2024-11-18 14:14:46 -07:00
internal/lsp: fix definition tests to use golden files
specifically it uses them for the guru compatability tests This change radically increases the test coverage of the godef tests as it now works for all the jump to definition tests not just the specialized ones. Change-Id: I63547138566ac3de56344dcfddb758ed5f362a06 Reviewed-on: https://go-review.googlesource.com/c/tools/+/174937 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
45e43b2cb4
commit
4ca280b5bd
@ -8,10 +8,10 @@ import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/tools/go/packages/packagestest"
|
||||
"golang.org/x/tools/internal/lsp/cmd"
|
||||
@ -21,8 +21,9 @@ import (
|
||||
var isRace = false
|
||||
|
||||
type runner struct {
|
||||
data *tests.Data
|
||||
app *cmd.Application
|
||||
exporter packagestest.Exporter
|
||||
data *tests.Data
|
||||
app *cmd.Application
|
||||
}
|
||||
|
||||
func TestCommandLine(t *testing.T) {
|
||||
@ -34,7 +35,8 @@ func testCommandLine(t *testing.T, exporter packagestest.Exporter) {
|
||||
defer data.Exported.Cleanup()
|
||||
|
||||
r := &runner{
|
||||
data: data,
|
||||
exporter: exporter,
|
||||
data: data,
|
||||
app: &cmd.Application{
|
||||
Config: *data.Exported.Config,
|
||||
},
|
||||
@ -84,20 +86,34 @@ func captureStdOut(t testing.TB, f func()) string {
|
||||
|
||||
// normalizePaths replaces all paths present in s with just the fragment portion
|
||||
// this is used to make golden files not depend on the temporary paths of the files
|
||||
func (r *runner) normalizePaths(s string) string {
|
||||
func normalizePaths(data *tests.Data, s string) string {
|
||||
type entry struct {
|
||||
path string
|
||||
index int
|
||||
path string
|
||||
index int
|
||||
fragment string
|
||||
}
|
||||
match := make([]entry, len(r.data.Exported.Modules))
|
||||
match := make([]entry, 0, len(data.Exported.Modules))
|
||||
// collect the initial state of all the matchers
|
||||
for i, m := range r.data.Exported.Modules {
|
||||
// any random file will do, we collect the first one only
|
||||
for f := range m.Files {
|
||||
path := strings.TrimSuffix(r.data.Exported.File(m.Name, f), f)
|
||||
index := strings.Index(s, path)
|
||||
match[i] = entry{path, index}
|
||||
break
|
||||
for _, m := range data.Exported.Modules {
|
||||
for fragment := range m.Files {
|
||||
filename := data.Exported.File(m.Name, fragment)
|
||||
index := strings.Index(s, filename)
|
||||
if index >= 0 {
|
||||
match = append(match, entry{filename, index, fragment})
|
||||
}
|
||||
if slash := filepath.ToSlash(filename); slash != filename {
|
||||
index := strings.Index(s, slash)
|
||||
if index >= 0 {
|
||||
match = append(match, entry{slash, index, fragment})
|
||||
}
|
||||
}
|
||||
quoted := strconv.Quote(filename)
|
||||
if escaped := quoted[1 : len(quoted)-1]; escaped != filename {
|
||||
index := strings.Index(s, escaped)
|
||||
if index >= 0 {
|
||||
match = append(match, entry{escaped, index, fragment})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// result should be the same or shorter than the input
|
||||
@ -122,20 +138,10 @@ func (r *runner) normalizePaths(s string) string {
|
||||
n := &match[next]
|
||||
// copy up to the start of the match
|
||||
buf.WriteString(s[last:n.index])
|
||||
// skip over the non fragment prefix
|
||||
// skip over the filename
|
||||
last = n.index + len(n.path)
|
||||
// now try to convert the fragment part
|
||||
for last < len(s) {
|
||||
r, size := utf8.DecodeRuneInString(s[last:])
|
||||
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '/' {
|
||||
buf.WriteRune(r)
|
||||
} else if r == '\\' {
|
||||
buf.WriteRune('/')
|
||||
} else {
|
||||
break
|
||||
}
|
||||
last += size
|
||||
}
|
||||
// add in the fragment instead
|
||||
buf.WriteString(n.fragment)
|
||||
// see what the next match for this path is
|
||||
n.index = strings.Index(s[last:], n.path)
|
||||
if n.index >= 0 {
|
||||
|
@ -6,14 +6,12 @@ package cmd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -28,7 +26,20 @@ const (
|
||||
expectedTypeDefinitionsCount = 2
|
||||
)
|
||||
|
||||
var verifyGuru = flag.Bool("verify-guru", false, "Check that the guru compatability matches")
|
||||
type godefMode int
|
||||
|
||||
const (
|
||||
plainGodef = godefMode(1 << iota)
|
||||
jsonGoDef
|
||||
guruGoDef
|
||||
)
|
||||
|
||||
var godefModes = []godefMode{
|
||||
plainGodef,
|
||||
jsonGoDef,
|
||||
guruGoDef,
|
||||
jsonGoDef | guruGoDef,
|
||||
}
|
||||
|
||||
func TestDefinitionHelpExample(t *testing.T) {
|
||||
if runtime.GOOS == "android" {
|
||||
@ -55,132 +66,96 @@ func TestDefinitionHelpExample(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
var brokenDefinitionTests = map[string]bool{
|
||||
// The following tests all have extra information in the description
|
||||
"A-definition-json-guru": true,
|
||||
"err-definition-json-guru": true,
|
||||
"myUnclosedIf-definition-json-guru": true,
|
||||
"Other-definition-json-guru": true,
|
||||
"RandomParamY-definition-json-guru": true,
|
||||
"S1-definition-json-guru": true,
|
||||
"S2-definition-json-guru": true,
|
||||
"Stuff-definition-json-guru": true,
|
||||
"Thing-definition-json-guru": true,
|
||||
"Things-definition-json-guru": true,
|
||||
}
|
||||
|
||||
func (r *runner) Definition(t *testing.T, data tests.Definitions) {
|
||||
for _, d := range data {
|
||||
if d.IsType {
|
||||
// TODO: support type definition queries
|
||||
continue
|
||||
}
|
||||
args := []string{"-remote=internal", "query"}
|
||||
if d.Flags != "" {
|
||||
args = append(args, strings.Split(d.Flags, " ")...)
|
||||
}
|
||||
args = append(args, "definition")
|
||||
src := span.New(d.Src.URI(), span.NewPoint(0, 0, d.Src.Start().Offset()), span.Point{})
|
||||
args = append(args, fmt.Sprint(src))
|
||||
got := captureStdOut(t, func() {
|
||||
tool.Main(context.Background(), r.app, args)
|
||||
})
|
||||
pattern := newPattern(d.Match, d.Def)
|
||||
if !pattern.matches(got) {
|
||||
t.Errorf("definition %v\nexpected:\n%s\ngot:\n%s", args, pattern, got)
|
||||
}
|
||||
if *verifyGuru {
|
||||
moduleMode := r.data.Exported.File(r.data.Exported.Modules[0].Name, "go.mod") != ""
|
||||
var guruArgs []string
|
||||
runGuru := false
|
||||
if !moduleMode {
|
||||
for _, arg := range args {
|
||||
switch {
|
||||
case arg == "query":
|
||||
// just ignore this one
|
||||
case arg == "-json":
|
||||
guruArgs = append(guruArgs, arg)
|
||||
case arg == "-emulate=guru":
|
||||
// if we don't see this one we should not run guru
|
||||
runGuru = true
|
||||
case strings.HasPrefix(arg, "-"):
|
||||
// unknown flag, ignore it
|
||||
break
|
||||
default:
|
||||
guruArgs = append(guruArgs, arg)
|
||||
}
|
||||
}
|
||||
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")
|
||||
}
|
||||
if runGuru {
|
||||
if mode&guruGoDef != 0 {
|
||||
if r.exporter.Name() != "GOPATH" {
|
||||
//only run guru compatability tests in GOPATH mode
|
||||
continue
|
||||
}
|
||||
if d.Name == "PackageFoo" {
|
||||
//guru does not support definition on packages
|
||||
continue
|
||||
}
|
||||
tag += "-guru"
|
||||
args = append(args, "-emulate=guru")
|
||||
}
|
||||
if _, found := brokenDefinitionTests[tag]; found {
|
||||
continue
|
||||
}
|
||||
args = append(args, "definition")
|
||||
uri := d.Src.URI()
|
||||
filename, err := uri.Filename()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
args = append(args, fmt.Sprint(d.Src))
|
||||
got := captureStdOut(t, func() {
|
||||
tool.Main(context.Background(), r.app, args)
|
||||
})
|
||||
got = normalizePaths(r.data, got)
|
||||
if mode&jsonGoDef != 0 && runtime.GOOS == "windows" {
|
||||
got = strings.Replace(got, "file:///", "file://", -1)
|
||||
}
|
||||
if mode&guruGoDef == 0 {
|
||||
expect := string(r.data.Golden(tag, filename, func() ([]byte, error) {
|
||||
return []byte(got), nil
|
||||
}))
|
||||
if got != expect {
|
||||
t.Errorf("definition %v failed with %#v expected:\n%s\ngot:\n%s", tag, args, expect, got)
|
||||
}
|
||||
continue
|
||||
}
|
||||
guruArgs := []string{}
|
||||
if mode&jsonGoDef != 0 {
|
||||
guruArgs = append(guruArgs, "-json")
|
||||
}
|
||||
guruArgs = append(guruArgs, "definition", fmt.Sprint(d.Src))
|
||||
expect := strings.TrimSpace(string(r.data.Golden(tag, filename, func() ([]byte, error) {
|
||||
cmd := exec.Command("guru", guruArgs...)
|
||||
cmd.Env = r.data.Exported.Config.Env
|
||||
out, err := cmd.CombinedOutput()
|
||||
out, _ := cmd.Output()
|
||||
if err != nil {
|
||||
t.Errorf("Could not run guru %v: %v\n%s", guruArgs, err, out)
|
||||
} else {
|
||||
guru := strings.TrimSpace(string(out))
|
||||
if !pattern.matches(guru) {
|
||||
t.Errorf("definition %v\nexpected:\n%s\nguru gave:\n%s", args, pattern, guru)
|
||||
if _, ok := err.(*exec.ExitError); !ok {
|
||||
return nil, fmt.Errorf("Could not run guru %v: %v\n%s", guruArgs, err, out)
|
||||
}
|
||||
}
|
||||
result := normalizePaths(r.data, string(out))
|
||||
// guru sometimes puts the full package path in type names, but we don't
|
||||
if mode&jsonGoDef == 0 && d.Name != "AImport" {
|
||||
result = strings.Replace(result, "golang.org/x/tools/internal/lsp/godef/", "", -1)
|
||||
}
|
||||
return []byte(result), nil
|
||||
})))
|
||||
if expect != "" && !strings.HasPrefix(got, expect) {
|
||||
t.Errorf("definition %v failed with %#v expected:\n%q\ngot:\n%q", tag, args, expect, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type pattern struct {
|
||||
raw string
|
||||
expanded []string
|
||||
matchAll bool
|
||||
}
|
||||
|
||||
func newPattern(s string, def span.Span) pattern {
|
||||
p := pattern{raw: s}
|
||||
if s == "" {
|
||||
p.expanded = []string{fmt.Sprintf("%v: ", def)}
|
||||
return p
|
||||
}
|
||||
p.matchAll = strings.HasSuffix(s, "$$")
|
||||
for _, fragment := range strings.Split(s, "$$") {
|
||||
p.expanded = append(p.expanded, os.Expand(fragment, func(name string) string {
|
||||
switch name {
|
||||
case "file":
|
||||
fname, _ := def.URI().Filename()
|
||||
return fname
|
||||
case "efile":
|
||||
fname, _ := def.URI().Filename()
|
||||
qfile := strconv.Quote(fname)
|
||||
return qfile[1 : len(qfile)-1]
|
||||
case "euri":
|
||||
quri := strconv.Quote(string(def.URI()))
|
||||
return quri[1 : len(quri)-1]
|
||||
case "line":
|
||||
return fmt.Sprint(def.Start().Line())
|
||||
case "col":
|
||||
return fmt.Sprint(def.Start().Column())
|
||||
case "offset":
|
||||
return fmt.Sprint(def.Start().Offset())
|
||||
case "eline":
|
||||
return fmt.Sprint(def.End().Line())
|
||||
case "ecol":
|
||||
return fmt.Sprint(def.End().Column())
|
||||
case "eoffset":
|
||||
return fmt.Sprint(def.End().Offset())
|
||||
default:
|
||||
return name
|
||||
}
|
||||
}))
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func (p pattern) String() string {
|
||||
return strings.Join(p.expanded, "$$")
|
||||
}
|
||||
|
||||
func (p pattern) matches(s string) bool {
|
||||
if len(p.expanded) == 0 {
|
||||
return false
|
||||
}
|
||||
if !strings.HasPrefix(s, p.expanded[0]) {
|
||||
return false
|
||||
}
|
||||
remains := s[len(p.expanded[0]):]
|
||||
for _, fragment := range p.expanded[1:] {
|
||||
i := strings.Index(remains, fragment)
|
||||
if i < 0 {
|
||||
return false
|
||||
}
|
||||
remains = remains[i+len(fragment):]
|
||||
}
|
||||
if !p.matchAll {
|
||||
return true
|
||||
}
|
||||
return len(remains) == 0
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ func (r *runner) Format(t *testing.T, data tests.Formats) {
|
||||
expect := string(r.data.Golden(tag, filename, func() ([]byte, error) {
|
||||
cmd := exec.Command("gofmt", args...)
|
||||
contents, _ := cmd.Output() // ignore error, sometimes we have intentionally ungofmt-able files
|
||||
contents = []byte(r.normalizePaths(fixFileHeader(string(contents))))
|
||||
contents = []byte(normalizePaths(r.data, fixFileHeader(string(contents))))
|
||||
return contents, nil
|
||||
}))
|
||||
if expect == "" {
|
||||
@ -46,7 +46,7 @@ func (r *runner) Format(t *testing.T, data tests.Formats) {
|
||||
got := captureStdOut(t, func() {
|
||||
tool.Main(context.Background(), app, append([]string{"-remote=internal", "format"}, args...))
|
||||
})
|
||||
got = r.normalizePaths(got)
|
||||
got = normalizePaths(r.data, got)
|
||||
// check the first two lines are the expected file header
|
||||
if expect != got {
|
||||
t.Errorf("format failed with %#v expected:\n%s\ngot:\n%s", args, expect, got)
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
find ./internal/lsp/ -name *.golden -delete
|
||||
go test ./internal/lsp/ ./internal/lsp/cmd -golden
|
||||
go test ./internal/lsp/ ./internal/lsp/cmd ./internal/lsp/source -golden
|
||||
|
76
internal/lsp/testdata/godef/a/a.go.golden
vendored
76
internal/lsp/testdata/godef/a/a.go.golden
vendored
@ -1,6 +1,82 @@
|
||||
-- Random-definition --
|
||||
godef/a/random.go:3:6-12: defined here as func Random() int
|
||||
-- Random-definition-guru --
|
||||
|
||||
-- Random-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/random.go",
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 6,
|
||||
"offset": 16
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 12,
|
||||
"offset": 22
|
||||
}
|
||||
},
|
||||
"description": "func Random() int"
|
||||
}
|
||||
|
||||
-- Random-definition-json-guru --
|
||||
|
||||
-- Random-hover --
|
||||
func Random() int
|
||||
-- Random2-definition --
|
||||
godef/a/random.go:8:6-13: defined here as func Random2(y int) int
|
||||
-- Random2-definition-guru --
|
||||
godef/a/random.go:8:6: defined here as func Random2(y int) int
|
||||
|
||||
-- Random2-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/random.go",
|
||||
"start": {
|
||||
"line": 8,
|
||||
"column": 6,
|
||||
"offset": 71
|
||||
},
|
||||
"end": {
|
||||
"line": 8,
|
||||
"column": 13,
|
||||
"offset": 78
|
||||
}
|
||||
},
|
||||
"description": "func Random2(y int) int"
|
||||
}
|
||||
|
||||
-- Random2-definition-json-guru --
|
||||
{
|
||||
"objpos": "godef/a/random.go:8:6",
|
||||
"desc": "func Random2(y int) int"
|
||||
}
|
||||
|
||||
-- Random2-hover --
|
||||
func Random2(y int) int
|
||||
-- err-definition --
|
||||
godef/a/a.go:14:6-9: defined here as var err error
|
||||
-- err-definition-guru --
|
||||
godef/a/a.go:14:6: defined here as var err
|
||||
|
||||
-- err-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/a.go",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 6,
|
||||
"offset": 201
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 9,
|
||||
"offset": 204
|
||||
}
|
||||
},
|
||||
"description": "var err error"
|
||||
}
|
||||
|
||||
-- err-hover --
|
||||
var err error
|
||||
|
41
internal/lsp/testdata/godef/a/d.go
vendored
41
internal/lsp/testdata/godef/a/d.go
vendored
@ -25,46 +25,15 @@ func useThings() {
|
||||
}
|
||||
|
||||
/*@
|
||||
definition(aStructType, "", Thing, "$file:$line:$col-$ecol: defined here as type Thing struct{Member string}")
|
||||
definition(aStructType, "-emulate=guru", Thing, "$file:$line:$col: defined here as type Thing")
|
||||
|
||||
definition(aMember, "", Member, "$file:$line:$col-$ecol: defined here as field Member string")
|
||||
definition(aMember, "-emulate=guru", Member, "$file:$line:$col: defined here as field Member string")
|
||||
|
||||
definition(aVar, "", Other, "$file:$line:$col-$ecol: defined here as var Other Thing")
|
||||
definition(aVar, "-emulate=guru", Other, "$file:$line:$col: defined here as var Other")
|
||||
|
||||
definition(aFunc, "", Things, "$file:$line:$col-$ecol: defined here as func Things(val []string) []Thing")
|
||||
definition(aFunc, "-emulate=guru", Things, "$file:$line:$col: defined here as func Things")
|
||||
|
||||
definition(aMethod, "", Method, "$file:$line:$col-$ecol: defined here as func (Thing).Method(i int) string")
|
||||
definition(aMethod, "-emulate=guru", Method, "$file:$line:$col: defined here as func (Thing).Method(i int) string")
|
||||
godef(aStructType, Thing)
|
||||
godef(aMember, Member)
|
||||
godef(aVar, Other)
|
||||
godef(aFunc, Things)
|
||||
godef(aMethod, Method)
|
||||
|
||||
//param
|
||||
//package name
|
||||
//const
|
||||
//anon field
|
||||
|
||||
// JSON tests
|
||||
|
||||
definition(aStructType, "-json", Thing, `{
|
||||
"span": {
|
||||
"uri": "$euri",
|
||||
"start": {
|
||||
"line": $line,
|
||||
"column": $col,
|
||||
"offset": $offset
|
||||
},
|
||||
"end": {
|
||||
"line": $eline,
|
||||
"column": $ecol,
|
||||
"offset": $eoffset
|
||||
}
|
||||
},
|
||||
"description": "type Thing struct{Member string}"
|
||||
}`)
|
||||
definition(aStructType, "-json -emulate=guru", Thing, `{
|
||||
"objpos": "$efile:$line:$col",
|
||||
"desc": "type Thing$$"
|
||||
}`)
|
||||
*/
|
||||
|
137
internal/lsp/testdata/godef/a/d.go.golden
vendored
Normal file
137
internal/lsp/testdata/godef/a/d.go.golden
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
-- Member-definition --
|
||||
godef/a/d.go:6:2-8: defined here as field Member string
|
||||
-- Member-definition-guru --
|
||||
godef/a/d.go:6:2: defined here as field Member string
|
||||
|
||||
-- Member-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/d.go",
|
||||
"start": {
|
||||
"line": 6,
|
||||
"column": 2,
|
||||
"offset": 55
|
||||
},
|
||||
"end": {
|
||||
"line": 6,
|
||||
"column": 8,
|
||||
"offset": 61
|
||||
}
|
||||
},
|
||||
"description": "field Member string"
|
||||
}
|
||||
|
||||
-- Member-definition-json-guru --
|
||||
{
|
||||
"objpos": "godef/a/d.go:6:2",
|
||||
"desc": "field Member string"
|
||||
}
|
||||
|
||||
-- Member-hover --
|
||||
field Member string
|
||||
-- Method-definition --
|
||||
godef/a/d.go:15:16-22: defined here as func (Thing).Method(i int) string
|
||||
-- Method-definition-guru --
|
||||
godef/a/d.go:15:16: defined here as func (Thing).Method(i int) string
|
||||
|
||||
-- Method-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/d.go",
|
||||
"start": {
|
||||
"line": 15,
|
||||
"column": 16,
|
||||
"offset": 184
|
||||
},
|
||||
"end": {
|
||||
"line": 15,
|
||||
"column": 22,
|
||||
"offset": 190
|
||||
}
|
||||
},
|
||||
"description": "func (Thing).Method(i int) string"
|
||||
}
|
||||
|
||||
-- Method-definition-json-guru --
|
||||
{
|
||||
"objpos": "godef/a/d.go:15:16",
|
||||
"desc": "func (Thing).Method(i int) string"
|
||||
}
|
||||
|
||||
-- Method-hover --
|
||||
func (Thing).Method(i int) string
|
||||
-- Other-definition --
|
||||
godef/a/d.go:9:5-10: defined here as var Other Thing
|
||||
-- Other-definition-guru --
|
||||
godef/a/d.go:9:5: defined here as var Other
|
||||
|
||||
-- Other-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/d.go",
|
||||
"start": {
|
||||
"line": 9,
|
||||
"column": 5,
|
||||
"offset": 86
|
||||
},
|
||||
"end": {
|
||||
"line": 9,
|
||||
"column": 10,
|
||||
"offset": 91
|
||||
}
|
||||
},
|
||||
"description": "var Other Thing"
|
||||
}
|
||||
|
||||
-- Other-hover --
|
||||
var Other Thing
|
||||
-- Thing-definition --
|
||||
godef/a/d.go:5:6-11: defined here as type Thing struct{Member string}
|
||||
-- Thing-definition-guru --
|
||||
godef/a/d.go:5:6: defined here as type Thing
|
||||
|
||||
-- Thing-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/d.go",
|
||||
"start": {
|
||||
"line": 5,
|
||||
"column": 6,
|
||||
"offset": 30
|
||||
},
|
||||
"end": {
|
||||
"line": 5,
|
||||
"column": 11,
|
||||
"offset": 35
|
||||
}
|
||||
},
|
||||
"description": "type Thing struct{Member string}"
|
||||
}
|
||||
|
||||
-- Thing-hover --
|
||||
type Thing struct{Member string}
|
||||
-- Things-definition --
|
||||
godef/a/d.go:11:6-12: defined here as func Things(val []string) []Thing
|
||||
-- Things-definition-guru --
|
||||
godef/a/d.go:11:6: defined here as func Things
|
||||
|
||||
-- Things-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/d.go",
|
||||
"start": {
|
||||
"line": 11,
|
||||
"column": 6,
|
||||
"offset": 113
|
||||
},
|
||||
"end": {
|
||||
"line": 11,
|
||||
"column": 12,
|
||||
"offset": 119
|
||||
}
|
||||
},
|
||||
"description": "func Things(val []string) []Thing"
|
||||
}
|
||||
|
||||
-- Things-hover --
|
||||
func Things(val []string) []Thing
|
76
internal/lsp/testdata/godef/a/random.go.golden
vendored
76
internal/lsp/testdata/godef/a/random.go.golden
vendored
@ -1,6 +1,82 @@
|
||||
-- PosSum-definition --
|
||||
godef/a/random.go:16:15-18: defined here as func (*Pos).Sum() int
|
||||
-- PosSum-definition-guru --
|
||||
|
||||
-- PosSum-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/random.go",
|
||||
"start": {
|
||||
"line": 16,
|
||||
"column": 15,
|
||||
"offset": 248
|
||||
},
|
||||
"end": {
|
||||
"line": 16,
|
||||
"column": 18,
|
||||
"offset": 251
|
||||
}
|
||||
},
|
||||
"description": "func (*Pos).Sum() int"
|
||||
}
|
||||
|
||||
-- PosSum-definition-json-guru --
|
||||
|
||||
-- PosSum-hover --
|
||||
func (*Pos).Sum() int
|
||||
-- PosX-definition --
|
||||
godef/a/random.go:13:2-3: defined here as field x int
|
||||
-- PosX-definition-guru --
|
||||
godef/a/random.go:13:2: defined here as field x int
|
||||
|
||||
-- PosX-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/random.go",
|
||||
"start": {
|
||||
"line": 13,
|
||||
"column": 2,
|
||||
"offset": 187
|
||||
},
|
||||
"end": {
|
||||
"line": 13,
|
||||
"column": 3,
|
||||
"offset": 188
|
||||
}
|
||||
},
|
||||
"description": "field x int"
|
||||
}
|
||||
|
||||
-- PosX-definition-json-guru --
|
||||
{
|
||||
"objpos": "godef/a/random.go:13:2",
|
||||
"desc": "field x int"
|
||||
}
|
||||
|
||||
-- PosX-hover --
|
||||
field x int
|
||||
-- RandomParamY-definition --
|
||||
godef/a/random.go:8:14-15: defined here as var y int
|
||||
-- RandomParamY-definition-guru --
|
||||
godef/a/random.go:8:14: defined here as var y
|
||||
|
||||
-- RandomParamY-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/random.go",
|
||||
"start": {
|
||||
"line": 8,
|
||||
"column": 14,
|
||||
"offset": 79
|
||||
},
|
||||
"end": {
|
||||
"line": 8,
|
||||
"column": 15,
|
||||
"offset": 80
|
||||
}
|
||||
},
|
||||
"description": "var y int"
|
||||
}
|
||||
|
||||
-- RandomParamY-hover --
|
||||
var y int
|
||||
|
257
internal/lsp/testdata/godef/b/b.go.golden
vendored
257
internal/lsp/testdata/godef/b/b.go.golden
vendored
@ -1,20 +1,277 @@
|
||||
-- A-definition --
|
||||
godef/a/a.go:7:6-7: defined here as type a.A string
|
||||
-- A-definition-guru --
|
||||
godef/a/a.go:7:6: defined here as type a.A
|
||||
|
||||
-- A-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/a.go",
|
||||
"start": {
|
||||
"line": 7,
|
||||
"column": 6,
|
||||
"offset": 75
|
||||
},
|
||||
"end": {
|
||||
"line": 7,
|
||||
"column": 7,
|
||||
"offset": 76
|
||||
}
|
||||
},
|
||||
"description": "type a.A string"
|
||||
}
|
||||
|
||||
-- A-hover --
|
||||
type a.A string
|
||||
-- AImport-definition --
|
||||
godef/b/b.go:5:2-3: defined here as package a ("golang.org/x/tools/internal/lsp/godef/a")
|
||||
-- AImport-definition-guru --
|
||||
godef/b/b.go:5:2: defined here as package a ("golang.org/x/tools/internal/lsp/godef/a")
|
||||
|
||||
-- AImport-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/b/b.go",
|
||||
"start": {
|
||||
"line": 5,
|
||||
"column": 2,
|
||||
"offset": 121
|
||||
},
|
||||
"end": {
|
||||
"line": 5,
|
||||
"column": 3,
|
||||
"offset": 122
|
||||
}
|
||||
},
|
||||
"description": "package a (\"golang.org/x/tools/internal/lsp/godef/a\")"
|
||||
}
|
||||
|
||||
-- AImport-definition-json-guru --
|
||||
{
|
||||
"objpos": "godef/b/b.go:5:2",
|
||||
"desc": "package a (\"golang.org/x/tools/internal/lsp/godef/a\")"
|
||||
}
|
||||
|
||||
-- AImport-hover --
|
||||
package a ("golang.org/x/tools/internal/lsp/godef/a")
|
||||
-- PackageFoo-definition --
|
||||
foo/foo.go:1:9-12: defined here as
|
||||
-- PackageFoo-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://foo/foo.go",
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 9,
|
||||
"offset": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12,
|
||||
"offset": 11
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
|
||||
-- PackageFoo-hover --
|
||||
|
||||
-- S1-definition --
|
||||
godef/b/b.go:8:6-8: defined here as type S1 struct{F1 int; S2; a.A}
|
||||
-- S1-definition-guru --
|
||||
godef/b/b.go:8:6: defined here as type S1
|
||||
|
||||
-- S1-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/b/b.go",
|
||||
"start": {
|
||||
"line": 8,
|
||||
"column": 6,
|
||||
"offset": 196
|
||||
},
|
||||
"end": {
|
||||
"line": 8,
|
||||
"column": 8,
|
||||
"offset": 198
|
||||
}
|
||||
},
|
||||
"description": "type S1 struct{F1 int; S2; a.A}"
|
||||
}
|
||||
|
||||
-- S1-hover --
|
||||
type S1 struct{F1 int; S2; a.A}
|
||||
-- S1F1-definition --
|
||||
godef/b/b.go:9:2-4: defined here as field F1 int
|
||||
-- S1F1-definition-guru --
|
||||
godef/b/b.go:9:2: defined here as field F1 int
|
||||
|
||||
-- S1F1-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/b/b.go",
|
||||
"start": {
|
||||
"line": 9,
|
||||
"column": 2,
|
||||
"offset": 215
|
||||
},
|
||||
"end": {
|
||||
"line": 9,
|
||||
"column": 4,
|
||||
"offset": 217
|
||||
}
|
||||
},
|
||||
"description": "field F1 int"
|
||||
}
|
||||
|
||||
-- S1F1-definition-json-guru --
|
||||
{
|
||||
"objpos": "godef/b/b.go:9:2",
|
||||
"desc": "field F1 int"
|
||||
}
|
||||
|
||||
-- S1F1-hover --
|
||||
field F1 int
|
||||
-- S1S2-definition --
|
||||
godef/b/b.go:10:2-4: defined here as field S2 S2
|
||||
-- S1S2-definition-guru --
|
||||
godef/b/b.go:10:2: defined here as field S2 S2
|
||||
|
||||
-- S1S2-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/b/b.go",
|
||||
"start": {
|
||||
"line": 10,
|
||||
"column": 2,
|
||||
"offset": 244
|
||||
},
|
||||
"end": {
|
||||
"line": 10,
|
||||
"column": 4,
|
||||
"offset": 246
|
||||
}
|
||||
},
|
||||
"description": "field S2 S2"
|
||||
}
|
||||
|
||||
-- S1S2-definition-json-guru --
|
||||
{
|
||||
"objpos": "godef/b/b.go:10:2",
|
||||
"desc": "field S2 S2"
|
||||
}
|
||||
|
||||
-- S1S2-hover --
|
||||
field S2 S2
|
||||
-- S2-definition --
|
||||
godef/b/b.go:14:6-8: defined here as type S2 struct{F1 string; F2 int; *a.A}
|
||||
-- S2-definition-guru --
|
||||
godef/b/b.go:14:6: defined here as type S2
|
||||
|
||||
-- S2-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/b/b.go",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 6,
|
||||
"offset": 323
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 8,
|
||||
"offset": 325
|
||||
}
|
||||
},
|
||||
"description": "type S2 struct{F1 string; F2 int; *a.A}"
|
||||
}
|
||||
|
||||
-- S2-hover --
|
||||
type S2 struct{F1 string; F2 int; *a.A}
|
||||
-- S2F1-definition --
|
||||
godef/b/b.go:15:2-4: defined here as field F1 string
|
||||
-- S2F1-definition-guru --
|
||||
godef/b/b.go:15:2: defined here as field F1 string
|
||||
|
||||
-- S2F1-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/b/b.go",
|
||||
"start": {
|
||||
"line": 15,
|
||||
"column": 2,
|
||||
"offset": 342
|
||||
},
|
||||
"end": {
|
||||
"line": 15,
|
||||
"column": 4,
|
||||
"offset": 344
|
||||
}
|
||||
},
|
||||
"description": "field F1 string"
|
||||
}
|
||||
|
||||
-- S2F1-definition-json-guru --
|
||||
{
|
||||
"objpos": "godef/b/b.go:15:2",
|
||||
"desc": "field F1 string"
|
||||
}
|
||||
|
||||
-- S2F1-hover --
|
||||
field F1 string
|
||||
-- S2F2-definition --
|
||||
godef/b/b.go:16:2-4: defined here as field F2 int
|
||||
-- S2F2-definition-guru --
|
||||
godef/b/b.go:16:2: defined here as field F2 int
|
||||
|
||||
-- S2F2-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/b/b.go",
|
||||
"start": {
|
||||
"line": 16,
|
||||
"column": 2,
|
||||
"offset": 375
|
||||
},
|
||||
"end": {
|
||||
"line": 16,
|
||||
"column": 4,
|
||||
"offset": 377
|
||||
}
|
||||
},
|
||||
"description": "field F2 int"
|
||||
}
|
||||
|
||||
-- S2F2-definition-json-guru --
|
||||
{
|
||||
"objpos": "godef/b/b.go:16:2",
|
||||
"desc": "field F2 int"
|
||||
}
|
||||
|
||||
-- S2F2-hover --
|
||||
field F2 int
|
||||
-- Stuff-definition --
|
||||
godef/a/a.go:9:6-11: defined here as func a.Stuff()
|
||||
-- Stuff-definition-guru --
|
||||
godef/a/a.go:9:6: defined here as func a.Stuff
|
||||
|
||||
-- Stuff-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/a.go",
|
||||
"start": {
|
||||
"line": 9,
|
||||
"column": 6,
|
||||
"offset": 95
|
||||
},
|
||||
"end": {
|
||||
"line": 9,
|
||||
"column": 11,
|
||||
"offset": 100
|
||||
}
|
||||
},
|
||||
"description": "func a.Stuff()"
|
||||
}
|
||||
|
||||
-- Stuff-hover --
|
||||
func a.Stuff()
|
||||
|
52
internal/lsp/testdata/godef/b/c.go.golden
vendored
52
internal/lsp/testdata/godef/b/c.go.golden
vendored
@ -1,4 +1,56 @@
|
||||
-- S1-definition --
|
||||
godef/b/b.go:8:6-8: defined here as type S1 struct{F1 int; S2; a.A}
|
||||
-- S1-definition-guru --
|
||||
godef/b/b.go:8:6: defined here as type S1 struct{F1 int; S2; a.A}
|
||||
|
||||
-- S1-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/b/b.go",
|
||||
"start": {
|
||||
"line": 8,
|
||||
"column": 6,
|
||||
"offset": 196
|
||||
},
|
||||
"end": {
|
||||
"line": 8,
|
||||
"column": 8,
|
||||
"offset": 198
|
||||
}
|
||||
},
|
||||
"description": "type S1 struct{F1 int; S2; a.A}"
|
||||
}
|
||||
|
||||
-- S1-hover --
|
||||
type S1 struct{F1 int; S2; a.A}
|
||||
-- S1F1-definition --
|
||||
godef/b/b.go:9:2-4: defined here as field F1 int
|
||||
-- S1F1-definition-guru --
|
||||
godef/b/b.go:9:2: defined here as field F1 int
|
||||
|
||||
-- S1F1-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/b/b.go",
|
||||
"start": {
|
||||
"line": 9,
|
||||
"column": 2,
|
||||
"offset": 215
|
||||
},
|
||||
"end": {
|
||||
"line": 9,
|
||||
"column": 4,
|
||||
"offset": 217
|
||||
}
|
||||
},
|
||||
"description": "field F1 int"
|
||||
}
|
||||
|
||||
-- S1F1-definition-json-guru --
|
||||
{
|
||||
"objpos": "godef/b/b.go:9:2",
|
||||
"desc": "field F1 int"
|
||||
}
|
||||
|
||||
-- S1F1-hover --
|
||||
field F1 int
|
||||
|
15
internal/lsp/testdata/godef/b/e.go
vendored
15
internal/lsp/testdata/godef/b/e.go
vendored
@ -14,15 +14,8 @@ func useThings() {
|
||||
}
|
||||
|
||||
/*@
|
||||
definition(bStructType, "", Thing, "$file:$line:$col-$ecol: defined here as type a.Thing struct{Member string}")
|
||||
definition(bStructType, "-emulate=guru", Thing, "$file:$line:$col: defined here as type $$a.Thing")
|
||||
|
||||
definition(bMember, "", Member, "$file:$line:$col-$ecol: defined here as field Member string")
|
||||
definition(bMember, "-emulate=guru", Member, "$file:$line:$col: defined here as field Member string")
|
||||
|
||||
definition(bVar, "", Other, "$file:$line:$col-$ecol: defined here as var a.Other a.Thing")
|
||||
definition(bVar, "-emulate=guru", Other, "$file:$line:$col: defined here as var $$a.Other")
|
||||
|
||||
definition(bFunc, "", Things, "$file:$line:$col-$ecol: defined here as func a.Things(val []string) []a.Thing")
|
||||
definition(bFunc, "-emulate=guru", Things, "$file:$line:$col: defined here as func $$a.Things")
|
||||
godef(bStructType, Thing)
|
||||
godef(bMember, Member)
|
||||
godef(bVar, Other)
|
||||
godef(bFunc, Things)
|
||||
*/
|
||||
|
106
internal/lsp/testdata/godef/b/e.go.golden
vendored
Normal file
106
internal/lsp/testdata/godef/b/e.go.golden
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
-- Member-definition --
|
||||
godef/a/d.go:6:2-8: defined here as field Member string
|
||||
-- Member-definition-guru --
|
||||
godef/a/d.go:6:2: defined here as field Member string
|
||||
|
||||
-- Member-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/d.go",
|
||||
"start": {
|
||||
"line": 6,
|
||||
"column": 2,
|
||||
"offset": 55
|
||||
},
|
||||
"end": {
|
||||
"line": 6,
|
||||
"column": 8,
|
||||
"offset": 61
|
||||
}
|
||||
},
|
||||
"description": "field Member string"
|
||||
}
|
||||
|
||||
-- Member-definition-json-guru --
|
||||
{
|
||||
"objpos": "godef/a/d.go:6:2",
|
||||
"desc": "field Member string"
|
||||
}
|
||||
|
||||
-- Member-hover --
|
||||
field Member string
|
||||
-- Other-definition --
|
||||
godef/a/d.go:9:5-10: defined here as var a.Other a.Thing
|
||||
-- Other-definition-guru --
|
||||
godef/a/d.go:9:5: defined here as var a.Other
|
||||
|
||||
-- Other-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/d.go",
|
||||
"start": {
|
||||
"line": 9,
|
||||
"column": 5,
|
||||
"offset": 86
|
||||
},
|
||||
"end": {
|
||||
"line": 9,
|
||||
"column": 10,
|
||||
"offset": 91
|
||||
}
|
||||
},
|
||||
"description": "var a.Other a.Thing"
|
||||
}
|
||||
|
||||
-- Other-hover --
|
||||
var a.Other a.Thing
|
||||
-- Thing-definition --
|
||||
godef/a/d.go:5:6-11: defined here as type a.Thing struct{Member string}
|
||||
-- Thing-definition-guru --
|
||||
godef/a/d.go:5:6: defined here as type a.Thing
|
||||
|
||||
-- Thing-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/d.go",
|
||||
"start": {
|
||||
"line": 5,
|
||||
"column": 6,
|
||||
"offset": 30
|
||||
},
|
||||
"end": {
|
||||
"line": 5,
|
||||
"column": 11,
|
||||
"offset": 35
|
||||
}
|
||||
},
|
||||
"description": "type a.Thing struct{Member string}"
|
||||
}
|
||||
|
||||
-- Thing-hover --
|
||||
type a.Thing struct{Member string}
|
||||
-- Things-definition --
|
||||
godef/a/d.go:11:6-12: defined here as func a.Things(val []string) []a.Thing
|
||||
-- Things-definition-guru --
|
||||
godef/a/d.go:11:6: defined here as func a.Things
|
||||
|
||||
-- Things-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/d.go",
|
||||
"start": {
|
||||
"line": 11,
|
||||
"column": 6,
|
||||
"offset": 113
|
||||
},
|
||||
"end": {
|
||||
"line": 11,
|
||||
"column": 12,
|
||||
"offset": 119
|
||||
}
|
||||
},
|
||||
"description": "func a.Things(val []string) []a.Thing"
|
||||
}
|
||||
|
||||
-- Things-hover --
|
||||
func a.Things(val []string) []a.Thing
|
@ -1,2 +1,25 @@
|
||||
-- myUnclosedIf-definition --
|
||||
godef/broken/unclosedIf.go:7:7-19: defined here as var myUnclosedIf string
|
||||
-- myUnclosedIf-definition-guru --
|
||||
godef/broken/unclosedIf.go:7:7: defined here as var myUnclosedIf
|
||||
|
||||
-- myUnclosedIf-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/broken/unclosedIf.go",
|
||||
"start": {
|
||||
"line": 7,
|
||||
"column": 7,
|
||||
"offset": 68
|
||||
},
|
||||
"end": {
|
||||
"line": 7,
|
||||
"column": 19,
|
||||
"offset": 80
|
||||
}
|
||||
},
|
||||
"description": "var myUnclosedIf string"
|
||||
}
|
||||
|
||||
-- myUnclosedIf-hover --
|
||||
var myUnclosedIf string
|
||||
|
@ -31,7 +31,7 @@ const (
|
||||
ExpectedCompletionsCount = 97
|
||||
ExpectedDiagnosticsCount = 17
|
||||
ExpectedFormatCount = 5
|
||||
ExpectedDefinitionsCount = 24
|
||||
ExpectedDefinitionsCount = 33
|
||||
ExpectedTypeDefinitionsCount = 2
|
||||
ExpectedHighlightsCount = 2
|
||||
ExpectedSymbolsCount = 1
|
||||
@ -97,9 +97,7 @@ type Definition struct {
|
||||
Name string
|
||||
Src span.Span
|
||||
IsType bool
|
||||
Flags string
|
||||
Def span.Span
|
||||
Match string
|
||||
}
|
||||
|
||||
type CompletionSnippet struct {
|
||||
|
Loading…
Reference in New Issue
Block a user