mirror of
https://github.com/hanzoai/expr.git
synced 2026-09-24 16:58:58 +00:00
86 lines
1.5 KiB
Go
86 lines
1.5 KiB
Go
package file
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type Error struct {
|
|
Location
|
|
Line int `json:"line"`
|
|
Column int `json:"column"`
|
|
Message string `json:"message"`
|
|
Snippet string `json:"snippet"`
|
|
Prev error `json:"prev"`
|
|
}
|
|
|
|
func (e *Error) Error() string {
|
|
return e.format()
|
|
}
|
|
|
|
var tabReplacer = strings.NewReplacer("\t", " ")
|
|
|
|
func (e *Error) Bind(source Source) *Error {
|
|
src := source.String()
|
|
|
|
var runeCount, lineStart int
|
|
e.Line = 1
|
|
e.Column = 0
|
|
for i, r := range src {
|
|
if runeCount == e.From {
|
|
break
|
|
}
|
|
if r == '\n' {
|
|
lineStart = i + 1
|
|
e.Line++
|
|
e.Column = 0
|
|
} else {
|
|
e.Column++
|
|
}
|
|
runeCount++
|
|
}
|
|
|
|
lineEnd := lineStart + strings.IndexByte(src[lineStart:], '\n')
|
|
if lineEnd < lineStart {
|
|
lineEnd = len(src)
|
|
}
|
|
if lineStart == lineEnd {
|
|
return e
|
|
}
|
|
|
|
const prefix = "\n | "
|
|
line := src[lineStart:lineEnd]
|
|
snippet := new(strings.Builder)
|
|
snippet.Grow(2*len(prefix) + len(line) + e.Column + 1)
|
|
snippet.WriteString(prefix)
|
|
tabReplacer.WriteString(snippet, line)
|
|
snippet.WriteString(prefix)
|
|
for i := 0; i < e.Column; i++ {
|
|
snippet.WriteByte('.')
|
|
}
|
|
snippet.WriteByte('^')
|
|
e.Snippet = snippet.String()
|
|
return e
|
|
}
|
|
|
|
func (e *Error) Unwrap() error {
|
|
return e.Prev
|
|
}
|
|
|
|
func (e *Error) Wrap(err error) {
|
|
e.Prev = err
|
|
}
|
|
|
|
func (e *Error) format() string {
|
|
if e.Snippet == "" {
|
|
return e.Message
|
|
}
|
|
return fmt.Sprintf(
|
|
"%s (%d:%d)%s",
|
|
e.Message,
|
|
e.Line,
|
|
e.Column+1, // add one to the 0-based column for display
|
|
e.Snippet,
|
|
)
|
|
}
|