getFuncAST gets the callee site function AST representation for the code inside the function f at line l.
(f string, l int)
| 114 | // getFuncAST gets the callee site function AST representation for the code |
| 115 | // inside the function f at line l. |
| 116 | func (p *parsedFile) getFuncAST(f string, l int) (d *ast.FuncDecl, err error) { |
| 117 | if len(p.lineToByteOffset) <= l { |
| 118 | // The line number in the stack trace line does not exist in the file. That |
| 119 | // can only mean that the sources on disk do not match the sources used to |
| 120 | // build the binary. |
| 121 | return nil, fmt.Errorf("line %d is over line count of %d", l, len(p.lineToByteOffset)-1) |
| 122 | } |
| 123 | |
| 124 | // Walk the AST to find the lineToByteOffset that fits the line number. |
| 125 | var lastFunc *ast.FuncDecl |
| 126 | // Inspect() goes depth first. This means for example that a function like: |
| 127 | // func a() { |
| 128 | // b := func() {} |
| 129 | // c() |
| 130 | // } |
| 131 | // |
| 132 | // Were we are looking at the c() call can return confused values. It is |
| 133 | // important to look at the actual ast.Node hierarchy. |
| 134 | ast.Inspect(p.parsed, func(n ast.Node) bool { |
| 135 | if d != nil { |
| 136 | return false |
| 137 | } |
| 138 | if n == nil { |
| 139 | return true |
| 140 | } |
| 141 | if int(n.Pos()) >= p.lineToByteOffset[l] { |
| 142 | // We are expecting a ast.CallExpr node. It can be harder to figure out |
| 143 | // when there are multiple calls on a single line, as the stack trace |
| 144 | // doesn't have file byte offset information, only line based. |
| 145 | // gofmt will always format to one function call per line but there can |
| 146 | // be edge cases, like: |
| 147 | // a = A{Foo(), Bar()} |
| 148 | d = lastFunc |
| 149 | //p.processNode(call, n) |
| 150 | return false |
| 151 | } else if f, ok := n.(*ast.FuncDecl); ok { |
| 152 | lastFunc = f |
| 153 | } |
| 154 | return true |
| 155 | }) |
| 156 | return |
| 157 | } |
| 158 | |
| 159 | func name(n ast.Node) string { |
| 160 | switch t := n.(type) { |