loopclosure

Imports

Imports #

_ "embed"
"go/ast"
"go/types"
"golang.org/x/tools/go/analysis"
"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/go/types/typeutil"
"golang.org/x/tools/internal/typesinternal"
"golang.org/x/tools/internal/versions"

Constants & Variables

Analyzer var #

var Analyzer = *ast.UnaryExpr

doc var #

go:embed doc.go

var doc string

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)

Generated with Arrow