68 lines
1.3 KiB
Go
Raw Normal View History

2024-06-13 10:13:32 +00:00
package errors
import (
"fmt"
"os"
"path/filepath"
"git.akyoto.dev/cli/q/src/build/token"
)
// Error is a compiler error at a given line and column.
type Error struct {
Path string
Line int
Column int
Err error
Stack string
}
// New generates an error message at the current token position.
// The error message is clickable in popular editors and leads you
// directly to the faulty file at the given line and position.
func New(err error, path string, tokens []token.Token, cursor int) *Error {
var (
lineCount = 1
lineStart = -1
)
for i := range cursor {
if tokens[i].Kind == token.NewLine {
lineCount++
lineStart = int(tokens[i].Position)
}
}
var column int
if cursor < len(tokens) {
column = tokens[cursor].Position - lineStart
} else {
lastToken := tokens[len(tokens)-1]
column = lastToken.Position - lineStart + len(lastToken.Text())
}
return &Error{path, lineCount, column, err, Stack()}
}
// Error generates the string representation.
func (e *Error) Error() string {
path := e.Path
cwd, err := os.Getwd()
if err == nil {
relativePath, err := filepath.Rel(cwd, e.Path)
if err == nil {
path = relativePath
}
}
return fmt.Sprintf("%s:%d:%d: %s\n\n%s", path, e.Line, e.Column, e.Err, e.Stack)
}
// Unwrap returns the wrapped error.
func (e *Error) Unwrap() error {
return e.Err
}