Skip to content

Commit

Permalink
Add Position.Col
Browse files Browse the repository at this point in the history
Previously it wasn't easy for users to get the Column information; this
has to be calculated from the Start field, but this isn't convenient.
  • Loading branch information
arp242 committed May 26, 2024
1 parent 5bcf186 commit 12b7e31
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 31 deletions.
5 changes: 3 additions & 2 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -540,12 +540,13 @@ func (md *MetaData) badtype(dst string, data any) error {

func (md *MetaData) parseErr(err error) error {
k := md.context.String()
d := string(md.data)
return ParseError{
LastKey: k,
Position: md.keyInfo[k].pos,
Position: md.keyInfo[k].pos.withCol(d),
Line: md.keyInfo[k].pos.Line,
err: err,
input: string(md.data),
input: d,
}
}

Expand Down
46 changes: 24 additions & 22 deletions error.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,28 @@ type ParseError struct {
// Position of an error.
type Position struct {
Line int // Line number, starting at 1.
Col int // Error column, starting at 1.
Start int // Start of error, as byte offset starting at 0.
Len int // Lenght in bytes.
Len int // Lenght of the error in bytes.
}

func (p Position) withCol(tomlFile string) Position {
var (
pos int
lines = strings.Split(tomlFile, "\n")
)
for i := range lines {
ll := len(lines[i]) + 1 // +1 for the removed newline
if pos+ll >= p.Start {
p.Col = p.Start - pos + 1
if p.Col < 1 { // Should never happen, but just in case.
p.Col = 1
}
break
}
pos += ll
}
return p
}

func (pe ParseError) Error() string {
Expand All @@ -94,7 +114,6 @@ func (pe ParseError) ErrorWithPosition() string {

var (
lines = strings.Split(pe.input, "\n")
col = pe.column(lines)
b = new(strings.Builder)
)

Expand All @@ -108,10 +127,10 @@ func (pe ParseError) ErrorWithPosition() string {

if pe.Position.Len == 1 {
fmt.Fprintf(b, "toml: error: %s\n\nAt line %d, column %d:\n\n",
msg, pe.Position.Line, col+1)
msg, pe.Position.Line, pe.Position.Col)
} else {
fmt.Fprintf(b, "toml: error: %s\n\nAt line %d, column %d-%d:\n\n",
msg, pe.Position.Line, col, col+pe.Position.Len)
msg, pe.Position.Line, pe.Position.Col, pe.Position.Col+pe.Position.Len-1)
}
if pe.Position.Line > 2 {
fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-2, expandTab(lines[pe.Position.Line-3]))
Expand All @@ -129,7 +148,7 @@ func (pe ParseError) ErrorWithPosition() string {
diff := len(expanded) - len(lines[pe.Position.Line-1])

fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line, expanded)
fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", col+diff), strings.Repeat("^", pe.Position.Len))
fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", pe.Position.Col-1+diff), strings.Repeat("^", pe.Position.Len))
return b.String()
}

Expand All @@ -151,23 +170,6 @@ func (pe ParseError) ErrorWithUsage() string {
return m
}

func (pe ParseError) column(lines []string) int {
var pos, col int
for i := range lines {
ll := len(lines[i]) + 1 // +1 for the removed newline
if pos+ll >= pe.Position.Start {
col = pe.Position.Start - pos
if col < 0 { // Should never happen, but just in case.
col = 0
}
break
}
pos += ll
}

return col
}

func expandTab(s string) string {
var (
b strings.Builder
Expand Down
4 changes: 2 additions & 2 deletions error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ At line 1, column 23:
{"array/tables-2.toml", `
toml: error: Key 'fruit.variety' has already been defined.
At line 9, column 3-8:
At line 9, column 4-8:
7 |
8 | # This table conflicts with the previous table
Expand All @@ -46,7 +46,7 @@ At line 9, column 3-8:
{"local-date/trailing-t.toml", `
toml: error: invalid datetime: "2006-01-30T"
At line 2, column 4-15:
At line 2, column 5-15:
1 | # Date cannot end with trailing T
2 | d = 2006-01-30T
Expand Down
10 changes: 5 additions & 5 deletions parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func parse(data string) (p *parser, err error) {
if i := strings.IndexRune(data[:ex], 0); i > -1 {
return nil, ParseError{
Message: "files cannot contain NULL bytes; probably using UTF-16; TOML files must be UTF-8",
Position: Position{Line: 1, Start: i, Len: 1},
Position: Position{Line: 1, Col: 1, Start: i, Len: 1},
Line: 1,
input: data,
}
Expand Down Expand Up @@ -93,7 +93,7 @@ func parse(data string) (p *parser, err error) {
func (p *parser) panicErr(it item, err error) {
panic(ParseError{
err: err,
Position: it.pos,
Position: it.pos.withCol(p.lx.input),
Line: it.pos.Len,
LastKey: p.current(),
})
Expand All @@ -102,7 +102,7 @@ func (p *parser) panicErr(it item, err error) {
func (p *parser) panicItemf(it item, format string, v ...any) {
panic(ParseError{
Message: fmt.Sprintf(format, v...),
Position: it.pos,
Position: it.pos.withCol(p.lx.input),
Line: it.pos.Len,
LastKey: p.current(),
})
Expand All @@ -111,7 +111,7 @@ func (p *parser) panicItemf(it item, format string, v ...any) {
func (p *parser) panicf(format string, v ...any) {
panic(ParseError{
Message: fmt.Sprintf(format, v...),
Position: p.pos,
Position: p.pos.withCol(p.lx.input),
Line: p.pos.Line,
LastKey: p.current(),
})
Expand All @@ -123,7 +123,7 @@ func (p *parser) next() item {
if it.typ == itemError {
if it.err != nil {
panic(ParseError{
Position: it.pos,
Position: it.pos.withCol(p.lx.input),
Line: it.pos.Line,
LastKey: p.current(),
err: it.err,
Expand Down

0 comments on commit 12b7e31

Please sign in to comment.