Skip to content

Commit

Permalink
go/analysis/passes/testinggoroutine: update for generics
Browse files Browse the repository at this point in the history
Update the testinggoroutine analyzer to find bad calls via instantiated
function calls.

For golang/go#48704

Change-Id: I39ef43090a0e5dd04dfe094376517ac25441ad27
Reviewed-on: https://go-review.googlesource.com/c/tools/+/359401
Trust: Robert Findley <rfindley@google.com>
Trust: Zvonimir Pavlinovic <zpavlinovic@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
  • Loading branch information
findleyr committed Oct 29, 2021
1 parent 96715ad commit 4d2571b
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2021 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 typeparams

import (
"testing"
)

func f[P any](t *testing.T) {
t.Fatal("failed")
}

func TestBadFatalf[P any](t *testing.T) {
go f[int](t) // want "call to .+T.+Fatal from a non-test goroutine"
}
23 changes: 19 additions & 4 deletions go/analysis/passes/testinggoroutine/testinggoroutine.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
"golang.org/x/tools/go/ast/inspector"
"golang.org/x/tools/internal/typeparams"
)

const Doc = `report calls to (*testing.T).Fatal from goroutines started by a test.
Expand Down Expand Up @@ -124,16 +125,30 @@ func typeIsTestingDotTOrB(expr ast.Expr) (string, bool) {
// function literals declared in the same function, and
// static calls within the same package are supported.
func goStmtFun(goStmt *ast.GoStmt) ast.Node {
switch goStmt.Call.Fun.(type) {
case *ast.Ident:
id := goStmt.Call.Fun.(*ast.Ident)
// TODO(cuonglm): improve this once golang/go#48141 resolved.
switch fun := goStmt.Call.Fun.(type) {
case *ast.IndexExpr, *typeparams.IndexListExpr:
ix := typeparams.GetIndexExprData(fun)
if ix == nil {
break
}
id, _ := ix.X.(*ast.Ident)
if id == nil {
break
}
if id.Obj == nil {
break
}
if funDecl, ok := id.Obj.Decl.(ast.Node); ok {
return funDecl
}
case *ast.Ident:
// TODO(cuonglm): improve this once golang/go#48141 resolved.
if fun.Obj == nil {
break
}
if funDecl, ok := fun.Obj.Decl.(ast.Node); ok {
return funDecl
}
case *ast.FuncLit:
return goStmt.Call.Fun
}
Expand Down
7 changes: 6 additions & 1 deletion go/analysis/passes/testinggoroutine/testinggoroutine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ import (

"golang.org/x/tools/go/analysis/analysistest"
"golang.org/x/tools/go/analysis/passes/testinggoroutine"
"golang.org/x/tools/internal/typeparams"
)

func Test(t *testing.T) {
testdata := analysistest.TestData()
analysistest.Run(t, testdata, testinggoroutine.Analyzer, "a")
pkgs := []string{"a"}
if typeparams.Enabled {
pkgs = append(pkgs, "typeparams")
}
analysistest.Run(t, testdata, testinggoroutine.Analyzer, pkgs...)
}

0 comments on commit 4d2571b

Please sign in to comment.