@codingame/monaco-vscode-treesitter-service-override 15.0.2 → 16.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 (22) hide show
  1. package/index.js +1 -1
  2. package/package.json +9 -6
  3. package/vscode/src/vs/editor/common/languages/highlights/typescript.scm +488 -0
  4. package/vscode/src/vs/editor/common/model/tokenStore.d.ts +0 -1
  5. package/vscode/src/vs/editor/common/model/tokenStore.js +14 -8
  6. package/vscode/src/vs/editor/common/model/treeSitterTokenStoreService.d.ts +3 -0
  7. package/vscode/src/vs/editor/common/model/treeSitterTokenStoreService.js +33 -27
  8. package/vscode/src/vs/editor/common/services/treeSitter/cursorUtils.d.ts +6 -0
  9. package/vscode/src/vs/editor/common/services/treeSitter/cursorUtils.js +76 -0
  10. package/vscode/src/vs/editor/common/services/treeSitter/textModelTreeSitter.d.ts +88 -0
  11. package/vscode/src/vs/editor/common/services/treeSitter/textModelTreeSitter.js +675 -0
  12. package/vscode/src/vs/editor/common/services/treeSitter/treeSitterLanguages.d.ts +30 -0
  13. package/vscode/src/vs/editor/common/services/treeSitter/treeSitterLanguages.js +102 -0
  14. package/vscode/src/vs/editor/common/services/treeSitter/treeSitterParserService.d.ts +8 -80
  15. package/vscode/src/vs/editor/common/services/treeSitter/treeSitterParserService.js +20 -522
  16. package/vscode/src/vs/editor/common/services/treeSitterParserService.d.ts +16 -3
  17. package/vscode/src/vs/editor/common/services/treeSitterParserService.js +1 -1
  18. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterCodeEditors.d.ts +7 -2
  19. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterCodeEditors.js +43 -22
  20. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.d.ts +14 -14
  21. package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.js +256 -169
  22. package/assets/typescript.scm +0 -388
@@ -16,13 +16,18 @@ import { StopWatch } from '@codingame/monaco-vscode-api/vscode/vs/base/common/st
16
16
  import { ITreeSitterTokenizationStoreService } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/model/treeSitterTokenStoreService.service';
17
17
  import { TokenQuality } from '../../../../editor/common/model/tokenStore.js';
18
18
  import { Range } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/core/range';
19
- import { ICodeEditorService } from '@codingame/monaco-vscode-api/vscode/vs/editor/browser/services/codeEditorService.service';
20
19
  import { setTimeout0 } from '@codingame/monaco-vscode-api/vscode/vs/base/common/platform';
21
20
  import { findLikelyRelevantLines } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/model/textModelTokens';
22
21
  import { TreeSitterCodeEditors } from './treeSitterCodeEditors.js';
23
- import { Position } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/core/position';
24
22
  import { IWorkbenchThemeService } from '@codingame/monaco-vscode-7ba0af96-90c2-5e11-ad7f-befdbbf246c8-common/vscode/vs/workbench/services/themes/common/workbenchThemeService.service';
23
+ import { Position } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/core/position';
25
24
 
25
+ const TREESITTER_BASE_SCOPES = {
26
+ 'css': 'source.css',
27
+ 'typescript': 'source.ts',
28
+ 'ini': 'source.ini',
29
+ 'regex': 'source.regex',
30
+ };
26
31
  const BRACKETS = /[\{\}\[\]\<\>\(\)]/g;
27
32
  let TreeSitterTokenizationFeature = class TreeSitterTokenizationFeature extends Disposable {
28
33
  constructor(_treeSitterImporter, _languageService, _configurationService, _instantiationService, _fileService) {
@@ -79,7 +84,7 @@ TreeSitterTokenizationFeature = ( __decorate([
79
84
  ( __param(4, IFileService))
80
85
  ], TreeSitterTokenizationFeature));
81
86
  let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends Disposable {
82
- constructor(_queries, Query, _languageId, _languageIdCodec, _treeSitterService, _themeService, _tokenizationStoreService, _codeEditorService, _instantiationService) {
87
+ constructor(_queries, Query, _languageId, _languageIdCodec, _treeSitterService, _themeService, _tokenizationStoreService, _instantiationService) {
83
88
  super();
84
89
  this._queries = _queries;
85
90
  this.Query = Query;
@@ -88,12 +93,11 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
88
93
  this._treeSitterService = _treeSitterService;
89
94
  this._themeService = _themeService;
90
95
  this._tokenizationStoreService = _tokenizationStoreService;
91
- this._codeEditorService = _codeEditorService;
92
96
  this._instantiationService = _instantiationService;
93
97
  this._onDidChangeTokens = this._register(( new Emitter()));
94
98
  this.onDidChangeTokens = this._onDidChangeTokens.event;
95
- this._onDidCompleteFirstTokenization = this._register(( new Emitter()));
96
- this.onDidCompleteFirstTokenization = this._onDidCompleteFirstTokenization.event;
99
+ this._onDidCompleteBackgroundTokenization = this._register(( new Emitter()));
100
+ this.onDidChangeBackgroundTokenization = this._onDidCompleteBackgroundTokenization.event;
97
101
  this._codeEditors = this._instantiationService.createInstance(TreeSitterCodeEditors, this._languageId);
98
102
  this._register(this._codeEditors.onDidChangeViewport(e => {
99
103
  this._parseAndTokenizeViewPort(e.model, e.ranges);
@@ -104,9 +108,8 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
104
108
  }
105
109
  });
106
110
  this._register(Event.runAndSubscribe(this._themeService.onDidColorThemeChange, (e) => this._updateTheme(e)));
107
- let hasDoneFullTokenization = false;
108
111
  this._register(this._treeSitterService.onDidUpdateTree((e) => {
109
- if (e.textModel.getLanguageId() !== this._languageId) {
112
+ if (e.languageId !== this._languageId) {
110
113
  return;
111
114
  }
112
115
  if (this._tokenizationStoreService.hasTokens(e.textModel)) {
@@ -117,27 +120,25 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
117
120
  if (e.versionId !== e.textModel.getVersionId()) {
118
121
  return;
119
122
  }
120
- let updatePromise;
121
123
  if (!this._tokenizationStoreService.hasTokens(e.textModel)) {
122
- updatePromise = this._firstTreeUpdate(e.textModel, e.versionId);
124
+ this._firstTreeUpdate(e.textModel, e.versionId, e.tree);
123
125
  }
124
126
  else {
125
- updatePromise = this._handleTreeUpdate(e);
126
- }
127
- if (!hasDoneFullTokenization) {
128
- hasDoneFullTokenization = true;
129
- updatePromise.then(() => {
130
- this._onDidCompleteFirstTokenization.fire({ textModel: e.textModel });
131
- });
127
+ this._handleTreeUpdate(e.ranges, e.textModel, e.versionId, e.tree);
132
128
  }
133
129
  }));
134
130
  }
131
+ get _encodedLanguageId() {
132
+ if (!this._encodedLanguage) {
133
+ this._encodedLanguage = this._languageIdCodec.encodeLanguageId(this._languageId);
134
+ }
135
+ return this._encodedLanguage;
136
+ }
135
137
  _setInitialTokens(textModel) {
136
138
  const tokens = this._createEmptyTokens(textModel);
137
139
  this._tokenizationStoreService.setTokens(textModel, tokens, TokenQuality.None);
138
140
  }
139
- _parseAndTokenizeViewPortRange(model, range, languageId, startOffsetOfRangeInDocument, endOffsetOfRangeInDocument) {
140
- const content = model.getValueInRange(range);
141
+ _forceParseAndTokenizeContent(model, range, startOffsetOfRangeInDocument, endOffsetOfRangeInDocument, content, asUpdate) {
141
142
  const likelyRelevantLines = findLikelyRelevantLines(model, range.startLineNumber).likelyRelevantLines;
142
143
  const likelyRelevantPrefix = likelyRelevantLines.join(model.getEOL());
143
144
  const tree = this._treeSitterService.getTreeSync(`${likelyRelevantPrefix}${content}`, this._languageId);
@@ -151,17 +152,21 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
151
152
  range.endColumn
152
153
  ));
153
154
  const captures = this._captureAtRange(treeRange, tree);
154
- const tokens = this._tokenizeCapturesWithMetadata(tree, captures, languageId, likelyRelevantPrefix.length, endOffsetOfRangeInDocument - startOffsetOfRangeInDocument);
155
+ const tokens = this._tokenizeCapturesWithMetadata(tree, captures, likelyRelevantPrefix.length, endOffsetOfRangeInDocument - startOffsetOfRangeInDocument + likelyRelevantPrefix.length);
155
156
  if (!tokens) {
156
157
  return;
157
158
  }
158
- return this._rangeTokensAsUpdates(startOffsetOfRangeInDocument, tokens.endOffsetsAndMetadata, likelyRelevantPrefix.length);
159
+ if (asUpdate) {
160
+ return this._rangeTokensAsUpdates(startOffsetOfRangeInDocument, tokens.endOffsetsAndMetadata, likelyRelevantPrefix.length);
161
+ }
162
+ else {
163
+ return tokens.endOffsetsAndMetadata;
164
+ }
159
165
  }
160
166
  async _parseAndTokenizeViewPort(model, viewportRanges) {
161
167
  if (!this._tokenizationStoreService.hasTokens(model)) {
162
168
  this._setInitialTokens(model);
163
169
  }
164
- const languageId = this._languageIdCodec.encodeLanguageId(this._languageId);
165
170
  for (const range of viewportRanges) {
166
171
  const startOffsetOfRangeInDocument = model.getOffsetAt(range.getStartPosition());
167
172
  const endOffsetOfRangeInDocument = model.getOffsetAt(range.getEndPosition());
@@ -169,7 +174,8 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
169
174
  if (this._tokenizationStoreService.rangeHasTokens(model, range, TokenQuality.ViewportGuess)) {
170
175
  continue;
171
176
  }
172
- const tokenUpdates = await this._parseAndTokenizeViewPortRange(model, range, languageId, startOffsetOfRangeInDocument, endOffsetOfRangeInDocument);
177
+ const content = model.getValueInRange(range);
178
+ const tokenUpdates = await this._forceParseAndTokenizeContent(model, range, startOffsetOfRangeInDocument, endOffsetOfRangeInDocument, content, true);
173
179
  if (!tokenUpdates || this._tokenizationStoreService.rangeHasTokens(model, range, TokenQuality.ViewportGuess)) {
174
180
  continue;
175
181
  }
@@ -182,27 +188,64 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
182
188
  this._onDidChangeTokens.fire({ textModel: model, changes: { semanticTokensApplied: false, ranges: [{ fromLineNumber: range.startLineNumber, toLineNumber: range.endLineNumber }] } });
183
189
  }
184
190
  }
191
+ guessTokensForLinesContent(lineNumber, textModel, lines) {
192
+ if (lines.length === 0) {
193
+ return undefined;
194
+ }
195
+ const lineContent = lines.join(textModel.getEOL());
196
+ const range = ( new Range(1, 1, lineNumber + lines.length, lines[lines.length - 1].length + 1));
197
+ const startOffset = textModel.getOffsetAt({ lineNumber, column: 1 });
198
+ const tokens = this._forceParseAndTokenizeContent(textModel, range, startOffset, startOffset + lineContent.length, lineContent, false);
199
+ if (!tokens) {
200
+ return undefined;
201
+ }
202
+ const tokensByLine = ( new Array(lines.length));
203
+ let tokensIndex = 0;
204
+ let tokenStartOffset = 0;
205
+ let lineStartOffset = 0;
206
+ for (let i = 0; i < lines.length; i++) {
207
+ const tokensForLine = [];
208
+ let moveToNextLine = false;
209
+ for (let j = tokensIndex; (!moveToNextLine && (j < tokens.length)); j++) {
210
+ const token = tokens[j];
211
+ const lineAdjustedEndOffset = token.endOffset - lineStartOffset;
212
+ const lineAdjustedStartOffset = tokenStartOffset - lineStartOffset;
213
+ if (lineAdjustedEndOffset <= lines[i].length) {
214
+ tokensForLine.push({ endOffset: lineAdjustedEndOffset, metadata: token.metadata });
215
+ tokensIndex++;
216
+ }
217
+ else if (lineAdjustedStartOffset < lines[i].length) {
218
+ const partialToken = { endOffset: lines[i].length, metadata: token.metadata };
219
+ tokensForLine.push(partialToken);
220
+ moveToNextLine = true;
221
+ }
222
+ else {
223
+ moveToNextLine = true;
224
+ }
225
+ tokenStartOffset = token.endOffset;
226
+ }
227
+ tokensByLine[i] = this._endOffsetTokensToUint32Array(tokensForLine);
228
+ lineStartOffset += lines[i].length + textModel.getEOL().length;
229
+ }
230
+ return tokensByLine;
231
+ }
185
232
  _emptyTokensForOffsetAndLength(offset, length, emptyToken) {
186
233
  return { token: emptyToken, length: offset + length, startOffsetInclusive: 0 };
187
234
  }
188
235
  _createEmptyTokens(textModel) {
189
- const languageId = this._languageIdCodec.encodeLanguageId(this._languageId);
190
- const emptyToken = this._emptyToken(languageId);
236
+ const emptyToken = this._emptyToken();
191
237
  const modelEndOffset = textModel.getValueLength();
192
238
  const emptyTokens = [this._emptyTokensForOffsetAndLength(0, modelEndOffset, emptyToken)];
193
239
  return emptyTokens;
194
240
  }
195
- _firstTreeUpdate(textModel, versionId) {
241
+ _firstTreeUpdate(textModel, versionId, tree) {
196
242
  this._setInitialTokens(textModel);
197
- return this._setViewPortTokens(textModel, versionId);
243
+ return this._setViewPortTokens(textModel, versionId, tree);
198
244
  }
199
- _codeEditorForModel(textModel) {
200
- return this._codeEditorService.listCodeEditors().find(editor => editor.getModel() === textModel);
201
- }
202
- _setViewPortTokens(textModel, versionId) {
245
+ _setViewPortTokens(textModel, versionId, tree) {
203
246
  const maxLine = textModel.getLineCount();
204
247
  let rangeChanges;
205
- const editor = this._codeEditorForModel(textModel);
248
+ const editor = this._codeEditors.getEditorForModel(textModel);
206
249
  if (editor) {
207
250
  const viewPort = editor.getVisibleRangesPlusViewportAboveBelow();
208
251
  const ranges = ( new Array(viewPort.length));
@@ -216,35 +259,41 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
216
259
  newRange: range,
217
260
  newRangeStartOffset,
218
261
  newRangeEndOffset,
219
- oldRangeLength: newRangeEndOffset - newRangeStartOffset
220
262
  };
221
263
  }
222
264
  }
223
265
  else {
224
266
  const valueLength = textModel.getValueLength();
225
- rangeChanges = [{ newRange: ( new Range(1, 1, maxLine, textModel.getLineMaxColumn(maxLine))), newRangeStartOffset: 0, newRangeEndOffset: valueLength, oldRangeLength: valueLength }];
267
+ rangeChanges = [{ newRange: ( new Range(1, 1, maxLine, textModel.getLineMaxColumn(maxLine))), newRangeStartOffset: 0, newRangeEndOffset: valueLength }];
226
268
  }
227
- return this._handleTreeUpdate({ ranges: rangeChanges, textModel, versionId });
269
+ return this._handleTreeUpdate(rangeChanges, textModel, versionId, tree);
228
270
  }
229
- _handleTreeUpdate(e) {
271
+ _handleTreeUpdate(ranges, textModel, versionId, textModelTreeSitter) {
272
+ const tree = textModelTreeSitter.parseResult?.tree;
273
+ if (!tree) {
274
+ return;
275
+ }
230
276
  const rangeChanges = [];
231
277
  const chunkSize = 1000;
232
- for (let i = 0; i < e.ranges.length; i++) {
233
- const rangeLinesLength = e.ranges[i].newRange.endLineNumber - e.ranges[i].newRange.startLineNumber;
278
+ for (let i = 0; i < ranges.length; i++) {
279
+ const rangeLinesLength = ranges[i].newRange.endLineNumber - ranges[i].newRange.startLineNumber;
234
280
  if (rangeLinesLength > chunkSize) {
235
- const fullRangeEndLineNumber = e.ranges[i].newRange.endLineNumber;
236
- let chunkLineStart = e.ranges[i].newRange.startLineNumber;
281
+ const fullRangeEndLineNumber = ranges[i].newRange.endLineNumber;
282
+ let chunkLineStart = ranges[i].newRange.startLineNumber;
283
+ let chunkColumnStart = ranges[i].newRange.startColumn;
237
284
  let chunkLineEnd = chunkLineStart + chunkSize;
238
285
  do {
239
- const chunkStartingPosition = ( new Position(chunkLineStart, 1));
240
- const chunkEndPosition = ( new Position(chunkLineEnd, e.textModel.getLineMaxColumn(chunkLineEnd)));
286
+ const chunkStartingPosition = ( new Position(chunkLineStart, chunkColumnStart));
287
+ const chunkEndColumn = ((chunkLineEnd === ranges[i].newRange.endLineNumber) ? ranges[i].newRange.endColumn : textModel.getLineMaxColumn(chunkLineEnd));
288
+ const chunkEndPosition = ( new Position(chunkLineEnd, chunkEndColumn));
241
289
  const chunkRange = Range.fromPositions(chunkStartingPosition, chunkEndPosition);
242
290
  rangeChanges.push({
243
291
  range: chunkRange,
244
- startOffset: e.textModel.getOffsetAt(chunkRange.getStartPosition()),
245
- endOffset: e.textModel.getOffsetAt(chunkRange.getEndPosition())
292
+ startOffset: textModel.getOffsetAt(chunkRange.getStartPosition()),
293
+ endOffset: textModel.getOffsetAt(chunkRange.getEndPosition())
246
294
  });
247
295
  chunkLineStart = chunkLineEnd + 1;
296
+ chunkColumnStart = 1;
248
297
  if (chunkLineEnd < fullRangeEndLineNumber && chunkLineEnd + chunkSize > fullRangeEndLineNumber) {
249
298
  chunkLineEnd = fullRangeEndLineNumber;
250
299
  }
@@ -254,51 +303,46 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
254
303
  } while (chunkLineEnd <= fullRangeEndLineNumber);
255
304
  }
256
305
  else {
257
- if ((i === 0) || (rangeChanges[i - 1].range.endLineNumber < e.ranges[i].newRange.startLineNumber)) {
258
- const range = ( new Range(
259
- e.ranges[i].newRange.startLineNumber,
260
- 1,
261
- e.ranges[i].newRange.endLineNumber,
262
- e.textModel.getLineMaxColumn(e.ranges[i].newRange.endLineNumber)
263
- ));
306
+ if ((i === 0) || (rangeChanges[i - 1].endOffset < ranges[i].newRangeStartOffset)) {
264
307
  rangeChanges.push({
265
- range,
266
- startOffset: e.textModel.getOffsetAt(range.getStartPosition()),
267
- endOffset: e.textModel.getOffsetAt(range.getEndPosition())
308
+ range: ranges[i].newRange,
309
+ startOffset: ranges[i].newRangeStartOffset,
310
+ endOffset: ranges[i].newRangeEndOffset
268
311
  });
269
312
  }
270
- else if (rangeChanges[i - 1].range.endLineNumber < e.ranges[i].newRange.endLineNumber) {
313
+ else if (rangeChanges[i - 1].endOffset < ranges[i].newRangeEndOffset) {
314
+ const startPosition = textModel.getPositionAt(rangeChanges[i - 1].endOffset + 1);
271
315
  const range = ( new Range(
272
- rangeChanges[i - 1].range.endLineNumber + 1,
273
- 1,
274
- e.ranges[i].newRange.endLineNumber,
275
- e.textModel.getLineMaxColumn(e.ranges[i].newRange.endLineNumber)
316
+ startPosition.lineNumber,
317
+ startPosition.column,
318
+ ranges[i].newRange.endLineNumber,
319
+ ranges[i].newRange.endColumn
276
320
  ));
277
321
  rangeChanges.push({
278
322
  range,
279
- startOffset: e.textModel.getOffsetAt(range.getStartPosition()),
280
- endOffset: e.textModel.getOffsetAt(range.getEndPosition())
323
+ startOffset: rangeChanges[i - 1].endOffset + 1,
324
+ endOffset: ranges[i].newRangeEndOffset
281
325
  });
282
326
  }
283
327
  }
284
328
  }
285
- const captures = ( rangeChanges.map(range => this._getTreeAndCaptures(range.range, e.textModel)));
286
- return this._updateTreeForRanges(e.textModel, rangeChanges, e.versionId, captures).then(() => {
287
- const tree = this._getTree(e.textModel);
288
- if (!e.textModel.isDisposed() && (tree?.versionId === e.textModel.getVersionId())) {
289
- this._refreshNeedsRefresh(e.textModel, e.versionId);
329
+ const captures = ( rangeChanges.map(range => this._getCaptures(range.range, textModelTreeSitter, tree)));
330
+ return this._updateTreeForRanges(textModel, rangeChanges, versionId, tree, captures).then(() => {
331
+ const tree = this._getTree(textModel);
332
+ if (!textModel.isDisposed() && (tree?.parseResult?.versionId === textModel.getVersionId())) {
333
+ this._refreshNeedsRefresh(textModel, versionId);
290
334
  }
291
335
  });
292
336
  }
293
- async _updateTreeForRanges(textModel, rangeChanges, versionId, captures) {
337
+ async _updateTreeForRanges(textModel, rangeChanges, versionId, tree, captures) {
294
338
  let tokenUpdate;
295
339
  for (let i = 0; i < rangeChanges.length; i++) {
296
- if (versionId !== textModel.getVersionId()) {
340
+ if (!textModel.isDisposed() && versionId !== textModel.getVersionId()) {
297
341
  break;
298
342
  }
299
343
  const capture = captures[i];
300
344
  const range = rangeChanges[i];
301
- const updates = this.getTokensInRange(textModel, range.range, range.startOffset, range.endOffset, capture);
345
+ const updates = this.getTokensInRange(textModel, range.range, range.startOffset, range.endOffset, tree, capture);
302
346
  if (updates) {
303
347
  tokenUpdate = { newTokens: updates };
304
348
  }
@@ -315,6 +359,7 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
315
359
  });
316
360
  await ( new Promise(resolve => setTimeout0(resolve)));
317
361
  }
362
+ this._onDidCompleteBackgroundTokenization.fire({ textModel });
318
363
  }
319
364
  _refreshNeedsRefresh(textModel, versionId) {
320
365
  const rangesToRefresh = this._tokenizationStoreService.getNeedsRefresh(textModel);
@@ -327,11 +372,13 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
327
372
  rangeChanges[i] = {
328
373
  newRange: range.range,
329
374
  newRangeStartOffset: range.startOffset,
330
- newRangeEndOffset: range.endOffset,
331
- oldRangeLength: range.endOffset - range.startOffset
375
+ newRangeEndOffset: range.endOffset
332
376
  };
333
377
  }
334
- this._handleTreeUpdate({ ranges: rangeChanges, textModel, versionId });
378
+ const tree = this._getTree(textModel);
379
+ if (tree?.parseResult?.tree && tree.parseResult.versionId === versionId) {
380
+ this._handleTreeUpdate(rangeChanges, textModel, versionId, tree);
381
+ }
335
382
  }
336
383
  _rangeTokensAsUpdates(rangeOffset, endOffsetToken, startingOffsetInArray) {
337
384
  const updates = [];
@@ -352,9 +399,8 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
352
399
  }
353
400
  return updates;
354
401
  }
355
- getTokensInRange(textModel, range, rangeStartOffset, rangeEndOffset, captures) {
356
- const languageId = this._languageIdCodec.encodeLanguageId(this._languageId);
357
- const tokens = captures ? this._tokenizeCapturesWithMetadata(captures.tree?.tree, captures.captures, languageId, rangeStartOffset, rangeEndOffset) : this._tokenize(languageId, range, rangeStartOffset, rangeEndOffset, textModel);
402
+ getTokensInRange(textModel, range, rangeStartOffset, rangeEndOffset, tree, captures) {
403
+ const tokens = captures ? this._tokenizeCapturesWithMetadata(tree, captures, rangeStartOffset, rangeEndOffset) : this._tokenize(range, rangeStartOffset, rangeEndOffset, textModel);
358
404
  if (tokens?.endOffsetsAndMetadata) {
359
405
  return this._rangeTokensAsUpdates(rangeStartOffset, tokens.endOffsetsAndMetadata);
360
406
  }
@@ -380,34 +426,25 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
380
426
  }
381
427
  _updateTheme(e) {
382
428
  this._colorThemeData = this._themeService.getColorTheme();
383
- for (const editor of this._codeEditors.editors) {
384
- const model = editor.getModel();
385
- if (model) {
386
- const modelRange = model.getFullModelRange();
387
- this._tokenizationStoreService.markForRefresh(model, modelRange);
429
+ for (const model of this._codeEditors.textModels) {
430
+ const modelRange = model.getFullModelRange();
431
+ this._tokenizationStoreService.markForRefresh(model, modelRange);
432
+ const editor = this._codeEditors.getEditorForModel(model);
433
+ if (editor) {
388
434
  this._parseAndTokenizeViewPort(model, editor.getVisibleRangesPlusViewportAboveBelow());
389
- if (e?.target !== 'preview') {
390
- this._handleTreeUpdate({
391
- ranges: [{
392
- newRange: modelRange,
393
- newRangeStartOffset: 0,
394
- newRangeEndOffset: model.getValueLength(),
395
- oldRangeLength: model.getValueLength()
396
- }],
397
- textModel: model,
398
- versionId: model.getVersionId()
399
- });
400
- }
401
435
  }
402
436
  }
403
437
  }
404
438
  captureAtPosition(lineNumber, column, textModel) {
405
- const tree = this._getTree(textModel);
406
- const captures = this._captureAtRange(( new Range(lineNumber, column, lineNumber, column + 1)), tree?.tree);
439
+ const textModelTreeSitter = this._getTree(textModel);
440
+ if (!textModelTreeSitter?.parseResult?.tree) {
441
+ return [];
442
+ }
443
+ const captures = this._captureAtRangeWithInjections(( new Range(lineNumber, column, lineNumber, column + 1)), textModelTreeSitter, textModelTreeSitter.parseResult.tree);
407
444
  return captures;
408
445
  }
409
- captureAtPositionTree(lineNumber, column, tree) {
410
- const captures = this._captureAtRange(( new Range(lineNumber, column, lineNumber, column + 1)), tree);
446
+ captureAtRangeTree(range, tree, textModelTreeSitter) {
447
+ const captures = textModelTreeSitter ? this._captureAtRangeWithInjections(range, textModelTreeSitter, tree) : this._captureAtRange(range, tree);
411
448
  return captures;
412
449
  }
413
450
  _captureAtRange(range, tree) {
@@ -420,10 +457,44 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
420
457
  text: capture.node.text,
421
458
  node: {
422
459
  startIndex: capture.node.startIndex,
423
- endIndex: capture.node.endIndex
424
- }
460
+ endIndex: capture.node.endIndex,
461
+ startPosition: {
462
+ lineNumber: capture.node.startPosition.row + 1,
463
+ column: capture.node.startPosition.column + 1
464
+ },
465
+ endPosition: {
466
+ lineNumber: capture.node.endPosition.row + 1,
467
+ column: capture.node.endPosition.column + 1
468
+ }
469
+ },
470
+ encodedLanguageId: this._encodedLanguageId
425
471
  })));
426
472
  }
473
+ _captureAtRangeWithInjections(range, textModelTreeSitter, tree) {
474
+ const query = this._ensureQuery();
475
+ if (!textModelTreeSitter?.parseResult || !query) {
476
+ return [];
477
+ }
478
+ const captures = this._captureAtRange(range, tree);
479
+ for (let i = 0; i < captures.length; i++) {
480
+ const capture = captures[i];
481
+ const capStartLine = capture.node.startPosition.lineNumber;
482
+ const capEndLine = capture.node.endPosition.lineNumber;
483
+ const capStartColumn = capture.node.startPosition.column;
484
+ const capEndColumn = capture.node.endPosition.column;
485
+ const startLine = ((capStartLine > range.startLineNumber) && (capStartLine < range.endLineNumber)) ? capStartLine : range.startLineNumber;
486
+ const endLine = ((capEndLine > range.startLineNumber) && (capEndLine < range.endLineNumber)) ? capEndLine : range.endLineNumber;
487
+ const startColumn = (capStartLine === range.startLineNumber) ? (capStartColumn < range.startColumn ? range.startColumn : capStartColumn) : (capStartLine < range.startLineNumber ? range.startColumn : capStartColumn);
488
+ const endColumn = (capEndLine === range.endLineNumber) ? (capEndColumn > range.endColumn ? range.endColumn : capEndColumn) : (capEndLine > range.endLineNumber ? range.endColumn : capEndColumn);
489
+ const injectionRange = ( new Range(startLine, startColumn, endLine, endColumn));
490
+ const injection = this._getInjectionCaptures(textModelTreeSitter, capture, injectionRange);
491
+ if (injection && injection.length > 0) {
492
+ captures.splice(i + 1, 0, ...injection);
493
+ i += injection.length;
494
+ }
495
+ }
496
+ return captures;
497
+ }
427
498
  tokenizeEncoded(lineNumber, textModel) {
428
499
  const tokens = this._tokenizeEncoded(lineNumber, textModel);
429
500
  if (!tokens) {
@@ -441,35 +512,85 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
441
512
  }
442
513
  return { result: this._endOffsetTokensToUint32Array(tokens.result), captureTime: tokens.captureTime, metadataTime: tokens.metadataTime };
443
514
  }
444
- _getTreeAndCaptures(range, textModel) {
445
- const tree = this._getTree(textModel);
446
- const captures = this._captureAtRange(range, tree?.tree);
447
- return { tree, captures };
515
+ _getCaptures(range, textModelTreeSitter, tree) {
516
+ const captures = this._captureAtRangeWithInjections(range, textModelTreeSitter, tree);
517
+ return captures;
448
518
  }
449
- _tokenize(encodedLanguageId, range, rangeStartOffset, rangeEndOffset, textModel) {
450
- const { tree, captures } = this._getTreeAndCaptures(range, textModel);
451
- const result = this._tokenizeCapturesWithMetadata(tree?.tree, captures, encodedLanguageId, rangeStartOffset, rangeEndOffset);
452
- if (!tree || !result) {
519
+ _tokenize(range, rangeStartOffset, rangeEndOffset, textModel) {
520
+ const tree = this._getTree(textModel);
521
+ if (!tree?.parseResult?.tree) {
453
522
  return undefined;
454
523
  }
455
- return { ...result, versionId: tree.versionId };
524
+ const captures = this._getCaptures(range, tree, tree.parseResult.tree);
525
+ const result = this._tokenizeCapturesWithMetadata(tree.parseResult.tree, captures, rangeStartOffset, rangeEndOffset);
526
+ if (!result) {
527
+ return undefined;
528
+ }
529
+ return { ...result, versionId: tree.parseResult.versionId };
456
530
  }
457
531
  _createTokensFromCaptures(tree, captures, rangeStartOffset, rangeEndOffset) {
458
532
  const stopwatch = StopWatch.create();
459
533
  const rangeLength = rangeEndOffset - rangeStartOffset;
534
+ const encodedLanguageId = this._languageIdCodec.encodeLanguageId(this._languageId);
535
+ const baseScope = TREESITTER_BASE_SCOPES[this._languageId] || 'source';
460
536
  if (captures.length === 0) {
461
537
  if (tree) {
462
538
  stopwatch.stop();
463
- const endOffsetsAndMetadata = [{ endOffset: rangeLength, scopes: [] }];
539
+ const endOffsetsAndMetadata = [{ endOffset: rangeLength, scopes: [], encodedLanguageId }];
464
540
  return { endOffsets: endOffsetsAndMetadata, captureTime: stopwatch.elapsed() };
465
541
  }
466
542
  return undefined;
467
543
  }
468
544
  const endOffsetsAndScopes = Array(captures.length);
469
- endOffsetsAndScopes.fill({ endOffset: 0, scopes: [] });
545
+ endOffsetsAndScopes.fill({ endOffset: 0, scopes: [baseScope], encodedLanguageId });
470
546
  let tokenIndex = 0;
471
547
  const increaseSizeOfTokensByOneToken = () => {
472
- endOffsetsAndScopes.push({ endOffset: 0, scopes: [] });
548
+ endOffsetsAndScopes.push({ endOffset: 0, scopes: [baseScope], encodedLanguageId });
549
+ };
550
+ const brackets = (capture, startOffset) => {
551
+ return (capture.name.includes('punctuation') && capture.text) ? ( Array.from(capture.text.matchAll(BRACKETS)).map(match => startOffset + match.index)) : undefined;
552
+ };
553
+ const addCurrentTokenToArray = (capture, startOffset, endOffset, position) => {
554
+ if (position !== undefined) {
555
+ const oldScopes = endOffsetsAndScopes[position].scopes;
556
+ let oldBracket = endOffsetsAndScopes[position].bracket;
557
+ const prevEndOffset = position > 0 ? endOffsetsAndScopes[position - 1].endOffset : 0;
558
+ if (prevEndOffset !== startOffset) {
559
+ let preInsertBracket = undefined;
560
+ if (oldBracket && oldBracket.length > 0) {
561
+ preInsertBracket = [];
562
+ const postInsertBracket = [];
563
+ for (let i = 0; i < oldBracket.length; i++) {
564
+ const bracket = oldBracket[i];
565
+ if (bracket < startOffset) {
566
+ preInsertBracket.push(bracket);
567
+ }
568
+ else if (bracket > endOffset) {
569
+ postInsertBracket.push(bracket);
570
+ }
571
+ }
572
+ if (preInsertBracket.length === 0) {
573
+ preInsertBracket = undefined;
574
+ }
575
+ if (postInsertBracket.length === 0) {
576
+ oldBracket = undefined;
577
+ }
578
+ else {
579
+ oldBracket = postInsertBracket;
580
+ }
581
+ }
582
+ endOffsetsAndScopes.splice(position, 0, { endOffset: startOffset, scopes: [...oldScopes], bracket: preInsertBracket, encodedLanguageId: capture.encodedLanguageId });
583
+ position++;
584
+ increaseSizeOfTokensByOneToken();
585
+ tokenIndex++;
586
+ }
587
+ endOffsetsAndScopes.splice(position, 0, { endOffset: endOffset, scopes: [...oldScopes, capture.name], bracket: brackets(capture, startOffset), encodedLanguageId: capture.encodedLanguageId });
588
+ endOffsetsAndScopes[tokenIndex].bracket = oldBracket;
589
+ }
590
+ else {
591
+ endOffsetsAndScopes[tokenIndex] = { endOffset: endOffset, scopes: [baseScope, capture.name], bracket: brackets(capture, startOffset), encodedLanguageId: capture.encodedLanguageId };
592
+ }
593
+ tokenIndex++;
473
594
  };
474
595
  for (let captureIndex = 0; captureIndex < captures.length; captureIndex++) {
475
596
  const capture = captures[captureIndex];
@@ -486,57 +607,13 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
486
607
  }
487
608
  const startOffset = endOffset - currentTokenLength;
488
609
  if ((previousEndOffset >= 0) && (previousEndOffset < startOffset)) {
489
- endOffsetsAndScopes[tokenIndex] = { endOffset: startOffset, scopes: [] };
610
+ endOffsetsAndScopes[tokenIndex] = { endOffset: startOffset, scopes: [baseScope], encodedLanguageId: this._encodedLanguageId };
490
611
  tokenIndex++;
491
612
  increaseSizeOfTokensByOneToken();
492
613
  }
493
614
  if (currentTokenLength < 0) {
494
615
  continue;
495
616
  }
496
- const brackets = () => {
497
- return (capture.name.includes('punctuation') && capture.text) ? ( Array.from(capture.text.matchAll(BRACKETS)).map(match => startOffset + match.index)) : undefined;
498
- };
499
- const addCurrentTokenToArray = (position) => {
500
- if (position !== undefined) {
501
- let oldBracket = endOffsetsAndScopes[position].bracket;
502
- const prevEndOffset = position > 0 ? endOffsetsAndScopes[position - 1].endOffset : 0;
503
- if (prevEndOffset !== startOffset) {
504
- let preInsertBracket = undefined;
505
- if (oldBracket && oldBracket.length > 0) {
506
- preInsertBracket = [];
507
- const postInsertBracket = [];
508
- for (let i = 0; i < oldBracket.length; i++) {
509
- const bracket = oldBracket[i];
510
- if (bracket < startOffset) {
511
- preInsertBracket.push(bracket);
512
- }
513
- else if (bracket > endOffset) {
514
- postInsertBracket.push(bracket);
515
- }
516
- }
517
- if (preInsertBracket.length === 0) {
518
- preInsertBracket = undefined;
519
- }
520
- if (postInsertBracket.length === 0) {
521
- oldBracket = undefined;
522
- }
523
- else {
524
- oldBracket = postInsertBracket;
525
- }
526
- }
527
- endOffsetsAndScopes.splice(position, 0, { endOffset: startOffset, scopes: [...endOffsetsAndScopes[position].scopes], bracket: preInsertBracket });
528
- position++;
529
- increaseSizeOfTokensByOneToken();
530
- tokenIndex++;
531
- }
532
- endOffsetsAndScopes.splice(position, 0, { endOffset: endOffset, scopes: [capture.name], bracket: brackets() });
533
- endOffsetsAndScopes[tokenIndex].bracket = oldBracket;
534
- }
535
- else {
536
- endOffsetsAndScopes[tokenIndex] = { endOffset: endOffset, scopes: [capture.name], bracket: brackets() };
537
- }
538
- tokenIndex++;
539
- };
540
617
  if (previousEndOffset >= endOffset) {
541
618
  let withinTokenIndex = tokenIndex - 1;
542
619
  let previousTokenEndOffset = endOffsetsAndScopes[withinTokenIndex].endOffset;
@@ -544,12 +621,13 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
544
621
  do {
545
622
  if ((previousTokenStartOffset + currentTokenLength) === previousTokenEndOffset) {
546
623
  if (previousTokenStartOffset === startOffset) {
547
- endOffsetsAndScopes[withinTokenIndex].scopes[endOffsetsAndScopes[withinTokenIndex].scopes.length - 1] = capture.name;
548
- endOffsetsAndScopes[withinTokenIndex].bracket = brackets();
624
+ endOffsetsAndScopes[withinTokenIndex].scopes.push(capture.name);
625
+ const oldBracket = endOffsetsAndScopes[withinTokenIndex].bracket;
626
+ endOffsetsAndScopes[withinTokenIndex].bracket = ((oldBracket && (oldBracket.length > 0)) ? oldBracket : brackets(capture, startOffset));
549
627
  }
550
628
  }
551
629
  else if (previousTokenStartOffset <= startOffset) {
552
- addCurrentTokenToArray(withinTokenIndex);
630
+ addCurrentTokenToArray(capture, startOffset, endOffset, withinTokenIndex);
553
631
  break;
554
632
  }
555
633
  withinTokenIndex--;
@@ -558,13 +636,13 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
558
636
  } while (previousTokenEndOffset > startOffset);
559
637
  }
560
638
  else {
561
- addCurrentTokenToArray();
639
+ addCurrentTokenToArray(capture, startOffset, endOffset);
562
640
  }
563
641
  }
564
642
  if ((endOffsetsAndScopes[tokenIndex - 1].endOffset < rangeLength)) {
565
643
  if (rangeLength - endOffsetsAndScopes[tokenIndex - 1].endOffset > 0) {
566
644
  increaseSizeOfTokensByOneToken();
567
- endOffsetsAndScopes[tokenIndex] = { endOffset: rangeLength, scopes: endOffsetsAndScopes[tokenIndex].scopes };
645
+ endOffsetsAndScopes[tokenIndex] = { endOffset: rangeLength, scopes: endOffsetsAndScopes[tokenIndex].scopes, encodedLanguageId: this._encodedLanguageId };
568
646
  tokenIndex++;
569
647
  }
570
648
  }
@@ -578,7 +656,18 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
578
656
  const captureTime = stopwatch.elapsed();
579
657
  return { endOffsets: endOffsetsAndScopes, captureTime };
580
658
  }
581
- _tokenizeCapturesWithMetadata(tree, captures, encodedLanguageId, rangeStartOffset, rangeEndOffset) {
659
+ _getInjectionCaptures(textModelTreeSitter, parentCapture, range) {
660
+ const injection = textModelTreeSitter.getInjection(parentCapture.node.startIndex, this._languageId);
661
+ if (!injection?.tree || injection.versionId !== textModelTreeSitter.parseResult?.versionId) {
662
+ return undefined;
663
+ }
664
+ const feature = TreeSitterTokenizationRegistry.get(injection.languageId);
665
+ if (!feature) {
666
+ return undefined;
667
+ }
668
+ return feature.captureAtRangeTree(range, injection.tree, textModelTreeSitter);
669
+ }
670
+ _tokenizeCapturesWithMetadata(tree, captures, rangeStartOffset, rangeEndOffset) {
582
671
  const stopwatch = StopWatch.create();
583
672
  const emptyTokens = this._createTokensFromCaptures(tree, captures, rangeStartOffset, rangeEndOffset);
584
673
  if (!emptyTokens) {
@@ -587,21 +676,20 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
587
676
  const endOffsetsAndScopes = emptyTokens.endOffsets;
588
677
  for (let i = 0; i < endOffsetsAndScopes.length; i++) {
589
678
  const token = endOffsetsAndScopes[i];
590
- token.metadata = findMetadata(this._colorThemeData, token.scopes, encodedLanguageId, !!token.bracket && (token.bracket.length > 0));
679
+ token.metadata = findMetadata(this._colorThemeData, token.scopes, token.encodedLanguageId, !!token.bracket && (token.bracket.length > 0));
591
680
  }
592
681
  const metadataTime = stopwatch.elapsed();
593
682
  return { endOffsetsAndMetadata: endOffsetsAndScopes, captureTime: emptyTokens.captureTime, metadataTime };
594
683
  }
595
- _emptyToken(encodedLanguageId) {
596
- return findMetadata(this._colorThemeData, [], encodedLanguageId, false);
684
+ _emptyToken() {
685
+ return findMetadata(this._colorThemeData, [], this._encodedLanguageId, false);
597
686
  }
598
687
  _tokenizeEncoded(lineNumber, textModel) {
599
- const encodedLanguageId = this._languageIdCodec.encodeLanguageId(this._languageId);
600
688
  const lineOffset = textModel.getOffsetAt({ lineNumber: lineNumber, column: 1 });
601
689
  const maxLine = textModel.getLineCount();
602
690
  const lineEndOffset = (lineNumber + 1 <= maxLine) ? textModel.getOffsetAt({ lineNumber: lineNumber + 1, column: 1 }) : textModel.getValueLength();
603
691
  const lineLength = lineEndOffset - lineOffset;
604
- const result = this._tokenize(encodedLanguageId, ( new Range(lineNumber, 1, lineNumber, lineLength + 1)), lineOffset, lineEndOffset, textModel);
692
+ const result = this._tokenize(( new Range(lineNumber, 1, lineNumber, lineLength + 1)), lineOffset, lineEndOffset, textModel);
605
693
  if (!result) {
606
694
  return undefined;
607
695
  }
@@ -625,8 +713,7 @@ TreeSitterTokenizationSupport = ( __decorate([
625
713
  ( __param(4, ITreeSitterParserService)),
626
714
  ( __param(5, IWorkbenchThemeService)),
627
715
  ( __param(6, ITreeSitterTokenizationStoreService)),
628
- ( __param(7, ICodeEditorService)),
629
- ( __param(8, IInstantiationService))
716
+ ( __param(7, IInstantiationService))
630
717
  ], TreeSitterTokenizationSupport));
631
718
 
632
- export { TreeSitterTokenizationFeature, TreeSitterTokenizationSupport };
719
+ export { TREESITTER_BASE_SCOPES, TreeSitterTokenizationFeature, TreeSitterTokenizationSupport };