...
1 package source
2
3 import (
4 "fmt"
5 "go/ast"
6 "go/token"
7 )
8
9 func scanToDeferLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node {
10 var matchedNode ast.Node
11 ast.Inspect(node, func(node ast.Node) bool {
12 switch {
13 case node == nil || matchedNode != nil:
14 return false
15 case fileset.Position(node.End()).Line == lineNum:
16 if funcLit, ok := node.(*ast.FuncLit); ok {
17 matchedNode = funcLit
18 return false
19 }
20 }
21 return true
22 })
23 debug("defer line node: %s", debugFormatNode{matchedNode})
24 return matchedNode
25 }
26
27 func guessDefer(node ast.Node) (ast.Node, error) {
28 defers := collectDefers(node)
29 switch len(defers) {
30 case 0:
31 return nil, fmt.Errorf("failed to find expression in defer")
32 case 1:
33 return defers[0].Call, nil
34 default:
35 return nil, fmt.Errorf(
36 "ambiguous call expression: multiple (%d) defers in call block",
37 len(defers))
38 }
39 }
40
41 func collectDefers(node ast.Node) []*ast.DeferStmt {
42 var defers []*ast.DeferStmt
43 ast.Inspect(node, func(node ast.Node) bool {
44 if d, ok := node.(*ast.DeferStmt); ok {
45 defers = append(defers, d)
46 debug("defer: %s", debugFormatNode{d})
47 return false
48 }
49 return true
50 })
51 return defers
52 }
53
View as plain text