package source import ( "fmt" "go/ast" "go/token" ) func scanToDeferLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node { var matchedNode ast.Node ast.Inspect(node, func(node ast.Node) bool { switch { case node == nil || matchedNode != nil: return false case fileset.Position(node.End()).Line == lineNum: if funcLit, ok := node.(*ast.FuncLit); ok { matchedNode = funcLit return false } } return true }) debug("defer line node: %s", debugFormatNode{matchedNode}) return matchedNode } func guessDefer(node ast.Node) (ast.Node, error) { defers := collectDefers(node) switch len(defers) { case 0: return nil, fmt.Errorf("failed to find expression in defer") case 1: return defers[0].Call, nil default: return nil, fmt.Errorf( "ambiguous call expression: multiple (%d) defers in call block", len(defers)) } } func collectDefers(node ast.Node) []*ast.DeferStmt { var defers []*ast.DeferStmt ast.Inspect(node, func(node ast.Node) bool { if d, ok := node.(*ast.DeferStmt); ok { defers = append(defers, d) debug("defer: %s", debugFormatNode{d}) return false } return true }) return defers }