68 lines
1.3 KiB
Go

package errors
import (
"fmt"
"os"
"path/filepath"
"git.akyoto.dev/cli/q/src/build/fs"
"git.akyoto.dev/cli/q/src/build/token"
)
// Error is a compiler error at a given line and column.
type Error struct {
Err error
File *fs.File
Position int
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, file *fs.File, position int) *Error {
return &Error{
Err: err,
File: file,
Position: position,
Stack: Stack(),
}
}
// Error generates the string representation.
func (e *Error) Error() string {
path := e.File.Path
cwd, err := os.Getwd()
if err == nil {
relativePath, err := filepath.Rel(cwd, e.File.Path)
if err == nil {
path = relativePath
}
}
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)
}
// Unwrap returns the wrapped error.
func (e *Error) Unwrap() error {
return e.Err
}