-
Notifications
You must be signed in to change notification settings - Fork 58
Expand file tree
/
Copy pathtemplate_error.go
More file actions
121 lines (110 loc) · 2.82 KB
/
Copy pathtemplate_error.go
File metadata and controls
121 lines (110 loc) · 2.82 KB
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package plush
import (
"errors"
"fmt"
"strconv"
"strings"
"github.com/gobuffalo/plush/v5/helpers/hctx"
"github.com/gobuffalo/plush/v5/helpers/meta"
)
type TemplateErrorFrame struct {
File string
Line int
}
type TemplateTraceError struct {
Frames []TemplateErrorFrame
Message string
}
func (e *TemplateTraceError) Error() string {
if e == nil {
return ""
}
parts := make([]string, 0, len(e.Frames))
for _, frame := range e.Frames {
if part := templateErrorFrameString(frame); part != "" {
parts = append(parts, part)
}
}
message := strings.TrimSpace(e.Message)
if len(parts) == 0 {
return message
}
if message == "" {
return strings.Join(parts, ":")
}
return strings.Join(parts, ":") + ": " + message
}
func IsTemplateTraceError(err error) bool {
var trace *TemplateTraceError
return errors.As(err, &trace)
}
func WrapPartialRenderError(parentFile string, parentLine int, childFile string, err error) error {
if err == nil {
return nil
}
parent := TemplateErrorFrame{File: parentFile, Line: parentLine}
var trace *TemplateTraceError
if errors.As(err, &trace) {
frames := append([]TemplateErrorFrame{}, parent)
frames = append(frames, trace.Frames...)
return &TemplateTraceError{Frames: compactTemplateErrorFrames(frames), Message: trace.Message}
}
message := strings.TrimSpace(err.Error())
childLine, rest, ok := splitLineErrorPrefix(message)
if ok {
message = rest
}
frames := []TemplateErrorFrame{parent, {File: childFile, Line: childLine}}
return &TemplateTraceError{Frames: compactTemplateErrorFrames(frames), Message: message}
}
func TemplateFilenameForError(ctx hctx.Context) string {
if ctx == nil {
return ""
}
if filename, ok := ctx.Value(meta.TemplateFileKey).(string); ok {
return filename
}
return ""
}
func templateErrorFrameString(frame TemplateErrorFrame) string {
file := strings.TrimSpace(frame.File)
switch {
case file != "" && frame.Line > 0:
return fmt.Sprintf("%s:%d", file, frame.Line)
case file != "":
return file
case frame.Line > 0:
return fmt.Sprintf("line %d", frame.Line)
default:
return ""
}
}
func compactTemplateErrorFrames(frames []TemplateErrorFrame) []TemplateErrorFrame {
if len(frames) == 0 {
return nil
}
out := make([]TemplateErrorFrame, 0, len(frames))
for _, frame := range frames {
if frame.File == "" && frame.Line <= 0 {
continue
}
out = append(out, frame)
}
return out
}
func splitLineErrorPrefix(message string) (int, string, bool) {
message = strings.TrimSpace(message)
if !strings.HasPrefix(message, "line ") {
return 0, message, false
}
rest := strings.TrimPrefix(message, "line ")
colon := strings.Index(rest, ":")
if colon <= 0 {
return 0, message, false
}
line, err := strconv.Atoi(strings.TrimSpace(rest[:colon]))
if err != nil {
return 0, message, false
}
return line, strings.TrimSpace(rest[colon+1:]), true
}