Skip to content

Commit a2be0cd

Browse files
committed
go/analysis/passes/tests: update for generics
Warn about Test functions that contain type parameters. For golang/go#48704 Change-Id: I3f6852613482ec6f33e5650a014564915f11b920 Reviewed-on: https://go-review.googlesource.com/c/tools/+/359494 Run-TryBot: Tim King <[email protected]> gopls-CI: kokoro <[email protected]> TryBot-Result: Go Bot <[email protected]> Trust: Tim King <[email protected]> Reviewed-by: Michael Matloob <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 4d2571b commit a2be0cd

File tree

4 files changed

+48
-3
lines changed

4 files changed

+48
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package typeparams
6+
7+
func Zero[T any]() T {
8+
var zero T
9+
return zero
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package typeparams
6+
7+
import "testing"
8+
9+
func Test(*testing.T) {
10+
_ = Zero[int]() // It is fine to use generics within tests.
11+
}
12+
13+
// Note: We format {Test,Benchmark}typeParam with a 't' in "type" to avoid an error from
14+
// cmd/go/internal/load. That package can also give an error about Test and Benchmark
15+
// functions with TypeParameters. These tests may need to be updated if that logic changes.
16+
func TesttypeParam[T any](*testing.T) {} // want "TesttypeParam has type parameters: it will not be run by go test as a TestXXX function" "TesttypeParam has malformed name"
17+
func BenchmarktypeParam[T any](*testing.B) {} // want "BenchmarktypeParam has type parameters: it will not be run by go test as a BenchmarkXXX function" "BenchmarktypeParam has malformed name"
18+
19+
func ExampleZero[T any]() { // want "ExampleZero should not have type params"
20+
print(Zero[T]())
21+
}

Diff for: go/analysis/passes/tests/tests.go

+10
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"unicode/utf8"
1717

1818
"golang.org/x/tools/go/analysis"
19+
"golang.org/x/tools/internal/typeparams"
1920
)
2021

2122
const Doc = `check for common mistaken usages of tests and examples
@@ -170,6 +171,9 @@ func checkExampleName(pass *analysis.Pass, fn *ast.FuncDecl) {
170171
if results := fn.Type.Results; results != nil && len(results.List) != 0 {
171172
pass.Reportf(fn.Pos(), "%s should return nothing", fnName)
172173
}
174+
if tparams := typeparams.ForFuncType(fn.Type); tparams != nil && len(tparams.List) > 0 {
175+
pass.Reportf(fn.Pos(), "%s should not have type params", fnName)
176+
}
173177

174178
if fnName == "Example" {
175179
// Nothing more to do.
@@ -236,6 +240,12 @@ func checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) {
236240
return
237241
}
238242

243+
if tparams := typeparams.ForFuncType(fn.Type); tparams != nil && len(tparams.List) > 0 {
244+
// Note: cmd/go/internal/load also errors about TestXXX and BenchmarkXXX functions with type parameters.
245+
// We have currently decided to also warn before compilation/package loading. This can help users in IDEs.
246+
pass.Reportf(fn.Pos(), "%s has type parameters: it will not be run by go test as a %sXXX function", fn.Name.Name, prefix)
247+
}
248+
239249
if !isTestSuffix(fn.Name.Name[len(prefix):]) {
240250
pass.Reportf(fn.Pos(), "%s has malformed name: first letter after '%s' must not be lowercase", fn.Name.Name, prefix)
241251
}

Diff for: go/analysis/passes/tests/tests_test.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@ import (
99

1010
"golang.org/x/tools/go/analysis/analysistest"
1111
"golang.org/x/tools/go/analysis/passes/tests"
12+
"golang.org/x/tools/internal/typeparams"
1213
)
1314

1415
func Test(t *testing.T) {
1516
testdata := analysistest.TestData()
16-
17-
analysistest.Run(t, testdata, tests.Analyzer,
17+
pkgs := []string{
1818
"a", // loads "a", "a [a.test]", and "a.test"
1919
"b_x_test", // loads "b" and "b_x_test"
2020
"divergent",
21-
)
21+
}
22+
if typeparams.Enabled {
23+
pkgs = append(pkgs, "typeparams")
24+
}
25+
analysistest.Run(t, testdata, tests.Analyzer, pkgs...)
2226
}

0 commit comments

Comments
 (0)