@shikijs/core 1.15.2 → 1.16.1
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/dist/chunk-engines.d.mts +29 -1
- package/dist/index.d.mts +117 -78
- package/dist/index.mjs +1009 -922
- package/dist/types.d.mts +665 -5
- package/dist/wasm-inlined.d.mts +1 -0
- package/package.json +3 -2
- package/dist/chunk-tokens.d.mts +0 -1062
- package/dist/textmate.d.mts +0 -3
- package/dist/textmate.mjs +0 -3135
package/dist/textmate.mjs
DELETED
|
@@ -1,3135 +0,0 @@
|
|
|
1
|
-
import { FontStyle } from './types.mjs';
|
|
2
|
-
|
|
3
|
-
/*---------------------------------------------------------
|
|
4
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
5
|
-
*--------------------------------------------------------*/
|
|
6
|
-
({
|
|
7
|
-
InDebugMode: (typeof process !== 'undefined' && !!process.env['VSCODE_TEXTMATE_DEBUG'])
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
/*---------------------------------------------------------
|
|
11
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
12
|
-
*--------------------------------------------------------*/
|
|
13
|
-
var EncodedTokenAttributes;
|
|
14
|
-
(function (EncodedTokenAttributes) {
|
|
15
|
-
function toBinaryStr(encodedTokenAttributes) {
|
|
16
|
-
return encodedTokenAttributes.toString(2).padStart(32, "0");
|
|
17
|
-
}
|
|
18
|
-
EncodedTokenAttributes.toBinaryStr = toBinaryStr;
|
|
19
|
-
function print(encodedTokenAttributes) {
|
|
20
|
-
const languageId = EncodedTokenAttributes.getLanguageId(encodedTokenAttributes);
|
|
21
|
-
const tokenType = EncodedTokenAttributes.getTokenType(encodedTokenAttributes);
|
|
22
|
-
const fontStyle = EncodedTokenAttributes.getFontStyle(encodedTokenAttributes);
|
|
23
|
-
const foreground = EncodedTokenAttributes.getForeground(encodedTokenAttributes);
|
|
24
|
-
const background = EncodedTokenAttributes.getBackground(encodedTokenAttributes);
|
|
25
|
-
console.log({
|
|
26
|
-
languageId: languageId,
|
|
27
|
-
tokenType: tokenType,
|
|
28
|
-
fontStyle: fontStyle,
|
|
29
|
-
foreground: foreground,
|
|
30
|
-
background: background,
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
EncodedTokenAttributes.print = print;
|
|
34
|
-
function getLanguageId(encodedTokenAttributes) {
|
|
35
|
-
return ((encodedTokenAttributes & 255 /* EncodedTokenDataConsts.LANGUAGEID_MASK */) >>>
|
|
36
|
-
0 /* EncodedTokenDataConsts.LANGUAGEID_OFFSET */);
|
|
37
|
-
}
|
|
38
|
-
EncodedTokenAttributes.getLanguageId = getLanguageId;
|
|
39
|
-
function getTokenType(encodedTokenAttributes) {
|
|
40
|
-
return ((encodedTokenAttributes & 768 /* EncodedTokenDataConsts.TOKEN_TYPE_MASK */) >>>
|
|
41
|
-
8 /* EncodedTokenDataConsts.TOKEN_TYPE_OFFSET */);
|
|
42
|
-
}
|
|
43
|
-
EncodedTokenAttributes.getTokenType = getTokenType;
|
|
44
|
-
function containsBalancedBrackets(encodedTokenAttributes) {
|
|
45
|
-
return (encodedTokenAttributes & 1024 /* EncodedTokenDataConsts.BALANCED_BRACKETS_MASK */) !== 0;
|
|
46
|
-
}
|
|
47
|
-
EncodedTokenAttributes.containsBalancedBrackets = containsBalancedBrackets;
|
|
48
|
-
function getFontStyle(encodedTokenAttributes) {
|
|
49
|
-
return ((encodedTokenAttributes & 30720 /* EncodedTokenDataConsts.FONT_STYLE_MASK */) >>>
|
|
50
|
-
11 /* EncodedTokenDataConsts.FONT_STYLE_OFFSET */);
|
|
51
|
-
}
|
|
52
|
-
EncodedTokenAttributes.getFontStyle = getFontStyle;
|
|
53
|
-
function getForeground(encodedTokenAttributes) {
|
|
54
|
-
return ((encodedTokenAttributes & 16744448 /* EncodedTokenDataConsts.FOREGROUND_MASK */) >>>
|
|
55
|
-
15 /* EncodedTokenDataConsts.FOREGROUND_OFFSET */);
|
|
56
|
-
}
|
|
57
|
-
EncodedTokenAttributes.getForeground = getForeground;
|
|
58
|
-
function getBackground(encodedTokenAttributes) {
|
|
59
|
-
return ((encodedTokenAttributes & 4278190080 /* EncodedTokenDataConsts.BACKGROUND_MASK */) >>>
|
|
60
|
-
24 /* EncodedTokenDataConsts.BACKGROUND_OFFSET */);
|
|
61
|
-
}
|
|
62
|
-
EncodedTokenAttributes.getBackground = getBackground;
|
|
63
|
-
/**
|
|
64
|
-
* Updates the fields in `metadata`.
|
|
65
|
-
* A value of `0`, `NotSet` or `null` indicates that the corresponding field should be left as is.
|
|
66
|
-
*/
|
|
67
|
-
function set(encodedTokenAttributes, languageId, tokenType, containsBalancedBrackets, fontStyle, foreground, background) {
|
|
68
|
-
let _languageId = EncodedTokenAttributes.getLanguageId(encodedTokenAttributes);
|
|
69
|
-
let _tokenType = EncodedTokenAttributes.getTokenType(encodedTokenAttributes);
|
|
70
|
-
let _containsBalancedBracketsBit = EncodedTokenAttributes.containsBalancedBrackets(encodedTokenAttributes) ? 1 : 0;
|
|
71
|
-
let _fontStyle = EncodedTokenAttributes.getFontStyle(encodedTokenAttributes);
|
|
72
|
-
let _foreground = EncodedTokenAttributes.getForeground(encodedTokenAttributes);
|
|
73
|
-
let _background = EncodedTokenAttributes.getBackground(encodedTokenAttributes);
|
|
74
|
-
if (languageId !== 0) {
|
|
75
|
-
_languageId = languageId;
|
|
76
|
-
}
|
|
77
|
-
if (tokenType !== 8 /* OptionalStandardTokenType.NotSet */) {
|
|
78
|
-
_tokenType = fromOptionalTokenType(tokenType);
|
|
79
|
-
}
|
|
80
|
-
if (containsBalancedBrackets !== null) {
|
|
81
|
-
_containsBalancedBracketsBit = containsBalancedBrackets ? 1 : 0;
|
|
82
|
-
}
|
|
83
|
-
if (fontStyle !== -1 /* FontStyle.NotSet */) {
|
|
84
|
-
_fontStyle = fontStyle;
|
|
85
|
-
}
|
|
86
|
-
if (foreground !== 0) {
|
|
87
|
-
_foreground = foreground;
|
|
88
|
-
}
|
|
89
|
-
if (background !== 0) {
|
|
90
|
-
_background = background;
|
|
91
|
-
}
|
|
92
|
-
return (((_languageId << 0 /* EncodedTokenDataConsts.LANGUAGEID_OFFSET */) |
|
|
93
|
-
(_tokenType << 8 /* EncodedTokenDataConsts.TOKEN_TYPE_OFFSET */) |
|
|
94
|
-
(_containsBalancedBracketsBit <<
|
|
95
|
-
10 /* EncodedTokenDataConsts.BALANCED_BRACKETS_OFFSET */) |
|
|
96
|
-
(_fontStyle << 11 /* EncodedTokenDataConsts.FONT_STYLE_OFFSET */) |
|
|
97
|
-
(_foreground << 15 /* EncodedTokenDataConsts.FOREGROUND_OFFSET */) |
|
|
98
|
-
(_background << 24 /* EncodedTokenDataConsts.BACKGROUND_OFFSET */)) >>>
|
|
99
|
-
0);
|
|
100
|
-
}
|
|
101
|
-
EncodedTokenAttributes.set = set;
|
|
102
|
-
})(EncodedTokenAttributes || (EncodedTokenAttributes = {}));
|
|
103
|
-
function toOptionalTokenType(standardType) {
|
|
104
|
-
return standardType;
|
|
105
|
-
}
|
|
106
|
-
function fromOptionalTokenType(standardType) {
|
|
107
|
-
return standardType;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/*---------------------------------------------------------
|
|
111
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
112
|
-
*--------------------------------------------------------*/
|
|
113
|
-
function createMatchers(selector, matchesName) {
|
|
114
|
-
const results = [];
|
|
115
|
-
const tokenizer = newTokenizer(selector);
|
|
116
|
-
let token = tokenizer.next();
|
|
117
|
-
while (token !== null) {
|
|
118
|
-
let priority = 0;
|
|
119
|
-
if (token.length === 2 && token.charAt(1) === ':') {
|
|
120
|
-
switch (token.charAt(0)) {
|
|
121
|
-
case 'R':
|
|
122
|
-
priority = 1;
|
|
123
|
-
break;
|
|
124
|
-
case 'L':
|
|
125
|
-
priority = -1;
|
|
126
|
-
break;
|
|
127
|
-
default:
|
|
128
|
-
console.log(`Unknown priority ${token} in scope selector`);
|
|
129
|
-
}
|
|
130
|
-
token = tokenizer.next();
|
|
131
|
-
}
|
|
132
|
-
let matcher = parseConjunction();
|
|
133
|
-
results.push({ matcher, priority });
|
|
134
|
-
if (token !== ',') {
|
|
135
|
-
break;
|
|
136
|
-
}
|
|
137
|
-
token = tokenizer.next();
|
|
138
|
-
}
|
|
139
|
-
return results;
|
|
140
|
-
function parseOperand() {
|
|
141
|
-
if (token === '-') {
|
|
142
|
-
token = tokenizer.next();
|
|
143
|
-
const expressionToNegate = parseOperand();
|
|
144
|
-
return matcherInput => !!expressionToNegate && !expressionToNegate(matcherInput);
|
|
145
|
-
}
|
|
146
|
-
if (token === '(') {
|
|
147
|
-
token = tokenizer.next();
|
|
148
|
-
const expressionInParents = parseInnerExpression();
|
|
149
|
-
if (token === ')') {
|
|
150
|
-
token = tokenizer.next();
|
|
151
|
-
}
|
|
152
|
-
return expressionInParents;
|
|
153
|
-
}
|
|
154
|
-
if (isIdentifier(token)) {
|
|
155
|
-
const identifiers = [];
|
|
156
|
-
do {
|
|
157
|
-
identifiers.push(token);
|
|
158
|
-
token = tokenizer.next();
|
|
159
|
-
} while (isIdentifier(token));
|
|
160
|
-
return matcherInput => matchesName(identifiers, matcherInput);
|
|
161
|
-
}
|
|
162
|
-
return null;
|
|
163
|
-
}
|
|
164
|
-
function parseConjunction() {
|
|
165
|
-
const matchers = [];
|
|
166
|
-
let matcher = parseOperand();
|
|
167
|
-
while (matcher) {
|
|
168
|
-
matchers.push(matcher);
|
|
169
|
-
matcher = parseOperand();
|
|
170
|
-
}
|
|
171
|
-
return matcherInput => matchers.every(matcher => matcher(matcherInput)); // and
|
|
172
|
-
}
|
|
173
|
-
function parseInnerExpression() {
|
|
174
|
-
const matchers = [];
|
|
175
|
-
let matcher = parseConjunction();
|
|
176
|
-
while (matcher) {
|
|
177
|
-
matchers.push(matcher);
|
|
178
|
-
if (token === '|' || token === ',') {
|
|
179
|
-
do {
|
|
180
|
-
token = tokenizer.next();
|
|
181
|
-
} while (token === '|' || token === ','); // ignore subsequent commas
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
break;
|
|
185
|
-
}
|
|
186
|
-
matcher = parseConjunction();
|
|
187
|
-
}
|
|
188
|
-
return matcherInput => matchers.some(matcher => matcher(matcherInput)); // or
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
function isIdentifier(token) {
|
|
192
|
-
return !!token && !!token.match(/[\w\.:]+/);
|
|
193
|
-
}
|
|
194
|
-
function newTokenizer(input) {
|
|
195
|
-
let regex = /([LR]:|[\w\.:][\w\.:\-]*|[\,\|\-\(\)])/g;
|
|
196
|
-
let match = regex.exec(input);
|
|
197
|
-
return {
|
|
198
|
-
next: () => {
|
|
199
|
-
if (!match) {
|
|
200
|
-
return null;
|
|
201
|
-
}
|
|
202
|
-
const res = match[0];
|
|
203
|
-
match = regex.exec(input);
|
|
204
|
-
return res;
|
|
205
|
-
}
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/*---------------------------------------------------------
|
|
210
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
211
|
-
*--------------------------------------------------------*/
|
|
212
|
-
function disposeOnigString(str) {
|
|
213
|
-
if (typeof str.dispose === 'function') {
|
|
214
|
-
str.dispose();
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/*---------------------------------------------------------
|
|
219
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
220
|
-
*--------------------------------------------------------*/
|
|
221
|
-
function clone(something) {
|
|
222
|
-
return doClone(something);
|
|
223
|
-
}
|
|
224
|
-
function doClone(something) {
|
|
225
|
-
if (Array.isArray(something)) {
|
|
226
|
-
return cloneArray(something);
|
|
227
|
-
}
|
|
228
|
-
if (typeof something === 'object') {
|
|
229
|
-
return cloneObj(something);
|
|
230
|
-
}
|
|
231
|
-
return something;
|
|
232
|
-
}
|
|
233
|
-
function cloneArray(arr) {
|
|
234
|
-
let r = [];
|
|
235
|
-
for (let i = 0, len = arr.length; i < len; i++) {
|
|
236
|
-
r[i] = doClone(arr[i]);
|
|
237
|
-
}
|
|
238
|
-
return r;
|
|
239
|
-
}
|
|
240
|
-
function cloneObj(obj) {
|
|
241
|
-
let r = {};
|
|
242
|
-
for (let key in obj) {
|
|
243
|
-
r[key] = doClone(obj[key]);
|
|
244
|
-
}
|
|
245
|
-
return r;
|
|
246
|
-
}
|
|
247
|
-
function mergeObjects(target, ...sources) {
|
|
248
|
-
sources.forEach(source => {
|
|
249
|
-
for (let key in source) {
|
|
250
|
-
target[key] = source[key];
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
return target;
|
|
254
|
-
}
|
|
255
|
-
function basename(path) {
|
|
256
|
-
const idx = ~path.lastIndexOf('/') || ~path.lastIndexOf('\\');
|
|
257
|
-
if (idx === 0) {
|
|
258
|
-
return path;
|
|
259
|
-
}
|
|
260
|
-
else if (~idx === path.length - 1) {
|
|
261
|
-
return basename(path.substring(0, path.length - 1));
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
return path.substr(~idx + 1);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
let CAPTURING_REGEX_SOURCE = /\$(\d+)|\${(\d+):\/(downcase|upcase)}/g;
|
|
268
|
-
class RegexSource {
|
|
269
|
-
static hasCaptures(regexSource) {
|
|
270
|
-
if (regexSource === null) {
|
|
271
|
-
return false;
|
|
272
|
-
}
|
|
273
|
-
CAPTURING_REGEX_SOURCE.lastIndex = 0;
|
|
274
|
-
return CAPTURING_REGEX_SOURCE.test(regexSource);
|
|
275
|
-
}
|
|
276
|
-
static replaceCaptures(regexSource, captureSource, captureIndices) {
|
|
277
|
-
return regexSource.replace(CAPTURING_REGEX_SOURCE, (match, index, commandIndex, command) => {
|
|
278
|
-
let capture = captureIndices[parseInt(index || commandIndex, 10)];
|
|
279
|
-
if (capture) {
|
|
280
|
-
let result = captureSource.substring(capture.start, capture.end);
|
|
281
|
-
// Remove leading dots that would make the selector invalid
|
|
282
|
-
while (result[0] === '.') {
|
|
283
|
-
result = result.substring(1);
|
|
284
|
-
}
|
|
285
|
-
switch (command) {
|
|
286
|
-
case 'downcase':
|
|
287
|
-
return result.toLowerCase();
|
|
288
|
-
case 'upcase':
|
|
289
|
-
return result.toUpperCase();
|
|
290
|
-
default:
|
|
291
|
-
return result;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
return match;
|
|
296
|
-
}
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
function strcmp(a, b) {
|
|
301
|
-
if (a < b) {
|
|
302
|
-
return -1;
|
|
303
|
-
}
|
|
304
|
-
if (a > b) {
|
|
305
|
-
return 1;
|
|
306
|
-
}
|
|
307
|
-
return 0;
|
|
308
|
-
}
|
|
309
|
-
function strArrCmp(a, b) {
|
|
310
|
-
if (a === null && b === null) {
|
|
311
|
-
return 0;
|
|
312
|
-
}
|
|
313
|
-
if (!a) {
|
|
314
|
-
return -1;
|
|
315
|
-
}
|
|
316
|
-
if (!b) {
|
|
317
|
-
return 1;
|
|
318
|
-
}
|
|
319
|
-
let len1 = a.length;
|
|
320
|
-
let len2 = b.length;
|
|
321
|
-
if (len1 === len2) {
|
|
322
|
-
for (let i = 0; i < len1; i++) {
|
|
323
|
-
let res = strcmp(a[i], b[i]);
|
|
324
|
-
if (res !== 0) {
|
|
325
|
-
return res;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
return 0;
|
|
329
|
-
}
|
|
330
|
-
return len1 - len2;
|
|
331
|
-
}
|
|
332
|
-
function isValidHexColor(hex) {
|
|
333
|
-
if (/^#[0-9a-f]{6}$/i.test(hex)) {
|
|
334
|
-
// #rrggbb
|
|
335
|
-
return true;
|
|
336
|
-
}
|
|
337
|
-
if (/^#[0-9a-f]{8}$/i.test(hex)) {
|
|
338
|
-
// #rrggbbaa
|
|
339
|
-
return true;
|
|
340
|
-
}
|
|
341
|
-
if (/^#[0-9a-f]{3}$/i.test(hex)) {
|
|
342
|
-
// #rgb
|
|
343
|
-
return true;
|
|
344
|
-
}
|
|
345
|
-
if (/^#[0-9a-f]{4}$/i.test(hex)) {
|
|
346
|
-
// #rgba
|
|
347
|
-
return true;
|
|
348
|
-
}
|
|
349
|
-
return false;
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Escapes regular expression characters in a given string
|
|
353
|
-
*/
|
|
354
|
-
function escapeRegExpCharacters(value) {
|
|
355
|
-
return value.replace(/[\-\\\{\}\*\+\?\|\^\$\.\,\[\]\(\)\#\s]/g, '\\$&');
|
|
356
|
-
}
|
|
357
|
-
class CachedFn {
|
|
358
|
-
fn;
|
|
359
|
-
cache = new Map();
|
|
360
|
-
constructor(fn) {
|
|
361
|
-
this.fn = fn;
|
|
362
|
-
}
|
|
363
|
-
get(key) {
|
|
364
|
-
if (this.cache.has(key)) {
|
|
365
|
-
return this.cache.get(key);
|
|
366
|
-
}
|
|
367
|
-
const value = this.fn(key);
|
|
368
|
-
this.cache.set(key, value);
|
|
369
|
-
return value;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/*---------------------------------------------------------
|
|
374
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
375
|
-
*--------------------------------------------------------*/
|
|
376
|
-
/**
|
|
377
|
-
* References the top level rule of a grammar with the given scope name.
|
|
378
|
-
*/
|
|
379
|
-
class TopLevelRuleReference {
|
|
380
|
-
scopeName;
|
|
381
|
-
constructor(scopeName) {
|
|
382
|
-
this.scopeName = scopeName;
|
|
383
|
-
}
|
|
384
|
-
toKey() {
|
|
385
|
-
return this.scopeName;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* References a rule of a grammar in the top level repository section with the given name.
|
|
390
|
-
*/
|
|
391
|
-
class TopLevelRepositoryRuleReference {
|
|
392
|
-
scopeName;
|
|
393
|
-
ruleName;
|
|
394
|
-
constructor(scopeName, ruleName) {
|
|
395
|
-
this.scopeName = scopeName;
|
|
396
|
-
this.ruleName = ruleName;
|
|
397
|
-
}
|
|
398
|
-
toKey() {
|
|
399
|
-
return `${this.scopeName}#${this.ruleName}`;
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
class ExternalReferenceCollector {
|
|
403
|
-
_references = [];
|
|
404
|
-
_seenReferenceKeys = new Set();
|
|
405
|
-
get references() {
|
|
406
|
-
return this._references;
|
|
407
|
-
}
|
|
408
|
-
visitedRule = new Set();
|
|
409
|
-
add(reference) {
|
|
410
|
-
const key = reference.toKey();
|
|
411
|
-
if (this._seenReferenceKeys.has(key)) {
|
|
412
|
-
return;
|
|
413
|
-
}
|
|
414
|
-
this._seenReferenceKeys.add(key);
|
|
415
|
-
this._references.push(reference);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
class ScopeDependencyProcessor {
|
|
419
|
-
repo;
|
|
420
|
-
initialScopeName;
|
|
421
|
-
seenFullScopeRequests = new Set();
|
|
422
|
-
seenPartialScopeRequests = new Set();
|
|
423
|
-
Q;
|
|
424
|
-
constructor(repo, initialScopeName) {
|
|
425
|
-
this.repo = repo;
|
|
426
|
-
this.initialScopeName = initialScopeName;
|
|
427
|
-
this.seenFullScopeRequests.add(this.initialScopeName);
|
|
428
|
-
this.Q = [new TopLevelRuleReference(this.initialScopeName)];
|
|
429
|
-
}
|
|
430
|
-
processQueue() {
|
|
431
|
-
const q = this.Q;
|
|
432
|
-
this.Q = [];
|
|
433
|
-
const deps = new ExternalReferenceCollector();
|
|
434
|
-
for (const dep of q) {
|
|
435
|
-
collectReferencesOfReference(dep, this.initialScopeName, this.repo, deps);
|
|
436
|
-
}
|
|
437
|
-
for (const dep of deps.references) {
|
|
438
|
-
if (dep instanceof TopLevelRuleReference) {
|
|
439
|
-
if (this.seenFullScopeRequests.has(dep.scopeName)) {
|
|
440
|
-
// already processed
|
|
441
|
-
continue;
|
|
442
|
-
}
|
|
443
|
-
this.seenFullScopeRequests.add(dep.scopeName);
|
|
444
|
-
this.Q.push(dep);
|
|
445
|
-
}
|
|
446
|
-
else {
|
|
447
|
-
if (this.seenFullScopeRequests.has(dep.scopeName)) {
|
|
448
|
-
// already processed in full
|
|
449
|
-
continue;
|
|
450
|
-
}
|
|
451
|
-
if (this.seenPartialScopeRequests.has(dep.toKey())) {
|
|
452
|
-
// already processed
|
|
453
|
-
continue;
|
|
454
|
-
}
|
|
455
|
-
this.seenPartialScopeRequests.add(dep.toKey());
|
|
456
|
-
this.Q.push(dep);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
function collectReferencesOfReference(reference, baseGrammarScopeName, repo, result) {
|
|
462
|
-
const selfGrammar = repo.lookup(reference.scopeName);
|
|
463
|
-
if (!selfGrammar) {
|
|
464
|
-
if (reference.scopeName === baseGrammarScopeName) {
|
|
465
|
-
throw new Error(`No grammar provided for <${baseGrammarScopeName}>`);
|
|
466
|
-
}
|
|
467
|
-
return;
|
|
468
|
-
}
|
|
469
|
-
const baseGrammar = repo.lookup(baseGrammarScopeName);
|
|
470
|
-
if (reference instanceof TopLevelRuleReference) {
|
|
471
|
-
collectExternalReferencesInTopLevelRule({ baseGrammar, selfGrammar }, result);
|
|
472
|
-
}
|
|
473
|
-
else {
|
|
474
|
-
collectExternalReferencesInTopLevelRepositoryRule(reference.ruleName, { baseGrammar, selfGrammar, repository: selfGrammar.repository }, result);
|
|
475
|
-
}
|
|
476
|
-
const injections = repo.injections(reference.scopeName);
|
|
477
|
-
if (injections) {
|
|
478
|
-
for (const injection of injections) {
|
|
479
|
-
result.add(new TopLevelRuleReference(injection));
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
function collectExternalReferencesInTopLevelRepositoryRule(ruleName, context, result) {
|
|
484
|
-
if (context.repository && context.repository[ruleName]) {
|
|
485
|
-
const rule = context.repository[ruleName];
|
|
486
|
-
collectExternalReferencesInRules([rule], context, result);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
function collectExternalReferencesInTopLevelRule(context, result) {
|
|
490
|
-
if (context.selfGrammar.patterns && Array.isArray(context.selfGrammar.patterns)) {
|
|
491
|
-
collectExternalReferencesInRules(context.selfGrammar.patterns, { ...context, repository: context.selfGrammar.repository }, result);
|
|
492
|
-
}
|
|
493
|
-
if (context.selfGrammar.injections) {
|
|
494
|
-
collectExternalReferencesInRules(Object.values(context.selfGrammar.injections), { ...context, repository: context.selfGrammar.repository }, result);
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
function collectExternalReferencesInRules(rules, context, result) {
|
|
498
|
-
for (const rule of rules) {
|
|
499
|
-
if (result.visitedRule.has(rule)) {
|
|
500
|
-
continue;
|
|
501
|
-
}
|
|
502
|
-
result.visitedRule.add(rule);
|
|
503
|
-
const patternRepository = rule.repository ? mergeObjects({}, context.repository, rule.repository) : context.repository;
|
|
504
|
-
if (Array.isArray(rule.patterns)) {
|
|
505
|
-
collectExternalReferencesInRules(rule.patterns, { ...context, repository: patternRepository }, result);
|
|
506
|
-
}
|
|
507
|
-
const include = rule.include;
|
|
508
|
-
if (!include) {
|
|
509
|
-
continue;
|
|
510
|
-
}
|
|
511
|
-
const reference = parseInclude(include);
|
|
512
|
-
switch (reference.kind) {
|
|
513
|
-
case 0 /* IncludeReferenceKind.Base */:
|
|
514
|
-
collectExternalReferencesInTopLevelRule({ ...context, selfGrammar: context.baseGrammar }, result);
|
|
515
|
-
break;
|
|
516
|
-
case 1 /* IncludeReferenceKind.Self */:
|
|
517
|
-
collectExternalReferencesInTopLevelRule(context, result);
|
|
518
|
-
break;
|
|
519
|
-
case 2 /* IncludeReferenceKind.RelativeReference */:
|
|
520
|
-
collectExternalReferencesInTopLevelRepositoryRule(reference.ruleName, { ...context, repository: patternRepository }, result);
|
|
521
|
-
break;
|
|
522
|
-
case 3 /* IncludeReferenceKind.TopLevelReference */:
|
|
523
|
-
case 4 /* IncludeReferenceKind.TopLevelRepositoryReference */:
|
|
524
|
-
const selfGrammar = reference.scopeName === context.selfGrammar.scopeName
|
|
525
|
-
? context.selfGrammar
|
|
526
|
-
: reference.scopeName === context.baseGrammar.scopeName
|
|
527
|
-
? context.baseGrammar
|
|
528
|
-
: undefined;
|
|
529
|
-
if (selfGrammar) {
|
|
530
|
-
const newContext = { baseGrammar: context.baseGrammar, selfGrammar, repository: patternRepository };
|
|
531
|
-
if (reference.kind === 4 /* IncludeReferenceKind.TopLevelRepositoryReference */) {
|
|
532
|
-
collectExternalReferencesInTopLevelRepositoryRule(reference.ruleName, newContext, result);
|
|
533
|
-
}
|
|
534
|
-
else {
|
|
535
|
-
collectExternalReferencesInTopLevelRule(newContext, result);
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
else {
|
|
539
|
-
if (reference.kind === 4 /* IncludeReferenceKind.TopLevelRepositoryReference */) {
|
|
540
|
-
result.add(new TopLevelRepositoryRuleReference(reference.scopeName, reference.ruleName));
|
|
541
|
-
}
|
|
542
|
-
else {
|
|
543
|
-
result.add(new TopLevelRuleReference(reference.scopeName));
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
break;
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
class BaseReference {
|
|
551
|
-
kind = 0 /* IncludeReferenceKind.Base */;
|
|
552
|
-
}
|
|
553
|
-
class SelfReference {
|
|
554
|
-
kind = 1 /* IncludeReferenceKind.Self */;
|
|
555
|
-
}
|
|
556
|
-
class RelativeReference {
|
|
557
|
-
ruleName;
|
|
558
|
-
kind = 2 /* IncludeReferenceKind.RelativeReference */;
|
|
559
|
-
constructor(ruleName) {
|
|
560
|
-
this.ruleName = ruleName;
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
class TopLevelReference {
|
|
564
|
-
scopeName;
|
|
565
|
-
kind = 3 /* IncludeReferenceKind.TopLevelReference */;
|
|
566
|
-
constructor(scopeName) {
|
|
567
|
-
this.scopeName = scopeName;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
class TopLevelRepositoryReference {
|
|
571
|
-
scopeName;
|
|
572
|
-
ruleName;
|
|
573
|
-
kind = 4 /* IncludeReferenceKind.TopLevelRepositoryReference */;
|
|
574
|
-
constructor(scopeName, ruleName) {
|
|
575
|
-
this.scopeName = scopeName;
|
|
576
|
-
this.ruleName = ruleName;
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
function parseInclude(include) {
|
|
580
|
-
if (include === '$base') {
|
|
581
|
-
return new BaseReference();
|
|
582
|
-
}
|
|
583
|
-
else if (include === '$self') {
|
|
584
|
-
return new SelfReference();
|
|
585
|
-
}
|
|
586
|
-
const indexOfSharp = include.indexOf("#");
|
|
587
|
-
if (indexOfSharp === -1) {
|
|
588
|
-
return new TopLevelReference(include);
|
|
589
|
-
}
|
|
590
|
-
else if (indexOfSharp === 0) {
|
|
591
|
-
return new RelativeReference(include.substring(1));
|
|
592
|
-
}
|
|
593
|
-
else {
|
|
594
|
-
const scopeName = include.substring(0, indexOfSharp);
|
|
595
|
-
const ruleName = include.substring(indexOfSharp + 1);
|
|
596
|
-
return new TopLevelRepositoryReference(scopeName, ruleName);
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
/*---------------------------------------------------------
|
|
601
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
602
|
-
*--------------------------------------------------------*/
|
|
603
|
-
const HAS_BACK_REFERENCES = /\\(\d+)/;
|
|
604
|
-
const BACK_REFERENCING_END = /\\(\d+)/g;
|
|
605
|
-
// This is a special constant to indicate that the end regexp matched.
|
|
606
|
-
const endRuleId = -1;
|
|
607
|
-
// This is a special constant to indicate that the while regexp matched.
|
|
608
|
-
const whileRuleId = -2;
|
|
609
|
-
function ruleIdFromNumber(id) {
|
|
610
|
-
return id;
|
|
611
|
-
}
|
|
612
|
-
function ruleIdToNumber(id) {
|
|
613
|
-
return id;
|
|
614
|
-
}
|
|
615
|
-
class Rule {
|
|
616
|
-
$location;
|
|
617
|
-
id;
|
|
618
|
-
_nameIsCapturing;
|
|
619
|
-
_name;
|
|
620
|
-
_contentNameIsCapturing;
|
|
621
|
-
_contentName;
|
|
622
|
-
constructor($location, id, name, contentName) {
|
|
623
|
-
this.$location = $location;
|
|
624
|
-
this.id = id;
|
|
625
|
-
this._name = name || null;
|
|
626
|
-
this._nameIsCapturing = RegexSource.hasCaptures(this._name);
|
|
627
|
-
this._contentName = contentName || null;
|
|
628
|
-
this._contentNameIsCapturing = RegexSource.hasCaptures(this._contentName);
|
|
629
|
-
}
|
|
630
|
-
get debugName() {
|
|
631
|
-
const location = this.$location ? `${basename(this.$location.filename)}:${this.$location.line}` : 'unknown';
|
|
632
|
-
return `${this.constructor.name}#${this.id} @ ${location}`;
|
|
633
|
-
}
|
|
634
|
-
getName(lineText, captureIndices) {
|
|
635
|
-
if (!this._nameIsCapturing || this._name === null || lineText === null || captureIndices === null) {
|
|
636
|
-
return this._name;
|
|
637
|
-
}
|
|
638
|
-
return RegexSource.replaceCaptures(this._name, lineText, captureIndices);
|
|
639
|
-
}
|
|
640
|
-
getContentName(lineText, captureIndices) {
|
|
641
|
-
if (!this._contentNameIsCapturing || this._contentName === null) {
|
|
642
|
-
return this._contentName;
|
|
643
|
-
}
|
|
644
|
-
return RegexSource.replaceCaptures(this._contentName, lineText, captureIndices);
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
class CaptureRule extends Rule {
|
|
648
|
-
retokenizeCapturedWithRuleId;
|
|
649
|
-
constructor($location, id, name, contentName, retokenizeCapturedWithRuleId) {
|
|
650
|
-
super($location, id, name, contentName);
|
|
651
|
-
this.retokenizeCapturedWithRuleId = retokenizeCapturedWithRuleId;
|
|
652
|
-
}
|
|
653
|
-
dispose() {
|
|
654
|
-
// nothing to dispose
|
|
655
|
-
}
|
|
656
|
-
collectPatterns(grammar, out) {
|
|
657
|
-
throw new Error('Not supported!');
|
|
658
|
-
}
|
|
659
|
-
compile(grammar, endRegexSource) {
|
|
660
|
-
throw new Error('Not supported!');
|
|
661
|
-
}
|
|
662
|
-
compileAG(grammar, endRegexSource, allowA, allowG) {
|
|
663
|
-
throw new Error('Not supported!');
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
class MatchRule extends Rule {
|
|
667
|
-
_match;
|
|
668
|
-
captures;
|
|
669
|
-
_cachedCompiledPatterns;
|
|
670
|
-
constructor($location, id, name, match, captures) {
|
|
671
|
-
super($location, id, name, null);
|
|
672
|
-
this._match = new RegExpSource(match, this.id);
|
|
673
|
-
this.captures = captures;
|
|
674
|
-
this._cachedCompiledPatterns = null;
|
|
675
|
-
}
|
|
676
|
-
dispose() {
|
|
677
|
-
if (this._cachedCompiledPatterns) {
|
|
678
|
-
this._cachedCompiledPatterns.dispose();
|
|
679
|
-
this._cachedCompiledPatterns = null;
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
get debugMatchRegExp() {
|
|
683
|
-
return `${this._match.source}`;
|
|
684
|
-
}
|
|
685
|
-
collectPatterns(grammar, out) {
|
|
686
|
-
out.push(this._match);
|
|
687
|
-
}
|
|
688
|
-
compile(grammar, endRegexSource) {
|
|
689
|
-
return this._getCachedCompiledPatterns(grammar).compile(grammar);
|
|
690
|
-
}
|
|
691
|
-
compileAG(grammar, endRegexSource, allowA, allowG) {
|
|
692
|
-
return this._getCachedCompiledPatterns(grammar).compileAG(grammar, allowA, allowG);
|
|
693
|
-
}
|
|
694
|
-
_getCachedCompiledPatterns(grammar) {
|
|
695
|
-
if (!this._cachedCompiledPatterns) {
|
|
696
|
-
this._cachedCompiledPatterns = new RegExpSourceList();
|
|
697
|
-
this.collectPatterns(grammar, this._cachedCompiledPatterns);
|
|
698
|
-
}
|
|
699
|
-
return this._cachedCompiledPatterns;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
class IncludeOnlyRule extends Rule {
|
|
703
|
-
hasMissingPatterns;
|
|
704
|
-
patterns;
|
|
705
|
-
_cachedCompiledPatterns;
|
|
706
|
-
constructor($location, id, name, contentName, patterns) {
|
|
707
|
-
super($location, id, name, contentName);
|
|
708
|
-
this.patterns = patterns.patterns;
|
|
709
|
-
this.hasMissingPatterns = patterns.hasMissingPatterns;
|
|
710
|
-
this._cachedCompiledPatterns = null;
|
|
711
|
-
}
|
|
712
|
-
dispose() {
|
|
713
|
-
if (this._cachedCompiledPatterns) {
|
|
714
|
-
this._cachedCompiledPatterns.dispose();
|
|
715
|
-
this._cachedCompiledPatterns = null;
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
collectPatterns(grammar, out) {
|
|
719
|
-
for (const pattern of this.patterns) {
|
|
720
|
-
const rule = grammar.getRule(pattern);
|
|
721
|
-
rule.collectPatterns(grammar, out);
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
compile(grammar, endRegexSource) {
|
|
725
|
-
return this._getCachedCompiledPatterns(grammar).compile(grammar);
|
|
726
|
-
}
|
|
727
|
-
compileAG(grammar, endRegexSource, allowA, allowG) {
|
|
728
|
-
return this._getCachedCompiledPatterns(grammar).compileAG(grammar, allowA, allowG);
|
|
729
|
-
}
|
|
730
|
-
_getCachedCompiledPatterns(grammar) {
|
|
731
|
-
if (!this._cachedCompiledPatterns) {
|
|
732
|
-
this._cachedCompiledPatterns = new RegExpSourceList();
|
|
733
|
-
this.collectPatterns(grammar, this._cachedCompiledPatterns);
|
|
734
|
-
}
|
|
735
|
-
return this._cachedCompiledPatterns;
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
class BeginEndRule extends Rule {
|
|
739
|
-
_begin;
|
|
740
|
-
beginCaptures;
|
|
741
|
-
_end;
|
|
742
|
-
endHasBackReferences;
|
|
743
|
-
endCaptures;
|
|
744
|
-
applyEndPatternLast;
|
|
745
|
-
hasMissingPatterns;
|
|
746
|
-
patterns;
|
|
747
|
-
_cachedCompiledPatterns;
|
|
748
|
-
constructor($location, id, name, contentName, begin, beginCaptures, end, endCaptures, applyEndPatternLast, patterns) {
|
|
749
|
-
super($location, id, name, contentName);
|
|
750
|
-
this._begin = new RegExpSource(begin, this.id);
|
|
751
|
-
this.beginCaptures = beginCaptures;
|
|
752
|
-
this._end = new RegExpSource(end ? end : '\uFFFF', -1);
|
|
753
|
-
this.endHasBackReferences = this._end.hasBackReferences;
|
|
754
|
-
this.endCaptures = endCaptures;
|
|
755
|
-
this.applyEndPatternLast = applyEndPatternLast || false;
|
|
756
|
-
this.patterns = patterns.patterns;
|
|
757
|
-
this.hasMissingPatterns = patterns.hasMissingPatterns;
|
|
758
|
-
this._cachedCompiledPatterns = null;
|
|
759
|
-
}
|
|
760
|
-
dispose() {
|
|
761
|
-
if (this._cachedCompiledPatterns) {
|
|
762
|
-
this._cachedCompiledPatterns.dispose();
|
|
763
|
-
this._cachedCompiledPatterns = null;
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
get debugBeginRegExp() {
|
|
767
|
-
return `${this._begin.source}`;
|
|
768
|
-
}
|
|
769
|
-
get debugEndRegExp() {
|
|
770
|
-
return `${this._end.source}`;
|
|
771
|
-
}
|
|
772
|
-
getEndWithResolvedBackReferences(lineText, captureIndices) {
|
|
773
|
-
return this._end.resolveBackReferences(lineText, captureIndices);
|
|
774
|
-
}
|
|
775
|
-
collectPatterns(grammar, out) {
|
|
776
|
-
out.push(this._begin);
|
|
777
|
-
}
|
|
778
|
-
compile(grammar, endRegexSource) {
|
|
779
|
-
return this._getCachedCompiledPatterns(grammar, endRegexSource).compile(grammar);
|
|
780
|
-
}
|
|
781
|
-
compileAG(grammar, endRegexSource, allowA, allowG) {
|
|
782
|
-
return this._getCachedCompiledPatterns(grammar, endRegexSource).compileAG(grammar, allowA, allowG);
|
|
783
|
-
}
|
|
784
|
-
_getCachedCompiledPatterns(grammar, endRegexSource) {
|
|
785
|
-
if (!this._cachedCompiledPatterns) {
|
|
786
|
-
this._cachedCompiledPatterns = new RegExpSourceList();
|
|
787
|
-
for (const pattern of this.patterns) {
|
|
788
|
-
const rule = grammar.getRule(pattern);
|
|
789
|
-
rule.collectPatterns(grammar, this._cachedCompiledPatterns);
|
|
790
|
-
}
|
|
791
|
-
if (this.applyEndPatternLast) {
|
|
792
|
-
this._cachedCompiledPatterns.push(this._end.hasBackReferences ? this._end.clone() : this._end);
|
|
793
|
-
}
|
|
794
|
-
else {
|
|
795
|
-
this._cachedCompiledPatterns.unshift(this._end.hasBackReferences ? this._end.clone() : this._end);
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
if (this._end.hasBackReferences) {
|
|
799
|
-
if (this.applyEndPatternLast) {
|
|
800
|
-
this._cachedCompiledPatterns.setSource(this._cachedCompiledPatterns.length() - 1, endRegexSource);
|
|
801
|
-
}
|
|
802
|
-
else {
|
|
803
|
-
this._cachedCompiledPatterns.setSource(0, endRegexSource);
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
return this._cachedCompiledPatterns;
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
class BeginWhileRule extends Rule {
|
|
810
|
-
_begin;
|
|
811
|
-
beginCaptures;
|
|
812
|
-
whileCaptures;
|
|
813
|
-
_while;
|
|
814
|
-
whileHasBackReferences;
|
|
815
|
-
hasMissingPatterns;
|
|
816
|
-
patterns;
|
|
817
|
-
_cachedCompiledPatterns;
|
|
818
|
-
_cachedCompiledWhilePatterns;
|
|
819
|
-
constructor($location, id, name, contentName, begin, beginCaptures, _while, whileCaptures, patterns) {
|
|
820
|
-
super($location, id, name, contentName);
|
|
821
|
-
this._begin = new RegExpSource(begin, this.id);
|
|
822
|
-
this.beginCaptures = beginCaptures;
|
|
823
|
-
this.whileCaptures = whileCaptures;
|
|
824
|
-
this._while = new RegExpSource(_while, whileRuleId);
|
|
825
|
-
this.whileHasBackReferences = this._while.hasBackReferences;
|
|
826
|
-
this.patterns = patterns.patterns;
|
|
827
|
-
this.hasMissingPatterns = patterns.hasMissingPatterns;
|
|
828
|
-
this._cachedCompiledPatterns = null;
|
|
829
|
-
this._cachedCompiledWhilePatterns = null;
|
|
830
|
-
}
|
|
831
|
-
dispose() {
|
|
832
|
-
if (this._cachedCompiledPatterns) {
|
|
833
|
-
this._cachedCompiledPatterns.dispose();
|
|
834
|
-
this._cachedCompiledPatterns = null;
|
|
835
|
-
}
|
|
836
|
-
if (this._cachedCompiledWhilePatterns) {
|
|
837
|
-
this._cachedCompiledWhilePatterns.dispose();
|
|
838
|
-
this._cachedCompiledWhilePatterns = null;
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
get debugBeginRegExp() {
|
|
842
|
-
return `${this._begin.source}`;
|
|
843
|
-
}
|
|
844
|
-
get debugWhileRegExp() {
|
|
845
|
-
return `${this._while.source}`;
|
|
846
|
-
}
|
|
847
|
-
getWhileWithResolvedBackReferences(lineText, captureIndices) {
|
|
848
|
-
return this._while.resolveBackReferences(lineText, captureIndices);
|
|
849
|
-
}
|
|
850
|
-
collectPatterns(grammar, out) {
|
|
851
|
-
out.push(this._begin);
|
|
852
|
-
}
|
|
853
|
-
compile(grammar, endRegexSource) {
|
|
854
|
-
return this._getCachedCompiledPatterns(grammar).compile(grammar);
|
|
855
|
-
}
|
|
856
|
-
compileAG(grammar, endRegexSource, allowA, allowG) {
|
|
857
|
-
return this._getCachedCompiledPatterns(grammar).compileAG(grammar, allowA, allowG);
|
|
858
|
-
}
|
|
859
|
-
_getCachedCompiledPatterns(grammar) {
|
|
860
|
-
if (!this._cachedCompiledPatterns) {
|
|
861
|
-
this._cachedCompiledPatterns = new RegExpSourceList();
|
|
862
|
-
for (const pattern of this.patterns) {
|
|
863
|
-
const rule = grammar.getRule(pattern);
|
|
864
|
-
rule.collectPatterns(grammar, this._cachedCompiledPatterns);
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
return this._cachedCompiledPatterns;
|
|
868
|
-
}
|
|
869
|
-
compileWhile(grammar, endRegexSource) {
|
|
870
|
-
return this._getCachedCompiledWhilePatterns(grammar, endRegexSource).compile(grammar);
|
|
871
|
-
}
|
|
872
|
-
compileWhileAG(grammar, endRegexSource, allowA, allowG) {
|
|
873
|
-
return this._getCachedCompiledWhilePatterns(grammar, endRegexSource).compileAG(grammar, allowA, allowG);
|
|
874
|
-
}
|
|
875
|
-
_getCachedCompiledWhilePatterns(grammar, endRegexSource) {
|
|
876
|
-
if (!this._cachedCompiledWhilePatterns) {
|
|
877
|
-
this._cachedCompiledWhilePatterns = new RegExpSourceList();
|
|
878
|
-
this._cachedCompiledWhilePatterns.push(this._while.hasBackReferences ? this._while.clone() : this._while);
|
|
879
|
-
}
|
|
880
|
-
if (this._while.hasBackReferences) {
|
|
881
|
-
this._cachedCompiledWhilePatterns.setSource(0, endRegexSource ? endRegexSource : '\uFFFF');
|
|
882
|
-
}
|
|
883
|
-
return this._cachedCompiledWhilePatterns;
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
class RuleFactory {
|
|
887
|
-
static createCaptureRule(helper, $location, name, contentName, retokenizeCapturedWithRuleId) {
|
|
888
|
-
return helper.registerRule((id) => {
|
|
889
|
-
return new CaptureRule($location, id, name, contentName, retokenizeCapturedWithRuleId);
|
|
890
|
-
});
|
|
891
|
-
}
|
|
892
|
-
static getCompiledRuleId(desc, helper, repository) {
|
|
893
|
-
if (!desc.id) {
|
|
894
|
-
helper.registerRule((id) => {
|
|
895
|
-
desc.id = id;
|
|
896
|
-
if (desc.match) {
|
|
897
|
-
return new MatchRule(desc.$vscodeTextmateLocation, desc.id, desc.name, desc.match, RuleFactory._compileCaptures(desc.captures, helper, repository));
|
|
898
|
-
}
|
|
899
|
-
if (typeof desc.begin === 'undefined') {
|
|
900
|
-
if (desc.repository) {
|
|
901
|
-
repository = mergeObjects({}, repository, desc.repository);
|
|
902
|
-
}
|
|
903
|
-
let patterns = desc.patterns;
|
|
904
|
-
if (typeof patterns === 'undefined' && desc.include) {
|
|
905
|
-
patterns = [{ include: desc.include }];
|
|
906
|
-
}
|
|
907
|
-
return new IncludeOnlyRule(desc.$vscodeTextmateLocation, desc.id, desc.name, desc.contentName, RuleFactory._compilePatterns(patterns, helper, repository));
|
|
908
|
-
}
|
|
909
|
-
if (desc.while) {
|
|
910
|
-
return new BeginWhileRule(desc.$vscodeTextmateLocation, desc.id, desc.name, desc.contentName, desc.begin, RuleFactory._compileCaptures(desc.beginCaptures || desc.captures, helper, repository), desc.while, RuleFactory._compileCaptures(desc.whileCaptures || desc.captures, helper, repository), RuleFactory._compilePatterns(desc.patterns, helper, repository));
|
|
911
|
-
}
|
|
912
|
-
return new BeginEndRule(desc.$vscodeTextmateLocation, desc.id, desc.name, desc.contentName, desc.begin, RuleFactory._compileCaptures(desc.beginCaptures || desc.captures, helper, repository), desc.end, RuleFactory._compileCaptures(desc.endCaptures || desc.captures, helper, repository), desc.applyEndPatternLast, RuleFactory._compilePatterns(desc.patterns, helper, repository));
|
|
913
|
-
});
|
|
914
|
-
}
|
|
915
|
-
return desc.id;
|
|
916
|
-
}
|
|
917
|
-
static _compileCaptures(captures, helper, repository) {
|
|
918
|
-
let r = [];
|
|
919
|
-
if (captures) {
|
|
920
|
-
// Find the maximum capture id
|
|
921
|
-
let maximumCaptureId = 0;
|
|
922
|
-
for (const captureId in captures) {
|
|
923
|
-
if (captureId === '$vscodeTextmateLocation') {
|
|
924
|
-
continue;
|
|
925
|
-
}
|
|
926
|
-
const numericCaptureId = parseInt(captureId, 10);
|
|
927
|
-
if (numericCaptureId > maximumCaptureId) {
|
|
928
|
-
maximumCaptureId = numericCaptureId;
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
// Initialize result
|
|
932
|
-
for (let i = 0; i <= maximumCaptureId; i++) {
|
|
933
|
-
r[i] = null;
|
|
934
|
-
}
|
|
935
|
-
// Fill out result
|
|
936
|
-
for (const captureId in captures) {
|
|
937
|
-
if (captureId === '$vscodeTextmateLocation') {
|
|
938
|
-
continue;
|
|
939
|
-
}
|
|
940
|
-
const numericCaptureId = parseInt(captureId, 10);
|
|
941
|
-
let retokenizeCapturedWithRuleId = 0;
|
|
942
|
-
if (captures[captureId].patterns) {
|
|
943
|
-
retokenizeCapturedWithRuleId = RuleFactory.getCompiledRuleId(captures[captureId], helper, repository);
|
|
944
|
-
}
|
|
945
|
-
r[numericCaptureId] = RuleFactory.createCaptureRule(helper, captures[captureId].$vscodeTextmateLocation, captures[captureId].name, captures[captureId].contentName, retokenizeCapturedWithRuleId);
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
return r;
|
|
949
|
-
}
|
|
950
|
-
static _compilePatterns(patterns, helper, repository) {
|
|
951
|
-
let r = [];
|
|
952
|
-
if (patterns) {
|
|
953
|
-
for (let i = 0, len = patterns.length; i < len; i++) {
|
|
954
|
-
const pattern = patterns[i];
|
|
955
|
-
let ruleId = -1;
|
|
956
|
-
if (pattern.include) {
|
|
957
|
-
const reference = parseInclude(pattern.include);
|
|
958
|
-
switch (reference.kind) {
|
|
959
|
-
case 0 /* IncludeReferenceKind.Base */:
|
|
960
|
-
case 1 /* IncludeReferenceKind.Self */:
|
|
961
|
-
ruleId = RuleFactory.getCompiledRuleId(repository[pattern.include], helper, repository);
|
|
962
|
-
break;
|
|
963
|
-
case 2 /* IncludeReferenceKind.RelativeReference */:
|
|
964
|
-
// Local include found in `repository`
|
|
965
|
-
let localIncludedRule = repository[reference.ruleName];
|
|
966
|
-
if (localIncludedRule) {
|
|
967
|
-
ruleId = RuleFactory.getCompiledRuleId(localIncludedRule, helper, repository);
|
|
968
|
-
}
|
|
969
|
-
break;
|
|
970
|
-
case 3 /* IncludeReferenceKind.TopLevelReference */:
|
|
971
|
-
case 4 /* IncludeReferenceKind.TopLevelRepositoryReference */:
|
|
972
|
-
const externalGrammarName = reference.scopeName;
|
|
973
|
-
const externalGrammarInclude = reference.kind === 4 /* IncludeReferenceKind.TopLevelRepositoryReference */
|
|
974
|
-
? reference.ruleName
|
|
975
|
-
: null;
|
|
976
|
-
// External include
|
|
977
|
-
const externalGrammar = helper.getExternalGrammar(externalGrammarName, repository);
|
|
978
|
-
if (externalGrammar) {
|
|
979
|
-
if (externalGrammarInclude) {
|
|
980
|
-
let externalIncludedRule = externalGrammar.repository[externalGrammarInclude];
|
|
981
|
-
if (externalIncludedRule) {
|
|
982
|
-
ruleId = RuleFactory.getCompiledRuleId(externalIncludedRule, helper, externalGrammar.repository);
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
else {
|
|
986
|
-
ruleId = RuleFactory.getCompiledRuleId(externalGrammar.repository.$self, helper, externalGrammar.repository);
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
break;
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
else {
|
|
993
|
-
ruleId = RuleFactory.getCompiledRuleId(pattern, helper, repository);
|
|
994
|
-
}
|
|
995
|
-
if (ruleId !== -1) {
|
|
996
|
-
const rule = helper.getRule(ruleId);
|
|
997
|
-
let skipRule = false;
|
|
998
|
-
if (rule instanceof IncludeOnlyRule || rule instanceof BeginEndRule || rule instanceof BeginWhileRule) {
|
|
999
|
-
if (rule.hasMissingPatterns && rule.patterns.length === 0) {
|
|
1000
|
-
skipRule = true;
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
if (skipRule) {
|
|
1004
|
-
// console.log('REMOVING RULE ENTIRELY DUE TO EMPTY PATTERNS THAT ARE MISSING');
|
|
1005
|
-
continue;
|
|
1006
|
-
}
|
|
1007
|
-
r.push(ruleId);
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
return {
|
|
1012
|
-
patterns: r,
|
|
1013
|
-
hasMissingPatterns: ((patterns ? patterns.length : 0) !== r.length)
|
|
1014
|
-
};
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
class RegExpSource {
|
|
1018
|
-
source;
|
|
1019
|
-
ruleId;
|
|
1020
|
-
hasAnchor;
|
|
1021
|
-
hasBackReferences;
|
|
1022
|
-
_anchorCache;
|
|
1023
|
-
constructor(regExpSource, ruleId) {
|
|
1024
|
-
if (regExpSource) {
|
|
1025
|
-
const len = regExpSource.length;
|
|
1026
|
-
let lastPushedPos = 0;
|
|
1027
|
-
let output = [];
|
|
1028
|
-
let hasAnchor = false;
|
|
1029
|
-
for (let pos = 0; pos < len; pos++) {
|
|
1030
|
-
const ch = regExpSource.charAt(pos);
|
|
1031
|
-
if (ch === '\\') {
|
|
1032
|
-
if (pos + 1 < len) {
|
|
1033
|
-
const nextCh = regExpSource.charAt(pos + 1);
|
|
1034
|
-
if (nextCh === 'z') {
|
|
1035
|
-
output.push(regExpSource.substring(lastPushedPos, pos));
|
|
1036
|
-
output.push('$(?!\\n)(?<!\\n)');
|
|
1037
|
-
lastPushedPos = pos + 2;
|
|
1038
|
-
}
|
|
1039
|
-
else if (nextCh === 'A' || nextCh === 'G') {
|
|
1040
|
-
hasAnchor = true;
|
|
1041
|
-
}
|
|
1042
|
-
pos++;
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
this.hasAnchor = hasAnchor;
|
|
1047
|
-
if (lastPushedPos === 0) {
|
|
1048
|
-
// No \z hit
|
|
1049
|
-
this.source = regExpSource;
|
|
1050
|
-
}
|
|
1051
|
-
else {
|
|
1052
|
-
output.push(regExpSource.substring(lastPushedPos, len));
|
|
1053
|
-
this.source = output.join('');
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
else {
|
|
1057
|
-
this.hasAnchor = false;
|
|
1058
|
-
this.source = regExpSource;
|
|
1059
|
-
}
|
|
1060
|
-
if (this.hasAnchor) {
|
|
1061
|
-
this._anchorCache = this._buildAnchorCache();
|
|
1062
|
-
}
|
|
1063
|
-
else {
|
|
1064
|
-
this._anchorCache = null;
|
|
1065
|
-
}
|
|
1066
|
-
this.ruleId = ruleId;
|
|
1067
|
-
this.hasBackReferences = HAS_BACK_REFERENCES.test(this.source);
|
|
1068
|
-
// console.log('input: ' + regExpSource + ' => ' + this.source + ', ' + this.hasAnchor);
|
|
1069
|
-
}
|
|
1070
|
-
clone() {
|
|
1071
|
-
return new RegExpSource(this.source, this.ruleId);
|
|
1072
|
-
}
|
|
1073
|
-
setSource(newSource) {
|
|
1074
|
-
if (this.source === newSource) {
|
|
1075
|
-
return;
|
|
1076
|
-
}
|
|
1077
|
-
this.source = newSource;
|
|
1078
|
-
if (this.hasAnchor) {
|
|
1079
|
-
this._anchorCache = this._buildAnchorCache();
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
resolveBackReferences(lineText, captureIndices) {
|
|
1083
|
-
let capturedValues = captureIndices.map((capture) => {
|
|
1084
|
-
return lineText.substring(capture.start, capture.end);
|
|
1085
|
-
});
|
|
1086
|
-
BACK_REFERENCING_END.lastIndex = 0;
|
|
1087
|
-
return this.source.replace(BACK_REFERENCING_END, (match, g1) => {
|
|
1088
|
-
return escapeRegExpCharacters(capturedValues[parseInt(g1, 10)] || '');
|
|
1089
|
-
});
|
|
1090
|
-
}
|
|
1091
|
-
_buildAnchorCache() {
|
|
1092
|
-
let A0_G0_result = [];
|
|
1093
|
-
let A0_G1_result = [];
|
|
1094
|
-
let A1_G0_result = [];
|
|
1095
|
-
let A1_G1_result = [];
|
|
1096
|
-
let pos, len, ch, nextCh;
|
|
1097
|
-
for (pos = 0, len = this.source.length; pos < len; pos++) {
|
|
1098
|
-
ch = this.source.charAt(pos);
|
|
1099
|
-
A0_G0_result[pos] = ch;
|
|
1100
|
-
A0_G1_result[pos] = ch;
|
|
1101
|
-
A1_G0_result[pos] = ch;
|
|
1102
|
-
A1_G1_result[pos] = ch;
|
|
1103
|
-
if (ch === '\\') {
|
|
1104
|
-
if (pos + 1 < len) {
|
|
1105
|
-
nextCh = this.source.charAt(pos + 1);
|
|
1106
|
-
if (nextCh === 'A') {
|
|
1107
|
-
A0_G0_result[pos + 1] = '\uFFFF';
|
|
1108
|
-
A0_G1_result[pos + 1] = '\uFFFF';
|
|
1109
|
-
A1_G0_result[pos + 1] = 'A';
|
|
1110
|
-
A1_G1_result[pos + 1] = 'A';
|
|
1111
|
-
}
|
|
1112
|
-
else if (nextCh === 'G') {
|
|
1113
|
-
A0_G0_result[pos + 1] = '\uFFFF';
|
|
1114
|
-
A0_G1_result[pos + 1] = 'G';
|
|
1115
|
-
A1_G0_result[pos + 1] = '\uFFFF';
|
|
1116
|
-
A1_G1_result[pos + 1] = 'G';
|
|
1117
|
-
}
|
|
1118
|
-
else {
|
|
1119
|
-
A0_G0_result[pos + 1] = nextCh;
|
|
1120
|
-
A0_G1_result[pos + 1] = nextCh;
|
|
1121
|
-
A1_G0_result[pos + 1] = nextCh;
|
|
1122
|
-
A1_G1_result[pos + 1] = nextCh;
|
|
1123
|
-
}
|
|
1124
|
-
pos++;
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
return {
|
|
1129
|
-
A0_G0: A0_G0_result.join(''),
|
|
1130
|
-
A0_G1: A0_G1_result.join(''),
|
|
1131
|
-
A1_G0: A1_G0_result.join(''),
|
|
1132
|
-
A1_G1: A1_G1_result.join('')
|
|
1133
|
-
};
|
|
1134
|
-
}
|
|
1135
|
-
resolveAnchors(allowA, allowG) {
|
|
1136
|
-
if (!this.hasAnchor || !this._anchorCache) {
|
|
1137
|
-
return this.source;
|
|
1138
|
-
}
|
|
1139
|
-
if (allowA) {
|
|
1140
|
-
if (allowG) {
|
|
1141
|
-
return this._anchorCache.A1_G1;
|
|
1142
|
-
}
|
|
1143
|
-
else {
|
|
1144
|
-
return this._anchorCache.A1_G0;
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
|
-
else {
|
|
1148
|
-
if (allowG) {
|
|
1149
|
-
return this._anchorCache.A0_G1;
|
|
1150
|
-
}
|
|
1151
|
-
else {
|
|
1152
|
-
return this._anchorCache.A0_G0;
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
class RegExpSourceList {
|
|
1158
|
-
_items;
|
|
1159
|
-
_hasAnchors;
|
|
1160
|
-
_cached;
|
|
1161
|
-
_anchorCache;
|
|
1162
|
-
constructor() {
|
|
1163
|
-
this._items = [];
|
|
1164
|
-
this._hasAnchors = false;
|
|
1165
|
-
this._cached = null;
|
|
1166
|
-
this._anchorCache = {
|
|
1167
|
-
A0_G0: null,
|
|
1168
|
-
A0_G1: null,
|
|
1169
|
-
A1_G0: null,
|
|
1170
|
-
A1_G1: null
|
|
1171
|
-
};
|
|
1172
|
-
}
|
|
1173
|
-
dispose() {
|
|
1174
|
-
this._disposeCaches();
|
|
1175
|
-
}
|
|
1176
|
-
_disposeCaches() {
|
|
1177
|
-
if (this._cached) {
|
|
1178
|
-
this._cached.dispose();
|
|
1179
|
-
this._cached = null;
|
|
1180
|
-
}
|
|
1181
|
-
if (this._anchorCache.A0_G0) {
|
|
1182
|
-
this._anchorCache.A0_G0.dispose();
|
|
1183
|
-
this._anchorCache.A0_G0 = null;
|
|
1184
|
-
}
|
|
1185
|
-
if (this._anchorCache.A0_G1) {
|
|
1186
|
-
this._anchorCache.A0_G1.dispose();
|
|
1187
|
-
this._anchorCache.A0_G1 = null;
|
|
1188
|
-
}
|
|
1189
|
-
if (this._anchorCache.A1_G0) {
|
|
1190
|
-
this._anchorCache.A1_G0.dispose();
|
|
1191
|
-
this._anchorCache.A1_G0 = null;
|
|
1192
|
-
}
|
|
1193
|
-
if (this._anchorCache.A1_G1) {
|
|
1194
|
-
this._anchorCache.A1_G1.dispose();
|
|
1195
|
-
this._anchorCache.A1_G1 = null;
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
push(item) {
|
|
1199
|
-
this._items.push(item);
|
|
1200
|
-
this._hasAnchors = this._hasAnchors || item.hasAnchor;
|
|
1201
|
-
}
|
|
1202
|
-
unshift(item) {
|
|
1203
|
-
this._items.unshift(item);
|
|
1204
|
-
this._hasAnchors = this._hasAnchors || item.hasAnchor;
|
|
1205
|
-
}
|
|
1206
|
-
length() {
|
|
1207
|
-
return this._items.length;
|
|
1208
|
-
}
|
|
1209
|
-
setSource(index, newSource) {
|
|
1210
|
-
if (this._items[index].source !== newSource) {
|
|
1211
|
-
// bust the cache
|
|
1212
|
-
this._disposeCaches();
|
|
1213
|
-
this._items[index].setSource(newSource);
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
|
-
compile(onigLib) {
|
|
1217
|
-
if (!this._cached) {
|
|
1218
|
-
let regExps = this._items.map(e => e.source);
|
|
1219
|
-
this._cached = new CompiledRule(onigLib, regExps, this._items.map(e => e.ruleId));
|
|
1220
|
-
}
|
|
1221
|
-
return this._cached;
|
|
1222
|
-
}
|
|
1223
|
-
compileAG(onigLib, allowA, allowG) {
|
|
1224
|
-
if (!this._hasAnchors) {
|
|
1225
|
-
return this.compile(onigLib);
|
|
1226
|
-
}
|
|
1227
|
-
else {
|
|
1228
|
-
if (allowA) {
|
|
1229
|
-
if (allowG) {
|
|
1230
|
-
if (!this._anchorCache.A1_G1) {
|
|
1231
|
-
this._anchorCache.A1_G1 = this._resolveAnchors(onigLib, allowA, allowG);
|
|
1232
|
-
}
|
|
1233
|
-
return this._anchorCache.A1_G1;
|
|
1234
|
-
}
|
|
1235
|
-
else {
|
|
1236
|
-
if (!this._anchorCache.A1_G0) {
|
|
1237
|
-
this._anchorCache.A1_G0 = this._resolveAnchors(onigLib, allowA, allowG);
|
|
1238
|
-
}
|
|
1239
|
-
return this._anchorCache.A1_G0;
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
else {
|
|
1243
|
-
if (allowG) {
|
|
1244
|
-
if (!this._anchorCache.A0_G1) {
|
|
1245
|
-
this._anchorCache.A0_G1 = this._resolveAnchors(onigLib, allowA, allowG);
|
|
1246
|
-
}
|
|
1247
|
-
return this._anchorCache.A0_G1;
|
|
1248
|
-
}
|
|
1249
|
-
else {
|
|
1250
|
-
if (!this._anchorCache.A0_G0) {
|
|
1251
|
-
this._anchorCache.A0_G0 = this._resolveAnchors(onigLib, allowA, allowG);
|
|
1252
|
-
}
|
|
1253
|
-
return this._anchorCache.A0_G0;
|
|
1254
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1257
|
-
}
|
|
1258
|
-
_resolveAnchors(onigLib, allowA, allowG) {
|
|
1259
|
-
let regExps = this._items.map(e => e.resolveAnchors(allowA, allowG));
|
|
1260
|
-
return new CompiledRule(onigLib, regExps, this._items.map(e => e.ruleId));
|
|
1261
|
-
}
|
|
1262
|
-
}
|
|
1263
|
-
class CompiledRule {
|
|
1264
|
-
regExps;
|
|
1265
|
-
rules;
|
|
1266
|
-
scanner;
|
|
1267
|
-
constructor(onigLib, regExps, rules) {
|
|
1268
|
-
this.regExps = regExps;
|
|
1269
|
-
this.rules = rules;
|
|
1270
|
-
this.scanner = onigLib.createOnigScanner(regExps);
|
|
1271
|
-
}
|
|
1272
|
-
dispose() {
|
|
1273
|
-
if (typeof this.scanner.dispose === "function") {
|
|
1274
|
-
this.scanner.dispose();
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
toString() {
|
|
1278
|
-
const r = [];
|
|
1279
|
-
for (let i = 0, len = this.rules.length; i < len; i++) {
|
|
1280
|
-
r.push(" - " + this.rules[i] + ": " + this.regExps[i]);
|
|
1281
|
-
}
|
|
1282
|
-
return r.join("\n");
|
|
1283
|
-
}
|
|
1284
|
-
findNextMatchSync(string, startPosition, options) {
|
|
1285
|
-
const result = this.scanner.findNextMatchSync(string, startPosition, options);
|
|
1286
|
-
if (!result) {
|
|
1287
|
-
return null;
|
|
1288
|
-
}
|
|
1289
|
-
return {
|
|
1290
|
-
ruleId: this.rules[result.index],
|
|
1291
|
-
captureIndices: result.captureIndices,
|
|
1292
|
-
};
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
|
|
1296
|
-
/*---------------------------------------------------------
|
|
1297
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
1298
|
-
*--------------------------------------------------------*/
|
|
1299
|
-
class Theme {
|
|
1300
|
-
_colorMap;
|
|
1301
|
-
_defaults;
|
|
1302
|
-
_root;
|
|
1303
|
-
static createFromRawTheme(source, colorMap) {
|
|
1304
|
-
return this.createFromParsedTheme(parseTheme(source), colorMap);
|
|
1305
|
-
}
|
|
1306
|
-
static createFromParsedTheme(source, colorMap) {
|
|
1307
|
-
return resolveParsedThemeRules(source, colorMap);
|
|
1308
|
-
}
|
|
1309
|
-
_cachedMatchRoot = new CachedFn((scopeName) => this._root.match(scopeName));
|
|
1310
|
-
constructor(_colorMap, _defaults, _root) {
|
|
1311
|
-
this._colorMap = _colorMap;
|
|
1312
|
-
this._defaults = _defaults;
|
|
1313
|
-
this._root = _root;
|
|
1314
|
-
}
|
|
1315
|
-
getColorMap() {
|
|
1316
|
-
return this._colorMap.getColorMap();
|
|
1317
|
-
}
|
|
1318
|
-
getDefaults() {
|
|
1319
|
-
return this._defaults;
|
|
1320
|
-
}
|
|
1321
|
-
match(scopePath) {
|
|
1322
|
-
if (scopePath === null) {
|
|
1323
|
-
return this._defaults;
|
|
1324
|
-
}
|
|
1325
|
-
const scopeName = scopePath.scopeName;
|
|
1326
|
-
const matchingTrieElements = this._cachedMatchRoot.get(scopeName);
|
|
1327
|
-
const effectiveRule = matchingTrieElements.find((v) => _scopePathMatchesParentScopes(scopePath.parent, v.parentScopes));
|
|
1328
|
-
if (!effectiveRule) {
|
|
1329
|
-
return null;
|
|
1330
|
-
}
|
|
1331
|
-
return new StyleAttributes(effectiveRule.fontStyle, effectiveRule.foreground, effectiveRule.background);
|
|
1332
|
-
}
|
|
1333
|
-
}
|
|
1334
|
-
class ScopeStack {
|
|
1335
|
-
parent;
|
|
1336
|
-
scopeName;
|
|
1337
|
-
static push(path, scopeNames) {
|
|
1338
|
-
for (const name of scopeNames) {
|
|
1339
|
-
path = new ScopeStack(path, name);
|
|
1340
|
-
}
|
|
1341
|
-
return path;
|
|
1342
|
-
}
|
|
1343
|
-
static from(...segments) {
|
|
1344
|
-
let result = null;
|
|
1345
|
-
for (let i = 0; i < segments.length; i++) {
|
|
1346
|
-
result = new ScopeStack(result, segments[i]);
|
|
1347
|
-
}
|
|
1348
|
-
return result;
|
|
1349
|
-
}
|
|
1350
|
-
constructor(parent, scopeName) {
|
|
1351
|
-
this.parent = parent;
|
|
1352
|
-
this.scopeName = scopeName;
|
|
1353
|
-
}
|
|
1354
|
-
push(scopeName) {
|
|
1355
|
-
return new ScopeStack(this, scopeName);
|
|
1356
|
-
}
|
|
1357
|
-
getSegments() {
|
|
1358
|
-
let item = this;
|
|
1359
|
-
const result = [];
|
|
1360
|
-
while (item) {
|
|
1361
|
-
result.push(item.scopeName);
|
|
1362
|
-
item = item.parent;
|
|
1363
|
-
}
|
|
1364
|
-
result.reverse();
|
|
1365
|
-
return result;
|
|
1366
|
-
}
|
|
1367
|
-
toString() {
|
|
1368
|
-
return this.getSegments().join(' ');
|
|
1369
|
-
}
|
|
1370
|
-
extends(other) {
|
|
1371
|
-
if (this === other) {
|
|
1372
|
-
return true;
|
|
1373
|
-
}
|
|
1374
|
-
if (this.parent === null) {
|
|
1375
|
-
return false;
|
|
1376
|
-
}
|
|
1377
|
-
return this.parent.extends(other);
|
|
1378
|
-
}
|
|
1379
|
-
getExtensionIfDefined(base) {
|
|
1380
|
-
const result = [];
|
|
1381
|
-
let item = this;
|
|
1382
|
-
while (item && item !== base) {
|
|
1383
|
-
result.push(item.scopeName);
|
|
1384
|
-
item = item.parent;
|
|
1385
|
-
}
|
|
1386
|
-
return item === base ? result.reverse() : undefined;
|
|
1387
|
-
}
|
|
1388
|
-
}
|
|
1389
|
-
function _scopePathMatchesParentScopes(scopePath, parentScopes) {
|
|
1390
|
-
if (parentScopes === null) {
|
|
1391
|
-
return true;
|
|
1392
|
-
}
|
|
1393
|
-
let index = 0;
|
|
1394
|
-
let scopePattern = parentScopes[index];
|
|
1395
|
-
while (scopePath) {
|
|
1396
|
-
if (_matchesScope(scopePath.scopeName, scopePattern)) {
|
|
1397
|
-
index++;
|
|
1398
|
-
if (index === parentScopes.length) {
|
|
1399
|
-
return true;
|
|
1400
|
-
}
|
|
1401
|
-
scopePattern = parentScopes[index];
|
|
1402
|
-
}
|
|
1403
|
-
scopePath = scopePath.parent;
|
|
1404
|
-
}
|
|
1405
|
-
return false;
|
|
1406
|
-
}
|
|
1407
|
-
function _matchesScope(scopeName, scopePattern) {
|
|
1408
|
-
return scopePattern === scopeName || (scopeName.startsWith(scopePattern) && scopeName[scopePattern.length] === '.');
|
|
1409
|
-
}
|
|
1410
|
-
class StyleAttributes {
|
|
1411
|
-
fontStyle;
|
|
1412
|
-
foregroundId;
|
|
1413
|
-
backgroundId;
|
|
1414
|
-
constructor(fontStyle, foregroundId, backgroundId) {
|
|
1415
|
-
this.fontStyle = fontStyle;
|
|
1416
|
-
this.foregroundId = foregroundId;
|
|
1417
|
-
this.backgroundId = backgroundId;
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
/**
|
|
1421
|
-
* Parse a raw theme into rules.
|
|
1422
|
-
*/
|
|
1423
|
-
function parseTheme(source) {
|
|
1424
|
-
if (!source) {
|
|
1425
|
-
return [];
|
|
1426
|
-
}
|
|
1427
|
-
if (!source.settings || !Array.isArray(source.settings)) {
|
|
1428
|
-
return [];
|
|
1429
|
-
}
|
|
1430
|
-
let settings = source.settings;
|
|
1431
|
-
let result = [], resultLen = 0;
|
|
1432
|
-
for (let i = 0, len = settings.length; i < len; i++) {
|
|
1433
|
-
let entry = settings[i];
|
|
1434
|
-
if (!entry.settings) {
|
|
1435
|
-
continue;
|
|
1436
|
-
}
|
|
1437
|
-
let scopes;
|
|
1438
|
-
if (typeof entry.scope === 'string') {
|
|
1439
|
-
let _scope = entry.scope;
|
|
1440
|
-
// remove leading commas
|
|
1441
|
-
_scope = _scope.replace(/^[,]+/, '');
|
|
1442
|
-
// remove trailing commans
|
|
1443
|
-
_scope = _scope.replace(/[,]+$/, '');
|
|
1444
|
-
scopes = _scope.split(',');
|
|
1445
|
-
}
|
|
1446
|
-
else if (Array.isArray(entry.scope)) {
|
|
1447
|
-
scopes = entry.scope;
|
|
1448
|
-
}
|
|
1449
|
-
else {
|
|
1450
|
-
scopes = [''];
|
|
1451
|
-
}
|
|
1452
|
-
let fontStyle = -1 /* FontStyle.NotSet */;
|
|
1453
|
-
if (typeof entry.settings.fontStyle === 'string') {
|
|
1454
|
-
fontStyle = 0 /* FontStyle.None */;
|
|
1455
|
-
let segments = entry.settings.fontStyle.split(' ');
|
|
1456
|
-
for (let j = 0, lenJ = segments.length; j < lenJ; j++) {
|
|
1457
|
-
let segment = segments[j];
|
|
1458
|
-
switch (segment) {
|
|
1459
|
-
case 'italic':
|
|
1460
|
-
fontStyle = fontStyle | 1 /* FontStyle.Italic */;
|
|
1461
|
-
break;
|
|
1462
|
-
case 'bold':
|
|
1463
|
-
fontStyle = fontStyle | 2 /* FontStyle.Bold */;
|
|
1464
|
-
break;
|
|
1465
|
-
case 'underline':
|
|
1466
|
-
fontStyle = fontStyle | 4 /* FontStyle.Underline */;
|
|
1467
|
-
break;
|
|
1468
|
-
case 'strikethrough':
|
|
1469
|
-
fontStyle = fontStyle | 8 /* FontStyle.Strikethrough */;
|
|
1470
|
-
break;
|
|
1471
|
-
}
|
|
1472
|
-
}
|
|
1473
|
-
}
|
|
1474
|
-
let foreground = null;
|
|
1475
|
-
if (typeof entry.settings.foreground === 'string' && isValidHexColor(entry.settings.foreground)) {
|
|
1476
|
-
foreground = entry.settings.foreground;
|
|
1477
|
-
}
|
|
1478
|
-
let background = null;
|
|
1479
|
-
if (typeof entry.settings.background === 'string' && isValidHexColor(entry.settings.background)) {
|
|
1480
|
-
background = entry.settings.background;
|
|
1481
|
-
}
|
|
1482
|
-
for (let j = 0, lenJ = scopes.length; j < lenJ; j++) {
|
|
1483
|
-
let _scope = scopes[j].trim();
|
|
1484
|
-
let segments = _scope.split(' ');
|
|
1485
|
-
let scope = segments[segments.length - 1];
|
|
1486
|
-
let parentScopes = null;
|
|
1487
|
-
if (segments.length > 1) {
|
|
1488
|
-
parentScopes = segments.slice(0, segments.length - 1);
|
|
1489
|
-
parentScopes.reverse();
|
|
1490
|
-
}
|
|
1491
|
-
result[resultLen++] = new ParsedThemeRule(scope, parentScopes, i, fontStyle, foreground, background);
|
|
1492
|
-
}
|
|
1493
|
-
}
|
|
1494
|
-
return result;
|
|
1495
|
-
}
|
|
1496
|
-
class ParsedThemeRule {
|
|
1497
|
-
scope;
|
|
1498
|
-
parentScopes;
|
|
1499
|
-
index;
|
|
1500
|
-
fontStyle;
|
|
1501
|
-
foreground;
|
|
1502
|
-
background;
|
|
1503
|
-
constructor(scope, parentScopes, index, fontStyle, foreground, background) {
|
|
1504
|
-
this.scope = scope;
|
|
1505
|
-
this.parentScopes = parentScopes;
|
|
1506
|
-
this.index = index;
|
|
1507
|
-
this.fontStyle = fontStyle;
|
|
1508
|
-
this.foreground = foreground;
|
|
1509
|
-
this.background = background;
|
|
1510
|
-
}
|
|
1511
|
-
}
|
|
1512
|
-
/**
|
|
1513
|
-
* Resolve rules (i.e. inheritance).
|
|
1514
|
-
*/
|
|
1515
|
-
function resolveParsedThemeRules(parsedThemeRules, _colorMap) {
|
|
1516
|
-
// Sort rules lexicographically, and then by index if necessary
|
|
1517
|
-
parsedThemeRules.sort((a, b) => {
|
|
1518
|
-
let r = strcmp(a.scope, b.scope);
|
|
1519
|
-
if (r !== 0) {
|
|
1520
|
-
return r;
|
|
1521
|
-
}
|
|
1522
|
-
r = strArrCmp(a.parentScopes, b.parentScopes);
|
|
1523
|
-
if (r !== 0) {
|
|
1524
|
-
return r;
|
|
1525
|
-
}
|
|
1526
|
-
return a.index - b.index;
|
|
1527
|
-
});
|
|
1528
|
-
// Determine defaults
|
|
1529
|
-
let defaultFontStyle = 0 /* FontStyle.None */;
|
|
1530
|
-
let defaultForeground = '#000000';
|
|
1531
|
-
let defaultBackground = '#ffffff';
|
|
1532
|
-
while (parsedThemeRules.length >= 1 && parsedThemeRules[0].scope === '') {
|
|
1533
|
-
let incomingDefaults = parsedThemeRules.shift();
|
|
1534
|
-
if (incomingDefaults.fontStyle !== -1 /* FontStyle.NotSet */) {
|
|
1535
|
-
defaultFontStyle = incomingDefaults.fontStyle;
|
|
1536
|
-
}
|
|
1537
|
-
if (incomingDefaults.foreground !== null) {
|
|
1538
|
-
defaultForeground = incomingDefaults.foreground;
|
|
1539
|
-
}
|
|
1540
|
-
if (incomingDefaults.background !== null) {
|
|
1541
|
-
defaultBackground = incomingDefaults.background;
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
let colorMap = new ColorMap(_colorMap);
|
|
1545
|
-
let defaults = new StyleAttributes(defaultFontStyle, colorMap.getId(defaultForeground), colorMap.getId(defaultBackground));
|
|
1546
|
-
let root = new ThemeTrieElement(new ThemeTrieElementRule(0, null, -1 /* FontStyle.NotSet */, 0, 0), []);
|
|
1547
|
-
for (let i = 0, len = parsedThemeRules.length; i < len; i++) {
|
|
1548
|
-
let rule = parsedThemeRules[i];
|
|
1549
|
-
root.insert(0, rule.scope, rule.parentScopes, rule.fontStyle, colorMap.getId(rule.foreground), colorMap.getId(rule.background));
|
|
1550
|
-
}
|
|
1551
|
-
return new Theme(colorMap, defaults, root);
|
|
1552
|
-
}
|
|
1553
|
-
class ColorMap {
|
|
1554
|
-
_isFrozen;
|
|
1555
|
-
_lastColorId;
|
|
1556
|
-
_id2color;
|
|
1557
|
-
_color2id;
|
|
1558
|
-
constructor(_colorMap) {
|
|
1559
|
-
this._lastColorId = 0;
|
|
1560
|
-
this._id2color = [];
|
|
1561
|
-
this._color2id = Object.create(null);
|
|
1562
|
-
if (Array.isArray(_colorMap)) {
|
|
1563
|
-
this._isFrozen = true;
|
|
1564
|
-
for (let i = 0, len = _colorMap.length; i < len; i++) {
|
|
1565
|
-
this._color2id[_colorMap[i]] = i;
|
|
1566
|
-
this._id2color[i] = _colorMap[i];
|
|
1567
|
-
}
|
|
1568
|
-
}
|
|
1569
|
-
else {
|
|
1570
|
-
this._isFrozen = false;
|
|
1571
|
-
}
|
|
1572
|
-
}
|
|
1573
|
-
getId(color) {
|
|
1574
|
-
if (color === null) {
|
|
1575
|
-
return 0;
|
|
1576
|
-
}
|
|
1577
|
-
color = color.toUpperCase();
|
|
1578
|
-
let value = this._color2id[color];
|
|
1579
|
-
if (value) {
|
|
1580
|
-
return value;
|
|
1581
|
-
}
|
|
1582
|
-
if (this._isFrozen) {
|
|
1583
|
-
throw new Error(`Missing color in color map - ${color}`);
|
|
1584
|
-
}
|
|
1585
|
-
value = ++this._lastColorId;
|
|
1586
|
-
this._color2id[color] = value;
|
|
1587
|
-
this._id2color[value] = color;
|
|
1588
|
-
return value;
|
|
1589
|
-
}
|
|
1590
|
-
getColorMap() {
|
|
1591
|
-
return this._id2color.slice(0);
|
|
1592
|
-
}
|
|
1593
|
-
}
|
|
1594
|
-
class ThemeTrieElementRule {
|
|
1595
|
-
scopeDepth;
|
|
1596
|
-
parentScopes;
|
|
1597
|
-
fontStyle;
|
|
1598
|
-
foreground;
|
|
1599
|
-
background;
|
|
1600
|
-
constructor(scopeDepth, parentScopes, fontStyle, foreground, background) {
|
|
1601
|
-
this.scopeDepth = scopeDepth;
|
|
1602
|
-
this.parentScopes = parentScopes;
|
|
1603
|
-
this.fontStyle = fontStyle;
|
|
1604
|
-
this.foreground = foreground;
|
|
1605
|
-
this.background = background;
|
|
1606
|
-
}
|
|
1607
|
-
clone() {
|
|
1608
|
-
return new ThemeTrieElementRule(this.scopeDepth, this.parentScopes, this.fontStyle, this.foreground, this.background);
|
|
1609
|
-
}
|
|
1610
|
-
static cloneArr(arr) {
|
|
1611
|
-
let r = [];
|
|
1612
|
-
for (let i = 0, len = arr.length; i < len; i++) {
|
|
1613
|
-
r[i] = arr[i].clone();
|
|
1614
|
-
}
|
|
1615
|
-
return r;
|
|
1616
|
-
}
|
|
1617
|
-
acceptOverwrite(scopeDepth, fontStyle, foreground, background) {
|
|
1618
|
-
if (this.scopeDepth > scopeDepth) {
|
|
1619
|
-
console.log('how did this happen?');
|
|
1620
|
-
}
|
|
1621
|
-
else {
|
|
1622
|
-
this.scopeDepth = scopeDepth;
|
|
1623
|
-
}
|
|
1624
|
-
// console.log('TODO -> my depth: ' + this.scopeDepth + ', overwriting depth: ' + scopeDepth);
|
|
1625
|
-
if (fontStyle !== -1 /* FontStyle.NotSet */) {
|
|
1626
|
-
this.fontStyle = fontStyle;
|
|
1627
|
-
}
|
|
1628
|
-
if (foreground !== 0) {
|
|
1629
|
-
this.foreground = foreground;
|
|
1630
|
-
}
|
|
1631
|
-
if (background !== 0) {
|
|
1632
|
-
this.background = background;
|
|
1633
|
-
}
|
|
1634
|
-
}
|
|
1635
|
-
}
|
|
1636
|
-
class ThemeTrieElement {
|
|
1637
|
-
_mainRule;
|
|
1638
|
-
_children;
|
|
1639
|
-
_rulesWithParentScopes;
|
|
1640
|
-
constructor(_mainRule, rulesWithParentScopes = [], _children = {}) {
|
|
1641
|
-
this._mainRule = _mainRule;
|
|
1642
|
-
this._children = _children;
|
|
1643
|
-
this._rulesWithParentScopes = rulesWithParentScopes;
|
|
1644
|
-
}
|
|
1645
|
-
static _sortBySpecificity(arr) {
|
|
1646
|
-
if (arr.length === 1) {
|
|
1647
|
-
return arr;
|
|
1648
|
-
}
|
|
1649
|
-
arr.sort(this._cmpBySpecificity);
|
|
1650
|
-
return arr;
|
|
1651
|
-
}
|
|
1652
|
-
static _cmpBySpecificity(a, b) {
|
|
1653
|
-
if (a.scopeDepth === b.scopeDepth) {
|
|
1654
|
-
const aParentScopes = a.parentScopes;
|
|
1655
|
-
const bParentScopes = b.parentScopes;
|
|
1656
|
-
let aParentScopesLen = aParentScopes === null ? 0 : aParentScopes.length;
|
|
1657
|
-
let bParentScopesLen = bParentScopes === null ? 0 : bParentScopes.length;
|
|
1658
|
-
if (aParentScopesLen === bParentScopesLen) {
|
|
1659
|
-
for (let i = 0; i < aParentScopesLen; i++) {
|
|
1660
|
-
const aLen = aParentScopes[i].length;
|
|
1661
|
-
const bLen = bParentScopes[i].length;
|
|
1662
|
-
if (aLen !== bLen) {
|
|
1663
|
-
return bLen - aLen;
|
|
1664
|
-
}
|
|
1665
|
-
}
|
|
1666
|
-
}
|
|
1667
|
-
return bParentScopesLen - aParentScopesLen;
|
|
1668
|
-
}
|
|
1669
|
-
return b.scopeDepth - a.scopeDepth;
|
|
1670
|
-
}
|
|
1671
|
-
match(scope) {
|
|
1672
|
-
if (scope === '') {
|
|
1673
|
-
return ThemeTrieElement._sortBySpecificity([].concat(this._mainRule).concat(this._rulesWithParentScopes));
|
|
1674
|
-
}
|
|
1675
|
-
let dotIndex = scope.indexOf('.');
|
|
1676
|
-
let head;
|
|
1677
|
-
let tail;
|
|
1678
|
-
if (dotIndex === -1) {
|
|
1679
|
-
head = scope;
|
|
1680
|
-
tail = '';
|
|
1681
|
-
}
|
|
1682
|
-
else {
|
|
1683
|
-
head = scope.substring(0, dotIndex);
|
|
1684
|
-
tail = scope.substring(dotIndex + 1);
|
|
1685
|
-
}
|
|
1686
|
-
if (this._children.hasOwnProperty(head)) {
|
|
1687
|
-
return this._children[head].match(tail);
|
|
1688
|
-
}
|
|
1689
|
-
return ThemeTrieElement._sortBySpecificity([].concat(this._mainRule).concat(this._rulesWithParentScopes));
|
|
1690
|
-
}
|
|
1691
|
-
insert(scopeDepth, scope, parentScopes, fontStyle, foreground, background) {
|
|
1692
|
-
if (scope === '') {
|
|
1693
|
-
this._doInsertHere(scopeDepth, parentScopes, fontStyle, foreground, background);
|
|
1694
|
-
return;
|
|
1695
|
-
}
|
|
1696
|
-
let dotIndex = scope.indexOf('.');
|
|
1697
|
-
let head;
|
|
1698
|
-
let tail;
|
|
1699
|
-
if (dotIndex === -1) {
|
|
1700
|
-
head = scope;
|
|
1701
|
-
tail = '';
|
|
1702
|
-
}
|
|
1703
|
-
else {
|
|
1704
|
-
head = scope.substring(0, dotIndex);
|
|
1705
|
-
tail = scope.substring(dotIndex + 1);
|
|
1706
|
-
}
|
|
1707
|
-
let child;
|
|
1708
|
-
if (this._children.hasOwnProperty(head)) {
|
|
1709
|
-
child = this._children[head];
|
|
1710
|
-
}
|
|
1711
|
-
else {
|
|
1712
|
-
child = new ThemeTrieElement(this._mainRule.clone(), ThemeTrieElementRule.cloneArr(this._rulesWithParentScopes));
|
|
1713
|
-
this._children[head] = child;
|
|
1714
|
-
}
|
|
1715
|
-
child.insert(scopeDepth + 1, tail, parentScopes, fontStyle, foreground, background);
|
|
1716
|
-
}
|
|
1717
|
-
_doInsertHere(scopeDepth, parentScopes, fontStyle, foreground, background) {
|
|
1718
|
-
if (parentScopes === null) {
|
|
1719
|
-
// Merge into the main rule
|
|
1720
|
-
this._mainRule.acceptOverwrite(scopeDepth, fontStyle, foreground, background);
|
|
1721
|
-
return;
|
|
1722
|
-
}
|
|
1723
|
-
// Try to merge into existing rule
|
|
1724
|
-
for (let i = 0, len = this._rulesWithParentScopes.length; i < len; i++) {
|
|
1725
|
-
let rule = this._rulesWithParentScopes[i];
|
|
1726
|
-
if (strArrCmp(rule.parentScopes, parentScopes) === 0) {
|
|
1727
|
-
// bingo! => we get to merge this into an existing one
|
|
1728
|
-
rule.acceptOverwrite(scopeDepth, fontStyle, foreground, background);
|
|
1729
|
-
return;
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
// Must add a new rule
|
|
1733
|
-
// Inherit from main rule
|
|
1734
|
-
if (fontStyle === -1 /* FontStyle.NotSet */) {
|
|
1735
|
-
fontStyle = this._mainRule.fontStyle;
|
|
1736
|
-
}
|
|
1737
|
-
if (foreground === 0) {
|
|
1738
|
-
foreground = this._mainRule.foreground;
|
|
1739
|
-
}
|
|
1740
|
-
if (background === 0) {
|
|
1741
|
-
background = this._mainRule.background;
|
|
1742
|
-
}
|
|
1743
|
-
this._rulesWithParentScopes.push(new ThemeTrieElementRule(scopeDepth, parentScopes, fontStyle, foreground, background));
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
|
|
1747
|
-
/*---------------------------------------------------------
|
|
1748
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
1749
|
-
*--------------------------------------------------------*/
|
|
1750
|
-
class BasicScopeAttributes {
|
|
1751
|
-
languageId;
|
|
1752
|
-
tokenType;
|
|
1753
|
-
constructor(languageId, tokenType) {
|
|
1754
|
-
this.languageId = languageId;
|
|
1755
|
-
this.tokenType = tokenType;
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
class BasicScopeAttributesProvider {
|
|
1759
|
-
_defaultAttributes;
|
|
1760
|
-
_embeddedLanguagesMatcher;
|
|
1761
|
-
constructor(initialLanguageId, embeddedLanguages) {
|
|
1762
|
-
this._defaultAttributes = new BasicScopeAttributes(initialLanguageId, 8 /* OptionalStandardTokenType.NotSet */);
|
|
1763
|
-
this._embeddedLanguagesMatcher = new ScopeMatcher(Object.entries(embeddedLanguages || {}));
|
|
1764
|
-
}
|
|
1765
|
-
getDefaultAttributes() {
|
|
1766
|
-
return this._defaultAttributes;
|
|
1767
|
-
}
|
|
1768
|
-
getBasicScopeAttributes(scopeName) {
|
|
1769
|
-
if (scopeName === null) {
|
|
1770
|
-
return BasicScopeAttributesProvider._NULL_SCOPE_METADATA;
|
|
1771
|
-
}
|
|
1772
|
-
return this._getBasicScopeAttributes.get(scopeName);
|
|
1773
|
-
}
|
|
1774
|
-
static _NULL_SCOPE_METADATA = new BasicScopeAttributes(0, 0);
|
|
1775
|
-
_getBasicScopeAttributes = new CachedFn((scopeName) => {
|
|
1776
|
-
const languageId = this._scopeToLanguage(scopeName);
|
|
1777
|
-
const standardTokenType = this._toStandardTokenType(scopeName);
|
|
1778
|
-
return new BasicScopeAttributes(languageId, standardTokenType);
|
|
1779
|
-
});
|
|
1780
|
-
/**
|
|
1781
|
-
* Given a produced TM scope, return the language that token describes or null if unknown.
|
|
1782
|
-
* e.g. source.html => html, source.css.embedded.html => css, punctuation.definition.tag.html => null
|
|
1783
|
-
*/
|
|
1784
|
-
_scopeToLanguage(scope) {
|
|
1785
|
-
return this._embeddedLanguagesMatcher.match(scope) || 0;
|
|
1786
|
-
}
|
|
1787
|
-
_toStandardTokenType(scopeName) {
|
|
1788
|
-
const m = scopeName.match(BasicScopeAttributesProvider.STANDARD_TOKEN_TYPE_REGEXP);
|
|
1789
|
-
if (!m) {
|
|
1790
|
-
return 8 /* OptionalStandardTokenType.NotSet */;
|
|
1791
|
-
}
|
|
1792
|
-
switch (m[1]) {
|
|
1793
|
-
case "comment":
|
|
1794
|
-
return 1 /* OptionalStandardTokenType.Comment */;
|
|
1795
|
-
case "string":
|
|
1796
|
-
return 2 /* OptionalStandardTokenType.String */;
|
|
1797
|
-
case "regex":
|
|
1798
|
-
return 3 /* OptionalStandardTokenType.RegEx */;
|
|
1799
|
-
case "meta.embedded":
|
|
1800
|
-
return 0 /* OptionalStandardTokenType.Other */;
|
|
1801
|
-
}
|
|
1802
|
-
throw new Error("Unexpected match for standard token type!");
|
|
1803
|
-
}
|
|
1804
|
-
static STANDARD_TOKEN_TYPE_REGEXP = /\b(comment|string|regex|meta\.embedded)\b/;
|
|
1805
|
-
}
|
|
1806
|
-
class ScopeMatcher {
|
|
1807
|
-
values;
|
|
1808
|
-
scopesRegExp;
|
|
1809
|
-
constructor(values) {
|
|
1810
|
-
if (values.length === 0) {
|
|
1811
|
-
this.values = null;
|
|
1812
|
-
this.scopesRegExp = null;
|
|
1813
|
-
}
|
|
1814
|
-
else {
|
|
1815
|
-
this.values = new Map(values);
|
|
1816
|
-
// create the regex
|
|
1817
|
-
const escapedScopes = values.map(([scopeName, value]) => escapeRegExpCharacters(scopeName));
|
|
1818
|
-
escapedScopes.sort();
|
|
1819
|
-
escapedScopes.reverse(); // Longest scope first
|
|
1820
|
-
this.scopesRegExp = new RegExp(`^((${escapedScopes.join(")|(")}))($|\\.)`, "");
|
|
1821
|
-
}
|
|
1822
|
-
}
|
|
1823
|
-
match(scope) {
|
|
1824
|
-
if (!this.scopesRegExp) {
|
|
1825
|
-
return undefined;
|
|
1826
|
-
}
|
|
1827
|
-
const m = scope.match(this.scopesRegExp);
|
|
1828
|
-
if (!m) {
|
|
1829
|
-
// no scopes matched
|
|
1830
|
-
return undefined;
|
|
1831
|
-
}
|
|
1832
|
-
return this.values.get(m[1]);
|
|
1833
|
-
}
|
|
1834
|
-
}
|
|
1835
|
-
|
|
1836
|
-
/*---------------------------------------------------------
|
|
1837
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
1838
|
-
*--------------------------------------------------------*/
|
|
1839
|
-
class TokenizeStringResult {
|
|
1840
|
-
stack;
|
|
1841
|
-
stoppedEarly;
|
|
1842
|
-
constructor(stack, stoppedEarly) {
|
|
1843
|
-
this.stack = stack;
|
|
1844
|
-
this.stoppedEarly = stoppedEarly;
|
|
1845
|
-
}
|
|
1846
|
-
}
|
|
1847
|
-
/**
|
|
1848
|
-
* Tokenize a string
|
|
1849
|
-
* @param grammar
|
|
1850
|
-
* @param lineText
|
|
1851
|
-
* @param isFirstLine
|
|
1852
|
-
* @param linePos
|
|
1853
|
-
* @param stack
|
|
1854
|
-
* @param lineTokens
|
|
1855
|
-
* @param checkWhileConditions
|
|
1856
|
-
* @param timeLimit Use `0` to indicate no time limit
|
|
1857
|
-
* @returns the StackElement or StackElement.TIME_LIMIT_REACHED if the time limit has been reached
|
|
1858
|
-
*/
|
|
1859
|
-
function _tokenizeString(grammar, lineText, isFirstLine, linePos, stack, lineTokens, checkWhileConditions, timeLimit) {
|
|
1860
|
-
const lineLength = lineText.content.length;
|
|
1861
|
-
let STOP = false;
|
|
1862
|
-
let anchorPosition = -1;
|
|
1863
|
-
if (checkWhileConditions) {
|
|
1864
|
-
const whileCheckResult = _checkWhileConditions(grammar, lineText, isFirstLine, linePos, stack, lineTokens);
|
|
1865
|
-
stack = whileCheckResult.stack;
|
|
1866
|
-
linePos = whileCheckResult.linePos;
|
|
1867
|
-
isFirstLine = whileCheckResult.isFirstLine;
|
|
1868
|
-
anchorPosition = whileCheckResult.anchorPosition;
|
|
1869
|
-
}
|
|
1870
|
-
const startTime = Date.now();
|
|
1871
|
-
while (!STOP) {
|
|
1872
|
-
if (timeLimit !== 0) {
|
|
1873
|
-
const elapsedTime = Date.now() - startTime;
|
|
1874
|
-
if (elapsedTime > timeLimit) {
|
|
1875
|
-
return new TokenizeStringResult(stack, true);
|
|
1876
|
-
}
|
|
1877
|
-
}
|
|
1878
|
-
scanNext(); // potentially modifies linePos && anchorPosition
|
|
1879
|
-
}
|
|
1880
|
-
return new TokenizeStringResult(stack, false);
|
|
1881
|
-
function scanNext() {
|
|
1882
|
-
const r = matchRuleOrInjections(grammar, lineText, isFirstLine, linePos, stack, anchorPosition);
|
|
1883
|
-
if (!r) {
|
|
1884
|
-
// No match
|
|
1885
|
-
lineTokens.produce(stack, lineLength);
|
|
1886
|
-
STOP = true;
|
|
1887
|
-
return;
|
|
1888
|
-
}
|
|
1889
|
-
const captureIndices = r.captureIndices;
|
|
1890
|
-
const matchedRuleId = r.matchedRuleId;
|
|
1891
|
-
const hasAdvanced = captureIndices && captureIndices.length > 0
|
|
1892
|
-
? captureIndices[0].end > linePos
|
|
1893
|
-
: false;
|
|
1894
|
-
if (matchedRuleId === endRuleId) {
|
|
1895
|
-
// We matched the `end` for this rule => pop it
|
|
1896
|
-
const poppedRule = stack.getRule(grammar);
|
|
1897
|
-
lineTokens.produce(stack, captureIndices[0].start);
|
|
1898
|
-
stack = stack.withContentNameScopesList(stack.nameScopesList);
|
|
1899
|
-
handleCaptures(grammar, lineText, isFirstLine, stack, lineTokens, poppedRule.endCaptures, captureIndices);
|
|
1900
|
-
lineTokens.produce(stack, captureIndices[0].end);
|
|
1901
|
-
// pop
|
|
1902
|
-
const popped = stack;
|
|
1903
|
-
stack = stack.parent;
|
|
1904
|
-
anchorPosition = popped.getAnchorPos();
|
|
1905
|
-
if (!hasAdvanced && popped.getEnterPos() === linePos) {
|
|
1906
|
-
// See https://github.com/Microsoft/vscode-textmate/issues/12
|
|
1907
|
-
// Let's assume this was a mistake by the grammar author and the intent was to continue in this state
|
|
1908
|
-
stack = popped;
|
|
1909
|
-
lineTokens.produce(stack, lineLength);
|
|
1910
|
-
STOP = true;
|
|
1911
|
-
return;
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
else {
|
|
1915
|
-
// We matched a rule!
|
|
1916
|
-
const _rule = grammar.getRule(matchedRuleId);
|
|
1917
|
-
lineTokens.produce(stack, captureIndices[0].start);
|
|
1918
|
-
const beforePush = stack;
|
|
1919
|
-
// push it on the stack rule
|
|
1920
|
-
const scopeName = _rule.getName(lineText.content, captureIndices);
|
|
1921
|
-
const nameScopesList = stack.contentNameScopesList.pushAttributed(scopeName, grammar);
|
|
1922
|
-
stack = stack.push(matchedRuleId, linePos, anchorPosition, captureIndices[0].end === lineLength, null, nameScopesList, nameScopesList);
|
|
1923
|
-
if (_rule instanceof BeginEndRule) {
|
|
1924
|
-
const pushedRule = _rule;
|
|
1925
|
-
handleCaptures(grammar, lineText, isFirstLine, stack, lineTokens, pushedRule.beginCaptures, captureIndices);
|
|
1926
|
-
lineTokens.produce(stack, captureIndices[0].end);
|
|
1927
|
-
anchorPosition = captureIndices[0].end;
|
|
1928
|
-
const contentName = pushedRule.getContentName(lineText.content, captureIndices);
|
|
1929
|
-
const contentNameScopesList = nameScopesList.pushAttributed(contentName, grammar);
|
|
1930
|
-
stack = stack.withContentNameScopesList(contentNameScopesList);
|
|
1931
|
-
if (pushedRule.endHasBackReferences) {
|
|
1932
|
-
stack = stack.withEndRule(pushedRule.getEndWithResolvedBackReferences(lineText.content, captureIndices));
|
|
1933
|
-
}
|
|
1934
|
-
if (!hasAdvanced && beforePush.hasSameRuleAs(stack)) {
|
|
1935
|
-
stack = stack.pop();
|
|
1936
|
-
lineTokens.produce(stack, lineLength);
|
|
1937
|
-
STOP = true;
|
|
1938
|
-
return;
|
|
1939
|
-
}
|
|
1940
|
-
}
|
|
1941
|
-
else if (_rule instanceof BeginWhileRule) {
|
|
1942
|
-
const pushedRule = _rule;
|
|
1943
|
-
handleCaptures(grammar, lineText, isFirstLine, stack, lineTokens, pushedRule.beginCaptures, captureIndices);
|
|
1944
|
-
lineTokens.produce(stack, captureIndices[0].end);
|
|
1945
|
-
anchorPosition = captureIndices[0].end;
|
|
1946
|
-
const contentName = pushedRule.getContentName(lineText.content, captureIndices);
|
|
1947
|
-
const contentNameScopesList = nameScopesList.pushAttributed(contentName, grammar);
|
|
1948
|
-
stack = stack.withContentNameScopesList(contentNameScopesList);
|
|
1949
|
-
if (pushedRule.whileHasBackReferences) {
|
|
1950
|
-
stack = stack.withEndRule(pushedRule.getWhileWithResolvedBackReferences(lineText.content, captureIndices));
|
|
1951
|
-
}
|
|
1952
|
-
if (!hasAdvanced && beforePush.hasSameRuleAs(stack)) {
|
|
1953
|
-
stack = stack.pop();
|
|
1954
|
-
lineTokens.produce(stack, lineLength);
|
|
1955
|
-
STOP = true;
|
|
1956
|
-
return;
|
|
1957
|
-
}
|
|
1958
|
-
}
|
|
1959
|
-
else {
|
|
1960
|
-
const matchingRule = _rule;
|
|
1961
|
-
handleCaptures(grammar, lineText, isFirstLine, stack, lineTokens, matchingRule.captures, captureIndices);
|
|
1962
|
-
lineTokens.produce(stack, captureIndices[0].end);
|
|
1963
|
-
// pop rule immediately since it is a MatchRule
|
|
1964
|
-
stack = stack.pop();
|
|
1965
|
-
if (!hasAdvanced) {
|
|
1966
|
-
stack = stack.safePop();
|
|
1967
|
-
lineTokens.produce(stack, lineLength);
|
|
1968
|
-
STOP = true;
|
|
1969
|
-
return;
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
}
|
|
1973
|
-
if (captureIndices[0].end > linePos) {
|
|
1974
|
-
// Advance stream
|
|
1975
|
-
linePos = captureIndices[0].end;
|
|
1976
|
-
isFirstLine = false;
|
|
1977
|
-
}
|
|
1978
|
-
}
|
|
1979
|
-
}
|
|
1980
|
-
/**
|
|
1981
|
-
* Walk the stack from bottom to top, and check each while condition in this order.
|
|
1982
|
-
* If any fails, cut off the entire stack above the failed while condition. While conditions
|
|
1983
|
-
* may also advance the linePosition.
|
|
1984
|
-
*/
|
|
1985
|
-
function _checkWhileConditions(grammar, lineText, isFirstLine, linePos, stack, lineTokens) {
|
|
1986
|
-
let anchorPosition = (stack.beginRuleCapturedEOL ? 0 : -1);
|
|
1987
|
-
const whileRules = [];
|
|
1988
|
-
for (let node = stack; node; node = node.pop()) {
|
|
1989
|
-
const nodeRule = node.getRule(grammar);
|
|
1990
|
-
if (nodeRule instanceof BeginWhileRule) {
|
|
1991
|
-
whileRules.push({
|
|
1992
|
-
rule: nodeRule,
|
|
1993
|
-
stack: node
|
|
1994
|
-
});
|
|
1995
|
-
}
|
|
1996
|
-
}
|
|
1997
|
-
for (let whileRule = whileRules.pop(); whileRule; whileRule = whileRules.pop()) {
|
|
1998
|
-
const { ruleScanner, findOptions } = prepareRuleWhileSearch(whileRule.rule, grammar, whileRule.stack.endRule, isFirstLine, linePos === anchorPosition);
|
|
1999
|
-
const r = ruleScanner.findNextMatchSync(lineText, linePos, findOptions);
|
|
2000
|
-
if (r) {
|
|
2001
|
-
const matchedRuleId = r.ruleId;
|
|
2002
|
-
if (matchedRuleId !== whileRuleId) {
|
|
2003
|
-
// we shouldn't end up here
|
|
2004
|
-
stack = whileRule.stack.pop();
|
|
2005
|
-
break;
|
|
2006
|
-
}
|
|
2007
|
-
if (r.captureIndices && r.captureIndices.length) {
|
|
2008
|
-
lineTokens.produce(whileRule.stack, r.captureIndices[0].start);
|
|
2009
|
-
handleCaptures(grammar, lineText, isFirstLine, whileRule.stack, lineTokens, whileRule.rule.whileCaptures, r.captureIndices);
|
|
2010
|
-
lineTokens.produce(whileRule.stack, r.captureIndices[0].end);
|
|
2011
|
-
anchorPosition = r.captureIndices[0].end;
|
|
2012
|
-
if (r.captureIndices[0].end > linePos) {
|
|
2013
|
-
linePos = r.captureIndices[0].end;
|
|
2014
|
-
isFirstLine = false;
|
|
2015
|
-
}
|
|
2016
|
-
}
|
|
2017
|
-
}
|
|
2018
|
-
else {
|
|
2019
|
-
stack = whileRule.stack.pop();
|
|
2020
|
-
break;
|
|
2021
|
-
}
|
|
2022
|
-
}
|
|
2023
|
-
return { stack: stack, linePos: linePos, anchorPosition: anchorPosition, isFirstLine: isFirstLine };
|
|
2024
|
-
}
|
|
2025
|
-
function matchRuleOrInjections(grammar, lineText, isFirstLine, linePos, stack, anchorPosition) {
|
|
2026
|
-
// Look for normal grammar rule
|
|
2027
|
-
const matchResult = matchRule(grammar, lineText, isFirstLine, linePos, stack, anchorPosition);
|
|
2028
|
-
// Look for injected rules
|
|
2029
|
-
const injections = grammar.getInjections();
|
|
2030
|
-
if (injections.length === 0) {
|
|
2031
|
-
// No injections whatsoever => early return
|
|
2032
|
-
return matchResult;
|
|
2033
|
-
}
|
|
2034
|
-
const injectionResult = matchInjections(injections, grammar, lineText, isFirstLine, linePos, stack, anchorPosition);
|
|
2035
|
-
if (!injectionResult) {
|
|
2036
|
-
// No injections matched => early return
|
|
2037
|
-
return matchResult;
|
|
2038
|
-
}
|
|
2039
|
-
if (!matchResult) {
|
|
2040
|
-
// Only injections matched => early return
|
|
2041
|
-
return injectionResult;
|
|
2042
|
-
}
|
|
2043
|
-
// Decide if `matchResult` or `injectionResult` should win
|
|
2044
|
-
const matchResultScore = matchResult.captureIndices[0].start;
|
|
2045
|
-
const injectionResultScore = injectionResult.captureIndices[0].start;
|
|
2046
|
-
if (injectionResultScore < matchResultScore || (injectionResult.priorityMatch && injectionResultScore === matchResultScore)) {
|
|
2047
|
-
// injection won!
|
|
2048
|
-
return injectionResult;
|
|
2049
|
-
}
|
|
2050
|
-
return matchResult;
|
|
2051
|
-
}
|
|
2052
|
-
function matchRule(grammar, lineText, isFirstLine, linePos, stack, anchorPosition) {
|
|
2053
|
-
const rule = stack.getRule(grammar);
|
|
2054
|
-
const { ruleScanner, findOptions } = prepareRuleSearch(rule, grammar, stack.endRule, isFirstLine, linePos === anchorPosition);
|
|
2055
|
-
const r = ruleScanner.findNextMatchSync(lineText, linePos, findOptions);
|
|
2056
|
-
if (r) {
|
|
2057
|
-
return {
|
|
2058
|
-
captureIndices: r.captureIndices,
|
|
2059
|
-
matchedRuleId: r.ruleId
|
|
2060
|
-
};
|
|
2061
|
-
}
|
|
2062
|
-
return null;
|
|
2063
|
-
}
|
|
2064
|
-
function matchInjections(injections, grammar, lineText, isFirstLine, linePos, stack, anchorPosition) {
|
|
2065
|
-
// The lower the better
|
|
2066
|
-
let bestMatchRating = Number.MAX_VALUE;
|
|
2067
|
-
let bestMatchCaptureIndices = null;
|
|
2068
|
-
let bestMatchRuleId;
|
|
2069
|
-
let bestMatchResultPriority = 0;
|
|
2070
|
-
const scopes = stack.contentNameScopesList.getScopeNames();
|
|
2071
|
-
for (let i = 0, len = injections.length; i < len; i++) {
|
|
2072
|
-
const injection = injections[i];
|
|
2073
|
-
if (!injection.matcher(scopes)) {
|
|
2074
|
-
// injection selector doesn't match stack
|
|
2075
|
-
continue;
|
|
2076
|
-
}
|
|
2077
|
-
const rule = grammar.getRule(injection.ruleId);
|
|
2078
|
-
const { ruleScanner, findOptions } = prepareRuleSearch(rule, grammar, null, isFirstLine, linePos === anchorPosition);
|
|
2079
|
-
const matchResult = ruleScanner.findNextMatchSync(lineText, linePos, findOptions);
|
|
2080
|
-
if (!matchResult) {
|
|
2081
|
-
continue;
|
|
2082
|
-
}
|
|
2083
|
-
const matchRating = matchResult.captureIndices[0].start;
|
|
2084
|
-
if (matchRating >= bestMatchRating) {
|
|
2085
|
-
// Injections are sorted by priority, so the previous injection had a better or equal priority
|
|
2086
|
-
continue;
|
|
2087
|
-
}
|
|
2088
|
-
bestMatchRating = matchRating;
|
|
2089
|
-
bestMatchCaptureIndices = matchResult.captureIndices;
|
|
2090
|
-
bestMatchRuleId = matchResult.ruleId;
|
|
2091
|
-
bestMatchResultPriority = injection.priority;
|
|
2092
|
-
if (bestMatchRating === linePos) {
|
|
2093
|
-
// No more need to look at the rest of the injections.
|
|
2094
|
-
break;
|
|
2095
|
-
}
|
|
2096
|
-
}
|
|
2097
|
-
if (bestMatchCaptureIndices) {
|
|
2098
|
-
return {
|
|
2099
|
-
priorityMatch: bestMatchResultPriority === -1,
|
|
2100
|
-
captureIndices: bestMatchCaptureIndices,
|
|
2101
|
-
matchedRuleId: bestMatchRuleId
|
|
2102
|
-
};
|
|
2103
|
-
}
|
|
2104
|
-
return null;
|
|
2105
|
-
}
|
|
2106
|
-
function prepareRuleSearch(rule, grammar, endRegexSource, allowA, allowG) {
|
|
2107
|
-
const ruleScanner = rule.compileAG(grammar, endRegexSource, allowA, allowG);
|
|
2108
|
-
return { ruleScanner, findOptions: 0 /* FindOption.None */ };
|
|
2109
|
-
}
|
|
2110
|
-
function prepareRuleWhileSearch(rule, grammar, endRegexSource, allowA, allowG) {
|
|
2111
|
-
const ruleScanner = rule.compileWhileAG(grammar, endRegexSource, allowA, allowG);
|
|
2112
|
-
return { ruleScanner, findOptions: 0 /* FindOption.None */ };
|
|
2113
|
-
}
|
|
2114
|
-
function handleCaptures(grammar, lineText, isFirstLine, stack, lineTokens, captures, captureIndices) {
|
|
2115
|
-
if (captures.length === 0) {
|
|
2116
|
-
return;
|
|
2117
|
-
}
|
|
2118
|
-
const lineTextContent = lineText.content;
|
|
2119
|
-
const len = Math.min(captures.length, captureIndices.length);
|
|
2120
|
-
const localStack = [];
|
|
2121
|
-
const maxEnd = captureIndices[0].end;
|
|
2122
|
-
for (let i = 0; i < len; i++) {
|
|
2123
|
-
const captureRule = captures[i];
|
|
2124
|
-
if (captureRule === null) {
|
|
2125
|
-
// Not interested
|
|
2126
|
-
continue;
|
|
2127
|
-
}
|
|
2128
|
-
const captureIndex = captureIndices[i];
|
|
2129
|
-
if (captureIndex.length === 0) {
|
|
2130
|
-
// Nothing really captured
|
|
2131
|
-
continue;
|
|
2132
|
-
}
|
|
2133
|
-
if (captureIndex.start > maxEnd) {
|
|
2134
|
-
// Capture going beyond consumed string
|
|
2135
|
-
break;
|
|
2136
|
-
}
|
|
2137
|
-
// pop captures while needed
|
|
2138
|
-
while (localStack.length > 0 && localStack[localStack.length - 1].endPos <= captureIndex.start) {
|
|
2139
|
-
// pop!
|
|
2140
|
-
lineTokens.produceFromScopes(localStack[localStack.length - 1].scopes, localStack[localStack.length - 1].endPos);
|
|
2141
|
-
localStack.pop();
|
|
2142
|
-
}
|
|
2143
|
-
if (localStack.length > 0) {
|
|
2144
|
-
lineTokens.produceFromScopes(localStack[localStack.length - 1].scopes, captureIndex.start);
|
|
2145
|
-
}
|
|
2146
|
-
else {
|
|
2147
|
-
lineTokens.produce(stack, captureIndex.start);
|
|
2148
|
-
}
|
|
2149
|
-
if (captureRule.retokenizeCapturedWithRuleId) {
|
|
2150
|
-
// the capture requires additional matching
|
|
2151
|
-
const scopeName = captureRule.getName(lineTextContent, captureIndices);
|
|
2152
|
-
const nameScopesList = stack.contentNameScopesList.pushAttributed(scopeName, grammar);
|
|
2153
|
-
const contentName = captureRule.getContentName(lineTextContent, captureIndices);
|
|
2154
|
-
const contentNameScopesList = nameScopesList.pushAttributed(contentName, grammar);
|
|
2155
|
-
const stackClone = stack.push(captureRule.retokenizeCapturedWithRuleId, captureIndex.start, -1, false, null, nameScopesList, contentNameScopesList);
|
|
2156
|
-
const onigSubStr = grammar.createOnigString(lineTextContent.substring(0, captureIndex.end));
|
|
2157
|
-
_tokenizeString(grammar, onigSubStr, (isFirstLine && captureIndex.start === 0), captureIndex.start, stackClone, lineTokens, false, /* no time limit */ 0);
|
|
2158
|
-
disposeOnigString(onigSubStr);
|
|
2159
|
-
continue;
|
|
2160
|
-
}
|
|
2161
|
-
const captureRuleScopeName = captureRule.getName(lineTextContent, captureIndices);
|
|
2162
|
-
if (captureRuleScopeName !== null) {
|
|
2163
|
-
// push
|
|
2164
|
-
const base = localStack.length > 0 ? localStack[localStack.length - 1].scopes : stack.contentNameScopesList;
|
|
2165
|
-
const captureRuleScopesList = base.pushAttributed(captureRuleScopeName, grammar);
|
|
2166
|
-
localStack.push(new LocalStackElement(captureRuleScopesList, captureIndex.end));
|
|
2167
|
-
}
|
|
2168
|
-
}
|
|
2169
|
-
while (localStack.length > 0) {
|
|
2170
|
-
// pop!
|
|
2171
|
-
lineTokens.produceFromScopes(localStack[localStack.length - 1].scopes, localStack[localStack.length - 1].endPos);
|
|
2172
|
-
localStack.pop();
|
|
2173
|
-
}
|
|
2174
|
-
}
|
|
2175
|
-
class LocalStackElement {
|
|
2176
|
-
scopes;
|
|
2177
|
-
endPos;
|
|
2178
|
-
constructor(scopes, endPos) {
|
|
2179
|
-
this.scopes = scopes;
|
|
2180
|
-
this.endPos = endPos;
|
|
2181
|
-
}
|
|
2182
|
-
}
|
|
2183
|
-
|
|
2184
|
-
/*---------------------------------------------------------
|
|
2185
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
2186
|
-
*--------------------------------------------------------*/
|
|
2187
|
-
function createGrammar(scopeName, grammar, initialLanguage, embeddedLanguages, tokenTypes, balancedBracketSelectors, grammarRepository, onigLib) {
|
|
2188
|
-
return new Grammar(scopeName, grammar, initialLanguage, embeddedLanguages, tokenTypes, balancedBracketSelectors, grammarRepository, onigLib); //TODO
|
|
2189
|
-
}
|
|
2190
|
-
function collectInjections(result, selector, rule, ruleFactoryHelper, grammar) {
|
|
2191
|
-
const matchers = createMatchers(selector, nameMatcher);
|
|
2192
|
-
const ruleId = RuleFactory.getCompiledRuleId(rule, ruleFactoryHelper, grammar.repository);
|
|
2193
|
-
for (const matcher of matchers) {
|
|
2194
|
-
result.push({
|
|
2195
|
-
debugSelector: selector,
|
|
2196
|
-
matcher: matcher.matcher,
|
|
2197
|
-
ruleId: ruleId,
|
|
2198
|
-
grammar: grammar,
|
|
2199
|
-
priority: matcher.priority
|
|
2200
|
-
});
|
|
2201
|
-
}
|
|
2202
|
-
}
|
|
2203
|
-
function nameMatcher(identifers, scopes) {
|
|
2204
|
-
if (scopes.length < identifers.length) {
|
|
2205
|
-
return false;
|
|
2206
|
-
}
|
|
2207
|
-
let lastIndex = 0;
|
|
2208
|
-
return identifers.every(identifier => {
|
|
2209
|
-
for (let i = lastIndex; i < scopes.length; i++) {
|
|
2210
|
-
if (scopesAreMatching(scopes[i], identifier)) {
|
|
2211
|
-
lastIndex = i + 1;
|
|
2212
|
-
return true;
|
|
2213
|
-
}
|
|
2214
|
-
}
|
|
2215
|
-
return false;
|
|
2216
|
-
});
|
|
2217
|
-
}
|
|
2218
|
-
function scopesAreMatching(thisScopeName, scopeName) {
|
|
2219
|
-
if (!thisScopeName) {
|
|
2220
|
-
return false;
|
|
2221
|
-
}
|
|
2222
|
-
if (thisScopeName === scopeName) {
|
|
2223
|
-
return true;
|
|
2224
|
-
}
|
|
2225
|
-
const len = scopeName.length;
|
|
2226
|
-
return thisScopeName.length > len && thisScopeName.substr(0, len) === scopeName && thisScopeName[len] === '.';
|
|
2227
|
-
}
|
|
2228
|
-
class Grammar {
|
|
2229
|
-
_rootScopeName;
|
|
2230
|
-
balancedBracketSelectors;
|
|
2231
|
-
_onigLib;
|
|
2232
|
-
_rootId;
|
|
2233
|
-
_lastRuleId;
|
|
2234
|
-
_ruleId2desc;
|
|
2235
|
-
_includedGrammars;
|
|
2236
|
-
_grammarRepository;
|
|
2237
|
-
_grammar;
|
|
2238
|
-
_injections;
|
|
2239
|
-
_basicScopeAttributesProvider;
|
|
2240
|
-
_tokenTypeMatchers;
|
|
2241
|
-
get themeProvider() { return this._grammarRepository; }
|
|
2242
|
-
constructor(_rootScopeName, grammar, initialLanguage, embeddedLanguages, tokenTypes, balancedBracketSelectors, grammarRepository, _onigLib) {
|
|
2243
|
-
this._rootScopeName = _rootScopeName;
|
|
2244
|
-
this.balancedBracketSelectors = balancedBracketSelectors;
|
|
2245
|
-
this._onigLib = _onigLib;
|
|
2246
|
-
this._basicScopeAttributesProvider = new BasicScopeAttributesProvider(initialLanguage, embeddedLanguages);
|
|
2247
|
-
this._rootId = -1;
|
|
2248
|
-
this._lastRuleId = 0;
|
|
2249
|
-
this._ruleId2desc = [null];
|
|
2250
|
-
this._includedGrammars = {};
|
|
2251
|
-
this._grammarRepository = grammarRepository;
|
|
2252
|
-
this._grammar = initGrammar(grammar, null);
|
|
2253
|
-
this._injections = null;
|
|
2254
|
-
this._tokenTypeMatchers = [];
|
|
2255
|
-
if (tokenTypes) {
|
|
2256
|
-
for (const selector of Object.keys(tokenTypes)) {
|
|
2257
|
-
const matchers = createMatchers(selector, nameMatcher);
|
|
2258
|
-
for (const matcher of matchers) {
|
|
2259
|
-
this._tokenTypeMatchers.push({
|
|
2260
|
-
matcher: matcher.matcher,
|
|
2261
|
-
type: tokenTypes[selector],
|
|
2262
|
-
});
|
|
2263
|
-
}
|
|
2264
|
-
}
|
|
2265
|
-
}
|
|
2266
|
-
}
|
|
2267
|
-
dispose() {
|
|
2268
|
-
for (const rule of this._ruleId2desc) {
|
|
2269
|
-
if (rule) {
|
|
2270
|
-
rule.dispose();
|
|
2271
|
-
}
|
|
2272
|
-
}
|
|
2273
|
-
}
|
|
2274
|
-
createOnigScanner(sources) {
|
|
2275
|
-
return this._onigLib.createOnigScanner(sources);
|
|
2276
|
-
}
|
|
2277
|
-
createOnigString(sources) {
|
|
2278
|
-
return this._onigLib.createOnigString(sources);
|
|
2279
|
-
}
|
|
2280
|
-
getMetadataForScope(scope) {
|
|
2281
|
-
return this._basicScopeAttributesProvider.getBasicScopeAttributes(scope);
|
|
2282
|
-
}
|
|
2283
|
-
_collectInjections() {
|
|
2284
|
-
const grammarRepository = {
|
|
2285
|
-
lookup: (scopeName) => {
|
|
2286
|
-
if (scopeName === this._rootScopeName) {
|
|
2287
|
-
return this._grammar;
|
|
2288
|
-
}
|
|
2289
|
-
return this.getExternalGrammar(scopeName);
|
|
2290
|
-
},
|
|
2291
|
-
injections: (scopeName) => {
|
|
2292
|
-
return this._grammarRepository.injections(scopeName);
|
|
2293
|
-
},
|
|
2294
|
-
};
|
|
2295
|
-
const result = [];
|
|
2296
|
-
const scopeName = this._rootScopeName;
|
|
2297
|
-
const grammar = grammarRepository.lookup(scopeName);
|
|
2298
|
-
if (grammar) {
|
|
2299
|
-
// add injections from the current grammar
|
|
2300
|
-
const rawInjections = grammar.injections;
|
|
2301
|
-
if (rawInjections) {
|
|
2302
|
-
for (let expression in rawInjections) {
|
|
2303
|
-
collectInjections(result, expression, rawInjections[expression], this, grammar);
|
|
2304
|
-
}
|
|
2305
|
-
}
|
|
2306
|
-
// add injection grammars contributed for the current scope
|
|
2307
|
-
const injectionScopeNames = this._grammarRepository.injections(scopeName);
|
|
2308
|
-
if (injectionScopeNames) {
|
|
2309
|
-
injectionScopeNames.forEach((injectionScopeName) => {
|
|
2310
|
-
const injectionGrammar = this.getExternalGrammar(injectionScopeName);
|
|
2311
|
-
if (injectionGrammar) {
|
|
2312
|
-
const selector = injectionGrammar.injectionSelector;
|
|
2313
|
-
if (selector) {
|
|
2314
|
-
collectInjections(result, selector, injectionGrammar, this, injectionGrammar);
|
|
2315
|
-
}
|
|
2316
|
-
}
|
|
2317
|
-
});
|
|
2318
|
-
}
|
|
2319
|
-
}
|
|
2320
|
-
result.sort((i1, i2) => i1.priority - i2.priority); // sort by priority
|
|
2321
|
-
return result;
|
|
2322
|
-
}
|
|
2323
|
-
getInjections() {
|
|
2324
|
-
if (this._injections === null) {
|
|
2325
|
-
this._injections = this._collectInjections();
|
|
2326
|
-
}
|
|
2327
|
-
return this._injections;
|
|
2328
|
-
}
|
|
2329
|
-
registerRule(factory) {
|
|
2330
|
-
const id = ++this._lastRuleId;
|
|
2331
|
-
const result = factory(ruleIdFromNumber(id));
|
|
2332
|
-
this._ruleId2desc[id] = result;
|
|
2333
|
-
return result;
|
|
2334
|
-
}
|
|
2335
|
-
getRule(ruleId) {
|
|
2336
|
-
return this._ruleId2desc[ruleIdToNumber(ruleId)];
|
|
2337
|
-
}
|
|
2338
|
-
getExternalGrammar(scopeName, repository) {
|
|
2339
|
-
if (this._includedGrammars[scopeName]) {
|
|
2340
|
-
return this._includedGrammars[scopeName];
|
|
2341
|
-
}
|
|
2342
|
-
else if (this._grammarRepository) {
|
|
2343
|
-
const rawIncludedGrammar = this._grammarRepository.lookup(scopeName);
|
|
2344
|
-
if (rawIncludedGrammar) {
|
|
2345
|
-
// console.log('LOADED GRAMMAR ' + pattern.include);
|
|
2346
|
-
this._includedGrammars[scopeName] = initGrammar(rawIncludedGrammar, repository && repository.$base);
|
|
2347
|
-
return this._includedGrammars[scopeName];
|
|
2348
|
-
}
|
|
2349
|
-
}
|
|
2350
|
-
return undefined;
|
|
2351
|
-
}
|
|
2352
|
-
tokenizeLine(lineText, prevState, timeLimit = 0) {
|
|
2353
|
-
const r = this._tokenize(lineText, prevState, false, timeLimit);
|
|
2354
|
-
return {
|
|
2355
|
-
tokens: r.lineTokens.getResult(r.ruleStack, r.lineLength),
|
|
2356
|
-
ruleStack: r.ruleStack,
|
|
2357
|
-
stoppedEarly: r.stoppedEarly,
|
|
2358
|
-
};
|
|
2359
|
-
}
|
|
2360
|
-
tokenizeLine2(lineText, prevState, timeLimit = 0) {
|
|
2361
|
-
const r = this._tokenize(lineText, prevState, true, timeLimit);
|
|
2362
|
-
return {
|
|
2363
|
-
tokens: r.lineTokens.getBinaryResult(r.ruleStack, r.lineLength),
|
|
2364
|
-
ruleStack: r.ruleStack,
|
|
2365
|
-
stoppedEarly: r.stoppedEarly,
|
|
2366
|
-
};
|
|
2367
|
-
}
|
|
2368
|
-
_tokenize(lineText, prevState, emitBinaryTokens, timeLimit) {
|
|
2369
|
-
if (this._rootId === -1) {
|
|
2370
|
-
this._rootId = RuleFactory.getCompiledRuleId(this._grammar.repository.$self, this, this._grammar.repository);
|
|
2371
|
-
// This ensures ids are deterministic, and thus equal in renderer and webworker.
|
|
2372
|
-
this.getInjections();
|
|
2373
|
-
}
|
|
2374
|
-
let isFirstLine;
|
|
2375
|
-
if (!prevState || prevState === StateStackImpl.NULL) {
|
|
2376
|
-
isFirstLine = true;
|
|
2377
|
-
const rawDefaultMetadata = this._basicScopeAttributesProvider.getDefaultAttributes();
|
|
2378
|
-
const defaultStyle = this.themeProvider.getDefaults();
|
|
2379
|
-
const defaultMetadata = EncodedTokenAttributes.set(0, rawDefaultMetadata.languageId, rawDefaultMetadata.tokenType, null, defaultStyle.fontStyle, defaultStyle.foregroundId, defaultStyle.backgroundId);
|
|
2380
|
-
const rootScopeName = this.getRule(this._rootId).getName(null, null);
|
|
2381
|
-
let scopeList;
|
|
2382
|
-
if (rootScopeName) {
|
|
2383
|
-
scopeList = AttributedScopeStack.createRootAndLookUpScopeName(rootScopeName, defaultMetadata, this);
|
|
2384
|
-
}
|
|
2385
|
-
else {
|
|
2386
|
-
scopeList = AttributedScopeStack.createRoot("unknown", defaultMetadata);
|
|
2387
|
-
}
|
|
2388
|
-
prevState = new StateStackImpl(null, this._rootId, -1, -1, false, null, scopeList, scopeList);
|
|
2389
|
-
}
|
|
2390
|
-
else {
|
|
2391
|
-
isFirstLine = false;
|
|
2392
|
-
prevState.reset();
|
|
2393
|
-
}
|
|
2394
|
-
lineText = lineText + "\n";
|
|
2395
|
-
const onigLineText = this.createOnigString(lineText);
|
|
2396
|
-
const lineLength = onigLineText.content.length;
|
|
2397
|
-
const lineTokens = new LineTokens(emitBinaryTokens, lineText, this._tokenTypeMatchers, this.balancedBracketSelectors);
|
|
2398
|
-
const r = _tokenizeString(this, onigLineText, isFirstLine, 0, prevState, lineTokens, true, timeLimit);
|
|
2399
|
-
disposeOnigString(onigLineText);
|
|
2400
|
-
return {
|
|
2401
|
-
lineLength: lineLength,
|
|
2402
|
-
lineTokens: lineTokens,
|
|
2403
|
-
ruleStack: r.stack,
|
|
2404
|
-
stoppedEarly: r.stoppedEarly,
|
|
2405
|
-
};
|
|
2406
|
-
}
|
|
2407
|
-
}
|
|
2408
|
-
function initGrammar(grammar, base) {
|
|
2409
|
-
grammar = clone(grammar);
|
|
2410
|
-
grammar.repository = grammar.repository || {};
|
|
2411
|
-
grammar.repository.$self = {
|
|
2412
|
-
$vscodeTextmateLocation: grammar.$vscodeTextmateLocation,
|
|
2413
|
-
patterns: grammar.patterns,
|
|
2414
|
-
name: grammar.scopeName
|
|
2415
|
-
};
|
|
2416
|
-
grammar.repository.$base = base || grammar.repository.$self;
|
|
2417
|
-
return grammar;
|
|
2418
|
-
}
|
|
2419
|
-
class AttributedScopeStack {
|
|
2420
|
-
parent;
|
|
2421
|
-
scopePath;
|
|
2422
|
-
tokenAttributes;
|
|
2423
|
-
static fromExtension(namesScopeList, contentNameScopesList) {
|
|
2424
|
-
let current = namesScopeList;
|
|
2425
|
-
let scopeNames = namesScopeList?.scopePath ?? null;
|
|
2426
|
-
for (const frame of contentNameScopesList) {
|
|
2427
|
-
scopeNames = ScopeStack.push(scopeNames, frame.scopeNames);
|
|
2428
|
-
current = new AttributedScopeStack(current, scopeNames, frame.encodedTokenAttributes);
|
|
2429
|
-
}
|
|
2430
|
-
return current;
|
|
2431
|
-
}
|
|
2432
|
-
static createRoot(scopeName, tokenAttributes) {
|
|
2433
|
-
return new AttributedScopeStack(null, new ScopeStack(null, scopeName), tokenAttributes);
|
|
2434
|
-
}
|
|
2435
|
-
static createRootAndLookUpScopeName(scopeName, tokenAttributes, grammar) {
|
|
2436
|
-
const rawRootMetadata = grammar.getMetadataForScope(scopeName);
|
|
2437
|
-
const scopePath = new ScopeStack(null, scopeName);
|
|
2438
|
-
const rootStyle = grammar.themeProvider.themeMatch(scopePath);
|
|
2439
|
-
const resolvedTokenAttributes = AttributedScopeStack.mergeAttributes(tokenAttributes, rawRootMetadata, rootStyle);
|
|
2440
|
-
return new AttributedScopeStack(null, scopePath, resolvedTokenAttributes);
|
|
2441
|
-
}
|
|
2442
|
-
get scopeName() { return this.scopePath.scopeName; }
|
|
2443
|
-
/**
|
|
2444
|
-
* Invariant:
|
|
2445
|
-
* ```
|
|
2446
|
-
* if (parent && !scopePath.extends(parent.scopePath)) {
|
|
2447
|
-
* throw new Error();
|
|
2448
|
-
* }
|
|
2449
|
-
* ```
|
|
2450
|
-
*/
|
|
2451
|
-
constructor(parent, scopePath, tokenAttributes) {
|
|
2452
|
-
this.parent = parent;
|
|
2453
|
-
this.scopePath = scopePath;
|
|
2454
|
-
this.tokenAttributes = tokenAttributes;
|
|
2455
|
-
}
|
|
2456
|
-
toString() {
|
|
2457
|
-
return this.getScopeNames().join(' ');
|
|
2458
|
-
}
|
|
2459
|
-
equals(other) {
|
|
2460
|
-
return AttributedScopeStack.equals(this, other);
|
|
2461
|
-
}
|
|
2462
|
-
static equals(a, b) {
|
|
2463
|
-
do {
|
|
2464
|
-
if (a === b) {
|
|
2465
|
-
return true;
|
|
2466
|
-
}
|
|
2467
|
-
if (!a && !b) {
|
|
2468
|
-
// End of list reached for both
|
|
2469
|
-
return true;
|
|
2470
|
-
}
|
|
2471
|
-
if (!a || !b) {
|
|
2472
|
-
// End of list reached only for one
|
|
2473
|
-
return false;
|
|
2474
|
-
}
|
|
2475
|
-
if (a.scopeName !== b.scopeName || a.tokenAttributes !== b.tokenAttributes) {
|
|
2476
|
-
return false;
|
|
2477
|
-
}
|
|
2478
|
-
// Go to previous pair
|
|
2479
|
-
a = a.parent;
|
|
2480
|
-
b = b.parent;
|
|
2481
|
-
} while (true);
|
|
2482
|
-
}
|
|
2483
|
-
static mergeAttributes(existingTokenAttributes, basicScopeAttributes, styleAttributes) {
|
|
2484
|
-
let fontStyle = -1 /* FontStyle.NotSet */;
|
|
2485
|
-
let foreground = 0;
|
|
2486
|
-
let background = 0;
|
|
2487
|
-
if (styleAttributes !== null) {
|
|
2488
|
-
fontStyle = styleAttributes.fontStyle;
|
|
2489
|
-
foreground = styleAttributes.foregroundId;
|
|
2490
|
-
background = styleAttributes.backgroundId;
|
|
2491
|
-
}
|
|
2492
|
-
return EncodedTokenAttributes.set(existingTokenAttributes, basicScopeAttributes.languageId, basicScopeAttributes.tokenType, null, fontStyle, foreground, background);
|
|
2493
|
-
}
|
|
2494
|
-
pushAttributed(scopePath, grammar) {
|
|
2495
|
-
if (scopePath === null) {
|
|
2496
|
-
return this;
|
|
2497
|
-
}
|
|
2498
|
-
if (scopePath.indexOf(' ') === -1) {
|
|
2499
|
-
// This is the common case and much faster
|
|
2500
|
-
return AttributedScopeStack._pushAttributed(this, scopePath, grammar);
|
|
2501
|
-
}
|
|
2502
|
-
const scopes = scopePath.split(/ /g);
|
|
2503
|
-
let result = this;
|
|
2504
|
-
for (const scope of scopes) {
|
|
2505
|
-
result = AttributedScopeStack._pushAttributed(result, scope, grammar);
|
|
2506
|
-
}
|
|
2507
|
-
return result;
|
|
2508
|
-
}
|
|
2509
|
-
static _pushAttributed(target, scopeName, grammar) {
|
|
2510
|
-
const rawMetadata = grammar.getMetadataForScope(scopeName);
|
|
2511
|
-
const newPath = target.scopePath.push(scopeName);
|
|
2512
|
-
const scopeThemeMatchResult = grammar.themeProvider.themeMatch(newPath);
|
|
2513
|
-
const metadata = AttributedScopeStack.mergeAttributes(target.tokenAttributes, rawMetadata, scopeThemeMatchResult);
|
|
2514
|
-
return new AttributedScopeStack(target, newPath, metadata);
|
|
2515
|
-
}
|
|
2516
|
-
getScopeNames() {
|
|
2517
|
-
return this.scopePath.getSegments();
|
|
2518
|
-
}
|
|
2519
|
-
getExtensionIfDefined(base) {
|
|
2520
|
-
const result = [];
|
|
2521
|
-
let self = this;
|
|
2522
|
-
while (self && self !== base) {
|
|
2523
|
-
result.push({
|
|
2524
|
-
encodedTokenAttributes: self.tokenAttributes,
|
|
2525
|
-
scopeNames: self.scopePath.getExtensionIfDefined(self.parent?.scopePath ?? null),
|
|
2526
|
-
});
|
|
2527
|
-
self = self.parent;
|
|
2528
|
-
}
|
|
2529
|
-
return self === base ? result.reverse() : undefined;
|
|
2530
|
-
}
|
|
2531
|
-
}
|
|
2532
|
-
/**
|
|
2533
|
-
* Represents a "pushed" state on the stack (as a linked list element).
|
|
2534
|
-
*/
|
|
2535
|
-
class StateStackImpl {
|
|
2536
|
-
parent;
|
|
2537
|
-
ruleId;
|
|
2538
|
-
beginRuleCapturedEOL;
|
|
2539
|
-
endRule;
|
|
2540
|
-
nameScopesList;
|
|
2541
|
-
contentNameScopesList;
|
|
2542
|
-
_stackElementBrand = undefined;
|
|
2543
|
-
// TODO remove me
|
|
2544
|
-
static NULL = new StateStackImpl(null, 0, 0, 0, false, null, null, null);
|
|
2545
|
-
/**
|
|
2546
|
-
* The position on the current line where this state was pushed.
|
|
2547
|
-
* This is relevant only while tokenizing a line, to detect endless loops.
|
|
2548
|
-
* Its value is meaningless across lines.
|
|
2549
|
-
*/
|
|
2550
|
-
_enterPos;
|
|
2551
|
-
/**
|
|
2552
|
-
* The captured anchor position when this stack element was pushed.
|
|
2553
|
-
* This is relevant only while tokenizing a line, to restore the anchor position when popping.
|
|
2554
|
-
* Its value is meaningless across lines.
|
|
2555
|
-
*/
|
|
2556
|
-
_anchorPos;
|
|
2557
|
-
/**
|
|
2558
|
-
* The depth of the stack.
|
|
2559
|
-
*/
|
|
2560
|
-
depth;
|
|
2561
|
-
/**
|
|
2562
|
-
* Invariant:
|
|
2563
|
-
* ```
|
|
2564
|
-
* if (contentNameScopesList !== nameScopesList && contentNameScopesList?.parent !== nameScopesList) {
|
|
2565
|
-
* throw new Error();
|
|
2566
|
-
* }
|
|
2567
|
-
* if (this.parent && !nameScopesList.extends(this.parent.contentNameScopesList)) {
|
|
2568
|
-
* throw new Error();
|
|
2569
|
-
* }
|
|
2570
|
-
* ```
|
|
2571
|
-
*/
|
|
2572
|
-
constructor(
|
|
2573
|
-
/**
|
|
2574
|
-
* The previous state on the stack (or null for the root state).
|
|
2575
|
-
*/
|
|
2576
|
-
parent,
|
|
2577
|
-
/**
|
|
2578
|
-
* The state (rule) that this element represents.
|
|
2579
|
-
*/
|
|
2580
|
-
ruleId, enterPos, anchorPos,
|
|
2581
|
-
/**
|
|
2582
|
-
* The state has entered and captured \n. This means that the next line should have an anchorPosition of 0.
|
|
2583
|
-
*/
|
|
2584
|
-
beginRuleCapturedEOL,
|
|
2585
|
-
/**
|
|
2586
|
-
* The "pop" (end) condition for this state in case that it was dynamically generated through captured text.
|
|
2587
|
-
*/
|
|
2588
|
-
endRule,
|
|
2589
|
-
/**
|
|
2590
|
-
* The list of scopes containing the "name" for this state.
|
|
2591
|
-
*/
|
|
2592
|
-
nameScopesList,
|
|
2593
|
-
/**
|
|
2594
|
-
* The list of scopes containing the "contentName" (besides "name") for this state.
|
|
2595
|
-
* This list **must** contain as an element `scopeName`.
|
|
2596
|
-
*/
|
|
2597
|
-
contentNameScopesList) {
|
|
2598
|
-
this.parent = parent;
|
|
2599
|
-
this.ruleId = ruleId;
|
|
2600
|
-
this.beginRuleCapturedEOL = beginRuleCapturedEOL;
|
|
2601
|
-
this.endRule = endRule;
|
|
2602
|
-
this.nameScopesList = nameScopesList;
|
|
2603
|
-
this.contentNameScopesList = contentNameScopesList;
|
|
2604
|
-
this.depth = this.parent ? this.parent.depth + 1 : 1;
|
|
2605
|
-
this._enterPos = enterPos;
|
|
2606
|
-
this._anchorPos = anchorPos;
|
|
2607
|
-
}
|
|
2608
|
-
equals(other) {
|
|
2609
|
-
if (other === null) {
|
|
2610
|
-
return false;
|
|
2611
|
-
}
|
|
2612
|
-
return StateStackImpl._equals(this, other);
|
|
2613
|
-
}
|
|
2614
|
-
static _equals(a, b) {
|
|
2615
|
-
if (a === b) {
|
|
2616
|
-
return true;
|
|
2617
|
-
}
|
|
2618
|
-
if (!this._structuralEquals(a, b)) {
|
|
2619
|
-
return false;
|
|
2620
|
-
}
|
|
2621
|
-
return AttributedScopeStack.equals(a.contentNameScopesList, b.contentNameScopesList);
|
|
2622
|
-
}
|
|
2623
|
-
/**
|
|
2624
|
-
* A structural equals check. Does not take into account `scopes`.
|
|
2625
|
-
*/
|
|
2626
|
-
static _structuralEquals(a, b) {
|
|
2627
|
-
do {
|
|
2628
|
-
if (a === b) {
|
|
2629
|
-
return true;
|
|
2630
|
-
}
|
|
2631
|
-
if (!a && !b) {
|
|
2632
|
-
// End of list reached for both
|
|
2633
|
-
return true;
|
|
2634
|
-
}
|
|
2635
|
-
if (!a || !b) {
|
|
2636
|
-
// End of list reached only for one
|
|
2637
|
-
return false;
|
|
2638
|
-
}
|
|
2639
|
-
if (a.depth !== b.depth ||
|
|
2640
|
-
a.ruleId !== b.ruleId ||
|
|
2641
|
-
a.endRule !== b.endRule) {
|
|
2642
|
-
return false;
|
|
2643
|
-
}
|
|
2644
|
-
// Go to previous pair
|
|
2645
|
-
a = a.parent;
|
|
2646
|
-
b = b.parent;
|
|
2647
|
-
} while (true);
|
|
2648
|
-
}
|
|
2649
|
-
clone() {
|
|
2650
|
-
return this;
|
|
2651
|
-
}
|
|
2652
|
-
static _reset(el) {
|
|
2653
|
-
while (el) {
|
|
2654
|
-
el._enterPos = -1;
|
|
2655
|
-
el._anchorPos = -1;
|
|
2656
|
-
el = el.parent;
|
|
2657
|
-
}
|
|
2658
|
-
}
|
|
2659
|
-
reset() {
|
|
2660
|
-
StateStackImpl._reset(this);
|
|
2661
|
-
}
|
|
2662
|
-
pop() {
|
|
2663
|
-
return this.parent;
|
|
2664
|
-
}
|
|
2665
|
-
safePop() {
|
|
2666
|
-
if (this.parent) {
|
|
2667
|
-
return this.parent;
|
|
2668
|
-
}
|
|
2669
|
-
return this;
|
|
2670
|
-
}
|
|
2671
|
-
push(ruleId, enterPos, anchorPos, beginRuleCapturedEOL, endRule, nameScopesList, contentNameScopesList) {
|
|
2672
|
-
return new StateStackImpl(this, ruleId, enterPos, anchorPos, beginRuleCapturedEOL, endRule, nameScopesList, contentNameScopesList);
|
|
2673
|
-
}
|
|
2674
|
-
getEnterPos() {
|
|
2675
|
-
return this._enterPos;
|
|
2676
|
-
}
|
|
2677
|
-
getAnchorPos() {
|
|
2678
|
-
return this._anchorPos;
|
|
2679
|
-
}
|
|
2680
|
-
getRule(grammar) {
|
|
2681
|
-
return grammar.getRule(this.ruleId);
|
|
2682
|
-
}
|
|
2683
|
-
toString() {
|
|
2684
|
-
const r = [];
|
|
2685
|
-
this._writeString(r, 0);
|
|
2686
|
-
return "[" + r.join(",") + "]";
|
|
2687
|
-
}
|
|
2688
|
-
_writeString(res, outIndex) {
|
|
2689
|
-
if (this.parent) {
|
|
2690
|
-
outIndex = this.parent._writeString(res, outIndex);
|
|
2691
|
-
}
|
|
2692
|
-
res[outIndex++] = `(${this.ruleId}, ${this.nameScopesList?.toString()}, ${this.contentNameScopesList?.toString()})`;
|
|
2693
|
-
return outIndex;
|
|
2694
|
-
}
|
|
2695
|
-
withContentNameScopesList(contentNameScopeStack) {
|
|
2696
|
-
if (this.contentNameScopesList === contentNameScopeStack) {
|
|
2697
|
-
return this;
|
|
2698
|
-
}
|
|
2699
|
-
return this.parent.push(this.ruleId, this._enterPos, this._anchorPos, this.beginRuleCapturedEOL, this.endRule, this.nameScopesList, contentNameScopeStack);
|
|
2700
|
-
}
|
|
2701
|
-
withEndRule(endRule) {
|
|
2702
|
-
if (this.endRule === endRule) {
|
|
2703
|
-
return this;
|
|
2704
|
-
}
|
|
2705
|
-
return new StateStackImpl(this.parent, this.ruleId, this._enterPos, this._anchorPos, this.beginRuleCapturedEOL, endRule, this.nameScopesList, this.contentNameScopesList);
|
|
2706
|
-
}
|
|
2707
|
-
// Used to warn of endless loops
|
|
2708
|
-
hasSameRuleAs(other) {
|
|
2709
|
-
let el = this;
|
|
2710
|
-
while (el && el._enterPos === other._enterPos) {
|
|
2711
|
-
if (el.ruleId === other.ruleId) {
|
|
2712
|
-
return true;
|
|
2713
|
-
}
|
|
2714
|
-
el = el.parent;
|
|
2715
|
-
}
|
|
2716
|
-
return false;
|
|
2717
|
-
}
|
|
2718
|
-
toStateStackFrame() {
|
|
2719
|
-
return {
|
|
2720
|
-
ruleId: ruleIdToNumber(this.ruleId),
|
|
2721
|
-
beginRuleCapturedEOL: this.beginRuleCapturedEOL,
|
|
2722
|
-
endRule: this.endRule,
|
|
2723
|
-
nameScopesList: this.nameScopesList?.getExtensionIfDefined(this.parent?.nameScopesList ?? null) ?? [],
|
|
2724
|
-
contentNameScopesList: this.contentNameScopesList?.getExtensionIfDefined(this.nameScopesList) ?? [],
|
|
2725
|
-
};
|
|
2726
|
-
}
|
|
2727
|
-
static pushFrame(self, frame) {
|
|
2728
|
-
const namesScopeList = AttributedScopeStack.fromExtension(self?.nameScopesList ?? null, frame.nameScopesList);
|
|
2729
|
-
return new StateStackImpl(self, ruleIdFromNumber(frame.ruleId), frame.enterPos ?? -1, frame.anchorPos ?? -1, frame.beginRuleCapturedEOL, frame.endRule, namesScopeList, AttributedScopeStack.fromExtension(namesScopeList, frame.contentNameScopesList));
|
|
2730
|
-
}
|
|
2731
|
-
}
|
|
2732
|
-
class BalancedBracketSelectors {
|
|
2733
|
-
balancedBracketScopes;
|
|
2734
|
-
unbalancedBracketScopes;
|
|
2735
|
-
allowAny = false;
|
|
2736
|
-
constructor(balancedBracketScopes, unbalancedBracketScopes) {
|
|
2737
|
-
this.balancedBracketScopes = balancedBracketScopes.flatMap((selector) => {
|
|
2738
|
-
if (selector === '*') {
|
|
2739
|
-
this.allowAny = true;
|
|
2740
|
-
return [];
|
|
2741
|
-
}
|
|
2742
|
-
return createMatchers(selector, nameMatcher).map((m) => m.matcher);
|
|
2743
|
-
});
|
|
2744
|
-
this.unbalancedBracketScopes = unbalancedBracketScopes.flatMap((selector) => createMatchers(selector, nameMatcher).map((m) => m.matcher));
|
|
2745
|
-
}
|
|
2746
|
-
get matchesAlways() {
|
|
2747
|
-
return this.allowAny && this.unbalancedBracketScopes.length === 0;
|
|
2748
|
-
}
|
|
2749
|
-
get matchesNever() {
|
|
2750
|
-
return this.balancedBracketScopes.length === 0 && !this.allowAny;
|
|
2751
|
-
}
|
|
2752
|
-
match(scopes) {
|
|
2753
|
-
for (const excluder of this.unbalancedBracketScopes) {
|
|
2754
|
-
if (excluder(scopes)) {
|
|
2755
|
-
return false;
|
|
2756
|
-
}
|
|
2757
|
-
}
|
|
2758
|
-
for (const includer of this.balancedBracketScopes) {
|
|
2759
|
-
if (includer(scopes)) {
|
|
2760
|
-
return true;
|
|
2761
|
-
}
|
|
2762
|
-
}
|
|
2763
|
-
return this.allowAny;
|
|
2764
|
-
}
|
|
2765
|
-
}
|
|
2766
|
-
class LineTokens {
|
|
2767
|
-
balancedBracketSelectors;
|
|
2768
|
-
_emitBinaryTokens;
|
|
2769
|
-
/**
|
|
2770
|
-
* defined only if `false`.
|
|
2771
|
-
*/
|
|
2772
|
-
_lineText;
|
|
2773
|
-
/**
|
|
2774
|
-
* used only if `_emitBinaryTokens` is false.
|
|
2775
|
-
*/
|
|
2776
|
-
_tokens;
|
|
2777
|
-
/**
|
|
2778
|
-
* used only if `_emitBinaryTokens` is true.
|
|
2779
|
-
*/
|
|
2780
|
-
_binaryTokens;
|
|
2781
|
-
_lastTokenEndIndex;
|
|
2782
|
-
_tokenTypeOverrides;
|
|
2783
|
-
constructor(emitBinaryTokens, lineText, tokenTypeOverrides, balancedBracketSelectors) {
|
|
2784
|
-
this.balancedBracketSelectors = balancedBracketSelectors;
|
|
2785
|
-
this._emitBinaryTokens = emitBinaryTokens;
|
|
2786
|
-
this._tokenTypeOverrides = tokenTypeOverrides;
|
|
2787
|
-
{
|
|
2788
|
-
this._lineText = null;
|
|
2789
|
-
}
|
|
2790
|
-
this._tokens = [];
|
|
2791
|
-
this._binaryTokens = [];
|
|
2792
|
-
this._lastTokenEndIndex = 0;
|
|
2793
|
-
}
|
|
2794
|
-
produce(stack, endIndex) {
|
|
2795
|
-
this.produceFromScopes(stack.contentNameScopesList, endIndex);
|
|
2796
|
-
}
|
|
2797
|
-
produceFromScopes(scopesList, endIndex) {
|
|
2798
|
-
if (this._lastTokenEndIndex >= endIndex) {
|
|
2799
|
-
return;
|
|
2800
|
-
}
|
|
2801
|
-
if (this._emitBinaryTokens) {
|
|
2802
|
-
let metadata = scopesList?.tokenAttributes ?? 0;
|
|
2803
|
-
let containsBalancedBrackets = false;
|
|
2804
|
-
if (this.balancedBracketSelectors?.matchesAlways) {
|
|
2805
|
-
containsBalancedBrackets = true;
|
|
2806
|
-
}
|
|
2807
|
-
if (this._tokenTypeOverrides.length > 0 || (this.balancedBracketSelectors && !this.balancedBracketSelectors.matchesAlways && !this.balancedBracketSelectors.matchesNever)) {
|
|
2808
|
-
// Only generate scope array when required to improve performance
|
|
2809
|
-
const scopes = scopesList?.getScopeNames() ?? [];
|
|
2810
|
-
for (const tokenType of this._tokenTypeOverrides) {
|
|
2811
|
-
if (tokenType.matcher(scopes)) {
|
|
2812
|
-
metadata = EncodedTokenAttributes.set(metadata, 0, toOptionalTokenType(tokenType.type), null, -1 /* FontStyle.NotSet */, 0, 0);
|
|
2813
|
-
}
|
|
2814
|
-
}
|
|
2815
|
-
if (this.balancedBracketSelectors) {
|
|
2816
|
-
containsBalancedBrackets = this.balancedBracketSelectors.match(scopes);
|
|
2817
|
-
}
|
|
2818
|
-
}
|
|
2819
|
-
if (containsBalancedBrackets) {
|
|
2820
|
-
metadata = EncodedTokenAttributes.set(metadata, 0, 8 /* OptionalStandardTokenType.NotSet */, containsBalancedBrackets, -1 /* FontStyle.NotSet */, 0, 0);
|
|
2821
|
-
}
|
|
2822
|
-
if (this._binaryTokens.length > 0 && this._binaryTokens[this._binaryTokens.length - 1] === metadata) {
|
|
2823
|
-
// no need to push a token with the same metadata
|
|
2824
|
-
this._lastTokenEndIndex = endIndex;
|
|
2825
|
-
return;
|
|
2826
|
-
}
|
|
2827
|
-
this._binaryTokens.push(this._lastTokenEndIndex);
|
|
2828
|
-
this._binaryTokens.push(metadata);
|
|
2829
|
-
this._lastTokenEndIndex = endIndex;
|
|
2830
|
-
return;
|
|
2831
|
-
}
|
|
2832
|
-
const scopes = scopesList?.getScopeNames() ?? [];
|
|
2833
|
-
this._tokens.push({
|
|
2834
|
-
startIndex: this._lastTokenEndIndex,
|
|
2835
|
-
endIndex: endIndex,
|
|
2836
|
-
// value: lineText.substring(lastTokenEndIndex, endIndex),
|
|
2837
|
-
scopes: scopes
|
|
2838
|
-
});
|
|
2839
|
-
this._lastTokenEndIndex = endIndex;
|
|
2840
|
-
}
|
|
2841
|
-
getResult(stack, lineLength) {
|
|
2842
|
-
if (this._tokens.length > 0 && this._tokens[this._tokens.length - 1].startIndex === lineLength - 1) {
|
|
2843
|
-
// pop produced token for newline
|
|
2844
|
-
this._tokens.pop();
|
|
2845
|
-
}
|
|
2846
|
-
if (this._tokens.length === 0) {
|
|
2847
|
-
this._lastTokenEndIndex = -1;
|
|
2848
|
-
this.produce(stack, lineLength);
|
|
2849
|
-
this._tokens[this._tokens.length - 1].startIndex = 0;
|
|
2850
|
-
}
|
|
2851
|
-
return this._tokens;
|
|
2852
|
-
}
|
|
2853
|
-
getBinaryResult(stack, lineLength) {
|
|
2854
|
-
if (this._binaryTokens.length > 0 && this._binaryTokens[this._binaryTokens.length - 2] === lineLength - 1) {
|
|
2855
|
-
// pop produced token for newline
|
|
2856
|
-
this._binaryTokens.pop();
|
|
2857
|
-
this._binaryTokens.pop();
|
|
2858
|
-
}
|
|
2859
|
-
if (this._binaryTokens.length === 0) {
|
|
2860
|
-
this._lastTokenEndIndex = -1;
|
|
2861
|
-
this.produce(stack, lineLength);
|
|
2862
|
-
this._binaryTokens[this._binaryTokens.length - 2] = 0;
|
|
2863
|
-
}
|
|
2864
|
-
const result = new Uint32Array(this._binaryTokens.length);
|
|
2865
|
-
for (let i = 0, len = this._binaryTokens.length; i < len; i++) {
|
|
2866
|
-
result[i] = this._binaryTokens[i];
|
|
2867
|
-
}
|
|
2868
|
-
return result;
|
|
2869
|
-
}
|
|
2870
|
-
}
|
|
2871
|
-
|
|
2872
|
-
/*---------------------------------------------------------
|
|
2873
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
2874
|
-
*--------------------------------------------------------*/
|
|
2875
|
-
class SyncRegistry {
|
|
2876
|
-
_onigLibPromise;
|
|
2877
|
-
_grammars = new Map();
|
|
2878
|
-
_rawGrammars = new Map();
|
|
2879
|
-
_injectionGrammars = new Map();
|
|
2880
|
-
_theme;
|
|
2881
|
-
constructor(theme, _onigLibPromise) {
|
|
2882
|
-
this._onigLibPromise = _onigLibPromise;
|
|
2883
|
-
this._theme = theme;
|
|
2884
|
-
}
|
|
2885
|
-
dispose() {
|
|
2886
|
-
for (const grammar of this._grammars.values()) {
|
|
2887
|
-
grammar.dispose();
|
|
2888
|
-
}
|
|
2889
|
-
}
|
|
2890
|
-
setTheme(theme) {
|
|
2891
|
-
this._theme = theme;
|
|
2892
|
-
}
|
|
2893
|
-
getColorMap() {
|
|
2894
|
-
return this._theme.getColorMap();
|
|
2895
|
-
}
|
|
2896
|
-
/**
|
|
2897
|
-
* Add `grammar` to registry and return a list of referenced scope names
|
|
2898
|
-
*/
|
|
2899
|
-
addGrammar(grammar, injectionScopeNames) {
|
|
2900
|
-
this._rawGrammars.set(grammar.scopeName, grammar);
|
|
2901
|
-
if (injectionScopeNames) {
|
|
2902
|
-
this._injectionGrammars.set(grammar.scopeName, injectionScopeNames);
|
|
2903
|
-
}
|
|
2904
|
-
}
|
|
2905
|
-
/**
|
|
2906
|
-
* Lookup a raw grammar.
|
|
2907
|
-
*/
|
|
2908
|
-
lookup(scopeName) {
|
|
2909
|
-
return this._rawGrammars.get(scopeName);
|
|
2910
|
-
}
|
|
2911
|
-
/**
|
|
2912
|
-
* Returns the injections for the given grammar
|
|
2913
|
-
*/
|
|
2914
|
-
injections(targetScope) {
|
|
2915
|
-
return this._injectionGrammars.get(targetScope);
|
|
2916
|
-
}
|
|
2917
|
-
/**
|
|
2918
|
-
* Get the default theme settings
|
|
2919
|
-
*/
|
|
2920
|
-
getDefaults() {
|
|
2921
|
-
return this._theme.getDefaults();
|
|
2922
|
-
}
|
|
2923
|
-
/**
|
|
2924
|
-
* Match a scope in the theme.
|
|
2925
|
-
*/
|
|
2926
|
-
themeMatch(scopePath) {
|
|
2927
|
-
return this._theme.match(scopePath);
|
|
2928
|
-
}
|
|
2929
|
-
/**
|
|
2930
|
-
* Lookup a grammar.
|
|
2931
|
-
*/
|
|
2932
|
-
async grammarForScopeName(scopeName, initialLanguage, embeddedLanguages, tokenTypes, balancedBracketSelectors) {
|
|
2933
|
-
if (!this._grammars.has(scopeName)) {
|
|
2934
|
-
let rawGrammar = this._rawGrammars.get(scopeName);
|
|
2935
|
-
if (!rawGrammar) {
|
|
2936
|
-
return null;
|
|
2937
|
-
}
|
|
2938
|
-
this._grammars.set(scopeName, createGrammar(scopeName, rawGrammar, initialLanguage, embeddedLanguages, tokenTypes, balancedBracketSelectors, this, await this._onigLibPromise));
|
|
2939
|
-
}
|
|
2940
|
-
return this._grammars.get(scopeName);
|
|
2941
|
-
}
|
|
2942
|
-
}
|
|
2943
|
-
|
|
2944
|
-
/*---------------------------------------------------------
|
|
2945
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
2946
|
-
*--------------------------------------------------------*/
|
|
2947
|
-
/**
|
|
2948
|
-
* The registry that will hold all grammars.
|
|
2949
|
-
*/
|
|
2950
|
-
let Registry$1 = class Registry {
|
|
2951
|
-
_options;
|
|
2952
|
-
_syncRegistry;
|
|
2953
|
-
_ensureGrammarCache;
|
|
2954
|
-
constructor(options) {
|
|
2955
|
-
this._options = options;
|
|
2956
|
-
this._syncRegistry = new SyncRegistry(Theme.createFromRawTheme(options.theme, options.colorMap), options.onigLib);
|
|
2957
|
-
this._ensureGrammarCache = new Map();
|
|
2958
|
-
}
|
|
2959
|
-
dispose() {
|
|
2960
|
-
this._syncRegistry.dispose();
|
|
2961
|
-
}
|
|
2962
|
-
/**
|
|
2963
|
-
* Change the theme. Once called, no previous `ruleStack` should be used anymore.
|
|
2964
|
-
*/
|
|
2965
|
-
setTheme(theme, colorMap) {
|
|
2966
|
-
this._syncRegistry.setTheme(Theme.createFromRawTheme(theme, colorMap));
|
|
2967
|
-
}
|
|
2968
|
-
/**
|
|
2969
|
-
* Returns a lookup array for color ids.
|
|
2970
|
-
*/
|
|
2971
|
-
getColorMap() {
|
|
2972
|
-
return this._syncRegistry.getColorMap();
|
|
2973
|
-
}
|
|
2974
|
-
/**
|
|
2975
|
-
* Load the grammar for `scopeName` and all referenced included grammars asynchronously.
|
|
2976
|
-
* Please do not use language id 0.
|
|
2977
|
-
*/
|
|
2978
|
-
loadGrammarWithEmbeddedLanguages(initialScopeName, initialLanguage, embeddedLanguages) {
|
|
2979
|
-
return this.loadGrammarWithConfiguration(initialScopeName, initialLanguage, { embeddedLanguages });
|
|
2980
|
-
}
|
|
2981
|
-
/**
|
|
2982
|
-
* Load the grammar for `scopeName` and all referenced included grammars asynchronously.
|
|
2983
|
-
* Please do not use language id 0.
|
|
2984
|
-
*/
|
|
2985
|
-
loadGrammarWithConfiguration(initialScopeName, initialLanguage, configuration) {
|
|
2986
|
-
return this._loadGrammar(initialScopeName, initialLanguage, configuration.embeddedLanguages, configuration.tokenTypes, new BalancedBracketSelectors(configuration.balancedBracketSelectors || [], configuration.unbalancedBracketSelectors || []));
|
|
2987
|
-
}
|
|
2988
|
-
/**
|
|
2989
|
-
* Load the grammar for `scopeName` and all referenced included grammars asynchronously.
|
|
2990
|
-
*/
|
|
2991
|
-
loadGrammar(initialScopeName) {
|
|
2992
|
-
return this._loadGrammar(initialScopeName, 0, null, null, null);
|
|
2993
|
-
}
|
|
2994
|
-
async _loadGrammar(initialScopeName, initialLanguage, embeddedLanguages, tokenTypes, balancedBracketSelectors) {
|
|
2995
|
-
const dependencyProcessor = new ScopeDependencyProcessor(this._syncRegistry, initialScopeName);
|
|
2996
|
-
while (dependencyProcessor.Q.length > 0) {
|
|
2997
|
-
await Promise.all(dependencyProcessor.Q.map((request) => this._loadSingleGrammar(request.scopeName)));
|
|
2998
|
-
dependencyProcessor.processQueue();
|
|
2999
|
-
}
|
|
3000
|
-
return this._grammarForScopeName(initialScopeName, initialLanguage, embeddedLanguages, tokenTypes, balancedBracketSelectors);
|
|
3001
|
-
}
|
|
3002
|
-
async _loadSingleGrammar(scopeName) {
|
|
3003
|
-
if (!this._ensureGrammarCache.has(scopeName)) {
|
|
3004
|
-
this._ensureGrammarCache.set(scopeName, this._doLoadSingleGrammar(scopeName));
|
|
3005
|
-
}
|
|
3006
|
-
return this._ensureGrammarCache.get(scopeName);
|
|
3007
|
-
}
|
|
3008
|
-
async _doLoadSingleGrammar(scopeName) {
|
|
3009
|
-
const grammar = await this._options.loadGrammar(scopeName);
|
|
3010
|
-
if (grammar) {
|
|
3011
|
-
const injections = typeof this._options.getInjections === "function" ? this._options.getInjections(scopeName) : undefined;
|
|
3012
|
-
this._syncRegistry.addGrammar(grammar, injections);
|
|
3013
|
-
}
|
|
3014
|
-
}
|
|
3015
|
-
/**
|
|
3016
|
-
* Adds a rawGrammar.
|
|
3017
|
-
*/
|
|
3018
|
-
async addGrammar(rawGrammar, injections = [], initialLanguage = 0, embeddedLanguages = null) {
|
|
3019
|
-
this._syncRegistry.addGrammar(rawGrammar, injections);
|
|
3020
|
-
return (await this._grammarForScopeName(rawGrammar.scopeName, initialLanguage, embeddedLanguages));
|
|
3021
|
-
}
|
|
3022
|
-
/**
|
|
3023
|
-
* Get the grammar for `scopeName`. The grammar must first be created via `loadGrammar` or `addGrammar`.
|
|
3024
|
-
*/
|
|
3025
|
-
_grammarForScopeName(scopeName, initialLanguage = 0, embeddedLanguages = null, tokenTypes = null, balancedBracketSelectors = null) {
|
|
3026
|
-
return this._syncRegistry.grammarForScopeName(scopeName, initialLanguage, embeddedLanguages, tokenTypes, balancedBracketSelectors);
|
|
3027
|
-
}
|
|
3028
|
-
};
|
|
3029
|
-
const INITIAL = StateStackImpl.NULL;
|
|
3030
|
-
|
|
3031
|
-
/**
|
|
3032
|
-
* Helpers to manage the "collapsed" metadata of an entire StackElement stack.
|
|
3033
|
-
* The following assumptions have been made:
|
|
3034
|
-
* - languageId < 256 => needs 8 bits
|
|
3035
|
-
* - unique color count < 512 => needs 9 bits
|
|
3036
|
-
*
|
|
3037
|
-
* The binary format is:
|
|
3038
|
-
* - -------------------------------------------
|
|
3039
|
-
* 3322 2222 2222 1111 1111 1100 0000 0000
|
|
3040
|
-
* 1098 7654 3210 9876 5432 1098 7654 3210
|
|
3041
|
-
* - -------------------------------------------
|
|
3042
|
-
* xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
|
|
3043
|
-
* bbbb bbbb bfff ffff ffFF FTTT LLLL LLLL
|
|
3044
|
-
* - -------------------------------------------
|
|
3045
|
-
* - L = LanguageId (8 bits)
|
|
3046
|
-
* - T = StandardTokenType (3 bits)
|
|
3047
|
-
* - F = FontStyle (3 bits)
|
|
3048
|
-
* - f = foreground color (9 bits)
|
|
3049
|
-
* - b = background color (9 bits)
|
|
3050
|
-
*/
|
|
3051
|
-
const MetadataConsts = {
|
|
3052
|
-
LANGUAGEID_MASK: 0b00000000000000000000000011111111,
|
|
3053
|
-
TOKEN_TYPE_MASK: 0b00000000000000000000001100000000,
|
|
3054
|
-
BALANCED_BRACKETS_MASK: 0b00000000000000000000010000000000,
|
|
3055
|
-
FONT_STYLE_MASK: 0b00000000000000000011100000000000,
|
|
3056
|
-
FOREGROUND_MASK: 0b00000000011111111100000000000000,
|
|
3057
|
-
BACKGROUND_MASK: 0b11111111100000000000000000000000,
|
|
3058
|
-
LANGUAGEID_OFFSET: 0,
|
|
3059
|
-
TOKEN_TYPE_OFFSET: 8,
|
|
3060
|
-
BALANCED_BRACKETS_OFFSET: 10,
|
|
3061
|
-
FONT_STYLE_OFFSET: 11,
|
|
3062
|
-
FOREGROUND_OFFSET: 15,
|
|
3063
|
-
BACKGROUND_OFFSET: 24,
|
|
3064
|
-
};
|
|
3065
|
-
class StackElementMetadata {
|
|
3066
|
-
static toBinaryStr(metadata) {
|
|
3067
|
-
let r = metadata.toString(2);
|
|
3068
|
-
while (r.length < 32)
|
|
3069
|
-
r = `0${r}`;
|
|
3070
|
-
return r;
|
|
3071
|
-
}
|
|
3072
|
-
// public static printMetadata(metadata: number): void {
|
|
3073
|
-
// const languageId = StackElementMetadata.getLanguageId(metadata)
|
|
3074
|
-
// const tokenType = StackElementMetadata.getTokenType(metadata)
|
|
3075
|
-
// const fontStyle = StackElementMetadata.getFontStyle(metadata)
|
|
3076
|
-
// const foreground = StackElementMetadata.getForeground(metadata)
|
|
3077
|
-
// const background = StackElementMetadata.getBackground(metadata)
|
|
3078
|
-
// console.log({
|
|
3079
|
-
// languageId,
|
|
3080
|
-
// tokenType,
|
|
3081
|
-
// fontStyle,
|
|
3082
|
-
// foreground,
|
|
3083
|
-
// background,
|
|
3084
|
-
// })
|
|
3085
|
-
// }
|
|
3086
|
-
static getLanguageId(metadata) {
|
|
3087
|
-
return (metadata & MetadataConsts.LANGUAGEID_MASK) >>> MetadataConsts.LANGUAGEID_OFFSET;
|
|
3088
|
-
}
|
|
3089
|
-
static getTokenType(metadata) {
|
|
3090
|
-
return (metadata & MetadataConsts.TOKEN_TYPE_MASK) >>> MetadataConsts.TOKEN_TYPE_OFFSET;
|
|
3091
|
-
}
|
|
3092
|
-
static getFontStyle(metadata) {
|
|
3093
|
-
return (metadata & MetadataConsts.FONT_STYLE_MASK) >>> MetadataConsts.FONT_STYLE_OFFSET;
|
|
3094
|
-
}
|
|
3095
|
-
static getForeground(metadata) {
|
|
3096
|
-
return (metadata & MetadataConsts.FOREGROUND_MASK) >>> MetadataConsts.FOREGROUND_OFFSET;
|
|
3097
|
-
}
|
|
3098
|
-
static getBackground(metadata) {
|
|
3099
|
-
return (metadata & MetadataConsts.BACKGROUND_MASK) >>> MetadataConsts.BACKGROUND_OFFSET;
|
|
3100
|
-
}
|
|
3101
|
-
static containsBalancedBrackets(metadata) {
|
|
3102
|
-
return (metadata & MetadataConsts.BALANCED_BRACKETS_MASK) !== 0;
|
|
3103
|
-
}
|
|
3104
|
-
static set(metadata, languageId, tokenType, fontStyle, foreground, background) {
|
|
3105
|
-
let _languageId = StackElementMetadata.getLanguageId(metadata);
|
|
3106
|
-
let _tokenType = StackElementMetadata.getTokenType(metadata);
|
|
3107
|
-
let _fontStyle = StackElementMetadata.getFontStyle(metadata);
|
|
3108
|
-
let _foreground = StackElementMetadata.getForeground(metadata);
|
|
3109
|
-
let _background = StackElementMetadata.getBackground(metadata);
|
|
3110
|
-
const _containsBalancedBracketsBit = StackElementMetadata.containsBalancedBrackets(metadata)
|
|
3111
|
-
? 1
|
|
3112
|
-
: 0;
|
|
3113
|
-
if (languageId !== 0)
|
|
3114
|
-
_languageId = languageId;
|
|
3115
|
-
if (tokenType !== 0 /* TemporaryStandardTokenType.Other */) {
|
|
3116
|
-
_tokenType
|
|
3117
|
-
= tokenType === 8 /* TemporaryStandardTokenType.MetaEmbedded */ ? 0 /* StandardTokenType.Other */ : tokenType;
|
|
3118
|
-
}
|
|
3119
|
-
if (fontStyle !== FontStyle.NotSet)
|
|
3120
|
-
_fontStyle = fontStyle;
|
|
3121
|
-
if (foreground !== 0)
|
|
3122
|
-
_foreground = foreground;
|
|
3123
|
-
if (background !== 0)
|
|
3124
|
-
_background = background;
|
|
3125
|
-
return (((_languageId << MetadataConsts.LANGUAGEID_OFFSET)
|
|
3126
|
-
| (_tokenType << MetadataConsts.TOKEN_TYPE_OFFSET)
|
|
3127
|
-
| (_fontStyle << MetadataConsts.FONT_STYLE_OFFSET)
|
|
3128
|
-
| (_containsBalancedBracketsBit << MetadataConsts.BALANCED_BRACKETS_OFFSET)
|
|
3129
|
-
| (_foreground << MetadataConsts.FOREGROUND_OFFSET)
|
|
3130
|
-
| (_background << MetadataConsts.BACKGROUND_OFFSET))
|
|
3131
|
-
>>> 0);
|
|
3132
|
-
}
|
|
3133
|
-
}
|
|
3134
|
-
|
|
3135
|
-
export { INITIAL, Registry$1 as Registry, StackElementMetadata, Theme };
|