mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 15:05:28 +02:00
feat(common): Add Position to common
This commit is contained in:
parent
dbd82e4939
commit
5b660d9b60
@ -12,11 +12,60 @@ type Location struct {
|
||||
Character uint32
|
||||
}
|
||||
|
||||
func (l Location) GetRelativeIndexPosition(i IndexPosition) IndexPosition {
|
||||
return i - IndexPosition(l.Character)
|
||||
}
|
||||
|
||||
// LocationRange: Represents a range of characters in a document
|
||||
// Locations are zero-based, start-inclusive and end-exclusive
|
||||
// This approach is preferred over using an index-based range, because
|
||||
// it allows to check very easily for cursor positions, as well as for
|
||||
// index-based ranges.
|
||||
type LocationRange struct {
|
||||
Start Location
|
||||
End Location
|
||||
}
|
||||
|
||||
func (l LocationRange) ContainsPosition(p Position) bool {
|
||||
return l.IsPositionAfterStart(p) && l.IsPositionBeforeEnd(p)
|
||||
}
|
||||
|
||||
// Check if the given position is after the start of the range
|
||||
// It's like: Position >= Start
|
||||
// This checks inclusively
|
||||
func (l LocationRange) IsPositionAfterStart(p Position) bool {
|
||||
return p.getValue() >= l.Start.Character
|
||||
}
|
||||
|
||||
func (l LocationRange) IsPositionBeforeStart(p Position) bool {
|
||||
return p.getValue() < l.Start.Character
|
||||
}
|
||||
|
||||
// Check if the given position is before the end of the range
|
||||
// It's like: Position <= End
|
||||
// This checks inclusively
|
||||
func (l LocationRange) IsPositionBeforeEnd(p Position) bool {
|
||||
switch p.(type) {
|
||||
case CursorPosition:
|
||||
return p.getValue() <= l.End.Character
|
||||
case IndexPosition:
|
||||
return p.getValue() < l.End.Character
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (l LocationRange) IsPositionAfterEnd(p Position) bool {
|
||||
switch p.(type) {
|
||||
case CursorPosition:
|
||||
return p.getValue() > l.End.Character
|
||||
case IndexPosition:
|
||||
return p.getValue() >= l.End.Character
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (l LocationRange) ShiftHorizontal(offset uint32) LocationRange {
|
||||
return LocationRange{
|
||||
Start: Location{
|
||||
@ -57,7 +106,7 @@ func (l LocationRange) ToLSPRange() protocol.Range {
|
||||
},
|
||||
End: protocol.Position{
|
||||
Line: l.End.Line,
|
||||
Character: l.End.Character + 1,
|
||||
Character: l.End.Character,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -67,10 +116,6 @@ func (l *LocationRange) ChangeBothLines(newLine uint32) {
|
||||
l.End.Line = newLine
|
||||
}
|
||||
|
||||
func (l LocationRange) ContainsCursor(line uint32, character uint32) bool {
|
||||
return line == l.Start.Line && character >= l.Start.Character && character <= l.End.Character
|
||||
}
|
||||
|
||||
func (l LocationRange) ContainsCursorByCharacter(character uint32) bool {
|
||||
return character >= l.Start.Character && character <= l.End.Character
|
||||
}
|
||||
@ -115,7 +160,57 @@ func CharacterRangeFromCtx(
|
||||
},
|
||||
End: Location{
|
||||
Line: line,
|
||||
Character: end,
|
||||
Character: end + 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type Position interface {
|
||||
getValue() uint32
|
||||
}
|
||||
|
||||
// Use this type if you want to use a cursor based position
|
||||
// A cursor based position is a position that represents a cursor
|
||||
// Given the example:
|
||||
// "PermitRootLogin yes"
|
||||
// Taking a look at the first character "P" - the index is 0.
|
||||
// However, the cursor can either be at:
|
||||
//
|
||||
// "|P" - 0 or
|
||||
// "P|" - 1
|
||||
//
|
||||
// This is used for example for textDocument/completion or textDocument/signature
|
||||
type CursorPosition uint32
|
||||
|
||||
func (c CursorPosition) getValue() uint32 {
|
||||
return uint32(c)
|
||||
}
|
||||
|
||||
func (c CursorPosition) shiftHorizontal(offset uint32) CursorPosition {
|
||||
return CursorPosition(uint32(c) + offset)
|
||||
}
|
||||
|
||||
func LSPCharacterAsCursorPosition(character uint32) CursorPosition {
|
||||
return CursorPosition(character)
|
||||
}
|
||||
|
||||
func (c CursorPosition) IsBeforeIndexPosition(i IndexPosition) bool {
|
||||
// |H[e]llo
|
||||
return uint32(c) < uint32(i)
|
||||
}
|
||||
|
||||
func (c CursorPosition) IsAfterIndexPosition(i IndexPosition) bool {
|
||||
// H[e]|llo
|
||||
return uint32(c) > uint32(i)+1
|
||||
}
|
||||
|
||||
// Use this type if you want to use an index based position
|
||||
type IndexPosition uint32
|
||||
|
||||
func (i IndexPosition) getValue() uint32 {
|
||||
return uint32(i)
|
||||
}
|
||||
|
||||
func LSPCharacterAsIndexPosition(character uint32) IndexPosition {
|
||||
return IndexPosition(character)
|
||||
}
|
||||
|
137
common/location_test.go
Normal file
137
common/location_test.go
Normal file
@ -0,0 +1,137 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCursorPosition(
|
||||
t *testing.T,
|
||||
) {
|
||||
// Contains fictive range for the name "Test" in the code:
|
||||
// func Test() {}
|
||||
locationRange := LocationRange{
|
||||
Start: Location{
|
||||
Line: 0,
|
||||
Character: 5,
|
||||
},
|
||||
End: Location{
|
||||
Line: 0,
|
||||
Character: 9,
|
||||
},
|
||||
}
|
||||
|
||||
if !(locationRange.ContainsPosition(LSPCharacterAsCursorPosition(5)) == true) {
|
||||
t.Errorf("Expected 5 to be in range, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.ContainsPosition(LSPCharacterAsCursorPosition(6)) == true) {
|
||||
t.Errorf("Expected 6 to be in range, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.ContainsPosition(LSPCharacterAsCursorPosition(9)) == true) {
|
||||
t.Errorf("Expected 9 to be in range, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.ContainsPosition(LSPCharacterAsCursorPosition(10)) == false) {
|
||||
t.Errorf("Expected 10 to not be in range, but it was")
|
||||
}
|
||||
|
||||
if !(locationRange.ContainsPosition(LSPCharacterAsCursorPosition(4)) == false) {
|
||||
t.Errorf("Expected 4 to not be in range, but it was")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionBeforeStart(LSPCharacterAsCursorPosition(0)) == true) {
|
||||
t.Errorf("Expected 0 to be before start, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionBeforeStart(LSPCharacterAsCursorPosition(4)) == true) {
|
||||
t.Errorf("Expected 5 to be before start, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionBeforeStart(LSPCharacterAsCursorPosition(5)) == false) {
|
||||
t.Errorf("Expected 5 to not be before start, but it was")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionBeforeStart(LSPCharacterAsCursorPosition(10)) == false) {
|
||||
t.Errorf("Expected 10 to not be before start, but it was")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionAfterEnd(LSPCharacterAsCursorPosition(10)) == true) {
|
||||
t.Errorf("Expected 10 to be after end, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionAfterEnd(LSPCharacterAsCursorPosition(11)) == true) {
|
||||
t.Errorf("Expected 11 to be after end, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionAfterEnd(LSPCharacterAsCursorPosition(9)) == false) {
|
||||
t.Errorf("Expected 9 to not be after end, but it was")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionAfterEnd(LSPCharacterAsCursorPosition(5)) == false) {
|
||||
t.Errorf("Expected 5 to not be after end, but it was")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndexPosition(t *testing.T) {
|
||||
// Contains fictive range for the name "Test" in the code:
|
||||
// func Test() {}
|
||||
locationRange := LocationRange{
|
||||
Start: Location{
|
||||
Line: 0,
|
||||
Character: 5,
|
||||
},
|
||||
End: Location{
|
||||
Line: 0,
|
||||
Character: 9,
|
||||
},
|
||||
}
|
||||
|
||||
if !(locationRange.ContainsPosition(LSPCharacterAsIndexPosition(5)) == true) {
|
||||
t.Errorf("Expected index position 5 to be in range, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.ContainsPosition(LSPCharacterAsIndexPosition(6)) == true) {
|
||||
t.Errorf("Expected index position 6 to be in range, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.ContainsPosition(LSPCharacterAsIndexPosition(8)) == true) {
|
||||
t.Errorf("Expected index position 6 to be in range, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.ContainsPosition(LSPCharacterAsIndexPosition(9)) == false) {
|
||||
t.Errorf("Expected index position 9 to not be in range, but it was")
|
||||
}
|
||||
|
||||
if !(locationRange.ContainsPosition(LSPCharacterAsIndexPosition(10)) == false) {
|
||||
t.Errorf("Expected index position 10 to not be in range, but it was")
|
||||
}
|
||||
|
||||
if !(locationRange.ContainsPosition(LSPCharacterAsIndexPosition(4)) == false) {
|
||||
t.Errorf("Expected index position 4 to not be in range, but it was")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionBeforeStart(LSPCharacterAsIndexPosition(4)) == true) {
|
||||
t.Errorf("Expected index position 4 to be before start, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionBeforeStart(LSPCharacterAsIndexPosition(5)) == false) {
|
||||
t.Errorf("Expected index position 5 to not be before start, but it was")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionBeforeStart(LSPCharacterAsIndexPosition(10)) == false) {
|
||||
t.Errorf("Expected index position 10 to not be before start, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionAfterEnd(LSPCharacterAsIndexPosition(10)) == true) {
|
||||
t.Errorf("Expected index position 10 to be after end, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionAfterEnd(LSPCharacterAsIndexPosition(9)) == true) {
|
||||
t.Errorf("Expected index position 9 to be after end, but it wasn't")
|
||||
}
|
||||
|
||||
if !(locationRange.IsPositionAfterEnd(LSPCharacterAsIndexPosition(5)) == false) {
|
||||
t.Errorf("Expected index position 5 to not be after end, but it was")
|
||||
}
|
||||
}
|
@ -1,5 +1,19 @@
|
||||
package common
|
||||
|
||||
// LSPCharacterAsCursorPosition:
|
||||
// @deprecated
|
||||
func CursorToCharacterIndex(cursor uint32) uint32 {
|
||||
return max(1, cursor) - 1
|
||||
}
|
||||
|
||||
func DeprecatedImprovedCursorToIndex(
|
||||
c CursorPosition,
|
||||
line string,
|
||||
offset uint32,
|
||||
) uint32 {
|
||||
if len(line) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return min(uint32(len(line)-1), uint32(c)-offset+1)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user