-
Notifications
You must be signed in to change notification settings - Fork 9
/
errors.go
68 lines (56 loc) · 1.59 KB
/
errors.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// Copyright 2022 Namespace Labs Inc; All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
package fncue
import (
"fmt"
"cuelang.org/go/cue/errors"
"namespacelabs.dev/foundation/framework/rpcerrors/multierr"
)
// Wraps a Cue error to include error location information in the error message.
// Also supports Cue list-errors which are translated into multierr.Error.
func WrapCueError(e error, absPath func(string) string) error {
cueE, ok := e.(errors.Error)
if !ok {
// Pass non-Cue errors as-is.
return e
}
// Deduplicate.
sanitized := errors.Sanitize(cueE)
list := errors.Errors(sanitized)
errs := []error{}
for _, e := range list {
errs = append(errs, cueError{cueE: e, absPath: absPath})
}
if len(errs) == 1 {
return errs[0]
}
return multierr.New(errs...)
}
type cueError struct {
cueE errors.Error
absPath func(string) string
}
// Implements fnerrors.Location.
func (e cueError) ErrorLocation() string {
pos := e.cueE.Position()
if !pos.IsValid() {
// If we don't have any position information,
// just pass through the underlying message.
return e.cueE.Error()
}
return fmt.Sprintf("%s:%d:%d", e.absPath(pos.Filename()), pos.Line(), pos.Column())
}
// Implements error.
func (e cueError) Error() string {
loc := e.ErrorLocation()
if loc == "" {
return e.cueE.Error()
}
// See also [errors.Print] for examples on how to handle positions.
return fmt.Sprintf("%s: %s", loc, e.cueE.Error())
}
// Implements error.
func (e cueError) Unwrap() error {
return e.cueE
}