vendor tsgo
This commit is contained in:
71
tools/tsgo/internal/ls/lsconv/linemap.go
Normal file
71
tools/tsgo/internal/ls/lsconv/linemap.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package lsconv
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"slices"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
)
|
||||
|
||||
type LSPLineStarts []core.TextPos
|
||||
|
||||
type LSPLineMap struct {
|
||||
LineStarts LSPLineStarts
|
||||
AsciiOnly bool // TODO(jakebailey): collect ascii-only info per line
|
||||
}
|
||||
|
||||
func ComputeLSPLineStarts(text string) *LSPLineMap {
|
||||
// This is like core.ComputeLineStarts, but only considers "\n", "\r", and "\r\n" as line breaks,
|
||||
// and reports when the text is ASCII-only.
|
||||
lineStarts := make([]core.TextPos, 0, strings.Count(text, "\n")+1)
|
||||
asciiOnly := true
|
||||
|
||||
textLen := core.TextPos(len(text))
|
||||
var pos core.TextPos
|
||||
var lineStart core.TextPos
|
||||
for pos < textLen {
|
||||
b := text[pos]
|
||||
if b < utf8.RuneSelf {
|
||||
pos++
|
||||
switch b {
|
||||
case '\r':
|
||||
if pos < textLen && text[pos] == '\n' {
|
||||
pos++
|
||||
}
|
||||
fallthrough
|
||||
case '\n':
|
||||
lineStarts = append(lineStarts, lineStart)
|
||||
lineStart = pos
|
||||
}
|
||||
} else {
|
||||
_, size := utf8.DecodeRuneInString(text[pos:])
|
||||
pos += core.TextPos(size)
|
||||
asciiOnly = false
|
||||
}
|
||||
}
|
||||
lineStarts = append(lineStarts, lineStart)
|
||||
|
||||
return &LSPLineMap{
|
||||
LineStarts: lineStarts,
|
||||
AsciiOnly: asciiOnly,
|
||||
}
|
||||
}
|
||||
|
||||
func (lm *LSPLineMap) ComputeIndexOfLineStart(targetPos core.TextPos) int {
|
||||
// port of computeLineOfPosition(lineStarts: readonly number[], position: number, lowerBound?: number): number {
|
||||
lineNumber, ok := slices.BinarySearchFunc(lm.LineStarts, targetPos, func(p, t core.TextPos) int {
|
||||
return cmp.Compare(int(p), int(t))
|
||||
})
|
||||
if !ok && lineNumber > 0 {
|
||||
// If the actual position was not found, the binary search returns where the target line start would be inserted
|
||||
// if the target was in the slice.
|
||||
// e.g. if the line starts at [5, 10, 23, 80] and the position requested was 20
|
||||
// then the search will return (3, false).
|
||||
//
|
||||
// We want the index of the previous line start, so we subtract 1.
|
||||
lineNumber = lineNumber - 1
|
||||
}
|
||||
return lineNumber
|
||||
}
|
||||
Reference in New Issue
Block a user