|
@@ -1,9 +1,10 @@
|
|
|
package errors
|
|
package errors
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
|
+ "bufio"
|
|
|
"bytes"
|
|
"bytes"
|
|
|
"fmt"
|
|
"fmt"
|
|
|
- "io/ioutil"
|
|
|
|
|
|
|
+ "os"
|
|
|
"runtime"
|
|
"runtime"
|
|
|
"strings"
|
|
"strings"
|
|
|
)
|
|
)
|
|
@@ -62,18 +63,29 @@ func (frame *StackFrame) String() string {
|
|
|
|
|
|
|
|
// SourceLine gets the line of code (from File and Line) of the original source if possible.
|
|
// SourceLine gets the line of code (from File and Line) of the original source if possible.
|
|
|
func (frame *StackFrame) SourceLine() (string, error) {
|
|
func (frame *StackFrame) SourceLine() (string, error) {
|
|
|
- data, err := ioutil.ReadFile(frame.File)
|
|
|
|
|
|
|
+ if frame.LineNumber <= 0 {
|
|
|
|
|
+ return "???", nil
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ file, err := os.Open(frame.File)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return "", New(err)
|
|
return "", New(err)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- lines := bytes.Split(data, []byte{'\n'})
|
|
|
|
|
- if frame.LineNumber <= 0 || frame.LineNumber >= len(lines) {
|
|
|
|
|
- return "???", nil
|
|
|
|
|
|
|
+ defer file.Close()
|
|
|
|
|
+
|
|
|
|
|
+ scanner := bufio.NewScanner(file)
|
|
|
|
|
+ currentLine := 1
|
|
|
|
|
+ for scanner.Scan() {
|
|
|
|
|
+ if currentLine == frame.LineNumber {
|
|
|
|
|
+ return string(bytes.Trim(scanner.Bytes(), " \t")), nil
|
|
|
|
|
+ }
|
|
|
|
|
+ currentLine++
|
|
|
}
|
|
}
|
|
|
- // -1 because line-numbers are 1 based, but our array is 0 based
|
|
|
|
|
- return string(bytes.Trim(lines[frame.LineNumber-1], " \t")), nil
|
|
|
|
|
|
|
+ if err := scanner.Err(); err != nil {
|
|
|
|
|
+ return "", New(err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return "???", nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func packageAndName(fn *runtime.Func) (string, string) {
|
|
func packageAndName(fn *runtime.Func) (string, string) {
|