offsetForPosition converts a protocol (UTF-16) position to a byte offset. content is utf8 encoded sequence.
(content []byte, p lsp.Position)
| 31 | |
| 32 | // offsetForPosition converts a protocol (UTF-16) position to a byte offset. content is utf8 encoded sequence. |
| 33 | func offsetForPosition(content []byte, p lsp.Position) (byteOffset int, whyInvalid error) { |
| 34 | newLineCount := bytes.Count(content, []byte("\n")) |
| 35 | lineNumber := newLineCount + 1 |
| 36 | // lineStartOffsets records the byte offset of each line start. |
| 37 | lineStartOffsets := make([]int, 1, lineNumber) // Init as {0} |
| 38 | for offset, b := range content { |
| 39 | if b == '\n' { |
| 40 | nextLineBeginOffset := offset + 1 |
| 41 | lineStartOffsets = append(lineStartOffsets, nextLineBeginOffset) |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | // Validate line number, notes that the Position in LSP is 0-based. |
| 46 | if int(p.Line) >= lineNumber { |
| 47 | return 0, errors.Errorf("line number %d out of range [0, %d)", p.Line, lineNumber) |
| 48 | } |
| 49 | |
| 50 | offset := lineStartOffsets[p.Line] |
| 51 | trimmedContent := content[offset:] |
| 52 | |
| 53 | col8 := 0 |
| 54 | for col16 := 0; col16 < int(p.Character); col16++ { |
| 55 | // Unpack the first rune. |
| 56 | r, sz := utf8.DecodeRune(trimmedContent) |
| 57 | if sz == 0 { |
| 58 | return 0, errors.Errorf("column is beyond end of file") |
| 59 | } |
| 60 | if r == '\n' { |
| 61 | return 0, errors.Errorf("column is beyond end of line") |
| 62 | } |
| 63 | if sz == 1 && r == utf8.RuneError { |
| 64 | return 0, errors.Errorf("mem buffer contains invalid UTF-8 text") |
| 65 | } |
| 66 | |
| 67 | // Step to the first code unit of next rune. |
| 68 | trimmedContent = trimmedContent[sz:] |
| 69 | |
| 70 | if r > 0xFFFF { |
| 71 | // Rune was encoded by a pair of surrogate UTF-16 codes. |
| 72 | col16++ |
| 73 | |
| 74 | // Requested position is in the middle of a rune? Valid? |
| 75 | if col16 == int(p.Character) { |
| 76 | break |
| 77 | } |
| 78 | } |
| 79 | col8 += sz |
| 80 | } |
| 81 | return offset + col8, nil |
| 82 | } |
| 83 | |
| 84 | func getSQLStatementRangesUTF16Position(content []byte) []lsp.Range { |
| 85 | s := strings.TrimRightFunc(string(content), unicode.IsSpace) |