Skip to content

Commit 8a45895

Browse files
committed
Prepare decodeTextMateToken for returning modeId (microsoft#14136)
1 parent 6790d0a commit 8a45895

1 file changed

Lines changed: 69 additions & 32 deletions

File tree

src/vs/editor/node/textMate/TMSyntax.ts

Lines changed: 69 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,53 @@ export class TMScopeDecodeData {
248248
}
249249
}
250250

251+
/**
252+
* Data associated with a stack of text mate scopes as part of decoding.
253+
*/
254+
export class TMScopesDecodeData {
255+
_tmScopesDecodeDataBrand: void;
256+
257+
/**
258+
* The last scope in the stack.
259+
*/
260+
public readonly scope: string;
261+
/**
262+
* The resolved tokens mask.
263+
* tokens[i] === true ===> token with id i is present.
264+
*/
265+
public readonly tokensMask: boolean[];
266+
/**
267+
* The resolved language.
268+
*/
269+
private readonly language: string;
270+
271+
constructor(parent: TMScopesDecodeData, scope: TMScopeDecodeData) {
272+
// 1) Inherit data from `parent`.
273+
let tokensMask: boolean[];
274+
let language: string;
275+
if (parent) {
276+
tokensMask = parent.tokensMask.slice(0);
277+
language = parent.language;
278+
} else {
279+
tokensMask = [];
280+
language = null;
281+
}
282+
283+
// 2) Overwrite with data from `scope`.
284+
let scopeTokenIds = scope.tokenIds;
285+
for (let i = 0, len = scopeTokenIds.length; i < len; i++) {
286+
tokensMask[scopeTokenIds[i]] = true;
287+
}
288+
if (scope.language) {
289+
language = scope.language;
290+
}
291+
292+
this.scope = scope.scope;
293+
this.tokensMask = tokensMask;
294+
this.language = language;
295+
}
296+
}
297+
251298
export class DecodeMap {
252299
_decodeMapBrand: void;
253300

@@ -256,15 +303,15 @@ export class DecodeMap {
256303
private readonly scopeToTokenIds: { [scope: string]: TMScopeDecodeData; };
257304
private readonly tokenToTokenId: { [token: string]: number; };
258305
private readonly tokenIdToToken: string[];
259-
prevToken: TMTokenDecodeData;
306+
prevTokenScopes: TMScopesDecodeData[];
260307

261308
constructor(scopeRegistry: TMScopeRegistry) {
262309
this.lastAssignedTokenId = 0;
263310
this.scopeRegistry = scopeRegistry;
264311
this.scopeToTokenIds = Object.create(null);
265312
this.tokenToTokenId = Object.create(null);
266313
this.tokenIdToToken = [null];
267-
this.prevToken = new TMTokenDecodeData([], []);
314+
this.prevTokenScopes = [];
268315
}
269316

270317
private _getTokenId(token: string): number {
@@ -313,18 +360,6 @@ export class DecodeMap {
313360
}
314361
}
315362

316-
export class TMTokenDecodeData {
317-
_tmTokenDecodeDataBrand: void;
318-
319-
public readonly scopes: string[];
320-
public readonly scopeTokensMaps: boolean[][];
321-
322-
constructor(scopes: string[], scopeTokensMaps: boolean[][]) {
323-
this.scopes = scopes;
324-
this.scopeTokensMaps = scopeTokensMaps;
325-
}
326-
}
327-
328363
function depth(stackElement: StackElement): number {
329364
let result = 0;
330365
while (stackElement) {
@@ -390,34 +425,36 @@ export function decodeTextMateTokens(line: string, offsetDelta: number, decodeMa
390425
}
391426

392427
export function decodeTextMateToken(decodeMap: DecodeMap, scopes: string[]): string {
393-
const prevTokenScopes = decodeMap.prevToken.scopes;
428+
if (scopes.length <= 1) {
429+
// fast case
430+
return '';
431+
}
432+
433+
const prevTokenScopes = decodeMap.prevTokenScopes;
394434
const prevTokenScopesLength = prevTokenScopes.length;
395-
const prevTokenScopeTokensMaps = decodeMap.prevToken.scopeTokensMaps;
396435

397-
let scopeTokensMaps: boolean[][] = [];
398-
let prevScopeTokensMaps: boolean[] = [];
436+
let resultScopes: TMScopesDecodeData[] = [null];
437+
let lastResultScope: TMScopesDecodeData = null;
438+
399439
let sameAsPrev = true;
400440
for (let level = 1/* deliberately skip scope 0*/, scopesLength = scopes.length; level < scopesLength; level++) {
401441
let scope = scopes[level];
402442

403-
if (sameAsPrev) {
404-
if (level < prevTokenScopesLength && prevTokenScopes[level] === scope) {
405-
prevScopeTokensMaps = prevTokenScopeTokensMaps[level];
406-
scopeTokensMaps[level] = prevScopeTokensMaps;
443+
if (sameAsPrev && level < prevTokenScopesLength) {
444+
let prevTokenScope = prevTokenScopes[level];
445+
if (prevTokenScope.scope === scope) {
446+
// continue reusing the results of the previous token's computation
447+
lastResultScope = prevTokenScope;
448+
resultScopes[level] = lastResultScope;
407449
continue;
408450
}
409-
sameAsPrev = false;
410451
}
452+
sameAsPrev = false;
411453

412-
let decodedScope = decodeMap.decodeTMScope(scope);
413-
let decodedScopeTokens = decodedScope.tokenIds;
414-
prevScopeTokensMaps = prevScopeTokensMaps.slice(0);
415-
for (let i = 0, len = decodedScopeTokens.length; i < len; i++) {
416-
prevScopeTokensMaps[decodedScopeTokens[i]] = true;
417-
}
418-
scopeTokensMaps[level] = prevScopeTokensMaps;
454+
lastResultScope = new TMScopesDecodeData(lastResultScope, decodeMap.decodeTMScope(scope));
455+
resultScopes[level] = lastResultScope;
419456
}
420457

421-
decodeMap.prevToken = new TMTokenDecodeData(scopes, scopeTokensMaps);
422-
return decodeMap.getToken(prevScopeTokensMaps);
458+
decodeMap.prevTokenScopes = resultScopes;
459+
return decodeMap.getToken(lastResultScope.tokensMask);
423460
}

0 commit comments

Comments
 (0)