Skip to content

Commit 69920f2

Browse files
committed
gopls/internal/regtest/marker: add missing tests for hover
Add additional tests for hover behavior. These tests would have failed in earlier patchsets of the subsequent CL rewriting hover. Also, add support for the special "env" file to the marker framework. Change-Id: Iecbd4994a6c1261f87163d50793fbbc5f26ea1ba Reviewed-on: https://go-review.googlesource.com/c/tools/+/466135 TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Robert Findley <[email protected]> Reviewed-by: Alan Donovan <[email protected]> gopls-CI: kokoro <[email protected]>
1 parent 24a13c6 commit 69920f2

File tree

3 files changed

+181
-6
lines changed

3 files changed

+181
-6
lines changed

gopls/internal/lsp/regtest/marker.go

+31-6
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ var updateGolden = flag.Bool("update", false, "if set, update test data during m
9595
// for the test.
9696
// - "settings.json": this file is parsed as JSON, and used as the
9797
// session configuration (see gopls/doc/settings.md)
98+
// - "env": this file is parsed as a list of VAR=VALUE fields specifying the
99+
// editor environment.
98100
// - Golden files: Within the archive, file names starting with '@' are
99101
// treated as "golden" content, and are not written to disk, but instead are
100102
// made available to test methods expecting an argument of type *Golden,
@@ -189,7 +191,6 @@ var updateGolden = flag.Bool("update", false, "if set, update test data during m
189191
//
190192
// Remaining TODO:
191193
// - parallelize/optimize test execution
192-
// - add support for per-test environment?
193194
// - reorganize regtest packages (and rename to just 'test'?)
194195
//
195196
// Existing marker tests to port:
@@ -246,9 +247,13 @@ func RunMarkerTests(t *testing.T, dir string) {
246247
testenv.NeedsGo1Point(t, 18)
247248
}
248249
test.executed = true
250+
config := fake.EditorConfig{
251+
Settings: test.settings,
252+
Env: test.env,
253+
}
249254
c := &markerContext{
250255
test: test,
251-
env: newEnv(t, cache, test.files, test.settings),
256+
env: newEnv(t, cache, test.files, config),
252257

253258
locations: make(map[expect.Identifier]protocol.Location),
254259
diags: make(map[protocol.Location][]protocol.Diagnostic),
@@ -380,6 +385,7 @@ type MarkerTest struct {
380385
fset *token.FileSet // fileset used for parsing notes
381386
archive *txtar.Archive // original test archive
382387
settings map[string]interface{} // gopls settings
388+
env map[string]string // editor environment
383389
files map[string][]byte // data files from the archive (excluding special files)
384390
notes []*expect.Note // extracted notes from data files
385391
golden map[string]*Golden // extracted golden content, by identifier name
@@ -490,6 +496,19 @@ func loadMarkerTest(name string, archive *txtar.Archive) (*MarkerTest, error) {
490496
}
491497
continue
492498
}
499+
if file.Name == "env" {
500+
test.env = make(map[string]string)
501+
fields := strings.Fields(string(file.Data))
502+
for _, field := range fields {
503+
// TODO: use strings.Cut once we are on 1.18+.
504+
idx := strings.IndexByte(field, '=')
505+
if idx < 0 {
506+
return nil, fmt.Errorf("env vars must be formatted as var=value, got %q", field)
507+
}
508+
test.env[field[:idx]] = field[idx+1:]
509+
}
510+
continue
511+
}
493512
if strings.HasPrefix(file.Name, "@") { // golden content
494513
// TODO: use strings.Cut once we are on 1.18+.
495514
idx := strings.IndexByte(file.Name, '/')
@@ -541,6 +560,15 @@ func writeMarkerTests(dir string, tests []*MarkerTest) error {
541560
}
542561
arch.Files = append(arch.Files, txtar.File{Name: "settings.json", Data: data})
543562
}
563+
if len(test.env) > 0 {
564+
var vars []string
565+
for k, v := range test.env {
566+
vars = append(vars, fmt.Sprintf("%s=%s", k, v))
567+
}
568+
sort.Strings(vars)
569+
data := []byte(strings.Join(vars, "\n"))
570+
arch.Files = append(arch.Files, txtar.File{Name: "env", Data: data})
571+
}
544572

545573
// ...followed by ordinary files. Preserve the order they appeared in the
546574
// original archive.
@@ -578,7 +606,7 @@ func writeMarkerTests(dir string, tests []*MarkerTest) error {
578606
//
579607
// TODO(rfindley): simplify and refactor the construction of testing
580608
// environments across regtests, marker tests, and benchmarks.
581-
func newEnv(t *testing.T, cache *cache.Cache, files map[string][]byte, settings map[string]interface{}) *Env {
609+
func newEnv(t *testing.T, cache *cache.Cache, files map[string][]byte, config fake.EditorConfig) *Env {
582610
sandbox, err := fake.NewSandbox(&fake.SandboxConfig{
583611
RootDir: t.TempDir(),
584612
GOPROXY: "https://proxy.golang.org",
@@ -596,9 +624,6 @@ func newEnv(t *testing.T, cache *cache.Cache, files map[string][]byte, settings
596624
awaiter := NewAwaiter(sandbox.Workdir)
597625
ss := lsprpc.NewStreamServer(cache, false, hooks.Options)
598626
server := servertest.NewPipeServer(ss, jsonrpc2.NewRawStream)
599-
config := fake.EditorConfig{
600-
Settings: settings,
601-
}
602627
editor, err := fake.NewEditor(sandbox, config).Connect(ctx, server, awaiter.Hooks())
603628
if err != nil {
604629
sandbox.Close() // ignore error
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
This test checks that links in hover obey GOPRIVATE.
2+
-- env --
3+
GOPRIVATE=mod.com
4+
-- go.mod --
5+
module mod.com
6+
-- p.go --
7+
package p
8+
9+
// T should not be linked, as it is private.
10+
type T struct{} //@hover("T", "T", T)
11+
-- lib/lib.go --
12+
package lib
13+
14+
// GOPRIVATE should also match nested packages.
15+
type L struct{} //@hover("L", "L", L)
16+
-- @L/hover.md --
17+
```go
18+
type L struct{}
19+
```
20+
21+
GOPRIVATE should also match nested packages.
22+
-- @T/hover.md --
23+
```go
24+
type T struct{}
25+
```
26+
27+
T should not be linked, as it is private.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
This test checks that we correctly determine pkgsite links for various
2+
identifiers.
3+
4+
We should only produce links that work, meaning the object is reachable via the
5+
package's public API.
6+
-- go.mod --
7+
module mod.com
8+
9+
go 1.18
10+
-- p.go --
11+
package p
12+
13+
type E struct {
14+
Embed int
15+
}
16+
17+
// T is in the package scope, and so should be linkable.
18+
type T struct{ //@hover("T", "T", T)
19+
// Only exported fields should be linkable
20+
21+
f int //@hover("f", "f", f)
22+
F int //@hover("F", "F", F)
23+
24+
E
25+
26+
// TODO(rfindley): is the link here correct? It ignores N.
27+
N struct {
28+
// Nested fields should also be linkable.
29+
Nested int //@hover("Nested", "Nested", Nested)
30+
}
31+
}
32+
// M is an exported method, and so should be linkable.
33+
func (T) M() {}
34+
35+
// m is not exported, and so should not be linkable.
36+
func (T) m() {}
37+
38+
func _() {
39+
var t T
40+
41+
// Embedded fields should be linkable.
42+
_ = t.Embed //@hover("Embed", "Embed", Embed)
43+
44+
// Local variables should not be linkable, even if they are capitalized.
45+
var X int //@hover("X", "X", X)
46+
_ = X
47+
48+
// Local types should not be linkable, even if they are capitalized.
49+
type Local struct { //@hover("Local", "Local", Local)
50+
E
51+
}
52+
53+
// But the embedded field should still be linkable.
54+
var l Local
55+
_ = l.Embed //@hover("Embed", "Embed", Embed)
56+
}
57+
-- @Embed/hover.md --
58+
```go
59+
field Embed int
60+
```
61+
62+
[`(p.E).Embed` on pkg.go.dev](https://pkg.go.dev/mod.com#E.Embed)
63+
-- @F/hover.md --
64+
```go
65+
field F int
66+
```
67+
68+
@hover("F", "F", F)
69+
70+
71+
[`(p.T).F` on pkg.go.dev](https://pkg.go.dev/mod.com#T.F)
72+
-- @Local/hover.md --
73+
```go
74+
type Local struct {
75+
E
76+
}
77+
```
78+
79+
Local types should not be linkable, even if they are capitalized.
80+
-- @Nested/hover.md --
81+
```go
82+
field Nested int
83+
```
84+
85+
Nested fields should also be linkable.
86+
87+
88+
[`(p.T).Nested` on pkg.go.dev](https://pkg.go.dev/mod.com#T.Nested)
89+
-- @T/hover.md --
90+
```go
91+
type T struct {
92+
f int //@hover("f", "f", f)
93+
F int //@hover("F", "F", F)
94+
95+
E
96+
97+
// TODO(rfindley): is the link here correct? It ignores N.
98+
N struct {
99+
// Nested fields should also be linkable.
100+
Nested int //@hover("Nested", "Nested", Nested)
101+
}
102+
}
103+
104+
func (T).M()
105+
func (T).m()
106+
```
107+
108+
T is in the package scope, and so should be linkable.
109+
110+
111+
[`p.T` on pkg.go.dev](https://pkg.go.dev/mod.com#T)
112+
-- @X/hover.md --
113+
```go
114+
var X int
115+
```
116+
117+
Local variables should not be linkable, even if they are capitalized.
118+
-- @f/hover.md --
119+
```go
120+
field f int
121+
```
122+
123+
@hover("f", "f", f)

0 commit comments

Comments
 (0)