aboutsummaryrefslogtreecommitdiff
path: root/gopls/internal/regtest/marker
diff options
context:
space:
mode:
Diffstat (limited to 'gopls/internal/regtest/marker')
-rw-r--r--gopls/internal/regtest/marker/marker_test.go21
-rw-r--r--gopls/internal/regtest/marker/testdata/definition/embed.txt254
-rw-r--r--gopls/internal/regtest/marker/testdata/definition/import.txt52
-rw-r--r--gopls/internal/regtest/marker/testdata/definition/misc.txt230
-rw-r--r--gopls/internal/regtest/marker/testdata/hover/basiclit.txt60
-rw-r--r--gopls/internal/regtest/marker/testdata/hover/const.txt18
-rw-r--r--gopls/internal/regtest/marker/testdata/hover/generics.txt77
-rw-r--r--gopls/internal/regtest/marker/testdata/hover/goprivate.txt27
-rw-r--r--gopls/internal/regtest/marker/testdata/hover/hover.txt29
-rw-r--r--gopls/internal/regtest/marker/testdata/hover/linkable.txt120
-rw-r--r--gopls/internal/regtest/marker/testdata/hover/linkable_generics.txt145
-rw-r--r--gopls/internal/regtest/marker/testdata/hover/std.txt80
-rw-r--r--gopls/internal/regtest/marker/testdata/rename/basic.txt22
-rw-r--r--gopls/internal/regtest/marker/testdata/rename/conflict.txt59
-rw-r--r--gopls/internal/regtest/marker/testdata/rename/embed.txt36
-rw-r--r--gopls/internal/regtest/marker/testdata/rename/methods.txt67
-rw-r--r--gopls/internal/regtest/marker/testdata/rename/typeswitch.txt26
-rw-r--r--gopls/internal/regtest/marker/testdata/stubmethods/basic.txt24
18 files changed, 1347 insertions, 0 deletions
diff --git a/gopls/internal/regtest/marker/marker_test.go b/gopls/internal/regtest/marker/marker_test.go
new file mode 100644
index 000000000..ac051a555
--- /dev/null
+++ b/gopls/internal/regtest/marker/marker_test.go
@@ -0,0 +1,21 @@
+// Copyright 2023 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 marker
+
+import (
+ "testing"
+
+ . "golang.org/x/tools/gopls/internal/lsp/regtest"
+)
+
+// Note: we use a separate package for the marker tests so that we can easily
+// compare their performance to the existing marker tests in ./internal/lsp.
+
+// TestMarkers runs the marker tests from the testdata directory.
+//
+// See RunMarkerTests for details on how marker tests work.
+func TestMarkers(t *testing.T) {
+ RunMarkerTests(t, "testdata")
+}
diff --git a/gopls/internal/regtest/marker/testdata/definition/embed.txt b/gopls/internal/regtest/marker/testdata/definition/embed.txt
new file mode 100644
index 000000000..e28c7fed6
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/definition/embed.txt
@@ -0,0 +1,254 @@
+This test checks definition and hover operations over embedded fields and methods.
+
+-- go.mod --
+module mod.com
+
+go 1.18
+
+-- a/a.go --
+package a
+
+type A string //@loc(AString, "A")
+
+func (_ A) Hi() {} //@loc(AHi, "Hi")
+
+type S struct {
+ Field int //@loc(SField, "Field")
+ R // embed a struct
+ H // embed an interface
+}
+
+type R struct {
+ Field2 int //@loc(RField2, "Field2")
+}
+
+func (_ R) Hey() {} //@loc(RHey, "Hey")
+
+type H interface { //@loc(H, "H")
+ Goodbye() //@loc(HGoodbye, "Goodbye")
+}
+
+type I interface { //@loc(I, "I")
+ B() //@loc(IB, "B")
+ J
+}
+
+type J interface { //@loc(J, "J")
+ Hello() //@loc(JHello, "Hello")
+}
+
+-- b/b.go --
+package b
+
+import "mod.com/a" //@loc(AImport, re"\".*\"")
+
+type embed struct {
+ F int //@loc(F, "F")
+}
+
+func (embed) M() //@loc(M, "M")
+
+type Embed struct {
+ embed
+ *a.A
+ a.I
+ a.S
+}
+
+func _() {
+ e := Embed{}
+ e.Hi() //@def("Hi", AHi),hover("Hi", "Hi", AHi)
+ e.B() //@def("B", IB),hover("B", "B", IB)
+ _ = e.Field //@def("Field", SField),hover("Field", "Field", SField)
+ _ = e.Field2 //@def("Field2", RField2),hover("Field2", "Field2", RField2)
+ e.Hello() //@def("Hello", JHello),hover("Hello", "Hello",JHello)
+ e.Hey() //@def("Hey", RHey),hover("Hey", "Hey", RHey)
+ e.Goodbye() //@def("Goodbye", HGoodbye),hover("Goodbye", "Goodbye", HGoodbye)
+ e.M() //@def("M", M),hover("M", "M", M)
+ _ = e.F //@def("F", F),hover("F", "F", F)
+}
+
+type aAlias = a.A //@loc(aAlias, "aAlias")
+
+type S1 struct { //@loc(S1, "S1")
+ F1 int //@loc(S1F1, "F1")
+ S2 //@loc(S1S2, "S2"),def("S2", S2),hover("S2", "S2", S2)
+ a.A //@def("A", AString),hover("A", "A", aA)
+ aAlias //@def("a", aAlias),hover("a", "aAlias", aAlias)
+}
+
+type S2 struct { //@loc(S2, "S2")
+ F1 string //@loc(S2F1, "F1")
+ F2 int //@loc(S2F2, "F2")
+ *a.A //@def("A", AString),def("a",AImport)
+}
+
+type S3 struct {
+ F1 struct {
+ a.A //@def("A", AString)
+ }
+}
+
+func Bar() {
+ var x S1 //@def("S1", S1),hover("S1", "S1", S1)
+ _ = x.S2 //@def("S2", S1S2),hover("S2", "S2", S1S2)
+ _ = x.F1 //@def("F1", S1F1),hover("F1", "F1", S1F1)
+ _ = x.F2 //@def("F2", S2F2),hover("F2", "F2", S2F2)
+ _ = x.S2.F1 //@def("F1", S2F1),hover("F1", "F1", S2F1)
+}
+
+-- b/c.go --
+package b
+
+var _ = S1{ //@def("S1", S1),hover("S1", "S1", S1)
+ F1: 99, //@def("F1", S1F1),hover("F1", "F1", S1F1)
+}
+
+-- @AHi/hover.md --
+```go
+func (a.A).Hi()
+```
+
+[`(a.A).Hi` on pkg.go.dev](https://pkg.go.dev/mod.com/a#A.Hi)
+-- @F/hover.md --
+```go
+field F int
+```
+
+@loc(F, "F")
+
+
+[`(b.Embed).F` on pkg.go.dev](https://pkg.go.dev/mod.com/b#Embed.F)
+-- @HGoodbye/hover.md --
+```go
+func (a.H).Goodbye()
+```
+
+@loc(HGoodbye, "Goodbye")
+
+
+[`(a.H).Goodbye` on pkg.go.dev](https://pkg.go.dev/mod.com/a#H.Goodbye)
+-- @IB/hover.md --
+```go
+func (a.I).B()
+```
+
+@loc(IB, "B")
+
+
+[`(a.I).B` on pkg.go.dev](https://pkg.go.dev/mod.com/a#I.B)
+-- @JHello/hover.md --
+```go
+func (a.J).Hello()
+```
+
+@loc(JHello, "Hello")
+
+
+[`(a.J).Hello` on pkg.go.dev](https://pkg.go.dev/mod.com/a#J.Hello)
+-- @M/hover.md --
+```go
+func (embed).M()
+```
+
+[`(b.Embed).M` on pkg.go.dev](https://pkg.go.dev/mod.com/b#Embed.M)
+-- @RField2/hover.md --
+```go
+field Field2 int
+```
+
+@loc(RField2, "Field2")
+
+
+[`(a.R).Field2` on pkg.go.dev](https://pkg.go.dev/mod.com/a#R.Field2)
+-- @RHey/hover.md --
+```go
+func (a.R).Hey()
+```
+
+[`(a.R).Hey` on pkg.go.dev](https://pkg.go.dev/mod.com/a#R.Hey)
+-- @S1/hover.md --
+```go
+type S1 struct {
+ F1 int //@loc(S1F1, "F1")
+ S2 //@loc(S1S2, "S2"),def("S2", S2),hover("S2", "S2", S2)
+ a.A //@def("A", AString),hover("A", "A", aA)
+ aAlias //@def("a", aAlias),hover("a", "aAlias", aAlias)
+}
+```
+
+[`b.S1` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S1)
+-- @S1F1/hover.md --
+```go
+field F1 int
+```
+
+@loc(S1F1, "F1")
+
+
+[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S1.F1)
+-- @S1S2/hover.md --
+```go
+field S2 S2
+```
+
+@loc(S1S2, "S2"),def("S2", S2),hover("S2", "S2", S2)
+
+
+[`(b.S1).S2` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S1.S2)
+-- @S2/hover.md --
+```go
+type S2 struct {
+ F1 string //@loc(S2F1, "F1")
+ F2 int //@loc(S2F2, "F2")
+ *a.A //@def("A", AString),def("a",AImport)
+}
+```
+
+[`b.S2` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S2)
+-- @S2F1/hover.md --
+```go
+field F1 string
+```
+
+@loc(S2F1, "F1")
+
+
+[`(b.S2).F1` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S2.F1)
+-- @S2F2/hover.md --
+```go
+field F2 int
+```
+
+@loc(S2F2, "F2")
+
+
+[`(b.S2).F2` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S2.F2)
+-- @SField/hover.md --
+```go
+field Field int
+```
+
+@loc(SField, "Field")
+
+
+[`(a.S).Field` on pkg.go.dev](https://pkg.go.dev/mod.com/a#S.Field)
+-- @aA/hover.md --
+```go
+type A string
+
+func (a.A).Hi()
+```
+
+@loc(AString, "A")
+
+
+[`a.A` on pkg.go.dev](https://pkg.go.dev/mod.com/a#A)
+-- @aAlias/hover.md --
+```go
+type aAlias = a.A
+
+func (a.A).Hi()
+```
+
+@loc(aAlias, "aAlias")
diff --git a/gopls/internal/regtest/marker/testdata/definition/import.txt b/gopls/internal/regtest/marker/testdata/definition/import.txt
new file mode 100644
index 000000000..9e5e5929a
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/definition/import.txt
@@ -0,0 +1,52 @@
+This test checks definition and hover over imports.
+-- go.mod --
+module mod.com
+
+go 1.18
+-- foo/foo.go --
+package foo
+
+type Foo struct{}
+
+// DoFoo does foo.
+func DoFoo() {} //@loc(DoFoo, "DoFoo")
+-- bar/bar.go --
+package bar
+
+import (
+ myFoo "mod.com/foo" //@loc(myFoo, "myFoo")
+)
+
+var _ *myFoo.Foo //@def("myFoo", myFoo),hover("myFoo", "myFoo", myFoo)
+-- bar/dotimport.go --
+package bar
+
+import . "mod.com/foo"
+
+func _() {
+ // variable of type foo.Foo
+ var _ Foo //@hover("_", "_", FooVar)
+
+ DoFoo() //@hover("DoFoo", "DoFoo", DoFoo)
+}
+-- @DoFoo/hover.md --
+```go
+func DoFoo()
+```
+
+DoFoo does foo.
+
+
+[`foo.DoFoo` on pkg.go.dev](https://pkg.go.dev/mod.com/foo#DoFoo)
+-- @FooVar/hover.md --
+```go
+var _ Foo
+```
+
+variable of type foo.Foo
+-- @myFoo/hover.md --
+```go
+package myFoo ("mod.com/foo")
+```
+
+[`myFoo` on pkg.go.dev](https://pkg.go.dev/mod.com/foo)
diff --git a/gopls/internal/regtest/marker/testdata/definition/misc.txt b/gopls/internal/regtest/marker/testdata/definition/misc.txt
new file mode 100644
index 000000000..48f5d340c
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/definition/misc.txt
@@ -0,0 +1,230 @@
+This test exercises miscellaneous definition and hover requests.
+-- go.mod --
+module mod.com
+
+go 1.16
+-- a.go --
+package a //@loc(aPackage, re"package (a)"),hover(aPackage, aPackage, aPackage)
+
+var (
+ // x is a variable.
+ x string //@loc(x, "x"),hover(x, x, hoverx)
+)
+
+// Constant block. When I hover on h, I should see this comment.
+const (
+ // When I hover on g, I should see this comment.
+ g = 1 //@hover("g", "g", hoverg)
+
+ h = 2 //@hover("h", "h", hoverh)
+)
+
+// z is a variable too.
+var z string //@loc(z, "z"),hover(z, z, hoverz)
+
+func AStuff() { //@loc(AStuff, "AStuff")
+ x := 5
+ Random2(x) //@def("dom2", Random2)
+ Random() //@def("()", Random)
+}
+
+type H interface { //@loc(H, "H")
+ Goodbye()
+}
+
+type I interface { //@loc(I, "I")
+ B()
+ J
+}
+
+type J interface { //@loc(J, "J")
+ Hello()
+}
+
+func _() {
+ // 1st type declaration block
+ type (
+ a struct { //@hover("a", "a", hoverDeclBlocka)
+ x string
+ }
+ )
+
+ // 2nd type declaration block
+ type (
+ // b has a comment
+ b struct{} //@hover("b", "b", hoverDeclBlockb)
+ )
+
+ // 3rd type declaration block
+ type (
+ // c is a struct
+ c struct { //@hover("c", "c", hoverDeclBlockc)
+ f string
+ }
+
+ d string //@hover("d", "d", hoverDeclBlockd)
+ )
+
+ type (
+ e struct { //@hover("e", "e", hoverDeclBlocke)
+ f float64
+ } // e has a comment
+ )
+}
+
+var (
+ hh H //@hover("H", "H", hoverH)
+ ii I //@hover("I", "I", hoverI)
+ jj J //@hover("J", "J", hoverJ)
+)
+-- a_test.go --
+package a
+
+import (
+ "testing"
+)
+
+func TestA(t *testing.T) { //@hover("TestA", "TestA", hoverTestA)
+}
+-- random.go --
+package a
+
+func Random() int { //@loc(Random, "Random")
+ y := 6 + 7
+ return y
+}
+
+func Random2(y int) int { //@loc(Random2, "Random2"),loc(RandomParamY, "y")
+ return y //@def("y", RandomParamY),hover("y", "y", hovery)
+}
+
+type Pos struct {
+ x, y int //@loc(PosX, "x"),loc(PosY, "y")
+}
+
+// Typ has a comment. Its fields do not.
+type Typ struct{ field string } //@loc(TypField, "field")
+
+func _() {
+ x := &Typ{}
+ _ = x.field //@def("field", TypField),hover("field", "field", hoverfield)
+}
+
+func (p *Pos) Sum() int { //@loc(PosSum, "Sum")
+ return p.x + p.y //@hover("x", "x", hoverpx)
+}
+
+func _() {
+ var p Pos
+ _ = p.Sum() //@def("()", PosSum),hover("()", `Sum`, hoverSum)
+}
+-- @aPackage/hover.md --
+-- @hoverDeclBlocka/hover.md --
+```go
+type a struct {
+ x string
+}
+```
+
+1st type declaration block
+-- @hoverDeclBlockb/hover.md --
+```go
+type b struct{}
+```
+
+b has a comment
+-- @hoverDeclBlockc/hover.md --
+```go
+type c struct {
+ f string
+}
+```
+
+c is a struct
+-- @hoverDeclBlockd/hover.md --
+```go
+type d string
+```
+
+3rd type declaration block
+-- @hoverDeclBlocke/hover.md --
+```go
+type e struct {
+ f float64
+}
+```
+
+e has a comment
+-- @hoverH/hover.md --
+```go
+type H interface {
+ Goodbye()
+}
+```
+
+[`a.H` on pkg.go.dev](https://pkg.go.dev/mod.com#H)
+-- @hoverI/hover.md --
+```go
+type I interface {
+ B()
+ J
+}
+```
+
+[`a.I` on pkg.go.dev](https://pkg.go.dev/mod.com#I)
+-- @hoverJ/hover.md --
+```go
+type J interface {
+ Hello()
+}
+```
+
+[`a.J` on pkg.go.dev](https://pkg.go.dev/mod.com#J)
+-- @hoverSum/hover.md --
+```go
+func (*Pos).Sum() int
+```
+
+[`(a.Pos).Sum` on pkg.go.dev](https://pkg.go.dev/mod.com#Pos.Sum)
+-- @hoverTestA/hover.md --
+```go
+func TestA(t *testing.T)
+```
+-- @hoverfield/hover.md --
+```go
+field field string
+```
+-- @hoverg/hover.md --
+```go
+const g untyped int = 1
+```
+
+When I hover on g, I should see this comment.
+-- @hoverh/hover.md --
+```go
+const h untyped int = 2
+```
+
+Constant block. When I hover on h, I should see this comment.
+-- @hoverpx/hover.md --
+```go
+field x int
+```
+
+@loc(PosX, "x"),loc(PosY, "y")
+-- @hoverx/hover.md --
+```go
+var x string
+```
+
+x is a variable.
+-- @hovery/hover.md --
+```go
+var y int
+```
+-- @hoverz/hover.md --
+```go
+var z string
+```
+
+z is a variable too.
diff --git a/gopls/internal/regtest/marker/testdata/hover/basiclit.txt b/gopls/internal/regtest/marker/testdata/hover/basiclit.txt
new file mode 100644
index 000000000..32527420d
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/hover/basiclit.txt
@@ -0,0 +1,60 @@
+This test checks gopls behavior when hovering over basic literals.
+-- basiclit.go --
+package basiclit
+
+func _() {
+ _ = 'a' //@hover("'a'", "'a'", latinA)
+ _ = 0x61 //@hover("0x61", "0x61", latinA)
+
+ _ = '\u2211' //@hover("'\\u2211'", "'\\u2211'", summation)
+ _ = 0x2211 //@hover("0x2211", "0x2211", summation)
+ _ = "foo \u2211 bar" //@hover("\\u2211", "\\u2211", summation)
+
+ _ = '\a' //@hover("'\\a'", "'\\a'", control)
+ _ = "foo \a bar" //@hover("\\a", "\\a", control)
+
+ _ = '\U0001F30A' //@hover("'\\U0001F30A'", "'\\U0001F30A'", waterWave)
+ _ = 0x0001F30A //@hover("0x0001F30A", "0x0001F30A", waterWave)
+ _ = "foo \U0001F30A bar" //@hover("\\U0001F30A", "\\U0001F30A", waterWave)
+
+ _ = '\x7E' //@hover("'\\x7E'", "'\\x7E'", tilde)
+ _ = "foo \x7E bar" //@hover("\\x7E", "\\x7E", tilde)
+ _ = "foo \a bar" //@hover("\\a", "\\a", control)
+
+ _ = '\173' //@hover("'\\173'", "'\\173'", leftCurly)
+ _ = "foo \173 bar" //@hover("\\173","\\173", leftCurly)
+ _ = "foo \173 bar \u2211 baz" //@hover("\\173","\\173", leftCurly)
+ _ = "foo \173 bar \u2211 baz" //@hover("\\u2211","\\u2211", summation)
+ _ = "foo\173bar\u2211baz" //@hover("\\173","\\173", leftCurly)
+ _ = "foo\173bar\u2211baz" //@hover("\\u2211","\\u2211", summation)
+
+ // search for runes in string only if there is an escaped sequence
+ _ = "hello" //@hover(`"hello"`, _, _)
+
+ // incorrect escaped rune sequences
+ _ = '\0' //@hover("'\\0'", _, _),diag(re`\\0()'`, re"illegal character")
+ _ = '\u22111' //@hover("'\\u22111'", _, _)
+ _ = '\U00110000' //@hover("'\\U00110000'", _, _)
+ _ = '\u12e45'//@hover("'\\u12e45'", _, _)
+ _ = '\xa' //@hover("'\\xa'", _, _)
+ _ = 'aa' //@hover("'aa'", _, _)
+
+ // other basic lits
+ _ = 1 //@hover("1", _, _)
+ _ = 1.2 //@hover("1.2", _, _)
+ _ = 1.2i //@hover("1.2i", _, _)
+ _ = 0123 //@hover("0123", _, _)
+ _ = 0x1234567890 //@hover("0x1234567890", _, _)
+)
+-- @control/hover.md --
+U+0007, control
+-- @latinA/hover.md --
+'a', U+0061, LATIN SMALL LETTER A
+-- @leftCurly/hover.md --
+'{', U+007B, LEFT CURLY BRACKET
+-- @summation/hover.md --
+'∑', U+2211, N-ARY SUMMATION
+-- @tilde/hover.md --
+'~', U+007E, TILDE
+-- @waterWave/hover.md --
+'🌊', U+1F30A, WATER WAVE
diff --git a/gopls/internal/regtest/marker/testdata/hover/const.txt b/gopls/internal/regtest/marker/testdata/hover/const.txt
new file mode 100644
index 000000000..cdb0e51e2
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/hover/const.txt
@@ -0,0 +1,18 @@
+This test checks hovering over constants.
+-- go.mod --
+module mod.com
+
+go 1.18
+-- c.go --
+package c
+
+const X = 0 //@hover("X", "X", bX)
+-- @bX/hover.md --
+```go
+const X untyped int = 0
+```
+
+@hover("X", "X", bX)
+
+
+[`c.X` on pkg.go.dev](https://pkg.go.dev/mod.com#X)
diff --git a/gopls/internal/regtest/marker/testdata/hover/generics.txt b/gopls/internal/regtest/marker/testdata/hover/generics.txt
new file mode 100644
index 000000000..673e860a3
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/hover/generics.txt
@@ -0,0 +1,77 @@
+This file contains tests for hovering over generic Go code.
+
+-- flags --
+-min_go=go1.18
+
+-- go.mod --
+// A go.mod is require for correct pkgsite links.
+// TODO(rfindley): don't link to ad-hoc or command-line-arguments packages!
+module mod.com
+
+go 1.18
+
+-- generics.go --
+package generics
+
+type value[T any] struct { //hover("lue", "value", value),hover("T", "T", valueT)
+ val T //@hover("T", "T", valuevalT)
+ Q int //@hover("Q", "Q", valueQ)
+}
+
+type Value[T any] struct { //@hover("T", "T", ValueT)
+ val T //@hover("T", "T", ValuevalT)
+ Q int //@hover("Q", "Q", ValueQ)
+}
+
+// disabled - see issue #54822
+func F[P interface{ ~int | string }]() { // hover("P","P",Ptparam)
+ // disabled - see issue #54822
+ var _ P // hover("P","P",Pvar)
+}
+
+-- inferred.go --
+package generics
+
+func app[S interface{ ~[]E }, E interface{}](s S, e E) S {
+ return append(s, e)
+}
+
+func _() {
+ _ = app[[]int] //@hover("app", "app", appint)
+ _ = app[[]int, int] //@hover("app", "app", appint)
+ // TODO(rfindley): eliminate this diagnostic.
+ _ = app[[]int]([]int{}, 0) //@hover("app", "app", appint),diag("[[]int]", re"unnecessary type arguments")
+ _ = app([]int{}, 0) //@hover("app", "app", appint)
+}
+
+-- @ValueQ/hover.md --
+```go
+field Q int
+```
+
+@hover("Q", "Q", ValueQ)
+
+
+[`(generics.Value).Q` on pkg.go.dev](https://pkg.go.dev/mod.com#Value.Q)
+-- @ValueT/hover.md --
+```go
+type parameter T any
+```
+-- @ValuevalT/hover.md --
+```go
+type parameter T any
+```
+-- @appint/hover.md --
+```go
+func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
+```
+-- @valueQ/hover.md --
+```go
+field Q int
+```
+
+@hover("Q", "Q", valueQ)
+-- @valuevalT/hover.md --
+```go
+type parameter T any
+```
diff --git a/gopls/internal/regtest/marker/testdata/hover/goprivate.txt b/gopls/internal/regtest/marker/testdata/hover/goprivate.txt
new file mode 100644
index 000000000..4c309ef38
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/hover/goprivate.txt
@@ -0,0 +1,27 @@
+This test checks that links in hover obey GOPRIVATE.
+-- env --
+GOPRIVATE=mod.com
+-- go.mod --
+module mod.com
+-- p.go --
+package p
+
+// T should not be linked, as it is private.
+type T struct{} //@hover("T", "T", T)
+-- lib/lib.go --
+package lib
+
+// GOPRIVATE should also match nested packages.
+type L struct{} //@hover("L", "L", L)
+-- @L/hover.md --
+```go
+type L struct{}
+```
+
+GOPRIVATE should also match nested packages.
+-- @T/hover.md --
+```go
+type T struct{}
+```
+
+T should not be linked, as it is private.
diff --git a/gopls/internal/regtest/marker/testdata/hover/hover.txt b/gopls/internal/regtest/marker/testdata/hover/hover.txt
new file mode 100644
index 000000000..f9cd3311b
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/hover/hover.txt
@@ -0,0 +1,29 @@
+This test demonstrates some features of the new marker test runner.
+-- a.go --
+package a
+
+const abc = 0x2a //@hover("b", "abc", abc),hover(" =", "abc", abc)
+-- typeswitch.go --
+package a
+
+func _() {
+ var y interface{}
+ switch x := y.(type) { //@hover("x", "x", x)
+ case int:
+ println(x) //@hover("x", "x", xint),hover(")", "x", xint)
+ }
+}
+-- @abc/hover.md --
+```go
+const abc untyped int = 42
+```
+
+@hover("b", "abc", abc),hover(" =", "abc", abc)
+-- @x/hover.md --
+```go
+var x interface{}
+```
+-- @xint/hover.md --
+```go
+var x int
+```
diff --git a/gopls/internal/regtest/marker/testdata/hover/linkable.txt b/gopls/internal/regtest/marker/testdata/hover/linkable.txt
new file mode 100644
index 000000000..981716d84
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/hover/linkable.txt
@@ -0,0 +1,120 @@
+This test checks that we correctly determine pkgsite links for various
+identifiers.
+
+We should only produce links that work, meaning the object is reachable via the
+package's public API.
+-- go.mod --
+module mod.com
+
+go 1.18
+-- p.go --
+package p
+
+type E struct {
+ Embed int
+}
+
+// T is in the package scope, and so should be linkable.
+type T struct{ //@hover("T", "T", T)
+ // Only exported fields should be linkable
+
+ f int //@hover("f", "f", f)
+ F int //@hover("F", "F", F)
+
+ E
+
+ // TODO(rfindley): is the link here correct? It ignores N.
+ N struct {
+ // Nested fields should also be linkable.
+ Nested int //@hover("Nested", "Nested", Nested)
+ }
+}
+// M is an exported method, and so should be linkable.
+func (T) M() {}
+
+// m is not exported, and so should not be linkable.
+func (T) m() {}
+
+func _() {
+ var t T
+
+ // Embedded fields should be linkable.
+ _ = t.Embed //@hover("Embed", "Embed", Embed)
+
+ // Local variables should not be linkable, even if they are capitalized.
+ var X int //@hover("X", "X", X)
+ _ = X
+
+ // Local types should not be linkable, even if they are capitalized.
+ type Local struct { //@hover("Local", "Local", Local)
+ E
+ }
+
+ // But the embedded field should still be linkable.
+ var l Local
+ _ = l.Embed //@hover("Embed", "Embed", Embed)
+}
+-- @Embed/hover.md --
+```go
+field Embed int
+```
+
+[`(p.E).Embed` on pkg.go.dev](https://pkg.go.dev/mod.com#E.Embed)
+-- @F/hover.md --
+```go
+field F int
+```
+
+@hover("F", "F", F)
+
+
+[`(p.T).F` on pkg.go.dev](https://pkg.go.dev/mod.com#T.F)
+-- @Local/hover.md --
+```go
+type Local struct {
+ E
+}
+```
+
+Local types should not be linkable, even if they are capitalized.
+-- @Nested/hover.md --
+```go
+field Nested int
+```
+
+Nested fields should also be linkable.
+-- @T/hover.md --
+```go
+type T struct {
+ f int //@hover("f", "f", f)
+ F int //@hover("F", "F", F)
+
+ E
+
+ // TODO(rfindley): is the link here correct? It ignores N.
+ N struct {
+ // Nested fields should also be linkable.
+ Nested int //@hover("Nested", "Nested", Nested)
+ }
+}
+
+func (T).M()
+func (T).m()
+```
+
+T is in the package scope, and so should be linkable.
+
+
+[`p.T` on pkg.go.dev](https://pkg.go.dev/mod.com#T)
+-- @X/hover.md --
+```go
+var X int
+```
+
+Local variables should not be linkable, even if they are capitalized.
+-- @f/hover.md --
+```go
+field f int
+```
+
+@hover("f", "f", f)
diff --git a/gopls/internal/regtest/marker/testdata/hover/linkable_generics.txt b/gopls/internal/regtest/marker/testdata/hover/linkable_generics.txt
new file mode 100644
index 000000000..be8e9e5cd
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/hover/linkable_generics.txt
@@ -0,0 +1,145 @@
+This file contains tests for documentation links to generic code in hover.
+
+-- flags --
+-min_go=go1.18
+
+-- go.mod --
+module mod.com
+
+go 1.19
+
+-- a.go --
+package a
+
+import "mod.com/generic"
+
+func _() {
+ // Hovering over instantiated object should produce accurate type
+ // information, but link to the generic declarations.
+
+ var x generic.GT[int] //@hover("GT", "GT", xGT)
+ _ = x.F //@hover("x", "x", x),hover("F", "F", xF)
+
+ f := generic.GF[int] //@hover("GF", "GF", fGF)
+ _ = f //@hover("f", "f", f)
+}
+
+-- generic/generic.go --
+package generic
+
+// Hovering over type parameters should link to documentation.
+//
+// TODO(rfindley): should it? We should probably link to the type.
+type GT[P any] struct{ //@hover("GT", "GT", GT),hover("P", "P", GTP)
+ F P //@hover("F", "F", F),hover("P", "P", FP)
+}
+
+func (GT[P]) M(p P) { //@hover("GT", "GT", GTrecv),hover("M","M", M),hover(re"p (P)", re"p (P)", pP)
+}
+
+func GF[P any] (p P) { //@hover("GF", "GF", GF)
+}
+
+-- @F/hover.md --
+```go
+field F P
+```
+
+@hover("F", "F", F),hover("P", "P", FP)
+
+
+[`(generic.GT).F` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT.F)
+-- @FP/hover.md --
+```go
+type parameter P any
+```
+-- @GF/hover.md --
+```go
+func GF[P any](p P)
+```
+
+[`generic.GF` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GF)
+-- @GT/hover.md --
+```go
+type GT[P any] struct {
+ F P //@hover("F", "F", F),hover("P", "P", FP)
+}
+
+func (GT[P]).M(p P)
+```
+
+Hovering over type parameters should link to documentation.
+
+TODO(rfindley): should it? We should probably link to the type.
+
+
+[`generic.GT` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT)
+-- @GTP/hover.md --
+```go
+type parameter P any
+```
+-- @GTrecv/hover.md --
+```go
+type GT[P any] struct {
+ F P //@hover("F", "F", F),hover("P", "P", FP)
+}
+
+func (GT[P]).M(p P)
+```
+
+Hovering over type parameters should link to documentation.
+
+TODO(rfindley): should it? We should probably link to the type.
+
+
+[`generic.GT` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT)
+-- @M/hover.md --
+```go
+func (GT[P]).M(p P)
+```
+
+[`(generic.GT).M` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT.M)
+-- @f/hover.md --
+```go
+var f func(p int)
+```
+-- @fGF/hover.md --
+```go
+func generic.GF(p int) // func[P any](p P)
+```
+
+[`generic.GF` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GF)
+-- @pP/hover.md --
+```go
+type parameter P any
+```
+-- @x/hover.md --
+```go
+var x generic.GT[int]
+```
+
+@hover("GT", "GT", xGT)
+-- @xF/hover.md --
+```go
+field F int
+```
+
+@hover("F", "F", F),hover("P", "P", FP)
+
+
+[`(generic.GT).F` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT.F)
+-- @xGT/hover.md --
+```go
+type GT[P any] struct {
+ F P //@hover("F", "F", F),hover("P", "P", FP)
+}
+
+func (generic.GT[P]).M(p P)
+```
+
+Hovering over type parameters should link to documentation.
+
+TODO(rfindley): should it? We should probably link to the type.
+
+
+[`generic.GT` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT)
diff --git a/gopls/internal/regtest/marker/testdata/hover/std.txt b/gopls/internal/regtest/marker/testdata/hover/std.txt
new file mode 100644
index 000000000..a526b5211
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/hover/std.txt
@@ -0,0 +1,80 @@
+This test checks hover results for built-in or standard library symbols.
+
+It uses synopsis documentation as full documentation for some of these
+built-ins varies across Go versions, where as it just so happens that the
+synopsis does not.
+
+In the future we may need to limit this test to the latest Go version to avoid
+documentation churn.
+-- settings.json --
+{
+ "hoverKind": "SynopsisDocumentation"
+}
+-- go.mod --
+module mod.com
+
+go 1.18
+-- std.go --
+package std
+
+import (
+ "fmt"
+ "go/types"
+ "sync"
+)
+
+func _() {
+ var err error //@loc(err, "err")
+ fmt.Printf("%v", err) //@def("err", err)
+
+ var _ string //@hover("string", "string", hoverstring)
+ _ = make([]int, 0) //@hover("make", "make", hovermake)
+
+ var mu sync.Mutex
+ mu.Lock() //@hover("Lock", "Lock", hoverLock)
+
+ var typ *types.Named //@hover("types", "types", hoverTypes)
+ typ.Obj().Name() //@hover("Name", "Name", hoverName)
+}
+-- @hoverLock/hover.md --
+```go
+func (*sync.Mutex).Lock()
+```
+
+Lock locks m.
+
+
+[`(sync.Mutex).Lock` on pkg.go.dev](https://pkg.go.dev/sync#Mutex.Lock)
+-- @hoverName/hover.md --
+```go
+func (*types.object).Name() string
+```
+
+Name returns the object's (package-local, unqualified) name.
+
+
+[`(types.TypeName).Name` on pkg.go.dev](https://pkg.go.dev/go/types#TypeName.Name)
+-- @hoverTypes/hover.md --
+```go
+package types ("go/types")
+```
+
+[`types` on pkg.go.dev](https://pkg.go.dev/go/types)
+-- @hovermake/hover.md --
+```go
+func make(t Type, size ...int) Type
+```
+
+The make built-in function allocates and initializes an object of type slice, map, or chan (only).
+
+
+[`make` on pkg.go.dev](https://pkg.go.dev/builtin#make)
+-- @hoverstring/hover.md --
+```go
+type string string
+```
+
+string is the set of all strings of 8-bit bytes, conventionally but not necessarily representing UTF-8-encoded text.
+
+
+[`string` on pkg.go.dev](https://pkg.go.dev/builtin#string)
diff --git a/gopls/internal/regtest/marker/testdata/rename/basic.txt b/gopls/internal/regtest/marker/testdata/rename/basic.txt
new file mode 100644
index 000000000..fe723cf9f
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/rename/basic.txt
@@ -0,0 +1,22 @@
+This test performs basic coverage of 'rename' within a single package.
+
+-- basic.go --
+package p
+
+func f(x int) { println(x) } //@rename("x", y, param_x)
+
+-- @param_x/basic.go --
+package p
+
+func f(y int) { println(y) } //@rename("x", y, param_x)
+
+-- errors.go --
+package p
+
+func _(x []int) { //@renameerr("_", blank, `can't rename "_"`)
+ x = append(x, 1) //@renameerr("append", blank, "built in and cannot be renamed")
+ x = nil //@renameerr("nil", blank, "built in and cannot be renamed")
+ x = nil //@renameerr("x", x, "old and new names are the same: x")
+ _ = 1 //@renameerr("1", x, "no identifier found")
+}
+
diff --git a/gopls/internal/regtest/marker/testdata/rename/conflict.txt b/gopls/internal/regtest/marker/testdata/rename/conflict.txt
new file mode 100644
index 000000000..18438c8a8
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/rename/conflict.txt
@@ -0,0 +1,59 @@
+This test exercises some renaming conflict scenarios
+and ensures that the errors are informative.
+
+-- go.mod --
+module example.com
+go 1.12
+
+-- super/p.go --
+package super
+
+var x int
+
+func f(y int) {
+ println(x)
+ println(y) //@renameerr("y", x, errSuperBlockConflict)
+}
+
+-- @errSuperBlockConflict --
+super/p.go:5:8: renaming this var "y" to "x"
+super/p.go:6:10: would shadow this reference
+super/p.go:3:5: to the var declared here
+-- sub/p.go --
+package sub
+
+var a int
+
+func f2(b int) {
+ println(a) //@renameerr("a", b, errSubBlockConflict)
+ println(b)
+}
+
+-- @errSubBlockConflict --
+sub/p.go:3:5: renaming this var "a" to "b"
+sub/p.go:6:10: would cause this reference to become shadowed
+sub/p.go:5:9: by this intervening var definition
+-- pkgname/p.go --
+package pkgname
+
+import e1 "errors" //@renameerr("e1", errors, errImportConflict)
+import "errors"
+
+var _ = errors.New
+var _ = e1.New
+
+-- @errImportConflict --
+pkgname/p.go:3:8: renaming this imported package name "e1" to "errors"
+pkgname/p.go:4:8: conflicts with imported package name in same block
+-- pkgname2/p1.go --
+package pkgname2
+var x int
+
+-- pkgname2/p2.go --
+package pkgname2
+import "errors" //@renameerr("errors", x, errImportConflict2)
+var _ = errors.New
+
+-- @errImportConflict2 --
+pkgname2/p2.go:2:8: renaming this imported package name "errors" to "x" would conflict
+pkgname2/p1.go:2:5: with this package member var
diff --git a/gopls/internal/regtest/marker/testdata/rename/embed.txt b/gopls/internal/regtest/marker/testdata/rename/embed.txt
new file mode 100644
index 000000000..68cf771bc
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/rename/embed.txt
@@ -0,0 +1,36 @@
+This test exercises renaming of types used as embedded fields.
+
+-- go.mod --
+module example.com
+go 1.12
+
+-- a/a.go --
+package a
+
+type A int //@rename("A", A2, type)
+
+-- b/b.go --
+package b
+
+import "example.com/a"
+
+type B struct { a.A } //@renameerr("A", A3, errAnonField)
+
+var _ = new(B).A //@renameerr("A", A4, errAnonField)
+
+-- @errAnonField --
+can't rename embedded fields: rename the type directly or name the field
+-- @type/a/a.go --
+package a
+
+type A2 int //@rename("A", A2, type)
+
+-- @type/b/b.go --
+package b
+
+import "example.com/a"
+
+type B struct { a.A2 } //@renameerr("A", A3, errAnonField)
+
+var _ = new(B).A2 //@renameerr("A", A4, errAnonField)
+
diff --git a/gopls/internal/regtest/marker/testdata/rename/methods.txt b/gopls/internal/regtest/marker/testdata/rename/methods.txt
new file mode 100644
index 000000000..1bd985bcf
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/rename/methods.txt
@@ -0,0 +1,67 @@
+This test exercises renaming of interface methods.
+
+The golden is currently wrong due to https://github.com/golang/go/issues/58506:
+the reference to B.F in package b should be renamed too.
+
+-- go.mod --
+module example.com
+go 1.12
+
+-- a/a.go --
+package a
+
+type A int
+
+func (A) F() {} //@renameerr("F", G, errAfToG)
+
+-- b/b.go --
+package b
+
+import "example.com/a"
+import "example.com/c"
+
+type B interface { F() } //@rename("F", G, BfToG)
+
+var _ B = a.A(0)
+var _ B = c.C(0)
+
+-- c/c.go --
+package c
+
+type C int
+
+func (C) F() {} //@renameerr("F", G, errCfToG)
+
+-- d/d.go --
+package d
+
+import "example.com/b"
+
+var _ = b.B.F
+
+-- @errAfToG --
+a/a.go:5:10: renaming this method "F" to "G"
+b/b.go:6:6: would make example.com/a.A no longer assignable to interface B
+b/b.go:6:20: (rename example.com/b.B.F if you intend to change both types)
+-- @BfToG/b/b.go --
+package b
+
+import "example.com/a"
+import "example.com/c"
+
+type B interface { G() } //@rename("F", G, BfToG)
+
+var _ B = a.A(0)
+var _ B = c.C(0)
+
+-- @BfToG/d/d.go --
+package d
+
+import "example.com/b"
+
+var _ = b.B.G
+
+-- @errCfToG --
+c/c.go:5:10: renaming this method "F" to "G"
+b/b.go:6:6: would make example.com/c.C no longer assignable to interface B
+b/b.go:6:20: (rename example.com/b.B.F if you intend to change both types)
diff --git a/gopls/internal/regtest/marker/testdata/rename/typeswitch.txt b/gopls/internal/regtest/marker/testdata/rename/typeswitch.txt
new file mode 100644
index 000000000..6743b99ef
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/rename/typeswitch.txt
@@ -0,0 +1,26 @@
+This test covers the special case of renaming a type switch var.
+
+-- p.go --
+package p
+
+func _(x interface{}) {
+ switch y := x.(type) { //@rename("y", z, yToZ)
+ case string:
+ print(y) //@rename("y", z, yToZ)
+ default:
+ print(y) //@rename("y", z, yToZ)
+ }
+}
+
+-- @yToZ/p.go --
+package p
+
+func _(x interface{}) {
+ switch z := x.(type) { //@rename("y", z, yToZ)
+ case string:
+ print(z) //@rename("y", z, yToZ)
+ default:
+ print(z) //@rename("y", z, yToZ)
+ }
+}
+
diff --git a/gopls/internal/regtest/marker/testdata/stubmethods/basic.txt b/gopls/internal/regtest/marker/testdata/stubmethods/basic.txt
new file mode 100644
index 000000000..bb53e6767
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/stubmethods/basic.txt
@@ -0,0 +1,24 @@
+This test exercises basic 'stub methods' functionality.
+
+-- go.mod --
+module example.com
+go 1.12
+
+-- a/a.go --
+package a
+
+type C int
+
+var _ error = C(0) //@suggestedfix(re"C.0.", re"missing method Error", "refactor.rewrite", stub)
+
+-- @stub/a/a.go --
+package a
+
+type C int
+
+// Error implements error
+func (C) Error() string {
+ panic("unimplemented")
+}
+
+var _ error = C(0) //@suggestedfix(re"C.0.", re"missing method Error", "refactor.rewrite", stub)