mirror of https://github.com/golang/go.git
108 lines
2.8 KiB
Go
108 lines
2.8 KiB
Go
// Copyright 2022 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package lsppos_test
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
. "golang.org/x/tools/internal/lsp/lsppos"
|
|
"golang.org/x/tools/internal/lsp/protocol"
|
|
)
|
|
|
|
type testCase struct {
|
|
content string // input text
|
|
substrOrOffset interface{} // explicit integer offset, or a substring
|
|
wantLine, wantChar int // expected LSP position information
|
|
}
|
|
|
|
// offset returns the test case byte offset
|
|
func (c testCase) offset() int {
|
|
switch x := c.substrOrOffset.(type) {
|
|
case int:
|
|
return x
|
|
case string:
|
|
i := strings.Index(c.content, x)
|
|
if i < 0 {
|
|
panic(fmt.Sprintf("%q does not contain substring %q", c.content, x))
|
|
}
|
|
return i
|
|
}
|
|
panic("substrOrIndex must be an integer or string")
|
|
}
|
|
|
|
var tests = []testCase{
|
|
{"a𐐀b", "a", 0, 0},
|
|
{"a𐐀b", "𐐀", 0, 1},
|
|
{"a𐐀b", "b", 0, 3},
|
|
{"a𐐀b\n", "\n", 0, 4},
|
|
{"a𐐀b\r\n", "\n", 0, 4}, // \r|\n is not a valid position, so we move back to the end of the first line.
|
|
{"a𐐀b\r\nx", "x", 1, 0},
|
|
{"a𐐀b\r\nx\ny", "y", 2, 0},
|
|
|
|
// Testing EOL and EOF positions
|
|
{"", 0, 0, 0}, // 0th position of an empty buffer is (0, 0)
|
|
{"abc", "c", 0, 2},
|
|
{"abc", 3, 0, 3},
|
|
{"abc\n", "\n", 0, 3},
|
|
{"abc\n", 4, 1, 0}, // position after a newline is on the next line
|
|
}
|
|
|
|
func TestLineChar(t *testing.T) {
|
|
for _, test := range tests {
|
|
m := NewMapper([]byte(test.content))
|
|
offset := test.offset()
|
|
gotLine, gotChar := m.LineColUTF16(offset)
|
|
if gotLine != test.wantLine || gotChar != test.wantChar {
|
|
t.Errorf("LineChar(%d) = (%d,%d), want (%d,%d)", offset, gotLine, gotChar, test.wantLine, test.wantChar)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestInvalidOffset(t *testing.T) {
|
|
content := []byte("a𐐀b\r\nx\ny")
|
|
m := NewMapper(content)
|
|
for _, offset := range []int{-1, 100} {
|
|
gotLine, gotChar := m.LineColUTF16(offset)
|
|
if gotLine != -1 {
|
|
t.Errorf("LineChar(%d) = (%d,%d), want (-1,-1)", offset, gotLine, gotChar)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPosition(t *testing.T) {
|
|
for _, test := range tests {
|
|
m := NewMapper([]byte(test.content))
|
|
offset := test.offset()
|
|
got, ok := m.Position(offset)
|
|
if !ok {
|
|
t.Error("invalid position for", test.substrOrOffset)
|
|
continue
|
|
}
|
|
want := protocol.Position{Line: uint32(test.wantLine), Character: uint32(test.wantChar)}
|
|
if got != want {
|
|
t.Errorf("Position(%d) = %v, want %v", offset, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRange(t *testing.T) {
|
|
for _, test := range tests {
|
|
m := NewMapper([]byte(test.content))
|
|
offset := test.offset()
|
|
got, err := m.Range(0, offset)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
want := protocol.Range{
|
|
End: protocol.Position{Line: uint32(test.wantLine), Character: uint32(test.wantChar)},
|
|
}
|
|
if got != want {
|
|
t.Errorf("Range(%d) = %v, want %v", offset, got, want)
|
|
}
|
|
}
|
|
}
|