mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-19 07:25:27 +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
|
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 {
|
type LocationRange struct {
|
||||||
Start Location
|
Start Location
|
||||||
End 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 {
|
func (l LocationRange) ShiftHorizontal(offset uint32) LocationRange {
|
||||||
return LocationRange{
|
return LocationRange{
|
||||||
Start: Location{
|
Start: Location{
|
||||||
@ -57,7 +106,7 @@ func (l LocationRange) ToLSPRange() protocol.Range {
|
|||||||
},
|
},
|
||||||
End: protocol.Position{
|
End: protocol.Position{
|
||||||
Line: l.End.Line,
|
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
|
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 {
|
func (l LocationRange) ContainsCursorByCharacter(character uint32) bool {
|
||||||
return character >= l.Start.Character && character <= l.End.Character
|
return character >= l.Start.Character && character <= l.End.Character
|
||||||
}
|
}
|
||||||
@ -115,7 +160,57 @@ func CharacterRangeFromCtx(
|
|||||||
},
|
},
|
||||||
End: Location{
|
End: Location{
|
||||||
Line: line,
|
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
|
package common
|
||||||
|
|
||||||
|
// LSPCharacterAsCursorPosition:
|
||||||
|
// @deprecated
|
||||||
func CursorToCharacterIndex(cursor uint32) uint32 {
|
func CursorToCharacterIndex(cursor uint32) uint32 {
|
||||||
return max(1, cursor) - 1
|
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