Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/common/tokens/contiguousTokensEditing.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { LineTokens } from './lineTokens.js';
7
8
export const EMPTY_LINE_TOKENS = (new Uint32Array(0)).buffer;
9
10
export class ContiguousTokensEditing {
11
12
public static deleteBeginning(lineTokens: Uint32Array | ArrayBuffer | null, toChIndex: number): Uint32Array | ArrayBuffer | null {
13
if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {
14
return lineTokens;
15
}
16
return ContiguousTokensEditing.delete(lineTokens, 0, toChIndex);
17
}
18
19
public static deleteEnding(lineTokens: Uint32Array | ArrayBuffer | null, fromChIndex: number): Uint32Array | ArrayBuffer | null {
20
if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {
21
return lineTokens;
22
}
23
24
const tokens = toUint32Array(lineTokens);
25
const lineTextLength = tokens[tokens.length - 2];
26
return ContiguousTokensEditing.delete(lineTokens, fromChIndex, lineTextLength);
27
}
28
29
public static delete(lineTokens: Uint32Array | ArrayBuffer | null, fromChIndex: number, toChIndex: number): Uint32Array | ArrayBuffer | null {
30
if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS || fromChIndex === toChIndex) {
31
return lineTokens;
32
}
33
34
const tokens = toUint32Array(lineTokens);
35
const tokensCount = (tokens.length >>> 1);
36
37
// special case: deleting everything
38
if (fromChIndex === 0 && tokens[tokens.length - 2] === toChIndex) {
39
return EMPTY_LINE_TOKENS;
40
}
41
42
const fromTokenIndex = LineTokens.findIndexInTokensArray(tokens, fromChIndex);
43
const fromTokenStartOffset = (fromTokenIndex > 0 ? tokens[(fromTokenIndex - 1) << 1] : 0);
44
const fromTokenEndOffset = tokens[fromTokenIndex << 1];
45
46
if (toChIndex < fromTokenEndOffset) {
47
// the delete range is inside a single token
48
const delta = (toChIndex - fromChIndex);
49
for (let i = fromTokenIndex; i < tokensCount; i++) {
50
tokens[i << 1] -= delta;
51
}
52
return lineTokens;
53
}
54
55
let dest: number;
56
let lastEnd: number;
57
if (fromTokenStartOffset !== fromChIndex) {
58
tokens[fromTokenIndex << 1] = fromChIndex;
59
dest = ((fromTokenIndex + 1) << 1);
60
lastEnd = fromChIndex;
61
} else {
62
dest = (fromTokenIndex << 1);
63
lastEnd = fromTokenStartOffset;
64
}
65
66
const delta = (toChIndex - fromChIndex);
67
for (let tokenIndex = fromTokenIndex + 1; tokenIndex < tokensCount; tokenIndex++) {
68
const tokenEndOffset = tokens[tokenIndex << 1] - delta;
69
if (tokenEndOffset > lastEnd) {
70
tokens[dest++] = tokenEndOffset;
71
tokens[dest++] = tokens[(tokenIndex << 1) + 1];
72
lastEnd = tokenEndOffset;
73
}
74
}
75
76
if (dest === tokens.length) {
77
// nothing to trim
78
return lineTokens;
79
}
80
81
const tmp = new Uint32Array(dest);
82
tmp.set(tokens.subarray(0, dest), 0);
83
return tmp.buffer;
84
}
85
86
public static append(lineTokens: Uint32Array | ArrayBuffer | null, _otherTokens: Uint32Array | ArrayBuffer | null): Uint32Array | ArrayBuffer | null {
87
if (_otherTokens === EMPTY_LINE_TOKENS) {
88
return lineTokens;
89
}
90
if (lineTokens === EMPTY_LINE_TOKENS) {
91
return _otherTokens;
92
}
93
if (lineTokens === null) {
94
return lineTokens;
95
}
96
if (_otherTokens === null) {
97
// cannot determine combined line length...
98
return null;
99
}
100
const myTokens = toUint32Array(lineTokens);
101
const otherTokens = toUint32Array(_otherTokens);
102
const otherTokensCount = (otherTokens.length >>> 1);
103
104
const result = new Uint32Array(myTokens.length + otherTokens.length);
105
result.set(myTokens, 0);
106
let dest = myTokens.length;
107
const delta = myTokens[myTokens.length - 2];
108
for (let i = 0; i < otherTokensCount; i++) {
109
result[dest++] = otherTokens[(i << 1)] + delta;
110
result[dest++] = otherTokens[(i << 1) + 1];
111
}
112
return result.buffer;
113
}
114
115
public static insert(lineTokens: Uint32Array | ArrayBuffer | null, chIndex: number, textLength: number): Uint32Array | ArrayBuffer | null {
116
if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {
117
// nothing to do
118
return lineTokens;
119
}
120
121
const tokens = toUint32Array(lineTokens);
122
const tokensCount = (tokens.length >>> 1);
123
124
let fromTokenIndex = LineTokens.findIndexInTokensArray(tokens, chIndex);
125
if (fromTokenIndex > 0) {
126
const fromTokenStartOffset = tokens[(fromTokenIndex - 1) << 1];
127
if (fromTokenStartOffset === chIndex) {
128
fromTokenIndex--;
129
}
130
}
131
for (let tokenIndex = fromTokenIndex; tokenIndex < tokensCount; tokenIndex++) {
132
tokens[tokenIndex << 1] += textLength;
133
}
134
return lineTokens;
135
}
136
}
137
138
export function toUint32Array(arr: Uint32Array | ArrayBuffer): Uint32Array<ArrayBuffer> {
139
if (arr instanceof Uint32Array) {
140
return arr as Uint32Array<ArrayBuffer>;
141
} else {
142
return new Uint32Array<ArrayBuffer>(arr);
143
}
144
}
145
146