-
Notifications
You must be signed in to change notification settings - Fork 153
/
errors.go
100 lines (90 loc) · 2.39 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
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
package ast
import (
"bytes"
"fmt"
"io"
"strconv"
)
// Check will inspect each node and annotate it with any AST errors.
// It will return the number of errors that were found.
func Check(root Node) int {
v := errorVisitor{}
Walk(&v, root)
return v.count
}
// check will inspect a single node and annotate it with any AST errors.
// For convenience, it returns the number of errors that were identified.
func check(n Node) int {
// TODO(jsternberg): Fill in the details for how we retrieve errors.
switch n := n.(type) {
case *BadStatement:
loc := n.Location()
// TODO(nathanielc): Remove the location information from the error message once we have a way to report the location information as part of the errors.
n.Errors = append(n.Errors, Error{
Msg: fmt.Sprintf("invalid statement %s@%d:%d-%d:%d: %s", loc.File, loc.Start.Line, loc.Start.Column, loc.End.Line, loc.End.Column, n.Text),
})
return len(n.Errors)
case *PipeExpression:
if n.Call == nil {
n.Errors = append(n.Errors, Error{
Msg: "pipe destination is missing",
})
}
}
return 0
}
// GetError will return the first error within an AST.
func GetError(n Node) error {
errs := GetErrors(n)
if len(errs) == 0 {
return nil
}
return errs[0]
}
// GetErrors will return each of the errors within an AST.
func GetErrors(n Node) (errs []error) {
Walk(CreateVisitor(func(node Node) {
if nerrs := node.Errs(); len(nerrs) > 0 {
for _, err := range nerrs {
errs = append(errs, err)
}
}
}), n)
return errs
}
// PrintErrors will format the errors within the AST and output them
// to the writer.
func PrintErrors(w io.Writer, root Node) {
var buf bytes.Buffer
Walk(CreateVisitor(func(node Node) {
if errs := node.Errs(); len(errs) > 0 {
loc := node.Location()
for _, err := range errs {
buf.WriteString("error")
if loc.Start.Line > 0 {
buf.WriteByte(':')
buf.WriteString(strconv.FormatInt(int64(loc.Start.Line), 10))
}
if loc.Start.Column > 0 {
if buf.Len() > 0 {
buf.WriteByte(':')
}
buf.WriteString(strconv.FormatInt(int64(loc.Start.Column), 10))
}
buf.WriteString(": ")
buf.WriteString(err.Msg)
buf.WriteByte('\n')
_, _ = w.Write(buf.Bytes())
buf.Reset()
}
}
}), root)
}
type errorVisitor struct {
count int
}
func (ev *errorVisitor) Visit(n Node) Visitor {
ev.count += check(n)
return ev
}
func (ev *errorVisitor) Done(n Node) {}