sparseMultilineTokens.ts ×33

Frontier kind: Code frontier

unlabeled · c_2a5c8f0bf420

20 tests · 39071 LOC · 240 files · introduces 0 tests · 153 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
35 ranges153 lines · 2 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
4522 ranges39071 lines · 240 files · Browse complete extent
All tests (intent)
20 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

2 files ranked by introduced lines: 153 introduced LOC across 35 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/editor/common/tokens/sparseMultilineTokens.ts 137 introduced LOC · 33 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- sparseMultilineTokens.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { CharCode } from '../../../base/common/charCode.js';
7 > import { Position } from '../core/position.js';
8 > import { IRange, Range } from '../core/range.js';
9 > import { countEOL } from '../core/misc/eolCounter.js';
10 > import { ITextModel } from '../model.js';
11 > import { RateLimiter } from './common.js';
12 >
13 > /**
14 > * Represents sparse tokens over a contiguous range of lines.
15 > */
16 > export class SparseMultilineTokens {
17 >
18 > public static create(startLineNumber: number, tokens: Uint32Array): SparseMultilineTokens {
19 > return new SparseMultilineTokens(startLineNumber, new SparseMultilineTokensStorage(tokens));
20 > }
21 >
22 > private _startLineNumber: number;
23 > private _endLineNumber: number;
24 > private readonly _tokens: SparseMultilineTokensStorage;
25 >
26 > /**
27 > * (Inclusive) start line number for these tokens.
28 > */
29 > public get startLineNumber(): number {
30 return this._startLineNumber;
31 }
33 > /**
34 > * (Inclusive) end line number for these tokens.
35 > */
36 > public get endLineNumber(): number {
37 return this._endLineNumber;
38 }
40 > private constructor(startLineNumber: number, tokens: SparseMultilineTokensStorage) {
41 > this._startLineNumber = startLineNumber;
42 > this._tokens = tokens;
43 > this._endLineNumber = this._startLineNumber + this._tokens.getMaxDeltaLine();
44 > }
45 >
46 > public toString(): string {
47 return this._tokens.toString(this._startLineNumber);
48 }
50 > private _updateEndLineNumber(): void {
51 this._endLineNumber = this._startLineNumber + this._tokens.getMaxDeltaLine();
52 }
54 > public isEmpty(): boolean {
55 return this._tokens.isEmpty();
56 }
58 > public getLineTokens(lineNumber: number): SparseLineTokens | null {
59 if (this._startLineNumber <= lineNumber && lineNumber <= this._endLineNumber) {
60 return this._tokens.getLineTokens(lineNumber - this._startLineNumber);
62 return null;
63 }
65 > public getRange(): Range | null {
66 const deltaRange = this._tokens.getRange();
67 if (!deltaRange) {
70 return new Range(this._startLineNumber + deltaRange.startLineNumber, deltaRange.startColumn, this._startLineNumber + deltaRange.endLineNumber, deltaRange.endColumn);
71 }
73 > public removeTokens(range: Range): void {
74 const startLineIndex = range.startLineNumber - this._startLineNumber;
75 const endLineIndex = range.endLineNumber - this._startLineNumber;
78 this._updateEndLineNumber();
79 }
81 > public split(range: Range): [SparseMultilineTokens, SparseMultilineTokens] {
82 // split tokens to two:
83 // a) all the tokens before `range`
89 return [new SparseMultilineTokens(this._startLineNumber, a), new SparseMultilineTokens(this._startLineNumber + bDeltaLine, b)];
90 }
92 > public applyEdit(range: IRange, text: string): void {
93 const [eolCount, firstLineLength, lastLineLength] = countEOL(text);
94 this.acceptEdit(range, eolCount, firstLineLength, lastLineLength, text.length > 0 ? text.charCodeAt(0) : CharCode.Null);
95 }
97 > public acceptEdit(range: IRange, eolCount: number, firstLineLength: number, lastLineLength: number, firstCharCode: number): void {
98 this._acceptDeleteRange(range);
99 this._acceptInsertText(new Position(range.startLineNumber, range.startColumn), eolCount, firstLineLength, lastLineLength, firstCharCode);
100 this._updateEndLineNumber();
101 }
103 > private _acceptDeleteRange(range: IRange): void {
104 if (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) {
105 // Nothing to delete
140 }
141 }
143 > private _acceptInsertText(position: Position, eolCount: number, firstLineLength: number, lastLineLength: number, firstCharCode: number): void {
144
145 if (eolCount === 0 && firstLineLength === 0) {
165 this._tokens.acceptInsertText(lineIndex, position.column - 1, eolCount, firstLineLength, lastLineLength, firstCharCode);
166 }
168 > public reportIfInvalid(model: ITextModel): void {
169 this._tokens.reportIfInvalid(model, this._startLineNumber);
170 }
172 >
173 > class SparseMultilineTokensStorage {
174 > /**
175 > * The encoding of tokens is:
176 > * 4*i deltaLine (from `startLineNumber`)
177 > * 4*i+1 startCharacter (from the line start)
178 > * 4*i+2 endCharacter (from the line start)
179 > * 4*i+3 metadata
180 > */
181 > private readonly _tokens: Uint32Array;
182 > private _tokenCount: number;
183 >
184 > constructor(tokens: Uint32Array) {
185 > this._tokens = tokens;
186 > this._tokenCount = tokens.length / 4;
187 > }
188 >
189 > public toString(startLineNumber: number): string {
190 const pieces: string[] = [];
191 for (let i = 0; i < this._tokenCount; i++) {
194 return `[${pieces.join(',')}]`;
195 }
197 > public getMaxDeltaLine(): number {
198 > const tokenCount = this._getTokenCount();
199 > if (tokenCount === 0) {
200 return -1;
201 }
202 > return this._getDeltaLine(tokenCount - 1); sparseMultilineTokens.ts
203 > }
204 >
205 > public getRange(): Range | null {
206 const tokenCount = this._getTokenCount();
207 if (tokenCount === 0) {
213 return new Range(0, startChar + 1, maxDeltaLine, endChar + 1);
214 }
216 > private _getTokenCount(): number {
217 > return this._tokenCount;
218 > }
219 >
220 > private _getDeltaLine(tokenIndex: number): number {
221 > return this._tokens[4 * tokenIndex];
222 > }
223 >
224 > private _getStartCharacter(tokenIndex: number): number {
225 return this._tokens[4 * tokenIndex + 1];
226 }
228 > private _getEndCharacter(tokenIndex: number): number {
229 return this._tokens[4 * tokenIndex + 2];
230 }
232 > public isEmpty(): boolean {
233 return (this._getTokenCount() === 0);
234 }
236 > public getLineTokens(deltaLine: number): SparseLineTokens | null {
237 let low = 0;
238 let high = this._getTokenCount() - 1;
265 return null;
266 }
268 > public clear(): void {
269 this._tokenCount = 0;
270 }
272 > public removeTokens(startDeltaLine: number, startChar: number, endDeltaLine: number, endChar: number): number {
273 const tokens = this._tokens;
274 const tokenCount = this._tokenCount;
311 return firstDeltaLine;
312 }
314 > public split(startDeltaLine: number, startChar: number, endDeltaLine: number, endChar: number): [SparseMultilineTokensStorage, SparseMultilineTokensStorage, number] {
315 const tokens = this._tokens;
316 const tokenCount = this._tokenCount;
350 return [new SparseMultilineTokensStorage(new Uint32Array(aTokens)), new SparseMultilineTokensStorage(new Uint32Array(bTokens)), destFirstDeltaLine];
351 }
353 > public acceptDeleteRange(horizontalShiftForFirstLineTokens: number, startDeltaLine: number, startCharacter: number, endDeltaLine: number, endCharacter: number): void {
354 // This is a bit complex, here are the cases I used to think about this:
355 //
483 this._tokenCount = newTokenCount;
484 }
486 > public acceptInsertText(deltaLine: number, character: number, eolCount: number, firstLineLength: number, lastLineLength: number, firstCharCode: number): void {
487 // Here are the cases I used to think about this:
488 //
568 }
569 }
571 > private static _rateLimiter = new RateLimiter(10 / 60); // limit to 10 times per minute
572 >
573 > public reportIfInvalid(model: ITextModel, startLineNumber: number): void {
574 for (let i = 0; i < this._tokenCount; i++) {
575 const lineNumber = this._getDeltaLine(i) + startLineNumber;
590 }
591 }
593 >
594 > export class SparseLineTokens {
595 >
596 > private readonly _tokens: Uint32Array;
597 >
598 > constructor(tokens: Uint32Array) {
599 this._tokens = tokens;
600 }
602 > public getCount(): number {
603 return this._tokens.length / 4;
604 }
606 > public getStartCharacter(tokenIndex: number): number {
607 return this._tokens[4 * tokenIndex + 1];
608 }
610 > public getEndCharacter(tokenIndex: number): number {
611 return this._tokens[4 * tokenIndex + 2];
612 }
614 > public getMetadata(tokenIndex: number): number {
615 return this._tokens[4 * tokenIndex + 3];
616 }
src/vs/editor/common/tokens/common.ts 16 introduced LOC · 2 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- common.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > export class RateLimiter {
7 > private _lastRun: number;
8 > private readonly _minimumTimeBetweenRuns: number;
9 >
10 > constructor(public readonly timesPerSecond: number = 5) {
11 > this._lastRun = 0;
12 > this._minimumTimeBetweenRuns = 1000 / timesPerSecond;
13 > }
14 >
15 > public runIfNotLimited(callback: () => void): void {
16 const now = Date.now();
17 if (now - this._lastRun >= this._minimumTimeBetweenRuns) {