godoc: handle type parameters correctly in LinkifyText

LinkifyText should not generate links to global declarations for
identifiers that are type parameters.

Because the syntactic resolver does not record the declaration for type
parameters declared in the method receiver (see
https://golang.org/issue/50956) a name lookup is used as a workaround.
This is fine here because it is only applied to undeclared indentifiers
and LinkifyText is only ever called on a single declaration at a time,
not on a full AST.

Updates golang/go#50717

Change-Id: I32f2203ce80c060ee18ca8b964a2d5fd80f41957
Reviewed-on: https://go-review.googlesource.com/c/tools/+/382714
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Alessandro Arzilli <alessandro.arzilli@gmail.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Trust: Peter Weinberger <pjw@google.com>
diff --git a/godoc/godoc_test.go b/godoc/godoc_test.go
index 33dbe3f..7f3470e 100644
--- a/godoc/godoc_test.go
+++ b/godoc/godoc_test.go
@@ -10,6 +10,8 @@
 	"go/token"
 	"strings"
 	"testing"
+
+	"golang.org/x/tools/internal/typeparams"
 )
 
 func TestPkgLinkFunc(t *testing.T) {
@@ -368,3 +370,58 @@
 		t.Errorf("filterOutBuildAnnotations should not remove non-build tag comment")
 	}
 }
+
+func TestLinkifyGenerics(t *testing.T) {
+	if !typeparams.Enabled {
+		t.Skip("type params are not enabled at this Go version")
+	}
+
+	got := linkifySource(t, []byte(`
+package foo
+
+type T struct {
+	field *T
+}
+
+type ParametricStruct[T any] struct {
+	field *T
+}
+
+func F1[T any](arg T) { }
+
+func F2(arg T) { }
+
+func (*ParametricStruct[T]) M(arg T) { }
+
+func (*T) M(arg T) { }
+
+type ParametricStruct2[T1, T2 any] struct {
+	a T1
+	b T2
+}
+
+func (*ParametricStruct2[T1, T2]) M(a T1, b T2) { }
+
+
+`))
+
+	want := `type T struct {
+<span id="T.field"></span>field *<a href="#T">T</a>
+}
+type ParametricStruct[T <a href="/pkg/builtin/#any">any</a>] struct {
+<span id="ParametricStruct.field"></span>field *T
+}
+func F1[T <a href="/pkg/builtin/#any">any</a>](arg T) {}
+func F2(arg <a href="#T">T</a>) {}
+func (*<a href="#ParametricStruct">ParametricStruct</a>[T]) M(arg T) {}
+func (*<a href="#T">T</a>) M(arg <a href="#T">T</a>) {}
+type ParametricStruct2[T1, T2 <a href="/pkg/builtin/#any">any</a>] struct {
+<span id="ParametricStruct2.a"></span>a T1
+<span id="ParametricStruct2.b"></span>b T2
+}
+func (*<a href="#ParametricStruct2">ParametricStruct2</a>[T1, T2]) M(a T1, b T2) {}`
+
+	if got != want {
+		t.Errorf("got: %s\n\nwant: %s\n", got, want)
+	}
+}