@codingame/monaco-vscode-treesitter-service-override 17.2.0 → 18.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/index.js +6 -12
  2. package/package.json +4 -5
  3. package/vscode/src/vs/amdX.d.ts +3 -0
  4. package/vscode/src/vs/amdX.js +188 -0
  5. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterLibraryService.d.ts +28 -0
  6. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterLibraryService.js +136 -0
  7. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterThemeService.d.ts +11 -0
  8. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterThemeService.js +26 -0
  9. package/vscode/src/vs/editor/common/model/tokenStore.d.ts +0 -65
  10. package/vscode/src/vs/editor/common/model/tokenStore.js +0 -412
  11. package/vscode/src/vs/editor/common/model/treeSitterTokenStoreService.d.ts +0 -32
  12. package/vscode/src/vs/editor/common/model/treeSitterTokenStoreService.js +0 -135
  13. package/vscode/src/vs/editor/common/services/treeSitter/cursorUtils.d.ts +0 -6
  14. package/vscode/src/vs/editor/common/services/treeSitter/cursorUtils.js +0 -76
  15. package/vscode/src/vs/editor/common/services/treeSitter/textModelTreeSitter.d.ts +0 -88
  16. package/vscode/src/vs/editor/common/services/treeSitter/textModelTreeSitter.js +0 -684
  17. package/vscode/src/vs/editor/common/services/treeSitter/treeSitterLanguages.d.ts +0 -31
  18. package/vscode/src/vs/editor/common/services/treeSitter/treeSitterLanguages.js +0 -120
  19. package/vscode/src/vs/editor/common/services/treeSitter/treeSitterParserService.d.ts +0 -48
  20. package/vscode/src/vs/editor/common/services/treeSitter/treeSitterParserService.js +0 -179
  21. package/vscode/src/vs/editor/common/services/treeSitterParserService.d.ts +0 -61
  22. package/vscode/src/vs/editor/common/services/treeSitterParserService.js +0 -36
  23. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterCodeEditors.d.ts +0 -32
  24. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterCodeEditors.js +0 -119
  25. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.contribution.d.ts +0 -1
  26. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.contribution.js +0 -54
  27. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.d.ts +0 -96
  28. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.js +0 -719
@@ -1,684 +0,0 @@
1
-
2
- import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
3
- import { ITreeSitterImporter } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/services/treeSitterParserService.service';
4
- import { Disposable, DisposableMap, DisposableStore, dispose } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
5
- import { ITelemetryService } from '@codingame/monaco-vscode-api/vscode/vs/platform/telemetry/common/telemetry.service';
6
- import { ILogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service';
7
- import { setTimeout0 } from '@codingame/monaco-vscode-api/vscode/vs/base/common/platform';
8
- import { Emitter, Event } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
9
- import { cancelOnDispose } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
10
- import { Range } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/core/range';
11
- import { LimitedQueue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
12
- import { TextLength } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/core/textLength';
13
- import { FileAccess } from '@codingame/monaco-vscode-api/vscode/vs/base/common/network';
14
- import { IFileService } from '@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service';
15
- import { isCancellationError, CancellationError } from '@codingame/monaco-vscode-api/vscode/vs/base/common/errors';
16
- import { gotoParent, getClosestPreviousNodes, nextSiblingOrParentSibling, gotoNthChild } from './cursorUtils.js';
17
-
18
- var TelemetryParseType;
19
- (function (TelemetryParseType) {
20
- TelemetryParseType["Full"] = "fullParse";
21
- TelemetryParseType["Incremental"] = "incrementalParse";
22
- })(TelemetryParseType || (TelemetryParseType = {}));
23
- let TextModelTreeSitter = class TextModelTreeSitter extends Disposable {
24
- get parseResult() { return this._rootTreeSitterTree; }
25
- constructor(textModel, _treeSitterLanguages, parseImmediately = true, _treeSitterImporter, _logService, _telemetryService, _fileService) {
26
- super();
27
- this.textModel = textModel;
28
- this._treeSitterLanguages = _treeSitterLanguages;
29
- this._treeSitterImporter = _treeSitterImporter;
30
- this._logService = _logService;
31
- this._telemetryService = _telemetryService;
32
- this._fileService = _fileService;
33
- this._onDidChangeParseResult = this._register(( new Emitter()));
34
- this.onDidChangeParseResult = this._onDidChangeParseResult.event;
35
- this._injectionTreeSitterTrees = this._register(( new DisposableMap()));
36
- this._versionId = 0;
37
- this._parseSessionDisposables = this._register(( new DisposableStore()));
38
- if (parseImmediately) {
39
- this._register(Event.runAndSubscribe(this.textModel.onDidChangeLanguage, (e => this._onDidChangeLanguage(e ? e.newLanguage : this.textModel.getLanguageId()))));
40
- }
41
- else {
42
- this._register(this.textModel.onDidChangeLanguage(e => this._onDidChangeLanguage(e ? e.newLanguage : this.textModel.getLanguageId())));
43
- }
44
- }
45
- async _onDidChangeLanguage(languageId) {
46
- this.parse(languageId);
47
- }
48
- async parse(languageId = this.textModel.getLanguageId()) {
49
- this._parseSessionDisposables.clear();
50
- this._rootTreeSitterTree = undefined;
51
- const token = cancelOnDispose(this._parseSessionDisposables);
52
- let language;
53
- try {
54
- language = await this._getLanguage(languageId, token);
55
- }
56
- catch (e) {
57
- if (isCancellationError(e)) {
58
- return;
59
- }
60
- throw e;
61
- }
62
- const Parser = await this._treeSitterImporter.getParserClass();
63
- if (token.isCancellationRequested) {
64
- return;
65
- }
66
- const treeSitterTree = this._parseSessionDisposables.add(( new TreeSitterParseResult(( new Parser()), languageId, language, this._logService, this._telemetryService)));
67
- this._rootTreeSitterTree = treeSitterTree;
68
- this._parseSessionDisposables.add(treeSitterTree.onDidUpdate(e => this._handleTreeUpdate(e)));
69
- this._parseSessionDisposables.add(this.textModel.onDidChangeContent(e => this._onDidChangeContent(treeSitterTree, [e])));
70
- this._onDidChangeContent(treeSitterTree, undefined);
71
- if (token.isCancellationRequested) {
72
- return;
73
- }
74
- return this._rootTreeSitterTree;
75
- }
76
- _getLanguage(languageId, token) {
77
- const language = this._treeSitterLanguages.getOrInitLanguage(languageId);
78
- if (language) {
79
- return Promise.resolve(language);
80
- }
81
- const disposables = [];
82
- return ( new Promise((resolve, reject) => {
83
- disposables.push(this._treeSitterLanguages.onDidAddLanguage(e => {
84
- if (e.id === languageId) {
85
- dispose(disposables);
86
- resolve(e.language);
87
- }
88
- }));
89
- token.onCancellationRequested(() => {
90
- dispose(disposables);
91
- reject(( new CancellationError()));
92
- }, undefined, disposables);
93
- }));
94
- }
95
- async _handleTreeUpdate(e, parentTreeResult, parentLanguage) {
96
- if (e.ranges && (e.versionId >= this._versionId)) {
97
- this._versionId = e.versionId;
98
- const tree = parentTreeResult ?? this._rootTreeSitterTree;
99
- let injections;
100
- if (tree.tree) {
101
- injections = await this._collectInjections(tree.tree);
102
- if (injections) {
103
- this._processInjections(injections, tree, parentLanguage ?? this.textModel.getLanguageId(), e.includedModelChanges);
104
- }
105
- }
106
- this._onDidChangeParseResult.fire({ ranges: e.ranges, versionId: e.versionId, tree: this, languageId: this.textModel.getLanguageId(), hasInjections: !!injections && injections.size > 0 });
107
- }
108
- }
109
- async _ensureInjectionQueries() {
110
- if (!this._queries) {
111
- const injectionsQueriesLocation = `vs/editor/common/languages/injections/${this.textModel.getLanguageId()}.scm`;
112
- const uri = ( FileAccess.asFileUri(injectionsQueriesLocation));
113
- if (!(await this._fileService.exists(uri))) {
114
- this._queries = '';
115
- }
116
- else if (this._fileService.hasProvider(uri)) {
117
- const query = await this._fileService.readFile(uri);
118
- this._queries = ( query.value.toString());
119
- }
120
- else {
121
- this._queries = '';
122
- }
123
- }
124
- return this._queries;
125
- }
126
- async _getQuery() {
127
- if (!this._query) {
128
- const language = await this._treeSitterLanguages.getLanguage(this.textModel.getLanguageId());
129
- if (!language) {
130
- return;
131
- }
132
- const queries = await this._ensureInjectionQueries();
133
- if (queries === '') {
134
- return;
135
- }
136
- const Query = await this._treeSitterImporter.getQueryClass();
137
- this._query = ( new Query(language, queries));
138
- }
139
- return this._query;
140
- }
141
- async _collectInjections(tree) {
142
- const query = await this._getQuery();
143
- if (!query) {
144
- return;
145
- }
146
- if (!tree?.rootNode) {
147
- return;
148
- }
149
- const cursor = tree.walk();
150
- const injections = ( new Map());
151
- let hasNext = true;
152
- while (hasNext) {
153
- hasNext = await this._processNode(cursor, query, injections);
154
- await ( new Promise(resolve => setTimeout0(resolve)));
155
- }
156
- return this._mergeAdjacentRanges(injections);
157
- }
158
- _processNode(cursor, query, injections) {
159
- const node = cursor.currentNode;
160
- const nodeLineCount = node.endPosition.row - node.startPosition.row;
161
- if (nodeLineCount <= 1000) {
162
- this._processCaptures(query, node, injections);
163
- return cursor.gotoNextSibling() || this.gotoNextSiblingOfAncestor(cursor);
164
- }
165
- else {
166
- return cursor.gotoFirstChild() || cursor.gotoNextSibling() || this.gotoNextSiblingOfAncestor(cursor);
167
- }
168
- }
169
- _processCaptures(query, node, injections) {
170
- const captures = query.captures(node);
171
- for (const capture of captures) {
172
- const injectionLanguage = capture.setProperties?.['injection.language'];
173
- if (injectionLanguage) {
174
- const range = this._createRangeFromNode(capture.node);
175
- if (!( injections.has(injectionLanguage))) {
176
- injections.set(injectionLanguage, []);
177
- }
178
- injections.get(injectionLanguage)?.push(range);
179
- }
180
- }
181
- }
182
- _createRangeFromNode(node) {
183
- return {
184
- startIndex: node.startIndex,
185
- endIndex: node.endIndex,
186
- startPosition: { row: node.startPosition.row, column: node.startPosition.column },
187
- endPosition: { row: node.endPosition.row, column: node.endPosition.column }
188
- };
189
- }
190
- _mergeAdjacentRanges(injections) {
191
- for (const [languageId, ranges] of injections) {
192
- if (ranges.length <= 1) {
193
- continue;
194
- }
195
- const mergedRanges = [];
196
- let current = ranges[0];
197
- for (let i = 1; i < ranges.length; i++) {
198
- const next = ranges[i];
199
- if (next.startIndex <= current.endIndex) {
200
- current = this._mergeRanges(current, next);
201
- }
202
- else {
203
- mergedRanges.push(current);
204
- current = next;
205
- }
206
- }
207
- mergedRanges.push(current);
208
- injections.set(languageId, mergedRanges);
209
- }
210
- return injections;
211
- }
212
- _mergeRanges(current, next) {
213
- return {
214
- startIndex: current.startIndex,
215
- endIndex: Math.max(current.endIndex, next.endIndex),
216
- startPosition: current.startPosition,
217
- endPosition: next.endPosition.row > current.endPosition.row ?
218
- next.endPosition :
219
- current.endPosition
220
- };
221
- }
222
- async _processInjections(injections, parentTree, parentLanguage, modelChanges) {
223
- if (injections.size === 0) {
224
- this._injectionTreeSitterTrees.clearAndDisposeAll();
225
- return;
226
- }
227
- const unseenInjections = ( new Set(( this._injectionTreeSitterTrees.keys())));
228
- for (const [languageId, ranges] of injections) {
229
- const language = await this._treeSitterLanguages.getLanguage(languageId);
230
- if (!language) {
231
- continue;
232
- }
233
- const treeSitterTree = await this._getOrCreateInjectedTree(languageId, language, parentTree, parentLanguage);
234
- if (treeSitterTree) {
235
- unseenInjections.delete(languageId);
236
- this._onDidChangeContent(treeSitterTree, modelChanges, ranges);
237
- }
238
- }
239
- for (const unseenInjection of unseenInjections) {
240
- this._injectionTreeSitterTrees.deleteAndDispose(unseenInjection);
241
- }
242
- }
243
- async _getOrCreateInjectedTree(languageId, language, parentTree, parentLanguage) {
244
- let treeSitterTree = this._injectionTreeSitterTrees.get(languageId);
245
- if (!treeSitterTree) {
246
- const Parser = await this._treeSitterImporter.getParserClass();
247
- treeSitterTree = ( new TreeSitterParseResult(( new Parser()), languageId, language, this._logService, this._telemetryService));
248
- this._parseSessionDisposables.add(treeSitterTree.onDidUpdate(e => this._handleTreeUpdate(e, parentTree, parentLanguage)));
249
- this._injectionTreeSitterTrees.set(languageId, treeSitterTree);
250
- }
251
- return treeSitterTree;
252
- }
253
- gotoNextSiblingOfAncestor(cursor) {
254
- while (cursor.gotoParent()) {
255
- if (cursor.gotoNextSibling()) {
256
- return true;
257
- }
258
- }
259
- return false;
260
- }
261
- getInjection(offset, parentLanguage) {
262
- if (this._injectionTreeSitterTrees.size === 0) {
263
- return undefined;
264
- }
265
- let hasFoundParentLanguage = parentLanguage === this.textModel.getLanguageId();
266
- for (const [_, treeSitterTree] of this._injectionTreeSitterTrees) {
267
- if (treeSitterTree.tree) {
268
- if (hasFoundParentLanguage && treeSitterTree.ranges?.find(r => r.startIndex <= offset && r.endIndex >= offset)) {
269
- return treeSitterTree;
270
- }
271
- if (!hasFoundParentLanguage && treeSitterTree.languageId === parentLanguage) {
272
- hasFoundParentLanguage = true;
273
- }
274
- }
275
- }
276
- return undefined;
277
- }
278
- _onDidChangeContent(treeSitterTree, change, ranges) {
279
- treeSitterTree.onDidChangeContent(this.textModel, change, ranges);
280
- }
281
- };
282
- TextModelTreeSitter = ( __decorate([
283
- ( __param(3, ITreeSitterImporter)),
284
- ( __param(4, ILogService)),
285
- ( __param(5, ITelemetryService)),
286
- ( __param(6, IFileService))
287
- ], TextModelTreeSitter));
288
- class TreeSitterParseResult {
289
- get versionId() {
290
- return this._versionId;
291
- }
292
- constructor(parser, languageId, language, _logService, _telemetryService) {
293
- this.parser = parser;
294
- this.languageId = languageId;
295
- this.language = language;
296
- this._logService = _logService;
297
- this._telemetryService = _telemetryService;
298
- this._onDidUpdate = ( new Emitter());
299
- this.onDidUpdate = this._onDidUpdate.event;
300
- this._versionId = 0;
301
- this._editVersion = 0;
302
- this._isDisposed = false;
303
- this._onDidChangeContentQueue = ( new LimitedQueue());
304
- this._lastYieldTime = 0;
305
- this.parser.setLanguage(language);
306
- }
307
- dispose() {
308
- this._isDisposed = true;
309
- this._onDidUpdate.dispose();
310
- this._tree?.delete();
311
- this._lastFullyParsed?.delete();
312
- this._lastFullyParsedWithEdits?.delete();
313
- this.parser?.delete();
314
- }
315
- get tree() { return this._lastFullyParsed; }
316
- get isDisposed() { return this._isDisposed; }
317
- findChangedNodes(newTree, oldTree) {
318
- const newCursor = newTree.walk();
319
- const oldCursor = oldTree.walk();
320
- const nodes = [];
321
- let next = true;
322
- do {
323
- if (newCursor.currentNode.hasChanges) {
324
- const newChildren = newCursor.currentNode.children;
325
- const indexChangedChildren = [];
326
- const changedChildren = newChildren.filter((c, index) => {
327
- if (c?.hasChanges || (oldCursor.currentNode.children.length <= index)) {
328
- indexChangedChildren.push(index);
329
- return true;
330
- }
331
- return false;
332
- });
333
- if ((changedChildren.length === 0) || (newCursor.currentNode.hasError !== oldCursor.currentNode.hasError)) {
334
- while (newCursor.currentNode.parent && next && !newCursor.currentNode.isNamed) {
335
- next = gotoParent(newCursor, oldCursor);
336
- }
337
- const newNode = newCursor.currentNode;
338
- const closestPreviousNode = getClosestPreviousNodes(newCursor, newTree) ?? newNode;
339
- nodes.push({
340
- startIndex: closestPreviousNode.startIndex,
341
- endIndex: newNode.endIndex,
342
- startPosition: closestPreviousNode.startPosition,
343
- endPosition: newNode.endPosition
344
- });
345
- next = nextSiblingOrParentSibling(newCursor, oldCursor);
346
- }
347
- else if (changedChildren.length >= 1) {
348
- next = gotoNthChild(newCursor, oldCursor, indexChangedChildren[0]);
349
- }
350
- }
351
- else {
352
- next = nextSiblingOrParentSibling(newCursor, oldCursor);
353
- }
354
- } while (next);
355
- return nodes;
356
- }
357
- findTreeChanges(newTree, changedNodes, newRanges) {
358
- let newRangeIndex = 0;
359
- const mergedChanges = [];
360
- for (let nodeIndex = 0; nodeIndex < changedNodes.length; nodeIndex++) {
361
- const node = changedNodes[nodeIndex];
362
- if (mergedChanges.length > 0) {
363
- if ((node.startIndex >= mergedChanges[mergedChanges.length - 1].newRangeStartOffset) && (node.endIndex <= mergedChanges[mergedChanges.length - 1].newRangeEndOffset)) {
364
- continue;
365
- }
366
- }
367
- const cursor = newTree.walk();
368
- const cursorContainersNode = () => cursor.startIndex < node.startIndex && cursor.endIndex > node.endIndex;
369
- while (cursorContainersNode()) {
370
- let child = cursor.gotoFirstChild();
371
- let foundChild = false;
372
- while (child) {
373
- if (cursorContainersNode() && cursor.currentNode.isNamed) {
374
- foundChild = true;
375
- break;
376
- }
377
- else {
378
- child = cursor.gotoNextSibling();
379
- }
380
- }
381
- if (!foundChild) {
382
- cursor.gotoParent();
383
- break;
384
- }
385
- if (cursor.currentNode.childCount === 0) {
386
- break;
387
- }
388
- }
389
- let nodesInRange;
390
- const foundNodeSize = cursor.endIndex - cursor.startIndex;
391
- if (foundNodeSize > 5000) {
392
- let child = cursor.gotoFirstChild();
393
- nodesInRange = [];
394
- while (child) {
395
- if (cursor.endIndex > node.startIndex) {
396
- nodesInRange.push(cursor.currentNode);
397
- do {
398
- child = cursor.gotoNextSibling();
399
- } while (child && (cursor.endIndex < node.endIndex));
400
- nodesInRange.push(cursor.currentNode);
401
- break;
402
- }
403
- child = cursor.gotoNextSibling();
404
- }
405
- }
406
- else {
407
- nodesInRange = [cursor.currentNode];
408
- }
409
- while (cursor.currentNode.id !== nodesInRange[0].id) {
410
- cursor.gotoPreviousSibling();
411
- }
412
- const previousNode = getClosestPreviousNodes(cursor, newTree);
413
- const startPosition = previousNode ? previousNode.endPosition : nodesInRange[0].startPosition;
414
- const startIndex = previousNode ? previousNode.endIndex : nodesInRange[0].startIndex;
415
- const endPosition = nodesInRange[nodesInRange.length - 1].endPosition;
416
- const endIndex = nodesInRange[nodesInRange.length - 1].endIndex;
417
- const newChange = { newRange: ( new Range(
418
- startPosition.row + 1,
419
- startPosition.column + 1,
420
- endPosition.row + 1,
421
- endPosition.column + 1
422
- )), newRangeStartOffset: startIndex, newRangeEndOffset: endIndex };
423
- if ((newRangeIndex < newRanges.length) && rangesIntersect(newRanges[newRangeIndex], { startIndex, endIndex})) {
424
- if (newRanges[newRangeIndex].startIndex < newChange.newRangeStartOffset) {
425
- newChange.newRange = newChange.newRange.setStartPosition(newRanges[newRangeIndex].startPosition.row + 1, newRanges[newRangeIndex].startPosition.column + 1);
426
- newChange.newRangeStartOffset = newRanges[newRangeIndex].startIndex;
427
- }
428
- if (newRanges[newRangeIndex].endIndex > newChange.newRangeEndOffset) {
429
- newChange.newRange = newChange.newRange.setEndPosition(newRanges[newRangeIndex].endPosition.row + 1, newRanges[newRangeIndex].endPosition.column + 1);
430
- newChange.newRangeEndOffset = newRanges[newRangeIndex].endIndex;
431
- }
432
- newRangeIndex++;
433
- }
434
- else if (newRangeIndex < newRanges.length && newRanges[newRangeIndex].endIndex < newChange.newRangeStartOffset) {
435
- mergedChanges.push({
436
- newRange: ( new Range(
437
- newRanges[newRangeIndex].startPosition.row + 1,
438
- newRanges[newRangeIndex].startPosition.column + 1,
439
- newRanges[newRangeIndex].endPosition.row + 1,
440
- newRanges[newRangeIndex].endPosition.column + 1
441
- )),
442
- newRangeStartOffset: newRanges[newRangeIndex].startIndex,
443
- newRangeEndOffset: newRanges[newRangeIndex].endIndex
444
- });
445
- }
446
- if ((mergedChanges.length > 0) && (mergedChanges[mergedChanges.length - 1].newRangeEndOffset >= newChange.newRangeStartOffset)) {
447
- mergedChanges[mergedChanges.length - 1].newRange = Range.fromPositions(mergedChanges[mergedChanges.length - 1].newRange.getStartPosition(), newChange.newRange.getEndPosition());
448
- mergedChanges[mergedChanges.length - 1].newRangeEndOffset = newChange.newRangeEndOffset;
449
- }
450
- else {
451
- mergedChanges.push(newChange);
452
- }
453
- }
454
- return this._constrainRanges(mergedChanges);
455
- }
456
- _constrainRanges(changes) {
457
- if (!this.ranges) {
458
- return changes;
459
- }
460
- const constrainedChanges = [];
461
- let changesIndex = 0;
462
- let rangesIndex = 0;
463
- while (changesIndex < changes.length && rangesIndex < this.ranges.length) {
464
- const change = changes[changesIndex];
465
- const range = this.ranges[rangesIndex];
466
- if (change.newRangeEndOffset < range.startIndex) {
467
- changesIndex++;
468
- }
469
- else if (change.newRangeStartOffset > range.endIndex) {
470
- rangesIndex++;
471
- }
472
- else {
473
- const newRangeStartOffset = Math.max(change.newRangeStartOffset, range.startIndex);
474
- const newRangeEndOffset = Math.min(change.newRangeEndOffset, range.endIndex);
475
- const newRange = change.newRange.intersectRanges(( new Range(
476
- range.startPosition.row + 1,
477
- range.startPosition.column + 1,
478
- range.endPosition.row + 1,
479
- range.endPosition.column + 1
480
- )));
481
- constrainedChanges.push({
482
- newRange,
483
- newRangeEndOffset,
484
- newRangeStartOffset
485
- });
486
- if (newRangeEndOffset < change.newRangeEndOffset) {
487
- change.newRange = Range.fromPositions(newRange.getEndPosition(), change.newRange.getEndPosition());
488
- change.newRangeStartOffset = newRangeEndOffset + 1;
489
- }
490
- else {
491
- changesIndex++;
492
- }
493
- }
494
- }
495
- return constrainedChanges;
496
- }
497
- onDidChangeContent(model, changes, ranges) {
498
- const version = model.getVersionId();
499
- if (version === this._editVersion) {
500
- return;
501
- }
502
- let newRanges = [];
503
- if (ranges) {
504
- newRanges = this._setRanges(ranges);
505
- }
506
- if (changes && changes.length > 0) {
507
- if (this._unfiredChanges) {
508
- this._unfiredChanges.push(...changes);
509
- }
510
- else {
511
- this._unfiredChanges = changes;
512
- }
513
- for (const change of changes) {
514
- this._applyEdits(change.changes, version);
515
- }
516
- }
517
- else {
518
- this._applyEdits([], version);
519
- }
520
- this._onDidChangeContentQueue.queue(async () => {
521
- if (this.isDisposed) {
522
- return;
523
- }
524
- const oldTree = this._lastFullyParsed;
525
- let changedNodes;
526
- if (this._lastFullyParsedWithEdits && this._lastFullyParsed) {
527
- changedNodes = this.findChangedNodes(this._lastFullyParsedWithEdits, this._lastFullyParsed);
528
- }
529
- const completed = await this._parseAndUpdateTree(model, version);
530
- if (completed) {
531
- let ranges;
532
- if (!changedNodes) {
533
- if (this._ranges) {
534
- ranges = ( this._ranges.map(r => ({ newRange: ( new Range(
535
- r.startPosition.row + 1,
536
- r.startPosition.column + 1,
537
- r.endPosition.row + 1,
538
- r.endPosition.column + 1
539
- )), oldRangeLength: r.endIndex - r.startIndex, newRangeStartOffset: r.startIndex, newRangeEndOffset: r.endIndex })));
540
- }
541
- else {
542
- ranges = [{ newRange: model.getFullModelRange(), newRangeStartOffset: 0, newRangeEndOffset: model.getValueLength() }];
543
- }
544
- }
545
- else if (oldTree && changedNodes) {
546
- ranges = this.findTreeChanges(completed, changedNodes, newRanges);
547
- }
548
- const changes = this._unfiredChanges ?? [];
549
- this._unfiredChanges = undefined;
550
- this._onDidUpdate.fire({ language: this.languageId, ranges, versionId: version, tree: completed, includedModelChanges: changes });
551
- }
552
- });
553
- }
554
- _applyEdits(changes, version) {
555
- for (const change of changes) {
556
- const originalTextLength = TextLength.ofRange(Range.lift(change.range));
557
- const newTextLength = TextLength.ofText(change.text);
558
- const summedTextLengths = change.text.length === 0 ? newTextLength : originalTextLength.add(newTextLength);
559
- const edit = {
560
- startIndex: change.rangeOffset,
561
- oldEndIndex: change.rangeOffset + change.rangeLength,
562
- newEndIndex: change.rangeOffset + change.text.length,
563
- startPosition: { row: change.range.startLineNumber - 1, column: change.range.startColumn - 1 },
564
- oldEndPosition: { row: change.range.endLineNumber - 1, column: change.range.endColumn - 1 },
565
- newEndPosition: { row: change.range.startLineNumber + summedTextLengths.lineCount - 1, column: summedTextLengths.lineCount ? summedTextLengths.columnCount : (change.range.endColumn + summedTextLengths.columnCount) }
566
- };
567
- this._tree?.edit(edit);
568
- this._lastFullyParsedWithEdits?.edit(edit);
569
- }
570
- this._editVersion = version;
571
- }
572
- async _parseAndUpdateTree(model, version) {
573
- const tree = await this._parse(model);
574
- if (tree) {
575
- this._tree?.delete();
576
- this._tree = tree;
577
- this._lastFullyParsed?.delete();
578
- this._lastFullyParsed = tree.copy();
579
- this._lastFullyParsedWithEdits?.delete();
580
- this._lastFullyParsedWithEdits = tree.copy();
581
- this._versionId = version;
582
- return tree;
583
- }
584
- else if (!this._tree) {
585
- this.parser.reset();
586
- }
587
- return undefined;
588
- }
589
- _parse(model) {
590
- let parseType = TelemetryParseType.Full;
591
- if (this.tree) {
592
- parseType = TelemetryParseType.Incremental;
593
- }
594
- return this._parseAndYield(model, parseType);
595
- }
596
- async _parseAndYield(model, parseType) {
597
- let time = 0;
598
- let passes = 0;
599
- const inProgressVersion = this._editVersion;
600
- let newTree;
601
- this._lastYieldTime = performance.now();
602
- do {
603
- const timer = performance.now();
604
- try {
605
- newTree = this.parser.parse((index, position) => this._parseCallback(model, index), this._tree, { progressCallback: this._parseProgressCallback.bind(this), includedRanges: this._ranges });
606
- }
607
- catch (e) {
608
- }
609
- finally {
610
- time += performance.now() - timer;
611
- passes++;
612
- }
613
- await ( new Promise(resolve => setTimeout0(resolve)));
614
- } while (!model.isDisposed() && !this.isDisposed && !newTree && inProgressVersion === model.getVersionId());
615
- this.sendParseTimeTelemetry(parseType, time, passes);
616
- return (newTree && (inProgressVersion === model.getVersionId())) ? newTree : undefined;
617
- }
618
- _parseProgressCallback(state) {
619
- const now = performance.now();
620
- if (now - this._lastYieldTime > 50) {
621
- this._lastYieldTime = now;
622
- return true;
623
- }
624
- return false;
625
- }
626
- _parseCallback(textModel, index) {
627
- try {
628
- return textModel.getTextBuffer().getNearestChunk(index);
629
- }
630
- catch (e) {
631
- this._logService.debug('Error getting chunk for tree-sitter parsing', e);
632
- }
633
- return undefined;
634
- }
635
- _setRanges(newRanges) {
636
- const unKnownRanges = [];
637
- if (this._ranges) {
638
- for (const newRange of newRanges) {
639
- let isFullyIncluded = false;
640
- for (let i = 0; i < this._ranges.length; i++) {
641
- const existingRange = this._ranges[i];
642
- if (rangesEqual(existingRange, newRange) || rangesIntersect(existingRange, newRange)) {
643
- isFullyIncluded = true;
644
- break;
645
- }
646
- }
647
- if (!isFullyIncluded) {
648
- unKnownRanges.push(newRange);
649
- }
650
- }
651
- }
652
- else {
653
- unKnownRanges.push(...newRanges);
654
- }
655
- this._ranges = newRanges;
656
- return unKnownRanges;
657
- }
658
- get ranges() {
659
- return this._ranges;
660
- }
661
- sendParseTimeTelemetry(parseType, time, passes) {
662
- this._logService.debug(`Tree parsing (${parseType}) took ${time} ms and ${passes} passes.`);
663
- if (parseType === TelemetryParseType.Full) {
664
- this._telemetryService.publicLog2(`treeSitter.fullParse`, { languageId: this.languageId, time, passes });
665
- }
666
- else {
667
- this._telemetryService.publicLog2(`treeSitter.incrementalParse`, { languageId: this.languageId, time, passes });
668
- }
669
- }
670
- }
671
- function rangesEqual(a, b) {
672
- return (a.startPosition.row === b.startPosition.row)
673
- && (a.startPosition.column === b.startPosition.column)
674
- && (a.endPosition.row === b.endPosition.row)
675
- && (a.endPosition.column === b.endPosition.column)
676
- && (a.startIndex === b.startIndex)
677
- && (a.endIndex === b.endIndex);
678
- }
679
- function rangesIntersect(a, b) {
680
- return (a.startIndex <= b.startIndex && a.endIndex >= b.startIndex) ||
681
- (b.startIndex <= a.startIndex && b.endIndex >= a.startIndex);
682
- }
683
-
684
- export { TextModelTreeSitter, TreeSitterParseResult };