@codingame/monaco-vscode-treesitter-service-override 13.1.7 → 14.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.
- package/index.js +4 -2
- package/package.json +5 -4
- package/vscode/src/vs/editor/{browser → common}/services/treeSitter/treeSitterParserService.d.ts +19 -13
- package/vscode/src/vs/editor/{browser → common}/services/treeSitter/treeSitterParserService.js +260 -72
- package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.contribution.js +2 -2
- package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.d.ts +61 -0
- package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.js +270 -46
package/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import { SyncDescriptor } from '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/descriptors';
|
|
3
3
|
import { ITreeSitterParserService } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/services/treeSitterParserService';
|
|
4
|
-
import { TreeSitterTextModelService } from './vscode/src/vs/editor/
|
|
4
|
+
import { TreeSitterTextModelService } from './vscode/src/vs/editor/common/services/treeSitter/treeSitterParserService.js';
|
|
5
5
|
import { ITreeSitterTokenizationFeature } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.service';
|
|
6
6
|
import { TreeSitterTokenizationFeature } from './vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.js';
|
|
7
7
|
import { registerAssets } from '@codingame/monaco-vscode-api/assets';
|
|
8
|
+
import { ITreeSitterTokenizationStoreService, TreeSitterTokenizationStoreService } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/model/treeSitterTokenStoreService';
|
|
8
9
|
import './vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.contribution.js';
|
|
9
10
|
|
|
10
11
|
registerAssets({
|
|
@@ -15,7 +16,8 @@ registerAssets({
|
|
|
15
16
|
function getServiceOverride() {
|
|
16
17
|
return {
|
|
17
18
|
[ITreeSitterParserService.toString()]: new SyncDescriptor(TreeSitterTextModelService, [], false),
|
|
18
|
-
[ITreeSitterTokenizationFeature.toString()]: new SyncDescriptor(TreeSitterTokenizationFeature, [], false)
|
|
19
|
+
[ITreeSitterTokenizationFeature.toString()]: new SyncDescriptor(TreeSitterTokenizationFeature, [], false),
|
|
20
|
+
[ITreeSitterTokenizationStoreService.toString()]: new SyncDescriptor(TreeSitterTokenizationStoreService, [], false)
|
|
19
21
|
};
|
|
20
22
|
}
|
|
21
23
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codingame/monaco-vscode-treesitter-service-override",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "14.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "VSCode public API plugged on the monaco editor - treesitter service-override",
|
|
6
6
|
"keywords": [],
|
|
@@ -15,9 +15,10 @@
|
|
|
15
15
|
},
|
|
16
16
|
"type": "module",
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@codingame/monaco-vscode-
|
|
19
|
-
"@codingame/monaco-vscode-
|
|
20
|
-
"@
|
|
18
|
+
"@codingame/monaco-vscode-168b98e5-dc20-5807-b1f9-798f1f92b37f-common": "14.0.0",
|
|
19
|
+
"@codingame/monaco-vscode-9d0168a3-519b-57f3-9bcc-89efc41f951a-common": "14.0.0",
|
|
20
|
+
"@codingame/monaco-vscode-api": "14.0.0",
|
|
21
|
+
"@vscode/tree-sitter-wasm": "0.0.5"
|
|
21
22
|
},
|
|
22
23
|
"main": "index.js",
|
|
23
24
|
"module": "index.js",
|
package/vscode/src/vs/editor/{browser → common}/services/treeSitter/treeSitterParserService.d.ts
RENAMED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import type { Parser } from "@vscode/tree-sitter-wasm";
|
|
2
|
-
import { ITreeSitterParserService, ITreeSitterParseResult, ITextModelTreeSitter } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/services/treeSitterParserService";
|
|
2
|
+
import { ITreeSitterParserService, ITreeSitterParseResult, ITextModelTreeSitter, TreeUpdateEvent, TreeParseUpdateEvent } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/services/treeSitterParserService";
|
|
3
3
|
import { IModelService } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/services/model";
|
|
4
4
|
import { Disposable, IDisposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
|
|
5
5
|
import { ITextModel } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/model";
|
|
6
6
|
import { IFileService } from "@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service";
|
|
7
|
-
import {
|
|
7
|
+
import { IModelContentChangedEvent } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/textModelEvents";
|
|
8
8
|
import { ITelemetryService } from "@codingame/monaco-vscode-api/vscode/vs/platform/telemetry/common/telemetry.service";
|
|
9
9
|
import { ILogService } from "@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service";
|
|
10
10
|
import { IConfigurationService } from "@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service";
|
|
11
11
|
import { Emitter, Event } from "@codingame/monaco-vscode-api/vscode/vs/base/common/event";
|
|
12
12
|
import { IEnvironmentService } from "@codingame/monaco-vscode-api/vscode/vs/platform/environment/common/environment.service";
|
|
13
|
-
import { Range } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/core/range";
|
|
14
13
|
export declare class TextModelTreeSitter extends Disposable implements ITextModelTreeSitter {
|
|
15
14
|
readonly model: ITextModel;
|
|
16
15
|
private readonly _treeSitterLanguages;
|
|
@@ -18,11 +17,12 @@ export declare class TextModelTreeSitter extends Disposable implements ITextMode
|
|
|
18
17
|
private readonly _logService;
|
|
19
18
|
private readonly _telemetryService;
|
|
20
19
|
private _onDidChangeParseResult;
|
|
21
|
-
readonly onDidChangeParseResult: Event<
|
|
20
|
+
readonly onDidChangeParseResult: Event<TreeParseUpdateEvent>;
|
|
22
21
|
private _parseResult;
|
|
22
|
+
private _versionId;
|
|
23
23
|
get parseResult(): ITreeSitterParseResult | undefined;
|
|
24
24
|
constructor(model: ITextModel, _treeSitterLanguages: TreeSitterLanguages, _treeSitterImporter: TreeSitterImporter, _logService: ILogService, _telemetryService: ITelemetryService, parseImmediately?: boolean);
|
|
25
|
-
private readonly
|
|
25
|
+
private readonly _parseSessionDisposables;
|
|
26
26
|
private _onDidChangeLanguage;
|
|
27
27
|
parse(languageId?: string): Promise<ITreeSitterParseResult | undefined>;
|
|
28
28
|
private _getLanguage;
|
|
@@ -34,15 +34,22 @@ export declare class TreeSitterParseResult implements IDisposable, ITreeSitterPa
|
|
|
34
34
|
private readonly _logService;
|
|
35
35
|
private readonly _telemetryService;
|
|
36
36
|
private _tree;
|
|
37
|
+
private _lastFullyParsed;
|
|
38
|
+
private _lastFullyParsedWithEdits;
|
|
39
|
+
private readonly _onDidUpdate;
|
|
40
|
+
readonly onDidUpdate: Event<TreeParseUpdateEvent>;
|
|
41
|
+
private _versionId;
|
|
42
|
+
private _editVersion;
|
|
43
|
+
get versionId(): number;
|
|
37
44
|
private _isDisposed;
|
|
38
45
|
constructor(parser: Parser, language: Parser.Language, _logService: ILogService, _telemetryService: ITelemetryService);
|
|
39
46
|
dispose(): void;
|
|
40
47
|
get tree(): Parser.Tree | undefined;
|
|
41
|
-
private set tree(value);
|
|
42
48
|
get isDisposed(): boolean;
|
|
49
|
+
private findChangedNodes;
|
|
50
|
+
private calculateRangeChange;
|
|
43
51
|
private _onDidChangeContentQueue;
|
|
44
|
-
onDidChangeContent(model: ITextModel, changes:
|
|
45
|
-
private _newEdits;
|
|
52
|
+
onDidChangeContent(model: ITextModel, changes: IModelContentChangedEvent | undefined): void;
|
|
46
53
|
private _applyEdits;
|
|
47
54
|
private _parseAndUpdateTree;
|
|
48
55
|
private _parse;
|
|
@@ -94,21 +101,20 @@ export declare class TreeSitterTextModelService extends Disposable implements IT
|
|
|
94
101
|
language: Parser.Language;
|
|
95
102
|
}>;
|
|
96
103
|
private _onDidUpdateTree;
|
|
97
|
-
readonly onDidUpdateTree: Event<
|
|
98
|
-
|
|
99
|
-
ranges: Range[];
|
|
100
|
-
}>;
|
|
104
|
+
readonly onDidUpdateTree: Event<TreeUpdateEvent>;
|
|
105
|
+
isTest: boolean;
|
|
101
106
|
constructor(_modelService: IModelService, fileService: IFileService, _telemetryService: ITelemetryService, _logService: ILogService, _configurationService: IConfigurationService, _environmentService: IEnvironmentService);
|
|
102
107
|
getOrInitLanguage(languageId: string): Parser.Language | undefined;
|
|
103
108
|
getParseResult(textModel: ITextModel): ITreeSitterParseResult | undefined;
|
|
104
109
|
getTree(content: string, languageId: string): Promise<Parser.Tree | undefined>;
|
|
110
|
+
getLanguage(languageId: string): Promise<Parser.Language | undefined>;
|
|
105
111
|
private _doInitParser;
|
|
106
112
|
private _hasInit;
|
|
107
113
|
private _initParser;
|
|
108
114
|
private _supportedLanguagesChanged;
|
|
109
115
|
private _getSetting;
|
|
110
116
|
private _registerModelServiceListeners;
|
|
111
|
-
getTextModelTreeSitter(model: ITextModel): ITextModelTreeSitter
|
|
117
|
+
getTextModelTreeSitter(model: ITextModel, parseImmediately?: boolean): Promise<ITextModelTreeSitter>;
|
|
112
118
|
private _createTextModelTreeSitter;
|
|
113
119
|
private _addGrammar;
|
|
114
120
|
private _removeGrammar;
|
package/vscode/src/vs/editor/{browser → common}/services/treeSitter/treeSitterParserService.js
RENAMED
|
@@ -16,9 +16,12 @@ import { isCancellationError, CancellationError } from '@codingame/monaco-vscode
|
|
|
16
16
|
import '@codingame/monaco-vscode-api/vscode/vs/base/common/arrays';
|
|
17
17
|
import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/autorun';
|
|
18
18
|
import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/derived';
|
|
19
|
-
import { PromiseResult } from '@codingame/monaco-vscode-
|
|
19
|
+
import { PromiseResult } from '@codingame/monaco-vscode-168b98e5-dc20-5807-b1f9-798f1f92b37f-common/vscode/vs/base/common/observableInternal/promise';
|
|
20
20
|
import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/utils';
|
|
21
21
|
import { Range } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/core/range';
|
|
22
|
+
import { Position } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/core/position';
|
|
23
|
+
import { LimitedQueue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
|
|
24
|
+
import { TextLength } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/core/textLength';
|
|
22
25
|
|
|
23
26
|
const EDITOR_TREESITTER_TELEMETRY = 'editor.experimental.treeSitterTelemetry';
|
|
24
27
|
const MODULE_LOCATION_SUBPATH = `@vscode/tree-sitter-wasm/wasm`;
|
|
@@ -37,7 +40,8 @@ class TextModelTreeSitter extends Disposable {
|
|
|
37
40
|
this._telemetryService = _telemetryService;
|
|
38
41
|
this._onDidChangeParseResult = this._register(( new Emitter()));
|
|
39
42
|
this.onDidChangeParseResult = this._onDidChangeParseResult.event;
|
|
40
|
-
this.
|
|
43
|
+
this._versionId = 0;
|
|
44
|
+
this._parseSessionDisposables = this._register(( new DisposableStore()));
|
|
41
45
|
if (parseImmediately) {
|
|
42
46
|
this._register(Event.runAndSubscribe(this.model.onDidChangeLanguage, (e => this._onDidChangeLanguage(e ? e.newLanguage : this.model.getLanguageId()))));
|
|
43
47
|
}
|
|
@@ -49,9 +53,9 @@ class TextModelTreeSitter extends Disposable {
|
|
|
49
53
|
this.parse(languageId);
|
|
50
54
|
}
|
|
51
55
|
async parse(languageId = this.model.getLanguageId()) {
|
|
52
|
-
this.
|
|
56
|
+
this._parseSessionDisposables.clear();
|
|
53
57
|
this._parseResult = undefined;
|
|
54
|
-
const token = cancelOnDispose(this.
|
|
58
|
+
const token = cancelOnDispose(this._parseSessionDisposables);
|
|
55
59
|
let language;
|
|
56
60
|
try {
|
|
57
61
|
language = await this._getLanguage(languageId, token);
|
|
@@ -66,13 +70,19 @@ class TextModelTreeSitter extends Disposable {
|
|
|
66
70
|
if (token.isCancellationRequested) {
|
|
67
71
|
return;
|
|
68
72
|
}
|
|
69
|
-
const treeSitterTree = this.
|
|
70
|
-
this.
|
|
71
|
-
|
|
73
|
+
const treeSitterTree = this._parseSessionDisposables.add(( new TreeSitterParseResult(( new Parser()), language, this._logService, this._telemetryService)));
|
|
74
|
+
this._parseResult = treeSitterTree;
|
|
75
|
+
this._parseSessionDisposables.add(treeSitterTree.onDidUpdate(e => {
|
|
76
|
+
if (e.ranges && (e.versionId > this._versionId)) {
|
|
77
|
+
this._versionId = e.versionId;
|
|
78
|
+
this._onDidChangeParseResult.fire({ ranges: e.ranges, versionId: e.versionId });
|
|
79
|
+
}
|
|
80
|
+
}));
|
|
81
|
+
this._parseSessionDisposables.add(this.model.onDidChangeContent(e => this._onDidChangeContent(treeSitterTree, e)));
|
|
82
|
+
this._onDidChangeContent(treeSitterTree, undefined);
|
|
72
83
|
if (token.isCancellationRequested) {
|
|
73
84
|
return;
|
|
74
85
|
}
|
|
75
|
-
this._parseResult = treeSitterTree;
|
|
76
86
|
return this._parseResult;
|
|
77
87
|
}
|
|
78
88
|
_getLanguage(languageId, token) {
|
|
@@ -94,17 +104,8 @@ class TextModelTreeSitter extends Disposable {
|
|
|
94
104
|
}, undefined, disposables);
|
|
95
105
|
}));
|
|
96
106
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (!diff || diff.length > 0) {
|
|
100
|
-
const ranges = diff ? ( diff.map(r => ( new Range(
|
|
101
|
-
r.startPosition.row + 1,
|
|
102
|
-
r.startPosition.column + 1,
|
|
103
|
-
r.endPosition.row + 1,
|
|
104
|
-
r.endPosition.column + 1
|
|
105
|
-
)))) : [this.model.getFullModelRange()];
|
|
106
|
-
this._onDidChangeParseResult.fire(ranges);
|
|
107
|
-
}
|
|
107
|
+
_onDidChangeContent(treeSitterTree, change) {
|
|
108
|
+
return treeSitterTree.onDidChangeContent(this.model, change);
|
|
108
109
|
}
|
|
109
110
|
}
|
|
110
111
|
var TelemetryParseType;
|
|
@@ -113,63 +114,246 @@ var TelemetryParseType;
|
|
|
113
114
|
TelemetryParseType["Incremental"] = "incrementalParse";
|
|
114
115
|
})(TelemetryParseType || (TelemetryParseType = {}));
|
|
115
116
|
class TreeSitterParseResult {
|
|
117
|
+
get versionId() {
|
|
118
|
+
return this._versionId;
|
|
119
|
+
}
|
|
116
120
|
constructor(parser, language, _logService, _telemetryService) {
|
|
117
121
|
this.parser = parser;
|
|
118
122
|
this.language = language;
|
|
119
123
|
this._logService = _logService;
|
|
120
124
|
this._telemetryService = _telemetryService;
|
|
125
|
+
this._onDidUpdate = ( new Emitter());
|
|
126
|
+
this.onDidUpdate = this._onDidUpdate.event;
|
|
127
|
+
this._versionId = 0;
|
|
128
|
+
this._editVersion = 0;
|
|
121
129
|
this._isDisposed = false;
|
|
122
|
-
this._onDidChangeContentQueue =
|
|
123
|
-
this._newEdits = true;
|
|
130
|
+
this._onDidChangeContentQueue = ( new LimitedQueue());
|
|
124
131
|
this.parser.setTimeoutMicros(50 * 1000);
|
|
125
132
|
this.parser.setLanguage(language);
|
|
126
133
|
}
|
|
127
134
|
dispose() {
|
|
128
135
|
this._isDisposed = true;
|
|
136
|
+
this._onDidUpdate.dispose();
|
|
129
137
|
this._tree?.delete();
|
|
138
|
+
this._lastFullyParsed?.delete();
|
|
139
|
+
this._lastFullyParsedWithEdits?.delete();
|
|
130
140
|
this.parser?.delete();
|
|
131
141
|
}
|
|
132
|
-
get tree() { return this.
|
|
133
|
-
set tree(newTree) {
|
|
134
|
-
this._tree?.delete();
|
|
135
|
-
this._tree = newTree;
|
|
136
|
-
}
|
|
142
|
+
get tree() { return this._lastFullyParsed; }
|
|
137
143
|
get isDisposed() { return this._isDisposed; }
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
144
|
+
findChangedNodes(newTree, oldTree) {
|
|
145
|
+
const newCursor = newTree.walk();
|
|
146
|
+
const oldCursor = oldTree.walk();
|
|
147
|
+
const gotoNextSibling = () => {
|
|
148
|
+
const n = newCursor.gotoNextSibling();
|
|
149
|
+
const o = oldCursor.gotoNextSibling();
|
|
150
|
+
if (n !== o) {
|
|
151
|
+
throw ( new Error('Trees are out of sync'));
|
|
152
|
+
}
|
|
153
|
+
return n && o;
|
|
154
|
+
};
|
|
155
|
+
const gotoParent = () => {
|
|
156
|
+
const n = newCursor.gotoParent();
|
|
157
|
+
const o = oldCursor.gotoParent();
|
|
158
|
+
if (n !== o) {
|
|
159
|
+
throw ( new Error('Trees are out of sync'));
|
|
160
|
+
}
|
|
161
|
+
return n && o;
|
|
162
|
+
};
|
|
163
|
+
const gotoNthChild = (index) => {
|
|
164
|
+
const n = newCursor.gotoFirstChild();
|
|
165
|
+
const o = oldCursor.gotoFirstChild();
|
|
166
|
+
if (n !== o) {
|
|
167
|
+
throw ( new Error('Trees are out of sync'));
|
|
168
|
+
}
|
|
169
|
+
if (index === 0) {
|
|
170
|
+
return n && o;
|
|
171
|
+
}
|
|
172
|
+
for (let i = 1; i <= index; i++) {
|
|
173
|
+
const nn = newCursor.gotoNextSibling();
|
|
174
|
+
const oo = oldCursor.gotoNextSibling();
|
|
175
|
+
if (nn !== oo) {
|
|
176
|
+
throw ( new Error('Trees are out of sync'));
|
|
145
177
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
178
|
+
if (!nn || !oo) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return n && o;
|
|
183
|
+
};
|
|
184
|
+
const changedRanges = [];
|
|
185
|
+
let next = true;
|
|
186
|
+
const nextSiblingOrParentSibling = () => {
|
|
187
|
+
do {
|
|
188
|
+
if (newCursor.currentNode.nextSibling) {
|
|
189
|
+
return gotoNextSibling();
|
|
190
|
+
}
|
|
191
|
+
if (newCursor.currentNode.parent) {
|
|
192
|
+
gotoParent();
|
|
193
|
+
}
|
|
194
|
+
} while (newCursor.currentNode.nextSibling || newCursor.currentNode.parent);
|
|
195
|
+
return false;
|
|
196
|
+
};
|
|
197
|
+
const getClosestPreviousNodes = () => {
|
|
198
|
+
const newFindPrev = newTree.walk();
|
|
199
|
+
newFindPrev.resetTo(newCursor);
|
|
200
|
+
const oldFindPrev = oldTree.walk();
|
|
201
|
+
oldFindPrev.resetTo(oldCursor);
|
|
202
|
+
const startingNode = newCursor.currentNode;
|
|
203
|
+
do {
|
|
204
|
+
if (newFindPrev.currentNode.previousSibling && ((newFindPrev.currentNode.endIndex - newFindPrev.currentNode.startIndex) !== 0)) {
|
|
205
|
+
newFindPrev.gotoPreviousSibling();
|
|
206
|
+
oldFindPrev.gotoPreviousSibling();
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
while (!newFindPrev.currentNode.previousSibling && newFindPrev.currentNode.parent) {
|
|
210
|
+
newFindPrev.gotoParent();
|
|
211
|
+
oldFindPrev.gotoParent();
|
|
212
|
+
}
|
|
213
|
+
newFindPrev.gotoPreviousSibling();
|
|
214
|
+
oldFindPrev.gotoPreviousSibling();
|
|
215
|
+
}
|
|
216
|
+
} while ((newFindPrev.currentNode.endIndex > startingNode.startIndex)
|
|
217
|
+
&& (newFindPrev.currentNode.parent || newFindPrev.currentNode.previousSibling)
|
|
218
|
+
&& (newFindPrev.currentNode.id !== startingNode.id));
|
|
219
|
+
if ((newFindPrev.currentNode.id !== startingNode.id) && newFindPrev.currentNode.endIndex <= startingNode.startIndex) {
|
|
220
|
+
return { old: oldFindPrev.currentNode, new: newFindPrev.currentNode };
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
do {
|
|
227
|
+
if (newCursor.currentNode.hasChanges) {
|
|
228
|
+
const newChildren = newCursor.currentNode.children;
|
|
229
|
+
const indexChangedChildren = [];
|
|
230
|
+
const changedChildren = newChildren.filter((c, index) => {
|
|
231
|
+
if (c.hasChanges) {
|
|
232
|
+
indexChangedChildren.push(index);
|
|
233
|
+
}
|
|
234
|
+
return c.hasChanges;
|
|
235
|
+
});
|
|
236
|
+
if (changedChildren.length >= 1) {
|
|
237
|
+
next = gotoNthChild(indexChangedChildren[0]);
|
|
238
|
+
}
|
|
239
|
+
else if (changedChildren.length === 0) {
|
|
240
|
+
while (newCursor.currentNode.parent && !newCursor.currentNode.isNamed && next) {
|
|
241
|
+
next = gotoParent();
|
|
242
|
+
}
|
|
243
|
+
const newNode = newCursor.currentNode;
|
|
244
|
+
const oldNode = oldCursor.currentNode;
|
|
245
|
+
const newEndPosition = ( new Position(newNode.endPosition.row + 1, newNode.endPosition.column + 1));
|
|
246
|
+
const oldEndIndex = oldNode.endIndex;
|
|
247
|
+
const closestPrev = getClosestPreviousNodes();
|
|
248
|
+
const newStartPosition = ( new Position(
|
|
249
|
+
closestPrev ? closestPrev.new.endPosition.row + 1 : newNode.startPosition.row + 1,
|
|
250
|
+
closestPrev ? closestPrev.new.endPosition.column + 1 : newNode.startPosition.column + 1
|
|
251
|
+
));
|
|
252
|
+
const newStartIndex = closestPrev ? closestPrev.new.endIndex : newNode.startIndex;
|
|
253
|
+
const oldStartIndex = closestPrev ? closestPrev.old.endIndex : oldNode.startIndex;
|
|
254
|
+
changedRanges.push({ newStartPosition, newEndPosition, oldStartIndex, oldEndIndex, newNodeId: newNode.id, newStartIndex, newEndIndex: newNode.endIndex });
|
|
255
|
+
next = nextSiblingOrParentSibling();
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
next = nextSiblingOrParentSibling();
|
|
260
|
+
}
|
|
261
|
+
} while (next);
|
|
262
|
+
if (changedRanges.length === 0 && newTree.rootNode.hasChanges) {
|
|
263
|
+
return [{ newStartPosition: ( new Position(
|
|
264
|
+
newTree.rootNode.startPosition.row + 1,
|
|
265
|
+
newTree.rootNode.startPosition.column + 1
|
|
266
|
+
)), newEndPosition: ( new Position(
|
|
267
|
+
newTree.rootNode.endPosition.row + 1,
|
|
268
|
+
newTree.rootNode.endPosition.column + 1
|
|
269
|
+
)), oldStartIndex: oldTree.rootNode.startIndex, oldEndIndex: oldTree.rootNode.endIndex, newStartIndex: newTree.rootNode.startIndex, newEndIndex: newTree.rootNode.endIndex, newNodeId: newTree.rootNode.id }];
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
return changedRanges;
|
|
273
|
+
}
|
|
152
274
|
}
|
|
153
|
-
|
|
275
|
+
calculateRangeChange(changedNodes) {
|
|
276
|
+
if (!changedNodes) {
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
const ranges = [];
|
|
280
|
+
for (let i = 0; i < changedNodes.length; i++) {
|
|
281
|
+
const node = changedNodes[i];
|
|
282
|
+
const prevNode = changedNodes[i - 1];
|
|
283
|
+
if ((i > 0) && prevNode.newEndPosition.equals(node.newStartPosition)) {
|
|
284
|
+
const prevRangeChange = ranges[ranges.length - 1];
|
|
285
|
+
prevRangeChange.newRange = ( new Range(
|
|
286
|
+
prevRangeChange.newRange.startLineNumber,
|
|
287
|
+
prevRangeChange.newRange.startColumn,
|
|
288
|
+
node.newEndPosition.lineNumber,
|
|
289
|
+
node.newEndPosition.column
|
|
290
|
+
));
|
|
291
|
+
prevRangeChange.oldRangeLength = node.oldEndIndex - prevNode.oldStartIndex;
|
|
292
|
+
prevRangeChange.newRangeEndOffset = node.newEndIndex;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
ranges.push({ newRange: Range.fromPositions(node.newStartPosition, node.newEndPosition), oldRangeLength: node.oldEndIndex - node.oldStartIndex, newRangeStartOffset: node.newStartIndex, newRangeEndOffset: node.newEndIndex });
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return ranges;
|
|
299
|
+
}
|
|
300
|
+
onDidChangeContent(model, changes) {
|
|
301
|
+
const version = model.getVersionId();
|
|
302
|
+
if (version === this._editVersion) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
this._applyEdits(changes?.changes ?? [], version);
|
|
306
|
+
this._onDidChangeContentQueue.queue(async () => {
|
|
307
|
+
if (this.isDisposed) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
let ranges;
|
|
311
|
+
if (this._lastFullyParsedWithEdits && this._lastFullyParsed) {
|
|
312
|
+
ranges = this.calculateRangeChange(this.findChangedNodes(this._lastFullyParsedWithEdits, this._lastFullyParsed));
|
|
313
|
+
}
|
|
314
|
+
const completed = await this._parseAndUpdateTree(model, version);
|
|
315
|
+
if (completed) {
|
|
316
|
+
if (!ranges) {
|
|
317
|
+
ranges = [{ newRange: model.getFullModelRange(), oldRangeLength: model.getValueLength(), newRangeStartOffset: 0, newRangeEndOffset: model.getValueLength() }];
|
|
318
|
+
}
|
|
319
|
+
this._onDidUpdate.fire({ ranges, versionId: version });
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
_applyEdits(changes, version) {
|
|
154
324
|
for (const change of changes) {
|
|
155
|
-
const
|
|
156
|
-
const
|
|
157
|
-
|
|
325
|
+
const originalTextLength = TextLength.ofRange(Range.lift(change.range));
|
|
326
|
+
const newTextLength = TextLength.ofText(change.text);
|
|
327
|
+
const summedTextLengths = change.text.length === 0 ? newTextLength : originalTextLength.add(newTextLength);
|
|
328
|
+
const edit = {
|
|
158
329
|
startIndex: change.rangeOffset,
|
|
159
330
|
oldEndIndex: change.rangeOffset + change.rangeLength,
|
|
160
331
|
newEndIndex: change.rangeOffset + change.text.length,
|
|
161
332
|
startPosition: { row: change.range.startLineNumber - 1, column: change.range.startColumn - 1 },
|
|
162
333
|
oldEndPosition: { row: change.range.endLineNumber - 1, column: change.range.endColumn - 1 },
|
|
163
|
-
newEndPosition: { row:
|
|
164
|
-
}
|
|
165
|
-
this.
|
|
334
|
+
newEndPosition: { row: change.range.startLineNumber + summedTextLengths.lineCount - 1, column: summedTextLengths.lineCount ? summedTextLengths.columnCount : (change.range.endColumn + summedTextLengths.columnCount) }
|
|
335
|
+
};
|
|
336
|
+
this._tree?.edit(edit);
|
|
337
|
+
this._lastFullyParsedWithEdits?.edit(edit);
|
|
166
338
|
}
|
|
339
|
+
this._editVersion = version;
|
|
167
340
|
}
|
|
168
|
-
async _parseAndUpdateTree(model) {
|
|
341
|
+
async _parseAndUpdateTree(model, version) {
|
|
169
342
|
const tree = await this._parse(model);
|
|
170
|
-
if (
|
|
171
|
-
this.
|
|
343
|
+
if (tree) {
|
|
344
|
+
this._tree?.delete();
|
|
345
|
+
this._tree = tree;
|
|
346
|
+
this._lastFullyParsed?.delete();
|
|
347
|
+
this._lastFullyParsed = tree.copy();
|
|
348
|
+
this._lastFullyParsedWithEdits?.delete();
|
|
349
|
+
this._lastFullyParsedWithEdits = tree.copy();
|
|
350
|
+
this._versionId = version;
|
|
351
|
+
return tree;
|
|
352
|
+
}
|
|
353
|
+
else if (!this._tree) {
|
|
354
|
+
this.parser.reset();
|
|
172
355
|
}
|
|
356
|
+
return undefined;
|
|
173
357
|
}
|
|
174
358
|
_parse(model) {
|
|
175
359
|
let parseType = TelemetryParseType.Full;
|
|
@@ -180,14 +364,14 @@ class TreeSitterParseResult {
|
|
|
180
364
|
}
|
|
181
365
|
async _parseAndYield(model, parseType) {
|
|
182
366
|
const language = model.getLanguageId();
|
|
183
|
-
let tree;
|
|
184
367
|
let time = 0;
|
|
185
368
|
let passes = 0;
|
|
186
|
-
|
|
369
|
+
const inProgressVersion = this._editVersion;
|
|
370
|
+
let newTree;
|
|
187
371
|
do {
|
|
188
372
|
const timer = performance.now();
|
|
189
373
|
try {
|
|
190
|
-
|
|
374
|
+
newTree = this.parser.parse((index, position) => this._parseCallback(model, index), this._tree);
|
|
191
375
|
}
|
|
192
376
|
catch (e) {
|
|
193
377
|
}
|
|
@@ -196,12 +380,9 @@ class TreeSitterParseResult {
|
|
|
196
380
|
passes++;
|
|
197
381
|
}
|
|
198
382
|
await ( new Promise(resolve => setTimeout0(resolve)));
|
|
199
|
-
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
} while (!tree && !this._newEdits);
|
|
383
|
+
} while (!model.isDisposed() && !this.isDisposed && !newTree && inProgressVersion === model.getVersionId());
|
|
203
384
|
this.sendParseTimeTelemetry(parseType, language, time, passes);
|
|
204
|
-
return
|
|
385
|
+
return (newTree && (inProgressVersion === model.getVersionId())) ? newTree : undefined;
|
|
205
386
|
}
|
|
206
387
|
_parseCallback(textModel, index) {
|
|
207
388
|
try {
|
|
@@ -308,6 +489,7 @@ let TreeSitterTextModelService = class TreeSitterTextModelService extends Dispos
|
|
|
308
489
|
this._treeSitterImporter = ( new TreeSitterImporter());
|
|
309
490
|
this._onDidUpdateTree = this._register(( new Emitter()));
|
|
310
491
|
this.onDidUpdateTree = this._onDidUpdateTree.event;
|
|
492
|
+
this.isTest = false;
|
|
311
493
|
this._hasInit = false;
|
|
312
494
|
this._treeSitterLanguages = this._register(( new TreeSitterLanguages(
|
|
313
495
|
this._treeSitterImporter,
|
|
@@ -331,8 +513,7 @@ let TreeSitterTextModelService = class TreeSitterTextModelService extends Dispos
|
|
|
331
513
|
return textModelTreeSitter?.textModelTreeSitter.parseResult;
|
|
332
514
|
}
|
|
333
515
|
async getTree(content, languageId) {
|
|
334
|
-
await this.
|
|
335
|
-
const language = await this._treeSitterLanguages.getLanguage(languageId);
|
|
516
|
+
const language = await this.getLanguage(languageId);
|
|
336
517
|
const Parser = await this._treeSitterImporter.getParserClass();
|
|
337
518
|
if (language) {
|
|
338
519
|
const parser = ( new Parser());
|
|
@@ -341,11 +522,22 @@ let TreeSitterTextModelService = class TreeSitterTextModelService extends Dispos
|
|
|
341
522
|
}
|
|
342
523
|
return undefined;
|
|
343
524
|
}
|
|
525
|
+
async getLanguage(languageId) {
|
|
526
|
+
await this._init;
|
|
527
|
+
return this._treeSitterLanguages.getLanguage(languageId);
|
|
528
|
+
}
|
|
344
529
|
async _doInitParser() {
|
|
345
530
|
const Parser = await this._treeSitterImporter.getParserClass();
|
|
531
|
+
const isTest = this.isTest;
|
|
346
532
|
await Parser.init({
|
|
347
533
|
locateFile(_file, _folder) {
|
|
348
|
-
|
|
534
|
+
const location = `${getModuleLocation()}/${FILENAME_TREESITTER_WASM}`;
|
|
535
|
+
if (isTest) {
|
|
536
|
+
return ( ( FileAccess.asFileUri(location)).toString(true));
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
539
|
+
return ( ( FileAccess.asBrowserUri(location)).toString(true));
|
|
540
|
+
}
|
|
349
541
|
}
|
|
350
542
|
});
|
|
351
543
|
return true;
|
|
@@ -400,32 +592,28 @@ let TreeSitterTextModelService = class TreeSitterTextModelService extends Dispos
|
|
|
400
592
|
}));
|
|
401
593
|
this._modelService.getModels().forEach(model => this._createTextModelTreeSitter(model));
|
|
402
594
|
}
|
|
403
|
-
getTextModelTreeSitter(model) {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
this._treeSitterLanguages,
|
|
407
|
-
this._treeSitterImporter,
|
|
408
|
-
this._logService,
|
|
409
|
-
this._telemetryService,
|
|
410
|
-
false
|
|
411
|
-
));
|
|
595
|
+
async getTextModelTreeSitter(model, parseImmediately = false) {
|
|
596
|
+
await this.getLanguage(model.getLanguageId());
|
|
597
|
+
return this._createTextModelTreeSitter(model, parseImmediately);
|
|
412
598
|
}
|
|
413
|
-
_createTextModelTreeSitter(model) {
|
|
599
|
+
_createTextModelTreeSitter(model, parseImmediately = true) {
|
|
414
600
|
const textModelTreeSitter = ( new TextModelTreeSitter(
|
|
415
601
|
model,
|
|
416
602
|
this._treeSitterLanguages,
|
|
417
603
|
this._treeSitterImporter,
|
|
418
604
|
this._logService,
|
|
419
|
-
this._telemetryService
|
|
605
|
+
this._telemetryService,
|
|
606
|
+
parseImmediately
|
|
420
607
|
));
|
|
421
608
|
const disposables = ( new DisposableStore());
|
|
422
609
|
disposables.add(textModelTreeSitter);
|
|
423
|
-
disposables.add(textModelTreeSitter.onDidChangeParseResult(
|
|
610
|
+
disposables.add(textModelTreeSitter.onDidChangeParseResult(change => this._onDidUpdateTree.fire({ textModel: model, ranges: change.ranges ?? [], versionId: change.versionId })));
|
|
424
611
|
this._textModelTreeSitters.set(model, {
|
|
425
612
|
textModelTreeSitter,
|
|
426
613
|
disposables,
|
|
427
614
|
dispose: disposables.dispose.bind(disposables)
|
|
428
615
|
});
|
|
616
|
+
return textModelTreeSitter;
|
|
429
617
|
}
|
|
430
618
|
_addGrammar(languageId, grammarName) {
|
|
431
619
|
if (!( this._registeredLanguages.has(languageId))) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
|
|
3
3
|
import '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/extensions';
|
|
4
4
|
import { registerWorkbenchContribution2, WorkbenchPhase } from '@codingame/monaco-vscode-api/vscode/vs/workbench/common/contributions';
|
|
5
|
-
import '../../../../editor/
|
|
5
|
+
import '../../../../editor/common/services/treeSitter/treeSitterParserService.js';
|
|
6
6
|
import { ITreeSitterParserService } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/services/treeSitterParserService';
|
|
7
7
|
import { ITreeSitterTokenizationFeature } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.service';
|
|
8
8
|
import { CommandsRegistry } from '@codingame/monaco-vscode-api/vscode/vs/platform/commands/common/commands';
|
|
@@ -30,7 +30,7 @@ CommandsRegistry.registerCommand('_workbench.colorizeTreeSitterTokens', async (a
|
|
|
30
30
|
if (!tokenizer) {
|
|
31
31
|
throw ( new Error(`Cannot resolve tokenizer for language ${textModel.getLanguageId()}`));
|
|
32
32
|
}
|
|
33
|
-
const textModelTreeSitter = treeSitterParserService.getTextModelTreeSitter(textModel);
|
|
33
|
+
const textModelTreeSitter = await treeSitterParserService.getTextModelTreeSitter(textModel);
|
|
34
34
|
if (!textModelTreeSitter) {
|
|
35
35
|
throw ( new Error(
|
|
36
36
|
`Cannot resolve tree sitter parser for language ${textModel.getLanguageId()}`
|
package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.d.ts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
|
+
import type { Parser } from "@vscode/tree-sitter-wasm";
|
|
2
|
+
import { Event } from "@codingame/monaco-vscode-api/vscode/vs/base/common/event";
|
|
1
3
|
import { Disposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
|
|
4
|
+
import { ILanguageIdCodec, ITreeSitterTokenizationSupport, QueryCapture } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/languages";
|
|
5
|
+
import { ITextModel } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/model";
|
|
6
|
+
import { ITreeSitterParserService, ITreeSitterParseResult } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/services/treeSitterParserService";
|
|
7
|
+
import { IModelTokensChangedEvent } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/textModelEvents";
|
|
2
8
|
import { IConfigurationService } from "@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service";
|
|
3
9
|
import { IFileService } from "@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service";
|
|
4
10
|
import { IInstantiationService } from "@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation";
|
|
11
|
+
import { IThemeService } from "@codingame/monaco-vscode-api/vscode/vs/platform/theme/common/themeService.service";
|
|
5
12
|
import { ILanguageService } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/languages/language";
|
|
13
|
+
import { ITreeSitterTokenizationStoreService } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/model/treeSitterTokenStoreService";
|
|
14
|
+
import { TokenUpdate } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/model/tokenStore";
|
|
15
|
+
import { Range } from "@codingame/monaco-vscode-api/vscode/vs/editor/common/core/range";
|
|
16
|
+
import { ICodeEditorService } from "@codingame/monaco-vscode-api/vscode/vs/editor/browser/services/codeEditorService";
|
|
6
17
|
import { ITreeSitterTokenizationFeature } from "@codingame/monaco-vscode-api/vscode/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.service";
|
|
18
|
+
type TreeSitterQueries = string;
|
|
7
19
|
export declare class TreeSitterTokenizationFeature extends Disposable implements ITreeSitterTokenizationFeature {
|
|
8
20
|
private readonly _languageService;
|
|
9
21
|
private readonly _configurationService;
|
|
@@ -17,3 +29,52 @@ export declare class TreeSitterTokenizationFeature extends Disposable implements
|
|
|
17
29
|
private _fetchQueries;
|
|
18
30
|
private _createTokenizationSupport;
|
|
19
31
|
}
|
|
32
|
+
export declare class TreeSitterTokenizationSupport extends Disposable implements ITreeSitterTokenizationSupport {
|
|
33
|
+
private readonly _queries;
|
|
34
|
+
private readonly _languageId;
|
|
35
|
+
private readonly _languageIdCodec;
|
|
36
|
+
private readonly _treeSitterService;
|
|
37
|
+
private readonly _themeService;
|
|
38
|
+
private readonly _tokenizationStoreService;
|
|
39
|
+
private readonly _codeEditorService;
|
|
40
|
+
private _query;
|
|
41
|
+
private readonly _onDidChangeTokens;
|
|
42
|
+
readonly onDidChangeTokens: Event<{
|
|
43
|
+
textModel: ITextModel;
|
|
44
|
+
changes: IModelTokensChangedEvent;
|
|
45
|
+
}>;
|
|
46
|
+
private _colorThemeData;
|
|
47
|
+
private _languageAddedListener;
|
|
48
|
+
constructor(_queries: TreeSitterQueries, _languageId: string, _languageIdCodec: ILanguageIdCodec, _treeSitterService: ITreeSitterParserService, _themeService: IThemeService, _tokenizationStoreService: ITreeSitterTokenizationStoreService, _codeEditorService: ICodeEditorService);
|
|
49
|
+
private _createEmptyTokens;
|
|
50
|
+
private _firstTreeUpdate;
|
|
51
|
+
private _setViewPortTokens;
|
|
52
|
+
private _handleTreeUpdate;
|
|
53
|
+
private _updateTreeForRanges;
|
|
54
|
+
private _refreshNeedsRefresh;
|
|
55
|
+
private _rangeTokensAsUpdates;
|
|
56
|
+
getTokensInRange(textModel: ITextModel, range: Range, rangeStartOffset: number, rangeEndOffset: number, captures?: {
|
|
57
|
+
tree: ITreeSitterParseResult | undefined;
|
|
58
|
+
captures: QueryCapture[];
|
|
59
|
+
}): TokenUpdate[] | undefined;
|
|
60
|
+
private _getTree;
|
|
61
|
+
private _ensureQuery;
|
|
62
|
+
private reset;
|
|
63
|
+
captureAtPosition(lineNumber: number, column: number, textModel: ITextModel): QueryCapture[];
|
|
64
|
+
captureAtPositionTree(lineNumber: number, column: number, tree: Parser.Tree): QueryCapture[];
|
|
65
|
+
private _captureAtRange;
|
|
66
|
+
tokenizeEncoded(lineNumber: number, textModel: ITextModel): Uint32Array | undefined;
|
|
67
|
+
tokenizeEncodedInstrumented(lineNumber: number, textModel: ITextModel): {
|
|
68
|
+
result: Uint32Array;
|
|
69
|
+
captureTime: number;
|
|
70
|
+
metadataTime: number;
|
|
71
|
+
} | undefined;
|
|
72
|
+
private _getTreeAndCaptures;
|
|
73
|
+
private _tokenize;
|
|
74
|
+
private _createTokensFromCaptures;
|
|
75
|
+
private _tokenizeCapturesWithMetadata;
|
|
76
|
+
private _emptyToken;
|
|
77
|
+
private _tokenizeEncoded;
|
|
78
|
+
dispose(): void;
|
|
79
|
+
}
|
|
80
|
+
export {};
|
package/vscode/src/vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.js
CHANGED
|
@@ -5,7 +5,6 @@ import { Disposable, DisposableMap, DisposableStore } from '@codingame/monaco-vs
|
|
|
5
5
|
import { FileAccess } from '@codingame/monaco-vscode-api/vscode/vs/base/common/network';
|
|
6
6
|
import { LazyTokenizationSupport, TreeSitterTokenizationRegistry } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/languages';
|
|
7
7
|
import { EDITOR_EXPERIMENTAL_PREFER_TREESITTER, ITreeSitterParserService } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/services/treeSitterParserService';
|
|
8
|
-
import { ColumnRange } from '@codingame/monaco-vscode-api/vscode/vs/editor/contrib/inlineCompletions/browser/utils';
|
|
9
8
|
import { IConfigurationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service';
|
|
10
9
|
import { IFileService } from '@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service';
|
|
11
10
|
import '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/extensions';
|
|
@@ -14,6 +13,10 @@ import { IThemeService } from '@codingame/monaco-vscode-api/vscode/vs/platform/t
|
|
|
14
13
|
import { findMetadata } from '@codingame/monaco-vscode-9d0168a3-519b-57f3-9bcc-89efc41f951a-common/vscode/vs/workbench/services/themes/common/colorThemeData';
|
|
15
14
|
import { ILanguageService } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/languages/language';
|
|
16
15
|
import { StopWatch } from '@codingame/monaco-vscode-api/vscode/vs/base/common/stopwatch';
|
|
16
|
+
import { ITreeSitterTokenizationStoreService } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/model/treeSitterTokenStoreService';
|
|
17
|
+
import { Range } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/core/range';
|
|
18
|
+
import { ICodeEditorService } from '@codingame/monaco-vscode-api/vscode/vs/editor/browser/services/codeEditorService';
|
|
19
|
+
import { setTimeout0 } from '@codingame/monaco-vscode-api/vscode/vs/base/common/platform';
|
|
17
20
|
|
|
18
21
|
const ALLOWED_SUPPORT = ['typescript'];
|
|
19
22
|
let TreeSitterTokenizationFeature = class TreeSitterTokenizationFeature extends Disposable {
|
|
@@ -23,7 +26,7 @@ let TreeSitterTokenizationFeature = class TreeSitterTokenizationFeature extends
|
|
|
23
26
|
this._configurationService = _configurationService;
|
|
24
27
|
this._instantiationService = _instantiationService;
|
|
25
28
|
this._fileService = _fileService;
|
|
26
|
-
this._tokenizersRegistrations = ( new DisposableMap());
|
|
29
|
+
this._tokenizersRegistrations = this._register(( new DisposableMap()));
|
|
27
30
|
this._handleGrammarsExtPoint();
|
|
28
31
|
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
|
29
32
|
if (e.affectsConfiguration(EDITOR_EXPERIMENTAL_PREFER_TREESITTER)) {
|
|
@@ -68,28 +71,183 @@ TreeSitterTokenizationFeature = ( __decorate([
|
|
|
68
71
|
( __param(3, IFileService))
|
|
69
72
|
], TreeSitterTokenizationFeature));
|
|
70
73
|
let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends Disposable {
|
|
71
|
-
constructor(_queries, _languageId, _languageIdCodec, _treeSitterService, _themeService) {
|
|
74
|
+
constructor(_queries, _languageId, _languageIdCodec, _treeSitterService, _themeService, _tokenizationStoreService, _codeEditorService) {
|
|
72
75
|
super();
|
|
73
76
|
this._queries = _queries;
|
|
74
77
|
this._languageId = _languageId;
|
|
75
78
|
this._languageIdCodec = _languageIdCodec;
|
|
76
79
|
this._treeSitterService = _treeSitterService;
|
|
77
80
|
this._themeService = _themeService;
|
|
81
|
+
this._tokenizationStoreService = _tokenizationStoreService;
|
|
82
|
+
this._codeEditorService = _codeEditorService;
|
|
78
83
|
this._onDidChangeTokens = ( new Emitter());
|
|
79
84
|
this.onDidChangeTokens = this._onDidChangeTokens.event;
|
|
80
85
|
this._register(Event.runAndSubscribe(this._themeService.onDidColorThemeChange, () => this.reset()));
|
|
81
86
|
this._register(this._treeSitterService.onDidUpdateTree((e) => {
|
|
82
|
-
|
|
87
|
+
if (this._tokenizationStoreService.hasTokens(e.textModel)) {
|
|
88
|
+
for (const range of e.ranges) {
|
|
89
|
+
this._tokenizationStoreService.markForRefresh(e.textModel, range.newRange);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (e.versionId !== e.textModel.getVersionId()) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (!this._tokenizationStoreService.hasTokens(e.textModel)) {
|
|
96
|
+
this._firstTreeUpdate(e.textModel, e.versionId);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
this._handleTreeUpdate(e);
|
|
100
|
+
}
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
_createEmptyTokens(textModel) {
|
|
104
|
+
const languageId = this._languageIdCodec.encodeLanguageId(this._languageId);
|
|
105
|
+
const emptyToken = this._emptyToken(languageId);
|
|
106
|
+
const modelEndOffset = textModel.getValueLength();
|
|
107
|
+
const emptyTokens = [{ token: emptyToken, length: modelEndOffset, startOffsetInclusive: 0 }];
|
|
108
|
+
return emptyTokens;
|
|
109
|
+
}
|
|
110
|
+
_firstTreeUpdate(textModel, versionId) {
|
|
111
|
+
const tokens = this._createEmptyTokens(textModel);
|
|
112
|
+
this._tokenizationStoreService.setTokens(textModel, tokens);
|
|
113
|
+
this._setViewPortTokens(textModel, versionId);
|
|
114
|
+
}
|
|
115
|
+
_setViewPortTokens(textModel, versionId) {
|
|
116
|
+
const maxLine = textModel.getLineCount();
|
|
117
|
+
let rangeChanges;
|
|
118
|
+
const editor = this._codeEditorService.listCodeEditors().find(editor => editor.getModel() === textModel);
|
|
119
|
+
if (editor) {
|
|
120
|
+
const viewPort = editor.getVisibleRangesPlusViewportAboveBelow();
|
|
121
|
+
const ranges = ( new Array(viewPort.length));
|
|
122
|
+
rangeChanges = ( new Array(viewPort.length));
|
|
123
|
+
for (let i = 0; i < viewPort.length; i++) {
|
|
124
|
+
const range = viewPort[i];
|
|
125
|
+
ranges[i] = { fromLineNumber: range.startLineNumber, toLineNumber: range.endLineNumber < maxLine ? range.endLineNumber : maxLine };
|
|
126
|
+
const newRangeStartOffset = textModel.getOffsetAt(range.getStartPosition());
|
|
127
|
+
const newRangeEndOffset = textModel.getOffsetAt(range.getEndPosition());
|
|
128
|
+
rangeChanges[i] = {
|
|
129
|
+
newRange: range,
|
|
130
|
+
newRangeStartOffset,
|
|
131
|
+
newRangeEndOffset,
|
|
132
|
+
oldRangeLength: newRangeEndOffset - newRangeStartOffset
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
const valueLength = textModel.getValueLength();
|
|
138
|
+
rangeChanges = [{ newRange: ( new Range(1, 1, maxLine, textModel.getLineMaxColumn(maxLine))), newRangeStartOffset: 0, newRangeEndOffset: valueLength, oldRangeLength: valueLength }];
|
|
139
|
+
}
|
|
140
|
+
this._handleTreeUpdate({ ranges: rangeChanges, textModel, versionId });
|
|
141
|
+
}
|
|
142
|
+
_handleTreeUpdate(e) {
|
|
143
|
+
let rangeChanges = [];
|
|
144
|
+
const chunkSize = 10000;
|
|
145
|
+
for (let i = 0; i < e.ranges.length; i++) {
|
|
146
|
+
const rangeLength = e.ranges[i].newRangeEndOffset - e.ranges[i].newRangeStartOffset;
|
|
147
|
+
if (e.ranges[i].oldRangeLength === rangeLength) {
|
|
148
|
+
if (rangeLength > chunkSize) {
|
|
149
|
+
const fullRangeEndOffset = e.ranges[i].newRangeEndOffset;
|
|
150
|
+
let chunkStart = e.ranges[i].newRangeStartOffset;
|
|
151
|
+
let chunkEnd = chunkStart + chunkSize;
|
|
152
|
+
let chunkStartingPosition = e.ranges[i].newRange.getStartPosition();
|
|
153
|
+
do {
|
|
154
|
+
const chunkEndPosition = e.textModel.getPositionAt(chunkEnd);
|
|
155
|
+
const chunkRange = Range.fromPositions(chunkStartingPosition, chunkEndPosition);
|
|
156
|
+
rangeChanges.push({
|
|
157
|
+
newRange: chunkRange,
|
|
158
|
+
newRangeStartOffset: chunkStart,
|
|
159
|
+
newRangeEndOffset: chunkEnd,
|
|
160
|
+
oldRangeLength: chunkEnd - chunkStart
|
|
161
|
+
});
|
|
162
|
+
chunkStart = chunkEnd;
|
|
163
|
+
if (chunkEnd < fullRangeEndOffset && chunkEnd + chunkSize > fullRangeEndOffset) {
|
|
164
|
+
chunkEnd = fullRangeEndOffset;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
chunkEnd = chunkEnd + chunkSize;
|
|
168
|
+
}
|
|
169
|
+
chunkStartingPosition = chunkEndPosition;
|
|
170
|
+
} while (chunkEnd <= fullRangeEndOffset);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
rangeChanges.push(e.ranges[i]);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
rangeChanges = e.ranges;
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const captures = ( rangeChanges.map(range => this._getTreeAndCaptures(range.newRange, e.textModel)));
|
|
182
|
+
this._updateTreeForRanges(e.textModel, rangeChanges, e.versionId, captures).then(() => {
|
|
183
|
+
const tree = this._getTree(e.textModel);
|
|
184
|
+
if (!e.textModel.isDisposed() && (tree?.versionId === e.textModel.getVersionId())) {
|
|
185
|
+
this._refreshNeedsRefresh(e.textModel);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
async _updateTreeForRanges(textModel, rangeChanges, versionId, captures) {
|
|
190
|
+
let tokenUpdate;
|
|
191
|
+
for (let i = 0; i < rangeChanges.length; i++) {
|
|
192
|
+
if (versionId !== textModel.getVersionId()) {
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
const capture = captures[i];
|
|
196
|
+
const range = rangeChanges[i];
|
|
197
|
+
const updates = this.getTokensInRange(textModel, range.newRange, range.newRangeStartOffset, range.newRangeEndOffset, capture);
|
|
198
|
+
if (updates) {
|
|
199
|
+
tokenUpdate = { oldRangeLength: range.oldRangeLength, newTokens: updates };
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
tokenUpdate = { oldRangeLength: range.oldRangeLength, newTokens: [] };
|
|
203
|
+
}
|
|
204
|
+
this._tokenizationStoreService.updateTokens(textModel, versionId, [tokenUpdate]);
|
|
83
205
|
this._onDidChangeTokens.fire({
|
|
84
|
-
textModel:
|
|
206
|
+
textModel: textModel,
|
|
85
207
|
changes: {
|
|
86
208
|
semanticTokensApplied: false,
|
|
87
|
-
ranges: (
|
|
88
|
-
range => ({ fromLineNumber: range.startLineNumber, toLineNumber: range.endLineNumber < maxLine ? range.endLineNumber : maxLine })
|
|
89
|
-
)),
|
|
209
|
+
ranges: [{ fromLineNumber: range.newRange.getStartPosition().lineNumber, toLineNumber: range.newRange.getEndPosition().lineNumber }]
|
|
90
210
|
}
|
|
91
211
|
});
|
|
92
|
-
|
|
212
|
+
await ( new Promise(resolve => setTimeout0(resolve)));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
_refreshNeedsRefresh(textModel) {
|
|
216
|
+
const rangesToRefresh = this._tokenizationStoreService.getNeedsRefresh(textModel);
|
|
217
|
+
if (rangesToRefresh.length === 0) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const rangeChanges = ( new Array(rangesToRefresh.length));
|
|
221
|
+
for (let i = 0; i < rangesToRefresh.length; i++) {
|
|
222
|
+
const range = rangesToRefresh[i];
|
|
223
|
+
rangeChanges[i] = {
|
|
224
|
+
newRange: range.range,
|
|
225
|
+
newRangeStartOffset: range.startOffset,
|
|
226
|
+
newRangeEndOffset: range.endOffset,
|
|
227
|
+
oldRangeLength: range.endOffset - range.startOffset
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
this._handleTreeUpdate({ ranges: rangeChanges, textModel, versionId: textModel.getVersionId() });
|
|
231
|
+
}
|
|
232
|
+
_rangeTokensAsUpdates(rangeOffset, endOffsetToken) {
|
|
233
|
+
const updates = [];
|
|
234
|
+
let lastEnd = 0;
|
|
235
|
+
for (const token of endOffsetToken) {
|
|
236
|
+
if (token.endOffset <= lastEnd) {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
updates.push({ startOffsetInclusive: rangeOffset + lastEnd, length: token.endOffset - lastEnd, token: token.metadata });
|
|
240
|
+
lastEnd = token.endOffset;
|
|
241
|
+
}
|
|
242
|
+
return updates;
|
|
243
|
+
}
|
|
244
|
+
getTokensInRange(textModel, range, rangeStartOffset, rangeEndOffset, captures) {
|
|
245
|
+
const languageId = this._languageIdCodec.encodeLanguageId(this._languageId);
|
|
246
|
+
const tokens = captures ? this._tokenizeCapturesWithMetadata(captures.tree, captures.captures, languageId, rangeStartOffset, rangeEndOffset) : this._tokenize(languageId, range, rangeStartOffset, rangeEndOffset, textModel);
|
|
247
|
+
if (tokens?.endOffsetsAndMetadata) {
|
|
248
|
+
return this._rangeTokensAsUpdates(rangeStartOffset, tokens.endOffsetsAndMetadata);
|
|
249
|
+
}
|
|
250
|
+
return undefined;
|
|
93
251
|
}
|
|
94
252
|
_getTree(textModel) {
|
|
95
253
|
return this._treeSitterService.getParseResult(textModel);
|
|
@@ -114,19 +272,26 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
|
|
|
114
272
|
}
|
|
115
273
|
captureAtPosition(lineNumber, column, textModel) {
|
|
116
274
|
const tree = this._getTree(textModel);
|
|
117
|
-
const captures = this._captureAtRange(
|
|
275
|
+
const captures = this._captureAtRange(( new Range(lineNumber, column, lineNumber, column + 1)), tree?.tree);
|
|
118
276
|
return captures;
|
|
119
277
|
}
|
|
120
278
|
captureAtPositionTree(lineNumber, column, tree) {
|
|
121
|
-
const captures = this._captureAtRange(
|
|
279
|
+
const captures = this._captureAtRange(( new Range(lineNumber, column, lineNumber, column + 1)), tree);
|
|
122
280
|
return captures;
|
|
123
281
|
}
|
|
124
|
-
_captureAtRange(
|
|
282
|
+
_captureAtRange(range, tree) {
|
|
125
283
|
const query = this._ensureQuery();
|
|
126
284
|
if (!tree || !query) {
|
|
127
285
|
return [];
|
|
128
286
|
}
|
|
129
|
-
return query.captures(tree.rootNode, { startPosition: { row:
|
|
287
|
+
return ( query.captures(tree.rootNode, { startPosition: { row: range.startLineNumber - 1, column: range.startColumn - 1 }, endPosition: { row: range.endLineNumber - 1, column: range.endColumn - 1 } }).map(capture => ({
|
|
288
|
+
name: capture.name,
|
|
289
|
+
text: capture.node.text,
|
|
290
|
+
node: {
|
|
291
|
+
startIndex: capture.node.startIndex,
|
|
292
|
+
endIndex: capture.node.endIndex
|
|
293
|
+
}
|
|
294
|
+
})));
|
|
130
295
|
}
|
|
131
296
|
tokenizeEncoded(lineNumber, textModel) {
|
|
132
297
|
return this._tokenizeEncoded(lineNumber, textModel)?.result;
|
|
@@ -134,34 +299,44 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
|
|
|
134
299
|
tokenizeEncodedInstrumented(lineNumber, textModel) {
|
|
135
300
|
return this._tokenizeEncoded(lineNumber, textModel);
|
|
136
301
|
}
|
|
137
|
-
|
|
138
|
-
const stopwatch = StopWatch.create();
|
|
139
|
-
const lineLength = textModel.getLineMaxColumn(lineNumber);
|
|
302
|
+
_getTreeAndCaptures(range, textModel) {
|
|
140
303
|
const tree = this._getTree(textModel);
|
|
141
|
-
const captures = this._captureAtRange(
|
|
304
|
+
const captures = this._captureAtRange(range, tree?.tree);
|
|
305
|
+
return { tree, captures };
|
|
306
|
+
}
|
|
307
|
+
_tokenize(encodedLanguageId, range, rangeStartOffset, rangeEndOffset, textModel) {
|
|
308
|
+
const { tree, captures } = this._getTreeAndCaptures(range, textModel);
|
|
309
|
+
return this._tokenizeCapturesWithMetadata(tree, captures, encodedLanguageId, rangeStartOffset, rangeEndOffset);
|
|
310
|
+
}
|
|
311
|
+
_createTokensFromCaptures(tree, captures, rangeStartOffset, rangeEndOffset) {
|
|
312
|
+
const stopwatch = StopWatch.create();
|
|
313
|
+
const rangeLength = rangeEndOffset - rangeStartOffset;
|
|
142
314
|
if (captures.length === 0) {
|
|
315
|
+
if (tree) {
|
|
316
|
+
stopwatch.stop();
|
|
317
|
+
const endOffsetsAndMetadata = [{ endOffset: rangeLength, scopes: [] }];
|
|
318
|
+
return { endOffsets: endOffsetsAndMetadata, captureTime: stopwatch.elapsed() };
|
|
319
|
+
}
|
|
143
320
|
return undefined;
|
|
144
321
|
}
|
|
145
322
|
const endOffsetsAndScopes = Array(captures.length);
|
|
146
323
|
endOffsetsAndScopes.fill({ endOffset: 0, scopes: [] });
|
|
147
324
|
let tokenIndex = 0;
|
|
148
|
-
const lineStartOffset = textModel.getOffsetAt({ lineNumber: lineNumber, column: 1 });
|
|
149
325
|
const increaseSizeOfTokensByOneToken = () => {
|
|
150
326
|
endOffsetsAndScopes.push({ endOffset: 0, scopes: [] });
|
|
151
327
|
};
|
|
152
|
-
const encodedLanguageId = this._languageIdCodec.encodeLanguageId(this._languageId);
|
|
153
328
|
for (let captureIndex = 0; captureIndex < captures.length; captureIndex++) {
|
|
154
329
|
const capture = captures[captureIndex];
|
|
155
|
-
const tokenEndIndex = capture.node.endIndex <
|
|
156
|
-
const tokenStartIndex = capture.node.startIndex <
|
|
157
|
-
const lineRelativeOffset = tokenEndIndex -
|
|
330
|
+
const tokenEndIndex = capture.node.endIndex < rangeEndOffset ? ((capture.node.endIndex < rangeStartOffset) ? rangeStartOffset : capture.node.endIndex) : rangeEndOffset;
|
|
331
|
+
const tokenStartIndex = capture.node.startIndex < rangeStartOffset ? rangeStartOffset : ((capture.node.startIndex > tokenEndIndex) ? tokenEndIndex : capture.node.startIndex);
|
|
332
|
+
const lineRelativeOffset = tokenEndIndex - rangeStartOffset;
|
|
158
333
|
let previousTokenEnd;
|
|
159
334
|
const currentTokenLength = tokenEndIndex - tokenStartIndex;
|
|
160
335
|
if (captureIndex > 0) {
|
|
161
336
|
previousTokenEnd = endOffsetsAndScopes[(tokenIndex - 1)].endOffset;
|
|
162
337
|
}
|
|
163
338
|
else {
|
|
164
|
-
previousTokenEnd = tokenStartIndex -
|
|
339
|
+
previousTokenEnd = tokenStartIndex - rangeStartOffset - 1;
|
|
165
340
|
}
|
|
166
341
|
const intermediateTokenOffset = lineRelativeOffset - currentTokenLength;
|
|
167
342
|
if ((previousTokenEnd >= 0) && (previousTokenEnd < intermediateTokenOffset)) {
|
|
@@ -174,42 +349,89 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
|
|
|
174
349
|
tokenIndex++;
|
|
175
350
|
};
|
|
176
351
|
if (previousTokenEnd >= lineRelativeOffset) {
|
|
177
|
-
const previousTokenStartOffset = ((tokenIndex >= 2) ? endOffsetsAndScopes[tokenIndex - 2].endOffset : 0);
|
|
178
352
|
const originalPreviousTokenEndOffset = endOffsetsAndScopes[tokenIndex - 1].endOffset;
|
|
179
|
-
|
|
353
|
+
const previousTokenStartOffset = ((tokenIndex >= 2) ? endOffsetsAndScopes[tokenIndex - 2].endOffset : 0);
|
|
354
|
+
const loopOriginalPreviousTokenEndOffset = endOffsetsAndScopes[tokenIndex - 1].endOffset;
|
|
355
|
+
const previousPreviousTokenEndOffset = (tokenIndex >= 2) ? endOffsetsAndScopes[tokenIndex - 2].endOffset : 0;
|
|
356
|
+
if ((previousTokenStartOffset + currentTokenLength) === loopOriginalPreviousTokenEndOffset) {
|
|
180
357
|
endOffsetsAndScopes[tokenIndex - 1].scopes[endOffsetsAndScopes[tokenIndex - 1].scopes.length - 1] = capture.name;
|
|
181
358
|
}
|
|
182
|
-
else {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
359
|
+
else if (previousPreviousTokenEndOffset <= intermediateTokenOffset) {
|
|
360
|
+
let originalPreviousTokenScopes;
|
|
361
|
+
if (previousPreviousTokenEndOffset !== intermediateTokenOffset) {
|
|
362
|
+
endOffsetsAndScopes[tokenIndex - 1] = { endOffset: intermediateTokenOffset, scopes: endOffsetsAndScopes[tokenIndex - 1].scopes };
|
|
363
|
+
addCurrentTokenToArray();
|
|
364
|
+
originalPreviousTokenScopes = [...endOffsetsAndScopes[tokenIndex - 2].scopes];
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
originalPreviousTokenScopes = [...endOffsetsAndScopes[tokenIndex - 1].scopes];
|
|
368
|
+
endOffsetsAndScopes[tokenIndex - 1] = { endOffset: lineRelativeOffset, scopes: [capture.name] };
|
|
369
|
+
}
|
|
370
|
+
if (originalPreviousTokenEndOffset !== lineRelativeOffset) {
|
|
371
|
+
increaseSizeOfTokensByOneToken();
|
|
372
|
+
endOffsetsAndScopes[tokenIndex] = { endOffset: originalPreviousTokenEndOffset, scopes: originalPreviousTokenScopes };
|
|
373
|
+
tokenIndex++;
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
endOffsetsAndScopes[tokenIndex - 1].scopes.unshift(...originalPreviousTokenScopes);
|
|
377
|
+
}
|
|
189
378
|
}
|
|
190
379
|
}
|
|
191
380
|
else {
|
|
192
381
|
addCurrentTokenToArray();
|
|
193
382
|
}
|
|
194
383
|
}
|
|
195
|
-
if (
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
384
|
+
if ((endOffsetsAndScopes[tokenIndex - 1].endOffset < rangeLength)) {
|
|
385
|
+
if (rangeLength - endOffsetsAndScopes[tokenIndex - 1].endOffset > 0) {
|
|
386
|
+
increaseSizeOfTokensByOneToken();
|
|
387
|
+
endOffsetsAndScopes[tokenIndex] = { endOffset: rangeLength, scopes: endOffsetsAndScopes[tokenIndex].scopes };
|
|
388
|
+
tokenIndex++;
|
|
389
|
+
}
|
|
199
390
|
}
|
|
200
|
-
|
|
201
|
-
stopwatch.reset();
|
|
202
|
-
const tokens = ( new Uint32Array((tokenIndex) * 2));
|
|
203
|
-
for (let i = 0; i < tokenIndex; i++) {
|
|
391
|
+
for (let i = 0; i < endOffsetsAndScopes.length; i++) {
|
|
204
392
|
const token = endOffsetsAndScopes[i];
|
|
205
|
-
if (token.endOffset === 0 && token.scopes.length === 0) {
|
|
393
|
+
if (token.endOffset === 0 && token.scopes.length === 0 && i !== 0) {
|
|
394
|
+
endOffsetsAndScopes.splice(i, endOffsetsAndScopes.length - i);
|
|
206
395
|
break;
|
|
207
396
|
}
|
|
208
|
-
|
|
209
|
-
|
|
397
|
+
}
|
|
398
|
+
const captureTime = stopwatch.elapsed();
|
|
399
|
+
return { endOffsets: endOffsetsAndScopes, captureTime };
|
|
400
|
+
}
|
|
401
|
+
_tokenizeCapturesWithMetadata(tree, captures, encodedLanguageId, rangeStartOffset, rangeEndOffset) {
|
|
402
|
+
const stopwatch = StopWatch.create();
|
|
403
|
+
const emptyTokens = this._createTokensFromCaptures(tree, captures, rangeStartOffset, rangeEndOffset);
|
|
404
|
+
if (!emptyTokens) {
|
|
405
|
+
return undefined;
|
|
406
|
+
}
|
|
407
|
+
const endOffsetsAndScopes = emptyTokens.endOffsets;
|
|
408
|
+
for (let i = 0; i < endOffsetsAndScopes.length; i++) {
|
|
409
|
+
const token = endOffsetsAndScopes[i];
|
|
410
|
+
token.metadata = findMetadata(this._colorThemeData, token.scopes, encodedLanguageId);
|
|
210
411
|
}
|
|
211
412
|
const metadataTime = stopwatch.elapsed();
|
|
212
|
-
return {
|
|
413
|
+
return { endOffsetsAndMetadata: endOffsetsAndScopes, captureTime: emptyTokens.captureTime, metadataTime };
|
|
414
|
+
}
|
|
415
|
+
_emptyToken(encodedLanguageId) {
|
|
416
|
+
return findMetadata(this._colorThemeData, [], encodedLanguageId);
|
|
417
|
+
}
|
|
418
|
+
_tokenizeEncoded(lineNumber, textModel) {
|
|
419
|
+
const encodedLanguageId = this._languageIdCodec.encodeLanguageId(this._languageId);
|
|
420
|
+
const lineOffset = textModel.getOffsetAt({ lineNumber: lineNumber, column: 1 });
|
|
421
|
+
const maxLine = textModel.getLineCount();
|
|
422
|
+
const lineEndOffset = (lineNumber + 1 <= maxLine) ? textModel.getOffsetAt({ lineNumber: lineNumber + 1, column: 1 }) : textModel.getValueLength();
|
|
423
|
+
const lineLength = lineEndOffset - lineOffset;
|
|
424
|
+
const result = this._tokenize(encodedLanguageId, ( new Range(lineNumber, 1, lineNumber, lineLength)), lineOffset, lineEndOffset, textModel);
|
|
425
|
+
if (!result) {
|
|
426
|
+
return undefined;
|
|
427
|
+
}
|
|
428
|
+
const tokens = ( new Uint32Array((result.endOffsetsAndMetadata.length) * 2));
|
|
429
|
+
for (let i = 0; i < result.endOffsetsAndMetadata.length; i++) {
|
|
430
|
+
const token = result.endOffsetsAndMetadata[i];
|
|
431
|
+
tokens[i * 2] = token.endOffset;
|
|
432
|
+
tokens[i * 2 + 1] = token.metadata;
|
|
433
|
+
}
|
|
434
|
+
return { result: tokens, captureTime: result.captureTime, metadataTime: result.metadataTime };
|
|
213
435
|
}
|
|
214
436
|
dispose() {
|
|
215
437
|
super.dispose();
|
|
@@ -219,7 +441,9 @@ let TreeSitterTokenizationSupport = class TreeSitterTokenizationSupport extends
|
|
|
219
441
|
};
|
|
220
442
|
TreeSitterTokenizationSupport = ( __decorate([
|
|
221
443
|
( __param(3, ITreeSitterParserService)),
|
|
222
|
-
( __param(4, IThemeService))
|
|
444
|
+
( __param(4, IThemeService)),
|
|
445
|
+
( __param(5, ITreeSitterTokenizationStoreService)),
|
|
446
|
+
( __param(6, ICodeEditorService))
|
|
223
447
|
], TreeSitterTokenizationSupport));
|
|
224
448
|
|
|
225
|
-
export { TreeSitterTokenizationFeature };
|
|
449
|
+
export { TreeSitterTokenizationFeature, TreeSitterTokenizationSupport };
|