Path: blob/main/src/vs/editor/common/tokens/tokenWithTextArray.ts
3294 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { OffsetRange } from '../core/ranges/offsetRange.js';6import { ILanguageIdCodec } from '../languages.js';7import { LineTokens } from './lineTokens.js';89/**10* This class represents a sequence of tokens.11* Conceptually, each token has a length and a metadata number.12* A token array might be used to annotate a string with metadata.13* Use {@link TokenWithTextArrayBuilder} to efficiently create a token array.14*15* TODO: Make this class more efficient (e.g. by using a Int32Array).16*/17export class TokenWithTextArray {18public static fromLineTokens(lineTokens: LineTokens): TokenWithTextArray {19const tokenInfo: TokenWithTextInfo[] = [];20for (let i = 0; i < lineTokens.getCount(); i++) {21tokenInfo.push(new TokenWithTextInfo(lineTokens.getTokenText(i), lineTokens.getMetadata(i)));22}23return TokenWithTextArray.create(tokenInfo);24}2526public static create(tokenInfo: TokenWithTextInfo[]): TokenWithTextArray {27return new TokenWithTextArray(tokenInfo);28}2930private constructor(31private readonly _tokenInfo: TokenWithTextInfo[],32) { }3334public toLineTokens(decoder: ILanguageIdCodec): LineTokens {35return LineTokens.createFromTextAndMetadata(this.map((_r, t) => ({ text: t.text, metadata: t.metadata })), decoder);36}3738public forEach(cb: (range: OffsetRange, tokenInfo: TokenWithTextInfo) => void): void {39let lengthSum = 0;40for (const tokenInfo of this._tokenInfo) {41const range = new OffsetRange(lengthSum, lengthSum + tokenInfo.text.length);42cb(range, tokenInfo);43lengthSum += tokenInfo.text.length;44}45}4647public map<T>(cb: (range: OffsetRange, tokenInfo: TokenWithTextInfo) => T): T[] {48const result: T[] = [];49let lengthSum = 0;50for (const tokenInfo of this._tokenInfo) {51const range = new OffsetRange(lengthSum, lengthSum + tokenInfo.text.length);52result.push(cb(range, tokenInfo));53lengthSum += tokenInfo.text.length;54}55return result;56}5758public slice(range: OffsetRange): TokenWithTextArray {59const result: TokenWithTextInfo[] = [];60let lengthSum = 0;61for (const tokenInfo of this._tokenInfo) {62const tokenStart = lengthSum;63const tokenEndEx = tokenStart + tokenInfo.text.length;64if (tokenEndEx > range.start) {65if (tokenStart >= range.endExclusive) {66break;67}6869const deltaBefore = Math.max(0, range.start - tokenStart);70const deltaAfter = Math.max(0, tokenEndEx - range.endExclusive);7172result.push(new TokenWithTextInfo(tokenInfo.text.slice(deltaBefore, tokenInfo.text.length - deltaAfter), tokenInfo.metadata));73}7475lengthSum += tokenInfo.text.length;76}77return TokenWithTextArray.create(result);78}7980public append(other: TokenWithTextArray): TokenWithTextArray {81const result: TokenWithTextInfo[] = this._tokenInfo.concat(other._tokenInfo);82return TokenWithTextArray.create(result);83}84}8586export type TokenMetadata = number;8788export class TokenWithTextInfo {89constructor(90public readonly text: string,91public readonly metadata: TokenMetadata,92) { }93}9495/**96* TODO: Make this class more efficient (e.g. by using a Int32Array).97*/98export class TokenWithTextArrayBuilder {99private readonly _tokens: TokenWithTextInfo[] = [];100101public add(text: string, metadata: TokenMetadata): void {102this._tokens.push(new TokenWithTextInfo(text, metadata));103}104105public build(): TokenWithTextArray {106return TokenWithTextArray.create(this._tokens);107}108}109110111