goparse/errors.go

63 lines
1.6 KiB
Go
Raw Normal View History

2024-07-28 00:16:36 -06:00
package parse
import "fmt"
// Error is an error that contains positional information.
type Error interface {
error
Position () Position
}
type errInternal struct {
position Position
message string
}
var _ Error = new(errInternal)
func (err *errInternal) Error () string {
return err.String()
}
func (err *errInternal) String () string {
return err.message
}
func (err *errInternal) Position () Position {
return err.position
}
// Errorf produces an error with a fmt'd message.
func Errorf (position Position, format string, variables ...any) Error {
return &errInternal {
position: position,
message: fmt.Sprintf(format, variables...),
}
}
// Format returns a formatted string representing an error. This string may take
// up multiple lines and contain ANSI escape codes. If err does not fulfill the
// Error interface, err.Error() is returned instead.
//
// When the error fulfills the Error interface, the formatted output will
// be of the general form:
// FILE:ROW+1:START+1: MESSAGE
// ROW+1 | LINE
// ^^^^
// Where the position of the underline (^^^^) corresponds to the start and end
// fields in the error's position. Note that the row and column numbers as
// displayed are increased by one from their normal zero-indexed state, because
// most editors display row and column numbers starting at 1:1. Additionally,
// because normal error messages do not produce trailing line breaks, neither
// does this function.
func Format (err error) string {
if e, ok := err.(Error); ok {
return fmt.Sprintf (
"%v: %v\n%v",
e.Position(),
e.Error(),
e.Position().Format())
} else {
return err.Error()
}
}