Path: blob/main/src/vs/editor/common/tokens/contiguousTokensEditing.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { LineTokens } from './lineTokens.js';67export const EMPTY_LINE_TOKENS = (new Uint32Array(0)).buffer;89export class ContiguousTokensEditing {1011public static deleteBeginning(lineTokens: Uint32Array | ArrayBuffer | null, toChIndex: number): Uint32Array | ArrayBuffer | null {12if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {13return lineTokens;14}15return ContiguousTokensEditing.delete(lineTokens, 0, toChIndex);16}1718public static deleteEnding(lineTokens: Uint32Array | ArrayBuffer | null, fromChIndex: number): Uint32Array | ArrayBuffer | null {19if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {20return lineTokens;21}2223const tokens = toUint32Array(lineTokens);24const lineTextLength = tokens[tokens.length - 2];25return ContiguousTokensEditing.delete(lineTokens, fromChIndex, lineTextLength);26}2728public static delete(lineTokens: Uint32Array | ArrayBuffer | null, fromChIndex: number, toChIndex: number): Uint32Array | ArrayBuffer | null {29if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS || fromChIndex === toChIndex) {30return lineTokens;31}3233const tokens = toUint32Array(lineTokens);34const tokensCount = (tokens.length >>> 1);3536// special case: deleting everything37if (fromChIndex === 0 && tokens[tokens.length - 2] === toChIndex) {38return EMPTY_LINE_TOKENS;39}4041const fromTokenIndex = LineTokens.findIndexInTokensArray(tokens, fromChIndex);42const fromTokenStartOffset = (fromTokenIndex > 0 ? tokens[(fromTokenIndex - 1) << 1] : 0);43const fromTokenEndOffset = tokens[fromTokenIndex << 1];4445if (toChIndex < fromTokenEndOffset) {46// the delete range is inside a single token47const delta = (toChIndex - fromChIndex);48for (let i = fromTokenIndex; i < tokensCount; i++) {49tokens[i << 1] -= delta;50}51return lineTokens;52}5354let dest: number;55let lastEnd: number;56if (fromTokenStartOffset !== fromChIndex) {57tokens[fromTokenIndex << 1] = fromChIndex;58dest = ((fromTokenIndex + 1) << 1);59lastEnd = fromChIndex;60} else {61dest = (fromTokenIndex << 1);62lastEnd = fromTokenStartOffset;63}6465const delta = (toChIndex - fromChIndex);66for (let tokenIndex = fromTokenIndex + 1; tokenIndex < tokensCount; tokenIndex++) {67const tokenEndOffset = tokens[tokenIndex << 1] - delta;68if (tokenEndOffset > lastEnd) {69tokens[dest++] = tokenEndOffset;70tokens[dest++] = tokens[(tokenIndex << 1) + 1];71lastEnd = tokenEndOffset;72}73}7475if (dest === tokens.length) {76// nothing to trim77return lineTokens;78}7980const tmp = new Uint32Array(dest);81tmp.set(tokens.subarray(0, dest), 0);82return tmp.buffer;83}8485public static append(lineTokens: Uint32Array | ArrayBuffer | null, _otherTokens: Uint32Array | ArrayBuffer | null): Uint32Array | ArrayBuffer | null {86if (_otherTokens === EMPTY_LINE_TOKENS) {87return lineTokens;88}89if (lineTokens === EMPTY_LINE_TOKENS) {90return _otherTokens;91}92if (lineTokens === null) {93return lineTokens;94}95if (_otherTokens === null) {96// cannot determine combined line length...97return null;98}99const myTokens = toUint32Array(lineTokens);100const otherTokens = toUint32Array(_otherTokens);101const otherTokensCount = (otherTokens.length >>> 1);102103const result = new Uint32Array(myTokens.length + otherTokens.length);104result.set(myTokens, 0);105let dest = myTokens.length;106const delta = myTokens[myTokens.length - 2];107for (let i = 0; i < otherTokensCount; i++) {108result[dest++] = otherTokens[(i << 1)] + delta;109result[dest++] = otherTokens[(i << 1) + 1];110}111return result.buffer;112}113114public static insert(lineTokens: Uint32Array | ArrayBuffer | null, chIndex: number, textLength: number): Uint32Array | ArrayBuffer | null {115if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {116// nothing to do117return lineTokens;118}119120const tokens = toUint32Array(lineTokens);121const tokensCount = (tokens.length >>> 1);122123let fromTokenIndex = LineTokens.findIndexInTokensArray(tokens, chIndex);124if (fromTokenIndex > 0) {125const fromTokenStartOffset = tokens[(fromTokenIndex - 1) << 1];126if (fromTokenStartOffset === chIndex) {127fromTokenIndex--;128}129}130for (let tokenIndex = fromTokenIndex; tokenIndex < tokensCount; tokenIndex++) {131tokens[tokenIndex << 1] += textLength;132}133return lineTokens;134}135}136137export function toUint32Array(arr: Uint32Array | ArrayBuffer): Uint32Array<ArrayBuffer> {138if (arr instanceof Uint32Array) {139return arr as Uint32Array<ArrayBuffer>;140} else {141return new Uint32Array<ArrayBuffer>(arr);142}143}144145146