|
5 | 5 | package godoc
|
6 | 6 |
|
7 | 7 | import (
|
| 8 | + "go/doc" |
8 | 9 | "net/http"
|
9 | 10 | "net/http/httptest"
|
10 | 11 | "net/url"
|
| 12 | + "sort" |
11 | 13 | "strings"
|
12 | 14 | "testing"
|
13 | 15 | "text/template"
|
14 | 16 |
|
15 | 17 | "golang.org/x/tools/godoc/vfs/mapfs"
|
| 18 | + "golang.org/x/tools/internal/typeparams" |
16 | 19 | )
|
17 | 20 |
|
18 | 21 | // TestIgnoredGoFiles tests the scenario where a folder has no .go or .c files,
|
@@ -128,3 +131,115 @@ func TestMarkdown(t *testing.T) {
|
128 | 131 | testServeBody(t, p, "/doc/test.html", "<strong>bold</strong>")
|
129 | 132 | testServeBody(t, p, "/doc/test2.html", "<em>template</em>")
|
130 | 133 | }
|
| 134 | + |
| 135 | +func TestGenerics(t *testing.T) { |
| 136 | + if !typeparams.Enabled { |
| 137 | + t.Skip("type params are not enabled at this Go version") |
| 138 | + } |
| 139 | + |
| 140 | + c := NewCorpus(mapfs.New(map[string]string{ |
| 141 | + "blah/blah.go": `package blah |
| 142 | +
|
| 143 | +var A AStruct[int] |
| 144 | +
|
| 145 | +type AStruct[T any] struct { |
| 146 | + A string |
| 147 | + X T |
| 148 | +} |
| 149 | +
|
| 150 | +func (a *AStruct[T]) Method() T { |
| 151 | + return a.X |
| 152 | +} |
| 153 | +
|
| 154 | +func (a AStruct[T]) NonPointerMethod() T { |
| 155 | + return a.X |
| 156 | +} |
| 157 | +
|
| 158 | +func NewAStruct[T any](arg T) *AStruct[T] { |
| 159 | + return &AStruct[T]{ X: arg } |
| 160 | +} |
| 161 | +
|
| 162 | +type NonGenericStruct struct { |
| 163 | + B int |
| 164 | +} |
| 165 | +
|
| 166 | +func (b *NonGenericStruct) NonGenericMethod() int { |
| 167 | + return b.B |
| 168 | +} |
| 169 | +
|
| 170 | +func NewNonGenericStruct(arg int) *NonGenericStruct { |
| 171 | + return &NonGenericStruct{arg} |
| 172 | +} |
| 173 | +
|
| 174 | +type Pair[K, V any] struct { |
| 175 | + K K |
| 176 | + V V |
| 177 | +} |
| 178 | +
|
| 179 | +func (p Pair[K, V]) Apply(kf func(K) K, vf func(V) V) Pair[K, V] { |
| 180 | + return &Pair{ K: kf(p.K), V: vf(p.V) } |
| 181 | +} |
| 182 | +
|
| 183 | +func (p *Pair[K, V]) Set(k K, v V) { |
| 184 | + p.K = k |
| 185 | + p.V = v |
| 186 | +} |
| 187 | +
|
| 188 | +func NewPair[K, V any](k K, v V) Pair[K, V] { |
| 189 | + return Pair[K, V]{ k, v } |
| 190 | +} |
| 191 | +`})) |
| 192 | + |
| 193 | + srv := &handlerServer{ |
| 194 | + p: &Presentation{ |
| 195 | + Corpus: c, |
| 196 | + }, |
| 197 | + c: c, |
| 198 | + } |
| 199 | + pInfo := srv.GetPageInfo("/blah/", "", NoFiltering, "linux", "amd64") |
| 200 | + t.Logf("%v\n", pInfo) |
| 201 | + |
| 202 | + findType := func(name string) *doc.Type { |
| 203 | + for _, typ := range pInfo.PDoc.Types { |
| 204 | + if typ.Name == name { |
| 205 | + return typ |
| 206 | + } |
| 207 | + } |
| 208 | + return nil |
| 209 | + } |
| 210 | + |
| 211 | + assertFuncs := func(typ *doc.Type, typFuncs []*doc.Func, funcs ...string) { |
| 212 | + typfuncs := make([]string, len(typFuncs)) |
| 213 | + for i := range typFuncs { |
| 214 | + typfuncs[i] = typFuncs[i].Name |
| 215 | + } |
| 216 | + sort.Strings(typfuncs) |
| 217 | + sort.Strings(funcs) |
| 218 | + if len(typfuncs) != len(funcs) { |
| 219 | + t.Errorf("function mismatch for type %q, got: %q, want: %q", typ.Name, typfuncs, funcs) |
| 220 | + return |
| 221 | + } |
| 222 | + for i := range funcs { |
| 223 | + if funcs[i] != typfuncs[i] { |
| 224 | + t.Errorf("function mismatch for type %q: got: %q, want: %q", typ.Name, typfuncs, funcs) |
| 225 | + return |
| 226 | + } |
| 227 | + } |
| 228 | + } |
| 229 | + |
| 230 | + aStructType := findType("AStruct") |
| 231 | + assertFuncs(aStructType, aStructType.Funcs, "NewAStruct") |
| 232 | + assertFuncs(aStructType, aStructType.Methods, "Method", "NonPointerMethod") |
| 233 | + |
| 234 | + nonGenericStructType := findType("NonGenericStruct") |
| 235 | + assertFuncs(nonGenericStructType, nonGenericStructType.Funcs, "NewNonGenericStruct") |
| 236 | + assertFuncs(nonGenericStructType, nonGenericStructType.Methods, "NonGenericMethod") |
| 237 | + |
| 238 | + pairType := findType("Pair") |
| 239 | + assertFuncs(pairType, pairType.Funcs, "NewPair") |
| 240 | + assertFuncs(pairType, pairType.Methods, "Apply", "Set") |
| 241 | + |
| 242 | + if len(pInfo.PDoc.Funcs) > 0 { |
| 243 | + t.Errorf("unexpected functions in package documentation") |
| 244 | + } |
| 245 | +} |
0 commit comments