defers.go 1.1 KB

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