diff --git a/internal/span/utf16.go b/internal/span/utf16.go index 4439acb6..887e3bed 100644 --- a/internal/span/utf16.go +++ b/internal/span/utf16.go @@ -36,12 +36,12 @@ func ToUTF16Column(p Point, content []byte) (int, error) { return -1, fmt.Errorf("ToUTF16Column: offsets %v-%v outside file contents (%v)", lineOffset, offset, len(content)) } // Use the offset to pick out the line start. - // This cannot panic: offset > len(content) and lineOffset < offset. + // This cannot panic: offset > len(content) and lineOffset < offset. start := content[lineOffset:] // Now, truncate down to the supplied column. - if col >= len(start) { - return -1, fmt.Errorf("ToUTF16Column: line (%v) is shorter than column (%v)", len(start), col) + if col > len(start) { // col is 1-indexed + return -1, fmt.Errorf("ToUTF16Column: length of line (%v) is less than column (%v)", len(start), col) } start = start[:col] // and count the number of utf16 characters diff --git a/internal/span/utf16_test.go b/internal/span/utf16_test.go index 3a3b659d..5f971085 100644 --- a/internal/span/utf16_test.go +++ b/internal/span/utf16_test.go @@ -27,7 +27,7 @@ func TestUTF16(t *testing.T) { c := span.NewContentConverter("test", input) for line := 1; line <= 9; line++ { runeColumn, runeChr := 0, 0 - for chr := 1; chr <= 9; chr++ { + for chr := 1; chr <= 10; chr++ { switch { case chr <= line: runeChr = chr @@ -67,3 +67,28 @@ func TestUTF16(t *testing.T) { } } } + +func TestUTF16Errors(t *testing.T) { + var input = []byte(` +hello +world +`)[1:] + for _, test := range []struct { + line, col, offset int + want string + }{ + { + 1, 6, 12, + "ToUTF16Column: length of line (5) is less than column (6)", + }, + { + 1, 6, 13, + "ToUTF16Column: offsets 8-13 outside file contents (12)", + }, + } { + p := span.NewPoint(test.line, test.col, test.offset) + if _, err := span.ToUTF16Column(p, input); err == nil || err.Error() != test.want { + t.Errorf("expected %v, got %v", test.want, err) + } + } +}