Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/test/common/model/model.modes.test.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 assert from 'assert';
7
import { IDisposable } from '../../../../base/common/lifecycle.js';
8
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';
9
import { EditOperation } from '../../../common/core/editOperation.js';
10
import { Position } from '../../../common/core/position.js';
11
import { Range } from '../../../common/core/range.js';
12
import * as languages from '../../../common/languages.js';
13
import { NullState } from '../../../common/languages/nullTokenize.js';
14
import { TextModel } from '../../../common/model/textModel.js';
15
import { createTextModel } from '../testTextModel.js';
16
17
// --------- utils
18
19
suite('Editor Model - Model Modes 1', () => {
20
21
let calledFor: string[] = [];
22
23
function getAndClear(): string[] {
24
const result = calledFor;
25
calledFor = [];
26
return result;
27
}
28
29
const tokenizationSupport: languages.ITokenizationSupport = {
30
getInitialState: () => NullState,
31
tokenize: undefined!,
32
tokenizeEncoded: (line: string, hasEOL: boolean, state: languages.IState): languages.EncodedTokenizationResult => {
33
calledFor.push(line.charAt(0));
34
return new languages.EncodedTokenizationResult(new Uint32Array(0), state);
35
}
36
};
37
38
let thisModel: TextModel;
39
let languageRegistration: IDisposable;
40
41
setup(() => {
42
const TEXT =
43
'1\r\n' +
44
'2\n' +
45
'3\n' +
46
'4\r\n' +
47
'5';
48
const LANGUAGE_ID = 'modelModeTest1';
49
calledFor = [];
50
languageRegistration = languages.TokenizationRegistry.register(LANGUAGE_ID, tokenizationSupport);
51
thisModel = createTextModel(TEXT, LANGUAGE_ID);
52
});
53
54
teardown(() => {
55
thisModel.dispose();
56
languageRegistration.dispose();
57
calledFor = [];
58
});
59
60
ensureNoDisposablesAreLeakedInTestSuite();
61
62
test('model calls syntax highlighter 1', () => {
63
thisModel.tokenization.forceTokenization(1);
64
assert.deepStrictEqual(getAndClear(), ['1']);
65
});
66
67
test('model calls syntax highlighter 2', () => {
68
thisModel.tokenization.forceTokenization(2);
69
assert.deepStrictEqual(getAndClear(), ['1', '2']);
70
71
thisModel.tokenization.forceTokenization(2);
72
assert.deepStrictEqual(getAndClear(), []);
73
});
74
75
test('model caches states', () => {
76
thisModel.tokenization.forceTokenization(1);
77
assert.deepStrictEqual(getAndClear(), ['1']);
78
79
thisModel.tokenization.forceTokenization(2);
80
assert.deepStrictEqual(getAndClear(), ['2']);
81
82
thisModel.tokenization.forceTokenization(3);
83
assert.deepStrictEqual(getAndClear(), ['3']);
84
85
thisModel.tokenization.forceTokenization(4);
86
assert.deepStrictEqual(getAndClear(), ['4']);
87
88
thisModel.tokenization.forceTokenization(5);
89
assert.deepStrictEqual(getAndClear(), ['5']);
90
91
thisModel.tokenization.forceTokenization(5);
92
assert.deepStrictEqual(getAndClear(), []);
93
});
94
95
test('model invalidates states for one line insert', () => {
96
thisModel.tokenization.forceTokenization(5);
97
assert.deepStrictEqual(getAndClear(), ['1', '2', '3', '4', '5']);
98
99
thisModel.applyEdits([EditOperation.insert(new Position(1, 1), '-')]);
100
thisModel.tokenization.forceTokenization(5);
101
assert.deepStrictEqual(getAndClear(), ['-']);
102
103
thisModel.tokenization.forceTokenization(5);
104
assert.deepStrictEqual(getAndClear(), []);
105
});
106
107
test('model invalidates states for many lines insert', () => {
108
thisModel.tokenization.forceTokenization(5);
109
assert.deepStrictEqual(getAndClear(), ['1', '2', '3', '4', '5']);
110
111
thisModel.applyEdits([EditOperation.insert(new Position(1, 1), '0\n-\n+')]);
112
assert.strictEqual(thisModel.getLineCount(), 7);
113
thisModel.tokenization.forceTokenization(7);
114
assert.deepStrictEqual(getAndClear(), ['0', '-', '+']);
115
116
thisModel.tokenization.forceTokenization(7);
117
assert.deepStrictEqual(getAndClear(), []);
118
});
119
120
test('model invalidates states for one new line', () => {
121
thisModel.tokenization.forceTokenization(5);
122
assert.deepStrictEqual(getAndClear(), ['1', '2', '3', '4', '5']);
123
124
thisModel.applyEdits([EditOperation.insert(new Position(1, 2), '\n')]);
125
thisModel.applyEdits([EditOperation.insert(new Position(2, 1), 'a')]);
126
thisModel.tokenization.forceTokenization(6);
127
assert.deepStrictEqual(getAndClear(), ['1', 'a']);
128
});
129
130
test('model invalidates states for one line delete', () => {
131
thisModel.tokenization.forceTokenization(5);
132
assert.deepStrictEqual(getAndClear(), ['1', '2', '3', '4', '5']);
133
134
thisModel.applyEdits([EditOperation.insert(new Position(1, 2), '-')]);
135
thisModel.tokenization.forceTokenization(5);
136
assert.deepStrictEqual(getAndClear(), ['1']);
137
138
thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 1, 2))]);
139
thisModel.tokenization.forceTokenization(5);
140
assert.deepStrictEqual(getAndClear(), ['-']);
141
142
thisModel.tokenization.forceTokenization(5);
143
assert.deepStrictEqual(getAndClear(), []);
144
});
145
146
test('model invalidates states for many lines delete', () => {
147
thisModel.tokenization.forceTokenization(5);
148
assert.deepStrictEqual(getAndClear(), ['1', '2', '3', '4', '5']);
149
150
thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 3, 1))]);
151
thisModel.tokenization.forceTokenization(3);
152
assert.deepStrictEqual(getAndClear(), ['3']);
153
154
thisModel.tokenization.forceTokenization(3);
155
assert.deepStrictEqual(getAndClear(), []);
156
});
157
});
158
159
suite('Editor Model - Model Modes 2', () => {
160
161
class ModelState2 implements languages.IState {
162
prevLineContent: string;
163
164
constructor(prevLineContent: string) {
165
this.prevLineContent = prevLineContent;
166
}
167
168
clone(): languages.IState {
169
return new ModelState2(this.prevLineContent);
170
}
171
172
equals(other: languages.IState): boolean {
173
return (other instanceof ModelState2) && other.prevLineContent === this.prevLineContent;
174
}
175
}
176
177
let calledFor: string[] = [];
178
179
function getAndClear(): string[] {
180
const actual = calledFor;
181
calledFor = [];
182
return actual;
183
}
184
185
const tokenizationSupport: languages.ITokenizationSupport = {
186
getInitialState: () => new ModelState2(''),
187
tokenize: undefined!,
188
tokenizeEncoded: (line: string, hasEOL: boolean, state: languages.IState): languages.EncodedTokenizationResult => {
189
calledFor.push(line);
190
(<ModelState2>state).prevLineContent = line;
191
return new languages.EncodedTokenizationResult(new Uint32Array(0), state);
192
}
193
};
194
195
let thisModel: TextModel;
196
let languageRegistration: IDisposable;
197
198
setup(() => {
199
const TEXT =
200
'Line1' + '\r\n' +
201
'Line2' + '\n' +
202
'Line3' + '\n' +
203
'Line4' + '\r\n' +
204
'Line5';
205
const LANGUAGE_ID = 'modelModeTest2';
206
languageRegistration = languages.TokenizationRegistry.register(LANGUAGE_ID, tokenizationSupport);
207
thisModel = createTextModel(TEXT, LANGUAGE_ID);
208
});
209
210
teardown(() => {
211
thisModel.dispose();
212
languageRegistration.dispose();
213
});
214
215
ensureNoDisposablesAreLeakedInTestSuite();
216
217
test('getTokensForInvalidLines one text insert', () => {
218
thisModel.tokenization.forceTokenization(5);
219
assert.deepStrictEqual(getAndClear(), ['Line1', 'Line2', 'Line3', 'Line4', 'Line5']);
220
thisModel.applyEdits([EditOperation.insert(new Position(1, 6), '-')]);
221
thisModel.tokenization.forceTokenization(5);
222
assert.deepStrictEqual(getAndClear(), ['Line1-', 'Line2']);
223
});
224
225
test('getTokensForInvalidLines two text insert', () => {
226
thisModel.tokenization.forceTokenization(5);
227
assert.deepStrictEqual(getAndClear(), ['Line1', 'Line2', 'Line3', 'Line4', 'Line5']);
228
thisModel.applyEdits([
229
EditOperation.insert(new Position(1, 6), '-'),
230
EditOperation.insert(new Position(3, 6), '-')
231
]);
232
233
thisModel.tokenization.forceTokenization(5);
234
assert.deepStrictEqual(getAndClear(), ['Line1-', 'Line2', 'Line3-', 'Line4']);
235
});
236
237
test('getTokensForInvalidLines one multi-line text insert, one small text insert', () => {
238
thisModel.tokenization.forceTokenization(5);
239
assert.deepStrictEqual(getAndClear(), ['Line1', 'Line2', 'Line3', 'Line4', 'Line5']);
240
thisModel.applyEdits([EditOperation.insert(new Position(1, 6), '\nNew line\nAnother new line')]);
241
thisModel.applyEdits([EditOperation.insert(new Position(5, 6), '-')]);
242
thisModel.tokenization.forceTokenization(7);
243
assert.deepStrictEqual(getAndClear(), ['Line1', 'New line', 'Another new line', 'Line2', 'Line3-', 'Line4']);
244
});
245
246
test('getTokensForInvalidLines one delete text', () => {
247
thisModel.tokenization.forceTokenization(5);
248
assert.deepStrictEqual(getAndClear(), ['Line1', 'Line2', 'Line3', 'Line4', 'Line5']);
249
thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 1, 5))]);
250
thisModel.tokenization.forceTokenization(5);
251
assert.deepStrictEqual(getAndClear(), ['1', 'Line2']);
252
});
253
254
test('getTokensForInvalidLines one line delete text', () => {
255
thisModel.tokenization.forceTokenization(5);
256
assert.deepStrictEqual(getAndClear(), ['Line1', 'Line2', 'Line3', 'Line4', 'Line5']);
257
thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 2, 1))]);
258
thisModel.tokenization.forceTokenization(4);
259
assert.deepStrictEqual(getAndClear(), ['Line2']);
260
});
261
262
test('getTokensForInvalidLines multiple lines delete text', () => {
263
thisModel.tokenization.forceTokenization(5);
264
assert.deepStrictEqual(getAndClear(), ['Line1', 'Line2', 'Line3', 'Line4', 'Line5']);
265
thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 3, 3))]);
266
thisModel.tokenization.forceTokenization(3);
267
assert.deepStrictEqual(getAndClear(), ['ne3', 'Line4']);
268
});
269
});
270
271