зеркало из https://github.com/golang/tools.git
internal/lsp/tests: simplify comparison of markdown at go1.18
In several places throughout the x/tools codebase, the internal/lsp/diff package is used to provide clearer test output when comparing large, multi-line strings. In some places, this is implemented via the tests.Diff helper function, but in others it is not (presumably due to import cycles). Factor out this pattern into a diff.Pretty function, and add commentary. Also remove the *testing.T argument, as diffs should never fail; opt to panic instead. Also add a test. Using this function, simplify the logic to comparing our 1.18 markdown output with 1.19 golden content, by normalizing differences between the two. This is necessary as markdown content will change as a result of moving internal/lsp to gopls/internal/lsp. For golang/go#54509 Change-Id: Ie1fea1091bbbeb49e00c4efa7e02707cafa415cc Reviewed-on: https://go-review.googlesource.com/c/tools/+/426776 TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Robert Findley <rfindley@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
Родитель
3eb8a8f04e
Коммит
4ccc73cbb5
|
@ -11,10 +11,10 @@ import (
|
|||
"golang.org/x/tools/gopls/internal/hooks"
|
||||
"golang.org/x/tools/internal/lsp/bug"
|
||||
. "golang.org/x/tools/internal/lsp/regtest"
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/command"
|
||||
"golang.org/x/tools/internal/lsp/protocol"
|
||||
"golang.org/x/tools/internal/lsp/tests"
|
||||
"golang.org/x/tools/internal/testenv"
|
||||
)
|
||||
|
||||
|
@ -187,10 +187,10 @@ require golang.org/x/hello v1.2.3
|
|||
}
|
||||
env.Await(env.DoneWithChangeWatchedFiles())
|
||||
if got := env.Editor.BufferText("a/go.mod"); got != wantGoModA {
|
||||
t.Fatalf("a/go.mod upgrade failed:\n%s", tests.Diff(t, wantGoModA, got))
|
||||
t.Fatalf("a/go.mod upgrade failed:\n%s", compare.Text(wantGoModA, got))
|
||||
}
|
||||
if got := env.Editor.BufferText("b/go.mod"); got != wantGoModB {
|
||||
t.Fatalf("b/go.mod changed unexpectedly:\n%s", tests.Diff(t, wantGoModB, got))
|
||||
t.Fatalf("b/go.mod changed unexpectedly:\n%s", compare.Text(wantGoModB, got))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -220,10 +220,10 @@ require golang.org/x/hello v1.2.3
|
|||
env.ApplyQuickFixes("a/go.mod", d.Diagnostics)
|
||||
env.Await(env.DoneWithChangeWatchedFiles())
|
||||
if got := env.Editor.BufferText("a/go.mod"); got != wantGoModA {
|
||||
t.Fatalf("a/go.mod upgrade failed:\n%s", tests.Diff(t, wantGoModA, got))
|
||||
t.Fatalf("a/go.mod upgrade failed:\n%s", compare.Text(wantGoModA, got))
|
||||
}
|
||||
if got := env.Editor.BufferText("b/go.mod"); got != wantGoModB {
|
||||
t.Fatalf("b/go.mod changed unexpectedly:\n%s", tests.Diff(t, wantGoModB, got))
|
||||
t.Fatalf("b/go.mod changed unexpectedly:\n%s", compare.Text(wantGoModB, got))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -285,7 +285,7 @@ go 1.14
|
|||
require golang.org/x/hello v1.0.0
|
||||
`
|
||||
if got != wantGoMod {
|
||||
t.Fatalf("go.mod tidy failed:\n%s", tests.Diff(t, wantGoMod, got))
|
||||
t.Fatalf("go.mod tidy failed:\n%s", compare.Text(wantGoMod, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@ import (
|
|||
|
||||
"golang.org/x/tools/internal/lsp/protocol"
|
||||
. "golang.org/x/tools/internal/lsp/regtest"
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
"golang.org/x/tools/internal/testenv"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/fake"
|
||||
"golang.org/x/tools/internal/lsp/tests"
|
||||
)
|
||||
|
||||
const internalDefinition = `
|
||||
|
@ -133,7 +133,7 @@ func main() {
|
|||
}
|
||||
want := "```go\nfunc (error).Error() string\n```"
|
||||
if content.Value != want {
|
||||
t.Fatalf("hover failed:\n%s", tests.Diff(t, want, content.Value))
|
||||
t.Fatalf("hover failed:\n%s", compare.Text(want, content.Value))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ import (
|
|||
"testing"
|
||||
|
||||
. "golang.org/x/tools/internal/lsp/regtest"
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/protocol"
|
||||
"golang.org/x/tools/internal/lsp/tests"
|
||||
)
|
||||
|
||||
// A basic test for fillstruct, now that it uses a command.
|
||||
|
@ -56,7 +56,7 @@ func Foo() {
|
|||
}
|
||||
`
|
||||
if got := env.Editor.BufferText("main.go"); got != want {
|
||||
t.Fatalf("TestFillStruct failed:\n%s", tests.Diff(t, want, got))
|
||||
t.Fatalf("TestFillStruct failed:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -9,8 +9,7 @@ import (
|
|||
"testing"
|
||||
|
||||
. "golang.org/x/tools/internal/lsp/regtest"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/tests"
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
)
|
||||
|
||||
const unformattedProgram = `
|
||||
|
@ -37,7 +36,7 @@ func TestFormatting(t *testing.T) {
|
|||
got := env.Editor.BufferText("main.go")
|
||||
want := env.ReadWorkspaceFile("main.go.golden")
|
||||
if got != want {
|
||||
t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
|
||||
t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -59,7 +58,7 @@ func f() {}
|
|||
got := env.Editor.BufferText("a.go")
|
||||
want := env.ReadWorkspaceFile("a.go.formatted")
|
||||
if got != want {
|
||||
t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
|
||||
t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -83,7 +82,7 @@ func f() { fmt.Println() }
|
|||
got := env.Editor.BufferText("a.go")
|
||||
want := env.ReadWorkspaceFile("a.go.imported")
|
||||
if got != want {
|
||||
t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
|
||||
t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -104,7 +103,7 @@ func f() {}
|
|||
got := env.Editor.BufferText("a.go")
|
||||
want := env.ReadWorkspaceFile("a.go.imported")
|
||||
if got != want {
|
||||
t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
|
||||
t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -150,7 +149,7 @@ func TestOrganizeImports(t *testing.T) {
|
|||
got := env.Editor.BufferText("main.go")
|
||||
want := env.ReadWorkspaceFile("main.go.organized")
|
||||
if got != want {
|
||||
t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
|
||||
t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -162,7 +161,7 @@ func TestFormattingOnSave(t *testing.T) {
|
|||
got := env.Editor.BufferText("main.go")
|
||||
want := env.ReadWorkspaceFile("main.go.formatted")
|
||||
if got != want {
|
||||
t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
|
||||
t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -262,7 +261,7 @@ func main() {
|
|||
got := env.Editor.BufferText("main.go")
|
||||
got = strings.ReplaceAll(got, "\r\n", "\n") // convert everything to LF for simplicity
|
||||
if tt.want != got {
|
||||
t.Errorf("unexpected content after save:\n%s", tests.Diff(t, tt.want, got))
|
||||
t.Errorf("unexpected content after save:\n%s", compare.Text(tt.want, got))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -361,7 +360,7 @@ const Bar = 42
|
|||
got := env.Editor.BufferText("foo.go")
|
||||
want := env.ReadWorkspaceFile("foo.go.formatted")
|
||||
if got != want {
|
||||
t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
|
||||
t.Errorf("unexpected formatting result:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"golang.org/x/tools/internal/lsp/command"
|
||||
"golang.org/x/tools/internal/lsp/protocol"
|
||||
. "golang.org/x/tools/internal/lsp/regtest"
|
||||
"golang.org/x/tools/internal/lsp/tests"
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
)
|
||||
|
||||
func TestAddImport(t *testing.T) {
|
||||
|
@ -51,7 +51,7 @@ func main() {
|
|||
}, nil)
|
||||
got := env.Editor.BufferText("main.go")
|
||||
if got != want {
|
||||
t.Fatalf("gopls.add_import failed\n%s", tests.Diff(t, want, got))
|
||||
t.Fatalf("gopls.add_import failed\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@ import (
|
|||
"golang.org/x/tools/gopls/internal/hooks"
|
||||
"golang.org/x/tools/internal/lsp/bug"
|
||||
. "golang.org/x/tools/internal/lsp/regtest"
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/protocol"
|
||||
"golang.org/x/tools/internal/lsp/tests"
|
||||
"golang.org/x/tools/internal/testenv"
|
||||
)
|
||||
|
||||
|
@ -101,7 +101,7 @@ func main() {
|
|||
),
|
||||
)
|
||||
if got := env.ReadWorkspaceFile("a/go.mod"); got != goModContent {
|
||||
t.Fatalf("go.mod changed on disk:\n%s", tests.Diff(t, goModContent, got))
|
||||
t.Fatalf("go.mod changed on disk:\n%s", compare.Text(goModContent, got))
|
||||
}
|
||||
// Save the buffer, which will format and organize imports.
|
||||
// Confirm that the go.mod file still does not change.
|
||||
|
@ -110,7 +110,7 @@ func main() {
|
|||
env.DiagnosticAtRegexp("a/main.go", "\"example.com/blah\""),
|
||||
)
|
||||
if got := env.ReadWorkspaceFile("a/go.mod"); got != goModContent {
|
||||
t.Fatalf("go.mod changed on disk:\n%s", tests.Diff(t, goModContent, got))
|
||||
t.Fatalf("go.mod changed on disk:\n%s", compare.Text(goModContent, got))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -154,7 +154,7 @@ func main() {
|
|||
),
|
||||
)
|
||||
if got := env.ReadWorkspaceFile("a/go.mod"); got != goModContent {
|
||||
t.Fatalf("go.mod changed on disk:\n%s", tests.Diff(t, goModContent, got))
|
||||
t.Fatalf("go.mod changed on disk:\n%s", compare.Text(goModContent, got))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -206,7 +206,7 @@ require example.com v1.2.3
|
|||
}
|
||||
env.ApplyQuickFixes("a/main.go", []protocol.Diagnostic{goGetDiag})
|
||||
if got := env.ReadWorkspaceFile("a/go.mod"); got != want {
|
||||
t.Fatalf("unexpected go.mod content:\n%s", tests.Diff(t, want, got))
|
||||
t.Fatalf("unexpected go.mod content:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -256,7 +256,7 @@ require random.org v1.2.3
|
|||
}
|
||||
env.ApplyQuickFixes("a/main.go", []protocol.Diagnostic{randomDiag})
|
||||
if got := env.ReadWorkspaceFile("a/go.mod"); got != want {
|
||||
t.Fatalf("unexpected go.mod content:\n%s", tests.Diff(t, want, got))
|
||||
t.Fatalf("unexpected go.mod content:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -312,7 +312,7 @@ require random.org v1.2.3
|
|||
}
|
||||
env.ApplyQuickFixes("a/main.go", []protocol.Diagnostic{randomDiag})
|
||||
if got := env.ReadWorkspaceFile("a/go.mod"); got != want {
|
||||
t.Fatalf("unexpected go.mod content:\n%s", tests.Diff(t, want, got))
|
||||
t.Fatalf("unexpected go.mod content:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ require example.com v1.2.3
|
|||
)
|
||||
env.ApplyQuickFixes("a/go.mod", d.Diagnostics)
|
||||
if got := env.Editor.BufferText("a/go.mod"); got != want {
|
||||
t.Fatalf("unexpected go.mod content:\n%s", tests.Diff(t, want, got))
|
||||
t.Fatalf("unexpected go.mod content:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -404,7 +404,7 @@ go 1.14
|
|||
)
|
||||
env.ApplyQuickFixes("a/go.mod", d.Diagnostics)
|
||||
if got := env.Editor.BufferText("a/go.mod"); got != want {
|
||||
t.Fatalf("unexpected go.mod content:\n%s", tests.Diff(t, want, got))
|
||||
t.Fatalf("unexpected go.mod content:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -476,7 +476,7 @@ require (
|
|||
)
|
||||
`
|
||||
if got := env.ReadWorkspaceFile("a/go.mod"); got != want {
|
||||
t.Fatalf("TestNewDepWithUnusedDep failed:\n%s", tests.Diff(t, want, got))
|
||||
t.Fatalf("TestNewDepWithUnusedDep failed:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -585,7 +585,7 @@ require (
|
|||
env.SaveBuffer("a/go.mod")
|
||||
env.Await(EmptyDiagnostics("a/main.go"))
|
||||
if got := env.Editor.BufferText("a/go.mod"); got != want {
|
||||
t.Fatalf("suggested fixes failed:\n%s", tests.Diff(t, want, got))
|
||||
t.Fatalf("suggested fixes failed:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -773,7 +773,7 @@ func main() {
|
|||
)
|
||||
got := env.ReadWorkspaceFile("go.mod")
|
||||
if got != original {
|
||||
t.Fatalf("go.mod file modified:\n%s", tests.Diff(t, original, got))
|
||||
t.Fatalf("go.mod file modified:\n%s", compare.Text(original, got))
|
||||
}
|
||||
env.RunGoCommand("get", "example.com/blah@v1.2.3")
|
||||
env.RunGoCommand("mod", "tidy")
|
||||
|
@ -1026,7 +1026,7 @@ go 1.12
|
|||
`
|
||||
env.ApplyQuickFixes("go.mod", d.Diagnostics)
|
||||
if got := env.Editor.BufferText("go.mod"); got != want {
|
||||
t.Fatalf("unexpected content in go.mod:\n%s", tests.Diff(t, want, got))
|
||||
t.Fatalf("unexpected content in go.mod:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -1079,7 +1079,7 @@ require random.com v1.2.3
|
|||
}
|
||||
env.ApplyQuickFixes("go.mod", diagnostics)
|
||||
if got := env.Editor.BufferText("go.mod"); got != want {
|
||||
t.Fatalf("unexpected content in go.mod:\n%s", tests.Diff(t, want, got))
|
||||
t.Fatalf("unexpected content in go.mod:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -1125,7 +1125,7 @@ func main() {
|
|||
example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
|
||||
`
|
||||
if got := env.ReadWorkspaceFile("go.sum"); got != want {
|
||||
t.Fatalf("unexpected go.sum contents:\n%s", tests.Diff(t, want, got))
|
||||
t.Fatalf("unexpected go.sum contents:\n%s", compare.Text(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/tests"
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
"golang.org/x/tools/internal/span"
|
||||
)
|
||||
|
||||
|
@ -32,6 +33,6 @@ func (r *runner) SuggestedFix(t *testing.T, spn span.Span, suggestedFixes []test
|
|||
return []byte(got), nil
|
||||
}))
|
||||
if want != got {
|
||||
t.Errorf("suggested fixes failed for %s:\n%s", filename, tests.Diff(t, want, got))
|
||||
t.Errorf("suggested fixes failed for %s:\n%s", filename, compare.Text(want, got))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
"golang.org/x/tools/internal/lsp/source"
|
||||
"golang.org/x/tools/internal/lsp/tests"
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
"golang.org/x/tools/internal/span"
|
||||
)
|
||||
|
||||
|
@ -48,6 +49,6 @@ func (r *runner) runWorkspaceSymbols(t *testing.T, uri span.URI, matcher, query
|
|||
}))
|
||||
|
||||
if expect != got {
|
||||
t.Errorf("workspace_symbol failed for %s:\n%s", query, tests.Diff(t, expect, got))
|
||||
t.Errorf("workspace_symbol failed for %s:\n%s", query, compare.Text(expect, got))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,10 +75,10 @@ const (
|
|||
|
||||
// ToUnified takes a file contents and a sequence of edits, and calculates
|
||||
// a unified diff that represents those edits.
|
||||
func ToUnified(from, to string, content string, edits []TextEdit) Unified {
|
||||
func ToUnified(fromName, toName string, content string, edits []TextEdit) Unified {
|
||||
u := Unified{
|
||||
From: from,
|
||||
To: to,
|
||||
From: fromName,
|
||||
To: toName,
|
||||
}
|
||||
if len(edits) == 0 {
|
||||
return u
|
||||
|
@ -160,14 +160,25 @@ func addEqualLines(h *Hunk, lines []string, start, end int) int {
|
|||
return delta
|
||||
}
|
||||
|
||||
// Format converts a unified diff to the standard textual form for that diff.
|
||||
// The output of this function can be passed to tools like patch.
|
||||
// Format write a textual representation of u to f (see the String method).
|
||||
//
|
||||
// TODO(rfindley): investigate (and possibly remove) this method. It's not
|
||||
// clear why Unified implements fmt.Formatter, since the formatting rune is not
|
||||
// used. Probably it is sufficient to only implement Stringer, but this method
|
||||
// was left here defensively.
|
||||
func (u Unified) Format(f fmt.State, r rune) {
|
||||
fmt.Fprintf(f, "%s", u.String())
|
||||
}
|
||||
|
||||
// String converts a unified diff to the standard textual form for that diff.
|
||||
// The output of this function can be passed to tools like patch.
|
||||
func (u Unified) String() string {
|
||||
if len(u.Hunks) == 0 {
|
||||
return
|
||||
return ""
|
||||
}
|
||||
fmt.Fprintf(f, "--- %s\n", u.From)
|
||||
fmt.Fprintf(f, "+++ %s\n", u.To)
|
||||
b := new(strings.Builder)
|
||||
fmt.Fprintf(b, "--- %s\n", u.From)
|
||||
fmt.Fprintf(b, "+++ %s\n", u.To)
|
||||
for _, hunk := range u.Hunks {
|
||||
fromCount, toCount := 0, 0
|
||||
for _, l := range hunk.Lines {
|
||||
|
@ -181,30 +192,31 @@ func (u Unified) Format(f fmt.State, r rune) {
|
|||
toCount++
|
||||
}
|
||||
}
|
||||
fmt.Fprint(f, "@@")
|
||||
fmt.Fprint(b, "@@")
|
||||
if fromCount > 1 {
|
||||
fmt.Fprintf(f, " -%d,%d", hunk.FromLine, fromCount)
|
||||
fmt.Fprintf(b, " -%d,%d", hunk.FromLine, fromCount)
|
||||
} else {
|
||||
fmt.Fprintf(f, " -%d", hunk.FromLine)
|
||||
fmt.Fprintf(b, " -%d", hunk.FromLine)
|
||||
}
|
||||
if toCount > 1 {
|
||||
fmt.Fprintf(f, " +%d,%d", hunk.ToLine, toCount)
|
||||
fmt.Fprintf(b, " +%d,%d", hunk.ToLine, toCount)
|
||||
} else {
|
||||
fmt.Fprintf(f, " +%d", hunk.ToLine)
|
||||
fmt.Fprintf(b, " +%d", hunk.ToLine)
|
||||
}
|
||||
fmt.Fprint(f, " @@\n")
|
||||
fmt.Fprint(b, " @@\n")
|
||||
for _, l := range hunk.Lines {
|
||||
switch l.Kind {
|
||||
case Delete:
|
||||
fmt.Fprintf(f, "-%s", l.Content)
|
||||
fmt.Fprintf(b, "-%s", l.Content)
|
||||
case Insert:
|
||||
fmt.Fprintf(f, "+%s", l.Content)
|
||||
fmt.Fprintf(b, "+%s", l.Content)
|
||||
default:
|
||||
fmt.Fprintf(f, " %s", l.Content)
|
||||
fmt.Fprintf(b, " %s", l.Content)
|
||||
}
|
||||
if !strings.HasSuffix(l.Content, "\n") {
|
||||
fmt.Fprintf(f, "\n\\ No newline at end of file\n")
|
||||
fmt.Fprintf(b, "\n\\ No newline at end of file\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@ import (
|
|||
"golang.org/x/tools/internal/lsp/cache"
|
||||
"golang.org/x/tools/internal/lsp/command"
|
||||
"golang.org/x/tools/internal/lsp/diff"
|
||||
"golang.org/x/tools/internal/lsp/diff/myers"
|
||||
"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/compare"
|
||||
"golang.org/x/tools/internal/span"
|
||||
"golang.org/x/tools/internal/testenv"
|
||||
)
|
||||
|
@ -469,12 +469,9 @@ func (r *runner) Import(t *testing.T, spn span.Span) {
|
|||
want := string(r.data.Golden("goimports", filename, func() ([]byte, error) {
|
||||
return []byte(got), nil
|
||||
}))
|
||||
if want != got {
|
||||
d, err := myers.ComputeEdits(uri, want, got)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Errorf("import failed for %s: %s", filename, diff.ToUnified("want", "got", want, d))
|
||||
|
||||
if d := compare.Text(want, got); d != "" {
|
||||
t.Errorf("import failed for %s:\n%s", filename, d)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,7 +569,7 @@ func (r *runner) SuggestedFix(t *testing.T, spn span.Span, actionKinds []tests.S
|
|||
return []byte(got), nil
|
||||
}))
|
||||
if want != got {
|
||||
t.Errorf("suggested fixes failed for %s:\n%s", u.Filename(), tests.Diff(t, want, got))
|
||||
t.Errorf("suggested fixes failed for %s:\n%s", u.Filename(), compare.Text(want, got))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -624,7 +621,7 @@ func (r *runner) FunctionExtraction(t *testing.T, start span.Span, end span.Span
|
|||
return []byte(got), nil
|
||||
}))
|
||||
if want != got {
|
||||
t.Errorf("function extraction failed for %s:\n%s", u.Filename(), tests.Diff(t, want, got))
|
||||
t.Errorf("function extraction failed for %s:\n%s", u.Filename(), compare.Text(want, got))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -676,7 +673,7 @@ func (r *runner) MethodExtraction(t *testing.T, start span.Span, end span.Span)
|
|||
return []byte(got), nil
|
||||
}))
|
||||
if want != got {
|
||||
t.Errorf("method extraction failed for %s:\n%s", u.Filename(), tests.Diff(t, want, got))
|
||||
t.Errorf("method extraction failed for %s:\n%s", u.Filename(), compare.Text(want, got))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1041,7 +1038,7 @@ func (r *runner) Rename(t *testing.T, spn span.Span, newText string) {
|
|||
return []byte(got), nil
|
||||
}))
|
||||
if want != got {
|
||||
t.Errorf("rename failed for %s:\n%s", newText, tests.Diff(t, want, got))
|
||||
t.Errorf("rename failed for %s:\n%s", newText, compare.Text(want, got))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1186,7 +1183,7 @@ func (r *runner) callWorkspaceSymbols(t *testing.T, uri span.URI, query string,
|
|||
want := string(r.data.Golden(fmt.Sprintf("workspace_symbol-%s-%s", strings.ToLower(string(matcher)), query), uri.Filename(), func() ([]byte, error) {
|
||||
return []byte(got), nil
|
||||
}))
|
||||
if diff := tests.Diff(t, want, got); diff != "" {
|
||||
if diff := compare.Text(want, got); diff != "" {
|
||||
t.Error(diff)
|
||||
}
|
||||
}
|
||||
|
@ -1299,7 +1296,7 @@ func (r *runner) AddImport(t *testing.T, uri span.URI, expectedImport string) {
|
|||
if want == nil {
|
||||
t.Fatalf("golden file %q not found", uri.Filename())
|
||||
}
|
||||
if diff := tests.Diff(t, got, string(want)); diff != "" {
|
||||
if diff := compare.Text(got, string(want)); diff != "" {
|
||||
t.Errorf("%s mismatch\n%s", command.AddImport, diff)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,10 @@
|
|||
package source
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/diff"
|
||||
"golang.org/x/tools/internal/lsp/diff/myers"
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
)
|
||||
|
||||
func TestImportPrefix(t *testing.T) {
|
||||
|
@ -39,8 +37,8 @@ func TestImportPrefix(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("%d: failed for %q:\n%s", i, tt.input, diffStr(t, tt.want, got))
|
||||
if d := compare.Text(tt.want, got); d != "" {
|
||||
t.Errorf("%d: failed for %q:\n%s", i, tt.input, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,22 +68,8 @@ Hi description
|
|||
t.Fatal(err)
|
||||
}
|
||||
want := strings.ReplaceAll(tt.want, "\n", "\r\n")
|
||||
if got != want {
|
||||
t.Errorf("%d: failed for %q:\n%s", i, tt.input, diffStr(t, want, got))
|
||||
if d := compare.Text(want, got); d != "" {
|
||||
t.Errorf("%d: failed for %q:\n%s", i, tt.input, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func diffStr(t *testing.T, want, got string) string {
|
||||
if want == got {
|
||||
return ""
|
||||
}
|
||||
// Add newlines to avoid newline messages in diff.
|
||||
want += "\n"
|
||||
got += "\n"
|
||||
d, err := myers.ComputeEdits("", want, got)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return fmt.Sprintf("%q", diff.ToUnified("want", "got", want, d))
|
||||
}
|
||||
|
|
|
@ -18,12 +18,12 @@ import (
|
|||
"golang.org/x/tools/internal/lsp/bug"
|
||||
"golang.org/x/tools/internal/lsp/cache"
|
||||
"golang.org/x/tools/internal/lsp/diff"
|
||||
"golang.org/x/tools/internal/lsp/diff/myers"
|
||||
"golang.org/x/tools/internal/lsp/fuzzy"
|
||||
"golang.org/x/tools/internal/lsp/protocol"
|
||||
"golang.org/x/tools/internal/lsp/source"
|
||||
"golang.org/x/tools/internal/lsp/source/completion"
|
||||
"golang.org/x/tools/internal/lsp/tests"
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
"golang.org/x/tools/internal/span"
|
||||
"golang.org/x/tools/internal/testenv"
|
||||
)
|
||||
|
@ -370,7 +370,7 @@ func (r *runner) foldingRanges(t *testing.T, prefix string, uri span.URI, data s
|
|||
return []byte(got), nil
|
||||
}))
|
||||
|
||||
if diff := tests.Diff(t, want, got); diff != "" {
|
||||
if diff := compare.Text(want, got); diff != "" {
|
||||
t.Errorf("%s: foldingRanges failed for %s, diff:\n%v", tag, uri.Filename(), diff)
|
||||
}
|
||||
}
|
||||
|
@ -397,7 +397,7 @@ func (r *runner) foldingRanges(t *testing.T, prefix string, uri span.URI, data s
|
|||
return []byte(got), nil
|
||||
}))
|
||||
|
||||
if diff := tests.Diff(t, want, got); diff != "" {
|
||||
if diff := compare.Text(want, got); diff != "" {
|
||||
t.Errorf("%s: failed for %s, diff:\n%v", tag, uri.Filename(), diff)
|
||||
}
|
||||
}
|
||||
|
@ -526,12 +526,8 @@ func (r *runner) Import(t *testing.T, spn span.Span) {
|
|||
want := string(r.data.Golden("goimports", spn.URI().Filename(), func() ([]byte, error) {
|
||||
return []byte(got), nil
|
||||
}))
|
||||
if want != got {
|
||||
d, err := myers.ComputeEdits(spn.URI(), want, got)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Errorf("import failed for %s: %s", spn.URI().Filename(), diff.ToUnified("want", "got", want, d))
|
||||
if d := compare.Text(got, want); d != "" {
|
||||
t.Errorf("import failed for %s:\n%s", spn.URI().Filename(), d)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -920,8 +916,8 @@ func (r *runner) callWorkspaceSymbols(t *testing.T, uri span.URI, query string,
|
|||
want := string(r.data.Golden(fmt.Sprintf("workspace_symbol-%s-%s", strings.ToLower(string(matcher)), query), uri.Filename(), func() ([]byte, error) {
|
||||
return []byte(got), nil
|
||||
}))
|
||||
if diff := tests.Diff(t, want, got); diff != "" {
|
||||
t.Error(diff)
|
||||
if d := compare.Text(want, got); d != "" {
|
||||
t.Error(d)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package compare
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/diff"
|
||||
)
|
||||
|
||||
// Text returns a formatted unified diff of the edits to go from want to
|
||||
// got, returning "" if and only if want == got.
|
||||
//
|
||||
// This function is intended for use in testing, and panics if any error occurs
|
||||
// while computing the diff. It is not sufficiently tested for production use.
|
||||
func Text(want, got string) string {
|
||||
if want == got {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Add newlines to avoid verbose newline messages ("No newline at end of file").
|
||||
want += "\n"
|
||||
got += "\n"
|
||||
|
||||
d, err := diff.NComputeEdits("", want, got)
|
||||
|
||||
// Panic on errors.
|
||||
//
|
||||
// TODO(rfindley): refactor so that this function doesn't need to panic.
|
||||
// Computing diffs should never fail.
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("computing edits failed: %v", err))
|
||||
}
|
||||
|
||||
diff := diff.ToUnified("want", "got", want, d).String()
|
||||
|
||||
// Defensively assert that we get an actual diff, so that we guarantee the
|
||||
// invariant that we return "" if and only if want == got.
|
||||
//
|
||||
// This is probably unnecessary, but convenient.
|
||||
if diff == "" {
|
||||
panic("empty diff for non-identical input")
|
||||
}
|
||||
|
||||
return diff
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package compare_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
)
|
||||
|
||||
func TestText(t *testing.T) {
|
||||
tests := []struct {
|
||||
got, want, wantDiff string
|
||||
}{
|
||||
{"", "", ""},
|
||||
{"equal", "equal", ""},
|
||||
{"a", "b", "--- want\n+++ got\n@@ -1 +1 @@\n-b\n+a\n"},
|
||||
{"a\nd\nc\n", "a\nb\nc\n", "--- want\n+++ got\n@@ -1,4 +1,4 @@\n a\n-b\n+d\n c\n \n"},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
if gotDiff := compare.Text(test.want, test.got); gotDiff != test.wantDiff {
|
||||
t.Errorf("compare.Text(%q, %q) =\n%q, want\n%q", test.want, test.got, gotDiff, test.wantDiff)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.19
|
||||
// +build !go1.19
|
||||
|
||||
package tests
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
)
|
||||
|
||||
// The markdown in the golden files matches the converter in comment.go,
|
||||
// but for go1.19 and later the conversion is done using go/doc/comment.
|
||||
// Compared to the newer version, the older version
|
||||
// has extra escapes, and treats code blocks slightly differently.
|
||||
func CheckSameMarkdown(t *testing.T, got, want string) {
|
||||
t.Helper()
|
||||
|
||||
got = normalizeMarkdown(got)
|
||||
want = normalizeMarkdown(want)
|
||||
|
||||
if diff := compare.Text(want, got); diff != "" {
|
||||
t.Errorf("normalized markdown differs:\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
// normalizeMarkdown normalizes whitespace and escaping of the input string, to
|
||||
// eliminate differences between the Go 1.18 and Go 1.19 generated markdown for
|
||||
// doc comments. Note that it does not normalize to either the 1.18 or 1.19
|
||||
// formatting: it simplifies both so that they may be compared.
|
||||
//
|
||||
// This function may need to be adjusted as we encounter more differences in
|
||||
// the generated text.
|
||||
func normalizeMarkdown(input string) string {
|
||||
input = strings.TrimSpace(input)
|
||||
|
||||
// For simplicity, eliminate blank lines.
|
||||
input = regexp.MustCompile("\n+").ReplaceAllString(input, "\n")
|
||||
|
||||
// Replace common escaped characters with their unescaped version.
|
||||
//
|
||||
// This list may not be exhaustive: it was just sufficient to make tests
|
||||
// pass.
|
||||
input = strings.NewReplacer(
|
||||
`\\`, ``,
|
||||
`\@`, `@`,
|
||||
`\(`, `(`,
|
||||
`\)`, `)`,
|
||||
`\"`, `"`,
|
||||
`\.`, `.`,
|
||||
`\-`, `-`,
|
||||
`\'`, `'`,
|
||||
`\n\n\n`, `\n\n`, // Note that these are *escaped* newlines.
|
||||
).Replace(input)
|
||||
|
||||
return input
|
||||
}
|
|
@ -9,6 +9,8 @@ package tests
|
|||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
)
|
||||
|
||||
// The markdown in the golden files matches the converter in comment.go,
|
||||
|
@ -17,7 +19,8 @@ import (
|
|||
// has extra escapes, and treats code blocks slightly differently.
|
||||
func CheckSameMarkdown(t *testing.T, got, want string) {
|
||||
t.Helper()
|
||||
if got != want {
|
||||
t.Errorf("got %q, want %q", got, want)
|
||||
|
||||
if diff := compare.Text(want, got); diff != "" {
|
||||
t.Errorf("normalized markdown differs:\n%s", diff)
|
||||
}
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.19
|
||||
// +build !go1.19
|
||||
|
||||
package tests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// The markdown in the golden files matches the converter in comment.go,
|
||||
// but for go1.19 and later the conversion is done using go/doc/comment.
|
||||
// Compared to the newer version, the older version
|
||||
// has extra escapes, and treats code blocks slightly differently.
|
||||
func CheckSameMarkdown(t *testing.T, got, want string) {
|
||||
t.Helper()
|
||||
for _, dd := range markDiffs {
|
||||
if got == dd.v18 && want == dd.v19 {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Errorf("got %q want %q", got, want)
|
||||
}
|
||||
|
||||
type markDiff struct {
|
||||
v18, v19 string
|
||||
}
|
||||
|
||||
var markDiffs = []markDiff{{v19: "Package a is a package for testing go to definition.\n", v18: "Package a is a package for testing go to definition\\."},
|
||||
{v19: "```go\nconst X untyped int = 0\n```\n\n@mark(bX, \"X\"),godef(\"X\", bX)\n\n\n[`b.X` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#X)", v18: "```go\nconst X untyped int = 0\n```\n\n\\@mark\\(bX, \\\"X\\\"\\),godef\\(\\\"X\\\", bX\\)\n\n[`b.X` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#X)"},
|
||||
{v19: "```go\nconst dur time.Duration = 910350000000 // 15m10.35s\n```\n\ndur is a constant of type time.Duration.\n", v18: "```go\nconst dur time.Duration = 910350000000 // 15m10.35s\n```\n\ndur is a constant of type time\\.Duration\\."},
|
||||
{v19: "```go\nconst g untyped int = 1\n```\n\nWhen I hover on g, I should see this comment.\n", v18: "```go\nconst g untyped int = 1\n```\n\nWhen I hover on g, I should see this comment\\."},
|
||||
{v19: "```go\nconst h untyped int = 2\n```\n\nConstant block.\n", v18: "```go\nconst h untyped int = 2\n```\n\nConstant block\\."},
|
||||
{v19: "```go\nfield F1 int\n```\n\n@mark(S1F1, \"F1\")\n\n\n[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.F1)", v18: "```go\nfield F1 int\n```\n\n\\@mark\\(S1F1, \\\"F1\\\"\\)\n\n[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.F1)"},
|
||||
{v19: "```go\nfield F1 string\n```\n\n@mark(S2F1, \"F1\")\n\n\n[`(b.S2).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2.F1)", v18: "```go\nfield F1 string\n```\n\n\\@mark\\(S2F1, \\\"F1\\\"\\)\n\n[`(b.S2).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2.F1)"},
|
||||
{v19: "```go\nfield F2 int\n```\n\n@mark(S2F2, \"F2\")\n\n\n[`(b.S2).F2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2.F2)", v18: "```go\nfield F2 int\n```\n\n\\@mark\\(S2F2, \\\"F2\\\"\\)\n\n[`(b.S2).F2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2.F2)"},
|
||||
{v19: "```go\nfield Field int\n```\n\n@mark(AField, \"Field\")\n\n\n[`(a.S).Field` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#S.Field)", v18: "```go\nfield Field int\n```\n\n\\@mark\\(AField, \\\"Field\\\"\\)\n\n[`(a.S).Field` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#S.Field)"},
|
||||
{v19: "```go\nfield Field2 int\n```\n\n@mark(AField2, \"Field2\")\n\n\n[`(a.R).Field2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#R.Field2)", v18: "```go\nfield Field2 int\n```\n\n\\@mark\\(AField2, \\\"Field2\\\"\\)\n\n[`(a.R).Field2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#R.Field2)"},
|
||||
{v19: "```go\nfield Member string\n```\n\n@Member\n\n\n[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing.Member)", v18: "```go\nfield Member string\n```\n\n\\@Member\n\n[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing.Member)"},
|
||||
{v19: "```go\nfield Q int\n```\n\n@mark(ValueQfield, \"Q\"),hoverdef(\"Q\", ValueQfield)\n\n\n[`(hover.Value).Q` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/hover_generics#Value.Q)", v18: "```go\nfield Q int\n```\n\n\\@mark\\(ValueQfield, \\\"Q\\\"\\),hoverdef\\(\\\"Q\\\", ValueQfield\\)\n\n[`(hover.Value).Q` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/hover_generics#Value.Q)"},
|
||||
{v19: "```go\nfield Q int\n```\n\n@mark(valueQfield, \"Q\"),hoverdef(\"Q\", valueQfield)\n", v18: "```go\nfield Q int\n```\n\n\\@mark\\(valueQfield, \\\"Q\\\"\\),hoverdef\\(\\\"Q\\\", valueQfield\\)"},
|
||||
{v19: "```go\nfield S2 S2\n```\n\n@godef(\"S2\", S2),mark(S1S2, \"S2\")\n\n\n[`(b.S1).S2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.S2)", v18: "```go\nfield S2 S2\n```\n\n\\@godef\\(\\\"S2\\\", S2\\),mark\\(S1S2, \\\"S2\\\"\\)\n\n[`(b.S1).S2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.S2)"},
|
||||
{v19: "```go\nfield a int\n```\n\na field\n", v18: "```go\nfield a int\n```\n\na field"},
|
||||
{v19: "```go\nfield b struct{c int}\n```\n\nb nested struct\n", v18: "```go\nfield b struct{c int}\n```\n\nb nested struct"},
|
||||
{v19: "```go\nfield c int\n```\n\nc field of nested struct\n", v18: "```go\nfield c int\n```\n\nc field of nested struct"},
|
||||
{v19: "```go\nfield d int\n```\n\nd field\n", v18: "```go\nfield d int\n```\n\nd field"},
|
||||
{v19: "```go\nfield desc string\n```\n\ntest description\n", v18: "```go\nfield desc string\n```\n\ntest description"},
|
||||
{v19: "```go\nfield e struct{f int}\n```\n\ne nested struct\n", v18: "```go\nfield e struct{f int}\n```\n\ne nested struct"},
|
||||
{v19: "```go\nfield f int\n```\n\nf field of nested struct\n", v18: "```go\nfield f int\n```\n\nf field of nested struct"},
|
||||
{v19: "```go\nfield h int\n```\n\nh field\n", v18: "```go\nfield h int\n```\n\nh field"},
|
||||
{v19: "```go\nfield i struct{j int}\n```\n\ni nested struct\n", v18: "```go\nfield i struct{j int}\n```\n\ni nested struct"},
|
||||
{v19: "```go\nfield in map[string][]struct{key string; value interface{}}\n```\n\ntest input\n", v18: "```go\nfield in map[string][]struct{key string; value interface{}}\n```\n\ntest input"},
|
||||
{v19: "```go\nfield j int\n```\n\nj field of nested struct\n", v18: "```go\nfield j int\n```\n\nj field of nested struct"},
|
||||
{v19: "```go\nfield key string\n```\n\ntest key\n", v18: "```go\nfield key string\n```\n\ntest key"},
|
||||
{v19: "```go\nfield m map[string]float64\n```\n\nnested map\n", v18: "```go\nfield m map[string]float64\n```\n\nnested map"},
|
||||
{v19: "```go\nfield number int64\n```\n\nnested number\n", v18: "```go\nfield number int64\n```\n\nnested number"},
|
||||
{v19: "```go\nfield str string\n```\n\nnested string\n", v18: "```go\nfield str string\n```\n\nnested string"},
|
||||
{v19: "```go\nfield value int\n```\n\nexpected test value\n", v18: "```go\nfield value int\n```\n\nexpected test value"},
|
||||
{v19: "```go\nfield value interface{}\n```\n\ntest value\n", v18: "```go\nfield value interface{}\n```\n\ntest value"},
|
||||
{v19: "```go\nfield x []string\n```\n\nX key field\n", v18: "```go\nfield x []string\n```\n\nX key field"},
|
||||
{v19: "```go\nfield x int\n```\n\n@mark(PosX, \"x\"),mark(PosY, \"y\")\n", v18: "```go\nfield x int\n```\n\n\\@mark\\(PosX, \\\"x\\\"\\),mark\\(PosY, \\\"y\\\"\\)"},
|
||||
{v19: "```go\nfield x int\n```\n\nX coord\n", v18: "```go\nfield x int\n```\n\nX coord"},
|
||||
{v19: "```go\nfield x string\n```\n\nX value field\n", v18: "```go\nfield x string\n```\n\nX value field"},
|
||||
{v19: "```go\nfield y int\n```\n\nY coord\n", v18: "```go\nfield y int\n```\n\nY coord"},
|
||||
{v19: "```go\nfunc (*sync.Mutex).Lock()\n```\n\nLock locks m.\n\n\n[`(sync.Mutex).Lock` on pkg.go.dev](https://pkg.go.dev/sync#Mutex.Lock)", v18: "```go\nfunc (*sync.Mutex).Lock()\n```\n\nLock locks m\\.\n\n[`(sync.Mutex).Lock` on pkg.go.dev](https://pkg.go.dev/sync#Mutex.Lock)"},
|
||||
{v19: "```go\nfunc (*types.object).Name() string\n```\n\nName returns the object's (package-local, unqualified) name.\n\n\n[`(types.TypeName).Name` on pkg.go.dev](https://pkg.go.dev/go/types#TypeName.Name)", v18: "```go\nfunc (*types.object).Name() string\n```\n\nName returns the object\\'s \\(package\\-local, unqualified\\) name\\.\n\n[`(types.TypeName).Name` on pkg.go.dev](https://pkg.go.dev/go/types#TypeName.Name)"},
|
||||
{v19: "```go\nfunc (a.H).Goodbye()\n```\n\n@mark(AGoodbye, \"Goodbye\")\n\n\n[`(a.H).Goodbye` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#H.Goodbye)", v18: "```go\nfunc (a.H).Goodbye()\n```\n\n\\@mark\\(AGoodbye, \\\"Goodbye\\\"\\)\n\n[`(a.H).Goodbye` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#H.Goodbye)"},
|
||||
{v19: "```go\nfunc (a.I).B()\n```\n\n@mark(AB, \"B\")\n\n\n[`(a.I).B` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#I.B)", v18: "```go\nfunc (a.I).B()\n```\n\n\\@mark\\(AB, \\\"B\\\"\\)\n\n[`(a.I).B` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#I.B)"},
|
||||
{v19: "```go\nfunc (a.J).Hello()\n```\n\n@mark(AHello, \"Hello\")\n\n\n[`(a.J).Hello` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#J.Hello)", v18: "```go\nfunc (a.J).Hello()\n```\n\n\\@mark\\(AHello, \\\"Hello\\\"\\)\n\n[`(a.J).Hello` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#J.Hello)"},
|
||||
{v19: "```go\nfunc (interface).open() error\n```\n\nopen method comment\n", v18: "```go\nfunc (interface).open() error\n```\n\nopen method comment"},
|
||||
{v19: "```go\nfunc make(t Type, size ...int) Type\n```\n\nThe make built-in function allocates and initializes an object of type slice, map, or chan (only).\n\n\n[`make` on pkg.go.dev](https://pkg.go.dev/builtin#make)", v18: "```go\nfunc make(t Type, size ...int) Type\n```\n\nThe make built\\-in function allocates and initializes an object of type slice, map, or chan \\(only\\)\\.\n\n[`make` on pkg.go.dev](https://pkg.go.dev/builtin#make)"},
|
||||
{v19: "```go\ntype A string\n```\n\n@mark(AString, \"A\")\n\n\n[`a.A` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#A)", v18: "```go\ntype A string\n```\n\n\\@mark\\(AString, \\\"A\\\"\\)\n\n[`a.A` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#A)"},
|
||||
{v19: "```go\ntype a struct {\n\tx string\n}\n```\n\n1st type declaration block\n", v18: "```go\ntype a struct {\n\tx string\n}\n```\n\n1st type declaration block"},
|
||||
{v19: "```go\ntype aAlias = a.A\n```\n\n@mark(aAlias, \"aAlias\")\n", v18: "```go\ntype aAlias = a.A\n```\n\n\\@mark\\(aAlias, \\\"aAlias\\\"\\)"},
|
||||
{v19: "```go\ntype b struct{}\n```\n\nb has a comment\n", v18: "```go\ntype b struct{}\n```\n\nb has a comment"},
|
||||
{v19: "```go\ntype c struct {\n\tf string\n}\n```\n\nc is a struct\n", v18: "```go\ntype c struct {\n\tf string\n}\n```\n\nc is a struct"},
|
||||
{v19: "```go\ntype d string\n```\n\n3rd type declaration block\n", v18: "```go\ntype d string\n```\n\n3rd type declaration block"},
|
||||
{v19: "```go\ntype e struct {\n\tf float64\n}\n```\n\ne has a comment\n", v18: "```go\ntype e struct {\n\tf float64\n}\n```\n\ne has a comment"},
|
||||
{v19: "```go\ntype string string\n```\n\nstring is the set of all strings of 8-bit bytes, conventionally but not necessarily representing UTF-8-encoded text.\n\n\n[`string` on pkg.go.dev](https://pkg.go.dev/builtin#string)", v18: "```go\ntype string string\n```\n\nstring is the set of all strings of 8\\-bit bytes, conventionally but not necessarily representing UTF\\-8\\-encoded text\\.\n\n[`string` on pkg.go.dev](https://pkg.go.dev/builtin#string)"},
|
||||
{v19: "```go\nvar Other Thing\n```\n\n@Other\n\n\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)", v18: "```go\nvar Other Thing\n```\n\n\\@Other\n\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)"},
|
||||
{v19: "```go\nvar _ A\n```\n\nvariable of type a.A\n", v18: "```go\nvar _ A\n```\n\nvariable of type a\\.A"},
|
||||
{v19: "```go\nvar a.Other a.Thing\n```\n\n@Other\n\n\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)", v18: "```go\nvar a.Other a.Thing\n```\n\n\\@Other\n\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)"},
|
||||
{v19: "```go\nvar err error\n```\n\n@err\n", v18: "```go\nvar err error\n```\n\n\\@err"},
|
||||
{v19: "```go\nvar myUnclosedIf string\n```\n\n@myUnclosedIf\n", v18: "```go\nvar myUnclosedIf string\n```\n\n\\@myUnclosedIf"},
|
||||
{v19: "```go\nvar x string\n```\n\nx is a variable.\n", v18: "```go\nvar x string\n```\n\nx is a variable\\."},
|
||||
{v19: "```go\nvar z string\n```\n\nz is a variable too.\n", v18: "```go\nvar z string\n```\n\nz is a variable too\\."},
|
||||
{v19: "godef/a/a.go:26:6-7: defined here as ```go\ntype A string\n```\n\n@mark(AString, \"A\")\n\n\n[`a.A` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#A)", v18: "godef/a/a.go:26:6-7: defined here as ```go\ntype A string\n```\n\n\\@mark\\(AString, \\\"A\\\"\\)\n\n[`a.A` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#A)"},
|
||||
{v19: "godef/a/a.go:33:6-9: defined here as ```go\nvar err error\n```\n\n@err", v18: "godef/a/a.go:33:6-9: defined here as ```go\nvar err error\n```\n\n\\@err"},
|
||||
{v19: "godef/a/d.go:6:2-8: defined here as ```go\nfield Member string\n```\n\n@Member\n\n\n[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing.Member)", v18: "godef/a/d.go:6:2-8: defined here as ```go\nfield Member string\n```\n\n\\@Member\n\n[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing.Member)"},
|
||||
{v19: "godef/a/d.go:9:5-10: defined here as ```go\nvar Other Thing\n```\n\n@Other\n\n\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)", v18: "godef/a/d.go:9:5-10: defined here as ```go\nvar Other Thing\n```\n\n\\@Other\n\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)"},
|
||||
{v19: "godef/a/d.go:9:5-10: defined here as ```go\nvar a.Other a.Thing\n```\n\n@Other\n\n\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)", v18: "godef/a/d.go:9:5-10: defined here as ```go\nvar a.Other a.Thing\n```\n\n\\@Other\n\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)"},
|
||||
{v19: "godef/a/random.go:13:2-3: defined here as ```go\nfield x int\n```\n\n@mark(PosX, \"x\"),mark(PosY, \"y\")", v18: "godef/a/random.go:13:2-3: defined here as ```go\nfield x int\n```\n\n\\@mark\\(PosX, \\\"x\\\"\\),mark\\(PosY, \\\"y\\\"\\)"},
|
||||
{v19: "godef/b/b.go:25:6-12: defined here as ```go\ntype aAlias = a.A\n```\n\n@mark(aAlias, \"aAlias\")", v18: "godef/b/b.go:25:6-12: defined here as ```go\ntype aAlias = a.A\n```\n\n\\@mark\\(aAlias, \\\"aAlias\\\"\\)"},
|
||||
{v19: "godef/b/b.go:28:2-4: defined here as ```go\nfield F1 int\n```\n\n@mark(S1F1, \"F1\")\n\n\n[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.F1)", v18: "godef/b/b.go:28:2-4: defined here as ```go\nfield F1 int\n```\n\n\\@mark\\(S1F1, \\\"F1\\\"\\)\n\n[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.F1)"},
|
||||
{v19: "godef/b/b.go:29:2-4: defined here as ```go\nfield S2 S2\n```\n\n@godef(\"S2\", S2),mark(S1S2, \"S2\")\n\n\n[`(b.S1).S2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.S2)", v18: "godef/b/b.go:29:2-4: defined here as ```go\nfield S2 S2\n```\n\n\\@godef\\(\\\"S2\\\", S2\\),mark\\(S1S2, \\\"S2\\\"\\)\n\n[`(b.S1).S2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.S2)"},
|
||||
{v19: "godef/b/b.go:35:2-4: defined here as ```go\nfield F1 string\n```\n\n@mark(S2F1, \"F1\")\n\n\n[`(b.S2).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2.F1)", v18: "godef/b/b.go:35:2-4: defined here as ```go\nfield F1 string\n```\n\n\\@mark\\(S2F1, \\\"F1\\\"\\)\n\n[`(b.S2).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2.F1)"},
|
||||
{v19: "godef/b/b.go:36:2-4: defined here as ```go\nfield F2 int\n```\n\n@mark(S2F2, \"F2\")\n\n\n[`(b.S2).F2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2.F2)", v18: "godef/b/b.go:36:2-4: defined here as ```go\nfield F2 int\n```\n\n\\@mark\\(S2F2, \\\"F2\\\"\\)\n\n[`(b.S2).F2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2.F2)"},
|
||||
{v19: "godef/b/b.go:57:7-8: defined here as ```go\nconst X untyped int = 0\n```\n\n@mark(bX, \"X\"),godef(\"X\", bX)\n\n\n[`b.X` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#X)", v18: "godef/b/b.go:57:7-8: defined here as ```go\nconst X untyped int = 0\n```\n\n\\@mark\\(bX, \\\"X\\\"\\),godef\\(\\\"X\\\", bX\\)\n\n[`b.X` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#X)"},
|
||||
{v19: "godef/broken/unclosedIf.go:7:7-19: defined here as ```go\nvar myUnclosedIf string\n```\n\n@myUnclosedIf", v18: "godef/broken/unclosedIf.go:7:7-19: defined here as ```go\nvar myUnclosedIf string\n```\n\n\\@myUnclosedIf"},
|
||||
{v19: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/a/a.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 26,\n\t\t\t\"column\": 6,\n\t\t\t\"offset\": 467\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 26,\n\t\t\t\"column\": 7,\n\t\t\t\"offset\": 468\n\t\t}\n\t},\n\t\"description\": \"```go\\ntype A string\\n```\\n\\n@mark(AString, \\\"A\\\")\\n\\n\\n[`a.A` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#A)\"\n}", v18: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/a/a.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 26,\n\t\t\t\"column\": 6,\n\t\t\t\"offset\": 467\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 26,\n\t\t\t\"column\": 7,\n\t\t\t\"offset\": 468\n\t\t}\n\t},\n\t\"description\": \"```go\\ntype A string\\n```\\n\\n\\\\@mark\\\\(AString, \\\\\\\"A\\\\\\\"\\\\)\\n\\n[`a.A` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#A)\"\n}\n"},
|
||||
{v19: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/a/a.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 33,\n\t\t\t\"column\": 6,\n\t\t\t\"offset\": 612\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 33,\n\t\t\t\"column\": 9,\n\t\t\t\"offset\": 615\n\t\t}\n\t},\n\t\"description\": \"```go\\nvar err error\\n```\\n\\n@err\"\n}", v18: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/a/a.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 33,\n\t\t\t\"column\": 6,\n\t\t\t\"offset\": 612\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 33,\n\t\t\t\"column\": 9,\n\t\t\t\"offset\": 615\n\t\t}\n\t},\n\t\"description\": \"```go\\nvar err error\\n```\\n\\n\\\\@err\"\n}\n"},
|
||||
{v19: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/a/d.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 6,\n\t\t\t\"column\": 2,\n\t\t\t\"offset\": 90\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 6,\n\t\t\t\"column\": 8,\n\t\t\t\"offset\": 96\n\t\t}\n\t},\n\t\"description\": \"```go\\nfield Member string\\n```\\n\\n@Member\\n\\n\\n[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing.Member)\"\n}", v18: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/a/d.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 6,\n\t\t\t\"column\": 2,\n\t\t\t\"offset\": 90\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 6,\n\t\t\t\"column\": 8,\n\t\t\t\"offset\": 96\n\t\t}\n\t},\n\t\"description\": \"```go\\nfield Member string\\n```\\n\\n\\\\@Member\\n\\n[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing.Member)\"\n}\n"},
|
||||
{v19: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/a/d.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 9,\n\t\t\t\"column\": 5,\n\t\t\t\"offset\": 121\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 9,\n\t\t\t\"column\": 10,\n\t\t\t\"offset\": 126\n\t\t}\n\t},\n\t\"description\": \"```go\\nvar Other Thing\\n```\\n\\n@Other\\n\\n\\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)\"\n}", v18: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/a/d.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 9,\n\t\t\t\"column\": 5,\n\t\t\t\"offset\": 121\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 9,\n\t\t\t\"column\": 10,\n\t\t\t\"offset\": 126\n\t\t}\n\t},\n\t\"description\": \"```go\\nvar Other Thing\\n```\\n\\n\\\\@Other\\n\\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)\"\n}\n"},
|
||||
{v19: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/a/d.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 9,\n\t\t\t\"column\": 5,\n\t\t\t\"offset\": 121\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 9,\n\t\t\t\"column\": 10,\n\t\t\t\"offset\": 126\n\t\t}\n\t},\n\t\"description\": \"```go\\nvar a.Other a.Thing\\n```\\n\\n@Other\\n\\n\\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)\"\n}", v18: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/a/d.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 9,\n\t\t\t\"column\": 5,\n\t\t\t\"offset\": 121\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 9,\n\t\t\t\"column\": 10,\n\t\t\t\"offset\": 126\n\t\t}\n\t},\n\t\"description\": \"```go\\nvar a.Other a.Thing\\n```\\n\\n\\\\@Other\\n\\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)\"\n}\n"},
|
||||
{v19: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/a/random.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 13,\n\t\t\t\"column\": 2,\n\t\t\t\"offset\": 187\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 13,\n\t\t\t\"column\": 3,\n\t\t\t\"offset\": 188\n\t\t}\n\t},\n\t\"description\": \"```go\\nfield x int\\n```\\n\\n@mark(PosX, \\\"x\\\"),mark(PosY, \\\"y\\\")\"\n}", v18: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/a/random.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 13,\n\t\t\t\"column\": 2,\n\t\t\t\"offset\": 187\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 13,\n\t\t\t\"column\": 3,\n\t\t\t\"offset\": 188\n\t\t}\n\t},\n\t\"description\": \"```go\\nfield x int\\n```\\n\\n\\\\@mark\\\\(PosX, \\\\\\\"x\\\\\\\"\\\\),mark\\\\(PosY, \\\\\\\"y\\\\\\\"\\\\)\"\n}\n"},
|
||||
{v19: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/b/b.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 25,\n\t\t\t\"column\": 6,\n\t\t\t\"offset\": 542\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 25,\n\t\t\t\"column\": 12,\n\t\t\t\"offset\": 548\n\t\t}\n\t},\n\t\"description\": \"```go\\ntype aAlias = a.A\\n```\\n\\n@mark(aAlias, \\\"aAlias\\\")\"\n}", v18: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/b/b.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 25,\n\t\t\t\"column\": 6,\n\t\t\t\"offset\": 542\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 25,\n\t\t\t\"column\": 12,\n\t\t\t\"offset\": 548\n\t\t}\n\t},\n\t\"description\": \"```go\\ntype aAlias = a.A\\n```\\n\\n\\\\@mark\\\\(aAlias, \\\\\\\"aAlias\\\\\\\"\\\\)\"\n}\n"},
|
||||
{v19: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/b/b.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 28,\n\t\t\t\"column\": 2,\n\t\t\t\"offset\": 606\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 28,\n\t\t\t\"column\": 4,\n\t\t\t\"offset\": 608\n\t\t}\n\t},\n\t\"description\": \"```go\\nfield F1 int\\n```\\n\\n@mark(S1F1, \\\"F1\\\")\\n\\n\\n[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.F1)\"\n}", v18: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/b/b.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 28,\n\t\t\t\"column\": 2,\n\t\t\t\"offset\": 606\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 28,\n\t\t\t\"column\": 4,\n\t\t\t\"offset\": 608\n\t\t}\n\t},\n\t\"description\": \"```go\\nfield F1 int\\n```\\n\\n\\\\@mark\\\\(S1F1, \\\\\\\"F1\\\\\\\"\\\\)\\n\\n[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.F1)\"\n}\n"},
|
||||
{v19: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/b/b.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 29,\n\t\t\t\"column\": 2,\n\t\t\t\"offset\": 638\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 29,\n\t\t\t\"column\": 4,\n\t\t\t\"offset\": 640\n\t\t}\n\t},\n\t\"description\": \"```go\\nfield S2 S2\\n```\\n\\n@godef(\\\"S2\\\", S2),mark(S1S2, \\\"S2\\\")\\n\\n\\n[`(b.S1).S2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.S2)\"\n}", v18: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/b/b.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 29,\n\t\t\t\"column\": 2,\n\t\t\t\"offset\": 638\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 29,\n\t\t\t\"column\": 4,\n\t\t\t\"offset\": 640\n\t\t}\n\t},\n\t\"description\": \"```go\\nfield S2 S2\\n```\\n\\n\\\\@godef\\\\(\\\\\\\"S2\\\\\\\", S2\\\\),mark\\\\(S1S2, \\\\\\\"S2\\\\\\\"\\\\)\\n\\n[`(b.S1).S2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.S2)\"\n}\n"},
|
||||
{v19: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/b/b.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 35,\n\t\t\t\"column\": 2,\n\t\t\t\"offset\": 781\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 35,\n\t\t\t\"column\": 4,\n\t\t\t\"offset\": 783\n\t\t}\n\t},\n\t\"description\": \"```go\\nfield F1 string\\n```\\n\\n@mark(S2F1, \\\"F1\\\")\\n\\n\\n[`(b.S2).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2.F1)\"\n}", v18: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/b/b.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 35,\n\t\t\t\"column\": 2,\n\t\t\t\"offset\": 781\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 35,\n\t\t\t\"column\": 4,\n\t\t\t\"offset\": 783\n\t\t}\n\t},\n\t\"description\": \"```go\\nfield F1 string\\n```\\n\\n\\\\@mark\\\\(S2F1, \\\\\\\"F1\\\\\\\"\\\\)\\n\\n[`(b.S2).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2.F1)\"\n}\n"},
|
||||
{v19: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/b/b.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 36,\n\t\t\t\"column\": 2,\n\t\t\t\"offset\": 814\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 36,\n\t\t\t\"column\": 4,\n\t\t\t\"offset\": 816\n\t\t}\n\t},\n\t\"description\": \"```go\\nfield F2 int\\n```\\n\\n@mark(S2F2, \\\"F2\\\")\\n\\n\\n[`(b.S2).F2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2.F2)\"\n}", v18: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/b/b.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 36,\n\t\t\t\"column\": 2,\n\t\t\t\"offset\": 814\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 36,\n\t\t\t\"column\": 4,\n\t\t\t\"offset\": 816\n\t\t}\n\t},\n\t\"description\": \"```go\\nfield F2 int\\n```\\n\\n\\\\@mark\\\\(S2F2, \\\\\\\"F2\\\\\\\"\\\\)\\n\\n[`(b.S2).F2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2.F2)\"\n}\n"},
|
||||
{v19: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/b/b.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 57,\n\t\t\t\"column\": 7,\n\t\t\t\"offset\": 1249\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 57,\n\t\t\t\"column\": 8,\n\t\t\t\"offset\": 1250\n\t\t}\n\t},\n\t\"description\": \"```go\\nconst X untyped int = 0\\n```\\n\\n@mark(bX, \\\"X\\\"),godef(\\\"X\\\", bX)\\n\\n\\n[`b.X` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#X)\"\n}", v18: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/b/b.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 57,\n\t\t\t\"column\": 7,\n\t\t\t\"offset\": 1249\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 57,\n\t\t\t\"column\": 8,\n\t\t\t\"offset\": 1250\n\t\t}\n\t},\n\t\"description\": \"```go\\nconst X untyped int = 0\\n```\\n\\n\\\\@mark\\\\(bX, \\\\\\\"X\\\\\\\"\\\\),godef\\\\(\\\\\\\"X\\\\\\\", bX\\\\)\\n\\n[`b.X` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#X)\"\n}\n"},
|
||||
{v19: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/broken/unclosedIf.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 7,\n\t\t\t\"column\": 7,\n\t\t\t\"offset\": 68\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 7,\n\t\t\t\"column\": 19,\n\t\t\t\"offset\": 80\n\t\t}\n\t},\n\t\"description\": \"```go\\nvar myUnclosedIf string\\n```\\n\\n@myUnclosedIf\"\n}", v18: "{\n\t\"span\": {\n\t\t\"uri\": \"file://godef/broken/unclosedIf.go\",\n\t\t\"start\": {\n\t\t\t\"line\": 7,\n\t\t\t\"column\": 7,\n\t\t\t\"offset\": 68\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": 7,\n\t\t\t\"column\": 19,\n\t\t\t\"offset\": 80\n\t\t}\n\t},\n\t\"description\": \"```go\\nvar myUnclosedIf string\\n```\\n\\n\\\\@myUnclosedIf\"\n}\n"},
|
||||
}
|
|
@ -31,6 +31,7 @@ import (
|
|||
"golang.org/x/tools/internal/lsp/protocol"
|
||||
"golang.org/x/tools/internal/lsp/source"
|
||||
"golang.org/x/tools/internal/lsp/source/completion"
|
||||
"golang.org/x/tools/internal/lsp/tests/compare"
|
||||
"golang.org/x/tools/internal/span"
|
||||
"golang.org/x/tools/internal/testenv"
|
||||
"golang.org/x/tools/internal/typeparams"
|
||||
|
@ -1015,7 +1016,7 @@ func checkData(t *testing.T, data *Data) {
|
|||
// These counters change when assertions are added or removed.
|
||||
// They act as an independent safety net to ensure that the
|
||||
// tests didn't spuriously pass because they did no work.
|
||||
t.Errorf("test summary does not match:\n%s\n(Run with -golden to update golden file; also, there may be one per Go version.)", Diff(t, want, got))
|
||||
t.Errorf("test summary does not match:\n%s\n(Run with -golden to update golden file; also, there may be one per Go version.)", compare.Text(want, got))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -569,20 +569,6 @@ func WorkspaceSymbolsTestTypeToMatcher(typ WorkspaceSymbolsTestType) source.Symb
|
|||
}
|
||||
}
|
||||
|
||||
func Diff(t *testing.T, want, got string) string {
|
||||
if want == got {
|
||||
return ""
|
||||
}
|
||||
// Add newlines to avoid newline messages in diff.
|
||||
want += "\n"
|
||||
got += "\n"
|
||||
d, err := myers.ComputeEdits("", want, got)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return fmt.Sprintf("%q", diff.ToUnified("want", "got", want, d))
|
||||
}
|
||||
|
||||
// StripSubscripts removes type parameter id subscripts.
|
||||
//
|
||||
// TODO(rfindley): remove this function once subscripts are removed from the
|
||||
|
|
Загрузка…
Ссылка в новой задаче