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"
2024-06-15 16:42:31 +00:00
"git.akyoto.dev/cli/q/src/build/fs"
2024-06-13 10:13:32 +00:00
"git.akyoto.dev/cli/q/src/build/token"
)
// Error is a compiler error at a given line and column.
type Error struct {
2024-06-15 16:42:31 +00:00
Err error
File *fs.File
Stack string
2024-06-30 20:54:59 +00:00
Position int
2024-06-13 10:13:32 +00:00
}
// 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.
2024-06-15 16:42:31 +00:00
func New(err error, file *fs.File, position int) *Error {
return &Error{
Err: err,
File: file,
Position: position,
Stack: Stack(),
2024-06-13 10:13:32 +00:00
}
}
// Error generates the string representation.
func (e *Error) Error() string {
2024-06-15 16:42:31 +00:00
path := e.File.Path
2024-06-13 10:13:32 +00:00
cwd, err := os.Getwd()
if err == nil {
2024-06-15 16:42:31 +00:00
relativePath, err := filepath.Rel(cwd, e.File.Path)
2024-06-13 10:13:32 +00:00
if err == nil {
path = relativePath
}
}
2024-06-15 16:42:31 +00:00
line := 1
column := 1
lineStart := -1
for _, t := range e.File.Tokens {
if t.Position >= e.Position {
column = e.Position - lineStart
break
}
if t.Kind == token.NewLine {
lineStart = t.Position
line++
}
}
return fmt.Sprintf("%s:%d:%d: %s\n\n%s", path, line, column, e.Err, e.Stack)
2024-06-13 10:13:32 +00:00
}
// Unwrap returns the wrapped error.
func (e *Error) Unwrap() error {
return e.Err
}