@codingame/monaco-vscode-treesitter-service-override 10.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.
@@ -0,0 +1,325 @@
1
+ ; Order matters! Place lower precedence first.
2
+ ; Adapted from https://github.com/zed-industries/zed/blob/main/crates/languages/src/typescript/highlights.scm
3
+
4
+ ; Variables
5
+
6
+ (identifier) @variable
7
+
8
+ ; Literals
9
+
10
+ (this) @variable.language.this
11
+ (super) @variable.language.super
12
+
13
+ (comment) @comment
14
+
15
+ ; TODO: This doesn't seem to be working
16
+ (escape_sequence) @constant.character.escape
17
+
18
+ [
19
+ (string)
20
+ (template_string)
21
+ (template_literal_type)
22
+ ] @string
23
+
24
+ ; NOTE: the typescript grammar doesn't break regex into nice parts so as to capture parts of it separately
25
+ (regex) @string.regexp
26
+ (number) @constant.numeric
27
+
28
+ ; Template TODO: These don't seem to be working
29
+
30
+ (template_substitution
31
+ "${" @punctuation.definition.template-expression.begin
32
+ "}" @punctuation.definition.template-expression.end)
33
+
34
+ (template_type
35
+ "${" @punctuation.definition.template-expression.begin
36
+ "}" @punctuation.definition.template-expression.end)
37
+
38
+ (type_arguments
39
+ "<" @punctuation.bracket
40
+ ">" @punctuation.bracket)
41
+
42
+ ; Properties
43
+
44
+ (member_expression
45
+ object: (this)
46
+ property: (property_identifier) @variable)
47
+
48
+ (member_expression
49
+ property: (property_identifier) @variable.other.constant
50
+ (#match? @variable.other.constant "^[A-Z][A-Z_]+$"))
51
+
52
+ [
53
+ (property_identifier)
54
+ (shorthand_property_identifier)
55
+ (shorthand_property_identifier_pattern)] @variable
56
+
57
+ ; Function and method definitions
58
+
59
+ (function_expression
60
+ name: (identifier) @entity.name.function)
61
+ (function_declaration
62
+ name: (identifier) @entity.name.function)
63
+ (method_definition
64
+ name: (property_identifier) @meta.definition.method @entity.name.function)
65
+ (method_definition
66
+ name: (property_identifier) @storage.type
67
+ (#eq? @storage.type "constructor"))
68
+ (method_signature
69
+ name: (property_identifier) @meta.definition.method @entity.name.function)
70
+
71
+ (pair
72
+ key: (property_identifier) @entity.name.function
73
+ value: [(function_expression) (arrow_function)])
74
+
75
+ (assignment_expression
76
+ left: (member_expression
77
+ property: (property_identifier) @entity.name.function)
78
+ right: [(function_expression) (arrow_function)])
79
+
80
+ (variable_declarator
81
+ name: (identifier) @entity.name.function
82
+ value: [(function_expression) (arrow_function)])
83
+
84
+ (assignment_expression
85
+ left: (identifier) @entity.name.function
86
+ right: [(function_expression) (arrow_function)])
87
+
88
+ ; Function and method calls
89
+
90
+ (call_expression
91
+ function: (identifier) @entity.name.function)
92
+
93
+ (call_expression
94
+ function: (member_expression
95
+ object: (identifier) @support.class.promise)
96
+ (#eq? @support.class.promise "Promise"))
97
+
98
+ (call_expression
99
+ function: (member_expression
100
+ property: (property_identifier) @entity.name.function))
101
+
102
+ (new_expression
103
+ constructor: (identifier) @entity.name.function)
104
+
105
+
106
+ ; Special identifiers
107
+
108
+ (predefined_type) @support.type
109
+ (predefined_type (["string" "boolean" "number" "any"])) @support.type.primitive
110
+ (type_identifier) @entity.name.type
111
+
112
+ (("const")
113
+ (variable_declarator
114
+ name: (identifier) @variable.other.constant))
115
+
116
+ ([
117
+ (identifier)
118
+ (shorthand_property_identifier)
119
+ (shorthand_property_identifier_pattern)] @variable.other.constant
120
+ (#match? @variable.other.constant "^[A-Z][A-Z_]+$"))
121
+
122
+ (extends_clause
123
+ value: (identifier) @entity.other.inherited-class)
124
+
125
+ ; Tokens
126
+
127
+ [
128
+ ";"
129
+ "?."
130
+ "."
131
+ ","
132
+ ":"
133
+ "?"
134
+ ] @punctuation.delimiter
135
+
136
+ [
137
+ "!"
138
+ "~"
139
+ "==="
140
+ "!=="
141
+ "&&"
142
+ "||"
143
+ "??"
144
+ ] @keyword.operator.logical
145
+
146
+ (binary_expression ([
147
+ "-"
148
+ "+"
149
+ "*"
150
+ "/"
151
+ "%"
152
+ "^"
153
+ ]) @keyword.operator.arithmetic)
154
+
155
+ (binary_expression ([
156
+ "<"
157
+ "<="
158
+ ">"
159
+ ">="
160
+ ]) @keyword.operator.relational)
161
+
162
+ [
163
+ "="
164
+ ] @keyword.operator.assignment
165
+
166
+ (augmented_assignment_expression ([
167
+ "-="
168
+ "+="
169
+ "*="
170
+ "/="
171
+ "%="
172
+ "^="
173
+ "&="
174
+ "|="
175
+ "&&="
176
+ "||="
177
+ "??="
178
+ ]) @keyword.operator.assignment.compound)
179
+
180
+ [
181
+ "++"
182
+ ] @keyword.operator.increment
183
+
184
+ [
185
+ "--"
186
+ ] @keyword.operator.decrement
187
+
188
+ [
189
+ "**"
190
+ "**="
191
+ "<<"
192
+ "<<="
193
+ "=="
194
+ "!="
195
+ "=>"
196
+ ">>"
197
+ ">>="
198
+ ">>>"
199
+ ">>>="
200
+ "~"
201
+ "&"
202
+ "|"
203
+ ] @keyword.operator
204
+
205
+ ; Keywords
206
+
207
+ ("typeof") @keyword.operator.expression.typeof
208
+
209
+ (binary_expression "instanceof" @keyword.operator.expression.instanceof)
210
+
211
+ ("of") @keyword.operator.expression.of
212
+
213
+ ("is") @keyword.operator.expression.is
214
+
215
+ [
216
+ "delete"
217
+ "in"
218
+ "infer"
219
+ "keyof"
220
+ ] @keyword.operator.expression
221
+
222
+ [
223
+ "as"
224
+ "await"
225
+ "break"
226
+ "case"
227
+ "catch"
228
+ "continue"
229
+ "default"
230
+ "do"
231
+ "else"
232
+ "export"
233
+ "finally"
234
+ "for"
235
+ "from"
236
+ "if"
237
+ "import"
238
+ "require"
239
+ "return"
240
+ "satisfies"
241
+ "switch"
242
+ "throw"
243
+ "try"
244
+ "type"
245
+ "while"
246
+ "yield"
247
+ ] @keyword.control
248
+
249
+ [
250
+ "abstract"
251
+ "async"
252
+ "declare"
253
+ "extends"
254
+ "implements"
255
+ "override"
256
+ "private"
257
+ "protected"
258
+ "public"
259
+ "readonly"
260
+ "static"
261
+ ] @storage.modifier
262
+
263
+ [
264
+ "=>"
265
+ "class"
266
+ "const"
267
+ "enum"
268
+ "function"
269
+ "get"
270
+ "interface"
271
+ "let"
272
+ "namespace"
273
+ "set"
274
+ "var"
275
+ ] @storage.type
276
+
277
+ [
278
+ "debugger"
279
+ "target"
280
+ "with"
281
+ ] @keyword
282
+
283
+ (regex_flags) @keyword
284
+
285
+ [
286
+ "void"
287
+ ] @support.type.primitive
288
+
289
+ [
290
+ "new"
291
+ ] @keyword.operator.new
292
+
293
+ (public_field_definition
294
+ ("?") @keyword.operator.optional)
295
+
296
+ (optional_parameter)
297
+ ([
298
+ "?"
299
+ ":"
300
+ ]) @keyword.operator.optional
301
+
302
+ (ternary_expression
303
+ ([
304
+ "?"
305
+ ":"
306
+ ]) @keyword.operator.ternary)
307
+
308
+ (optional_chain
309
+ ("?.") @punctuation.accessor.optional)
310
+
311
+ (rest_pattern) @keyword.operator.rest
312
+
313
+ (spread_element) @keyword.operator.spread
314
+
315
+ ; Language constants
316
+
317
+ [
318
+ (true)
319
+ (false)
320
+ (null)
321
+ (undefined)
322
+ ] @constant.language
323
+
324
+ (namespace_import
325
+ "*" @constant.language)
package/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { default } from 'vscode/service-override/treesitter';
package/index.js ADDED
@@ -0,0 +1 @@
1
+ export { default } from './treesitter.js';
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@codingame/monaco-vscode-treesitter-service-override",
3
+ "version": "10.0.0",
4
+ "keywords": [],
5
+ "author": {
6
+ "name": "CodinGame",
7
+ "url": "http://www.codingame.com"
8
+ },
9
+ "license": "MIT",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git@github.com:CodinGame/monaco-vscode-api.git"
13
+ },
14
+ "type": "module",
15
+ "private": false,
16
+ "description": "VSCode public API plugged on the monaco editor - treesitter service-override",
17
+ "main": "index.js",
18
+ "module": "index.js",
19
+ "types": "index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "default": "./index.js"
23
+ },
24
+ "./vscode/*": {
25
+ "default": "./vscode/src/*.js"
26
+ }
27
+ },
28
+ "dependencies": {
29
+ "vscode": "npm:@codingame/monaco-vscode-api@10.0.0",
30
+ "@vscode/tree-sitter-wasm": "^0.0.4"
31
+ }
32
+ }
package/treesitter.js ADDED
@@ -0,0 +1,21 @@
1
+ import { SyncDescriptor } from 'vscode/vscode/vs/platform/instantiation/common/descriptors';
2
+ import { ITreeSitterParserService } from 'vscode/vscode/vs/editor/common/services/treeSitterParserService';
3
+ import { TreeSitterTextModelService } from './vscode/src/vs/editor/browser/services/treeSitter/treeSitterParserService.js';
4
+ import { ITreeSitterTokenizationFeature } from 'vscode/vscode/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.service';
5
+ import { TreeSitterTokenizationFeature } from './vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.js';
6
+ import { registerAssets } from 'vscode/assets';
7
+ import './vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.contribution.js';
8
+
9
+ registerAssets({
10
+ 'vs/../../node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.wasm': new URL('@vscode/tree-sitter-wasm/wasm/tree-sitter.wasm', import.meta.url).href,
11
+ 'vs/../../node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-typescript.wasm': new URL('@vscode/tree-sitter-wasm/wasm/tree-sitter-typescript.wasm', import.meta.url).href,
12
+ 'vs/editor/common/languages/highlights/typescript.scm': new URL('./assets/typescript.scm', import.meta.url).href
13
+ });
14
+ function getServiceOverride() {
15
+ return {
16
+ [( ITreeSitterParserService.toString())]: new SyncDescriptor(TreeSitterTextModelService, [], false),
17
+ [( ITreeSitterTokenizationFeature.toString())]: new SyncDescriptor(TreeSitterTokenizationFeature, [], false)
18
+ };
19
+ }
20
+
21
+ export { getServiceOverride as default };
@@ -0,0 +1,455 @@
1
+ import { __decorate, __param } from 'vscode/external/tslib/tslib.es6.js';
2
+ import { nodeModulesPath, FileAccess } from 'vscode/vscode/vs/base/common/network';
3
+ import { EDITOR_EXPERIMENTAL_PREFER_TREESITTER } from 'vscode/vscode/vs/editor/common/services/treeSitterParserService';
4
+ import { IModelService } from 'vscode/vscode/vs/editor/common/services/model';
5
+ import { Disposable, DisposableStore, dispose, DisposableMap } from 'vscode/vscode/vs/base/common/lifecycle';
6
+ import { IFileService } from 'vscode/vscode/vs/platform/files/common/files.service';
7
+ import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/telemetry.service';
8
+ import { ILogService } from 'vscode/vscode/vs/platform/log/common/log.service';
9
+ import { IConfigurationService } from 'vscode/vscode/vs/platform/configuration/common/configuration.service';
10
+ import { setTimeout0 } from 'vscode/vscode/vs/base/common/platform';
11
+ import { Emitter, Event } from 'vscode/vscode/vs/base/common/event';
12
+ import { cancelOnDispose } from 'vscode/vscode/vs/base/common/cancellation';
13
+ import { IEnvironmentService } from 'vscode/vscode/vs/platform/environment/common/environment.service';
14
+ import { isCancellationError, CancellationError } from 'vscode/vscode/vs/base/common/errors';
15
+ import 'vscode/vscode/vs/base/common/arrays';
16
+ import 'vscode/vscode/vs/base/common/observableInternal/autorun';
17
+ import 'vscode/vscode/vs/base/common/observableInternal/derived';
18
+ import { PromiseResult } from 'vscode/vscode/vs/base/common/observableInternal/promise';
19
+ import 'vscode/vscode/vs/base/common/observableInternal/utils';
20
+ import { Range } from 'vscode/vscode/vs/editor/common/core/range';
21
+
22
+ const EDITOR_TREESITTER_TELEMETRY = 'editor.experimental.treeSitterTelemetry';
23
+ const MODULE_LOCATION_SUBPATH = `@vscode/tree-sitter-wasm/wasm`;
24
+ const FILENAME_TREESITTER_WASM = `tree-sitter.wasm`;
25
+ function getModuleLocation(environmentService) {
26
+ return `${nodeModulesPath}/${MODULE_LOCATION_SUBPATH}`;
27
+ }
28
+ class TextModelTreeSitter extends Disposable {
29
+ get parseResult() { return this._parseResult; }
30
+ constructor(model, _treeSitterLanguages, _treeSitterImporter, _logService, _telemetryService) {
31
+ super();
32
+ this.model = model;
33
+ this._treeSitterLanguages = _treeSitterLanguages;
34
+ this._treeSitterImporter = _treeSitterImporter;
35
+ this._logService = _logService;
36
+ this._telemetryService = _telemetryService;
37
+ this._onDidChangeParseResult = this._register(( new Emitter()));
38
+ this.onDidChangeParseResult = this._onDidChangeParseResult.event;
39
+ this._languageSessionDisposables = this._register(( new DisposableStore()));
40
+ this._register(Event.runAndSubscribe(this.model.onDidChangeLanguage, (e => this._onDidChangeLanguage(e ? e.newLanguage : this.model.getLanguageId()))));
41
+ }
42
+ async _onDidChangeLanguage(languageId) {
43
+ this._languageSessionDisposables.clear();
44
+ this._parseResult = undefined;
45
+ const token = cancelOnDispose(this._languageSessionDisposables);
46
+ let language;
47
+ try {
48
+ language = await this._getLanguage(languageId, token);
49
+ }
50
+ catch (e) {
51
+ if (isCancellationError(e)) {
52
+ return;
53
+ }
54
+ throw e;
55
+ }
56
+ const Parser = await this._treeSitterImporter.getParserClass();
57
+ if (token.isCancellationRequested) {
58
+ return;
59
+ }
60
+ const treeSitterTree = this._languageSessionDisposables.add(( new TreeSitterParseResult(( new Parser()), language, this._logService, this._telemetryService)));
61
+ this._languageSessionDisposables.add(this.model.onDidChangeContent(e => this._onDidChangeContent(treeSitterTree, e.changes)));
62
+ await this._onDidChangeContent(treeSitterTree, []);
63
+ if (token.isCancellationRequested) {
64
+ return;
65
+ }
66
+ this._parseResult = treeSitterTree;
67
+ }
68
+ _getLanguage(languageId, token) {
69
+ const language = this._treeSitterLanguages.getOrInitLanguage(languageId);
70
+ if (language) {
71
+ return Promise.resolve(language);
72
+ }
73
+ const disposables = [];
74
+ return ( new Promise((resolve, reject) => {
75
+ disposables.push(this._treeSitterLanguages.onDidAddLanguage(e => {
76
+ if (e.id === languageId) {
77
+ dispose(disposables);
78
+ resolve(e.language);
79
+ }
80
+ }));
81
+ token.onCancellationRequested(() => {
82
+ dispose(disposables);
83
+ reject(( new CancellationError()));
84
+ }, undefined, disposables);
85
+ }));
86
+ }
87
+ async _onDidChangeContent(treeSitterTree, changes) {
88
+ const diff = await treeSitterTree.onDidChangeContent(this.model, changes);
89
+ if (!diff || diff.length > 0) {
90
+ const ranges = diff ? ( diff.map(r => ( new Range(
91
+ r.startPosition.row + 1,
92
+ r.startPosition.column + 1,
93
+ r.endPosition.row + 1,
94
+ r.endPosition.column + 1
95
+ )))) : [this.model.getFullModelRange()];
96
+ this._onDidChangeParseResult.fire(ranges);
97
+ }
98
+ }
99
+ }
100
+ class TreeSitterParseResult {
101
+ constructor(parser, language, _logService, _telemetryService) {
102
+ this.parser = parser;
103
+ this.language = language;
104
+ this._logService = _logService;
105
+ this._telemetryService = _telemetryService;
106
+ this._isDisposed = false;
107
+ this._onDidChangeContentQueue = Promise.resolve();
108
+ this._newEdits = true;
109
+ this.parser.setTimeoutMicros(50 * 1000);
110
+ this.parser.setLanguage(language);
111
+ }
112
+ dispose() {
113
+ this._isDisposed = true;
114
+ this._tree?.delete();
115
+ this.parser?.delete();
116
+ }
117
+ get tree() { return this._tree; }
118
+ set tree(newTree) {
119
+ this._tree?.delete();
120
+ this._tree = newTree;
121
+ }
122
+ get isDisposed() { return this._isDisposed; }
123
+ async onDidChangeContent(model, changes) {
124
+ const oldTree = this.tree?.copy();
125
+ this._applyEdits(model, changes);
126
+ return ( new Promise(resolve => {
127
+ this._onDidChangeContentQueue = this._onDidChangeContentQueue.then(async () => {
128
+ if (this.isDisposed) {
129
+ return;
130
+ }
131
+ await this._parseAndUpdateTree(model);
132
+ resolve((this.tree && oldTree) ? oldTree.getChangedRanges(this.tree) : undefined);
133
+ }).catch((e) => {
134
+ this._logService.error('Error parsing tree-sitter tree', e);
135
+ });
136
+ }));
137
+ }
138
+ _applyEdits(model, changes) {
139
+ for (const change of changes) {
140
+ const newEndOffset = change.rangeOffset + change.text.length;
141
+ const newEndPosition = model.getPositionAt(newEndOffset);
142
+ this.tree?.edit({
143
+ startIndex: change.rangeOffset,
144
+ oldEndIndex: change.rangeOffset + change.rangeLength,
145
+ newEndIndex: change.rangeOffset + change.text.length,
146
+ startPosition: { row: change.range.startLineNumber - 1, column: change.range.startColumn - 1 },
147
+ oldEndPosition: { row: change.range.endLineNumber - 1, column: change.range.endColumn - 1 },
148
+ newEndPosition: { row: newEndPosition.lineNumber - 1, column: newEndPosition.column - 1 }
149
+ });
150
+ this._newEdits = true;
151
+ }
152
+ }
153
+ async _parseAndUpdateTree(model) {
154
+ const tree = await this._parse(model);
155
+ if (!this._newEdits) {
156
+ this.tree = tree;
157
+ }
158
+ }
159
+ _parse(model) {
160
+ let parseType = "fullParse" ;
161
+ if (this.tree) {
162
+ parseType = "incrementalParse" ;
163
+ }
164
+ return this._parseAndYield(model, parseType);
165
+ }
166
+ async _parseAndYield(model, parseType) {
167
+ const language = model.getLanguageId();
168
+ let tree;
169
+ let time = 0;
170
+ let passes = 0;
171
+ this._newEdits = false;
172
+ do {
173
+ const timer = performance.now();
174
+ try {
175
+ tree = this.parser.parse((index, position) => this._parseCallback(model, index), this.tree);
176
+ }
177
+ catch (e) {
178
+ }
179
+ finally {
180
+ time += performance.now() - timer;
181
+ passes++;
182
+ }
183
+ await ( new Promise(resolve => setTimeout0(resolve)));
184
+ if (model.isDisposed() || this.isDisposed) {
185
+ return;
186
+ }
187
+ } while (!tree && !this._newEdits);
188
+ this.sendParseTimeTelemetry(parseType, language, time, passes);
189
+ return tree;
190
+ }
191
+ _parseCallback(textModel, index) {
192
+ try {
193
+ return textModel.getTextBuffer().getNearestChunk(index);
194
+ }
195
+ catch (e) {
196
+ this._logService.debug('Error getting chunk for tree-sitter parsing', e);
197
+ }
198
+ return null;
199
+ }
200
+ sendParseTimeTelemetry(parseType, languageId, time, passes) {
201
+ this._logService.debug(`Tree parsing (${parseType}) took ${time} ms and ${passes} passes.`);
202
+ if (parseType === "fullParse" ) {
203
+ this._telemetryService.publicLog2(`treeSitter.fullParse`, { languageId, time, passes });
204
+ }
205
+ else {
206
+ this._telemetryService.publicLog2(`treeSitter.incrementalParse`, { languageId, time, passes });
207
+ }
208
+ }
209
+ }
210
+ class TreeSitterLanguages extends Disposable {
211
+ constructor(_treeSitterImporter, _fileService, _environmentService, _registeredLanguages) {
212
+ super();
213
+ this._treeSitterImporter = _treeSitterImporter;
214
+ this._fileService = _fileService;
215
+ this._environmentService = _environmentService;
216
+ this._registeredLanguages = _registeredLanguages;
217
+ this._languages = ( new AsyncCache());
218
+ this._onDidAddLanguage = this._register(( new Emitter()));
219
+ this.onDidAddLanguage = this._onDidAddLanguage.event;
220
+ }
221
+ getOrInitLanguage(languageId) {
222
+ if (this._languages.isCached(languageId)) {
223
+ return this._languages.getSyncIfCached(languageId);
224
+ }
225
+ else {
226
+ this._addLanguage(languageId);
227
+ return undefined;
228
+ }
229
+ }
230
+ async getLanguage(languageId) {
231
+ if (this._languages.isCached(languageId)) {
232
+ return this._languages.getSyncIfCached(languageId);
233
+ }
234
+ else {
235
+ await this._addLanguage(languageId);
236
+ return this._languages.get(languageId);
237
+ }
238
+ }
239
+ async _addLanguage(languageId) {
240
+ const languagePromise = this._languages.get(languageId);
241
+ if (!languagePromise) {
242
+ this._languages.set(languageId, this._fetchLanguage(languageId));
243
+ const language = await this._languages.get(languageId);
244
+ if (!language) {
245
+ return undefined;
246
+ }
247
+ this._onDidAddLanguage.fire({ id: languageId, language });
248
+ }
249
+ }
250
+ async _fetchLanguage(languageId) {
251
+ const grammarName = this._registeredLanguages.get(languageId);
252
+ const languageLocation = this._getLanguageLocation(languageId);
253
+ if (!grammarName || !languageLocation) {
254
+ return undefined;
255
+ }
256
+ const wasmPath = `${languageLocation}/${grammarName}.wasm`;
257
+ const languageFile = await (this._fileService.readFile(( FileAccess.asFileUri(wasmPath))));
258
+ const Parser = await this._treeSitterImporter.getParserClass();
259
+ return Parser.Language.load(languageFile.value.buffer);
260
+ }
261
+ _getLanguageLocation(languageId) {
262
+ const grammarName = this._registeredLanguages.get(languageId);
263
+ if (!grammarName) {
264
+ return undefined;
265
+ }
266
+ return getModuleLocation();
267
+ }
268
+ }
269
+ class TreeSitterImporter {
270
+ async _getTreeSitterImport() {
271
+ if (!this._treeSitterImport) {
272
+ this._treeSitterImport = await import('@vscode/tree-sitter-wasm').then(module => ({ Parser: module.default ?? module }));
273
+ }
274
+ return this._treeSitterImport;
275
+ }
276
+ async getParserClass() {
277
+ if (!this._parserClass) {
278
+ this._parserClass = (await this._getTreeSitterImport()).Parser;
279
+ }
280
+ return this._parserClass;
281
+ }
282
+ }
283
+ let TreeSitterTextModelService = class TreeSitterTextModelService extends Disposable {
284
+ constructor(_modelService, fileService, _telemetryService, _logService, _configurationService, _environmentService) {
285
+ super();
286
+ this._modelService = _modelService;
287
+ this._telemetryService = _telemetryService;
288
+ this._logService = _logService;
289
+ this._configurationService = _configurationService;
290
+ this._environmentService = _environmentService;
291
+ this._textModelTreeSitters = this._register(( new DisposableMap()));
292
+ this._registeredLanguages = ( new Map());
293
+ this._treeSitterImporter = ( new TreeSitterImporter());
294
+ this._onDidUpdateTree = this._register(( new Emitter()));
295
+ this.onDidUpdateTree = this._onDidUpdateTree.event;
296
+ this._hasInit = false;
297
+ this._treeSitterLanguages = this._register(( new TreeSitterLanguages(
298
+ this._treeSitterImporter,
299
+ fileService,
300
+ this._environmentService,
301
+ this._registeredLanguages
302
+ )));
303
+ this.onDidAddLanguage = this._treeSitterLanguages.onDidAddLanguage;
304
+ this._register(this._configurationService.onDidChangeConfiguration(e => {
305
+ if (e.affectsConfiguration(EDITOR_EXPERIMENTAL_PREFER_TREESITTER)) {
306
+ this._supportedLanguagesChanged();
307
+ }
308
+ }));
309
+ this._supportedLanguagesChanged();
310
+ }
311
+ getOrInitLanguage(languageId) {
312
+ return this._treeSitterLanguages.getOrInitLanguage(languageId);
313
+ }
314
+ getParseResult(textModel) {
315
+ const textModelTreeSitter = this._textModelTreeSitters.get(textModel);
316
+ return textModelTreeSitter?.textModelTreeSitter.parseResult;
317
+ }
318
+ async getTree(content, languageId) {
319
+ await this._init;
320
+ const language = await this._treeSitterLanguages.getLanguage(languageId);
321
+ const Parser = await this._treeSitterImporter.getParserClass();
322
+ if (language) {
323
+ const parser = ( new Parser());
324
+ parser.setLanguage(language);
325
+ return parser.parse(content);
326
+ }
327
+ return undefined;
328
+ }
329
+ async _doInitParser() {
330
+ const Parser = await this._treeSitterImporter.getParserClass();
331
+ await Parser.init({
332
+ locateFile(_file, _folder) {
333
+ return ( ( FileAccess.asBrowserUri(`${getModuleLocation()}/${FILENAME_TREESITTER_WASM}`)).toString(true));
334
+ }
335
+ });
336
+ return true;
337
+ }
338
+ async _initParser(hasLanguages) {
339
+ if (this._hasInit) {
340
+ return this._init;
341
+ }
342
+ if (hasLanguages) {
343
+ this._hasInit = true;
344
+ this._init = this._doInitParser();
345
+ this._init.then(() => this._registerModelServiceListeners());
346
+ }
347
+ else {
348
+ this._init = Promise.resolve(false);
349
+ }
350
+ return this._init;
351
+ }
352
+ async _supportedLanguagesChanged() {
353
+ const setting = this._getSetting();
354
+ let hasLanguages = true;
355
+ if (setting.length === 0) {
356
+ hasLanguages = false;
357
+ }
358
+ if (setting.includes('typescript')) {
359
+ this._addGrammar('typescript', 'tree-sitter-typescript');
360
+ }
361
+ else {
362
+ this._removeGrammar('typescript');
363
+ }
364
+ return this._initParser(hasLanguages);
365
+ }
366
+ _getSetting() {
367
+ const setting = this._configurationService.getValue(EDITOR_EXPERIMENTAL_PREFER_TREESITTER);
368
+ if (setting && setting.length > 0) {
369
+ return setting;
370
+ }
371
+ else {
372
+ const expSetting = this._configurationService.getValue(EDITOR_TREESITTER_TELEMETRY);
373
+ if (expSetting) {
374
+ return ['typescript'];
375
+ }
376
+ }
377
+ return [];
378
+ }
379
+ async _registerModelServiceListeners() {
380
+ this._register(this._modelService.onModelAdded(model => {
381
+ this._createTextModelTreeSitter(model);
382
+ }));
383
+ this._register(this._modelService.onModelRemoved(model => {
384
+ this._textModelTreeSitters.deleteAndDispose(model);
385
+ }));
386
+ this._modelService.getModels().forEach(model => this._createTextModelTreeSitter(model));
387
+ }
388
+ _createTextModelTreeSitter(model) {
389
+ const textModelTreeSitter = ( new TextModelTreeSitter(
390
+ model,
391
+ this._treeSitterLanguages,
392
+ this._treeSitterImporter,
393
+ this._logService,
394
+ this._telemetryService
395
+ ));
396
+ const disposables = ( new DisposableStore());
397
+ disposables.add(textModelTreeSitter);
398
+ disposables.add(textModelTreeSitter.onDidChangeParseResult((ranges) => this._onDidUpdateTree.fire({ textModel: model, ranges })));
399
+ this._textModelTreeSitters.set(model, {
400
+ textModelTreeSitter,
401
+ disposables,
402
+ dispose: disposables.dispose.bind(disposables)
403
+ });
404
+ }
405
+ _addGrammar(languageId, grammarName) {
406
+ if (!( this._registeredLanguages.has(languageId))) {
407
+ this._registeredLanguages.set(languageId, grammarName);
408
+ }
409
+ }
410
+ _removeGrammar(languageId) {
411
+ if (( this._registeredLanguages.has(languageId))) {
412
+ this._registeredLanguages.delete('typescript');
413
+ }
414
+ }
415
+ };
416
+ TreeSitterTextModelService = ( __decorate([
417
+ ( __param(0, IModelService)),
418
+ ( __param(1, IFileService)),
419
+ ( __param(2, ITelemetryService)),
420
+ ( __param(3, ILogService)),
421
+ ( __param(4, IConfigurationService)),
422
+ ( __param(5, IEnvironmentService))
423
+ ], TreeSitterTextModelService));
424
+ class PromiseWithSyncAccess {
425
+ get result() {
426
+ return this._result;
427
+ }
428
+ constructor(promise) {
429
+ this.promise = promise;
430
+ promise.then(result => {
431
+ this._result = ( new PromiseResult(result, undefined));
432
+ }).catch(e => {
433
+ this._result = ( new PromiseResult(undefined, e));
434
+ });
435
+ }
436
+ }
437
+ class AsyncCache {
438
+ constructor() {
439
+ this._values = ( new Map());
440
+ }
441
+ set(key, promise) {
442
+ this._values.set(key, ( new PromiseWithSyncAccess(promise)));
443
+ }
444
+ get(key) {
445
+ return this._values.get(key)?.promise;
446
+ }
447
+ getSyncIfCached(key) {
448
+ return this._values.get(key)?.result?.data;
449
+ }
450
+ isCached(key) {
451
+ return this._values.get(key)?.result !== undefined;
452
+ }
453
+ }
454
+
455
+ export { TextModelTreeSitter, TreeSitterImporter, TreeSitterLanguages, TreeSitterParseResult, TreeSitterTextModelService };
@@ -0,0 +1,15 @@
1
+ import { __decorate, __param } from 'vscode/external/tslib/tslib.es6.js';
2
+ import { registerWorkbenchContribution2 } from 'vscode/vscode/vs/workbench/common/contributions';
3
+ import '../../../../editor/browser/services/treeSitter/treeSitterParserService.js';
4
+ import { ITreeSitterParserService } from 'vscode/vscode/vs/editor/common/services/treeSitterParserService';
5
+ import { ITreeSitterTokenizationFeature } from 'vscode/vscode/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.service';
6
+
7
+ let TreeSitterTokenizationInstantiator = class TreeSitterTokenizationInstantiator {
8
+ static { this.ID = 'workbench.contrib.treeSitterTokenizationInstantiator'; }
9
+ constructor(_treeSitterTokenizationService, _treeSitterTokenizationFeature) { }
10
+ };
11
+ TreeSitterTokenizationInstantiator = ( __decorate([
12
+ ( __param(0, ITreeSitterParserService)),
13
+ ( __param(1, ITreeSitterTokenizationFeature))
14
+ ], TreeSitterTokenizationInstantiator));
15
+ registerWorkbenchContribution2(TreeSitterTokenizationInstantiator.ID, TreeSitterTokenizationInstantiator, 2 );
@@ -0,0 +1,212 @@
1
+ import { __decorate, __param } from 'vscode/external/tslib/tslib.es6.js';
2
+ import { Emitter, Event } from 'vscode/vscode/vs/base/common/event';
3
+ import { Disposable, DisposableMap, DisposableStore } from 'vscode/vscode/vs/base/common/lifecycle';
4
+ import { FileAccess } from 'vscode/vscode/vs/base/common/network';
5
+ import { LazyTokenizationSupport, TreeSitterTokenizationRegistry } from 'vscode/vscode/vs/editor/common/languages';
6
+ import { EDITOR_EXPERIMENTAL_PREFER_TREESITTER, ITreeSitterParserService } from 'vscode/vscode/vs/editor/common/services/treeSitterParserService';
7
+ import { ColumnRange } from 'vscode/vscode/vs/editor/contrib/inlineCompletions/browser/utils';
8
+ import { IConfigurationService } from 'vscode/vscode/vs/platform/configuration/common/configuration.service';
9
+ import { IFileService } from 'vscode/vscode/vs/platform/files/common/files.service';
10
+ import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
11
+ import { IThemeService } from 'vscode/vscode/vs/platform/theme/common/themeService.service';
12
+ import { findMetadata } from 'vscode/vscode/vs/workbench/services/themes/common/colorThemeData';
13
+ import { ILanguageService } from 'vscode/vscode/vs/editor/common/languages/language';
14
+
15
+ const ALLOWED_SUPPORT = ['typescript'];
16
+ let TreeSitterTokenizationFeature = class TreeSitterTokenizationFeature extends Disposable {
17
+ constructor(_languageService, _configurationService, _instantiationService, _fileService) {
18
+ super();
19
+ this._languageService = _languageService;
20
+ this._configurationService = _configurationService;
21
+ this._instantiationService = _instantiationService;
22
+ this._fileService = _fileService;
23
+ this._tokenizersRegistrations = ( new DisposableMap());
24
+ this._handleGrammarsExtPoint();
25
+ this._register(this._configurationService.onDidChangeConfiguration(e => {
26
+ if (e.affectsConfiguration(EDITOR_EXPERIMENTAL_PREFER_TREESITTER)) {
27
+ this._handleGrammarsExtPoint();
28
+ }
29
+ }));
30
+ }
31
+ _getSetting() {
32
+ return this._configurationService.getValue(EDITOR_EXPERIMENTAL_PREFER_TREESITTER) || [];
33
+ }
34
+ _handleGrammarsExtPoint() {
35
+ const setting = this._getSetting();
36
+ for (const languageId of setting) {
37
+ if (ALLOWED_SUPPORT.includes(languageId) && !( this._tokenizersRegistrations.has(languageId))) {
38
+ const lazyTokenizationSupport = ( new LazyTokenizationSupport(() => this._createTokenizationSupport(languageId)));
39
+ const disposableStore = ( new DisposableStore());
40
+ disposableStore.add(lazyTokenizationSupport);
41
+ disposableStore.add(TreeSitterTokenizationRegistry.registerFactory(languageId, lazyTokenizationSupport));
42
+ this._tokenizersRegistrations.set(languageId, disposableStore);
43
+ TreeSitterTokenizationRegistry.getOrCreate(languageId);
44
+ }
45
+ }
46
+ const languagesToUnregister = [...( this._tokenizersRegistrations.keys())].filter(languageId => !setting.includes(languageId));
47
+ for (const languageId of languagesToUnregister) {
48
+ this._tokenizersRegistrations.deleteAndDispose(languageId);
49
+ }
50
+ }
51
+ async _fetchQueries(newLanguage) {
52
+ const languageLocation = `vs/editor/common/languages/highlights/${newLanguage}.scm`;
53
+ const query = await this._fileService.readFile(( FileAccess.asFileUri(languageLocation)));
54
+ return ( query.value.toString());
55
+ }
56
+ async _createTokenizationSupport(languageId) {
57
+ const queries = await this._fetchQueries(languageId);
58
+ return this._instantiationService.createInstance(TreeSitterTokenizationSupport, queries, languageId, this._languageService.languageIdCodec);
59
+ }
60
+ };
61
+ TreeSitterTokenizationFeature = ( __decorate([
62
+ ( __param(0, ILanguageService)),
63
+ ( __param(1, IConfigurationService)),
64
+ ( __param(2, IInstantiationService)),
65
+ ( __param(3, IFileService))
66
+ ], TreeSitterTokenizationFeature));
67
+ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends Disposable {
68
+ constructor(_queries, _languageId, _languageIdCodec, _treeSitterService, _themeService) {
69
+ super();
70
+ this._queries = _queries;
71
+ this._languageId = _languageId;
72
+ this._languageIdCodec = _languageIdCodec;
73
+ this._treeSitterService = _treeSitterService;
74
+ this._themeService = _themeService;
75
+ this._onDidChangeTokens = ( new Emitter());
76
+ this.onDidChangeTokens = this._onDidChangeTokens.event;
77
+ this._register(Event.runAndSubscribe(this._themeService.onDidColorThemeChange, () => this.reset()));
78
+ this._register(this._treeSitterService.onDidUpdateTree((e) => {
79
+ const maxLine = e.textModel.getLineCount();
80
+ this._onDidChangeTokens.fire({
81
+ textModel: e.textModel,
82
+ changes: {
83
+ semanticTokensApplied: false,
84
+ ranges: ( e.ranges.map(
85
+ range => ({ fromLineNumber: range.startLineNumber, toLineNumber: range.endLineNumber < maxLine ? range.endLineNumber : maxLine })
86
+ )),
87
+ }
88
+ });
89
+ }));
90
+ }
91
+ _getTree(textModel) {
92
+ return this._treeSitterService.getParseResult(textModel);
93
+ }
94
+ _ensureQuery() {
95
+ if (!this._query) {
96
+ const language = this._treeSitterService.getOrInitLanguage(this._languageId);
97
+ if (!language) {
98
+ if (!this._languageAddedListener) {
99
+ this._languageAddedListener = this._register(Event.onceIf(this._treeSitterService.onDidAddLanguage, e => e.id === this._languageId)((e) => {
100
+ this._query = e.language.query(this._queries);
101
+ }));
102
+ }
103
+ return;
104
+ }
105
+ this._query = language.query(this._queries);
106
+ }
107
+ return this._query;
108
+ }
109
+ reset() {
110
+ this._colorThemeData = this._themeService.getColorTheme();
111
+ }
112
+ captureAtPosition(lineNumber, column, textModel) {
113
+ const tree = this._getTree(textModel);
114
+ const captures = this._captureAtRange(lineNumber, ( new ColumnRange(column, column)), tree?.tree);
115
+ return captures;
116
+ }
117
+ captureAtPositionTree(lineNumber, column, tree) {
118
+ const captures = this._captureAtRange(lineNumber, ( new ColumnRange(column, column)), tree);
119
+ return captures;
120
+ }
121
+ _captureAtRange(lineNumber, columnRange, tree) {
122
+ const query = this._ensureQuery();
123
+ if (!tree || !query) {
124
+ return [];
125
+ }
126
+ return query.captures(tree.rootNode, { startPosition: { row: lineNumber - 1, column: columnRange.startColumn - 1 }, endPosition: { row: lineNumber - 1, column: columnRange.endColumnExclusive } });
127
+ }
128
+ tokenizeEncoded(lineNumber, textModel) {
129
+ const lineLength = textModel.getLineMaxColumn(lineNumber);
130
+ const tree = this._getTree(textModel);
131
+ const captures = this._captureAtRange(lineNumber, ( new ColumnRange(1, lineLength)), tree?.tree);
132
+ if (captures.length === 0) {
133
+ return undefined;
134
+ }
135
+ const endOffsetsAndScopes = Array(captures.length);
136
+ endOffsetsAndScopes.fill({ endOffset: 0, scopes: [] });
137
+ let tokenIndex = 0;
138
+ const lineStartOffset = textModel.getOffsetAt({ lineNumber: lineNumber, column: 1 });
139
+ const increaseSizeOfTokensByOneToken = () => {
140
+ endOffsetsAndScopes.push({ endOffset: 0, scopes: [] });
141
+ };
142
+ const encodedLanguageId = this._languageIdCodec.encodeLanguageId(this._languageId);
143
+ for (let captureIndex = 0; captureIndex < captures.length; captureIndex++) {
144
+ const capture = captures[captureIndex];
145
+ const tokenEndIndex = capture.node.endIndex < lineStartOffset + lineLength ? capture.node.endIndex : lineStartOffset + lineLength;
146
+ const tokenStartIndex = capture.node.startIndex < lineStartOffset ? lineStartOffset : capture.node.startIndex;
147
+ const lineRelativeOffset = tokenEndIndex - lineStartOffset;
148
+ let previousTokenEnd;
149
+ const currentTokenLength = tokenEndIndex - tokenStartIndex;
150
+ if (captureIndex > 0) {
151
+ previousTokenEnd = endOffsetsAndScopes[(tokenIndex - 1)].endOffset;
152
+ }
153
+ else {
154
+ previousTokenEnd = tokenStartIndex - lineStartOffset - 1;
155
+ }
156
+ const intermediateTokenOffset = lineRelativeOffset - currentTokenLength;
157
+ if ((previousTokenEnd >= 0) && (previousTokenEnd < intermediateTokenOffset)) {
158
+ endOffsetsAndScopes[tokenIndex] = { endOffset: intermediateTokenOffset, scopes: [] };
159
+ tokenIndex++;
160
+ increaseSizeOfTokensByOneToken();
161
+ }
162
+ const addCurrentTokenToArray = () => {
163
+ endOffsetsAndScopes[tokenIndex] = { endOffset: lineRelativeOffset, scopes: [capture.name] };
164
+ tokenIndex++;
165
+ };
166
+ if (previousTokenEnd >= lineRelativeOffset) {
167
+ const previousTokenStartOffset = ((tokenIndex >= 2) ? endOffsetsAndScopes[tokenIndex - 2].endOffset : 0);
168
+ const originalPreviousTokenEndOffset = endOffsetsAndScopes[tokenIndex - 1].endOffset;
169
+ if ((previousTokenStartOffset + currentTokenLength) === originalPreviousTokenEndOffset) {
170
+ endOffsetsAndScopes[tokenIndex - 1].scopes.push(capture.name);
171
+ }
172
+ else {
173
+ endOffsetsAndScopes[tokenIndex - 1].endOffset = intermediateTokenOffset;
174
+ addCurrentTokenToArray();
175
+ increaseSizeOfTokensByOneToken();
176
+ endOffsetsAndScopes[tokenIndex].endOffset = originalPreviousTokenEndOffset;
177
+ endOffsetsAndScopes[tokenIndex].scopes = endOffsetsAndScopes[tokenIndex - 2].scopes;
178
+ tokenIndex++;
179
+ }
180
+ }
181
+ else {
182
+ addCurrentTokenToArray();
183
+ }
184
+ }
185
+ if (captures[captures.length - 1].node.endPosition.column + 1 < lineLength) {
186
+ increaseSizeOfTokensByOneToken();
187
+ endOffsetsAndScopes[tokenIndex].endOffset = lineLength - 1;
188
+ tokenIndex++;
189
+ }
190
+ const tokens = ( new Uint32Array((tokenIndex) * 2));
191
+ for (let i = 0; i < tokenIndex; i++) {
192
+ const token = endOffsetsAndScopes[i];
193
+ if (token.endOffset === 0 && token.scopes.length === 0) {
194
+ break;
195
+ }
196
+ tokens[i * 2] = token.endOffset;
197
+ tokens[i * 2 + 1] = findMetadata(this._colorThemeData, token.scopes, encodedLanguageId);
198
+ }
199
+ return tokens;
200
+ }
201
+ dispose() {
202
+ super.dispose();
203
+ this._query?.delete();
204
+ this._query = undefined;
205
+ }
206
+ };
207
+ TreeSitterTokenizationSupport = ( __decorate([
208
+ ( __param(3, ITreeSitterParserService)),
209
+ ( __param(4, IThemeService))
210
+ ], TreeSitterTokenizationSupport));
211
+
212
+ export { TreeSitterTokenizationFeature };