Functions
forEachLastStmt
function
#
forEachLastStmt calls onLast on each "last" statement in a list of statements.
"Last" is defined recursively so, for example, if the last statement is
a switch statement, then each switch case is also visited to examine
its last statements.
func forEachLastStmt(stmts []ast.Stmt, onLast func(last ast.Stmt))
goInvoke
function
#
goInvoke returns a function expression that would be called asynchronously
(but not awaited) in another goroutine as a consequence of the call.
For example, given the g.Go call below, it returns the function literal expression.
import "sync/errgroup"
var g errgroup.Group
g.Go(func() error { ... })
Currently only "golang.org/x/sync/errgroup.Group()" is considered.
func goInvoke(info *types.Info, call *ast.CallExpr) ast.Expr
isMethodCall
function
#
isMethodCall reports whether expr is a method call of
...
func isMethodCall(info *types.Info, expr ast.Expr, pkgPath string, typeName string, method string) bool
litStmts
function
#
litStmts returns all statements from the function body of a function
literal.
If fun is not a function literal, it returns nil.
func litStmts(fun ast.Expr) []ast.Stmt
parallelSubtest
function
#
parallelSubtest returns statements that can be easily proven to execute
concurrently via the go test runner, as t.Run has been invoked with a
function literal that calls t.Parallel.
In practice, users rely on the fact that statements before the call to
t.Parallel are synchronous. For example by declaring test := test inside the
function literal, but before the call to t.Parallel.
Therefore, we only flag references in statements that are obviously
dominated by a call to t.Parallel. As a simple heuristic, we only consider
statements following the final labeled statement in the function body, to
avoid scenarios where a jump would cause either the call to t.Parallel or
the problematic reference to be skipped.
import "testing"
func TestFoo(t *testing.T) {
tests := []int{0, 1, 2}
for i, test := range tests {
t.Run("subtest", func(t *testing.T) {
println(i, test) // OK
t.Parallel()
println(i, test) // Not OK
})
}
}
func parallelSubtest(info *types.Info, call *ast.CallExpr) []ast.Stmt
reportCaptured
function
#
reportCaptured reports a diagnostic stating a loop variable
has been captured by a func literal if checkStmt has escaping
references to vars. vars is expected to be variables updated by a loop statement,
and checkStmt is expected to be a statements from the body of a func literal in the loop.
func reportCaptured(pass *analysis.Pass, vars []types.Object, checkStmt ast.Stmt)
run
function
#
func run(pass *analysis.Pass) (interface{}, error)
unlabel
function
#
unlabel returns the inner statement for the possibly labeled statement stmt,
stripping any (possibly nested) *ast.LabeledStmt wrapper.
The second result reports whether stmt was an *ast.LabeledStmt.
func unlabel(stmt ast.Stmt) (ast.Stmt, bool)