Atlas › Test

monospaceLineBreaksComputer.test|title=Editor ViewModel - MonospaceLineBreaksComputer issue #152773: Word wrap algorithm behaves differently with bracket followed by comma|occurrence=1

Exact test identity: mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/editor/test/common/viewModel/monospaceLineBreaksComputer.test|title=Editor ViewModel - MonospaceLineBreaksComputer issue #152773: Word wrap algorithm behaves differently with bracket followed by comma|occurrence=1

Package
mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/editor/test/common/viewModel
Suite / test hierarchy
monospaceLineBreaksComputer.test|title=Editor ViewModel - MonospaceLineBreaksComputer issue #152773: Word wrap algorithm behaves differently with bracket followed by comma|occurrence=1
Test
monospaceLineBreaksComputer.test|title=Editor ViewModel - MonospaceLineBreaksComputer issue #152773: Word wrap algorithm behaves differently with bracket followed by comma|occurrence=1
Introduced at
monospaceLineBreaksComputer.test|title=Editor ViewModel - MonospaceLineBreaksComputer issue #33366: Word wrap algorithm behaves differently around punctuation|occurrence=1, monospaceLineBreaksComputer.test|title=Editor ViewModel - MonospaceLineBreaksComputer issue #152773: Word wrap algorithm behaves differently with bracket followed by comma|occurrence=1 Frontier kind: Test frontier
Covered ranges
1359
Covered lines
15405
Covered files
44

Co-introduced tests

1 other test enter at the same concept.

Covered source

Expand a file to inspect source; the > gutter marks covered lines.

src/vs/editor/common/config/editorOptions.ts 5717 covered LOC · 92 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- editorOptions.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 * as arrays from '../../../base/common/arrays.js';
7 > import { IMarkdownString } from '../../../base/common/htmlContent.js';
8 > import { IJSONSchema } from '../../../base/common/jsonSchema.js';
9 > import * as objects from '../../../base/common/objects.js';
10 > import * as platform from '../../../base/common/platform.js';
11 > import { ScrollbarVisibility } from '../../../base/common/scrollable.js';
12 > import { Constants } from '../../../base/common/uint.js';
13 > import { EDITOR_FONT_DEFAULTS, FONT_VARIATION_OFF, FONT_VARIATION_TRANSLATE, FontInfo } from './fontInfo.js';
14 > import { EDITOR_MODEL_DEFAULTS } from '../core/misc/textModelDefaults.js';
15 > import { USUAL_WORD_SEPARATORS } from '../core/wordHelper.js';
16 > import * as nls from '../../../nls.js';
17 > import { AccessibilitySupport } from '../../../platform/accessibility/common/accessibility.js';
18 > import { IConfigurationPropertySchema } from '../../../platform/configuration/common/configurationRegistry.js';
19 >
20 > //#region typed options
21 >
22 > /**
23 > * Configuration options for auto closing quotes and brackets
24 > */
25 > export type EditorAutoClosingStrategy = 'always' | 'languageDefined' | 'beforeWhitespace' | 'never';
26 >
27 > /**
28 > * Configuration options for auto wrapping quotes and brackets
29 > */
30 > export type EditorAutoSurroundStrategy = 'languageDefined' | 'quotes' | 'brackets' | 'never';
31 >
32 > /**
33 > * Configuration options for typing over closing quotes or brackets
34 > */
35 > export type EditorAutoClosingEditStrategy = 'always' | 'auto' | 'never';
36 >
37 > type Unknown<T> = { [K in keyof T]: unknown };
38 >
39 > /**
40 > * Configuration options for auto indentation in the editor
41 > */
42 > export const enum EditorAutoIndentStrategy {
43 > None = 0,
44 > Keep = 1,
45 > Brackets = 2,
46 > Advanced = 3,
47 > Full = 4
48 > }
49 >
50 > /**
51 > * Configuration options for the editor.
52 > */
53 > export interface IEditorOptions {
54 > /**
55 > * This editor is used inside a diff editor.
56 > */
57 > inDiffEditor?: boolean;
58 > /**
59 > * This editor is allowed to use variable line heights.
60 > */
61 > allowVariableLineHeights?: boolean;
62 > /**
63 > * This editor is allowed to use variable font-sizes and font-families
64 > */
65 > allowVariableFonts?: boolean;
66 > /**
67 > * This editor is allowed to use variable font-sizes and font-families in accessibility mode
68 > */
69 > allowVariableFontsInAccessibilityMode?: boolean;
70 > /**
71 > * The aria label for the editor's textarea (when it is focused).
72 > */
73 > ariaLabel?: string;
74 >
75 > /**
76 > * Whether the aria-required attribute should be set on the editors textarea.
77 > */
78 > ariaRequired?: boolean;
79 > /**
80 > * Control whether a screen reader announces inline suggestion content immediately.
81 > */
82 > screenReaderAnnounceInlineSuggestion?: boolean;
83 > /**
84 > * The `tabindex` property of the editor's textarea
85 > */
86 > tabIndex?: number;
87 > /**
88 > * Render vertical lines at the specified columns.
89 > * Defaults to empty array.
90 > */
91 > rulers?: (number | IRulerOption)[];
92 > /**
93 > * Locales used for segmenting lines into words when doing word related navigations or operations.
94 > *
95 > * Specify the BCP 47 language tag of the word you wish to recognize (e.g., ja, zh-CN, zh-Hant-TW, etc.).
96 > * Defaults to empty array
97 > */
98 > wordSegmenterLocales?: string | string[];
99 > /**
100 > * A string containing the word separators used when doing word navigation.
101 > * Defaults to `~!@#$%^&*()-=+[{]}\\|;:\'",.<>/?
102 > */
103 > wordSeparators?: string;
104 > /**
105 > * Enable Linux primary clipboard.
106 > * Defaults to true.
107 > */
108 > selectionClipboard?: boolean;
109 > /**
110 > * Control the rendering of line numbers.
111 > * If it is a function, it will be invoked when rendering a line number and the return value will be rendered.
112 > * Otherwise, if it is a truthy, line numbers will be rendered normally (equivalent of using an identity function).
113 > * Otherwise, line numbers will not be rendered.
114 > * Defaults to `on`.
115 > */
116 > lineNumbers?: LineNumbersType;
117 > /**
118 > * Controls the minimal number of visible leading and trailing lines surrounding the cursor.
119 > * Defaults to 0.
120 > */
121 > cursorSurroundingLines?: number;
122 > /**
123 > * Controls when `cursorSurroundingLines` should be enforced
124 > * Defaults to `default`, `cursorSurroundingLines` is not enforced when cursor position is changed
125 > * by mouse.
126 > */
127 > cursorSurroundingLinesStyle?: 'default' | 'all';
128 > /**
129 > * Render last line number when the file ends with a newline.
130 > * Defaults to 'on' for Windows and macOS and 'dimmed' for Linux.
131 > */
132 > renderFinalNewline?: 'on' | 'off' | 'dimmed';
133 > /**
134 > * Remove unusual line terminators like LINE SEPARATOR (LS), PARAGRAPH SEPARATOR (PS).
135 > * Defaults to 'prompt'.
136 > */
137 > unusualLineTerminators?: 'auto' | 'off' | 'prompt';
138 > /**
139 > * Should the corresponding line be selected when clicking on the line number?
140 > * Defaults to true.
141 > */
142 > selectOnLineNumbers?: boolean;
143 > /**
144 > * Control the width of line numbers, by reserving horizontal space for rendering at least an amount of digits.
145 > * Defaults to 5.
146 > */
147 > lineNumbersMinChars?: number;
148 > /**
149 > * Enable the rendering of the glyph margin.
150 > * Defaults to true in vscode and to false in monaco-editor.
151 > */
152 > glyphMargin?: boolean;
153 > /**
154 > * The width reserved for line decorations (in px).
155 > * Line decorations are placed between line numbers and the editor content.
156 > * You can pass in a string in the format floating point followed by "ch". e.g. 1.3ch.
157 > * Defaults to 10.
158 > */
159 > lineDecorationsWidth?: number | string;
160 > /**
161 > * When revealing the cursor, a virtual padding (px) is added to the cursor, turning it into a rectangle.
162 > * This virtual padding ensures that the cursor gets revealed before hitting the edge of the viewport.
163 > * Defaults to 30 (px).
164 > */
165 > revealHorizontalRightPadding?: number;
166 > /**
167 > * Render the editor selection with rounded borders.
168 > * Defaults to true.
169 > */
170 > roundedSelection?: boolean;
171 > /**
172 > * Class name to be added to the editor.
173 > */
174 > extraEditorClassName?: string;
175 > /**
176 > * Should the editor be read only. See also `domReadOnly`.
177 > * Defaults to false.
178 > */
179 > readOnly?: boolean;
180 > /**
181 > * The message to display when the editor is readonly.
182 > */
183 > readOnlyMessage?: IMarkdownString;
184 > /**
185 > * Should the textarea used for input use the DOM `readonly` attribute.
186 > * Defaults to false.
187 > */
188 > domReadOnly?: boolean;
189 > /**
190 > * Enable linked editing.
191 > * Defaults to false.
192 > */
193 > linkedEditing?: boolean;
194 > /**
195 > * deprecated, use linkedEditing instead
196 > */
197 > renameOnType?: boolean;
198 > /**
199 > * Should the editor render validation decorations.
200 > * Defaults to editable.
201 > */
202 > renderValidationDecorations?: 'editable' | 'on' | 'off';
203 > /**
204 > * Control the behavior and rendering of the scrollbars.
205 > */
206 > scrollbar?: IEditorScrollbarOptions;
207 > /**
208 > * Control the behavior of sticky scroll options
209 > */
210 > stickyScroll?: IEditorStickyScrollOptions;
211 > /**
212 > * Control the behavior and rendering of the minimap.
213 > */
214 > minimap?: IEditorMinimapOptions;
215 > /**
216 > * Control the behavior of the find widget.
217 > */
218 > find?: IEditorFindOptions;
219 > /**
220 > * Display overflow widgets as `fixed`.
221 > * Defaults to `false`.
222 > */
223 > fixedOverflowWidgets?: boolean;
224 > /**
225 > * Allow content widgets and overflow widgets to overflow the editor viewport.
226 > * Defaults to `true`.
227 > */
228 > allowOverflow?: boolean;
229 > /**
230 > * The number of vertical lanes the overview ruler should render.
231 > * Defaults to 3.
232 > */
233 > overviewRulerLanes?: number;
234 > /**
235 > * Controls if a border should be drawn around the overview ruler.
236 > * Defaults to `true`.
237 > */
238 > overviewRulerBorder?: boolean;
239 > /**
240 > * Control the cursor animation style, possible values are 'blink', 'smooth', 'phase', 'expand' and 'solid'.
241 > * Defaults to 'blink'.
242 > */
243 > cursorBlinking?: 'blink' | 'smooth' | 'phase' | 'expand' | 'solid';
244 > /**
245 > * Zoom the font in the editor when using the mouse wheel in combination with holding Ctrl.
246 > * Defaults to false.
247 > */
248 > mouseWheelZoom?: boolean;
249 > /**
250 > * Control the mouse pointer style, either 'text' or 'default' or 'copy'
251 > * Defaults to 'text'
252 > */
253 > mouseStyle?: 'text' | 'default' | 'copy';
254 > /**
255 > * Enable smooth caret animation.
256 > * Defaults to 'off'.
257 > */
258 > cursorSmoothCaretAnimation?: 'off' | 'explicit' | 'on';
259 > /**
260 > * Control the cursor style in insert mode.
261 > * Defaults to 'line'.
262 > */
263 > cursorStyle?: 'line' | 'block' | 'underline' | 'line-thin' | 'block-outline' | 'underline-thin';
264 > /**
265 > * Control the cursor style in overtype mode.
266 > * Defaults to 'block'.
267 > */
268 > overtypeCursorStyle?: 'line' | 'block' | 'underline' | 'line-thin' | 'block-outline' | 'underline-thin';
269 > /**
270 > * Controls whether paste in overtype mode should overwrite or insert.
271 > */
272 > overtypeOnPaste?: boolean;
273 > /**
274 > * Control the width of the cursor when cursorStyle is set to 'line'
275 > */
276 > cursorWidth?: number;
277 > /**
278 > * Control the height of the cursor when cursorStyle is set to 'line'
279 > */
280 > cursorHeight?: number;
281 > /**
282 > * Enable font ligatures.
283 > * Defaults to false.
284 > */
285 > fontLigatures?: boolean | string;
286 > /**
287 > * Enable font variations.
288 > * Defaults to false.
289 > */
290 > fontVariations?: boolean | string;
291 > /**
292 > * Controls whether to use default color decorations or not using the default document color provider
293 > */
294 > defaultColorDecorators?: 'auto' | 'always' | 'never';
295 > /**
296 > * Disable the use of `transform: translate3d(0px, 0px, 0px)` for the editor margin and lines layers.
297 > * The usage of `transform: translate3d(0px, 0px, 0px)` acts as a hint for browsers to create an extra layer.
298 > * Defaults to false.
299 > */
300 > disableLayerHinting?: boolean;
301 > /**
302 > * Disable the optimizations for monospace fonts.
303 > * Defaults to false.
304 > */
305 > disableMonospaceOptimizations?: boolean;
306 > /**
307 > * Should the cursor be hidden in the overview ruler.
308 > * Defaults to false.
309 > */
310 > hideCursorInOverviewRuler?: boolean;
311 > /**
312 > * Enable that scrolling can go one screen size after the last line.
313 > * Defaults to true.
314 > */
315 > scrollBeyondLastLine?: boolean;
316 > /**
317 > * Scroll editor on middle click
318 > */
319 > scrollOnMiddleClick?: boolean;
320 > /**
321 > * Enable that scrolling can go beyond the last column by a number of columns.
322 > * Defaults to 5.
323 > */
324 > scrollBeyondLastColumn?: number;
325 > /**
326 > * Enable that the editor animates scrolling to a position.
327 > * Defaults to false.
328 > */
329 > smoothScrolling?: boolean;
330 > /**
331 > * Enable that the editor will install a ResizeObserver to check if its container dom node size has changed.
332 > * Defaults to false.
333 > */
334 > automaticLayout?: boolean;
335 > /**
336 > * Control the wrapping of the editor.
337 > * When `wordWrap` = "off", the lines will never wrap.
338 > * When `wordWrap` = "on", the lines will wrap at the viewport width.
339 > * When `wordWrap` = "wordWrapColumn", the lines will wrap at `wordWrapColumn`.
340 > * When `wordWrap` = "bounded", the lines will wrap at min(viewport width, wordWrapColumn).
341 > * Defaults to "off".
342 > */
343 > wordWrap?: 'off' | 'on' | 'wordWrapColumn' | 'bounded';
344 > /**
345 > * Override the `wordWrap` setting.
346 > */
347 > wordWrapOverride1?: 'off' | 'on' | 'inherit';
348 > /**
349 > * Override the `wordWrapOverride1` setting.
350 > */
351 > wordWrapOverride2?: 'off' | 'on' | 'inherit';
352 > /**
353 > * Control the wrapping of the editor.
354 > * When `wordWrap` = "off", the lines will never wrap.
355 > * When `wordWrap` = "on", the lines will wrap at the viewport width.
356 > * When `wordWrap` = "wordWrapColumn", the lines will wrap at `wordWrapColumn`.
357 > * When `wordWrap` = "bounded", the lines will wrap at min(viewport width, wordWrapColumn).
358 > * Defaults to 80.
359 > */
360 > wordWrapColumn?: number;
361 > /**
362 > * Control indentation of wrapped lines. Can be: 'none', 'same', 'indent' or 'deepIndent'.
363 > * Defaults to 'same' in vscode and to 'none' in monaco-editor.
364 > */
365 > wrappingIndent?: 'none' | 'same' | 'indent' | 'deepIndent';
366 > /**
367 > * Controls the wrapping strategy to use.
368 > * Defaults to 'simple'.
369 > */
370 > wrappingStrategy?: 'simple' | 'advanced';
371 > /**
372 > * Create a softwrap on every quoted "\n" literal.
373 > * Defaults to false.
374 > */
375 > wrapOnEscapedLineFeeds?: boolean;
376 > /**
377 > * Configure word wrapping characters. A break will be introduced before these characters.
378 > */
379 > wordWrapBreakBeforeCharacters?: string;
380 > /**
381 > * Configure word wrapping characters. A break will be introduced after these characters.
382 > */
383 > wordWrapBreakAfterCharacters?: string;
384 > /**
385 > * Sets whether line breaks appear wherever the text would otherwise overflow its content box.
386 > * When wordBreak = 'normal', Use the default line break rule.
387 > * When wordBreak = 'keepAll', Word breaks should not be used for Chinese/Japanese/Korean (CJK) text. Non-CJK text behavior is the same as for normal.
388 > */
389 > wordBreak?: 'normal' | 'keepAll';
390 > /**
391 > * Performance guard: Stop rendering a line after x characters.
392 > * Defaults to 10000.
393 > * Use -1 to never stop rendering
394 > */
395 > stopRenderingLineAfter?: number;
396 > /**
397 > * Configure the editor's hover.
398 > */
399 > hover?: IEditorHoverOptions;
400 > /**
401 > * Enable detecting links and making them clickable.
402 > * Defaults to true.
403 > */
404 > links?: boolean;
405 > /**
406 > * Enable inline color decorators and color picker rendering.
407 > */
408 > colorDecorators?: boolean;
409 > /**
410 > * Controls what is the condition to spawn a color picker from a color dectorator
411 > */
412 > colorDecoratorsActivatedOn?: 'clickAndHover' | 'click' | 'hover';
413 > /**
414 > * Controls the max number of color decorators that can be rendered in an editor at once.
415 > */
416 > colorDecoratorsLimit?: number;
417 > /**
418 > * Control the behaviour of comments in the editor.
419 > */
420 > comments?: IEditorCommentsOptions;
421 > /**
422 > * Enable custom contextmenu.
423 > * Defaults to true.
424 > */
425 > contextmenu?: boolean;
426 > /**
427 > * A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.
428 > * Defaults to 1.
429 > */
430 > mouseWheelScrollSensitivity?: number;
431 > /**
432 > * FastScrolling mulitplier speed when pressing `Alt`
433 > * Defaults to 5.
434 > */
435 > fastScrollSensitivity?: number;
436 > /**
437 > * Enable that the editor scrolls only the predominant axis. Prevents horizontal drift when scrolling vertically on a trackpad.
438 > * Defaults to true.
439 > */
440 > scrollPredominantAxis?: boolean;
441 > /**
442 > * Make scrolling inertial - mostly useful with touchpad on linux.
443 > */
444 > inertialScroll?: boolean;
445 > /**
446 > * Enable that the selection with the mouse and keys is doing column selection.
447 > * Defaults to false.
448 > */
449 > columnSelection?: boolean;
450 > /**
451 > * The modifier to be used to add multiple cursors with the mouse.
452 > * Defaults to 'alt'
453 > */
454 > multiCursorModifier?: 'ctrlCmd' | 'alt';
455 > /**
456 > * Merge overlapping selections.
457 > * Defaults to true
458 > */
459 > multiCursorMergeOverlapping?: boolean;
460 > /**
461 > * Configure the behaviour when pasting a text with the line count equal to the cursor count.
462 > * Defaults to 'spread'.
463 > */
464 > multiCursorPaste?: 'spread' | 'full';
465 > /**
466 > * Controls the max number of text cursors that can be in an active editor at once.
467 > */
468 > multiCursorLimit?: number;
469 > /**
470 > * Enables middle mouse button to open links and Go To Definition
471 > */
472 > mouseMiddleClickAction?: MouseMiddleClickAction;
473 > /**
474 > * Configure the editor's accessibility support.
475 > * Defaults to 'auto'. It is best to leave this to 'auto'.
476 > */
477 > accessibilitySupport?: 'auto' | 'off' | 'on';
478 > /**
479 > * Controls the number of lines in the editor that can be read out by a screen reader
480 > */
481 > accessibilityPageSize?: number;
482 > /**
483 > * Suggest options.
484 > */
485 > suggest?: ISuggestOptions;
486 > inlineSuggest?: IInlineSuggestOptions;
487 > /**
488 > * Smart select options.
489 > */
490 > smartSelect?: ISmartSelectOptions;
491 > /**
492 > *
493 > */
494 > gotoLocation?: IGotoLocationOptions;
495 > /**
496 > * Enable quick suggestions (shadow suggestions)
497 > * Defaults to true.
498 > */
499 > quickSuggestions?: boolean | QuickSuggestionsValue | IQuickSuggestionsOptions;
500 > /**
501 > * Quick suggestions show delay (in ms)
502 > * Defaults to 10 (ms)
503 > */
504 > quickSuggestionsDelay?: number;
505 > /**
506 > * Controls the spacing around the editor.
507 > */
508 > padding?: IEditorPaddingOptions;
509 > /**
510 > * Parameter hint options.
511 > */
512 > parameterHints?: IEditorParameterHintOptions;
513 > /**
514 > * Options for auto closing brackets.
515 > * Defaults to language defined behavior.
516 > */
517 > autoClosingBrackets?: EditorAutoClosingStrategy;
518 > /**
519 > * Options for auto closing comments.
520 > * Defaults to language defined behavior.
521 > */
522 > autoClosingComments?: EditorAutoClosingStrategy;
523 > /**
524 > * Options for auto closing quotes.
525 > * Defaults to language defined behavior.
526 > */
527 > autoClosingQuotes?: EditorAutoClosingStrategy;
528 > /**
529 > * Options for pressing backspace near quotes or bracket pairs.
530 > */
531 > autoClosingDelete?: EditorAutoClosingEditStrategy;
532 > /**
533 > * Options for typing over closing quotes or brackets.
534 > */
535 > autoClosingOvertype?: EditorAutoClosingEditStrategy;
536 > /**
537 > * Options for auto surrounding.
538 > * Defaults to always allowing auto surrounding.
539 > */
540 > autoSurround?: EditorAutoSurroundStrategy;
541 > /**
542 > * Controls whether the editor should automatically adjust the indentation when users type, paste, move or indent lines.
543 > * Defaults to advanced.
544 > */
545 > autoIndent?: 'none' | 'keep' | 'brackets' | 'advanced' | 'full';
546 > /**
547 > * Boolean which controls whether to autoindent on paste
548 > */
549 > autoIndentOnPaste?: boolean;
550 > /**
551 > * Boolean which controls whether to autoindent on paste within a string when autoIndentOnPaste is enabled.
552 > */
553 > autoIndentOnPasteWithinString?: boolean;
554 > /**
555 > * Emulate selection behaviour of tab characters when using spaces for indentation.
556 > * This means selection will stick to tab stops.
557 > */
558 > stickyTabStops?: boolean;
559 > /**
560 > * Enable format on type.
561 > * Defaults to false.
562 > */
563 > formatOnType?: boolean;
564 > /**
565 > * Enable format on paste.
566 > * Defaults to false.
567 > */
568 > formatOnPaste?: boolean;
569 > /**
570 > * Controls whether double-clicking next to a bracket or quote selects the content inside.
571 > * Defaults to true.
572 > */
573 > doubleClickSelectsBlock?: boolean;
574 > /**
575 > * Controls if the editor should allow to move selections via drag and drop.
576 > * Defaults to false.
577 > */
578 > dragAndDrop?: boolean;
579 > /**
580 > * Enable the suggestion box to pop-up on trigger characters.
581 > * Defaults to true.
582 > */
583 > suggestOnTriggerCharacters?: boolean;
584 > /**
585 > * Accept suggestions on ENTER.
586 > * Defaults to 'on'.
587 > */
588 > acceptSuggestionOnEnter?: 'on' | 'smart' | 'off';
589 > /**
590 > * Accept suggestions on provider defined characters.
591 > * Defaults to true.
592 > */
593 > acceptSuggestionOnCommitCharacter?: boolean;
594 > /**
595 > * Enable snippet suggestions. Default to 'true'.
596 > */
597 > snippetSuggestions?: 'top' | 'bottom' | 'inline' | 'none';
598 > /**
599 > * Copying without a selection copies the current line.
600 > */
601 > emptySelectionClipboard?: boolean;
602 > /**
603 > * Syntax highlighting is copied.
604 > */
605 > copyWithSyntaxHighlighting?: boolean;
606 > /**
607 > * The history mode for suggestions.
608 > */
609 > suggestSelection?: 'first' | 'recentlyUsed' | 'recentlyUsedByPrefix';
610 > /**
611 > * The font size for the suggest widget.
612 > * Defaults to the editor font size.
613 > */
614 > suggestFontSize?: number;
615 > /**
616 > * The line height for the suggest widget.
617 > * Defaults to the editor line height.
618 > */
619 > suggestLineHeight?: number;
620 > /**
621 > * Enable tab completion.
622 > */
623 > tabCompletion?: 'on' | 'off' | 'onlySnippets';
624 > /**
625 > * Enable selection highlight.
626 > * Defaults to true.
627 > */
628 > selectionHighlight?: boolean;
629 > /**
630 > * Enable selection highlight for multiline selections.
631 > * Defaults to false.
632 > */
633 > selectionHighlightMultiline?: boolean;
634 > /**
635 > * Maximum length (in characters) for selection highlights.
636 > * Set to 0 to have an unlimited length.
637 > */
638 > selectionHighlightMaxLength?: number;
639 > /**
640 > * Enable semantic occurrences highlight.
641 > * Defaults to 'singleFile'.
642 > * 'off' disables occurrence highlighting
643 > * 'singleFile' triggers occurrence highlighting in the current document
644 > * 'multiFile' triggers occurrence highlighting across valid open documents
645 > */
646 > occurrencesHighlight?: 'off' | 'singleFile' | 'multiFile';
647 > /**
648 > * Controls delay for occurrences highlighting
649 > * Defaults to 250.
650 > * Minimum value is 0
651 > * Maximum value is 2000
652 > */
653 > occurrencesHighlightDelay?: number;
654 > /**
655 > * Show code lens
656 > * Defaults to true.
657 > */
658 > codeLens?: boolean;
659 > /**
660 > * Code lens font family. Defaults to editor font family.
661 > */
662 > codeLensFontFamily?: string;
663 > /**
664 > * Code lens font size. Default to 90% of the editor font size
665 > */
666 > codeLensFontSize?: number;
667 > /**
668 > * Control the behavior and rendering of the code action lightbulb.
669 > */
670 > lightbulb?: IEditorLightbulbOptions;
671 > /**
672 > * Timeout for running code actions on save.
673 > */
674 > codeActionsOnSaveTimeout?: number;
675 > /**
676 > * Enable code folding.
677 > * Defaults to true.
678 > */
679 > folding?: boolean;
680 > /**
681 > * Selects the folding strategy. 'auto' uses the strategies contributed for the current document, 'indentation' uses the indentation based folding strategy.
682 > * Defaults to 'auto'.
683 > */
684 > foldingStrategy?: 'auto' | 'indentation';
685 > /**
686 > * Enable highlight for folded regions.
687 > * Defaults to true.
688 > */
689 > foldingHighlight?: boolean;
690 > /**
691 > * Auto fold imports folding regions.
692 > * Defaults to true.
693 > */
694 > foldingImportsByDefault?: boolean;
695 > /**
696 > * Maximum number of foldable regions.
697 > * Defaults to 5000.
698 > */
699 > foldingMaximumRegions?: number;
700 > /**
701 > * Controls whether the fold actions in the gutter stay always visible or hide unless the mouse is over the gutter.
702 > * Defaults to 'mouseover'.
703 > */
704 > showFoldingControls?: 'always' | 'never' | 'mouseover';
705 > /**
706 > * Controls whether clicking on the empty content after a folded line will unfold the line.
707 > * Defaults to false.
708 > */
709 > unfoldOnClickAfterEndOfLine?: boolean;
710 > /**
711 > * Enable highlighting of matching brackets.
712 > * Defaults to 'always'.
713 > */
714 > matchBrackets?: 'never' | 'near' | 'always';
715 > /**
716 > * Enable experimental rendering using WebGPU.
717 > * Defaults to 'off'.
718 > */
719 > experimentalGpuAcceleration?: 'on' | 'off';
720 > /**
721 > * Enable experimental whitespace rendering.
722 > * Defaults to 'svg'.
723 > */
724 > experimentalWhitespaceRendering?: 'svg' | 'font' | 'off';
725 > /**
726 > * Enable rendering of whitespace.
727 > * Defaults to 'selection'.
728 > */
729 > renderWhitespace?: 'none' | 'boundary' | 'selection' | 'trailing' | 'all';
730 > /**
731 > * Enable rendering of control characters.
732 > * Defaults to true.
733 > */
734 > renderControlCharacters?: boolean;
735 > /**
736 > * Enable rendering of current line highlight.
737 > * Defaults to all.
738 > */
739 > renderLineHighlight?: 'none' | 'gutter' | 'line' | 'all';
740 > /**
741 > * Control if the current line highlight should be rendered only the editor is focused.
742 > * Defaults to false.
743 > */
744 > renderLineHighlightOnlyWhenFocus?: boolean;
745 > /**
746 > * Inserting and deleting whitespace follows tab stops.
747 > */
748 > useTabStops?: boolean;
749 > /**
750 > * Controls whether the editor should automatically remove indentation whitespace when joining lines with Delete.
751 > * Defaults to false.
752 > */
753 > trimWhitespaceOnDelete?: boolean;
754 > /**
755 > * The font family
756 > */
757 > fontFamily?: string;
758 > /**
759 > * The font weight
760 > */
761 > fontWeight?: string;
762 > /**
763 > * The font size
764 > */
765 > fontSize?: number;
766 > /**
767 > * The line height
768 > */
769 > lineHeight?: number;
770 > /**
771 > * The letter spacing
772 > */
773 > letterSpacing?: number;
774 > /**
775 > * Controls fading out of unused variables.
776 > */
777 > showUnused?: boolean;
778 > /**
779 > * Controls whether to focus the inline editor in the peek widget by default.
780 > * Defaults to false.
781 > */
782 > peekWidgetDefaultFocus?: 'tree' | 'editor';
783 >
784 > /**
785 > * Sets a placeholder for the editor.
786 > * If set, the placeholder is shown if the editor is empty.
787 > */
788 > placeholder?: string | undefined;
789 >
790 > /**
791 > * Controls whether the definition link opens element in the peek widget.
792 > * Defaults to false.
793 > */
794 > definitionLinkOpensInPeek?: boolean;
795 > /**
796 > * Controls strikethrough deprecated variables.
797 > */
798 > showDeprecated?: boolean;
799 > /**
800 > * Controls whether suggestions allow matches in the middle of the word instead of only at the beginning
801 > */
802 > matchOnWordStartOnly?: boolean;
803 > /**
804 > * Control the behavior and rendering of the inline hints.
805 > */
806 > inlayHints?: IEditorInlayHintsOptions;
807 > /**
808 > * Control if the editor should use shadow DOM.
809 > */
810 > useShadowDOM?: boolean;
811 > /**
812 > * Controls the behavior of editor guides.
813 > */
814 > guides?: IGuidesOptions;
815 >
816 > /**
817 > * Controls the behavior of the unicode highlight feature
818 > * (by default, ambiguous and invisible characters are highlighted).
819 > */
820 > unicodeHighlight?: IUnicodeHighlightOptions;
821 >
822 > /**
823 > * Configures bracket pair colorization (disabled by default).
824 > */
825 > bracketPairColorization?: IBracketPairColorizationOptions;
826 >
827 > /**
828 > * Controls dropping into the editor from an external source.
829 > *
830 > * When enabled, this shows a preview of the drop location and triggers an `onDropIntoEditor` event.
831 > */
832 > dropIntoEditor?: IDropIntoEditorOptions;
833 >
834 > /**
835 > * Sets whether the new experimental edit context should be used instead of the text area.
836 > */
837 > editContext?: boolean;
838 >
839 > /**
840 > * Controls whether to render rich HTML screen reader content when the EditContext is enabled
841 > */
842 > renderRichScreenReaderContent?: boolean;
843 >
844 > /**
845 > * Controls support for changing how content is pasted into the editor.
846 > */
847 > pasteAs?: IPasteAsOptions;
848 >
849 > /**
850 > * Controls whether the editor / terminal receives tabs or defers them to the workbench for navigation.
851 > */
852 > tabFocusMode?: boolean;
853 >
854 > /**
855 > * Controls whether the accessibility hint should be provided to screen reader users when an inline completion is shown.
856 > */
857 > inlineCompletionsAccessibilityVerbose?: boolean;
858 > }
859 >
860 > /**
861 > * @internal
862 > * The width of the minimap gutter, in pixels.
863 > */
864 > export const MINIMAP_GUTTER_WIDTH = 8;
865 >
866 > export interface IDiffEditorBaseOptions {
867 > /**
868 > * Allow the user to resize the diff editor split view.
869 > * Defaults to true.
870 > */
871 > enableSplitViewResizing?: boolean;
872 >
873 > /**
874 > * The default ratio when rendering side-by-side editors.
875 > * Must be a number between 0 and 1, min sizes apply.
876 > * Defaults to 0.5
877 > */
878 > splitViewDefaultRatio?: number;
879 >
880 > /**
881 > * Render the differences in two side-by-side editors.
882 > * Defaults to true.
883 > */
884 > renderSideBySide?: boolean;
885 >
886 > /**
887 > * When `renderSideBySide` is enabled, `useInlineViewWhenSpaceIsLimited` is set,
888 > * and the diff editor has a width less than `renderSideBySideInlineBreakpoint`, the inline view is used.
889 > */
890 > renderSideBySideInlineBreakpoint?: number | undefined;
891 >
892 > /**
893 > * When `renderSideBySide` is enabled, `useInlineViewWhenSpaceIsLimited` is set,
894 > * and the diff editor has a width less than `renderSideBySideInlineBreakpoint`, the inline view is used.
895 > */
896 > useInlineViewWhenSpaceIsLimited?: boolean;
897 >
898 > /**
899 > * If set, the diff editor is optimized for small views.
900 > * Defaults to `false`.
901 > */
902 > compactMode?: boolean;
903 >
904 > /**
905 > * If set, the original editor's line numbers are hidden in the inline view.
906 > * Defaults to `false`.
907 > * @internal
908 > */
909 > hideOriginalLineNumbers?: boolean;
910 >
911 > /**
912 > * Timeout in milliseconds after which diff computation is cancelled.
913 > * Defaults to 5000.
914 > */
915 > maxComputationTime?: number;
916 >
917 > /**
918 > * Maximum supported file size in MB.
919 > * Defaults to 50.
920 > */
921 > maxFileSize?: number;
922 >
923 > /**
924 > * Compute the diff by ignoring leading/trailing whitespace
925 > * Defaults to true.
926 > */
927 > ignoreTrimWhitespace?: boolean;
928 >
929 > /**
930 > * Render +/- indicators for added/deleted changes.
931 > * Defaults to true.
932 > */
933 > renderIndicators?: boolean;
934 >
935 > /**
936 > * Shows icons in the glyph margin to revert changes.
937 > * Default to true.
938 > */
939 > renderMarginRevertIcon?: boolean;
940 >
941 > /**
942 > * Indicates if the gutter menu should be rendered.
943 > */
944 > renderGutterMenu?: boolean;
945 >
946 > /**
947 > * Original model should be editable?
948 > * Defaults to false.
949 > */
950 > originalEditable?: boolean;
951 >
952 > /**
953 > * Should the diff editor enable code lens?
954 > * Defaults to false.
955 > */
956 > diffCodeLens?: boolean;
957 >
958 > /**
959 > * Is the diff editor should render overview ruler
960 > * Defaults to true
961 > */
962 > renderOverviewRuler?: boolean;
963 >
964 > /**
965 > * Control the wrapping of the diff editor.
966 > */
967 > diffWordWrap?: 'off' | 'on' | 'inherit';
968 >
969 > /**
970 > * Diff Algorithm
971 > */
972 > diffAlgorithm?: 'legacy' | 'advanced' | 'advanced-external' | 'advanced-wasm';
973 >
974 > /**
975 > * Whether the diff editor aria label should be verbose.
976 > */
977 > accessibilityVerbose?: boolean;
978 >
979 > experimental?: {
980 > /**
981 > * Defaults to false.
982 > */
983 > showMoves?: boolean;
984 >
985 > showEmptyDecorations?: boolean;
986 >
987 > /**
988 > * Only applies when `renderSideBySide` is set to false.
989 > */
990 > useTrueInlineView?: boolean;
991 > };
992 >
993 > /**
994 > * Is the diff editor inside another editor
995 > * Defaults to false
996 > */
997 > isInEmbeddedEditor?: boolean;
998 >
999 > /**
1000 > * If the diff editor should only show the difference review mode.
1001 > */
1002 > onlyShowAccessibleDiffViewer?: boolean;
1003 >
1004 > hideUnchangedRegions?: {
1005 > enabled?: boolean;
1006 > revealLineCount?: number;
1007 > minimumLineCount?: number;
1008 > contextLineCount?: number;
1009 > };
1010 > }
1011 >
1012 > /**
1013 > * Configuration options for the diff editor.
1014 > */
1015 > export interface IDiffEditorOptions extends IEditorOptions, IDiffEditorBaseOptions {
1016 > }
1017 >
1018 > /**
1019 > * @internal
1020 > */
1021 > export type ValidDiffEditorBaseOptions = Readonly<Required<IDiffEditorBaseOptions>>;
1022 >
1023 > //#endregion
1024 >
1025 > /**
1026 > * An event describing that the configuration of the editor has changed.
1027 > */
1028 > export class ConfigurationChangedEvent {
1029 > private readonly _values: boolean[];
1030 > /**
1031 > * @internal
1032 > */
1033 > constructor(values: boolean[]) {
1034 this._values = values;
1035 }
1036 > public hasChanged(id: EditorOption): boolean { editorOptions.ts
1037 return this._values[id];
1038 }
1039 > } editorOptions.ts
1040 >
1041 > /**
1042 > * All computed editor options.
1043 > */
1044 > export interface IComputedEditorOptions {
1045 > get<T extends EditorOption>(id: T): FindComputedEditorOptionValueById<T>;
1046 > }
1047 >
1048 > //#region IEditorOption
1049 >
1050 > /**
1051 > * @internal
1052 > */
1053 > export interface IEnvironmentalOptions {
1054 > readonly memory: ComputeOptionsMemory | null;
1055 > readonly outerWidth: number;
1056 > readonly outerHeight: number;
1057 > readonly fontInfo: FontInfo;
1058 > readonly extraEditorClassName: string;
1059 > readonly isDominatedByLongLines: boolean;
1060 > readonly viewLineCount: number;
1061 > readonly lineNumbersDigitCount: number;
1062 > readonly emptySelectionClipboard: boolean;
1063 > readonly pixelRatio: number;
1064 > readonly tabFocusMode: boolean;
1065 > readonly inputMode: 'insert' | 'overtype';
1066 > readonly accessibilitySupport: AccessibilitySupport;
1067 > readonly glyphMarginDecorationLaneCount: number;
1068 > readonly editContextSupported: boolean;
1069 > }
1070 >
1071 > /**
1072 > * @internal
1073 > */
1074 > export class ComputeOptionsMemory {
1075 >
1076 > public stableMinimapLayoutInput: IMinimapLayoutInput | null;
1077 > public stableFitMaxMinimapScale: number;
1078 > public stableFitRemainingWidth: number;
1079 >
1080 > constructor() {
1081 this.stableMinimapLayoutInput = null;
1082 this.stableFitMaxMinimapScale = 0;
1083 this.stableFitRemainingWidth = 0;
1084 }
1085 > } editorOptions.ts
1086 >
1087 > export interface IEditorOption<K extends EditorOption, V> {
1088 > readonly id: K;
1089 > readonly name: string;
1090 > defaultValue: V;
1091 > /**
1092 > * @internal
1093 > */
1094 > readonly schema: IConfigurationPropertySchema | { [path: string]: IConfigurationPropertySchema } | undefined;
1095 > /**
1096 > * @internal
1097 > */
1098 > validate(input: unknown): V;
1099 > /**
1100 > * @internal
1101 > */
1102 > compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: V): V;
1103 >
1104 > /**
1105 > * Might modify `value`.
1106 > */
1107 > applyUpdate(value: V | undefined, update: V): ApplyUpdateResult<V>;
1108 > }
1109 >
1110 > /**
1111 > * @internal
1112 > */
1113 > type PossibleKeyName0<V> = { [K in keyof IEditorOptions]: IEditorOptions[K] extends V | undefined ? K : never }[keyof IEditorOptions];
1114 > /**
1115 > * @internal
1116 > */
1117 > type PossibleKeyName<V> = NonNullable<PossibleKeyName0<V>>;
1118 >
1119 > /**
1120 > * @internal
1121 > */
1122 > abstract class BaseEditorOption<K extends EditorOption, T, V> implements IEditorOption<K, V> {
1123 >
1124 > public readonly id: K;
1125 > public readonly name: string;
1126 > public readonly defaultValue: V;
1127 > public readonly schema: IConfigurationPropertySchema | { [path: string]: IConfigurationPropertySchema } | undefined;
1128 >
1129 > constructor(id: K, name: PossibleKeyName<T>, defaultValue: V, schema?: IConfigurationPropertySchema | { [path: string]: IConfigurationPropertySchema }) {
1130 > this.id = id;
1131 > this.name = name;
1132 > this.defaultValue = defaultValue;
1133 > this.schema = schema;
1134 > }
1135 >
1136 > public applyUpdate(value: V | undefined, update: V): ApplyUpdateResult<V> {
1137 return applyUpdate(value, update);
1138 }
1140 > public abstract validate(input: unknown): V;
1141 >
1142 > public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: V): V {
1143 return value;
1144 }
1145 > } editorOptions.ts
1146 >
1147 > export class ApplyUpdateResult<T> {
1148 > constructor(
1149 public readonly newValue: T,
1150 public readonly didChange: boolean
1151 ) { }
1152 > } editorOptions.ts
1153 >
1154 function applyUpdate<T>(value: T | undefined, update: T): ApplyUpdateResult<T> {
1155 if (typeof value !== 'object' || typeof update !== 'object' || !value || !update) {
1172 return new ApplyUpdateResult(value, didChange);
1173 }
1175 > /**
1176 > * @internal
1177 > */
1178 > abstract class ComputedEditorOption<K extends EditorOption, V> implements IEditorOption<K, V> {
1179 >
1180 > public readonly id: K;
1181 > public readonly name: '_never_';
1182 > public readonly defaultValue: V;
1183 > public readonly schema: IConfigurationPropertySchema | undefined = undefined;
1184 >
1185 > constructor(id: K, defaultValue: V) {
1186 > this.id = id;
1187 > this.name = '_never_';
1188 > this.defaultValue = defaultValue;
1189 > }
1190 >
1191 > public applyUpdate(value: V | undefined, update: V): ApplyUpdateResult<V> {
1192 return applyUpdate(value, update);
1193 }
1195 > public validate(input: unknown): V {
1196 return this.defaultValue;
1197 }
1199 > public abstract compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: V): V;
1200 > }
1201 >
1202 > abstract class SimpleEditorOption<K extends EditorOption, V> implements IEditorOption<K, V> {
1203 >
1204 > public readonly id: K;
1205 > public readonly name: PossibleKeyName<V>;
1206 > public readonly defaultValue: V;
1207 > public readonly schema: IConfigurationPropertySchema | undefined;
1208 >
1209 > constructor(id: K, name: PossibleKeyName<V>, defaultValue: V, schema?: IConfigurationPropertySchema) {
1210 > this.id = id;
1211 > this.name = name;
1212 > this.defaultValue = defaultValue;
1213 > this.schema = schema;
1214 > }
1215 >
1216 > public applyUpdate(value: V | undefined, update: V): ApplyUpdateResult<V> {
1217 return applyUpdate(value, update);
1218 }
1220 > public abstract validate(input: unknown): V;
1221 >
1222 > public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: V): V {
1223 return value;
1224 }
1225 > } editorOptions.ts
1226 >
1227 > /**
1228 > * @internal
1229 > */
1230 > export function boolean(value: unknown, defaultValue: boolean): boolean {
1231 if (typeof value === 'undefined') {
1232 return defaultValue;
1238 return Boolean(value);
1239 }
1241 > class EditorBooleanOption<K extends EditorOption> extends SimpleEditorOption<K, boolean> {
1242 >
1243 > constructor(id: K, name: PossibleKeyName<boolean>, defaultValue: boolean, schema: IConfigurationPropertySchema | undefined = undefined) {
1244 > if (typeof schema !== 'undefined') {
1245 > schema.type = 'boolean';
1246 > schema.default = defaultValue;
1247 > }
1248 > super(id, name, defaultValue, schema);
1249 > }
1250 >
1251 > public override validate(input: unknown): boolean {
1252 return boolean(input, this.defaultValue);
1253 }
1254 > } editorOptions.ts
1255 >
1256 > /**
1257 > * @internal
1258 > */
1259 > export function clampedInt<T = number>(value: unknown, defaultValue: T, minimum: number, maximum: number): number | T {
1260 if (typeof value === 'string') {
1261 value = parseInt(value, 10);
1269 return r | 0;
1270 }
1272 > class EditorIntOption<K extends EditorOption> extends SimpleEditorOption<K, number> {
1273 >
1274 > public static clampedInt<T>(value: unknown, defaultValue: T, minimum: number, maximum: number): number | T {
1275 return clampedInt(value, defaultValue, minimum, maximum);
1276 }
1278 > public readonly minimum: number;
1279 > public readonly maximum: number;
1280 >
1281 > constructor(id: K, name: PossibleKeyName<number>, defaultValue: number, minimum: number, maximum: number, schema: IConfigurationPropertySchema | undefined = undefined) {
1282 > if (typeof schema !== 'undefined') {
1283 > schema.type = 'integer';
1284 > schema.default = defaultValue;
1285 > schema.minimum = minimum;
1286 > schema.maximum = maximum;
1287 > }
1288 > super(id, name, defaultValue, schema);
1289 > this.minimum = minimum;
1290 > this.maximum = maximum;
1291 > }
1292 >
1293 > public override validate(input: unknown): number {
1294 return EditorIntOption.clampedInt(input, this.defaultValue, this.minimum, this.maximum);
1295 }
1296 > } editorOptions.ts
1297 > /**
1298 > * @internal
1299 > */
1300 > export function clampedFloat<T extends number>(value: unknown, defaultValue: T, minimum: number, maximum: number): number | T {
1301 if (typeof value === 'undefined') {
1302 return defaultValue;
1305 return EditorFloatOption.clamp(r, minimum, maximum);
1306 }
1308 > class EditorFloatOption<K extends EditorOption> extends SimpleEditorOption<K, number> {
1309 >
1310 > public readonly minimum: number | undefined;
1311 > public readonly maximum: number | undefined;
1312 >
1313 > public static clamp(n: number, min: number, max: number): number {
1314 if (n < min) {
1315 return min;
1320 return n;
1321 }
1323 > public static float(value: unknown, defaultValue: number): number {
1324 if (typeof value === 'string') {
1325 value = parseFloat(value);
1330 return value;
1331 }
1333 > public readonly validationFn: (value: number) => number;
1334 >
1335 > constructor(id: K, name: PossibleKeyName<number>, defaultValue: number, validationFn: (value: number) => number, schema?: IConfigurationPropertySchema, minimum?: number, maximum?: number) {
1336 > if (typeof schema !== 'undefined') {
1337 > schema.type = 'number';
1338 > schema.default = defaultValue;
1339 > schema.minimum = minimum;
1340 > schema.maximum = maximum;
1341 > }
1342 > super(id, name, defaultValue, schema);
1343 > this.validationFn = validationFn;
1344 > this.minimum = minimum;
1345 > this.maximum = maximum;
1346 > }
1347 >
1348 > public override validate(input: unknown): number {
1349 return this.validationFn(EditorFloatOption.float(input, this.defaultValue));
1350 }
1351 > } editorOptions.ts
1352 >
1353 > class EditorStringOption<K extends EditorOption> extends SimpleEditorOption<K, string> {
1354 >
1355 > public static string(value: unknown, defaultValue: string): string {
1356 if (typeof value !== 'string') {
1357 return defaultValue;
1359 return value;
1360 }
1362 > constructor(id: K, name: PossibleKeyName<string>, defaultValue: string, schema: IConfigurationPropertySchema | undefined = undefined) {
1363 > if (typeof schema !== 'undefined') {
1364 > schema.type = 'string';
1365 > schema.default = defaultValue;
1366 > }
1367 > super(id, name, defaultValue, schema);
1368 > }
1369 >
1370 > public override validate(input: unknown): string {
1371 return EditorStringOption.string(input, this.defaultValue);
1372 }
1373 > } editorOptions.ts
1374 >
1375 > /**
1376 > * @internal
1377 > */
1378 > export function stringSet<T extends string>(value: unknown, defaultValue: T, allowedValues: ReadonlyArray<T>, renamedValues?: Record<string, T>): T {
1379 if (typeof value !== 'string') {
1380 return defaultValue;
1388 return value as T;
1389 }
1391 > class EditorStringEnumOption<K extends EditorOption, V extends string> extends SimpleEditorOption<K, V> {
1392 >
1393 > private readonly _allowedValues: ReadonlyArray<V>;
1394 >
1395 > constructor(id: K, name: PossibleKeyName<V>, defaultValue: V, allowedValues: ReadonlyArray<V>, schema: IConfigurationPropertySchema | undefined = undefined) {
1396 > if (typeof schema !== 'undefined') {
1397 > schema.type = 'string';
1398 > schema.enum = allowedValues.slice(0);
1399 > schema.default = defaultValue;
1400 > }
1401 > super(id, name, defaultValue, schema);
1402 > this._allowedValues = allowedValues;
1403 > }
1404 >
1405 > public override validate(input: unknown): V {
1406 return stringSet<V>(input, this.defaultValue, this._allowedValues);
1407 }
1408 > } editorOptions.ts
1409 >
1410 > class EditorEnumOption<K extends EditorOption, T extends string, V> extends BaseEditorOption<K, T, V> {
1411 >
1412 > private readonly _allowedValues: T[];
1413 > private readonly _convert: (value: T) => V;
1414 >
1415 > constructor(id: K, name: PossibleKeyName<T>, defaultValue: V, defaultStringValue: string, allowedValues: T[], convert: (value: T) => V, schema: IConfigurationPropertySchema | undefined = undefined) {
1416 > if (typeof schema !== 'undefined') {
1417 > schema.type = 'string';
1418 > schema.enum = allowedValues;
1419 > schema.default = defaultStringValue;
1420 > }
1421 > super(id, name, defaultValue, schema);
1422 > this._allowedValues = allowedValues;
1423 > this._convert = convert;
1424 > }
1425 >
1426 > public validate(input: unknown): V {
1427 if (typeof input !== 'string') {
1428 return this.defaultValue;
1433 return this._convert(<T>input);
1434 }
1435 > } editorOptions.ts
1436 >
1437 > //#endregion
1438 >
1439 > //#region autoIndent
1440 >
1441 function _autoIndentFromString(autoIndent: 'none' | 'keep' | 'brackets' | 'advanced' | 'full'): EditorAutoIndentStrategy {
1442 switch (autoIndent) {
1448 }
1449 }
1451 > //#endregion
1452 >
1453 > //#region accessibilitySupport
1454 >
1455 > class EditorAccessibilitySupport extends BaseEditorOption<EditorOption.accessibilitySupport, 'auto' | 'off' | 'on', AccessibilitySupport> {
1456 >
1457 > constructor() {
1458 > super(
1459 > EditorOption.accessibilitySupport, 'accessibilitySupport', AccessibilitySupport.Unknown,
1460 > {
1461 > type: 'string',
1462 > enum: ['auto', 'on', 'off'],
1463 > enumDescriptions: [
1464 > nls.localize('accessibilitySupport.auto', "Use platform APIs to detect when a Screen Reader is attached."),
1465 > nls.localize('accessibilitySupport.on', "Optimize for usage with a Screen Reader."),
1466 > nls.localize('accessibilitySupport.off', "Assume a screen reader is not attached."),
1467 > ],
1468 > default: 'auto',
1469 > tags: ['accessibility'],
1470 > description: nls.localize('accessibilitySupport', "Controls if the UI should run in a mode where it is optimized for screen readers.")
1471 > }
1472 > );
1473 > }
1474 >
1475 > public validate(input: unknown): AccessibilitySupport {
1476 switch (input) {
1477 case 'auto': return AccessibilitySupport.Unknown;
1481 return this.defaultValue;
1482 }
1484 > public override compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: AccessibilitySupport): AccessibilitySupport {
1485 if (value === AccessibilitySupport.Unknown) {
1486 // The editor reads the `accessibilitySupport` from the environment
1489 return value;
1490 }
1491 > } editorOptions.ts
1492 >
1493 > //#endregion
1494 >
1495 > //#region comments
1496 >
1497 > /**
1498 > * Configuration options for editor comments
1499 > */
1500 > export interface IEditorCommentsOptions {
1501 > /**
1502 > * Insert a space after the line comment token and inside the block comments tokens.
1503 > * Defaults to true.
1504 > */
1505 > insertSpace?: boolean;
1506 > /**
1507 > * Ignore empty lines when inserting line comments.
1508 > * Defaults to true.
1509 > */
1510 > ignoreEmptyLines?: boolean;
1511 > }
1512 >
1513 > /**
1514 > * @internal
1515 > */
1516 > export type EditorCommentsOptions = Readonly<Required<IEditorCommentsOptions>>;
1517 >
1518 > class EditorComments extends BaseEditorOption<EditorOption.comments, IEditorCommentsOptions, EditorCommentsOptions> {
1519 >
1520 > constructor() {
1521 > const defaults: EditorCommentsOptions = {
1522 > insertSpace: true,
1523 > ignoreEmptyLines: true,
1524 > };
1525 > super(
1526 > EditorOption.comments, 'comments', defaults,
1527 > {
1528 > 'editor.comments.insertSpace': {
1529 > type: 'boolean',
1530 > default: defaults.insertSpace,
1531 > description: nls.localize('comments.insertSpace', "Controls whether a space character is inserted when commenting.")
1532 > },
1533 > 'editor.comments.ignoreEmptyLines': {
1534 > type: 'boolean',
1535 > default: defaults.ignoreEmptyLines,
1536 > description: nls.localize('comments.ignoreEmptyLines', 'Controls if empty lines should be ignored with toggle, add or remove actions for line comments.')
1537 > },
1538 > }
1539 > );
1540 > }
1541 >
1542 > public validate(_input: unknown): EditorCommentsOptions {
1543 if (!_input || typeof _input !== 'object') {
1544 return this.defaultValue;
1550 };
1551 }
1552 > } editorOptions.ts
1553 >
1554 > //#endregion
1555 >
1556 > //#region cursorBlinking
1557 >
1558 > /**
1559 > * The kind of animation in which the editor's cursor should be rendered.
1560 > */
1561 > export const enum TextEditorCursorBlinkingStyle {
1562 > /**
1563 > * Hidden
1564 > */
1565 > Hidden = 0,
1566 > /**
1567 > * Blinking
1568 > */
1569 > Blink = 1,
1570 > /**
1571 > * Blinking with smooth fading
1572 > */
1573 > Smooth = 2,
1574 > /**
1575 > * Blinking with prolonged filled state and smooth fading
1576 > */
1577 > Phase = 3,
1578 > /**
1579 > * Expand collapse animation on the y axis
1580 > */
1581 > Expand = 4,
1582 > /**
1583 > * No-Blinking
1584 > */
1585 > Solid = 5
1586 > }
1587 >
1588 > /**
1589 > * @internal
1590 > */
1591 > export function cursorBlinkingStyleFromString(cursorBlinkingStyle: 'blink' | 'smooth' | 'phase' | 'expand' | 'solid'): TextEditorCursorBlinkingStyle {
1592 switch (cursorBlinkingStyle) {
1593 case 'blink': return TextEditorCursorBlinkingStyle.Blink;
1598 }
1599 }
1601 > //#endregion
1602 >
1603 > //#region cursorStyle
1604 >
1605 > /**
1606 > * The style in which the editor's cursor should be rendered.
1607 > */
1608 > export enum TextEditorCursorStyle {
1609 > /**
1610 > * As a vertical line (sitting between two characters).
1611 > */
1612 > Line = 1,
1613 > /**
1614 > * As a block (sitting on top of a character).
1615 > */
1616 > Block = 2,
1617 > /**
1618 > * As a horizontal line (sitting under a character).
1619 > */
1620 > Underline = 3,
1621 > /**
1622 > * As a thin vertical line (sitting between two characters).
1623 > */
1624 > LineThin = 4,
1625 > /**
1626 > * As an outlined block (sitting on top of a character).
1627 > */
1628 > BlockOutline = 5,
1629 > /**
1630 > * As a thin horizontal line (sitting under a character).
1631 > */
1632 > UnderlineThin = 6
1633 > }
1634 >
1635 > /**
1636 > * @internal
1637 > */
1638 > export function cursorStyleToString(cursorStyle: TextEditorCursorStyle): 'line' | 'block' | 'underline' | 'line-thin' | 'block-outline' | 'underline-thin' {
1639 switch (cursorStyle) {
1640 case TextEditorCursorStyle.Line: return 'line';
1646 }
1647 }
1649 > /**
1650 > * @internal
1651 > */
1652 > export function cursorStyleFromString(cursorStyle: 'line' | 'block' | 'underline' | 'line-thin' | 'block-outline' | 'underline-thin'): TextEditorCursorStyle {
1653 switch (cursorStyle) {
1654 case 'line': return TextEditorCursorStyle.Line;
1660 }
1661 }
1663 > //#endregion
1664 >
1665 > //#region editorClassName
1666 >
1667 > class EditorClassName extends ComputedEditorOption<EditorOption.editorClassName, string> {
1668 >
1669 > constructor() {
1670 > super(EditorOption.editorClassName, '');
1671 > }
1672 >
1673 > public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: string): string {
1674 const classNames = ['monaco-editor'];
1675 if (options.get(EditorOption.extraEditorClassName)) {
1695 return classNames.join(' ');
1696 }
1697 > } editorOptions.ts
1698 >
1699 > //#endregion
1700 >
1701 > //#region emptySelectionClipboard
1702 >
1703 > class EditorEmptySelectionClipboard extends EditorBooleanOption<EditorOption.emptySelectionClipboard> {
1704 >
1705 > constructor() {
1706 > super(
1707 > EditorOption.emptySelectionClipboard, 'emptySelectionClipboard', true,
1708 > { description: nls.localize('emptySelectionClipboard', "Controls whether copying without a selection copies the current line.") }
1709 > );
1710 > }
1711 >
1712 > public override compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: boolean): boolean {
1713 return value && env.emptySelectionClipboard;
1714 }
1715 > } editorOptions.ts
1716 >
1717 > //#endregion
1718 >
1719 > //#region find
1720 >
1721 > /**
1722 > * Configuration options for editor find widget
1723 > */
1724 > export interface IEditorFindOptions {
1725 > /**
1726 > * Controls whether the cursor should move to find matches while typing.
1727 > */
1728 > cursorMoveOnType?: boolean;
1729 > /**
1730 > * Controls whether the find widget should search as you type.
1731 > */
1732 > findOnType?: boolean;
1733 > /**
1734 > * Controls if we seed search string in the Find Widget with editor selection.
1735 > */
1736 > seedSearchStringFromSelection?: 'never' | 'always' | 'selection';
1737 > /**
1738 > * Controls if Find in Selection flag is turned on in the editor.
1739 > */
1740 > autoFindInSelection?: 'never' | 'always' | 'multiline';
1741 > /*
1742 > * Controls whether the Find Widget should add extra lines on top of the editor.
1743 > */
1744 > addExtraSpaceOnTop?: boolean;
1745 > /**
1746 > * @internal
1747 > * Controls if the Find Widget should read or modify the shared find clipboard on macOS
1748 > */
1749 > globalFindClipboard?: boolean;
1750 > /**
1751 > * Controls whether the search result and diff result automatically restarts from the beginning (or the end) when no further matches can be found
1752 > */
1753 > loop?: boolean;
1754 > /**
1755 > * Controls whether to close the Find Widget after an explicit find navigation command lands on a match.
1756 > */
1757 > closeOnResult?: boolean;
1758 > /**
1759 > * @internal
1760 > * Controls how the find widget search history should be stored
1761 > */
1762 > history?: 'never' | 'workspace';
1763 > /**
1764 > * @internal
1765 > * Controls how the replace widget search history should be stored
1766 > */
1767 > replaceHistory?: 'never' | 'workspace';
1768 > }
1769 >
1770 > /**
1771 > * @internal
1772 > */
1773 > export type EditorFindOptions = Readonly<Required<IEditorFindOptions>>;
1774 >
1775 > class EditorFind extends BaseEditorOption<EditorOption.find, IEditorFindOptions, EditorFindOptions> {
1776 >
1777 > constructor() {
1778 > const defaults: EditorFindOptions = {
1779 > cursorMoveOnType: true,
1780 > findOnType: true,
1781 > seedSearchStringFromSelection: 'always',
1782 > autoFindInSelection: 'never',
1783 > globalFindClipboard: false,
1784 > addExtraSpaceOnTop: true,
1785 > loop: true,
1786 > closeOnResult: false,
1787 > history: 'workspace',
1788 > replaceHistory: 'workspace',
1789 > };
1790 > super(
1791 > EditorOption.find, 'find', defaults,
1792 > {
1793 > 'editor.find.cursorMoveOnType': {
1794 > type: 'boolean',
1795 > default: defaults.cursorMoveOnType,
1796 > description: nls.localize('find.cursorMoveOnType', "Controls whether the cursor should jump to find matches while typing.")
1797 > },
1798 > 'editor.find.seedSearchStringFromSelection': {
1799 > type: 'string',
1800 > enum: ['never', 'always', 'selection'],
1801 > default: defaults.seedSearchStringFromSelection,
1802 > enumDescriptions: [
1803 > nls.localize('editor.find.seedSearchStringFromSelection.never', 'Never seed search string from the editor selection.'),
1804 > nls.localize('editor.find.seedSearchStringFromSelection.always', 'Always seed search string from the editor selection, including word at cursor position.'),
1805 > nls.localize('editor.find.seedSearchStringFromSelection.selection', 'Only seed search string from the editor selection.')
1806 > ],
1807 > description: nls.localize('find.seedSearchStringFromSelection', "Controls whether the search string in the Find Widget is seeded from the editor selection.")
1808 > },
1809 > 'editor.find.autoFindInSelection': {
1810 > type: 'string',
1811 > enum: ['never', 'always', 'multiline'],
1812 > default: defaults.autoFindInSelection,
1813 > enumDescriptions: [
1814 > nls.localize('editor.find.autoFindInSelection.never', 'Never turn on Find in Selection automatically (default).'),
1815 > nls.localize('editor.find.autoFindInSelection.always', 'Always turn on Find in Selection automatically.'),
1816 > nls.localize('editor.find.autoFindInSelection.multiline', 'Turn on Find in Selection automatically when multiple lines of content are selected.')
1817 > ],
1818 > description: nls.localize('find.autoFindInSelection', "Controls the condition for turning on Find in Selection automatically.")
1819 > },
1820 > 'editor.find.globalFindClipboard': {
1821 > type: 'boolean',
1822 > default: defaults.globalFindClipboard,
1823 > description: nls.localize('find.globalFindClipboard', "Controls whether the Find Widget should read or modify the shared find clipboard on macOS."),
1824 > included: platform.isMacintosh
1825 > },
1826 > 'editor.find.addExtraSpaceOnTop': {
1827 > type: 'boolean',
1828 > default: defaults.addExtraSpaceOnTop,
1829 > description: nls.localize('find.addExtraSpaceOnTop', "Controls whether the Find Widget should add extra lines on top of the editor. When true, you can scroll beyond the first line when the Find Widget is visible.")
1830 > },
1831 > 'editor.find.loop': {
1832 > type: 'boolean',
1833 > default: defaults.loop,
1834 > description: nls.localize('find.loop', "Controls whether the search automatically restarts from the beginning (or the end) when no further matches can be found.")
1835 > },
1836 > 'editor.find.closeOnResult': {
1837 > type: 'boolean',
1838 > default: defaults.closeOnResult,
1839 > description: nls.localize('find.closeOnResult', "Controls whether the Find Widget closes after an explicit find navigation command lands on a result.")
1840 > },
1841 > 'editor.find.history': {
1842 > type: 'string',
1843 > enum: ['never', 'workspace'],
1844 > default: 'workspace',
1845 > enumDescriptions: [
1846 > nls.localize('editor.find.history.never', 'Do not store search history from the find widget.'),
1847 > nls.localize('editor.find.history.workspace', 'Store search history across the active workspace'),
1848 > ],
1849 > description: nls.localize('find.history', "Controls how the find widget history should be stored")
1850 > },
1851 > 'editor.find.replaceHistory': {
1852 > type: 'string',
1853 > enum: ['never', 'workspace'],
1854 > default: 'workspace',
1855 > enumDescriptions: [
1856 > nls.localize('editor.find.replaceHistory.never', 'Do not store history from the replace widget.'),
1857 > nls.localize('editor.find.replaceHistory.workspace', 'Store replace history across the active workspace'),
1858 > ],
1859 > description: nls.localize('find.replaceHistory', "Controls how the replace widget history should be stored")
1860 > },
1861 > 'editor.find.findOnType': {
1862 > type: 'boolean',
1863 > default: defaults.findOnType,
1864 > description: nls.localize('find.findOnType', "Controls whether the Find Widget should search as you type.")
1865 > },
1866 > }
1867 > );
1868 > }
1869 >
1870 > public validate(_input: unknown): EditorFindOptions {
1871 if (!_input || typeof _input !== 'object') {
1872 return this.defaultValue;
1890 };
1891 }
1892 > } editorOptions.ts
1893 >
1894 > //#endregion
1895 >
1896 > //#region fontLigatures
1897 >
1898 > /**
1899 > * @internal
1900 > */
1901 > export class EditorFontLigatures extends BaseEditorOption<EditorOption.fontLigatures, boolean | string, string> {
1902 >
1903 > public static OFF = '"liga" off, "calt" off';
1904 > public static ON = '"liga" on, "calt" on';
1905 >
1906 > constructor() {
1907 > super(
1908 > EditorOption.fontLigatures, 'fontLigatures', EditorFontLigatures.OFF,
1909 > {
1910 > anyOf: [
1911 > {
1912 > type: 'boolean',
1913 > description: nls.localize('fontLigatures', "Enables/Disables font ligatures ('calt' and 'liga' font features). Change this to a string for fine-grained control of the 'font-feature-settings' CSS property."),
1914 > },
1915 > {
1916 > type: 'string',
1917 > description: nls.localize('fontFeatureSettings', "Explicit 'font-feature-settings' CSS property. A boolean can be passed instead if one only needs to turn on/off ligatures.")
1918 > }
1919 > ],
1920 > description: nls.localize('fontLigaturesGeneral', "Configures font ligatures or font features. Can be either a boolean to enable/disable ligatures or a string for the value of the CSS 'font-feature-settings' property."),
1921 > default: false
1922 > }
1923 > );
1924 > }
1925 >
1926 > public validate(input: unknown): string {
1927 if (typeof input === 'undefined') {
1928 return this.defaultValue;
1942 return EditorFontLigatures.OFF;
1943 }
1944 > } editorOptions.ts
1945 >
1946 > //#endregion
1947 >
1948 > //#region fontVariations
1949 >
1950 > /**
1951 > * @internal
1952 > */
1953 > export class EditorFontVariations extends BaseEditorOption<EditorOption.fontVariations, boolean | string, string> {
1954 > // Text is laid out using default settings.
1955 > public static OFF = FONT_VARIATION_OFF;
1956 >
1957 > // Translate `fontWeight` config to the `font-variation-settings` CSS property.
1958 > public static TRANSLATE = FONT_VARIATION_TRANSLATE;
1959 >
1960 > constructor() {
1961 > super(
1962 > EditorOption.fontVariations, 'fontVariations', EditorFontVariations.OFF,
1963 > {
1964 > anyOf: [
1965 > {
1966 > type: 'boolean',
1967 > description: nls.localize('fontVariations', "Enables/Disables the translation from font-weight to font-variation-settings. Change this to a string for fine-grained control of the 'font-variation-settings' CSS property."),
1968 > },
1969 > {
1970 > type: 'string',
1971 > description: nls.localize('fontVariationSettings', "Explicit 'font-variation-settings' CSS property. A boolean can be passed instead if one only needs to translate font-weight to font-variation-settings.")
1972 > }
1973 > ],
1974 > description: nls.localize('fontVariationsGeneral', "Configures font variations. Can be either a boolean to enable/disable the translation from font-weight to font-variation-settings or a string for the value of the CSS 'font-variation-settings' property."),
1975 > default: false
1976 > }
1977 > );
1978 > }
1979 >
1980 > public validate(input: unknown): string {
1981 if (typeof input === 'undefined') {
1982 return this.defaultValue;
1996 return EditorFontVariations.OFF;
1997 }
1999 > public override compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: string): string {
2000 // The value is computed from the fontWeight if it is true.
2001 // So take the result from env.fontInfo
2002 return env.fontInfo.fontVariationSettings;
2003 }
2004 > } editorOptions.ts
2005 >
2006 > //#endregion
2007 >
2008 > //#region fontInfo
2009 >
2010 > class EditorFontInfo extends ComputedEditorOption<EditorOption.fontInfo, FontInfo> {
2011 >
2012 > constructor() {
2013 > super(EditorOption.fontInfo, new FontInfo({
2014 > pixelRatio: 0,
2015 > fontFamily: '',
2016 > fontWeight: '',
2017 > fontSize: 0,
2018 > fontFeatureSettings: '',
2019 > fontVariationSettings: '',
2020 > lineHeight: 0,
2021 > letterSpacing: 0,
2022 > isMonospace: false,
2023 > typicalHalfwidthCharacterWidth: 0,
2024 > typicalFullwidthCharacterWidth: 0,
2025 > canUseHalfwidthRightwardsArrow: false,
2026 > spaceWidth: 0,
2027 > middotWidth: 0,
2028 > wsmiddotWidth: 0,
2029 > maxDigitWidth: 0,
2030 > }, false));
2031 > }
2032 >
2033 > public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: FontInfo): FontInfo {
2034 return env.fontInfo;
2035 }
2036 > } editorOptions.ts
2037 >
2038 > //#endregion
2039 >
2040 > //#region effectiveCursorStyle
2041 >
2042 > class EffectiveCursorStyle extends ComputedEditorOption<EditorOption.effectiveCursorStyle, TextEditorCursorStyle> {
2043 >
2044 > constructor() {
2045 > super(EditorOption.effectiveCursorStyle, TextEditorCursorStyle.Line);
2046 > }
2047 >
2048 > public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: TextEditorCursorStyle): TextEditorCursorStyle {
2049 return env.inputMode === 'overtype' ?
2050 options.get(EditorOption.overtypeCursorStyle) :
2051 options.get(EditorOption.cursorStyle);
2052 }
2053 > } editorOptions.ts
2054 >
2055 > //#endregion
2056 >
2057 > //#region effectiveExperimentalEditContext
2058 >
2059 > class EffectiveEditContextEnabled extends ComputedEditorOption<EditorOption.effectiveEditContext, boolean> {
2060 >
2061 > constructor() {
2062 > super(EditorOption.effectiveEditContext, false);
2063 > }
2064 >
2065 > public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions): boolean {
2066 return env.editContextSupported && options.get(EditorOption.editContext);
2067 }
2068 > } editorOptions.ts
2069 >
2070 > //#endregion
2071 >
2072 > //#region effectiveAllowVariableFonts
2073 >
2074 > class EffectiveAllowVariableFonts extends ComputedEditorOption<EditorOption.effectiveAllowVariableFonts, boolean> {
2075 >
2076 > constructor() {
2077 > super(EditorOption.effectiveAllowVariableFonts, false);
2078 > }
2079 >
2080 > public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions): boolean {
2081 const accessibilitySupport = env.accessibilitySupport;
2082 if (accessibilitySupport === AccessibilitySupport.Enabled) {
2086 }
2087 }
2088 > } editorOptions.ts
2089 >
2090 > //#engregion
2091 >
2092 > //#region fontSize
2093 >
2094 > class EditorFontSize extends SimpleEditorOption<EditorOption.fontSize, number> {
2095 >
2096 > constructor() {
2097 > super(
2098 > EditorOption.fontSize, 'fontSize', EDITOR_FONT_DEFAULTS.fontSize,
2099 > {
2100 > type: 'number',
2101 > minimum: 6,
2102 > maximum: 100,
2103 > default: EDITOR_FONT_DEFAULTS.fontSize,
2104 > description: nls.localize('fontSize', "Controls the font size in pixels.")
2105 > }
2106 > );
2107 > }
2108 >
2109 > public override validate(input: unknown): number {
2110 const r = EditorFloatOption.float(input, this.defaultValue);
2111 if (r === 0) {
2114 return EditorFloatOption.clamp(r, 6, 100);
2115 }
2116 > public override compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: number): number { editorOptions.ts
2117 // The final fontSize respects the editor zoom level.
2118 // So take the result from env.fontInfo
2119 return env.fontInfo.fontSize;
2120 }
2121 > } editorOptions.ts
2122 >
2123 > //#endregion
2124 >
2125 > //#region fontWeight
2126 >
2127 > class EditorFontWeight extends BaseEditorOption<EditorOption.fontWeight, string, string> {
2128 > private static SUGGESTION_VALUES = ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'];
2129 > private static MINIMUM_VALUE = 1;
2130 > private static MAXIMUM_VALUE = 1000;
2131 >
2132 > constructor() {
2133 > super(
2134 > EditorOption.fontWeight, 'fontWeight', EDITOR_FONT_DEFAULTS.fontWeight,
2135 > {
2136 > anyOf: [
2137 > {
2138 > type: 'number',
2139 > minimum: EditorFontWeight.MINIMUM_VALUE,
2140 > maximum: EditorFontWeight.MAXIMUM_VALUE,
2141 > errorMessage: nls.localize('fontWeightErrorMessage', "Only \"normal\" and \"bold\" keywords or numbers between 1 and 1000 are allowed.")
2142 > },
2143 > {
2144 > type: 'string',
2145 > pattern: '^(normal|bold|1000|[1-9][0-9]{0,2})$'
2146 > },
2147 > {
2148 > enum: EditorFontWeight.SUGGESTION_VALUES
2149 > }
2150 > ],
2151 > default: EDITOR_FONT_DEFAULTS.fontWeight,
2152 > description: nls.localize('fontWeight', "Controls the font weight. Accepts \"normal\" and \"bold\" keywords or numbers between 1 and 1000.")
2153 > }
2154 > );
2155 > }
2156 >
2157 > public validate(input: unknown): string {
2158 if (input === 'normal' || input === 'bold') {
2159 return input;
2161 return String(EditorIntOption.clampedInt(input, EDITOR_FONT_DEFAULTS.fontWeight, EditorFontWeight.MINIMUM_VALUE, EditorFontWeight.MAXIMUM_VALUE));
2162 }
2163 > } editorOptions.ts
2164 >
2165 > //#endregion
2166 >
2167 > //#region gotoLocation
2168 >
2169 > export type GoToLocationValues = 'peek' | 'gotoAndPeek' | 'goto';
2170 >
2171 > /**
2172 > * Configuration options for go to location
2173 > */
2174 > export interface IGotoLocationOptions {
2175 >
2176 > multiple?: GoToLocationValues;
2177 >
2178 > multipleDefinitions?: GoToLocationValues;
2179 > multipleTypeDefinitions?: GoToLocationValues;
2180 > multipleDeclarations?: GoToLocationValues;
2181 > multipleImplementations?: GoToLocationValues;
2182 > multipleReferences?: GoToLocationValues;
2183 > multipleTests?: GoToLocationValues;
2184 >
2185 > alternativeDefinitionCommand?: string;
2186 > alternativeTypeDefinitionCommand?: string;
2187 > alternativeDeclarationCommand?: string;
2188 > alternativeImplementationCommand?: string;
2189 > alternativeReferenceCommand?: string;
2190 > alternativeTestsCommand?: string;
2191 > }
2192 >
2193 > /**
2194 > * @internal
2195 > */
2196 > export type GoToLocationOptions = Readonly<Required<IGotoLocationOptions>>;
2197 >
2198 > class EditorGoToLocation extends BaseEditorOption<EditorOption.gotoLocation, IGotoLocationOptions, GoToLocationOptions> {
2199 >
2200 > constructor() {
2201 > const defaults: GoToLocationOptions = {
2202 > multiple: 'peek',
2203 > multipleDefinitions: 'peek',
2204 > multipleTypeDefinitions: 'peek',
2205 > multipleDeclarations: 'peek',
2206 > multipleImplementations: 'peek',
2207 > multipleReferences: 'peek',
2208 > multipleTests: 'peek',
2209 > alternativeDefinitionCommand: 'editor.action.goToReferences',
2210 > alternativeTypeDefinitionCommand: 'editor.action.goToReferences',
2211 > alternativeDeclarationCommand: 'editor.action.goToReferences',
2212 > alternativeImplementationCommand: '',
2213 > alternativeReferenceCommand: '',
2214 > alternativeTestsCommand: '',
2215 > };
2216 > const jsonSubset: IJSONSchema = {
2217 > type: 'string',
2218 > enum: ['peek', 'gotoAndPeek', 'goto'],
2219 > default: defaults.multiple,
2220 > enumDescriptions: [
2221 > nls.localize('editor.gotoLocation.multiple.peek', 'Show Peek view of the results (default)'),
2222 > nls.localize('editor.gotoLocation.multiple.gotoAndPeek', 'Go to the primary result and show a Peek view'),
2223 > nls.localize('editor.gotoLocation.multiple.goto', 'Go to the primary result and enable Peek-less navigation to others')
2224 > ]
2225 > };
2226 > const alternativeCommandOptions = ['', 'editor.action.referenceSearch.trigger', 'editor.action.goToReferences', 'editor.action.peekImplementation', 'editor.action.goToImplementation', 'editor.action.peekTypeDefinition', 'editor.action.goToTypeDefinition', 'editor.action.peekDeclaration', 'editor.action.revealDeclaration', 'editor.action.peekDefinition', 'editor.action.revealDefinitionAside', 'editor.action.revealDefinition'];
2227 > super(
2228 > EditorOption.gotoLocation, 'gotoLocation', defaults,
2229 > {
2230 > 'editor.gotoLocation.multiple': {
2231 > deprecationMessage: nls.localize('editor.gotoLocation.multiple.deprecated', "This setting is deprecated, please use separate settings like 'editor.editor.gotoLocation.multipleDefinitions' or 'editor.editor.gotoLocation.multipleImplementations' instead."),
2232 > },
2233 > 'editor.gotoLocation.multipleDefinitions': {
2234 > description: nls.localize('editor.editor.gotoLocation.multipleDefinitions', "Controls the behavior the 'Go to Definition'-command when multiple target locations exist."),
2235 > ...jsonSubset,
2236 > },
2237 > 'editor.gotoLocation.multipleTypeDefinitions': {
2238 > description: nls.localize('editor.editor.gotoLocation.multipleTypeDefinitions', "Controls the behavior the 'Go to Type Definition'-command when multiple target locations exist."),
2239 > ...jsonSubset,
2240 > },
2241 > 'editor.gotoLocation.multipleDeclarations': {
2242 > description: nls.localize('editor.editor.gotoLocation.multipleDeclarations', "Controls the behavior the 'Go to Declaration'-command when multiple target locations exist."),
2243 > ...jsonSubset,
2244 > },
2245 > 'editor.gotoLocation.multipleImplementations': {
2246 > description: nls.localize('editor.editor.gotoLocation.multipleImplemenattions', "Controls the behavior the 'Go to Implementations'-command when multiple target locations exist."),
2247 > ...jsonSubset,
2248 > },
2249 > 'editor.gotoLocation.multipleReferences': {
2250 > description: nls.localize('editor.editor.gotoLocation.multipleReferences', "Controls the behavior the 'Go to References'-command when multiple target locations exist."),
2251 > ...jsonSubset,
2252 > },
2253 > 'editor.gotoLocation.alternativeDefinitionCommand': {
2254 > type: 'string',
2255 > default: defaults.alternativeDefinitionCommand,
2256 > enum: alternativeCommandOptions,
2257 > description: nls.localize('alternativeDefinitionCommand', "Alternative command id that is being executed when the result of 'Go to Definition' is the current location.")
2258 > },
2259 > 'editor.gotoLocation.alternativeTypeDefinitionCommand': {
2260 > type: 'string',
2261 > default: defaults.alternativeTypeDefinitionCommand,
2262 > enum: alternativeCommandOptions,
2263 > description: nls.localize('alternativeTypeDefinitionCommand', "Alternative command id that is being executed when the result of 'Go to Type Definition' is the current location.")
2264 > },
2265 > 'editor.gotoLocation.alternativeDeclarationCommand': {
2266 > type: 'string',
2267 > default: defaults.alternativeDeclarationCommand,
2268 > enum: alternativeCommandOptions,
2269 > description: nls.localize('alternativeDeclarationCommand', "Alternative command id that is being executed when the result of 'Go to Declaration' is the current location.")
2270 > },
2271 > 'editor.gotoLocation.alternativeImplementationCommand': {
2272 > type: 'string',
2273 > default: defaults.alternativeImplementationCommand,
2274 > enum: alternativeCommandOptions,
2275 > description: nls.localize('alternativeImplementationCommand', "Alternative command id that is being executed when the result of 'Go to Implementation' is the current location.")
2276 > },
2277 > 'editor.gotoLocation.alternativeReferenceCommand': {
2278 > type: 'string',
2279 > default: defaults.alternativeReferenceCommand,
2280 > enum: alternativeCommandOptions,
2281 > description: nls.localize('alternativeReferenceCommand', "Alternative command id that is being executed when the result of 'Go to Reference' is the current location.")
2282 > },
2283 > }
2284 > );
2285 > }
2286 >
2287 > public validate(_input: unknown): GoToLocationOptions {
2288 if (!_input || typeof _input !== 'object') {
2289 return this.defaultValue;
2306 };
2307 }
2308 > } editorOptions.ts
2309 >
2310 > //#endregion
2311 >
2312 > //#region hover
2313 >
2314 > /**
2315 > * Configuration options for editor hover
2316 > */
2317 > export interface IEditorHoverOptions {
2318 > /**
2319 > * Enable the hover.
2320 > * Defaults to 'on'.
2321 > */
2322 > enabled?: 'on' | 'off' | 'onKeyboardModifier';
2323 > /**
2324 > * Delay for showing the hover.
2325 > * Defaults to 300.
2326 > */
2327 > delay?: number;
2328 > /**
2329 > * Is the hover sticky such that it can be clicked and its contents selected?
2330 > * Defaults to true.
2331 > */
2332 > sticky?: boolean;
2333 > /**
2334 > * Controls how long the hover is visible after you hovered out of it.
2335 > * Require sticky setting to be true.
2336 > */
2337 > hidingDelay?: number;
2338 > /**
2339 > * Should the hover be shown above the line if possible?
2340 > * Defaults to false.
2341 > */
2342 > above?: boolean;
2343 > /**
2344 > * Should long line warning hovers be shown (tokenization skipped, rendering paused)?
2345 > * Defaults to true.
2346 > */
2347 > showLongLineWarning?: boolean;
2348 > }
2349 >
2350 > /**
2351 > * @internal
2352 > */
2353 > export type EditorHoverOptions = Readonly<Required<IEditorHoverOptions>>;
2354 >
2355 > class EditorHover extends BaseEditorOption<EditorOption.hover, IEditorHoverOptions, EditorHoverOptions> {
2356 >
2357 > constructor() {
2358 > const defaults: EditorHoverOptions = {
2359 > enabled: 'on',
2360 > delay: 300,
2361 > hidingDelay: 300,
2362 > sticky: true,
2363 > above: true,
2364 > showLongLineWarning: true,
2365 > };
2366 > super(
2367 > EditorOption.hover, 'hover', defaults,
2368 > {
2369 > 'editor.hover.enabled': {
2370 > type: 'string',
2371 > enum: ['on', 'off', 'onKeyboardModifier'],
2372 > default: defaults.enabled,
2373 > markdownEnumDescriptions: [
2374 > nls.localize('hover.enabled.on', "Hover is enabled."),
2375 > nls.localize('hover.enabled.off', "Hover is disabled."),
2376 > nls.localize('hover.enabled.onKeyboardModifier', "Hover is shown when holding `{0}` or `Alt` (the opposite modifier of `#editor.multiCursorModifier#`)", platform.isMacintosh ? `Command` : `Control`)
2377 > ],
2378 > description: nls.localize('hover.enabled', "Controls whether the hover is shown."),
2379 > keywords: ['hint', 'info', 'tooltip']
2380 > },
2381 > 'editor.hover.delay': {
2382 > type: 'number',
2383 > default: defaults.delay,
2384 > minimum: 0,
2385 > maximum: 10000,
2386 > description: nls.localize('hover.delay', "Controls the delay in milliseconds after which the hover is shown.")
2387 > },
2388 > 'editor.hover.sticky': {
2389 > type: 'boolean',
2390 > default: defaults.sticky,
2391 > description: nls.localize('hover.sticky', "Controls whether the hover should remain visible when mouse is moved over it.")
2392 > },
2393 > 'editor.hover.hidingDelay': {
2394 > type: 'integer',
2395 > minimum: 0,
2396 > default: defaults.hidingDelay,
2397 > markdownDescription: nls.localize('hover.hidingDelay', "Controls the delay in milliseconds after which the hover is hidden. Requires `#editor.hover.sticky#` to be enabled.")
2398 > },
2399 > 'editor.hover.above': {
2400 > type: 'boolean',
2401 > default: defaults.above,
2402 > description: nls.localize('hover.above', "Prefer showing hovers above the line, if there's space.")
2403 > },
2404 > 'editor.hover.showLongLineWarning': {
2405 > type: 'boolean',
2406 > default: defaults.showLongLineWarning,
2407 > description: nls.localize('hover.showLongLineWarning', "Controls whether long line warning hovers are shown, such as when tokenization is skipped or rendering is paused.")
2408 > },
2409 > }
2410 > );
2411 > }
2412 >
2413 > public validate(_input: unknown): EditorHoverOptions {
2414 if (!_input || typeof _input !== 'object') {
2415 return this.defaultValue;
2425 };
2426 }
2427 > } editorOptions.ts
2428 >
2429 > //#endregion
2430 >
2431 > //#region layoutInfo
2432 >
2433 > /**
2434 > * A description for the overview ruler position.
2435 > */
2436 > export interface OverviewRulerPosition {
2437 > /**
2438 > * Width of the overview ruler
2439 > */
2440 > readonly width: number;
2441 > /**
2442 > * Height of the overview ruler
2443 > */
2444 > readonly height: number;
2445 > /**
2446 > * Top position for the overview ruler
2447 > */
2448 > readonly top: number;
2449 > /**
2450 > * Right position for the overview ruler
2451 > */
2452 > readonly right: number;
2453 > }
2454 >
2455 > export const enum RenderMinimap {
2456 > None = 0,
2457 > Text = 1,
2458 > Blocks = 2,
2459 > }
2460 >
2461 > /**
2462 > * The internal layout details of the editor.
2463 > */
2464 > export interface EditorLayoutInfo {
2465 >
2466 > /**
2467 > * Full editor width.
2468 > */
2469 > readonly width: number;
2470 > /**
2471 > * Full editor height.
2472 > */
2473 > readonly height: number;
2474 >
2475 > /**
2476 > * Left position for the glyph margin.
2477 > */
2478 > readonly glyphMarginLeft: number;
2479 > /**
2480 > * The width of the glyph margin.
2481 > */
2482 > readonly glyphMarginWidth: number;
2483 >
2484 > /**
2485 > * The number of decoration lanes to render in the glyph margin.
2486 > */
2487 > readonly glyphMarginDecorationLaneCount: number;
2488 >
2489 > /**
2490 > * Left position for the line numbers.
2491 > */
2492 > readonly lineNumbersLeft: number;
2493 > /**
2494 > * The width of the line numbers.
2495 > */
2496 > readonly lineNumbersWidth: number;
2497 >
2498 > /**
2499 > * Left position for the line decorations.
2500 > */
2501 > readonly decorationsLeft: number;
2502 > /**
2503 > * The width of the line decorations.
2504 > */
2505 > readonly decorationsWidth: number;
2506 >
2507 > /**
2508 > * Left position for the content (actual text)
2509 > */
2510 > readonly contentLeft: number;
2511 > /**
2512 > * The width of the content (actual text)
2513 > */
2514 > readonly contentWidth: number;
2515 >
2516 > /**
2517 > * Layout information for the minimap
2518 > */
2519 > readonly minimap: EditorMinimapLayoutInfo;
2520 >
2521 > /**
2522 > * The number of columns (of typical characters) fitting on a viewport line.
2523 > */
2524 > readonly viewportColumn: number;
2525 >
2526 > readonly isWordWrapMinified: boolean;
2527 > readonly isViewportWrapping: boolean;
2528 > readonly wrappingColumn: number;
2529 >
2530 > /**
2531 > * The width of the vertical scrollbar.
2532 > */
2533 > readonly verticalScrollbarWidth: number;
2534 > /**
2535 > * The height of the horizontal scrollbar.
2536 > */
2537 > readonly horizontalScrollbarHeight: number;
2538 >
2539 > /**
2540 > * The position of the overview ruler.
2541 > */
2542 > readonly overviewRuler: OverviewRulerPosition;
2543 > }
2544 >
2545 > /**
2546 > * The internal layout details of the editor.
2547 > */
2548 > export interface EditorMinimapLayoutInfo {
2549 > readonly renderMinimap: RenderMinimap;
2550 > readonly minimapLeft: number;
2551 > readonly minimapWidth: number;
2552 > readonly minimapHeightIsEditorHeight: boolean;
2553 > readonly minimapIsSampling: boolean;
2554 > readonly minimapScale: number;
2555 > readonly minimapLineHeight: number;
2556 > readonly minimapCanvasInnerWidth: number;
2557 > readonly minimapCanvasInnerHeight: number;
2558 > readonly minimapCanvasOuterWidth: number;
2559 > readonly minimapCanvasOuterHeight: number;
2560 > }
2561 >
2562 > /**
2563 > * @internal
2564 > */
2565 > export interface EditorLayoutInfoComputerEnv {
2566 > readonly memory: ComputeOptionsMemory | null;
2567 > readonly outerWidth: number;
2568 > readonly outerHeight: number;
2569 > readonly isDominatedByLongLines: boolean;
2570 > readonly lineHeight: number;
2571 > readonly viewLineCount: number;
2572 > readonly lineNumbersDigitCount: number;
2573 > readonly typicalHalfwidthCharacterWidth: number;
2574 > readonly maxDigitWidth: number;
2575 > readonly pixelRatio: number;
2576 > readonly glyphMarginDecorationLaneCount: number;
2577 > }
2578 >
2579 > /**
2580 > * @internal
2581 > */
2582 > export interface IEditorLayoutComputerInput {
2583 > readonly outerWidth: number;
2584 > readonly outerHeight: number;
2585 > readonly isDominatedByLongLines: boolean;
2586 > readonly lineHeight: number;
2587 > readonly lineNumbersDigitCount: number;
2588 > readonly typicalHalfwidthCharacterWidth: number;
2589 > readonly maxDigitWidth: number;
2590 > readonly pixelRatio: number;
2591 > readonly glyphMargin: boolean;
2592 > readonly lineDecorationsWidth: string | number;
2593 > readonly folding: boolean;
2594 > readonly minimap: Readonly<Required<IEditorMinimapOptions>>;
2595 > readonly scrollbar: InternalEditorScrollbarOptions;
2596 > readonly lineNumbers: InternalEditorRenderLineNumbersOptions;
2597 > readonly lineNumbersMinChars: number;
2598 > readonly scrollBeyondLastLine: boolean;
2599 > readonly wordWrap: 'wordWrapColumn' | 'on' | 'off' | 'bounded';
2600 > readonly wordWrapColumn: number;
2601 > readonly wordWrapMinified: boolean;
2602 > readonly accessibilitySupport: AccessibilitySupport;
2603 > }
2604 >
2605 > /**
2606 > * @internal
2607 > */
2608 > export interface IMinimapLayoutInput {
2609 > readonly outerWidth: number;
2610 > readonly outerHeight: number;
2611 > readonly lineHeight: number;
2612 > readonly typicalHalfwidthCharacterWidth: number;
2613 > readonly pixelRatio: number;
2614 > readonly scrollBeyondLastLine: boolean;
2615 > readonly paddingTop: number;
2616 > readonly paddingBottom: number;
2617 > readonly minimap: Readonly<Required<IEditorMinimapOptions>>;
2618 > readonly verticalScrollbarWidth: number;
2619 > readonly viewLineCount: number;
2620 > readonly remainingWidth: number;
2621 > readonly isViewportWrapping: boolean;
2622 > }
2623 >
2624 > /**
2625 > * @internal
2626 > */
2627 > export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.layoutInfo, EditorLayoutInfo> {
2628 >
2629 > constructor() {
2630 > super(EditorOption.layoutInfo, {
2631 > width: 0,
2632 > height: 0,
2633 > glyphMarginLeft: 0,
2634 > glyphMarginWidth: 0,
2635 > glyphMarginDecorationLaneCount: 0,
2636 > lineNumbersLeft: 0,
2637 > lineNumbersWidth: 0,
2638 > decorationsLeft: 0,
2639 > decorationsWidth: 0,
2640 > contentLeft: 0,
2641 > contentWidth: 0,
2642 > minimap: {
2643 > renderMinimap: RenderMinimap.None,
2644 > minimapLeft: 0,
2645 > minimapWidth: 0,
2646 > minimapHeightIsEditorHeight: false,
2647 > minimapIsSampling: false,
2648 > minimapScale: 1,
2649 > minimapLineHeight: 1,
2650 > minimapCanvasInnerWidth: 0,
2651 > minimapCanvasInnerHeight: 0,
2652 > minimapCanvasOuterWidth: 0,
2653 > minimapCanvasOuterHeight: 0,
2654 > },
2655 > viewportColumn: 0,
2656 > isWordWrapMinified: false,
2657 > isViewportWrapping: false,
2658 > wrappingColumn: -1,
2659 > verticalScrollbarWidth: 0,
2660 > horizontalScrollbarHeight: 0,
2661 > overviewRuler: {
2662 > top: 0,
2663 > width: 0,
2664 > height: 0,
2665 > right: 0
2666 > }
2667 > });
2668 > }
2669 >
2670 > public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: EditorLayoutInfo): EditorLayoutInfo {
2671 return EditorLayoutInfoComputer.computeLayout(options, {
2672 memory: env.memory,
2683 });
2684 }
2686 > public static computeContainedMinimapLineCount(input: {
2687 viewLineCount: number;
2688 scrollBeyondLastLine: boolean;
2703 return { typicalViewportLineCount, extraLinesBeforeFirstLine, extraLinesBeyondLastLine, desiredRatio, minimapLineCount };
2704 }
2706 > private static _computeMinimapLayout(input: IMinimapLayoutInput, memory: ComputeOptionsMemory): EditorMinimapLayoutInfo {
2707 const outerWidth = input.outerWidth;
2708 const outerHeight = input.outerHeight;
2879 };
2880 }
2882 > public static computeLayout(options: IComputedEditorOptions, env: EditorLayoutInfoComputerEnv): EditorLayoutInfo {
2883 const outerWidth = env.outerWidth | 0;
2884 const outerHeight = env.outerHeight | 0;
3024 };
3025 }
3026 > } editorOptions.ts
3027 >
3028 > //#endregion
3029 >
3030 > //#region WrappingStrategy
3031 > class WrappingStrategy extends BaseEditorOption<EditorOption.wrappingStrategy, 'simple' | 'advanced', 'simple' | 'advanced'> {
3032 >
3033 > constructor() {
3034 > super(EditorOption.wrappingStrategy, 'wrappingStrategy', 'simple',
3035 > {
3036 > 'editor.wrappingStrategy': {
3037 > enumDescriptions: [
3038 > nls.localize('wrappingStrategy.simple', "Assumes that all characters are of the same width. This is a fast algorithm that works correctly for monospace fonts and certain scripts (like Latin characters) where glyphs are of equal width."),
3039 > nls.localize('wrappingStrategy.advanced', "Delegates wrapping points computation to the browser. This is a slow algorithm, that might cause freezes for large files, but it works correctly in all cases.")
3040 > ],
3041 > type: 'string',
3042 > enum: ['simple', 'advanced'],
3043 > default: 'simple',
3044 > description: nls.localize('wrappingStrategy', "Controls the algorithm that computes wrapping points. Note that when in accessibility mode, advanced will be used for the best experience.")
3045 > }
3046 > }
3047 > );
3048 > }
3049 >
3050 > public validate(input: unknown): 'simple' | 'advanced' {
3051 return stringSet<'simple' | 'advanced'>(input, 'simple', ['simple', 'advanced']);
3052 }
3054 > public override compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: 'simple' | 'advanced'): 'simple' | 'advanced' {
3055 const accessibilitySupport = options.get(EditorOption.accessibilitySupport);
3056 if (accessibilitySupport === AccessibilitySupport.Enabled) {
3061 return value;
3062 }
3063 > } editorOptions.ts
3064 > //#endregion
3065 >
3066 > //#region lightbulb
3067 >
3068 > export enum ShowLightbulbIconMode {
3069 > Off = 'off',
3070 > OnCode = 'onCode',
3071 > On = 'on'
3072 > }
3073 >
3074 > /**
3075 > * Configuration options for editor lightbulb
3076 > */
3077 > export interface IEditorLightbulbOptions {
3078 > /**
3079 > * Enable the lightbulb code action.
3080 > * The three possible values are `off`, `on` and `onCode` and the default is `onCode`.
3081 > * `off` disables the code action menu.
3082 > * `on` shows the code action menu on code and on empty lines.
3083 > * `onCode` shows the code action menu on code only.
3084 > */
3085 > enabled?: ShowLightbulbIconMode;
3086 > }
3087 >
3088 > /**
3089 > * @internal
3090 > */
3091 > export type EditorLightbulbOptions = Readonly<Required<IEditorLightbulbOptions>>;
3092 >
3093 > class EditorLightbulb extends BaseEditorOption<EditorOption.lightbulb, IEditorLightbulbOptions, EditorLightbulbOptions> {
3094 >
3095 > constructor() {
3096 > const defaults: EditorLightbulbOptions = { enabled: ShowLightbulbIconMode.OnCode };
3097 > super(
3098 > EditorOption.lightbulb, 'lightbulb', defaults,
3099 > {
3100 > 'editor.lightbulb.enabled': {
3101 > type: 'string',
3102 > enum: [ShowLightbulbIconMode.Off, ShowLightbulbIconMode.OnCode, ShowLightbulbIconMode.On],
3103 > default: defaults.enabled,
3104 > enumDescriptions: [
3105 > nls.localize('editor.lightbulb.enabled.off', 'Disable the code action menu.'),
3106 > nls.localize('editor.lightbulb.enabled.onCode', 'Show the code action menu when the cursor is on lines with code.'),
3107 > nls.localize('editor.lightbulb.enabled.on', 'Show the code action menu when the cursor is on lines with code or on empty lines.'),
3108 > ],
3109 > description: nls.localize('enabled', "Enables the Code Action lightbulb in the editor.")
3110 > }
3111 > }
3112 > );
3113 > }
3114 >
3115 > public validate(_input: unknown): EditorLightbulbOptions {
3116 if (!_input || typeof _input !== 'object') {
3117 return this.defaultValue;
3122 };
3123 }
3124 > } editorOptions.ts
3125 >
3126 > //#endregion
3127 >
3128 > //#region stickyScroll
3129 >
3130 > export interface IEditorStickyScrollOptions {
3131 > /**
3132 > * Enable the sticky scroll
3133 > */
3134 > enabled?: boolean;
3135 > /**
3136 > * Maximum number of sticky lines to show
3137 > */
3138 > maxLineCount?: number;
3139 > /**
3140 > * Model to choose for sticky scroll by default
3141 > */
3142 > defaultModel?: 'outlineModel' | 'foldingProviderModel' | 'indentationModel';
3143 > /**
3144 > * Define whether to scroll sticky scroll with editor horizontal scrollbae
3145 > */
3146 > scrollWithEditor?: boolean;
3147 > }
3148 >
3149 > /**
3150 > * @internal
3151 > */
3152 > export type EditorStickyScrollOptions = Readonly<Required<IEditorStickyScrollOptions>>;
3153 >
3154 > class EditorStickyScroll extends BaseEditorOption<EditorOption.stickyScroll, IEditorStickyScrollOptions, EditorStickyScrollOptions> {
3155 >
3156 > constructor() {
3157 > const defaults: EditorStickyScrollOptions = { enabled: true, maxLineCount: 5, defaultModel: 'outlineModel', scrollWithEditor: true };
3158 > super(
3159 > EditorOption.stickyScroll, 'stickyScroll', defaults,
3160 > {
3161 > 'editor.stickyScroll.enabled': {
3162 > type: 'boolean',
3163 > default: defaults.enabled,
3164 > description: nls.localize('editor.stickyScroll.enabled', "Shows the nested current scopes during the scroll at the top of the editor.")
3165 > },
3166 > 'editor.stickyScroll.maxLineCount': {
3167 > type: 'number',
3168 > default: defaults.maxLineCount,
3169 > minimum: 1,
3170 > maximum: 20,
3171 > description: nls.localize('editor.stickyScroll.maxLineCount', "Defines the maximum number of sticky lines to show.")
3172 > },
3173 > 'editor.stickyScroll.defaultModel': {
3174 > type: 'string',
3175 > enum: ['outlineModel', 'foldingProviderModel', 'indentationModel'],
3176 > default: defaults.defaultModel,
3177 > description: nls.localize('editor.stickyScroll.defaultModel', "Defines the model to use for determining which lines to stick. If the outline model does not exist, it will fall back on the folding provider model which falls back on the indentation model. This order is respected in all three cases.")
3178 > },
3179 > 'editor.stickyScroll.scrollWithEditor': {
3180 > type: 'boolean',
3181 > default: defaults.scrollWithEditor,
3182 > description: nls.localize('editor.stickyScroll.scrollWithEditor', "Enable scrolling of Sticky Scroll with the editor's horizontal scrollbar.")
3183 > },
3184 > }
3185 > );
3186 > }
3187 >
3188 > public validate(_input: unknown): EditorStickyScrollOptions {
3189 if (!_input || typeof _input !== 'object') {
3190 return this.defaultValue;
3198 };
3199 }
3200 > } editorOptions.ts
3201 >
3202 > //#endregion
3203 >
3204 > //#region inlayHints
3205 >
3206 > /**
3207 > * Configuration options for editor inlayHints
3208 > */
3209 > export interface IEditorInlayHintsOptions {
3210 > /**
3211 > * Enable the inline hints.
3212 > * Defaults to true.
3213 > */
3214 > enabled?: 'on' | 'off' | 'offUnlessPressed' | 'onUnlessPressed';
3215 >
3216 > /**
3217 > * Font size of inline hints.
3218 > * Default to 90% of the editor font size.
3219 > */
3220 > fontSize?: number;
3221 >
3222 > /**
3223 > * Font family of inline hints.
3224 > * Defaults to editor font family.
3225 > */
3226 > fontFamily?: string;
3227 >
3228 > /**
3229 > * Enables the padding around the inlay hint.
3230 > * Defaults to false.
3231 > */
3232 > padding?: boolean;
3233 >
3234 > /**
3235 > * Maximum length for inlay hints per line
3236 > * Set to 0 to have an unlimited length.
3237 > */
3238 > maximumLength?: number;
3239 > }
3240 >
3241 > /**
3242 > * @internal
3243 > */
3244 > export type EditorInlayHintsOptions = Readonly<Required<IEditorInlayHintsOptions>>;
3245 >
3246 > class EditorInlayHints extends BaseEditorOption<EditorOption.inlayHints, IEditorInlayHintsOptions, EditorInlayHintsOptions> {
3247 >
3248 > constructor() {
3249 > const defaults: EditorInlayHintsOptions = { enabled: 'on', fontSize: 0, fontFamily: '', padding: false, maximumLength: 43 };
3250 > super(
3251 > EditorOption.inlayHints, 'inlayHints', defaults,
3252 > {
3253 > 'editor.inlayHints.enabled': {
3254 > type: 'string',
3255 > default: defaults.enabled,
3256 > description: nls.localize('inlayHints.enable', "Enables the inlay hints in the editor."),
3257 > enum: ['on', 'onUnlessPressed', 'offUnlessPressed', 'off'],
3258 > markdownEnumDescriptions: [
3259 > nls.localize('editor.inlayHints.on', "Inlay hints are enabled"),
3260 > nls.localize('editor.inlayHints.onUnlessPressed', "Inlay hints are showing by default and hide when holding {0}", platform.isMacintosh ? `Ctrl+Option` : `Ctrl+Alt`),
3261 > nls.localize('editor.inlayHints.offUnlessPressed', "Inlay hints are hidden by default and show when holding {0}", platform.isMacintosh ? `Ctrl+Option` : `Ctrl+Alt`),
3262 > nls.localize('editor.inlayHints.off', "Inlay hints are disabled"),
3263 > ],
3264 > },
3265 > 'editor.inlayHints.fontSize': {
3266 > type: 'number',
3267 > default: defaults.fontSize,
3268 > markdownDescription: nls.localize('inlayHints.fontSize', "Controls font size of inlay hints in the editor. As default the {0} is used when the configured value is less than {1} or greater than the editor font size.", '`#editor.fontSize#`', '`5`')
3269 > },
3270 > 'editor.inlayHints.fontFamily': {
3271 > type: 'string',
3272 > default: defaults.fontFamily,
3273 > markdownDescription: nls.localize('inlayHints.fontFamily', "Controls font family of inlay hints in the editor. When set to empty, the {0} is used.", '`#editor.fontFamily#`')
3274 > },
3275 > 'editor.inlayHints.padding': {
3276 > type: 'boolean',
3277 > default: defaults.padding,
3278 > description: nls.localize('inlayHints.padding', "Enables the padding around the inlay hints in the editor.")
3279 > },
3280 > 'editor.inlayHints.maximumLength': {
3281 > type: 'number',
3282 > default: defaults.maximumLength,
3283 > markdownDescription: nls.localize('inlayHints.maximumLength', "Maximum overall length of inlay hints, for a single line, before they get truncated by the editor. Set to `0` to never truncate")
3284 > }
3285 > }
3286 > );
3287 > }
3288 >
3289 > public validate(_input: unknown): EditorInlayHintsOptions {
3290 if (!_input || typeof _input !== 'object') {
3291 return this.defaultValue;
3303 };
3304 }
3305 > } editorOptions.ts
3306 >
3307 > //#endregion
3308 >
3309 > //#region lineDecorationsWidth
3310 >
3311 > class EditorLineDecorationsWidth extends BaseEditorOption<EditorOption.lineDecorationsWidth, number | string, number> {
3312 >
3313 > constructor() {
3314 > super(EditorOption.lineDecorationsWidth, 'lineDecorationsWidth', 10);
3315 > }
3316 >
3317 > public validate(input: unknown): number {
3318 if (typeof input === 'string' && /^\d+(\.\d+)?ch$/.test(input)) {
3319 const multiple = parseFloat(input.substring(0, input.length - 2));
3323 }
3324 }
3326 > public override compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: number): number {
3327 if (value < 0) {
3328 // negative numbers signal a multiple
3332 }
3333 }
3334 > } editorOptions.ts
3335 >
3336 > //#endregion
3337 >
3338 > //#region lineHeight
3339 >
3340 > class EditorLineHeight extends EditorFloatOption<EditorOption.lineHeight> {
3341 >
3342 > constructor() {
3343 > super(
3344 > EditorOption.lineHeight, 'lineHeight',
3345 > EDITOR_FONT_DEFAULTS.lineHeight,
3346 > x => EditorFloatOption.clamp(x, 0, 150),
3347 > { markdownDescription: nls.localize('lineHeight', "Controls the line height. \n - Use 0 to automatically compute the line height from the font size.\n - Values between 0 and 8 will be used as a multiplier with the font size.\n - Values greater than or equal to 8 will be used as effective values.") },
3348 > 0,
3349 > 150
3350 > );
3351 > }
3352 >
3353 > public override compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: number): number {
3354 // The lineHeight is computed from the fontSize if it is 0.
3355 // Moreover, the final lineHeight respects the editor zoom level.
3357 return env.fontInfo.lineHeight;
3358 }
3359 > } editorOptions.ts
3360 >
3361 > //#endregion
3362 >
3363 > //#region minimap
3364 >
3365 > /**
3366 > * Configuration options for editor minimap
3367 > */
3368 > export interface IEditorMinimapOptions {
3369 > /**
3370 > * Enable the rendering of the minimap.
3371 > * Defaults to true.
3372 > */
3373 > enabled?: boolean;
3374 > /**
3375 > * Control the rendering of minimap.
3376 > */
3377 > autohide?: 'none' | 'mouseover' | 'scroll';
3378 > /**
3379 > * Control the side of the minimap in editor.
3380 > * Defaults to 'right'.
3381 > */
3382 > side?: 'right' | 'left';
3383 > /**
3384 > * Control the minimap rendering mode.
3385 > * Defaults to 'actual'.
3386 > */
3387 > size?: 'proportional' | 'fill' | 'fit';
3388 > /**
3389 > * Control the rendering of the minimap slider.
3390 > * Defaults to 'mouseover'.
3391 > */
3392 > showSlider?: 'always' | 'mouseover';
3393 > /**
3394 > * Render the actual text on a line (as opposed to color blocks).
3395 > * Defaults to true.
3396 > */
3397 > renderCharacters?: boolean;
3398 > /**
3399 > * Limit the width of the minimap to render at most a certain number of columns.
3400 > * Defaults to 120.
3401 > */
3402 > maxColumn?: number;
3403 > /**
3404 > * Relative size of the font in the minimap. Defaults to 1.
3405 > */
3406 > scale?: number;
3407 > /**
3408 > * Whether to show named regions as section headers. Defaults to true.
3409 > */
3410 > showRegionSectionHeaders?: boolean;
3411 > /**
3412 > * Whether to show MARK: comments as section headers. Defaults to true.
3413 > */
3414 > showMarkSectionHeaders?: boolean;
3415 > /**
3416 > * When specified, is used to create a custom section header parser regexp.
3417 > * Must contain a match group named 'label' (written as (?<label>.+)) that encapsulates the section header.
3418 > * Optionally can include another match group named 'separator'.
3419 > * To match multi-line headers like:
3420 > * // ==========
3421 > * // My Section
3422 > * // ==========
3423 > * Use a pattern like: ^={3,}\n^\/\/ *(?<label>[^\n]*?)\n^={3,}$
3424 > */
3425 > markSectionHeaderRegex?: string;
3426 > /**
3427 > * Font size of section headers. Defaults to 9.
3428 > */
3429 > sectionHeaderFontSize?: number;
3430 > /**
3431 > * Spacing between the section header characters (in CSS px). Defaults to 1.
3432 > */
3433 > sectionHeaderLetterSpacing?: number;
3434 > }
3435 >
3436 > /**
3437 > * @internal
3438 > */
3439 > export type EditorMinimapOptions = Readonly<Required<IEditorMinimapOptions>>;
3440 >
3441 > class EditorMinimap extends BaseEditorOption<EditorOption.minimap, IEditorMinimapOptions, EditorMinimapOptions> {
3442 >
3443 > constructor() {
3444 > const defaults: EditorMinimapOptions = {
3445 > enabled: true,
3446 > size: 'proportional',
3447 > side: 'right',
3448 > showSlider: 'mouseover',
3449 > autohide: 'none',
3450 > renderCharacters: true,
3451 > maxColumn: 120,
3452 > scale: 1,
3453 > showRegionSectionHeaders: true,
3454 > showMarkSectionHeaders: true,
3455 > markSectionHeaderRegex: '\\bMARK:\\s*(?<separator>\-?)\\s*(?<label>.*)$',
3456 > sectionHeaderFontSize: 9,
3457 > sectionHeaderLetterSpacing: 1,
3458 > };
3459 > super(
3460 > EditorOption.minimap, 'minimap', defaults,
3461 > {
3462 > 'editor.minimap.enabled': {
3463 > type: 'boolean',
3464 > default: defaults.enabled,
3465 > description: nls.localize('minimap.enabled', "Controls whether the minimap is shown.")
3466 > },
3467 > 'editor.minimap.autohide': {
3468 > type: 'string',
3469 > enum: ['none', 'mouseover', 'scroll'],
3470 > enumDescriptions: [
3471 > nls.localize('minimap.autohide.none', "The minimap is always shown."),
3472 > nls.localize('minimap.autohide.mouseover', "The minimap is hidden when mouse is not over the minimap and shown when mouse is over the minimap."),
3473 > nls.localize('minimap.autohide.scroll', "The minimap is only shown when the editor is scrolled"),
3474 > ],
3475 > default: defaults.autohide,
3476 > description: nls.localize('minimap.autohide', "Controls whether the minimap is hidden automatically.")
3477 > },
3478 > 'editor.minimap.size': {
3479 > type: 'string',
3480 > enum: ['proportional', 'fill', 'fit'],
3481 > enumDescriptions: [
3482 > nls.localize('minimap.size.proportional', "The minimap has the same size as the editor contents (and might scroll)."),
3483 > nls.localize('minimap.size.fill', "The minimap will stretch or shrink as necessary to fill the height of the editor (no scrolling)."),
3484 > nls.localize('minimap.size.fit', "The minimap will shrink as necessary to never be larger than the editor (no scrolling)."),
3485 > ],
3486 > default: defaults.size,
3487 > description: nls.localize('minimap.size', "Controls the size of the minimap.")
3488 > },
3489 > 'editor.minimap.side': {
3490 > type: 'string',
3491 > enum: ['left', 'right'],
3492 > default: defaults.side,
3493 > description: nls.localize('minimap.side', "Controls the side where to render the minimap.")
3494 > },
3495 > 'editor.minimap.showSlider': {
3496 > type: 'string',
3497 > enum: ['always', 'mouseover'],
3498 > default: defaults.showSlider,
3499 > description: nls.localize('minimap.showSlider', "Controls when the minimap slider is shown.")
3500 > },
3501 > 'editor.minimap.scale': {
3502 > type: 'number',
3503 > default: defaults.scale,
3504 > minimum: 1,
3505 > maximum: 3,
3506 > enum: [1, 2, 3],
3507 > description: nls.localize('minimap.scale', "Scale of content drawn in the minimap: 1, 2 or 3.")
3508 > },
3509 > 'editor.minimap.renderCharacters': {
3510 > type: 'boolean',
3511 > default: defaults.renderCharacters,
3512 > description: nls.localize('minimap.renderCharacters', "Render the actual characters on a line as opposed to color blocks.")
3513 > },
3514 > 'editor.minimap.maxColumn': {
3515 > type: 'number',
3516 > default: defaults.maxColumn,
3517 > description: nls.localize('minimap.maxColumn', "Limit the width of the minimap to render at most a certain number of columns.")
3518 > },
3519 > 'editor.minimap.showRegionSectionHeaders': {
3520 > type: 'boolean',
3521 > default: defaults.showRegionSectionHeaders,
3522 > description: nls.localize('minimap.showRegionSectionHeaders', "Controls whether named regions are shown as section headers in the minimap.")
3523 > },
3524 > 'editor.minimap.showMarkSectionHeaders': {
3525 > type: 'boolean',
3526 > default: defaults.showMarkSectionHeaders,
3527 > description: nls.localize('minimap.showMarkSectionHeaders', "Controls whether MARK: comments are shown as section headers in the minimap.")
3528 > },
3529 > 'editor.minimap.markSectionHeaderRegex': {
3530 > type: 'string',
3531 > default: defaults.markSectionHeaderRegex,
3532 > description: nls.localize('minimap.markSectionHeaderRegex', "Defines the regular expression used to find section headers in comments. The regex must contain a named match group `label` (written as `(?<label>.+)`) that encapsulates the section header, otherwise it will not work. Optionally you can include another match group named `separator`. Use \\n in the pattern to match multi-line headers."),
3533 > },
3534 > 'editor.minimap.sectionHeaderFontSize': {
3535 > type: 'number',
3536 > default: defaults.sectionHeaderFontSize,
3537 > description: nls.localize('minimap.sectionHeaderFontSize', "Controls the font size of section headers in the minimap.")
3538 > },
3539 > 'editor.minimap.sectionHeaderLetterSpacing': {
3540 > type: 'number',
3541 > default: defaults.sectionHeaderLetterSpacing,
3542 > description: nls.localize('minimap.sectionHeaderLetterSpacing', "Controls the amount of space (in pixels) between characters of section header. This helps the readability of the header in small font sizes.")
3543 > }
3544 > }
3545 > );
3546 > }
3547 >
3548 > public validate(_input: unknown): EditorMinimapOptions {
3549 if (!_input || typeof _input !== 'object') {
3550 return this.defaultValue;
3578 };
3579 }
3580 > } editorOptions.ts
3581 >
3582 > //#endregion
3583 >
3584 > //#region multiCursorModifier
3585 >
3586 function _multiCursorModifierFromString(multiCursorModifier: 'ctrlCmd' | 'alt'): 'altKey' | 'metaKey' | 'ctrlKey' {
3587 if (multiCursorModifier === 'ctrlCmd') {
3590 return 'altKey';
3591 }
3593 > //#endregion
3594 >
3595 > //#region padding
3596 >
3597 > /**
3598 > * Configuration options for editor padding
3599 > */
3600 > export interface IEditorPaddingOptions {
3601 > /**
3602 > * Spacing between top edge of editor and first line.
3603 > */
3604 > top?: number;
3605 > /**
3606 > * Spacing between bottom edge of editor and last line.
3607 > */
3608 > bottom?: number;
3609 > }
3610 >
3611 > /**
3612 > * @internal
3613 > */
3614 > export type InternalEditorPaddingOptions = Readonly<Required<IEditorPaddingOptions>>;
3615 >
3616 > class EditorPadding extends BaseEditorOption<EditorOption.padding, IEditorPaddingOptions, InternalEditorPaddingOptions> {
3617 >
3618 > constructor() {
3619 > super(
3620 > EditorOption.padding, 'padding', { top: 0, bottom: 0 },
3621 > {
3622 > 'editor.padding.top': {
3623 > type: 'number',
3624 > default: 0,
3625 > minimum: 0,
3626 > maximum: 1000,
3627 > description: nls.localize('padding.top', "Controls the amount of space between the top edge of the editor and the first line.")
3628 > },
3629 > 'editor.padding.bottom': {
3630 > type: 'number',
3631 > default: 0,
3632 > minimum: 0,
3633 > maximum: 1000,
3634 > description: nls.localize('padding.bottom', "Controls the amount of space between the bottom edge of the editor and the last line.")
3635 > }
3636 > }
3637 > );
3638 > }
3639 >
3640 > public validate(_input: unknown): InternalEditorPaddingOptions {
3641 if (!_input || typeof _input !== 'object') {
3642 return this.defaultValue;
3649 };
3650 }
3651 > } editorOptions.ts
3652 > //#endregion
3653 >
3654 > //#region parameterHints
3655 >
3656 > /**
3657 > * Configuration options for parameter hints
3658 > */
3659 > export interface IEditorParameterHintOptions {
3660 > /**
3661 > * Enable parameter hints.
3662 > * Defaults to true.
3663 > */
3664 > enabled?: boolean;
3665 > /**
3666 > * Enable cycling of parameter hints.
3667 > * Defaults to false.
3668 > */
3669 > cycle?: boolean;
3670 > }
3671 >
3672 > /**
3673 > * @internal
3674 > */
3675 > export type InternalParameterHintOptions = Readonly<Required<IEditorParameterHintOptions>>;
3676 >
3677 > class EditorParameterHints extends BaseEditorOption<EditorOption.parameterHints, IEditorParameterHintOptions, InternalParameterHintOptions> {
3678 >
3679 > constructor() {
3680 > const defaults: InternalParameterHintOptions = {
3681 > enabled: true,
3682 > cycle: true
3683 > };
3684 > super(
3685 > EditorOption.parameterHints, 'parameterHints', defaults,
3686 > {
3687 > 'editor.parameterHints.enabled': {
3688 > type: 'boolean',
3689 > default: defaults.enabled,
3690 > description: nls.localize('parameterHints.enabled', "Enables a pop-up that shows parameter documentation and type information as you type.")
3691 > },
3692 > 'editor.parameterHints.cycle': {
3693 > type: 'boolean',
3694 > default: defaults.cycle,
3695 > description: nls.localize('parameterHints.cycle', "Controls whether the parameter hints menu cycles or closes when reaching the end of the list.")
3696 > },
3697 > }
3698 > );
3699 > }
3700 >
3701 > public validate(_input: unknown): InternalParameterHintOptions {
3702 if (!_input || typeof _input !== 'object') {
3703 return this.defaultValue;
3709 };
3710 }
3711 > } editorOptions.ts
3712 >
3713 > //#endregion
3714 >
3715 > //#region pixelRatio
3716 >
3717 > class EditorPixelRatio extends ComputedEditorOption<EditorOption.pixelRatio, number> {
3718 >
3719 > constructor() {
3720 > super(EditorOption.pixelRatio, 1);
3721 > }
3722 >
3723 > public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: number): number {
3724 return env.pixelRatio;
3725 }
3726 > } editorOptions.ts
3727 >
3728 > //#endregion
3729 >
3730 > //#region
3731 >
3732 > class PlaceholderOption extends BaseEditorOption<EditorOption.placeholder, string | undefined, string | undefined> {
3733 > constructor() {
3734 > super(EditorOption.placeholder, 'placeholder', undefined);
3735 > }
3736 >
3737 > public validate(input: unknown): string | undefined {
3738 if (typeof input === 'undefined') {
3739 return this.defaultValue;
3744 return this.defaultValue;
3745 }
3746 > } editorOptions.ts
3747 > //#endregion
3748 >
3749 > //#region quickSuggestions
3750 >
3751 > export type QuickSuggestionsValue = 'on' | 'inline' | 'off' | 'offWhenInlineCompletions';
3752 >
3753 > /**
3754 > * Configuration options for quick suggestions
3755 > */
3756 > export interface IQuickSuggestionsOptions {
3757 > other?: boolean | QuickSuggestionsValue;
3758 > comments?: boolean | QuickSuggestionsValue;
3759 > strings?: boolean | QuickSuggestionsValue;
3760 > }
3761 >
3762 > export interface InternalQuickSuggestionsOptions {
3763 > readonly other: QuickSuggestionsValue;
3764 > readonly comments: QuickSuggestionsValue;
3765 > readonly strings: QuickSuggestionsValue;
3766 > }
3767 >
3768 > class EditorQuickSuggestions extends BaseEditorOption<EditorOption.quickSuggestions, boolean | QuickSuggestionsValue | IQuickSuggestionsOptions, InternalQuickSuggestionsOptions> {
3769 >
3770 > public override readonly defaultValue: InternalQuickSuggestionsOptions;
3771 >
3772 > constructor() {
3773 > const defaults: InternalQuickSuggestionsOptions = {
3774 > other: 'offWhenInlineCompletions',
3775 > comments: 'off',
3776 > strings: 'off'
3777 > };
3778 > const types: IJSONSchema[] = [
3779 > { type: 'boolean' },
3780 > {
3781 > type: 'string',
3782 > enum: ['on', 'inline', 'off', 'offWhenInlineCompletions'],
3783 > enumDescriptions: [nls.localize('on', "Quick suggestions show inside the suggest widget"), nls.localize('inline', "Quick suggestions show as ghost text"), nls.localize('off', "Quick suggestions are disabled"), nls.localize('offWhenInlineCompletions', "Quick suggestions are disabled when inline completions are showing")]
3784 > }
3785 > ];
3786 > super(EditorOption.quickSuggestions, 'quickSuggestions', defaults, {
3787 > anyOf: [
3788 > { type: 'boolean' },
3789 > {
3790 > type: 'string',
3791 > enum: ['on', 'inline', 'off', 'offWhenInlineCompletions'],
3792 > enumDescriptions: [nls.localize('quickSuggestions.topLevel.on', "Quick suggestions are enabled for all token types"), nls.localize('quickSuggestions.topLevel.inline', "Quick suggestions show as ghost text for all token types"), nls.localize('quickSuggestions.topLevel.off', "Quick suggestions are disabled for all token types"), nls.localize('quickSuggestions.topLevel.offWhenInlineCompletions', "Quick suggestions are disabled for all token types when inline completions are showing")]
3793 > },
3794 > {
3795 > type: 'object',
3796 > additionalProperties: false,
3797 > properties: {
3798 > strings: {
3799 > anyOf: types,
3800 > default: defaults.strings,
3801 > description: nls.localize('quickSuggestions.strings', "Enable quick suggestions inside strings.")
3802 > },
3803 > comments: {
3804 > anyOf: types,
3805 > default: defaults.comments,
3806 > description: nls.localize('quickSuggestions.comments', "Enable quick suggestions inside comments.")
3807 > },
3808 > other: {
3809 > anyOf: types,
3810 > default: defaults.other,
3811 > description: nls.localize('quickSuggestions.other', "Enable quick suggestions outside of strings and comments.")
3812 > },
3813 > },
3814 > }
3815 > ],
3816 > default: defaults,
3817 > markdownDescription: nls.localize('quickSuggestions', "Controls whether suggestions should automatically show up while typing. This can be controlled for typing in comments, strings, and other code. Quick suggestion can be configured to show as ghost text or with the suggest widget. Also be aware of the {0}-setting which controls if suggestions are triggered by special characters.", '`#editor.suggestOnTriggerCharacters#`'),
3818 > experiment: {
3819 > mode: 'auto'
3820 > }
3821 > });
3822 > this.defaultValue = defaults;
3823 > }
3824 >
3825 > public validate(input: unknown): InternalQuickSuggestionsOptions {
3826 if (typeof input === 'boolean') {
3827 // boolean -> all on/off
3867 };
3868 }
3869 > } editorOptions.ts
3870 >
3871 > //#endregion
3872 >
3873 > //#region renderLineNumbers
3874 >
3875 > export type LineNumbersType = 'on' | 'off' | 'relative' | 'interval' | ((lineNumber: number) => string);
3876 >
3877 > export const enum RenderLineNumbersType {
3878 > Off = 0,
3879 > On = 1,
3880 > Relative = 2,
3881 > Interval = 3,
3882 > Custom = 4
3883 > }
3884 >
3885 > export interface InternalEditorRenderLineNumbersOptions {
3886 > readonly renderType: RenderLineNumbersType;
3887 > readonly renderFn: ((lineNumber: number) => string) | null;
3888 > }
3889 >
3890 > class EditorRenderLineNumbersOption extends BaseEditorOption<EditorOption.lineNumbers, LineNumbersType, InternalEditorRenderLineNumbersOptions> {
3891 >
3892 > constructor() {
3893 > super(
3894 > EditorOption.lineNumbers, 'lineNumbers', { renderType: RenderLineNumbersType.On, renderFn: null },
3895 > {
3896 > type: 'string',
3897 > enum: ['off', 'on', 'relative', 'interval'],
3898 > enumDescriptions: [
3899 > nls.localize('lineNumbers.off', "Line numbers are not rendered."),
3900 > nls.localize('lineNumbers.on', "Line numbers are rendered as absolute number."),
3901 > nls.localize('lineNumbers.relative', "Line numbers are rendered as distance in lines to cursor position."),
3902 > nls.localize('lineNumbers.interval', "Line numbers are rendered every 10 lines.")
3903 > ],
3904 > default: 'on',
3905 > description: nls.localize('lineNumbers', "Controls the display of line numbers.")
3906 > }
3907 > );
3908 > }
3909 >
3910 > public validate(lineNumbers: unknown): InternalEditorRenderLineNumbersOptions {
3911 let renderType: RenderLineNumbersType = this.defaultValue.renderType;
3912 let renderFn: ((lineNumber: number) => string) | null = this.defaultValue.renderFn;
3932 };
3933 }
3934 > } editorOptions.ts
3935 >
3936 > //#endregion
3937 >
3938 > //#region renderValidationDecorations
3939 >
3940 > /**
3941 > * @internal
3942 > */
3943 > export function filterValidationDecorations(options: IComputedEditorOptions): boolean {
3944 const renderValidationDecorations = options.get(EditorOption.renderValidationDecorations);
3945 if (renderValidationDecorations === 'editable') {
3948 return renderValidationDecorations === 'on' ? false : true;
3949 }
3951 > //#endregion
3952 >
3953 > //#region filterFontDecorations
3954 >
3955 > /**
3956 > * @internal
3957 > */
3958 > export function filterFontDecorations(options: IComputedEditorOptions): boolean {
3959 return !options.get(EditorOption.effectiveAllowVariableFonts);
3960 }
3962 > //#endregion
3963 >
3964 > //#region rulers
3965 >
3966 > export interface IRulerOption {
3967 > readonly column: number;
3968 > readonly color: string | null;
3969 > }
3970 >
3971 > class EditorRulers extends BaseEditorOption<EditorOption.rulers, (number | IRulerOption)[], IRulerOption[]> {
3972 >
3973 > constructor() {
3974 > const defaults: IRulerOption[] = [];
3975 > const columnSchema: IJSONSchema = { type: 'number', description: nls.localize('rulers.size', "Number of monospace characters at which this editor ruler will render.") };
3976 > super(
3977 > EditorOption.rulers, 'rulers', defaults,
3978 > {
3979 > type: 'array',
3980 > items: {
3981 > anyOf: [
3982 > columnSchema,
3983 > {
3984 > type: [
3985 > 'object'
3986 > ],
3987 > properties: {
3988 > column: columnSchema,
3989 > color: {
3990 > type: 'string',
3991 > description: nls.localize('rulers.color', "Color of this editor ruler."),
3992 > format: 'color-hex'
3993 > }
3994 > }
3995 > }
3996 > ]
3997 > },
3998 > default: defaults,
3999 > description: nls.localize('rulers', "Render vertical rulers after a certain number of monospace characters. Use multiple values for multiple rulers. No rulers are drawn if array is empty.")
4000 > }
4001 > );
4002 > }
4003 >
4004 > public validate(input: unknown): IRulerOption[] {
4005 if (Array.isArray(input)) {
4006 const rulers: IRulerOption[] = [];
4024 return this.defaultValue;
4025 }
4026 > } editorOptions.ts
4027 >
4028 > //#endregion
4029 >
4030 > //#region readonly
4031 >
4032 > /**
4033 > * Configuration options for readonly message
4034 > */
4035 > class ReadonlyMessage extends BaseEditorOption<EditorOption.readOnlyMessage, IMarkdownString | undefined, IMarkdownString | undefined> {
4036 > constructor() {
4037 > const defaults = undefined;
4038 >
4039 > super(
4040 > EditorOption.readOnlyMessage, 'readOnlyMessage', defaults
4041 > );
4042 > }
4043 >
4044 > public validate(_input: unknown): IMarkdownString | undefined {
4045 if (!_input || typeof _input !== 'object') {
4046 return this.defaultValue;
4048 return _input as IMarkdownString;
4049 }
4050 > } editorOptions.ts
4051 >
4052 > //#endregion
4053 >
4054 > //#region scrollbar
4055 >
4056 > /**
4057 > * Configuration options for editor scrollbars
4058 > */
4059 > export interface IEditorScrollbarOptions {
4060 > /**
4061 > * The size of arrows (if displayed).
4062 > * Defaults to 11.
4063 > * **NOTE**: This option cannot be updated using `updateOptions()`
4064 > */
4065 > arrowSize?: number;
4066 > /**
4067 > * Render vertical scrollbar.
4068 > * Defaults to 'auto'.
4069 > */
4070 > vertical?: 'auto' | 'visible' | 'hidden';
4071 > /**
4072 > * Render horizontal scrollbar.
4073 > * Defaults to 'auto'.
4074 > */
4075 > horizontal?: 'auto' | 'visible' | 'hidden';
4076 > /**
4077 > * Cast horizontal and vertical shadows when the content is scrolled.
4078 > * Defaults to true.
4079 > * **NOTE**: This option cannot be updated using `updateOptions()`
4080 > */
4081 > useShadows?: boolean;
4082 > /**
4083 > * Render arrows at the top and bottom of the vertical scrollbar.
4084 > * Defaults to false.
4085 > * **NOTE**: This option cannot be updated using `updateOptions()`
4086 > */
4087 > verticalHasArrows?: boolean;
4088 > /**
4089 > * Render arrows at the left and right of the horizontal scrollbar.
4090 > * Defaults to false.
4091 > * **NOTE**: This option cannot be updated using `updateOptions()`
4092 > */
4093 > horizontalHasArrows?: boolean;
4094 > /**
4095 > * Listen to mouse wheel events and react to them by scrolling.
4096 > * Defaults to true.
4097 > */
4098 > handleMouseWheel?: boolean;
4099 > /**
4100 > * Always consume mouse wheel events (always call preventDefault() and stopPropagation() on the browser events).
4101 > * Defaults to true.
4102 > * **NOTE**: This option cannot be updated using `updateOptions()`
4103 > */
4104 > alwaysConsumeMouseWheel?: boolean;
4105 > /**
4106 > * Height in pixels for the horizontal scrollbar.
4107 > * Defaults to 12 (px).
4108 > */
4109 > horizontalScrollbarSize?: number;
4110 > /**
4111 > * Width in pixels for the vertical scrollbar.
4112 > * Defaults to 14 (px).
4113 > */
4114 > verticalScrollbarSize?: number;
4115 > /**
4116 > * Width in pixels for the vertical slider.
4117 > * Defaults to `verticalScrollbarSize`.
4118 > * **NOTE**: This option cannot be updated using `updateOptions()`
4119 > */
4120 > verticalSliderSize?: number;
4121 > /**
4122 > * Height in pixels for the horizontal slider.
4123 > * Defaults to `horizontalScrollbarSize`.
4124 > * **NOTE**: This option cannot be updated using `updateOptions()`
4125 > */
4126 > horizontalSliderSize?: number;
4127 > /**
4128 > * Scroll gutter clicks move by page vs jump to position.
4129 > * Defaults to false.
4130 > */
4131 > scrollByPage?: boolean;
4132 >
4133 > /**
4134 > * When set, the horizontal scrollbar will not increase content height.
4135 > * Defaults to false.
4136 > */
4137 > ignoreHorizontalScrollbarInContentHeight?: boolean;
4138 > }
4139 >
4140 > export interface InternalEditorScrollbarOptions {
4141 > readonly arrowSize: number;
4142 > readonly vertical: ScrollbarVisibility;
4143 > readonly horizontal: ScrollbarVisibility;
4144 > readonly useShadows: boolean;
4145 > readonly verticalHasArrows: boolean;
4146 > readonly horizontalHasArrows: boolean;
4147 > readonly handleMouseWheel: boolean;
4148 > readonly alwaysConsumeMouseWheel: boolean;
4149 > readonly horizontalScrollbarSize: number;
4150 > readonly horizontalSliderSize: number;
4151 > readonly verticalScrollbarSize: number;
4152 > readonly verticalSliderSize: number;
4153 > readonly scrollByPage: boolean;
4154 > readonly ignoreHorizontalScrollbarInContentHeight: boolean;
4155 > }
4156 >
4157 function _scrollbarVisibilityFromString(visibility: unknown, defaultValue: ScrollbarVisibility): ScrollbarVisibility {
4158 if (typeof visibility !== 'string') {
4165 }
4166 }
4168 > class EditorScrollbar extends BaseEditorOption<EditorOption.scrollbar, IEditorScrollbarOptions, InternalEditorScrollbarOptions> {
4169 >
4170 > constructor() {
4171 > const defaults: InternalEditorScrollbarOptions = {
4172 > vertical: ScrollbarVisibility.Auto,
4173 > horizontal: ScrollbarVisibility.Auto,
4174 > arrowSize: 11,
4175 > useShadows: true,
4176 > verticalHasArrows: false,
4177 > horizontalHasArrows: false,
4178 > horizontalScrollbarSize: 12,
4179 > horizontalSliderSize: 12,
4180 > verticalScrollbarSize: 14,
4181 > verticalSliderSize: 14,
4182 > handleMouseWheel: true,
4183 > alwaysConsumeMouseWheel: true,
4184 > scrollByPage: false,
4185 > ignoreHorizontalScrollbarInContentHeight: false,
4186 > };
4187 > super(
4188 > EditorOption.scrollbar, 'scrollbar', defaults,
4189 > {
4190 > 'editor.scrollbar.vertical': {
4191 > type: 'string',
4192 > enum: ['auto', 'visible', 'hidden'],
4193 > enumDescriptions: [
4194 > nls.localize('scrollbar.vertical.auto', "The vertical scrollbar will be visible only when necessary."),
4195 > nls.localize('scrollbar.vertical.visible', "The vertical scrollbar will always be visible."),
4196 > nls.localize('scrollbar.vertical.fit', "The vertical scrollbar will always be hidden."),
4197 > ],
4198 > default: 'auto',
4199 > description: nls.localize('scrollbar.vertical', "Controls the visibility of the vertical scrollbar.")
4200 > },
4201 > 'editor.scrollbar.horizontal': {
4202 > type: 'string',
4203 > enum: ['auto', 'visible', 'hidden'],
4204 > enumDescriptions: [
4205 > nls.localize('scrollbar.horizontal.auto', "The horizontal scrollbar will be visible only when necessary."),
4206 > nls.localize('scrollbar.horizontal.visible', "The horizontal scrollbar will always be visible."),
4207 > nls.localize('scrollbar.horizontal.fit', "The horizontal scrollbar will always be hidden."),
4208 > ],
4209 > default: 'auto',
4210 > description: nls.localize('scrollbar.horizontal', "Controls the visibility of the horizontal scrollbar.")
4211 > },
4212 > 'editor.scrollbar.verticalScrollbarSize': {
4213 > type: 'number',
4214 > default: defaults.verticalScrollbarSize,
4215 > description: nls.localize('scrollbar.verticalScrollbarSize', "The width of the vertical scrollbar.")
4216 > },
4217 > 'editor.scrollbar.horizontalScrollbarSize': {
4218 > type: 'number',
4219 > default: defaults.horizontalScrollbarSize,
4220 > description: nls.localize('scrollbar.horizontalScrollbarSize', "The height of the horizontal scrollbar.")
4221 > },
4222 > 'editor.scrollbar.scrollByPage': {
4223 > type: 'boolean',
4224 > default: defaults.scrollByPage,
4225 > description: nls.localize('scrollbar.scrollByPage', "Controls whether clicks scroll by page or jump to click position.")
4226 > },
4227 > 'editor.scrollbar.ignoreHorizontalScrollbarInContentHeight': {
4228 > type: 'boolean',
4229 > default: defaults.ignoreHorizontalScrollbarInContentHeight,
4230 > description: nls.localize('scrollbar.ignoreHorizontalScrollbarInContentHeight', "When set, the horizontal scrollbar will not increase the size of the editor's content.")
4231 > }
4232 > }
4233 > );
4234 > }
4235 >
4236 > public validate(_input: unknown): InternalEditorScrollbarOptions {
4237 if (!_input || typeof _input !== 'object') {
4238 return this.defaultValue;
4258 };
4259 }
4260 > } editorOptions.ts
4261 >
4262 > //#endregion
4263 >
4264 > //#region UnicodeHighlight
4265 >
4266 > export type InUntrustedWorkspace = 'inUntrustedWorkspace';
4267 >
4268 > /**
4269 > * @internal
4270 > */
4271 > export const inUntrustedWorkspace: InUntrustedWorkspace = 'inUntrustedWorkspace';
4272 >
4273 > /**
4274 > * Configuration options for unicode highlighting.
4275 > */
4276 > export interface IUnicodeHighlightOptions {
4277 >
4278 > /**
4279 > * Controls whether all non-basic ASCII characters are highlighted. Only characters between U+0020 and U+007E, tab, line-feed and carriage-return are considered basic ASCII.
4280 > */
4281 > nonBasicASCII?: boolean | InUntrustedWorkspace;
4282 >
4283 > /**
4284 > * Controls whether characters that just reserve space or have no width at all are highlighted.
4285 > */
4286 > invisibleCharacters?: boolean;
4287 >
4288 > /**
4289 > * Controls whether characters are highlighted that can be confused with basic ASCII characters, except those that are common in the current user locale.
4290 > */
4291 > ambiguousCharacters?: boolean;
4292 >
4293 > /**
4294 > * Controls whether characters in comments should also be subject to unicode highlighting.
4295 > */
4296 > includeComments?: boolean | InUntrustedWorkspace;
4297 >
4298 > /**
4299 > * Controls whether characters in strings should also be subject to unicode highlighting.
4300 > */
4301 > includeStrings?: boolean | InUntrustedWorkspace;
4302 >
4303 > /**
4304 > * Defines allowed characters that are not being highlighted.
4305 > */
4306 > allowedCharacters?: Record<string, true>;
4307 >
4308 > /**
4309 > * Unicode characters that are common in allowed locales are not being highlighted.
4310 > */
4311 > allowedLocales?: Record<string | '_os' | '_vscode', true>;
4312 > }
4313 >
4314 > /**
4315 > * @internal
4316 > */
4317 > export type InternalUnicodeHighlightOptions = Required<Readonly<IUnicodeHighlightOptions>>;
4318 >
4319 > /**
4320 > * @internal
4321 > */
4322 > export const unicodeHighlightConfigKeys = {
4323 > allowedCharacters: 'editor.unicodeHighlight.allowedCharacters',
4324 > invisibleCharacters: 'editor.unicodeHighlight.invisibleCharacters',
4325 > nonBasicASCII: 'editor.unicodeHighlight.nonBasicASCII',
4326 > ambiguousCharacters: 'editor.unicodeHighlight.ambiguousCharacters',
4327 > includeComments: 'editor.unicodeHighlight.includeComments',
4328 > includeStrings: 'editor.unicodeHighlight.includeStrings',
4329 > allowedLocales: 'editor.unicodeHighlight.allowedLocales',
4330 > };
4331 >
4332 > class UnicodeHighlight extends BaseEditorOption<EditorOption.unicodeHighlighting, IUnicodeHighlightOptions, InternalUnicodeHighlightOptions> {
4333 > constructor() {
4334 > const defaults: InternalUnicodeHighlightOptions = {
4335 > nonBasicASCII: inUntrustedWorkspace,
4336 > invisibleCharacters: true,
4337 > ambiguousCharacters: true,
4338 > includeComments: inUntrustedWorkspace,
4339 > includeStrings: true,
4340 > allowedCharacters: {},
4341 > allowedLocales: { _os: true, _vscode: true },
4342 > };
4343 >
4344 > super(
4345 > EditorOption.unicodeHighlighting, 'unicodeHighlight', defaults,
4346 > {
4347 > [unicodeHighlightConfigKeys.nonBasicASCII]: {
4348 > restricted: true,
4349 > type: ['boolean', 'string'],
4350 > enum: [true, false, inUntrustedWorkspace],
4351 > default: defaults.nonBasicASCII,
4352 > description: nls.localize('unicodeHighlight.nonBasicASCII', "Controls whether all non-basic ASCII characters are highlighted. Only characters between U+0020 and U+007E, tab, line-feed and carriage-return are considered basic ASCII.")
4353 > },
4354 > [unicodeHighlightConfigKeys.invisibleCharacters]: {
4355 > restricted: true,
4356 > type: 'boolean',
4357 > default: defaults.invisibleCharacters,
4358 > description: nls.localize('unicodeHighlight.invisibleCharacters', "Controls whether characters that just reserve space or have no width at all are highlighted.")
4359 > },
4360 > [unicodeHighlightConfigKeys.ambiguousCharacters]: {
4361 > restricted: true,
4362 > type: 'boolean',
4363 > default: defaults.ambiguousCharacters,
4364 > description: nls.localize('unicodeHighlight.ambiguousCharacters', "Controls whether characters are highlighted that can be confused with basic ASCII characters, except those that are common in the current user locale.")
4365 > },
4366 > [unicodeHighlightConfigKeys.includeComments]: {
4367 > restricted: true,
4368 > type: ['boolean', 'string'],
4369 > enum: [true, false, inUntrustedWorkspace],
4370 > default: defaults.includeComments,
4371 > description: nls.localize('unicodeHighlight.includeComments', "Controls whether characters in comments should also be subject to Unicode highlighting.")
4372 > },
4373 > [unicodeHighlightConfigKeys.includeStrings]: {
4374 > restricted: true,
4375 > type: ['boolean', 'string'],
4376 > enum: [true, false, inUntrustedWorkspace],
4377 > default: defaults.includeStrings,
4378 > description: nls.localize('unicodeHighlight.includeStrings', "Controls whether characters in strings should also be subject to Unicode highlighting.")
4379 > },
4380 > [unicodeHighlightConfigKeys.allowedCharacters]: {
4381 > restricted: true,
4382 > type: 'object',
4383 > default: defaults.allowedCharacters,
4384 > description: nls.localize('unicodeHighlight.allowedCharacters', "Defines allowed characters that are not being highlighted."),
4385 > additionalProperties: {
4386 > type: 'boolean'
4387 > }
4388 > },
4389 > [unicodeHighlightConfigKeys.allowedLocales]: {
4390 > restricted: true,
4391 > type: 'object',
4392 > additionalProperties: {
4393 > type: 'boolean'
4394 > },
4395 > default: defaults.allowedLocales,
4396 > description: nls.localize('unicodeHighlight.allowedLocales', "Unicode characters that are common in allowed locales are not being highlighted.")
4397 > },
4398 > }
4399 > );
4400 > }
4401 >
4402 > public override applyUpdate(value: Required<Readonly<IUnicodeHighlightOptions>> | undefined, update: Required<Readonly<IUnicodeHighlightOptions>>): ApplyUpdateResult<Required<Readonly<IUnicodeHighlightOptions>>> {
4403 let didChange = false;
4404 if (update.allowedCharacters && value) {
4423 return result;
4424 }
4426 > public validate(_input: unknown): InternalUnicodeHighlightOptions {
4427 if (!_input || typeof _input !== 'object') {
4428 return this.defaultValue;
4439 };
4440 }
4442 > private validateBooleanMap(map: unknown, defaultValue: Record<string, true>): Record<string, true> {
4443 if ((typeof map !== 'object') || !map) {
4444 return defaultValue;
4452 return result;
4453 }
4454 > } editorOptions.ts
4455 >
4456 > //#endregion
4457 >
4458 > //#region inlineSuggest
4459 >
4460 > export interface IInlineSuggestOptions {
4461 > /**
4462 > * Enable or disable the rendering of automatic inline completions.
4463 > */
4464 > enabled?: boolean;
4465 >
4466 > /**
4467 > * Configures the mode.
4468 > * Use `prefix` to only show ghost text if the text to replace is a prefix of the suggestion text.
4469 > * Use `subword` to only show ghost text if the replace text is a subword of the suggestion text.
4470 > * Use `subwordSmart` to only show ghost text if the replace text is a subword of the suggestion text, but the subword must start after the cursor position.
4471 > * Defaults to `prefix`.
4472 > */
4473 > mode?: 'prefix' | 'subword' | 'subwordSmart';
4474 >
4475 > showToolbar?: 'always' | 'onHover' | 'never';
4476 >
4477 > syntaxHighlightingEnabled?: boolean;
4478 >
4479 > suppressSuggestions?: boolean;
4480 >
4481 > minShowDelay?: number;
4482 > suppressInSnippetMode?: boolean;
4483 > /**
4484 > * Does not clear active inline suggestions when the editor loses focus.
4485 > */
4486 > keepOnBlur?: boolean;
4487 >
4488 > /**
4489 > * Font family for inline suggestions.
4490 > */
4491 > fontFamily?: string | 'default';
4492 >
4493 > edits?: {
4494 > allowCodeShifting?: 'always' | 'horizontal' | 'never';
4495 >
4496 > renderSideBySide?: 'never' | 'auto';
4497 >
4498 > showCollapsed?: boolean;
4499 >
4500 > showLongDistanceHint?: boolean;
4501 >
4502 > /**
4503 > * Controls how many lines of surrounding context are shown above and below the target line
4504 > * in the long distance inline suggestion hint preview. `0` shows only the target line.
4505 > */
4506 > longDistanceHintContextLineCount?: number;
4507 >
4508 > /**
4509 > * @internal
4510 > */
4511 > enabled?: boolean;
4512 > };
4513 >
4514 > /**
4515 > * @internal
4516 > */
4517 > triggerCommandOnProviderChange?: boolean;
4518 >
4519 > /**
4520 > * @internal
4521 > */
4522 > experimental?: {
4523 > /**
4524 > * @internal
4525 > */
4526 > suppressInlineSuggestions?: string;
4527 >
4528 > /**
4529 > * @internal
4530 > */
4531 > emptyResponseInformation?: boolean;
4532 >
4533 > showOnSuggestConflict?: 'always' | 'never' | 'whenSuggestListIsIncomplete';
4534 > };
4535 > }
4536 >
4537 > type RequiredRecursive<T> = {
4538 > [P in keyof T]-?: T[P] extends object | undefined ? RequiredRecursive<T[P]> : T[P];
4539 > };
4540 >
4541 > /**
4542 > * @internal
4543 > */
4544 > export type InternalInlineSuggestOptions = Readonly<RequiredRecursive<IInlineSuggestOptions>>;
4545 >
4546 > /**
4547 > * Configuration options for inline suggestions
4548 > */
4549 > class InlineEditorSuggest extends BaseEditorOption<EditorOption.inlineSuggest, IInlineSuggestOptions, InternalInlineSuggestOptions> {
4550 > constructor() {
4551 > const defaults: InternalInlineSuggestOptions = {
4552 > enabled: true,
4553 > mode: 'subwordSmart',
4554 > showToolbar: 'onHover',
4555 > suppressSuggestions: false,
4556 > keepOnBlur: false,
4557 > fontFamily: 'default',
4558 > syntaxHighlightingEnabled: true,
4559 > minShowDelay: 0,
4560 > suppressInSnippetMode: true,
4561 > edits: {
4562 > enabled: true,
4563 > showCollapsed: false,
4564 > renderSideBySide: 'auto',
4565 > allowCodeShifting: 'always',
4566 > showLongDistanceHint: true,
4567 > longDistanceHintContextLineCount: 0,
4568 > },
4569 > triggerCommandOnProviderChange: false,
4570 > experimental: {
4571 > suppressInlineSuggestions: '',
4572 > showOnSuggestConflict: 'never',
4573 > emptyResponseInformation: true,
4574 > },
4575 > };
4576 >
4577 > super(
4578 > EditorOption.inlineSuggest, 'inlineSuggest', defaults,
4579 > {
4580 > 'editor.inlineSuggest.enabled': {
4581 > type: 'boolean',
4582 > default: defaults.enabled,
4583 > description: nls.localize('inlineSuggest.enabled', "Controls whether to automatically show inline suggestions in the editor.")
4584 > },
4585 > 'editor.inlineSuggest.showToolbar': {
4586 > type: 'string',
4587 > default: defaults.showToolbar,
4588 > enum: ['always', 'onHover', 'never'],
4589 > enumDescriptions: [
4590 > nls.localize('inlineSuggest.showToolbar.always', "Show the inline suggestion toolbar whenever an inline suggestion is shown."),
4591 > nls.localize('inlineSuggest.showToolbar.onHover', "Show the inline suggestion toolbar when hovering over an inline suggestion."),
4592 > nls.localize('inlineSuggest.showToolbar.never', "Never show the inline suggestion toolbar."),
4593 > ],
4594 > description: nls.localize('inlineSuggest.showToolbar', "Controls when to show the inline suggestion toolbar."),
4595 > },
4596 > 'editor.inlineSuggest.syntaxHighlightingEnabled': {
4597 > type: 'boolean',
4598 > default: defaults.syntaxHighlightingEnabled,
4599 > description: nls.localize('inlineSuggest.syntaxHighlightingEnabled', "Controls whether to show syntax highlighting for inline suggestions in the editor."),
4600 > },
4601 > 'editor.inlineSuggest.suppressSuggestions': {
4602 > type: 'boolean',
4603 > default: defaults.suppressSuggestions,
4604 > description: nls.localize('inlineSuggest.suppressSuggestions', "Controls how inline suggestions interact with the suggest widget. If enabled, the suggest widget is not shown automatically when inline suggestions are available.")
4605 > },
4606 > 'editor.inlineSuggest.suppressInSnippetMode': {
4607 > type: 'boolean',
4608 > default: defaults.suppressInSnippetMode,
4609 > description: nls.localize('inlineSuggest.suppressInSnippetMode', "Controls whether inline suggestions are suppressed when in snippet mode."),
4610 > },
4611 > 'editor.inlineSuggest.minShowDelay': {
4612 > type: 'number',
4613 > default: 0,
4614 > minimum: 0,
4615 > maximum: 10000,
4616 > description: nls.localize('inlineSuggest.minShowDelay', "Controls the minimal delay in milliseconds after which inline suggestions are shown after typing."),
4617 > },
4618 > 'editor.inlineSuggest.experimental.suppressInlineSuggestions': {
4619 > type: 'string',
4620 > default: defaults.experimental.suppressInlineSuggestions,
4621 > tags: ['experimental'],
4622 > description: nls.localize('inlineSuggest.suppressInlineSuggestions', "Suppresses inline completions for specified extension IDs -- comma separated."),
4623 > experiment: {
4624 > mode: 'auto'
4625 > }
4626 > },
4627 > 'editor.inlineSuggest.experimental.emptyResponseInformation': {
4628 > type: 'boolean',
4629 > default: defaults.experimental.emptyResponseInformation,
4630 > tags: ['experimental'],
4631 > description: nls.localize('inlineSuggest.emptyResponseInformation', "Controls whether to send request information from the inline suggestion provider."),
4632 > experiment: {
4633 > mode: 'auto'
4634 > }
4635 > },
4636 > 'editor.inlineSuggest.triggerCommandOnProviderChange': {
4637 > type: 'boolean',
4638 > default: defaults.triggerCommandOnProviderChange,
4639 > tags: ['experimental'],
4640 > description: nls.localize('inlineSuggest.triggerCommandOnProviderChange', "Controls whether to trigger a command when the inline suggestion provider changes."),
4641 > experiment: {
4642 > mode: 'auto'
4643 > }
4644 > },
4645 > 'editor.inlineSuggest.experimental.showOnSuggestConflict': {
4646 > type: 'string',
4647 > default: defaults.experimental.showOnSuggestConflict,
4648 > tags: ['experimental'],
4649 > enum: ['always', 'never', 'whenSuggestListIsIncomplete'],
4650 > description: nls.localize('inlineSuggest.showOnSuggestConflict', "Controls whether to show inline suggestions when there is a suggest conflict."),
4651 > experiment: {
4652 > mode: 'auto'
4653 > }
4654 > },
4655 > 'editor.inlineSuggest.fontFamily': {
4656 > type: 'string',
4657 > default: defaults.fontFamily,
4658 > description: nls.localize('inlineSuggest.fontFamily', "Controls the font family of the inline suggestions.")
4659 > },
4660 > 'editor.inlineSuggest.edits.allowCodeShifting': {
4661 > type: 'string',
4662 > default: defaults.edits.allowCodeShifting,
4663 > description: nls.localize('inlineSuggest.edits.allowCodeShifting', "Controls whether showing a suggestion will shift the code to make space for the suggestion inline."),
4664 > enum: ['always', 'horizontal', 'never'],
4665 > tags: ['nextEditSuggestions']
4666 > },
4667 > 'editor.inlineSuggest.edits.showLongDistanceHint': {
4668 > type: 'boolean',
4669 > default: defaults.edits.showLongDistanceHint,
4670 > description: nls.localize('inlineSuggest.edits.showLongDistanceHint', "Controls whether long distance inline suggestions are shown."),
4671 > tags: ['nextEditSuggestions', 'experimental']
4672 > },
4673 > 'editor.inlineSuggest.edits.longDistanceHintContextLineCount': {
4674 > type: 'number',
4675 > default: defaults.edits.longDistanceHintContextLineCount,
4676 > minimum: 0,
4677 > maximum: 10,
4678 > description: nls.localize('inlineSuggest.edits.longDistanceHintContextLineCount', "Controls how many lines of surrounding context are shown above and below the target line in the long distance inline suggestion preview. Set to 0 to only show the target line."),
4679 > tags: ['nextEditSuggestions', 'experimental'],
4680 > experiment: {
4681 > mode: 'auto'
4682 > }
4683 > },
4684 > 'editor.inlineSuggest.edits.renderSideBySide': {
4685 > type: 'string',
4686 > default: defaults.edits.renderSideBySide,
4687 > description: nls.localize('inlineSuggest.edits.renderSideBySide', "Controls whether larger suggestions can be shown side by side."),
4688 > enum: ['auto', 'never'],
4689 > enumDescriptions: [
4690 > nls.localize('editor.inlineSuggest.edits.renderSideBySide.auto', "Larger suggestions will show side by side if there is enough space, otherwise they will be shown below."),
4691 > nls.localize('editor.inlineSuggest.edits.renderSideBySide.never', "Larger suggestions are never shown side by side and will always be shown below."),
4692 > ],
4693 > tags: ['nextEditSuggestions']
4694 > },
4695 > 'editor.inlineSuggest.edits.showCollapsed': {
4696 > type: 'boolean',
4697 > default: defaults.edits.showCollapsed,
4698 > description: nls.localize('inlineSuggest.edits.showCollapsed', "Controls whether the suggestion will show as collapsed until jumping to it."),
4699 > tags: ['nextEditSuggestions']
4700 > },
4701 > }
4702 > );
4703 > }
4704 >
4705 > public validate(_input: unknown): InternalInlineSuggestOptions {
4706 if (!_input || typeof _input !== 'object') {
4707 return this.defaultValue;
4723 };
4724 }
4726 > private _validateEdits(_input: unknown): InternalInlineSuggestOptions['edits'] {
4727 if (!_input || typeof _input !== 'object') {
4728 return this.defaultValue.edits;
4738 };
4739 }
4741 > private _validateExperimental(_input: unknown): InternalInlineSuggestOptions['experimental'] {
4742 if (!_input || typeof _input !== 'object') {
4743 return this.defaultValue.experimental;
4750 };
4751 }
4752 > } editorOptions.ts
4753 >
4754 > //#endregion
4755 >
4756 > //#region bracketPairColorization
4757 >
4758 > export interface IBracketPairColorizationOptions {
4759 > /**
4760 > * Enable or disable bracket pair colorization.
4761 > */
4762 > enabled?: boolean;
4763 >
4764 > /**
4765 > * Use independent color pool per bracket type.
4766 > */
4767 > independentColorPoolPerBracketType?: boolean;
4768 > }
4769 >
4770 > /**
4771 > * @internal
4772 > */
4773 > export type InternalBracketPairColorizationOptions = Readonly<Required<IBracketPairColorizationOptions>>;
4774 >
4775 > /**
4776 > * Configuration options for inline suggestions
4777 > */
4778 > class BracketPairColorization extends BaseEditorOption<EditorOption.bracketPairColorization, IBracketPairColorizationOptions, InternalBracketPairColorizationOptions> {
4779 > constructor() {
4780 > const defaults: InternalBracketPairColorizationOptions = {
4781 > enabled: EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions.enabled,
4782 > independentColorPoolPerBracketType: EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions.independentColorPoolPerBracketType,
4783 > };
4784 >
4785 > super(
4786 > EditorOption.bracketPairColorization, 'bracketPairColorization', defaults,
4787 > {
4788 > 'editor.bracketPairColorization.enabled': {
4789 > type: 'boolean',
4790 > default: defaults.enabled,
4791 > markdownDescription: nls.localize('bracketPairColorization.enabled', "Controls whether bracket pair colorization is enabled or not. Use {0} to override the bracket highlight colors.", '`#workbench.colorCustomizations#`')
4792 > },
4793 > 'editor.bracketPairColorization.independentColorPoolPerBracketType': {
4794 > type: 'boolean',
4795 > default: defaults.independentColorPoolPerBracketType,
4796 > description: nls.localize('bracketPairColorization.independentColorPoolPerBracketType', "Controls whether each bracket type has its own independent color pool.")
4797 > },
4798 > }
4799 > );
4800 > }
4801 >
4802 > public validate(_input: unknown): InternalBracketPairColorizationOptions {
4803 if (!_input || typeof _input !== 'object') {
4804 return this.defaultValue;
4810 };
4811 }
4812 > } editorOptions.ts
4813 >
4814 > //#endregion
4815 >
4816 > //#region guides
4817 >
4818 > export interface IGuidesOptions {
4819 > /**
4820 > * Enable rendering of bracket pair guides.
4821 > * Defaults to false.
4822 > */
4823 > bracketPairs?: boolean | 'active';
4824 >
4825 > /**
4826 > * Enable rendering of vertical bracket pair guides.
4827 > * Defaults to 'active'.
4828 > */
4829 > bracketPairsHorizontal?: boolean | 'active';
4830 >
4831 > /**
4832 > * Enable highlighting of the active bracket pair.
4833 > * Defaults to true.
4834 > */
4835 > highlightActiveBracketPair?: boolean;
4836 >
4837 > /**
4838 > * Enable rendering of indent guides.
4839 > * Defaults to true.
4840 > */
4841 > indentation?: boolean;
4842 >
4843 > /**
4844 > * Enable highlighting of the active indent guide.
4845 > * Defaults to true.
4846 > */
4847 > highlightActiveIndentation?: boolean | 'always';
4848 > }
4849 >
4850 > /**
4851 > * @internal
4852 > */
4853 > export type InternalGuidesOptions = Readonly<Required<IGuidesOptions>>;
4854 >
4855 > /**
4856 > * Configuration options for inline suggestions
4857 > */
4858 > class GuideOptions extends BaseEditorOption<EditorOption.guides, IGuidesOptions, InternalGuidesOptions> {
4859 > constructor() {
4860 > const defaults: InternalGuidesOptions = {
4861 > bracketPairs: false,
4862 > bracketPairsHorizontal: 'active',
4863 > highlightActiveBracketPair: true,
4864 >
4865 > indentation: true,
4866 > highlightActiveIndentation: true
4867 > };
4868 >
4869 > super(
4870 > EditorOption.guides, 'guides', defaults,
4871 > {
4872 > 'editor.guides.bracketPairs': {
4873 > type: ['boolean', 'string'],
4874 > enum: [true, 'active', false],
4875 > enumDescriptions: [
4876 > nls.localize('editor.guides.bracketPairs.true', "Enables bracket pair guides."),
4877 > nls.localize('editor.guides.bracketPairs.active', "Enables bracket pair guides only for the active bracket pair."),
4878 > nls.localize('editor.guides.bracketPairs.false', "Disables bracket pair guides."),
4879 > ],
4880 > default: defaults.bracketPairs,
4881 > description: nls.localize('editor.guides.bracketPairs', "Controls whether bracket pair guides are enabled or not.")
4882 > },
4883 > 'editor.guides.bracketPairsHorizontal': {
4884 > type: ['boolean', 'string'],
4885 > enum: [true, 'active', false],
4886 > enumDescriptions: [
4887 > nls.localize('editor.guides.bracketPairsHorizontal.true', "Enables horizontal guides as addition to vertical bracket pair guides."),
4888 > nls.localize('editor.guides.bracketPairsHorizontal.active', "Enables horizontal guides only for the active bracket pair."),
4889 > nls.localize('editor.guides.bracketPairsHorizontal.false', "Disables horizontal bracket pair guides."),
4890 > ],
4891 > default: defaults.bracketPairsHorizontal,
4892 > description: nls.localize('editor.guides.bracketPairsHorizontal', "Controls whether horizontal bracket pair guides are enabled or not.")
4893 > },
4894 > 'editor.guides.highlightActiveBracketPair': {
4895 > type: 'boolean',
4896 > default: defaults.highlightActiveBracketPair,
4897 > description: nls.localize('editor.guides.highlightActiveBracketPair', "Controls whether the editor should highlight the active bracket pair.")
4898 > },
4899 > 'editor.guides.indentation': {
4900 > type: 'boolean',
4901 > default: defaults.indentation,
4902 > description: nls.localize('editor.guides.indentation', "Controls whether the editor should render indent guides.")
4903 > },
4904 > 'editor.guides.highlightActiveIndentation': {
4905 > type: ['boolean', 'string'],
4906 > enum: [true, 'always', false],
4907 > enumDescriptions: [
4908 > nls.localize('editor.guides.highlightActiveIndentation.true', "Highlights the active indent guide."),
4909 > nls.localize('editor.guides.highlightActiveIndentation.always', "Highlights the active indent guide even if bracket guides are highlighted."),
4910 > nls.localize('editor.guides.highlightActiveIndentation.false', "Do not highlight the active indent guide."),
4911 > ],
4912 > default: defaults.highlightActiveIndentation,
4913 >
4914 > description: nls.localize('editor.guides.highlightActiveIndentation', "Controls whether the editor should highlight the active indent guide.")
4915 > }
4916 > }
4917 > );
4918 > }
4919 >
4920 > public validate(_input: unknown): InternalGuidesOptions {
4921 if (!_input || typeof _input !== 'object') {
4922 return this.defaultValue;
4932 };
4933 }
4934 > } editorOptions.ts
4935 >
4936 function primitiveSet<T extends string | boolean>(value: unknown, defaultValue: T, allowedValues: T[]): T {
4937 const idx = allowedValues.indexOf(value as T);
4941 return allowedValues[idx];
4942 }
4944 > //#endregion
4945 >
4946 > //#region suggest
4947 >
4948 > /**
4949 > * Configuration options for editor suggest widget
4950 > */
4951 > export interface ISuggestOptions {
4952 > /**
4953 > * Overwrite word ends on accept. Default to false.
4954 > */
4955 > insertMode?: 'insert' | 'replace';
4956 > /**
4957 > * Enable graceful matching. Defaults to true.
4958 > */
4959 > filterGraceful?: boolean;
4960 > /**
4961 > * Prevent quick suggestions when a snippet is active. Defaults to true.
4962 > */
4963 > snippetsPreventQuickSuggestions?: boolean;
4964 > /**
4965 > * Favors words that appear close to the cursor.
4966 > */
4967 > localityBonus?: boolean;
4968 > /**
4969 > * Enable using global storage for remembering suggestions.
4970 > */
4971 > shareSuggestSelections?: boolean;
4972 > /**
4973 > * Select suggestions when triggered via quick suggest or trigger characters
4974 > */
4975 > selectionMode?: 'always' | 'never' | 'whenTriggerCharacter' | 'whenQuickSuggestion';
4976 > /**
4977 > * Enable or disable icons in suggestions. Defaults to true.
4978 > */
4979 > showIcons?: boolean;
4980 > /**
4981 > * Enable or disable the suggest status bar.
4982 > */
4983 > showStatusBar?: boolean;
4984 > /**
4985 > * Enable or disable the rendering of the suggestion preview.
4986 > */
4987 > preview?: boolean;
4988 > /**
4989 > * Configures the mode of the preview.
4990 > */
4991 > previewMode?: 'prefix' | 'subword' | 'subwordSmart';
4992 > /**
4993 > * Show details inline with the label. Defaults to true.
4994 > */
4995 > showInlineDetails?: boolean;
4996 > /**
4997 > * Show method-suggestions.
4998 > */
4999 > showMethods?: boolean;
5000 > /**
5001 > * Show function-suggestions.
5002 > */
5003 > showFunctions?: boolean;
5004 > /**
5005 > * Show constructor-suggestions.
5006 > */
5007 > showConstructors?: boolean;
5008 > /**
5009 > * Show deprecated-suggestions.
5010 > */
5011 > showDeprecated?: boolean;
5012 > /**
5013 > * Controls whether suggestions allow matches in the middle of the word instead of only at the beginning
5014 > */
5015 > matchOnWordStartOnly?: boolean;
5016 > /**
5017 > * Show field-suggestions.
5018 > */
5019 > showFields?: boolean;
5020 > /**
5021 > * Show variable-suggestions.
5022 > */
5023 > showVariables?: boolean;
5024 > /**
5025 > * Show class-suggestions.
5026 > */
5027 > showClasses?: boolean;
5028 > /**
5029 > * Show struct-suggestions.
5030 > */
5031 > showStructs?: boolean;
5032 > /**
5033 > * Show interface-suggestions.
5034 > */
5035 > showInterfaces?: boolean;
5036 > /**
5037 > * Show module-suggestions.
5038 > */
5039 > showModules?: boolean;
5040 > /**
5041 > * Show property-suggestions.
5042 > */
5043 > showProperties?: boolean;
5044 > /**
5045 > * Show event-suggestions.
5046 > */
5047 > showEvents?: boolean;
5048 > /**
5049 > * Show operator-suggestions.
5050 > */
5051 > showOperators?: boolean;
5052 > /**
5053 > * Show unit-suggestions.
5054 > */
5055 > showUnits?: boolean;
5056 > /**
5057 > * Show value-suggestions.
5058 > */
5059 > showValues?: boolean;
5060 > /**
5061 > * Show constant-suggestions.
5062 > */
5063 > showConstants?: boolean;
5064 > /**
5065 > * Show enum-suggestions.
5066 > */
5067 > showEnums?: boolean;
5068 > /**
5069 > * Show enumMember-suggestions.
5070 > */
5071 > showEnumMembers?: boolean;
5072 > /**
5073 > * Show keyword-suggestions.
5074 > */
5075 > showKeywords?: boolean;
5076 > /**
5077 > * Show text-suggestions.
5078 > */
5079 > showWords?: boolean;
5080 > /**
5081 > * Show color-suggestions.
5082 > */
5083 > showColors?: boolean;
5084 > /**
5085 > * Show file-suggestions.
5086 > */
5087 > showFiles?: boolean;
5088 > /**
5089 > * Show reference-suggestions.
5090 > */
5091 > showReferences?: boolean;
5092 > /**
5093 > * Show folder-suggestions.
5094 > */
5095 > showFolders?: boolean;
5096 > /**
5097 > * Show typeParameter-suggestions.
5098 > */
5099 > showTypeParameters?: boolean;
5100 > /**
5101 > * Show issue-suggestions.
5102 > */
5103 > showIssues?: boolean;
5104 > /**
5105 > * Show user-suggestions.
5106 > */
5107 > showUsers?: boolean;
5108 > /**
5109 > * Show snippet-suggestions.
5110 > */
5111 > showSnippets?: boolean;
5112 > }
5113 >
5114 > /**
5115 > * @internal
5116 > */
5117 > export type InternalSuggestOptions = Readonly<Required<ISuggestOptions>>;
5118 >
5119 > class EditorSuggest extends BaseEditorOption<EditorOption.suggest, ISuggestOptions, InternalSuggestOptions> {
5120 >
5121 > constructor() {
5122 > const defaults: InternalSuggestOptions = {
5123 > insertMode: 'insert',
5124 > filterGraceful: true,
5125 > snippetsPreventQuickSuggestions: false,
5126 > localityBonus: false,
5127 > shareSuggestSelections: false,
5128 > selectionMode: 'always',
5129 > showIcons: true,
5130 > showStatusBar: false,
5131 > preview: false,
5132 > previewMode: 'subwordSmart',
5133 > showInlineDetails: true,
5134 > showMethods: true,
5135 > showFunctions: true,
5136 > showConstructors: true,
5137 > showDeprecated: true,
5138 > matchOnWordStartOnly: true,
5139 > showFields: true,
5140 > showVariables: true,
5141 > showClasses: true,
5142 > showStructs: true,
5143 > showInterfaces: true,
5144 > showModules: true,
5145 > showProperties: true,
5146 > showEvents: true,
5147 > showOperators: true,
5148 > showUnits: true,
5149 > showValues: true,
5150 > showConstants: true,
5151 > showEnums: true,
5152 > showEnumMembers: true,
5153 > showKeywords: true,
5154 > showWords: true,
5155 > showColors: true,
5156 > showFiles: true,
5157 > showReferences: true,
5158 > showFolders: true,
5159 > showTypeParameters: true,
5160 > showSnippets: true,
5161 > showUsers: true,
5162 > showIssues: true,
5163 > };
5164 > super(
5165 > EditorOption.suggest, 'suggest', defaults,
5166 > {
5167 > 'editor.suggest.insertMode': {
5168 > type: 'string',
5169 > enum: ['insert', 'replace'],
5170 > enumDescriptions: [
5171 > nls.localize('suggest.insertMode.insert', "Insert suggestion without overwriting text right of the cursor."),
5172 > nls.localize('suggest.insertMode.replace', "Insert suggestion and overwrite text right of the cursor."),
5173 > ],
5174 > default: defaults.insertMode,
5175 > description: nls.localize('suggest.insertMode', "Controls whether words are overwritten when accepting completions. Note that this depends on extensions opting into this feature.")
5176 > },
5177 > 'editor.suggest.filterGraceful': {
5178 > type: 'boolean',
5179 > default: defaults.filterGraceful,
5180 > description: nls.localize('suggest.filterGraceful', "Controls whether filtering and sorting suggestions accounts for small typos.")
5181 > },
5182 > 'editor.suggest.localityBonus': {
5183 > type: 'boolean',
5184 > default: defaults.localityBonus,
5185 > description: nls.localize('suggest.localityBonus', "Controls whether sorting favors words that appear close to the cursor.")
5186 > },
5187 > 'editor.suggest.shareSuggestSelections': {
5188 > type: 'boolean',
5189 > default: defaults.shareSuggestSelections,
5190 > markdownDescription: nls.localize('suggest.shareSuggestSelections', "Controls whether remembered suggestion selections are shared between multiple workspaces and windows (needs `#editor.suggestSelection#`).")
5191 > },
5192 > 'editor.suggest.selectionMode': {
5193 > type: 'string',
5194 > enum: ['always', 'never', 'whenTriggerCharacter', 'whenQuickSuggestion'],
5195 > enumDescriptions: [
5196 > nls.localize('suggest.insertMode.always', "Always select a suggestion when automatically triggering IntelliSense."),
5197 > nls.localize('suggest.insertMode.never', "Never select a suggestion when automatically triggering IntelliSense."),
5198 > nls.localize('suggest.insertMode.whenTriggerCharacter', "Select a suggestion only when triggering IntelliSense from a trigger character."),
5199 > nls.localize('suggest.insertMode.whenQuickSuggestion', "Select a suggestion only when triggering IntelliSense as you type."),
5200 > ],
5201 > default: defaults.selectionMode,
5202 > markdownDescription: nls.localize('suggest.selectionMode', "Controls whether a suggestion is selected when the widget shows. Note that this only applies to automatically triggered suggestions ({0} and {1}) and that a suggestion is always selected when explicitly invoked, e.g via `Ctrl+Space`.", '`#editor.quickSuggestions#`', '`#editor.suggestOnTriggerCharacters#`')
5203 > },
5204 > 'editor.suggest.snippetsPreventQuickSuggestions': {
5205 > type: 'boolean',
5206 > default: defaults.snippetsPreventQuickSuggestions,
5207 > description: nls.localize('suggest.snippetsPreventQuickSuggestions', "Controls whether an active snippet prevents quick suggestions.")
5208 > },
5209 > 'editor.suggest.showIcons': {
5210 > type: 'boolean',
5211 > default: defaults.showIcons,
5212 > description: nls.localize('suggest.showIcons', "Controls whether to show or hide icons in suggestions.")
5213 > },
5214 > 'editor.suggest.showStatusBar': {
5215 > type: 'boolean',
5216 > default: defaults.showStatusBar,
5217 > description: nls.localize('suggest.showStatusBar', "Controls the visibility of the status bar at the bottom of the suggest widget.")
5218 > },
5219 > 'editor.suggest.preview': {
5220 > type: 'boolean',
5221 > default: defaults.preview,
5222 > description: nls.localize('suggest.preview', "Controls whether to preview the suggestion outcome in the editor.")
5223 > },
5224 > 'editor.suggest.showInlineDetails': {
5225 > type: 'boolean',
5226 > default: defaults.showInlineDetails,
5227 > description: nls.localize('suggest.showInlineDetails', "Controls whether suggest details show inline with the label or only in the details widget.")
5228 > },
5229 > 'editor.suggest.filteredTypes': {
5230 > type: 'object',
5231 > deprecationMessage: nls.localize('deprecated', "This setting is deprecated, please use separate settings like 'editor.suggest.showKeywords' or 'editor.suggest.showSnippets' instead.")
5232 > },
5233 > 'editor.suggest.showMethods': {
5234 > type: 'boolean',
5235 > default: true,
5236 > markdownDescription: nls.localize('editor.suggest.showMethods', "When enabled IntelliSense shows `method`-suggestions.")
5237 > },
5238 > 'editor.suggest.showFunctions': {
5239 > type: 'boolean',
5240 > default: true,
5241 > markdownDescription: nls.localize('editor.suggest.showFunctions', "When enabled IntelliSense shows `function`-suggestions.")
5242 > },
5243 > 'editor.suggest.showConstructors': {
5244 > type: 'boolean',
5245 > default: true,
5246 > markdownDescription: nls.localize('editor.suggest.showConstructors', "When enabled IntelliSense shows `constructor`-suggestions.")
5247 > },
5248 > 'editor.suggest.showDeprecated': {
5249 > type: 'boolean',
5250 > default: true,
5251 > markdownDescription: nls.localize('editor.suggest.showDeprecated', "When enabled IntelliSense shows `deprecated`-suggestions.")
5252 > },
5253 > 'editor.suggest.matchOnWordStartOnly': {
5254 > type: 'boolean',
5255 > default: true,
5256 > markdownDescription: nls.localize('editor.suggest.matchOnWordStartOnly', "When enabled IntelliSense filtering requires that the first character matches on a word start. For example, `c` on `Console` or `WebContext` but _not_ on `description`. When disabled IntelliSense will show more results but still sorts them by match quality.")
5257 > },
5258 > 'editor.suggest.showFields': {
5259 > type: 'boolean',
5260 > default: true,
5261 > markdownDescription: nls.localize('editor.suggest.showFields', "When enabled IntelliSense shows `field`-suggestions.")
5262 > },
5263 > 'editor.suggest.showVariables': {
5264 > type: 'boolean',
5265 > default: true,
5266 > markdownDescription: nls.localize('editor.suggest.showVariables', "When enabled IntelliSense shows `variable`-suggestions.")
5267 > },
5268 > 'editor.suggest.showClasses': {
5269 > type: 'boolean',
5270 > default: true,
5271 > markdownDescription: nls.localize('editor.suggest.showClasss', "When enabled IntelliSense shows `class`-suggestions.")
5272 > },
5273 > 'editor.suggest.showStructs': {
5274 > type: 'boolean',
5275 > default: true,
5276 > markdownDescription: nls.localize('editor.suggest.showStructs', "When enabled IntelliSense shows `struct`-suggestions.")
5277 > },
5278 > 'editor.suggest.showInterfaces': {
5279 > type: 'boolean',
5280 > default: true,
5281 > markdownDescription: nls.localize('editor.suggest.showInterfaces', "When enabled IntelliSense shows `interface`-suggestions.")
5282 > },
5283 > 'editor.suggest.showModules': {
5284 > type: 'boolean',
5285 > default: true,
5286 > markdownDescription: nls.localize('editor.suggest.showModules', "When enabled IntelliSense shows `module`-suggestions.")
5287 > },
5288 > 'editor.suggest.showProperties': {
5289 > type: 'boolean',
5290 > default: true,
5291 > markdownDescription: nls.localize('editor.suggest.showPropertys', "When enabled IntelliSense shows `property`-suggestions.")
5292 > },
5293 > 'editor.suggest.showEvents': {
5294 > type: 'boolean',
5295 > default: true,
5296 > markdownDescription: nls.localize('editor.suggest.showEvents', "When enabled IntelliSense shows `event`-suggestions.")
5297 > },
5298 > 'editor.suggest.showOperators': {
5299 > type: 'boolean',
5300 > default: true,
5301 > markdownDescription: nls.localize('editor.suggest.showOperators', "When enabled IntelliSense shows `operator`-suggestions.")
5302 > },
5303 > 'editor.suggest.showUnits': {
5304 > type: 'boolean',
5305 > default: true,
5306 > markdownDescription: nls.localize('editor.suggest.showUnits', "When enabled IntelliSense shows `unit`-suggestions.")
5307 > },
5308 > 'editor.suggest.showValues': {
5309 > type: 'boolean',
5310 > default: true,
5311 > markdownDescription: nls.localize('editor.suggest.showValues', "When enabled IntelliSense shows `value`-suggestions.")
5312 > },
5313 > 'editor.suggest.showConstants': {
5314 > type: 'boolean',
5315 > default: true,
5316 > markdownDescription: nls.localize('editor.suggest.showConstants', "When enabled IntelliSense shows `constant`-suggestions.")
5317 > },
5318 > 'editor.suggest.showEnums': {
5319 > type: 'boolean',
5320 > default: true,
5321 > markdownDescription: nls.localize('editor.suggest.showEnums', "When enabled IntelliSense shows `enum`-suggestions.")
5322 > },
5323 > 'editor.suggest.showEnumMembers': {
5324 > type: 'boolean',
5325 > default: true,
5326 > markdownDescription: nls.localize('editor.suggest.showEnumMembers', "When enabled IntelliSense shows `enumMember`-suggestions.")
5327 > },
5328 > 'editor.suggest.showKeywords': {
5329 > type: 'boolean',
5330 > default: true,
5331 > markdownDescription: nls.localize('editor.suggest.showKeywords', "When enabled IntelliSense shows `keyword`-suggestions.")
5332 > },
5333 > 'editor.suggest.showWords': {
5334 > type: 'boolean',
5335 > default: true,
5336 > markdownDescription: nls.localize('editor.suggest.showTexts', "When enabled IntelliSense shows `text`-suggestions.")
5337 > },
5338 > 'editor.suggest.showColors': {
5339 > type: 'boolean',
5340 > default: true,
5341 > markdownDescription: nls.localize('editor.suggest.showColors', "When enabled IntelliSense shows `color`-suggestions.")
5342 > },
5343 > 'editor.suggest.showFiles': {
5344 > type: 'boolean',
5345 > default: true,
5346 > markdownDescription: nls.localize('editor.suggest.showFiles', "When enabled IntelliSense shows `file`-suggestions.")
5347 > },
5348 > 'editor.suggest.showReferences': {
5349 > type: 'boolean',
5350 > default: true,
5351 > markdownDescription: nls.localize('editor.suggest.showReferences', "When enabled IntelliSense shows `reference`-suggestions.")
5352 > },
5353 > 'editor.suggest.showCustomcolors': {
5354 > type: 'boolean',
5355 > default: true,
5356 > markdownDescription: nls.localize('editor.suggest.showCustomcolors', "When enabled IntelliSense shows `customcolor`-suggestions.")
5357 > },
5358 > 'editor.suggest.showFolders': {
5359 > type: 'boolean',
5360 > default: true,
5361 > markdownDescription: nls.localize('editor.suggest.showFolders', "When enabled IntelliSense shows `folder`-suggestions.")
5362 > },
5363 > 'editor.suggest.showTypeParameters': {
5364 > type: 'boolean',
5365 > default: true,
5366 > markdownDescription: nls.localize('editor.suggest.showTypeParameters', "When enabled IntelliSense shows `typeParameter`-suggestions.")
5367 > },
5368 > 'editor.suggest.showSnippets': {
5369 > type: 'boolean',
5370 > default: true,
5371 > markdownDescription: nls.localize('editor.suggest.showSnippets', "When enabled IntelliSense shows `snippet`-suggestions.")
5372 > },
5373 > 'editor.suggest.showUsers': {
5374 > type: 'boolean',
5375 > default: true,
5376 > markdownDescription: nls.localize('editor.suggest.showUsers', "When enabled IntelliSense shows `user`-suggestions.")
5377 > },
5378 > 'editor.suggest.showIssues': {
5379 > type: 'boolean',
5380 > default: true,
5381 > markdownDescription: nls.localize('editor.suggest.showIssues', "When enabled IntelliSense shows `issues`-suggestions.")
5382 > }
5383 > }
5384 > );
5385 > }
5386 >
5387 > public validate(_input: unknown): InternalSuggestOptions {
5388 if (!_input || typeof _input !== 'object') {
5389 return this.defaultValue;
5433 };
5434 }
5435 > } editorOptions.ts
5436 >
5437 > //#endregion
5438 >
5439 > //#region smart select
5440 >
5441 > export interface ISmartSelectOptions {
5442 > selectLeadingAndTrailingWhitespace?: boolean;
5443 > selectSubwords?: boolean;
5444 > }
5445 >
5446 > /**
5447 > * @internal
5448 > */
5449 > export type SmartSelectOptions = Readonly<Required<ISmartSelectOptions>>;
5450 >
5451 > class SmartSelect extends BaseEditorOption<EditorOption.smartSelect, ISmartSelectOptions, SmartSelectOptions> {
5452 >
5453 > constructor() {
5454 > super(
5455 > EditorOption.smartSelect, 'smartSelect',
5456 > {
5457 > selectLeadingAndTrailingWhitespace: true,
5458 > selectSubwords: true,
5459 > },
5460 > {
5461 > 'editor.smartSelect.selectLeadingAndTrailingWhitespace': {
5462 > description: nls.localize('selectLeadingAndTrailingWhitespace', "Whether leading and trailing whitespace should always be selected."),
5463 > default: true,
5464 > type: 'boolean'
5465 > },
5466 > 'editor.smartSelect.selectSubwords': {
5467 > description: nls.localize('selectSubwords', "Whether subwords (like 'foo' in 'fooBar' or 'foo_bar') should be selected."),
5468 > default: true,
5469 > type: 'boolean'
5470 > }
5471 > }
5472 > );
5473 > }
5474 >
5475 > public validate(input: unknown): Readonly<Required<ISmartSelectOptions>> {
5476 if (!input || typeof input !== 'object') {
5477 return this.defaultValue;
5482 };
5483 }
5484 > } editorOptions.ts
5485 >
5486 > //#endregion
5487 >
5488 > //#region wordSegmenterLocales
5489 >
5490 > /**
5491 > * Locales used for segmenting lines into words when doing word related navigations or operations.
5492 > *
5493 > * Specify the BCP 47 language tag of the word you wish to recognize (e.g., ja, zh-CN, zh-Hant-TW, etc.).
5494 > */
5495 > class WordSegmenterLocales extends BaseEditorOption<EditorOption.wordSegmenterLocales, string | string[], string[]> {
5496 > constructor() {
5497 > const defaults: string[] = [];
5498 >
5499 > super(
5500 > EditorOption.wordSegmenterLocales, 'wordSegmenterLocales', defaults,
5501 > {
5502 > anyOf: [
5503 > {
5504 > type: 'string',
5505 > }, {
5506 > type: 'array',
5507 > items: {
5508 > type: 'string'
5509 > }
5510 > }
5511 > ],
5512 > description: nls.localize('wordSegmenterLocales', "Locales to be used for word segmentation when doing word related navigations or operations. Specify the BCP 47 language tag of the word you wish to recognize (e.g., ja, zh-CN, zh-Hant-TW, etc.)."),
5513 > type: 'array',
5514 > items: {
5515 > type: 'string',
5516 > },
5517 > default: defaults,
5518 > },
5519 > );
5520 > }
5521 >
5522 > public validate(input: unknown): string[] {
5523 if (typeof input === 'string') {
5524 input = [input];
5542 return this.defaultValue;
5543 }
5544 > } editorOptions.ts
5545 >
5546 >
5547 > //#endregion
5548 >
5549 > //#region wrappingIndent
5550 >
5551 > /**
5552 > * Describes how to indent wrapped lines.
5553 > */
5554 > export const enum WrappingIndent {
5555 > /**
5556 > * No indentation => wrapped lines begin at column 1.
5557 > */
5558 > None = 0,
5559 > /**
5560 > * Same => wrapped lines get the same indentation as the parent.
5561 > */
5562 > Same = 1,
5563 > /**
5564 > * Indent => wrapped lines get +1 indentation toward the parent.
5565 > */
5566 > Indent = 2,
5567 > /**
5568 > * DeepIndent => wrapped lines get +2 indentation toward the parent.
5569 > */
5570 > DeepIndent = 3
5571 > }
5572 >
5573 > class WrappingIndentOption extends BaseEditorOption<EditorOption.wrappingIndent, 'none' | 'same' | 'indent' | 'deepIndent', WrappingIndent> {
5574 >
5575 > constructor() {
5576 > super(EditorOption.wrappingIndent, 'wrappingIndent', WrappingIndent.Same,
5577 > {
5578 > 'editor.wrappingIndent': {
5579 > type: 'string',
5580 > enum: ['none', 'same', 'indent', 'deepIndent'],
5581 > enumDescriptions: [
5582 > nls.localize('wrappingIndent.none', "No indentation. Wrapped lines begin at column 1."),
5583 > nls.localize('wrappingIndent.same', "Wrapped lines get the same indentation as the parent."),
5584 > nls.localize('wrappingIndent.indent', "Wrapped lines get +1 indentation toward the parent."),
5585 > nls.localize('wrappingIndent.deepIndent', "Wrapped lines get +2 indentation toward the parent."),
5586 > ],
5587 > description: nls.localize('wrappingIndent', "Controls the indentation of wrapped lines."),
5588 > default: 'same'
5589 > }
5590 > }
5591 > );
5592 > }
5593 >
5594 > public validate(input: unknown): WrappingIndent {
5595 switch (input) {
5596 case 'none': return WrappingIndent.None;
5601 return WrappingIndent.Same;
5602 }
5604 > public override compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: WrappingIndent): WrappingIndent {
5605 const accessibilitySupport = options.get(EditorOption.accessibilitySupport);
5606 if (accessibilitySupport === AccessibilitySupport.Enabled) {
5611 return value;
5612 }
5613 > } editorOptions.ts
5614 >
5615 > //#endregion
5616 >
5617 > //#region wrappingInfo
5618 >
5619 > export interface EditorWrappingInfo {
5620 > readonly isDominatedByLongLines: boolean;
5621 > readonly isWordWrapMinified: boolean;
5622 > readonly isViewportWrapping: boolean;
5623 > readonly wrappingColumn: number;
5624 > }
5625 >
5626 > class EditorWrappingInfoComputer extends ComputedEditorOption<EditorOption.wrappingInfo, EditorWrappingInfo> {
5627 >
5628 > constructor() {
5629 > super(EditorOption.wrappingInfo, {
5630 > isDominatedByLongLines: false,
5631 > isWordWrapMinified: false,
5632 > isViewportWrapping: false,
5633 > wrappingColumn: -1
5634 > });
5635 > }
5636 >
5637 > public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: EditorWrappingInfo): EditorWrappingInfo {
5638 const layoutInfo = options.get(EditorOption.layoutInfo);
5639
5645 };
5646 }
5647 > } editorOptions.ts
5648 >
5649 > //#endregion
5650 >
5651 > //#region dropIntoEditor
5652 >
5653 > /**
5654 > * Configuration options for editor drop into behavior
5655 > */
5656 > export interface IDropIntoEditorOptions {
5657 > /**
5658 > * Enable dropping into editor.
5659 > * Defaults to true.
5660 > */
5661 > enabled?: boolean;
5662 >
5663 > /**
5664 > * Controls if a widget is shown after a drop.
5665 > * Defaults to 'afterDrop'.
5666 > */
5667 > showDropSelector?: 'afterDrop' | 'never';
5668 > }
5669 >
5670 > /**
5671 > * @internal
5672 > */
5673 > export type EditorDropIntoEditorOptions = Readonly<Required<IDropIntoEditorOptions>>;
5674 >
5675 > class EditorDropIntoEditor extends BaseEditorOption<EditorOption.dropIntoEditor, IDropIntoEditorOptions, EditorDropIntoEditorOptions> {
5676 >
5677 > constructor() {
5678 > const defaults: EditorDropIntoEditorOptions = { enabled: true, showDropSelector: 'afterDrop' };
5679 > super(
5680 > EditorOption.dropIntoEditor, 'dropIntoEditor', defaults,
5681 > {
5682 > 'editor.dropIntoEditor.enabled': {
5683 > type: 'boolean',
5684 > default: defaults.enabled,
5685 > markdownDescription: nls.localize('dropIntoEditor.enabled', "Controls whether you can drag and drop a file into a text editor by holding down the `Shift` key (instead of opening the file in an editor)."),
5686 > },
5687 > 'editor.dropIntoEditor.showDropSelector': {
5688 > type: 'string',
5689 > markdownDescription: nls.localize('dropIntoEditor.showDropSelector', "Controls if a widget is shown when dropping files into the editor. This widget lets you control how the file is dropped."),
5690 > enum: [
5691 > 'afterDrop',
5692 > 'never'
5693 > ],
5694 > enumDescriptions: [
5695 > nls.localize('dropIntoEditor.showDropSelector.afterDrop', "Show the drop selector widget after a file is dropped into the editor."),
5696 > nls.localize('dropIntoEditor.showDropSelector.never', "Never show the drop selector widget. Instead the default drop provider is always used."),
5697 > ],
5698 > default: 'afterDrop',
5699 > },
5700 > }
5701 > );
5702 > }
5703 >
5704 > public validate(_input: unknown): EditorDropIntoEditorOptions {
5705 if (!_input || typeof _input !== 'object') {
5706 return this.defaultValue;
5712 };
5713 }
5714 > } editorOptions.ts
5715 >
5716 > //#endregion
5717 >
5718 > //#region pasteAs
5719 >
5720 > /**
5721 > * Configuration options for editor pasting as into behavior
5722 > */
5723 > export interface IPasteAsOptions {
5724 > /**
5725 > * Enable paste as functionality in editors.
5726 > * Defaults to true.
5727 > */
5728 > enabled?: boolean;
5729 >
5730 > /**
5731 > * Controls if a widget is shown after a drop.
5732 > * Defaults to 'afterPaste'.
5733 > */
5734 > showPasteSelector?: 'afterPaste' | 'never';
5735 > }
5736 >
5737 > /**
5738 > * @internal
5739 > */
5740 > export type EditorPasteAsOptions = Readonly<Required<IPasteAsOptions>>;
5741 >
5742 > class EditorPasteAs extends BaseEditorOption<EditorOption.pasteAs, IPasteAsOptions, EditorPasteAsOptions> {
5743 >
5744 > constructor() {
5745 > const defaults: EditorPasteAsOptions = { enabled: true, showPasteSelector: 'afterPaste' };
5746 > super(
5747 > EditorOption.pasteAs, 'pasteAs', defaults,
5748 > {
5749 > 'editor.pasteAs.enabled': {
5750 > type: 'boolean',
5751 > default: defaults.enabled,
5752 > markdownDescription: nls.localize('pasteAs.enabled', "Controls whether you can paste content in different ways."),
5753 > },
5754 > 'editor.pasteAs.showPasteSelector': {
5755 > type: 'string',
5756 > markdownDescription: nls.localize('pasteAs.showPasteSelector', "Controls if a widget is shown when pasting content in to the editor. This widget lets you control how the file is pasted."),
5757 > enum: [
5758 > 'afterPaste',
5759 > 'never'
5760 > ],
5761 > enumDescriptions: [
5762 > nls.localize('pasteAs.showPasteSelector.afterPaste', "Show the paste selector widget after content is pasted into the editor."),
5763 > nls.localize('pasteAs.showPasteSelector.never', "Never show the paste selector widget. Instead the default pasting behavior is always used."),
5764 > ],
5765 > default: 'afterPaste',
5766 > },
5767 > }
5768 > );
5769 > }
5770 >
5771 > public validate(_input: unknown): EditorPasteAsOptions {
5772 if (!_input || typeof _input !== 'object') {
5773 return this.defaultValue;
5779 };
5780 }
5781 > } editorOptions.ts
5782 >
5783 > //#endregion
5784 >
5785 > /**
5786 > * @internal
5787 > */
5788 > export const editorOptionsRegistry: IEditorOption<EditorOption, unknown>[] = [];
5789 >
5790 > function register<K extends EditorOption, V>(option: IEditorOption<K, V>): IEditorOption<K, V> {
5791 > editorOptionsRegistry[option.id] = option;
5792 > return option;
5793 > }
5794 >
5795 > export const enum EditorOption {
5796 > acceptSuggestionOnCommitCharacter,
5797 > acceptSuggestionOnEnter,
5798 > accessibilitySupport,
5799 > accessibilityPageSize,
5800 > allowOverflow,
5801 > allowVariableLineHeights,
5802 > allowVariableFonts,
5803 > allowVariableFontsInAccessibilityMode,
5804 > ariaLabel,
5805 > ariaRequired,
5806 > autoClosingBrackets,
5807 > autoClosingComments,
5808 > screenReaderAnnounceInlineSuggestion,
5809 > autoClosingDelete,
5810 > autoClosingOvertype,
5811 > autoClosingQuotes,
5812 > autoIndent,
5813 > autoIndentOnPaste,
5814 > autoIndentOnPasteWithinString,
5815 > automaticLayout,
5816 > autoSurround,
5817 > bracketPairColorization,
5818 > guides,
5819 > codeLens,
5820 > codeLensFontFamily,
5821 > codeLensFontSize,
5822 > colorDecorators,
5823 > colorDecoratorsLimit,
5824 > columnSelection,
5825 > comments,
5826 > contextmenu,
5827 > copyWithSyntaxHighlighting,
5828 > cursorBlinking,
5829 > cursorSmoothCaretAnimation,
5830 > cursorStyle,
5831 > cursorSurroundingLines,
5832 > cursorSurroundingLinesStyle,
5833 > cursorWidth,
5834 > cursorHeight,
5835 > disableLayerHinting,
5836 > disableMonospaceOptimizations,
5837 > domReadOnly,
5838 > dragAndDrop,
5839 > dropIntoEditor,
5840 > editContext,
5841 > emptySelectionClipboard,
5842 > experimentalGpuAcceleration,
5843 > experimentalWhitespaceRendering,
5844 > extraEditorClassName,
5845 > fastScrollSensitivity,
5846 > find,
5847 > fixedOverflowWidgets,
5848 > folding,
5849 > foldingStrategy,
5850 > foldingHighlight,
5851 > foldingImportsByDefault,
5852 > foldingMaximumRegions,
5853 > unfoldOnClickAfterEndOfLine,
5854 > fontFamily,
5855 > fontInfo,
5856 > fontLigatures,
5857 > fontSize,
5858 > fontWeight,
5859 > fontVariations,
5860 > formatOnPaste,
5861 > formatOnType,
5862 > glyphMargin,
5863 > gotoLocation,
5864 > hideCursorInOverviewRuler,
5865 > hover,
5866 > inDiffEditor,
5867 > inlineSuggest,
5868 > letterSpacing,
5869 > lightbulb,
5870 > lineDecorationsWidth,
5871 > lineHeight,
5872 > lineNumbers,
5873 > lineNumbersMinChars,
5874 > linkedEditing,
5875 > links,
5876 > matchBrackets,
5877 > minimap,
5878 > mouseStyle,
5879 > mouseWheelScrollSensitivity,
5880 > mouseWheelZoom,
5881 > multiCursorMergeOverlapping,
5882 > multiCursorModifier,
5883 > mouseMiddleClickAction,
5884 > multiCursorPaste,
5885 > multiCursorLimit,
5886 > occurrencesHighlight,
5887 > occurrencesHighlightDelay,
5888 > overtypeCursorStyle,
5889 > overtypeOnPaste,
5890 > overviewRulerBorder,
5891 > overviewRulerLanes,
5892 > padding,
5893 > pasteAs,
5894 > parameterHints,
5895 > peekWidgetDefaultFocus,
5896 > placeholder,
5897 > definitionLinkOpensInPeek,
5898 > quickSuggestions,
5899 > quickSuggestionsDelay,
5900 > readOnly,
5901 > readOnlyMessage,
5902 > renameOnType,
5903 > renderRichScreenReaderContent,
5904 > renderControlCharacters,
5905 > renderFinalNewline,
5906 > renderLineHighlight,
5907 > renderLineHighlightOnlyWhenFocus,
5908 > renderValidationDecorations,
5909 > renderWhitespace,
5910 > revealHorizontalRightPadding,
5911 > roundedSelection,
5912 > rulers,
5913 > scrollbar,
5914 > scrollBeyondLastColumn,
5915 > scrollBeyondLastLine,
5916 > scrollPredominantAxis,
5917 > selectionClipboard,
5918 > selectionHighlight,
5919 > selectionHighlightMaxLength,
5920 > selectionHighlightMultiline,
5921 > selectOnLineNumbers,
5922 > showFoldingControls,
5923 > showUnused,
5924 > snippetSuggestions,
5925 > smartSelect,
5926 > smoothScrolling,
5927 > stickyScroll,
5928 > stickyTabStops,
5929 > stopRenderingLineAfter,
5930 > suggest,
5931 > suggestFontSize,
5932 > suggestLineHeight,
5933 > suggestOnTriggerCharacters,
5934 > suggestSelection,
5935 > tabCompletion,
5936 > tabIndex,
5937 > trimWhitespaceOnDelete,
5938 > unicodeHighlighting,
5939 > unusualLineTerminators,
5940 > useShadowDOM,
5941 > useTabStops,
5942 > wordBreak,
5943 > wordSegmenterLocales,
5944 > wordSeparators,
5945 > wordWrap,
5946 > wordWrapBreakAfterCharacters,
5947 > wordWrapBreakBeforeCharacters,
5948 > wordWrapColumn,
5949 > wordWrapOverride1,
5950 > wordWrapOverride2,
5951 > wrappingIndent,
5952 > wrappingStrategy,
5953 > showDeprecated,
5954 > inertialScroll,
5955 > inlayHints,
5956 > wrapOnEscapedLineFeeds,
5957 > // Leave these at the end (because they have dependencies!)
5958 > effectiveCursorStyle,
5959 > editorClassName,
5960 > pixelRatio,
5961 > tabFocusMode,
5962 > layoutInfo,
5963 > wrappingInfo,
5964 > defaultColorDecorators,
5965 > colorDecoratorsActivatedOn,
5966 > inlineCompletionsAccessibilityVerbose,
5967 > effectiveEditContext,
5968 > scrollOnMiddleClick,
5969 > effectiveAllowVariableFonts,
5970 > doubleClickSelectsBlock
5971 > }
5972 >
5973 > export const EditorOptions = {
5974 > acceptSuggestionOnCommitCharacter: register(new EditorBooleanOption(
5975 > EditorOption.acceptSuggestionOnCommitCharacter, 'acceptSuggestionOnCommitCharacter', true,
5976 > { markdownDescription: nls.localize('acceptSuggestionOnCommitCharacter', "Controls whether suggestions should be accepted on commit characters. For example, in JavaScript, the semi-colon (`;`) can be a commit character that accepts a suggestion and types that character.") }
5977 > )),
5978 > acceptSuggestionOnEnter: register(new EditorStringEnumOption(
5979 > EditorOption.acceptSuggestionOnEnter, 'acceptSuggestionOnEnter',
5980 > 'on' as 'on' | 'smart' | 'off',
5981 > ['on', 'smart', 'off'] as const,
5982 > {
5983 > markdownEnumDescriptions: [
5984 > '',
5985 > nls.localize('acceptSuggestionOnEnterSmart', "Only accept a suggestion with `Enter` when it makes a textual change."),
5986 > ''
5987 > ],
5988 > markdownDescription: nls.localize('acceptSuggestionOnEnter', "Controls whether suggestions should be accepted on `Enter`, in addition to `Tab`. Helps to avoid ambiguity between inserting new lines or accepting suggestions.")
5989 > }
5990 > )),
5991 > accessibilitySupport: register(new EditorAccessibilitySupport()),
5992 > accessibilityPageSize: register(new EditorIntOption(EditorOption.accessibilityPageSize, 'accessibilityPageSize', 500, 1, Constants.MAX_SAFE_SMALL_INTEGER,
5993 > {
5994 > description: nls.localize('accessibilityPageSize', "Controls the number of lines in the editor that can be read out by a screen reader at once. When we detect a screen reader we automatically set the default to be 500. Warning: this has a performance implication for numbers larger than the default."),
5995 > tags: ['accessibility']
5996 > }
5997 > )),
5998 > allowOverflow: register(new EditorBooleanOption(
5999 > EditorOption.allowOverflow, 'allowOverflow', true,
6000 > )),
6001 > allowVariableLineHeights: register(new EditorBooleanOption(
6002 > EditorOption.allowVariableLineHeights, 'allowVariableLineHeights', true,
6003 > {
6004 > description: nls.localize('allowVariableLineHeights', "Controls whether to allow using variable line heights in the editor.")
6005 > }
6006 > )),
6007 > allowVariableFonts: register(new EditorBooleanOption(
6008 > EditorOption.allowVariableFonts, 'allowVariableFonts', true,
6009 > {
6010 > description: nls.localize('allowVariableFonts', "Controls whether to allow using variable fonts in the editor.")
6011 > }
6012 > )),
6013 > allowVariableFontsInAccessibilityMode: register(new EditorBooleanOption(
6014 > EditorOption.allowVariableFontsInAccessibilityMode, 'allowVariableFontsInAccessibilityMode', false,
6015 > {
6016 > description: nls.localize('allowVariableFontsInAccessibilityMode', "Controls whether to allow using variable fonts in the editor in the accessibility mode."),
6017 > tags: ['accessibility']
6018 > }
6019 > )),
6020 > ariaLabel: register(new EditorStringOption(
6021 > EditorOption.ariaLabel, 'ariaLabel', nls.localize('editorViewAccessibleLabel', "Editor content")
6022 > )),
6023 > ariaRequired: register(new EditorBooleanOption(
6024 > EditorOption.ariaRequired, 'ariaRequired', false, undefined
6025 > )),
6026 > screenReaderAnnounceInlineSuggestion: register(new EditorBooleanOption(
6027 > EditorOption.screenReaderAnnounceInlineSuggestion, 'screenReaderAnnounceInlineSuggestion', true,
6028 > {
6029 > description: nls.localize('screenReaderAnnounceInlineSuggestion', "Control whether inline suggestions are announced by a screen reader."),
6030 > tags: ['accessibility']
6031 > }
6032 > )),
6033 > autoClosingBrackets: register(new EditorStringEnumOption(
6034 > EditorOption.autoClosingBrackets, 'autoClosingBrackets',
6035 > 'languageDefined' as 'always' | 'languageDefined' | 'beforeWhitespace' | 'never',
6036 > ['always', 'languageDefined', 'beforeWhitespace', 'never'] as const,
6037 > {
6038 > enumDescriptions: [
6039 > '',
6040 > nls.localize('editor.autoClosingBrackets.languageDefined', "Use language configurations to determine when to autoclose brackets."),
6041 > nls.localize('editor.autoClosingBrackets.beforeWhitespace', "Autoclose brackets only when the cursor is to the left of whitespace."),
6042 > '',
6043 > ],
6044 > description: nls.localize('autoClosingBrackets', "Controls whether the editor should automatically close brackets after the user adds an opening bracket.")
6045 > }
6046 > )),
6047 > autoClosingComments: register(new EditorStringEnumOption(
6048 > EditorOption.autoClosingComments, 'autoClosingComments',
6049 > 'languageDefined' as 'always' | 'languageDefined' | 'beforeWhitespace' | 'never',
6050 > ['always', 'languageDefined', 'beforeWhitespace', 'never'] as const,
6051 > {
6052 > enumDescriptions: [
6053 > '',
6054 > nls.localize('editor.autoClosingComments.languageDefined', "Use language configurations to determine when to autoclose comments."),
6055 > nls.localize('editor.autoClosingComments.beforeWhitespace', "Autoclose comments only when the cursor is to the left of whitespace."),
6056 > '',
6057 > ],
6058 > description: nls.localize('autoClosingComments', "Controls whether the editor should automatically close comments after the user adds an opening comment.")
6059 > }
6060 > )),
6061 > autoClosingDelete: register(new EditorStringEnumOption(
6062 > EditorOption.autoClosingDelete, 'autoClosingDelete',
6063 > 'auto' as 'always' | 'auto' | 'never',
6064 > ['always', 'auto', 'never'] as const,
6065 > {
6066 > enumDescriptions: [
6067 > '',
6068 > nls.localize('editor.autoClosingDelete.auto', "Remove adjacent closing quotes or brackets only if they were automatically inserted."),
6069 > '',
6070 > ],
6071 > description: nls.localize('autoClosingDelete', "Controls whether the editor should remove adjacent closing quotes or brackets when deleting.")
6072 > }
6073 > )),
6074 > autoClosingOvertype: register(new EditorStringEnumOption(
6075 > EditorOption.autoClosingOvertype, 'autoClosingOvertype',
6076 > 'auto' as 'always' | 'auto' | 'never',
6077 > ['always', 'auto', 'never'] as const,
6078 > {
6079 > enumDescriptions: [
6080 > '',
6081 > nls.localize('editor.autoClosingOvertype.auto', "Type over closing quotes or brackets only if they were automatically inserted."),
6082 > '',
6083 > ],
6084 > description: nls.localize('autoClosingOvertype', "Controls whether the editor should type over closing quotes or brackets.")
6085 > }
6086 > )),
6087 > autoClosingQuotes: register(new EditorStringEnumOption(
6088 > EditorOption.autoClosingQuotes, 'autoClosingQuotes',
6089 > 'languageDefined' as 'always' | 'languageDefined' | 'beforeWhitespace' | 'never',
6090 > ['always', 'languageDefined', 'beforeWhitespace', 'never'] as const,
6091 > {
6092 > enumDescriptions: [
6093 > '',
6094 > nls.localize('editor.autoClosingQuotes.languageDefined', "Use language configurations to determine when to autoclose quotes."),
6095 > nls.localize('editor.autoClosingQuotes.beforeWhitespace', "Autoclose quotes only when the cursor is to the left of whitespace."),
6096 > '',
6097 > ],
6098 > description: nls.localize('autoClosingQuotes', "Controls whether the editor should automatically close quotes after the user adds an opening quote.")
6099 > }
6100 > )),
6101 > autoIndent: register(new EditorEnumOption(
6102 > EditorOption.autoIndent, 'autoIndent',
6103 > EditorAutoIndentStrategy.Full, 'full',
6104 > ['none', 'keep', 'brackets', 'advanced', 'full'],
6105 > _autoIndentFromString,
6106 > {
6107 > enumDescriptions: [
6108 > nls.localize('editor.autoIndent.none', "The editor will not insert indentation automatically."),
6109 > nls.localize('editor.autoIndent.keep', "The editor will keep the current line's indentation."),
6110 > nls.localize('editor.autoIndent.brackets', "The editor will keep the current line's indentation and honor language defined brackets."),
6111 > nls.localize('editor.autoIndent.advanced', "The editor will keep the current line's indentation, honor language defined brackets and invoke special onEnterRules defined by languages."),
6112 > nls.localize('editor.autoIndent.full', "The editor will keep the current line's indentation, honor language defined brackets, invoke special onEnterRules defined by languages, and honor indentationRules defined by languages."),
6113 > ],
6114 > description: nls.localize('autoIndent', "Controls whether the editor should automatically adjust the indentation when users type, paste, move or indent lines.")
6115 > }
6116 > )),
6117 > autoIndentOnPaste: register(new EditorBooleanOption(
6118 > EditorOption.autoIndentOnPaste, 'autoIndentOnPaste', false,
6119 > { description: nls.localize('autoIndentOnPaste', "Controls whether the editor should automatically auto-indent the pasted content.") }
6120 > )),
6121 > autoIndentOnPasteWithinString: register(new EditorBooleanOption(
6122 > EditorOption.autoIndentOnPasteWithinString, 'autoIndentOnPasteWithinString', true,
6123 > { description: nls.localize('autoIndentOnPasteWithinString', "Controls whether the editor should automatically auto-indent the pasted content when pasted within a string. This takes effect when autoIndentOnPaste is true.") }
6124 > )),
6125 > automaticLayout: register(new EditorBooleanOption(
6126 > EditorOption.automaticLayout, 'automaticLayout', false,
6127 > )),
6128 > autoSurround: register(new EditorStringEnumOption(
6129 > EditorOption.autoSurround, 'autoSurround',
6130 > 'languageDefined' as 'languageDefined' | 'quotes' | 'brackets' | 'never',
6131 > ['languageDefined', 'quotes', 'brackets', 'never'] as const,
6132 > {
6133 > enumDescriptions: [
6134 > nls.localize('editor.autoSurround.languageDefined', "Use language configurations to determine when to automatically surround selections."),
6135 > nls.localize('editor.autoSurround.quotes', "Surround with quotes but not brackets."),
6136 > nls.localize('editor.autoSurround.brackets', "Surround with brackets but not quotes."),
6137 > ''
6138 > ],
6139 > description: nls.localize('autoSurround', "Controls whether the editor should automatically surround selections when typing quotes or brackets.")
6140 > }
6141 > )),
6142 > bracketPairColorization: register(new BracketPairColorization()),
6143 > bracketPairGuides: register(new GuideOptions()),
6144 > stickyTabStops: register(new EditorBooleanOption(
6145 > EditorOption.stickyTabStops, 'stickyTabStops', false,
6146 > { description: nls.localize('stickyTabStops', "Emulate selection behavior of tab characters when using spaces for indentation. Selection will stick to tab stops.") }
6147 > )),
6148 > codeLens: register(new EditorBooleanOption(
6149 > EditorOption.codeLens, 'codeLens', true,
6150 > { description: nls.localize('codeLens', "Controls whether the editor shows CodeLens.") }
6151 > )),
6152 > codeLensFontFamily: register(new EditorStringOption(
6153 > EditorOption.codeLensFontFamily, 'codeLensFontFamily', '',
6154 > { description: nls.localize('codeLensFontFamily', "Controls the font family for CodeLens.") }
6155 > )),
6156 > codeLensFontSize: register(new EditorIntOption(EditorOption.codeLensFontSize, 'codeLensFontSize', 0, 0, 100, {
6157 > type: 'number',
6158 > default: 0,
6159 > minimum: 0,
6160 > maximum: 100,
6161 > markdownDescription: nls.localize('codeLensFontSize', "Controls the font size in pixels for CodeLens. When set to 0, 90% of `#editor.fontSize#` is used.")
6162 > })),
6163 > colorDecorators: register(new EditorBooleanOption(
6164 > EditorOption.colorDecorators, 'colorDecorators', true,
6165 > { description: nls.localize('colorDecorators', "Controls whether the editor should render the inline color decorators and color picker.") }
6166 > )),
6167 > colorDecoratorActivatedOn: register(new EditorStringEnumOption(EditorOption.colorDecoratorsActivatedOn, 'colorDecoratorsActivatedOn', 'clickAndHover' as 'clickAndHover' | 'hover' | 'click', ['clickAndHover', 'hover', 'click'] as const, {
6168 > enumDescriptions: [
6169 > nls.localize('editor.colorDecoratorActivatedOn.clickAndHover', "Make the color picker appear both on click and hover of the color decorator"),
6170 > nls.localize('editor.colorDecoratorActivatedOn.hover', "Make the color picker appear on hover of the color decorator"),
6171 > nls.localize('editor.colorDecoratorActivatedOn.click', "Make the color picker appear on click of the color decorator")
6172 > ],
6173 > description: nls.localize('colorDecoratorActivatedOn', "Controls the condition to make a color picker appear from a color decorator.")
6174 > })),
6175 > colorDecoratorsLimit: register(new EditorIntOption(
6176 > EditorOption.colorDecoratorsLimit, 'colorDecoratorsLimit', 500, 1, 1000000,
6177 > {
6178 > markdownDescription: nls.localize('colorDecoratorsLimit', "Controls the max number of color decorators that can be rendered in an editor at once.")
6179 > }
6180 > )),
6181 > columnSelection: register(new EditorBooleanOption(
6182 > EditorOption.columnSelection, 'columnSelection', false,
6183 > { description: nls.localize('columnSelection', "Enable that the selection with the mouse and keys is doing column selection.") }
6184 > )),
6185 > comments: register(new EditorComments()),
6186 > contextmenu: register(new EditorBooleanOption(
6187 > EditorOption.contextmenu, 'contextmenu', true,
6188 > )),
6189 > copyWithSyntaxHighlighting: register(new EditorBooleanOption(
6190 > EditorOption.copyWithSyntaxHighlighting, 'copyWithSyntaxHighlighting', true,
6191 > { description: nls.localize('copyWithSyntaxHighlighting', "Controls whether syntax highlighting should be copied into the clipboard.") }
6192 > )),
6193 > cursorBlinking: register(new EditorEnumOption(
6194 > EditorOption.cursorBlinking, 'cursorBlinking',
6195 > TextEditorCursorBlinkingStyle.Blink, 'blink',
6196 > ['blink', 'smooth', 'phase', 'expand', 'solid'],
6197 > cursorBlinkingStyleFromString,
6198 > { description: nls.localize('cursorBlinking', "Control the cursor animation style.") }
6199 > )),
6200 > cursorSmoothCaretAnimation: register(new EditorStringEnumOption(
6201 > EditorOption.cursorSmoothCaretAnimation, 'cursorSmoothCaretAnimation',
6202 > 'off' as 'off' | 'explicit' | 'on',
6203 > ['off', 'explicit', 'on'] as const,
6204 > {
6205 > enumDescriptions: [
6206 > nls.localize('cursorSmoothCaretAnimation.off', "Smooth caret animation is disabled."),
6207 > nls.localize('cursorSmoothCaretAnimation.explicit', "Smooth caret animation is enabled only when the user moves the cursor with an explicit gesture."),
6208 > nls.localize('cursorSmoothCaretAnimation.on', "Smooth caret animation is always enabled.")
6209 > ],
6210 > description: nls.localize('cursorSmoothCaretAnimation', "Controls whether the smooth caret animation should be enabled.")
6211 > }
6212 > )),
6213 > cursorStyle: register(new EditorEnumOption(
6214 > EditorOption.cursorStyle, 'cursorStyle',
6215 > TextEditorCursorStyle.Line, 'line',
6216 > ['line', 'block', 'underline', 'line-thin', 'block-outline', 'underline-thin'],
6217 > cursorStyleFromString,
6218 > { description: nls.localize('cursorStyle', "Controls the cursor style in insert input mode.") }
6219 > )),
6220 > overtypeCursorStyle: register(new EditorEnumOption(
6221 > EditorOption.overtypeCursorStyle, 'overtypeCursorStyle',
6222 > TextEditorCursorStyle.Block, 'block',
6223 > ['line', 'block', 'underline', 'line-thin', 'block-outline', 'underline-thin'],
6224 > cursorStyleFromString,
6225 > { description: nls.localize('overtypeCursorStyle', "Controls the cursor style in overtype input mode.") }
6226 > )),
6227 > cursorSurroundingLines: register(new EditorIntOption(
6228 > EditorOption.cursorSurroundingLines, 'cursorSurroundingLines',
6229 > 0, 0, Constants.MAX_SAFE_SMALL_INTEGER,
6230 > { description: nls.localize('cursorSurroundingLines', "Controls the minimal number of visible leading lines (minimum 0) and trailing lines (minimum 1) surrounding the cursor. Known as 'scrollOff' or 'scrollOffset' in some other editors.") }
6231 > )),
6232 > cursorSurroundingLinesStyle: register(new EditorStringEnumOption(
6233 > EditorOption.cursorSurroundingLinesStyle, 'cursorSurroundingLinesStyle',
6234 > 'default' as 'default' | 'all',
6235 > ['default', 'all'] as const,
6236 > {
6237 > enumDescriptions: [
6238 > nls.localize('cursorSurroundingLinesStyle.default', "`cursorSurroundingLines` is enforced only when triggered via the keyboard or API."),
6239 > nls.localize('cursorSurroundingLinesStyle.all', "`cursorSurroundingLines` is enforced always.")
6240 > ],
6241 > markdownDescription: nls.localize('cursorSurroundingLinesStyle', "Controls when `#editor.cursorSurroundingLines#` should be enforced.")
6242 > }
6243 > )),
6244 > cursorWidth: register(new EditorIntOption(
6245 > EditorOption.cursorWidth, 'cursorWidth',
6246 > 0, 0, Constants.MAX_SAFE_SMALL_INTEGER,
6247 > { markdownDescription: nls.localize('cursorWidth', "Controls the width of the cursor when `#editor.cursorStyle#` is set to `line`.") }
6248 > )),
6249 > cursorHeight: register(new EditorIntOption(
6250 > EditorOption.cursorHeight, 'cursorHeight',
6251 > 0, 0, Constants.MAX_SAFE_SMALL_INTEGER,
6252 > { markdownDescription: nls.localize('cursorHeight', "Controls the height of the cursor when `#editor.cursorStyle#` is set to `line`. Cursor's max height depends on line height.") }
6253 > )),
6254 > disableLayerHinting: register(new EditorBooleanOption(
6255 > EditorOption.disableLayerHinting, 'disableLayerHinting', false,
6256 > )),
6257 > disableMonospaceOptimizations: register(new EditorBooleanOption(
6258 > EditorOption.disableMonospaceOptimizations, 'disableMonospaceOptimizations', false
6259 > )),
6260 > domReadOnly: register(new EditorBooleanOption(
6261 > EditorOption.domReadOnly, 'domReadOnly', false,
6262 > )),
6263 > doubleClickSelectsBlock: register(new EditorBooleanOption(
6264 > EditorOption.doubleClickSelectsBlock, 'doubleClickSelectsBlock', true,
6265 > { description: nls.localize('doubleClickSelectsBlock', "Controls whether double-clicking next to a bracket or quote selects the content inside.") }
6266 > )),
6267 > dragAndDrop: register(new EditorBooleanOption(
6268 > EditorOption.dragAndDrop, 'dragAndDrop', true,
6269 > { description: nls.localize('dragAndDrop', "Controls whether the editor should allow moving selections via drag and drop.") }
6270 > )),
6271 > emptySelectionClipboard: register(new EditorEmptySelectionClipboard()),
6272 > dropIntoEditor: register(new EditorDropIntoEditor()),
6273 > editContext: register(new EditorBooleanOption(
6274 > EditorOption.editContext, 'editContext', true,
6275 > {
6276 > description: nls.localize('editContext', "Sets whether the EditContext API should be used instead of the text area to power input in the editor."),
6277 > included: platform.isChrome || platform.isEdge || platform.isNative
6278 > }
6279 > )),
6280 > renderRichScreenReaderContent: register(new EditorBooleanOption(
6281 > EditorOption.renderRichScreenReaderContent, 'renderRichScreenReaderContent', false,
6282 > {
6283 > markdownDescription: nls.localize('renderRichScreenReaderContent', "Whether to render rich screen reader content when the `#editor.editContext#` setting is enabled."),
6284 > }
6285 > )),
6286 > stickyScroll: register(new EditorStickyScroll()),
6287 > experimentalGpuAcceleration: register(new EditorStringEnumOption(
6288 > EditorOption.experimentalGpuAcceleration, 'experimentalGpuAcceleration',
6289 > 'off' as 'off' | 'on',
6290 > ['off', 'on'] as const,
6291 > {
6292 > tags: ['experimental'],
6293 > enumDescriptions: [
6294 > nls.localize('experimentalGpuAcceleration.off', "Use regular DOM-based rendering."),
6295 > nls.localize('experimentalGpuAcceleration.on', "Use GPU acceleration."),
6296 > ],
6297 > description: nls.localize('experimentalGpuAcceleration', "Controls whether to use the experimental GPU acceleration to render the editor.")
6298 > }
6299 > )),
6300 > experimentalWhitespaceRendering: register(new EditorStringEnumOption(
6301 > EditorOption.experimentalWhitespaceRendering, 'experimentalWhitespaceRendering',
6302 > 'svg' as 'svg' | 'font' | 'off',
6303 > ['svg', 'font', 'off'] as const,
6304 > {
6305 > enumDescriptions: [
6306 > nls.localize('experimentalWhitespaceRendering.svg', "Use a new rendering method with svgs."),
6307 > nls.localize('experimentalWhitespaceRendering.font', "Use a new rendering method with font characters."),
6308 > nls.localize('experimentalWhitespaceRendering.off', "Use the stable rendering method."),
6309 > ],
6310 > description: nls.localize('experimentalWhitespaceRendering', "Controls whether whitespace is rendered with a new, experimental method.")
6311 > }
6312 > )),
6313 > extraEditorClassName: register(new EditorStringOption(
6314 > EditorOption.extraEditorClassName, 'extraEditorClassName', '',
6315 > )),
6316 > fastScrollSensitivity: register(new EditorFloatOption(
6317 > EditorOption.fastScrollSensitivity, 'fastScrollSensitivity',
6318 > 5, x => (x <= 0 ? 5 : x),
6319 > { markdownDescription: nls.localize('fastScrollSensitivity', "Scrolling speed multiplier when pressing `Alt`.") }
6320 > )),
6321 > find: register(new EditorFind()),
6322 > fixedOverflowWidgets: register(new EditorBooleanOption(
6323 > EditorOption.fixedOverflowWidgets, 'fixedOverflowWidgets', false,
6324 > )),
6325 > folding: register(new EditorBooleanOption(
6326 > EditorOption.folding, 'folding', true,
6327 > { description: nls.localize('folding', "Controls whether the editor has code folding enabled.") }
6328 > )),
6329 > foldingStrategy: register(new EditorStringEnumOption(
6330 > EditorOption.foldingStrategy, 'foldingStrategy',
6331 > 'auto' as 'auto' | 'indentation',
6332 > ['auto', 'indentation'] as const,
6333 > {
6334 > enumDescriptions: [
6335 > nls.localize('foldingStrategy.auto', "Use a language-specific folding strategy if available, else the indentation-based one."),
6336 > nls.localize('foldingStrategy.indentation', "Use the indentation-based folding strategy."),
6337 > ],
6338 > description: nls.localize('foldingStrategy', "Controls the strategy for computing folding ranges.")
6339 > }
6340 > )),
6341 > foldingHighlight: register(new EditorBooleanOption(
6342 > EditorOption.foldingHighlight, 'foldingHighlight', true,
6343 > { description: nls.localize('foldingHighlight', "Controls whether the editor should highlight folded ranges.") }
6344 > )),
6345 > foldingImportsByDefault: register(new EditorBooleanOption(
6346 > EditorOption.foldingImportsByDefault, 'foldingImportsByDefault', false,
6347 > { description: nls.localize('foldingImportsByDefault', "Controls whether the editor automatically collapses import ranges.") }
6348 > )),
6349 > foldingMaximumRegions: register(new EditorIntOption(
6350 > EditorOption.foldingMaximumRegions, 'foldingMaximumRegions',
6351 > 5000, 10, 65000, // limit must be less than foldingRanges MAX_FOLDING_REGIONS
6352 > { description: nls.localize('foldingMaximumRegions', "The maximum number of foldable regions. Increasing this value may result in the editor becoming less responsive when the current source has a large number of foldable regions.") }
6353 > )),
6354 > unfoldOnClickAfterEndOfLine: register(new EditorBooleanOption(
6355 > EditorOption.unfoldOnClickAfterEndOfLine, 'unfoldOnClickAfterEndOfLine', false,
6356 > { description: nls.localize('unfoldOnClickAfterEndOfLine', "Controls whether clicking on the empty content after a folded line will unfold the line.") }
6357 > )),
6358 > fontFamily: register(new EditorStringOption(
6359 > EditorOption.fontFamily, 'fontFamily', EDITOR_FONT_DEFAULTS.fontFamily,
6360 > { description: nls.localize('fontFamily', "Controls the font family.") }
6361 > )),
6362 > fontInfo: register(new EditorFontInfo()),
6363 > fontLigatures2: register(new EditorFontLigatures()),
6364 > fontSize: register(new EditorFontSize()),
6365 > fontWeight: register(new EditorFontWeight()),
6366 > fontVariations: register(new EditorFontVariations()),
6367 > formatOnPaste: register(new EditorBooleanOption(
6368 > EditorOption.formatOnPaste, 'formatOnPaste', false,
6369 > { description: nls.localize('formatOnPaste', "Controls whether the editor should automatically format the pasted content. A formatter must be available and the formatter should be able to format a range in a document.") }
6370 > )),
6371 > formatOnType: register(new EditorBooleanOption(
6372 > EditorOption.formatOnType, 'formatOnType', false,
6373 > { description: nls.localize('formatOnType', "Controls whether the editor should automatically format the line after typing.") }
6374 > )),
6375 > glyphMargin: register(new EditorBooleanOption(
6376 > EditorOption.glyphMargin, 'glyphMargin', true,
6377 > { description: nls.localize('glyphMargin', "Controls whether the editor should render the vertical glyph margin. Glyph margin is mostly used for debugging.") }
6378 > )),
6379 > gotoLocation: register(new EditorGoToLocation()),
6380 > hideCursorInOverviewRuler: register(new EditorBooleanOption(
6381 > EditorOption.hideCursorInOverviewRuler, 'hideCursorInOverviewRuler', false,
6382 > { description: nls.localize('hideCursorInOverviewRuler', "Controls whether the cursor should be hidden in the overview ruler.") }
6383 > )),
6384 > hover: register(new EditorHover()),
6385 > inDiffEditor: register(new EditorBooleanOption(
6386 > EditorOption.inDiffEditor, 'inDiffEditor', false
6387 > )),
6388 > inertialScroll: register(new EditorBooleanOption(
6389 > EditorOption.inertialScroll, 'inertialScroll', false,
6390 > { description: nls.localize('inertialScroll', "Make scrolling inertial - mostly useful with touchpad on linux.") }
6391 > )),
6392 > letterSpacing: register(new EditorFloatOption(
6393 > EditorOption.letterSpacing, 'letterSpacing',
6394 > EDITOR_FONT_DEFAULTS.letterSpacing, x => EditorFloatOption.clamp(x, -5, 20),
6395 > { description: nls.localize('letterSpacing', "Controls the letter spacing in pixels.") }
6396 > )),
6397 > lightbulb: register(new EditorLightbulb()),
6398 > lineDecorationsWidth: register(new EditorLineDecorationsWidth()),
6399 > lineHeight: register(new EditorLineHeight()),
6400 > lineNumbers: register(new EditorRenderLineNumbersOption()),
6401 > lineNumbersMinChars: register(new EditorIntOption(
6402 > EditorOption.lineNumbersMinChars, 'lineNumbersMinChars',
6403 > 5, 1, 300
6404 > )),
6405 > linkedEditing: register(new EditorBooleanOption(
6406 > EditorOption.linkedEditing, 'linkedEditing', false,
6407 > { description: nls.localize('linkedEditing', "Controls whether the editor has linked editing enabled. Depending on the language, related symbols such as HTML tags, are updated while editing.") }
6408 > )),
6409 > links: register(new EditorBooleanOption(
6410 > EditorOption.links, 'links', true,
6411 > { description: nls.localize('links', "Controls whether the editor should detect links and make them clickable.") }
6412 > )),
6413 > matchBrackets: register(new EditorStringEnumOption(
6414 > EditorOption.matchBrackets, 'matchBrackets',
6415 > 'always' as 'never' | 'near' | 'always',
6416 > ['always', 'near', 'never'] as const,
6417 > { description: nls.localize('matchBrackets', "Highlight matching brackets.") }
6418 > )),
6419 > minimap: register(new EditorMinimap()),
6420 > mouseStyle: register(new EditorStringEnumOption(
6421 > EditorOption.mouseStyle, 'mouseStyle',
6422 > 'text' as 'text' | 'default' | 'copy',
6423 > ['text', 'default', 'copy'] as const,
6424 > )),
6425 > mouseWheelScrollSensitivity: register(new EditorFloatOption(
6426 > EditorOption.mouseWheelScrollSensitivity, 'mouseWheelScrollSensitivity',
6427 > 1, x => (x === 0 ? 1 : x),
6428 > { markdownDescription: nls.localize('mouseWheelScrollSensitivity', "A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.") }
6429 > )),
6430 > mouseWheelZoom: register(new EditorBooleanOption(
6431 > EditorOption.mouseWheelZoom, 'mouseWheelZoom', false,
6432 > {
6433 > markdownDescription: platform.isMacintosh
6434 ? nls.localize('mouseWheelZoom.mac', "Zoom the font of the editor when using mouse wheel and holding `Cmd`.")
6435 > : nls.localize('mouseWheelZoom', "Zoom the font of the editor when using mouse wheel and holding `Ctrl`.") editorOptions.ts
6436 > }
6437 > )),
6438 > multiCursorMergeOverlapping: register(new EditorBooleanOption(
6439 > EditorOption.multiCursorMergeOverlapping, 'multiCursorMergeOverlapping', true,
6440 > { description: nls.localize('multiCursorMergeOverlapping', "Merge multiple cursors when they are overlapping.") }
6441 > )),
6442 > multiCursorModifier: register(new EditorEnumOption(
6443 > EditorOption.multiCursorModifier, 'multiCursorModifier',
6444 > 'altKey', 'alt',
6445 > ['ctrlCmd', 'alt'],
6446 > _multiCursorModifierFromString,
6447 > {
6448 > markdownEnumDescriptions: [
6449 > nls.localize('multiCursorModifier.ctrlCmd', "Maps to `Control` on Windows and Linux and to `Command` on macOS."),
6450 > nls.localize('multiCursorModifier.alt', "Maps to `Alt` on Windows and Linux and to `Option` on macOS.")
6451 > ],
6452 > markdownDescription: nls.localize({
6453 > key: 'multiCursorModifier',
6454 > comment: [
6455 > '- `ctrlCmd` refers to a value the setting can take and should not be localized.',
6456 > '- `Control` and `Command` refer to the modifier keys Ctrl or Cmd on the keyboard and can be localized.'
6457 > ]
6458 > }, "The modifier to be used to add multiple cursors with the mouse. The Go to Definition and Open Link mouse gestures will adapt such that they do not conflict with the [multicursor modifier](https://code.visualstudio.com/docs/editor/codebasics#_multicursor-modifier).")
6459 > }
6460 > )),
6461 > mouseMiddleClickAction: register(new EditorStringEnumOption(
6462 > EditorOption.mouseMiddleClickAction, 'mouseMiddleClickAction', 'default' as MouseMiddleClickAction,
6463 > ['default', 'openLink', 'ctrlLeftClick'] as MouseMiddleClickAction[],
6464 > { description: nls.localize('mouseMiddleClickAction', "Controls what happens when middle mouse button is clicked in the editor.") }
6465 > )),
6466 > multiCursorPaste: register(new EditorStringEnumOption(
6467 > EditorOption.multiCursorPaste, 'multiCursorPaste',
6468 > 'spread' as 'spread' | 'full',
6469 > ['spread', 'full'] as const,
6470 > {
6471 > markdownEnumDescriptions: [
6472 > nls.localize('multiCursorPaste.spread', "Each cursor pastes a single line of the text."),
6473 > nls.localize('multiCursorPaste.full', "Each cursor pastes the full text.")
6474 > ],
6475 > markdownDescription: nls.localize('multiCursorPaste', "Controls pasting when the line count of the pasted text matches the cursor count.")
6476 > }
6477 > )),
6478 > multiCursorLimit: register(new EditorIntOption(
6479 > EditorOption.multiCursorLimit, 'multiCursorLimit', 10000, 1, 100000,
6480 > {
6481 > markdownDescription: nls.localize('multiCursorLimit', "Controls the max number of cursors that can be in an active editor at once.")
6482 > }
6483 > )),
6484 > occurrencesHighlight: register(new EditorStringEnumOption(
6485 > EditorOption.occurrencesHighlight, 'occurrencesHighlight',
6486 > 'singleFile' as 'off' | 'singleFile' | 'multiFile',
6487 > ['off', 'singleFile', 'multiFile'] as const,
6488 > {
6489 > markdownEnumDescriptions: [
6490 > nls.localize('occurrencesHighlight.off', "Does not highlight occurrences."),
6491 > nls.localize('occurrencesHighlight.singleFile', "Highlights occurrences only in the current file."),
6492 > nls.localize('occurrencesHighlight.multiFile', "Experimental: Highlights occurrences across all valid open files.")
6493 > ],
6494 > markdownDescription: nls.localize('occurrencesHighlight', "Controls whether occurrences should be highlighted across open files.")
6495 > }
6496 > )),
6497 > occurrencesHighlightDelay: register(new EditorIntOption(
6498 > EditorOption.occurrencesHighlightDelay, 'occurrencesHighlightDelay',
6499 > 0, 0, 2000,
6500 > {
6501 > description: nls.localize('occurrencesHighlightDelay', "Controls the delay in milliseconds after which occurrences are highlighted."),
6502 > tags: ['preview']
6503 > }
6504 > )),
6505 > overtypeOnPaste: register(new EditorBooleanOption(
6506 > EditorOption.overtypeOnPaste, 'overtypeOnPaste', true,
6507 > { description: nls.localize('overtypeOnPaste', "Controls whether pasting should overtype.") }
6508 > )),
6509 > overviewRulerBorder: register(new EditorBooleanOption(
6510 > EditorOption.overviewRulerBorder, 'overviewRulerBorder', true,
6511 > { description: nls.localize('overviewRulerBorder', "Controls whether a border should be drawn around the overview ruler.") }
6512 > )),
6513 > overviewRulerLanes: register(new EditorIntOption(
6514 > EditorOption.overviewRulerLanes, 'overviewRulerLanes',
6515 > 3, 0, 3
6516 > )),
6517 > padding: register(new EditorPadding()),
6518 > pasteAs: register(new EditorPasteAs()),
6519 > parameterHints: register(new EditorParameterHints()),
6520 > peekWidgetDefaultFocus: register(new EditorStringEnumOption(
6521 > EditorOption.peekWidgetDefaultFocus, 'peekWidgetDefaultFocus',
6522 > 'tree' as 'tree' | 'editor',
6523 > ['tree', 'editor'] as const,
6524 > {
6525 > enumDescriptions: [
6526 > nls.localize('peekWidgetDefaultFocus.tree', "Focus the tree when opening peek"),
6527 > nls.localize('peekWidgetDefaultFocus.editor', "Focus the editor when opening peek")
6528 > ],
6529 > description: nls.localize('peekWidgetDefaultFocus', "Controls whether to focus the inline editor or the tree in the peek widget.")
6530 > }
6531 > )),
6532 > placeholder: register(new PlaceholderOption()),
6533 > definitionLinkOpensInPeek: register(new EditorBooleanOption(
6534 > EditorOption.definitionLinkOpensInPeek, 'definitionLinkOpensInPeek', false,
6535 > { description: nls.localize('definitionLinkOpensInPeek', "Controls whether the Go to Definition mouse gesture always opens the peek widget.") }
6536 > )),
6537 > quickSuggestions: register(new EditorQuickSuggestions()),
6538 > quickSuggestionsDelay: register(new EditorIntOption(
6539 > EditorOption.quickSuggestionsDelay, 'quickSuggestionsDelay',
6540 > 10, 0, Constants.MAX_SAFE_SMALL_INTEGER,
6541 > {
6542 > description: nls.localize('quickSuggestionsDelay', "Controls the delay in milliseconds after which quick suggestions will show up."),
6543 > experiment: {
6544 > mode: 'auto'
6545 > }
6546 > }
6547 > )),
6548 > readOnly: register(new EditorBooleanOption(
6549 > EditorOption.readOnly, 'readOnly', false,
6550 > )),
6551 > readOnlyMessage: register(new ReadonlyMessage()),
6552 > renameOnType: register(new EditorBooleanOption(
6553 > EditorOption.renameOnType, 'renameOnType', false,
6554 > { description: nls.localize('renameOnType', "Controls whether the editor auto renames on type."), markdownDeprecationMessage: nls.localize('renameOnTypeDeprecate', "Deprecated, use `#editor.linkedEditing#` instead.") }
6555 > )),
6556 > renderControlCharacters: register(new EditorBooleanOption(
6557 > EditorOption.renderControlCharacters, 'renderControlCharacters', true,
6558 > { description: nls.localize('renderControlCharacters', "Controls whether the editor should render control characters."), restricted: true }
6559 > )),
6560 > renderFinalNewline: register(new EditorStringEnumOption(
6561 > EditorOption.renderFinalNewline, 'renderFinalNewline',
6562 > (platform.isLinux ? 'dimmed' : 'on') as 'off' | 'on' | 'dimmed',
6563 > ['off', 'on', 'dimmed'] as const,
6564 > { description: nls.localize('renderFinalNewline', "Render last line number when the file ends with a newline.") }
6565 > )),
6566 > renderLineHighlight: register(new EditorStringEnumOption(
6567 > EditorOption.renderLineHighlight, 'renderLineHighlight',
6568 > 'line' as 'none' | 'gutter' | 'line' | 'all',
6569 > ['none', 'gutter', 'line', 'all'] as const,
6570 > {
6571 > enumDescriptions: [
6572 > '',
6573 > '',
6574 > '',
6575 > nls.localize('renderLineHighlight.all', "Highlights both the gutter and the current line."),
6576 > ],
6577 > description: nls.localize('renderLineHighlight', "Controls how the editor should render the current line highlight.")
6578 > }
6579 > )),
6580 > renderLineHighlightOnlyWhenFocus: register(new EditorBooleanOption(
6581 > EditorOption.renderLineHighlightOnlyWhenFocus, 'renderLineHighlightOnlyWhenFocus', false,
6582 > { description: nls.localize('renderLineHighlightOnlyWhenFocus', "Controls if the editor should render the current line highlight only when the editor is focused.") }
6583 > )),
6584 > renderValidationDecorations: register(new EditorStringEnumOption(
6585 > EditorOption.renderValidationDecorations, 'renderValidationDecorations',
6586 > 'editable' as 'editable' | 'on' | 'off',
6587 > ['editable', 'on', 'off'] as const
6588 > )),
6589 > renderWhitespace: register(new EditorStringEnumOption(
6590 > EditorOption.renderWhitespace, 'renderWhitespace',
6591 > 'selection' as 'selection' | 'none' | 'boundary' | 'trailing' | 'all',
6592 > ['none', 'boundary', 'selection', 'trailing', 'all'] as const,
6593 > {
6594 > enumDescriptions: [
6595 > '',
6596 > nls.localize('renderWhitespace.boundary', "Render whitespace characters except for single spaces between words."),
6597 > nls.localize('renderWhitespace.selection', "Render whitespace characters only on selected text."),
6598 > nls.localize('renderWhitespace.trailing', "Render only trailing whitespace characters."),
6599 > ''
6600 > ],
6601 > description: nls.localize('renderWhitespace', "Controls how the editor should render whitespace characters.")
6602 > }
6603 > )),
6604 > revealHorizontalRightPadding: register(new EditorIntOption(
6605 > EditorOption.revealHorizontalRightPadding, 'revealHorizontalRightPadding',
6606 > 15, 0, 1000,
6607 > )),
6608 > roundedSelection: register(new EditorBooleanOption(
6609 > EditorOption.roundedSelection, 'roundedSelection', true,
6610 > { description: nls.localize('roundedSelection', "Controls whether selections should have rounded corners.") }
6611 > )),
6612 > rulers: register(new EditorRulers()),
6613 > scrollbar: register(new EditorScrollbar()),
6614 > scrollBeyondLastColumn: register(new EditorIntOption(
6615 > EditorOption.scrollBeyondLastColumn, 'scrollBeyondLastColumn',
6616 > 4, 0, Constants.MAX_SAFE_SMALL_INTEGER,
6617 > { description: nls.localize('scrollBeyondLastColumn', "Controls the number of extra characters beyond which the editor will scroll horizontally.") }
6618 > )),
6619 > scrollBeyondLastLine: register(new EditorBooleanOption(
6620 > EditorOption.scrollBeyondLastLine, 'scrollBeyondLastLine', true,
6621 > { description: nls.localize('scrollBeyondLastLine', "Controls whether the editor will scroll beyond the last line.") }
6622 > )),
6623 > scrollOnMiddleClick: register(new EditorBooleanOption(
6624 > EditorOption.scrollOnMiddleClick, 'scrollOnMiddleClick', false,
6625 > { description: nls.localize('scrollOnMiddleClick', "Controls whether the editor will scroll when the middle button is pressed.") }
6626 > )),
6627 > scrollPredominantAxis: register(new EditorBooleanOption(
6628 > EditorOption.scrollPredominantAxis, 'scrollPredominantAxis', true,
6629 > { description: nls.localize('scrollPredominantAxis', "Scroll only along the predominant axis when scrolling both vertically and horizontally at the same time. Prevents horizontal drift when scrolling vertically on a trackpad.") }
6630 > )),
6631 > selectionClipboard: register(new EditorBooleanOption(
6632 > EditorOption.selectionClipboard, 'selectionClipboard', true,
6633 > {
6634 > description: nls.localize('selectionClipboard', "Controls whether the Linux primary clipboard should be supported."),
6635 > included: platform.isLinux
6636 > }
6637 > )),
6638 > selectionHighlight: register(new EditorBooleanOption(
6639 > EditorOption.selectionHighlight, 'selectionHighlight', true,
6640 > { description: nls.localize('selectionHighlight', "Controls whether the editor should highlight matches similar to the selection.") }
6641 > )),
6642 > selectionHighlightMaxLength: register(new EditorIntOption(
6643 > EditorOption.selectionHighlightMaxLength, 'selectionHighlightMaxLength',
6644 > 200, 0, Constants.MAX_SAFE_SMALL_INTEGER,
6645 > { description: nls.localize('selectionHighlightMaxLength', "Controls how many characters can be in the selection before similiar matches are not highlighted. Set to zero for unlimited.") }
6646 > )),
6647 > selectionHighlightMultiline: register(new EditorBooleanOption(
6648 > EditorOption.selectionHighlightMultiline, 'selectionHighlightMultiline', false,
6649 > { description: nls.localize('selectionHighlightMultiline', "Controls whether the editor should highlight selection matches that span multiple lines.") }
6650 > )),
6651 > selectOnLineNumbers: register(new EditorBooleanOption(
6652 > EditorOption.selectOnLineNumbers, 'selectOnLineNumbers', true,
6653 > )),
6654 > showFoldingControls: register(new EditorStringEnumOption(
6655 > EditorOption.showFoldingControls, 'showFoldingControls',
6656 > 'mouseover' as 'always' | 'never' | 'mouseover',
6657 > ['always', 'never', 'mouseover'] as const,
6658 > {
6659 > enumDescriptions: [
6660 > nls.localize('showFoldingControls.always', "Always show the folding controls."),
6661 > nls.localize('showFoldingControls.never', "Never show the folding controls and reduce the gutter size."),
6662 > nls.localize('showFoldingControls.mouseover', "Only show the folding controls when the mouse is over the gutter."),
6663 > ],
6664 > description: nls.localize('showFoldingControls', "Controls when the folding controls on the gutter are shown.")
6665 > }
6666 > )),
6667 > showUnused: register(new EditorBooleanOption(
6668 > EditorOption.showUnused, 'showUnused', true,
6669 > { description: nls.localize('showUnused', "Controls fading out of unused code.") }
6670 > )),
6671 > showDeprecated: register(new EditorBooleanOption(
6672 > EditorOption.showDeprecated, 'showDeprecated', true,
6673 > { description: nls.localize('showDeprecated', "Controls strikethrough deprecated variables.") }
6674 > )),
6675 > inlayHints: register(new EditorInlayHints()),
6676 > snippetSuggestions: register(new EditorStringEnumOption(
6677 > EditorOption.snippetSuggestions, 'snippetSuggestions',
6678 > 'inline' as 'top' | 'bottom' | 'inline' | 'none',
6679 > ['top', 'bottom', 'inline', 'none'] as const,
6680 > {
6681 > enumDescriptions: [
6682 > nls.localize('snippetSuggestions.top', "Show snippet suggestions on top of other suggestions."),
6683 > nls.localize('snippetSuggestions.bottom', "Show snippet suggestions below other suggestions."),
6684 > nls.localize('snippetSuggestions.inline', "Show snippets suggestions with other suggestions."),
6685 > nls.localize('snippetSuggestions.none', "Do not show snippet suggestions."),
6686 > ],
6687 > description: nls.localize('snippetSuggestions', "Controls whether snippets are shown with other suggestions and how they are sorted.")
6688 > }
6689 > )),
6690 > smartSelect: register(new SmartSelect()),
6691 > smoothScrolling: register(new EditorBooleanOption(
6692 > EditorOption.smoothScrolling, 'smoothScrolling', false,
6693 > { description: nls.localize('smoothScrolling', "Controls whether the editor will scroll using an animation.") }
6694 > )),
6695 > stopRenderingLineAfter: register(new EditorIntOption(
6696 > EditorOption.stopRenderingLineAfter, 'stopRenderingLineAfter',
6697 > 10000, -1, Constants.MAX_SAFE_SMALL_INTEGER,
6698 > )),
6699 > suggest: register(new EditorSuggest()),
6700 > inlineSuggest: register(new InlineEditorSuggest()),
6701 > inlineCompletionsAccessibilityVerbose: register(new EditorBooleanOption(EditorOption.inlineCompletionsAccessibilityVerbose, 'inlineCompletionsAccessibilityVerbose', false,
6702 > { description: nls.localize('inlineCompletionsAccessibilityVerbose', "Controls whether the accessibility hint should be provided to screen reader users when an inline completion is shown.") })),
6703 > suggestFontSize: register(new EditorIntOption(
6704 > EditorOption.suggestFontSize, 'suggestFontSize',
6705 > 0, 0, 1000,
6706 > { markdownDescription: nls.localize('suggestFontSize', "Font size for the suggest widget. When set to {0}, the value of {1} is used.", '`0`', '`#editor.fontSize#`') }
6707 > )),
6708 > suggestLineHeight: register(new EditorIntOption(
6709 > EditorOption.suggestLineHeight, 'suggestLineHeight',
6710 > 0, 0, 1000,
6711 > { markdownDescription: nls.localize('suggestLineHeight', "Line height for the suggest widget. When set to {0}, the value of {1} is used. The minimum value is 8.", '`0`', '`#editor.lineHeight#`') }
6712 > )),
6713 > suggestOnTriggerCharacters: register(new EditorBooleanOption(
6714 > EditorOption.suggestOnTriggerCharacters, 'suggestOnTriggerCharacters', true,
6715 > { description: nls.localize('suggestOnTriggerCharacters', "Controls whether suggestions should automatically show up when typing trigger characters.") }
6716 > )),
6717 > suggestSelection: register(new EditorStringEnumOption(
6718 > EditorOption.suggestSelection, 'suggestSelection',
6719 > 'first' as 'first' | 'recentlyUsed' | 'recentlyUsedByPrefix',
6720 > ['first', 'recentlyUsed', 'recentlyUsedByPrefix'] as const,
6721 > {
6722 > markdownEnumDescriptions: [
6723 > nls.localize('suggestSelection.first', "Always select the first suggestion."),
6724 > nls.localize('suggestSelection.recentlyUsed', "Select recent suggestions unless further typing selects one, e.g. `console.| -> console.log` because `log` has been completed recently."),
6725 > nls.localize('suggestSelection.recentlyUsedByPrefix', "Select suggestions based on previous prefixes that have completed those suggestions, e.g. `co -> console` and `con -> const`."),
6726 > ],
6727 > description: nls.localize('suggestSelection', "Controls how suggestions are pre-selected when showing the suggest list.")
6728 > }
6729 > )),
6730 > tabCompletion: register(new EditorStringEnumOption(
6731 > EditorOption.tabCompletion, 'tabCompletion',
6732 > 'off' as 'on' | 'off' | 'onlySnippets',
6733 > ['on', 'off', 'onlySnippets'] as const,
6734 > {
6735 > enumDescriptions: [
6736 > nls.localize('tabCompletion.on', "Tab complete will insert the best matching suggestion when pressing tab."),
6737 > nls.localize('tabCompletion.off', "Disable tab completions."),
6738 > nls.localize('tabCompletion.onlySnippets', "Tab complete snippets when their prefix match. Works best when 'quickSuggestions' aren't enabled."),
6739 > ],
6740 > description: nls.localize('tabCompletion', "Enables tab completions.")
6741 > }
6742 > )),
6743 > tabIndex: register(new EditorIntOption(
6744 > EditorOption.tabIndex, 'tabIndex',
6745 > 0, -1, Constants.MAX_SAFE_SMALL_INTEGER
6746 > )),
6747 > trimWhitespaceOnDelete: register(new EditorBooleanOption(
6748 > EditorOption.trimWhitespaceOnDelete, 'trimWhitespaceOnDelete', false,
6749 > { description: nls.localize('trimWhitespaceOnDelete', "Controls whether the editor will also delete the next line's indentation whitespace when deleting a newline.") }
6750 > )),
6751 > unicodeHighlight: register(new UnicodeHighlight()),
6752 > unusualLineTerminators: register(new EditorStringEnumOption(
6753 > EditorOption.unusualLineTerminators, 'unusualLineTerminators',
6754 > 'prompt' as 'auto' | 'off' | 'prompt',
6755 > ['auto', 'off', 'prompt'] as const,
6756 > {
6757 > enumDescriptions: [
6758 > nls.localize('unusualLineTerminators.auto', "Unusual line terminators are automatically removed."),
6759 > nls.localize('unusualLineTerminators.off', "Unusual line terminators are ignored."),
6760 > nls.localize('unusualLineTerminators.prompt', "Unusual line terminators prompt to be removed."),
6761 > ],
6762 > description: nls.localize('unusualLineTerminators', "Remove unusual line terminators that might cause problems.")
6763 > }
6764 > )),
6765 > useShadowDOM: register(new EditorBooleanOption(
6766 > EditorOption.useShadowDOM, 'useShadowDOM', true
6767 > )),
6768 > useTabStops: register(new EditorBooleanOption(
6769 > EditorOption.useTabStops, 'useTabStops', true,
6770 > { description: nls.localize('useTabStops', "Spaces and tabs are inserted and deleted in alignment with tab stops.") }
6771 > )),
6772 > wordBreak: register(new EditorStringEnumOption(
6773 > EditorOption.wordBreak, 'wordBreak',
6774 > 'normal' as 'normal' | 'keepAll',
6775 > ['normal', 'keepAll'] as const,
6776 > {
6777 > markdownEnumDescriptions: [
6778 > nls.localize('wordBreak.normal', "Use the default line break rule."),
6779 > nls.localize('wordBreak.keepAll', "Word breaks should not be used for Chinese/Japanese/Korean (CJK) text. Non-CJK text behavior is the same as for normal."),
6780 > ],
6781 > description: nls.localize('wordBreak', "Controls the word break rules used for Chinese/Japanese/Korean (CJK) text.")
6782 > }
6783 > )),
6784 > wordSegmenterLocales: register(new WordSegmenterLocales()),
6785 > wordSeparators: register(new EditorStringOption(
6786 > EditorOption.wordSeparators, 'wordSeparators', USUAL_WORD_SEPARATORS,
6787 > { description: nls.localize('wordSeparators', "Characters that will be used as word separators when doing word related navigations or operations.") }
6788 > )),
6789 > wordWrap: register(new EditorStringEnumOption(
6790 > EditorOption.wordWrap, 'wordWrap',
6791 > 'off' as 'off' | 'on' | 'wordWrapColumn' | 'bounded',
6792 > ['off', 'on', 'wordWrapColumn', 'bounded'] as const,
6793 > {
6794 > markdownEnumDescriptions: [
6795 > nls.localize('wordWrap.off', "Lines will never wrap."),
6796 > nls.localize('wordWrap.on', "Lines will wrap at the viewport width."),
6797 > nls.localize({
6798 > key: 'wordWrap.wordWrapColumn',
6799 > comment: [
6800 > '- `editor.wordWrapColumn` refers to a different setting and should not be localized.'
6801 > ]
6802 > }, "Lines will wrap at `#editor.wordWrapColumn#`."),
6803 > nls.localize({
6804 > key: 'wordWrap.bounded',
6805 > comment: [
6806 > '- viewport means the edge of the visible window size.',
6807 > '- `editor.wordWrapColumn` refers to a different setting and should not be localized.'
6808 > ]
6809 > }, "Lines will wrap at the minimum of viewport and `#editor.wordWrapColumn#`."),
6810 > ],
6811 > description: nls.localize({
6812 > key: 'wordWrap',
6813 > comment: [
6814 > '- \'off\', \'on\', \'wordWrapColumn\' and \'bounded\' refer to values the setting can take and should not be localized.',
6815 > '- `editor.wordWrapColumn` refers to a different setting and should not be localized.'
6816 > ]
6817 > }, "Controls how lines should wrap.")
6818 > }
6819 > )),
6820 > wordWrapBreakAfterCharacters: register(new EditorStringOption(
6821 > EditorOption.wordWrapBreakAfterCharacters, 'wordWrapBreakAfterCharacters',
6822 > // allow-any-unicode-next-line
6823 > ' \t})]?|/&.,;¢°′″‰℃、。。、¢,.:;?!%・・ゝゞヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻ァィゥェォャュョッー”〉》」』】〕)]}」',
6824 > )),
6825 > wordWrapBreakBeforeCharacters: register(new EditorStringOption(
6826 > EditorOption.wordWrapBreakBeforeCharacters, 'wordWrapBreakBeforeCharacters',
6827 > // allow-any-unicode-next-line
6828 > '([{‘“〈《「『【〔([{「£¥$£¥++'
6829 > )),
6830 > wordWrapColumn: register(new EditorIntOption(
6831 > EditorOption.wordWrapColumn, 'wordWrapColumn',
6832 > 80, 1, Constants.MAX_SAFE_SMALL_INTEGER,
6833 > {
6834 > markdownDescription: nls.localize({
6835 > key: 'wordWrapColumn',
6836 > comment: [
6837 > '- `editor.wordWrap` refers to a different setting and should not be localized.',
6838 > '- \'wordWrapColumn\' and \'bounded\' refer to values the different setting can take and should not be localized.'
6839 > ]
6840 > }, "Controls the wrapping column of the editor when `#editor.wordWrap#` is `wordWrapColumn` or `bounded`.")
6841 > }
6842 > )),
6843 > wordWrapOverride1: register(new EditorStringEnumOption(
6844 > EditorOption.wordWrapOverride1, 'wordWrapOverride1',
6845 > 'inherit' as 'off' | 'on' | 'inherit',
6846 > ['off', 'on', 'inherit'] as const
6847 > )),
6848 > wordWrapOverride2: register(new EditorStringEnumOption(
6849 > EditorOption.wordWrapOverride2, 'wordWrapOverride2',
6850 > 'inherit' as 'off' | 'on' | 'inherit',
6851 > ['off', 'on', 'inherit'] as const
6852 > )),
6853 > wrapOnEscapedLineFeeds: register(new EditorBooleanOption(
6854 > EditorOption.wrapOnEscapedLineFeeds, 'wrapOnEscapedLineFeeds', false,
6855 > { markdownDescription: nls.localize('wrapOnEscapedLineFeeds', "Controls whether literal `\\n` shall trigger a wordWrap when `#editor.wordWrap#` is enabled.\n\nFor example:\n```c\nchar* str=\"hello\\nworld\"\n```\nwill be displayed as\n```c\nchar* str=\"hello\\n\n world\"\n```") }
6856 > )),
6857 >
6858 > // Leave these at the end (because they have dependencies!)
6859 > effectiveCursorStyle: register(new EffectiveCursorStyle()),
6860 > editorClassName: register(new EditorClassName()),
6861 > defaultColorDecorators: register(new EditorStringEnumOption(
6862 > EditorOption.defaultColorDecorators, 'defaultColorDecorators', 'auto' as 'auto' | 'always' | 'never',
6863 > ['auto', 'always', 'never'] as const,
6864 > {
6865 > enumDescriptions: [
6866 > nls.localize('editor.defaultColorDecorators.auto', "Show default color decorators only when no extension provides colors decorators."),
6867 > nls.localize('editor.defaultColorDecorators.always', "Always show default color decorators."),
6868 > nls.localize('editor.defaultColorDecorators.never', "Never show default color decorators."),
6869 > ],
6870 > description: nls.localize('defaultColorDecorators', "Controls whether inline color decorations should be shown using the default document color provider.")
6871 > }
6872 > )),
6873 > pixelRatio: register(new EditorPixelRatio()),
6874 > tabFocusMode: register(new EditorBooleanOption(EditorOption.tabFocusMode, 'tabFocusMode', false,
6875 > { markdownDescription: nls.localize('tabFocusMode', "Controls whether the editor receives tabs or defers them to the workbench for navigation.") }
6876 > )),
6877 > layoutInfo: register(new EditorLayoutInfoComputer()),
6878 > wrappingInfo: register(new EditorWrappingInfoComputer()),
6879 > wrappingIndent: register(new WrappingIndentOption()),
6880 > wrappingStrategy: register(new WrappingStrategy()),
6881 > effectiveEditContextEnabled: register(new EffectiveEditContextEnabled()),
6882 > effectiveAllowVariableFonts: register(new EffectiveAllowVariableFonts())
6883 > };
6884 >
6885 > type EditorOptionsType = typeof EditorOptions;
6886 > type FindEditorOptionsKeyById<T extends EditorOption> = { [K in keyof EditorOptionsType]: EditorOptionsType[K]['id'] extends T ? K : never }[keyof EditorOptionsType];
6887 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
6888 > type ComputedEditorOptionValue<T extends IEditorOption<any, any>> = T extends IEditorOption<any, infer R> ? R : never;
6889 > export type FindComputedEditorOptionValueById<T extends EditorOption> = NonNullable<ComputedEditorOptionValue<EditorOptionsType[FindEditorOptionsKeyById<T>]>>;
6890 >
6891 > export type MouseMiddleClickAction = 'default' | 'openLink' | 'ctrlLeftClick';
src/vs/editor/common/model.ts 1559 covered LOC · 10 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- model.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 { Event } from '../../base/common/event.js';
7 > import { IMarkdownString } from '../../base/common/htmlContent.js';
8 > import { IDisposable } from '../../base/common/lifecycle.js';
9 > import { equals } from '../../base/common/objects.js';
10 > import { ThemeColor } from '../../base/common/themables.js';
11 > import { URI } from '../../base/common/uri.js';
12 > import { ISingleEditOperation } from './core/editOperation.js';
13 > import { IPosition, Position } from './core/position.js';
14 > import { IRange, Range } from './core/range.js';
15 > import { Selection } from './core/selection.js';
16 > import { TextChange } from './core/textChange.js';
17 > import { WordCharacterClassifier } from './core/wordCharacterClassifier.js';
18 > import { IWordAtPosition } from './core/wordHelper.js';
19 > import { FormattingOptions } from './languages.js';
20 > import { ILanguageSelection } from './languages/language.js';
21 > import { IBracketPairsTextModelPart } from './textModelBracketPairs.js';
22 > import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent, IModelTokensChangedEvent, LineInjectedText, ModelFontChangedEvent, ModelLineHeightChangedEvent } from './textModelEvents.js';
23 > import { IModelContentChange } from './model/mirrorTextModel.js';
24 > import { IGuidesTextModelPart } from './textModelGuides.js';
25 > import { ITokenizationTextModelPart } from './tokenizationTextModelPart.js';
26 > import { UndoRedoGroup } from '../../platform/undoRedo/common/undoRedo.js';
27 > import { TokenArray } from './tokens/lineTokens.js';
28 > import { IEditorModel } from './editorCommon.js';
29 > import { TextModelEditSource } from './textModelEditSource.js';
30 > import { TextEdit } from './core/edits/textEdit.js';
31 > import { IViewModel } from './viewModel.js';
32 >
33 > /**
34 > * Vertical Lane in the overview ruler of the editor.
35 > */
36 > export enum OverviewRulerLane {
37 > Left = 1,
38 > Center = 2,
39 > Right = 4,
40 > Full = 7
41 > }
42 >
43 > /**
44 > * Vertical Lane in the glyph margin of the editor.
45 > */
46 > export enum GlyphMarginLane {
47 > Left = 1,
48 > Center = 2,
49 > Right = 3,
50 > }
51 >
52 > export interface IGlyphMarginLanesModel {
53 > /**
54 > * The number of lanes that should be rendered in the editor.
55 > */
56 > readonly requiredLanes: number;
57 >
58 > /**
59 > * Gets the lanes that should be rendered starting at a given line number.
60 > */
61 > getLanesAtLine(lineNumber: number): GlyphMarginLane[];
62 >
63 > /**
64 > * Resets the model and ensures it can contain at least `maxLine` lines.
65 > */
66 > reset(maxLine: number): void;
67 >
68 > /**
69 > * Registers that a lane should be visible at the Range in the model.
70 > * @param persist - if true, notes that the lane should always be visible,
71 > * even on lines where there's no specific request for that lane.
72 > */
73 > push(lane: GlyphMarginLane, range: Range, persist?: boolean): void;
74 > }
75 >
76 > /**
77 > * Position in the minimap to render the decoration.
78 > */
79 > export const enum MinimapPosition {
80 > Inline = 1,
81 > Gutter = 2
82 > }
83 >
84 > /**
85 > * Section header style.
86 > */
87 > export const enum MinimapSectionHeaderStyle {
88 > Normal = 1,
89 > Underlined = 2
90 > }
91 >
92 > export interface IDecorationOptions {
93 > /**
94 > * CSS color to render.
95 > * e.g.: rgba(100, 100, 100, 0.5) or a color from the color registry
96 > */
97 > color: string | ThemeColor | undefined;
98 > /**
99 > * CSS color to render.
100 > * e.g.: rgba(100, 100, 100, 0.5) or a color from the color registry
101 > */
102 > darkColor?: string | ThemeColor;
103 > }
104 >
105 > export interface IModelDecorationGlyphMarginOptions {
106 > /**
107 > * The position in the glyph margin.
108 > */
109 > position: GlyphMarginLane;
110 >
111 > /**
112 > * Whether the glyph margin lane in {@link position} should be rendered even
113 > * outside of this decoration's range.
114 > */
115 > persistLane?: boolean;
116 > }
117 >
118 > /**
119 > * Options for rendering a model decoration in the overview ruler.
120 > */
121 > export interface IModelDecorationOverviewRulerOptions extends IDecorationOptions {
122 > /**
123 > * The position in the overview ruler.
124 > */
125 > position: OverviewRulerLane;
126 > }
127 >
128 > /**
129 > * Options for rendering a model decoration in the minimap.
130 > */
131 > export interface IModelDecorationMinimapOptions extends IDecorationOptions {
132 > /**
133 > * The position in the minimap.
134 > */
135 > position: MinimapPosition;
136 > /**
137 > * If the decoration is for a section header, which header style.
138 > */
139 > sectionHeaderStyle?: MinimapSectionHeaderStyle | null;
140 > /**
141 > * If the decoration is for a section header, the header text.
142 > */
143 > sectionHeaderText?: string | null;
144 > }
145 >
146 > /**
147 > * Options for a model decoration.
148 > */
149 > export interface IModelDecorationOptions {
150 > /**
151 > * A debug description that can be used for inspecting model decorations.
152 > * @internal
153 > */
154 > description: string;
155 > /**
156 > * Customize the growing behavior of the decoration when typing at the edges of the decoration.
157 > * Defaults to TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges
158 > */
159 > stickiness?: TrackedRangeStickiness;
160 > /**
161 > * CSS class name describing the decoration.
162 > */
163 > className?: string | null;
164 > /**
165 > * Indicates whether the decoration should span across the entire line when it continues onto the next line.
166 > */
167 > shouldFillLineOnLineBreak?: boolean | null;
168 > blockClassName?: string | null;
169 > /**
170 > * Indicates if this block should be rendered after the last line.
171 > * In this case, the range must be empty and set to the last line.
172 > */
173 > blockIsAfterEnd?: boolean | null;
174 > blockDoesNotCollapse?: boolean | null;
175 > blockPadding?: [top: number, right: number, bottom: number, left: number] | null;
176 >
177 > /**
178 > * Message to be rendered when hovering over the glyph margin decoration.
179 > */
180 > glyphMarginHoverMessage?: IMarkdownString | IMarkdownString[] | null;
181 > /**
182 > * Array of MarkdownString to render as the decoration message.
183 > */
184 > hoverMessage?: IMarkdownString | IMarkdownString[] | null;
185 > /**
186 > * Array of MarkdownString to render as the line number message.
187 > */
188 > lineNumberHoverMessage?: IMarkdownString | IMarkdownString[] | null;
189 > /**
190 > * Should the decoration expand to encompass a whole line.
191 > */
192 > isWholeLine?: boolean;
193 > /**
194 > * Always render the decoration (even when the range it encompasses is collapsed).
195 > */
196 > showIfCollapsed?: boolean;
197 > /**
198 > * Collapse the decoration if its entire range is being replaced via an edit.
199 > * @internal
200 > */
201 > collapseOnReplaceEdit?: boolean;
202 > /**
203 > * Specifies the stack order of a decoration.
204 > * A decoration with greater stack order is always in front of a decoration with
205 > * a lower stack order when the decorations are on the same line.
206 > */
207 > zIndex?: number;
208 > /**
209 > * If set, render this decoration in the overview ruler.
210 > */
211 > overviewRuler?: IModelDecorationOverviewRulerOptions | null;
212 > /**
213 > * If set, render this decoration in the minimap.
214 > */
215 > minimap?: IModelDecorationMinimapOptions | null;
216 > /**
217 > * If set, the decoration will be rendered in the glyph margin with this CSS class name.
218 > */
219 > glyphMarginClassName?: string | null;
220 > /**
221 > * If set and the decoration has {@link glyphMarginClassName} set, render this decoration
222 > * with the specified {@link IModelDecorationGlyphMarginOptions} in the glyph margin.
223 > */
224 > glyphMargin?: IModelDecorationGlyphMarginOptions | null;
225 > /**
226 > * If set, the decoration will override the line height of the lines it spans. This value is a multiplier to the default line height.
227 > */
228 > lineHeight?: number | null;
229 > /**
230 > * Font family
231 > */
232 > fontFamily?: string | null;
233 > /**
234 > * Font size
235 > */
236 > fontSize?: string | null;
237 > /**
238 > * Font weight
239 > */
240 > fontWeight?: string | null;
241 > /**
242 > * Font style
243 > */
244 > fontStyle?: string | null;
245 > /**
246 > * If set, the decoration will be rendered in the lines decorations with this CSS class name.
247 > */
248 > linesDecorationsClassName?: string | null;
249 > /**
250 > * Controls the tooltip text of the line decoration.
251 > */
252 > linesDecorationsTooltip?: string | null;
253 > /**
254 > * If set, the decoration will be rendered on the line number.
255 > */
256 > lineNumberClassName?: string | null;
257 > /**
258 > * If set, the decoration will be rendered in the lines decorations with this CSS class name, but only for the first line in case of line wrapping.
259 > */
260 > firstLineDecorationClassName?: string | null;
261 > /**
262 > * If set, the decoration will be rendered in the margin (covering its full width) with this CSS class name.
263 > */
264 > marginClassName?: string | null;
265 > /**
266 > * If set, the decoration will be rendered inline with the text with this CSS class name.
267 > * Please use this only for CSS rules that must impact the text. For example, use `className`
268 > * to have a background color decoration.
269 > */
270 > inlineClassName?: string | null;
271 > /**
272 > * If there is an `inlineClassName` which affects letter spacing.
273 > */
274 > inlineClassNameAffectsLetterSpacing?: boolean;
275 > /**
276 > * If set, the decoration will be rendered before the text with this CSS class name.
277 > */
278 > beforeContentClassName?: string | null;
279 > /**
280 > * If set, the decoration will be rendered after the text with this CSS class name.
281 > */
282 > afterContentClassName?: string | null;
283 > /**
284 > * If set, text will be injected in the view after the range.
285 > */
286 > after?: InjectedTextOptions | null;
287 >
288 > /**
289 > * If set, text will be injected in the view before the range.
290 > */
291 > before?: InjectedTextOptions | null;
292 >
293 > /**
294 > * If set, this decoration will not be rendered for comment tokens.
295 > * @internal
296 > */
297 > hideInCommentTokens?: boolean | null;
298 >
299 > /**
300 > * If set, this decoration will not be rendered for string tokens.
301 > * @internal
302 > */
303 > hideInStringTokens?: boolean | null;
304 >
305 > /**
306 > * Whether the decoration affects the font.
307 > * @internal
308 > */
309 > affectsFont?: boolean | null;
310 >
311 > /**
312 > * The text direction of the decoration.
313 > */
314 > textDirection?: TextDirection | null;
315 > }
316 >
317 > /**
318 > * Text Direction for a decoration.
319 > */
320 > export enum TextDirection {
321 > LTR = 0,
322 >
323 > RTL = 1,
324 > }
325 >
326 > /**
327 > * Configures text that is injected into the view without changing the underlying document.
328 > */
329 > export interface InjectedTextOptions {
330 > /**
331 > * Sets the text to inject. Must be a single line.
332 > */
333 > readonly content: string;
334 >
335 > /**
336 > * @internal
337 > */
338 > readonly tokens?: TokenArray | null;
339 >
340 > /**
341 > * If set, the decoration will be rendered inline with the text with this CSS class name.
342 > */
343 > readonly inlineClassName?: string | null;
344 >
345 > /**
346 > * If there is an `inlineClassName` which affects letter spacing.
347 > */
348 > readonly inlineClassNameAffectsLetterSpacing?: boolean;
349 >
350 > /**
351 > * This field allows to attach data to this injected text.
352 > * The data can be read when injected texts at a given position are queried.
353 > */
354 > readonly attachedData?: unknown;
355 >
356 > /**
357 > * Configures cursor stops around injected text.
358 > * Defaults to {@link InjectedTextCursorStops.Both}.
359 > */
360 > readonly cursorStops?: InjectedTextCursorStops | null;
361 > }
362 >
363 > export enum InjectedTextCursorStops {
364 > Both,
365 > Right,
366 > Left,
367 > None
368 > }
369 >
370 > /**
371 > * New model decorations.
372 > */
373 > export interface IModelDeltaDecoration {
374 > /**
375 > * Range that this decoration covers.
376 > */
377 > range: IRange;
378 > /**
379 > * Options associated with this decoration.
380 > */
381 > options: IModelDecorationOptions;
382 > }
383 >
384 > /**
385 > * A decoration in the model.
386 > */
387 > export interface IModelDecoration {
388 > /**
389 > * Identifier for a decoration.
390 > */
391 > readonly id: string;
392 > /**
393 > * Identifier for a decoration's owner.
394 > */
395 > readonly ownerId: number;
396 > /**
397 > * Range that this decoration covers.
398 > */
399 > readonly range: Range;
400 > /**
401 > * Options associated with this decoration.
402 > */
403 > readonly options: IModelDecorationOptions;
404 > }
405 >
406 > /**
407 > * An accessor that can add, change or remove model decorations.
408 > * @internal
409 > */
410 > export interface IModelDecorationsChangeAccessor {
411 > /**
412 > * Add a new decoration.
413 > * @param range Range that this decoration covers.
414 > * @param options Options associated with this decoration.
415 > * @return An unique identifier associated with this decoration.
416 > */
417 > addDecoration(range: IRange, options: IModelDecorationOptions): string;
418 > /**
419 > * Change the range that an existing decoration covers.
420 > * @param id The unique identifier associated with the decoration.
421 > * @param newRange The new range that this decoration covers.
422 > */
423 > changeDecoration(id: string, newRange: IRange): void;
424 > /**
425 > * Change the options associated with an existing decoration.
426 > * @param id The unique identifier associated with the decoration.
427 > * @param newOptions The new options associated with this decoration.
428 > */
429 > changeDecorationOptions(id: string, newOptions: IModelDecorationOptions): void;
430 > /**
431 > * Remove an existing decoration.
432 > * @param id The unique identifier associated with the decoration.
433 > */
434 > removeDecoration(id: string): void;
435 > /**
436 > * Perform a minimum amount of operations, in order to transform the decorations
437 > * identified by `oldDecorations` to the decorations described by `newDecorations`
438 > * and returns the new identifiers associated with the resulting decorations.
439 > *
440 > * @param oldDecorations Array containing previous decorations identifiers.
441 > * @param newDecorations Array describing what decorations should result after the call.
442 > * @return An array containing the new decorations identifiers.
443 > */
444 > deltaDecorations(oldDecorations: readonly string[], newDecorations: readonly IModelDeltaDecoration[]): string[];
445 > }
446 >
447 > /**
448 > * End of line character preference.
449 > */
450 > export const enum EndOfLinePreference {
451 > /**
452 > * Use the end of line character identified in the text buffer.
453 > */
454 > TextDefined = 0,
455 > /**
456 > * Use line feed (\n) as the end of line character.
457 > */
458 > LF = 1,
459 > /**
460 > * Use carriage return and line feed (\r\n) as the end of line character.
461 > */
462 > CRLF = 2
463 > }
464 >
465 > /**
466 > * The default end of line to use when instantiating models.
467 > */
468 > export const enum DefaultEndOfLine {
469 > /**
470 > * Use line feed (\n) as the end of line character.
471 > */
472 > LF = 1,
473 > /**
474 > * Use carriage return and line feed (\r\n) as the end of line character.
475 > */
476 > CRLF = 2
477 > }
478 >
479 > /**
480 > * End of line character preference.
481 > */
482 > export const enum EndOfLineSequence {
483 > /**
484 > * Use line feed (\n) as the end of line character.
485 > */
486 > LF = 0,
487 > /**
488 > * Use carriage return and line feed (\r\n) as the end of line character.
489 > */
490 > CRLF = 1
491 > }
492 >
493 > /**
494 > * An identifier for a single edit operation.
495 > * @internal
496 > */
497 > export interface ISingleEditOperationIdentifier {
498 > /**
499 > * Identifier major
500 > */
501 > major: number;
502 > /**
503 > * Identifier minor
504 > */
505 > minor: number;
506 > }
507 >
508 > /**
509 > * A single edit operation, that has an identifier.
510 > */
511 > export interface IIdentifiedSingleEditOperation extends ISingleEditOperation {
512 > /**
513 > * An identifier associated with this single edit operation.
514 > * @internal
515 > */
516 > identifier?: ISingleEditOperationIdentifier | null;
517 > /**
518 > * This indicates that this operation is inserting automatic whitespace
519 > * that can be removed on next model edit operation if `config.trimAutoWhitespace` is true.
520 > * @internal
521 > */
522 > isAutoWhitespaceEdit?: boolean;
523 > /**
524 > * This indicates that this operation is in a set of operations that are tracked and should not be "simplified".
525 > * @internal
526 > */
527 > _isTracked?: boolean;
528 > }
529 >
530 > export interface IValidEditOperation {
531 > /**
532 > * An identifier associated with this single edit operation.
533 > * @internal
534 > */
535 > identifier: ISingleEditOperationIdentifier | null;
536 > /**
537 > * The range to replace. This can be empty to emulate a simple insert.
538 > */
539 > range: Range;
540 > /**
541 > * The text to replace with. This can be empty to emulate a simple delete.
542 > */
543 > text: string;
544 > /**
545 > * @internal
546 > */
547 > textChange: TextChange;
548 > }
549 >
550 > /**
551 > * A callback that can compute the cursor state after applying a series of edit operations.
552 > */
553 > export interface ICursorStateComputer {
554 > /**
555 > * A callback that can compute the resulting cursors state after some edit operations have been executed.
556 > */
557 > (inverseEditOperations: IValidEditOperation[]): Selection[] | null;
558 > }
559 >
560 > export class TextModelResolvedOptions {
561 > _textModelResolvedOptionsBrand: void = undefined;
562 >
563 > readonly tabSize: number;
564 > readonly indentSize: number;
565 > private readonly _indentSizeIsTabSize: boolean;
566 > readonly insertSpaces: boolean;
567 > readonly defaultEOL: DefaultEndOfLine;
568 > readonly trimAutoWhitespace: boolean;
569 > readonly bracketPairColorizationOptions: BracketPairColorizationOptions;
570 >
571 > public get originalIndentSize(): number | 'tabSize' {
572 > return this._indentSizeIsTabSize ? 'tabSize' : this.indentSize;
573 > }
574 >
575 > /**
576 > * @internal
577 > */
578 > constructor(src: {
579 tabSize: number;
580 indentSize: number | 'tabSize';
597 this.bracketPairColorizationOptions = src.bracketPairColorizationOptions;
598 }
599 > model.ts
600 > /**
601 > * @internal
602 > */
603 > public equals(other: TextModelResolvedOptions): boolean {
604 return (
605 this.tabSize === other.tabSize
612 );
613 }
614 > model.ts
615 > /**
616 > * @internal
617 > */
618 > public createChangeEvent(newOpts: TextModelResolvedOptions): IModelOptionsChangedEvent {
619 return {
620 tabSize: this.tabSize !== newOpts.tabSize,
624 };
625 }
626 > } model.ts
627 >
628 > /**
629 > * @internal
630 > */
631 > export interface ITextModelCreationOptions {
632 > tabSize: number;
633 > indentSize: number | 'tabSize';
634 > insertSpaces: boolean;
635 > detectIndentation: boolean;
636 > trimAutoWhitespace: boolean;
637 > defaultEOL: DefaultEndOfLine;
638 > isForSimpleWidget: boolean;
639 > largeFileOptimizations: boolean;
640 > bracketPairColorizationOptions: BracketPairColorizationOptions;
641 > }
642 >
643 > export interface BracketPairColorizationOptions {
644 > enabled: boolean;
645 > independentColorPoolPerBracketType: boolean;
646 > }
647 >
648 > export interface ITextModelUpdateOptions {
649 > tabSize?: number;
650 > indentSize?: number | 'tabSize';
651 > insertSpaces?: boolean;
652 > trimAutoWhitespace?: boolean;
653 > bracketColorizationOptions?: BracketPairColorizationOptions;
654 > }
655 >
656 > export class FindMatch {
657 > _findMatchBrand: void = undefined;
658 >
659 > public readonly range: Range;
660 > public readonly matches: string[] | null;
661 >
662 > /**
663 > * @internal
664 > */
665 > constructor(range: Range, matches: string[] | null) {
666 this.range = range;
667 this.matches = matches;
668 }
669 > } model.ts
670 >
671 > /**
672 > * Describes the behavior of decorations when typing/editing near their edges.
673 > * Note: Please do not edit the values, as they very carefully match `DecorationRangeBehavior`
674 > */
675 > export const enum TrackedRangeStickiness {
676 > AlwaysGrowsWhenTypingAtEdges = 0,
677 > NeverGrowsWhenTypingAtEdges = 1,
678 > GrowsOnlyWhenTypingBefore = 2,
679 > GrowsOnlyWhenTypingAfter = 3,
680 > }
681 >
682 > /**
683 > * Text snapshot that works like an iterator.
684 > * Will try to return chunks of roughly ~64KB size.
685 > * Will return null when finished.
686 > */
687 > export interface ITextSnapshot {
688 > read(): string | null;
689 > }
690 >
691 > /**
692 > * @internal
693 > */
694 > export function isITextSnapshot(obj: unknown): obj is ITextSnapshot {
695 return (!!obj && typeof (obj as ITextSnapshot).read === 'function');
696 }
697 > model.ts
698 > /**
699 > * A model.
700 > */
701 > export interface ITextModel {
702 >
703 > /**
704 > * Gets the resource associated with this editor model.
705 > */
706 > readonly uri: URI;
707 >
708 > /**
709 > * A unique identifier associated with this model.
710 > */
711 > readonly id: string;
712 >
713 > /**
714 > * This model is constructed for a simple widget code editor.
715 > * @internal
716 > */
717 > readonly isForSimpleWidget: boolean;
718 >
719 > /**
720 > * Method to register a view model on a model
721 > * @internal
722 > */
723 > registerViewModel(viewModel: IViewModel): void;
724 >
725 > /**
726 > * Method which unregister a view model on a model
727 > * @internal
728 > */
729 > unregisterViewModel(viewModel: IViewModel): void;
730 >
731 > /**
732 > * If true, the text model might contain RTL.
733 > * If false, the text model **contains only** contain LTR.
734 > * @internal
735 > */
736 > mightContainRTL(): boolean;
737 >
738 > /**
739 > * If true, the text model might contain LINE SEPARATOR (LS), PARAGRAPH SEPARATOR (PS).
740 > * If false, the text model definitely does not contain these.
741 > * @internal
742 > */
743 > mightContainUnusualLineTerminators(): boolean;
744 >
745 > /**
746 > * @internal
747 > */
748 > removeUnusualLineTerminators(selections?: Selection[]): void;
749 >
750 > /**
751 > * If true, the text model might contain non basic ASCII.
752 > * If false, the text model **contains only** basic ASCII.
753 > * @internal
754 > */
755 > mightContainNonBasicASCII(): boolean;
756 >
757 > /**
758 > * Get the resolved options for this model.
759 > */
760 > getOptions(): TextModelResolvedOptions;
761 >
762 > /**
763 > * Get the formatting options for this model.
764 > * @internal
765 > */
766 > getFormattingOptions(): FormattingOptions;
767 >
768 > /**
769 > * Get the current version id of the model.
770 > * Anytime a change happens to the model (even undo/redo),
771 > * the version id is incremented.
772 > */
773 > getVersionId(): number;
774 >
775 > /**
776 > * Get the alternative version id of the model.
777 > * This alternative version id is not always incremented,
778 > * it will return the same values in the case of undo-redo.
779 > */
780 > getAlternativeVersionId(): number;
781 >
782 > /**
783 > * Replace the entire text buffer value contained in this model.
784 > */
785 > setValue(newValue: string | ITextSnapshot): void;
786 >
787 > /**
788 > * Get the text stored in this model.
789 > * @param eol The end of line character preference. Defaults to `EndOfLinePreference.TextDefined`.
790 > * @param preserverBOM Preserve a BOM character if it was detected when the model was constructed.
791 > * @return The text.
792 > */
793 > getValue(eol?: EndOfLinePreference, preserveBOM?: boolean): string;
794 >
795 > /**
796 > * Get the text stored in this model.
797 > * @param preserverBOM Preserve a BOM character if it was detected when the model was constructed.
798 > * @return The text snapshot (it is safe to consume it asynchronously).
799 > */
800 > createSnapshot(preserveBOM?: boolean): ITextSnapshot;
801 >
802 > /**
803 > * Get the length of the text stored in this model.
804 > */
805 > getValueLength(eol?: EndOfLinePreference, preserveBOM?: boolean): number;
806 >
807 > /**
808 > * Check if the raw text stored in this model equals another raw text.
809 > * @internal
810 > */
811 > equalsTextBuffer(other: ITextBuffer): boolean;
812 >
813 > /**
814 > * Get the underling text buffer.
815 > * @internal
816 > */
817 > getTextBuffer(): ITextBuffer;
818 >
819 > /**
820 > * Get the text in a certain range.
821 > * @param range The range describing what text to get.
822 > * @param eol The end of line character preference. This will only be used for multiline ranges. Defaults to `EndOfLinePreference.TextDefined`.
823 > * @return The text.
824 > */
825 > getValueInRange(range: IRange, eol?: EndOfLinePreference): string;
826 >
827 > /**
828 > * Get the length of text in a certain range.
829 > * @param range The range describing what text length to get.
830 > * @return The text length.
831 > */
832 > getValueLengthInRange(range: IRange, eol?: EndOfLinePreference): number;
833 >
834 > /**
835 > * Get the character count of text in a certain range.
836 > * @param range The range describing what text length to get.
837 > */
838 > getCharacterCountInRange(range: IRange, eol?: EndOfLinePreference): number;
839 >
840 > /**
841 > * Splits characters in two buckets. First bucket (A) is of characters that
842 > * sit in lines with length < `LONG_LINE_BOUNDARY`. Second bucket (B) is of
843 > * characters that sit in lines with length >= `LONG_LINE_BOUNDARY`.
844 > * If count(B) > count(A) return true. Returns false otherwise.
845 > * @internal
846 > */
847 > isDominatedByLongLines(): boolean;
848 >
849 > /**
850 > * Get the number of lines in the model.
851 > */
852 > getLineCount(): number;
853 >
854 > /**
855 > * Get the text for a certain line.
856 > */
857 > getLineContent(lineNumber: number): string;
858 >
859 > /**
860 > * Get the line injected text for a certain line.
861 > * @internal
862 > */
863 > getLineInjectedText(lineNumber: number, ownerId?: number): LineInjectedText[];
864 >
865 > /**
866 > * Get the text length for a certain line.
867 > */
868 > getLineLength(lineNumber: number): number;
869 >
870 > /**
871 > * Get the text for all lines.
872 > */
873 > getLinesContent(): string[];
874 >
875 > /**
876 > * Get the end of line sequence predominantly used in the text buffer.
877 > * @return EOL char sequence (e.g.: '\n' or '\r\n').
878 > */
879 > getEOL(): string;
880 >
881 > /**
882 > * Get the end of line sequence predominantly used in the text buffer.
883 > */
884 > getEndOfLineSequence(): EndOfLineSequence;
885 >
886 > /**
887 > * Get the minimum legal column for line at `lineNumber`
888 > */
889 > getLineMinColumn(lineNumber: number): number;
890 >
891 > /**
892 > * Get the maximum legal column for line at `lineNumber`
893 > */
894 > getLineMaxColumn(lineNumber: number): number;
895 >
896 > /**
897 > * Returns the column before the first non whitespace character for line at `lineNumber`.
898 > * Returns 0 if line is empty or contains only whitespace.
899 > */
900 > getLineFirstNonWhitespaceColumn(lineNumber: number): number;
901 >
902 > /**
903 > * Returns the column after the last non whitespace character for line at `lineNumber`.
904 > * Returns 0 if line is empty or contains only whitespace.
905 > */
906 > getLineLastNonWhitespaceColumn(lineNumber: number): number;
907 >
908 > /**
909 > * Create a valid position.
910 > */
911 > validatePosition(position: IPosition): Position;
912 >
913 > /**
914 > * Advances the given position by the given offset (negative offsets are also accepted)
915 > * and returns it as a new valid position.
916 > *
917 > * If the offset and position are such that their combination goes beyond the beginning or
918 > * end of the model, throws an exception.
919 > *
920 > * If the offset is such that the new position would be in the middle of a multi-byte
921 > * line terminator, throws an exception.
922 > */
923 > modifyPosition(position: IPosition, offset: number): Position;
924 >
925 > /**
926 > * Create a valid range.
927 > */
928 > validateRange(range: IRange): Range;
929 >
930 > /**
931 > * Verifies the range is valid.
932 > */
933 > isValidRange(range: IRange): boolean;
934 >
935 > /**
936 > * Converts the position to a zero-based offset.
937 > *
938 > * The position will be [adjusted](#TextDocument.validatePosition).
939 > *
940 > * @param position A position.
941 > * @return A valid zero-based offset.
942 > */
943 > getOffsetAt(position: IPosition): number;
944 >
945 > /**
946 > * Converts a zero-based offset to a position.
947 > *
948 > * @param offset A zero-based offset.
949 > * @return A valid [position](#Position).
950 > */
951 > getPositionAt(offset: number): Position;
952 >
953 > /**
954 > * Get a range covering the entire model.
955 > */
956 > getFullModelRange(): Range;
957 >
958 > /**
959 > * Returns if the model was disposed or not.
960 > */
961 > isDisposed(): boolean;
962 >
963 > /**
964 > * This model is so large that it would not be a good idea to sync it over
965 > * to web workers or other places.
966 > * @internal
967 > */
968 > isTooLargeForSyncing(): boolean;
969 >
970 > /**
971 > * The file is so large, that even tokenization is disabled.
972 > * @internal
973 > */
974 > isTooLargeForTokenization(): boolean;
975 >
976 > /**
977 > * The file is so large, that operations on it might be too large for heap
978 > * and can lead to OOM crashes so they should be disabled.
979 > * @internal
980 > */
981 > isTooLargeForHeapOperation(): boolean;
982 >
983 > /**
984 > * Search the model.
985 > * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.
986 > * @param searchOnlyEditableRange Limit the searching to only search inside the editable range of the model.
987 > * @param isRegex Used to indicate that `searchString` is a regular expression.
988 > * @param matchCase Force the matching to match lower/upper case exactly.
989 > * @param wordSeparators Force the matching to match entire words only. Pass null otherwise.
990 > * @param captureMatches The result will contain the captured groups.
991 > * @param limitResultCount Limit the number of results
992 > * @return The ranges where the matches are. It is empty if not matches have been found.
993 > */
994 > findMatches(searchString: string, searchOnlyEditableRange: boolean, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean, limitResultCount?: number): FindMatch[];
995 > /**
996 > * Search the model.
997 > * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.
998 > * @param searchScope Limit the searching to only search inside these ranges.
999 > * @param isRegex Used to indicate that `searchString` is a regular expression.
1000 > * @param matchCase Force the matching to match lower/upper case exactly.
1001 > * @param wordSeparators Force the matching to match entire words only. Pass null otherwise.
1002 > * @param captureMatches The result will contain the captured groups.
1003 > * @param limitResultCount Limit the number of results
1004 > * @return The ranges where the matches are. It is empty if no matches have been found.
1005 > */
1006 > findMatches(searchString: string, searchScope: IRange | IRange[], isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean, limitResultCount?: number): FindMatch[];
1007 > /**
1008 > * Search the model for the next match. Loops to the beginning of the model if needed.
1009 > * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.
1010 > * @param searchStart Start the searching at the specified position.
1011 > * @param isRegex Used to indicate that `searchString` is a regular expression.
1012 > * @param matchCase Force the matching to match lower/upper case exactly.
1013 > * @param wordSeparators Force the matching to match entire words only. Pass null otherwise.
1014 > * @param captureMatches The result will contain the captured groups.
1015 > * @return The range where the next match is. It is null if no next match has been found.
1016 > */
1017 > findNextMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean): FindMatch | null;
1018 > /**
1019 > * Search the model for the previous match. Loops to the end of the model if needed.
1020 > * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.
1021 > * @param searchStart Start the searching at the specified position.
1022 > * @param isRegex Used to indicate that `searchString` is a regular expression.
1023 > * @param matchCase Force the matching to match lower/upper case exactly.
1024 > * @param wordSeparators Force the matching to match entire words only. Pass null otherwise.
1025 > * @param captureMatches The result will contain the captured groups.
1026 > * @return The range where the previous match is. It is null if no previous match has been found.
1027 > */
1028 > findPreviousMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean): FindMatch | null;
1029 >
1030 >
1031 > /**
1032 > * Get the language associated with this model.
1033 > */
1034 > getLanguageId(): string;
1035 >
1036 > /**
1037 > * Set the current language mode associated with the model.
1038 > * @param languageId The new language.
1039 > * @param source The source of the call that set the language.
1040 > * @internal
1041 > */
1042 > setLanguage(languageId: string, source?: string): void;
1043 >
1044 > /**
1045 > * Set the current language mode associated with the model.
1046 > * @param languageSelection The new language selection.
1047 > * @param source The source of the call that set the language.
1048 > * @internal
1049 > */
1050 > setLanguage(languageSelection: ILanguageSelection, source?: string): void;
1051 >
1052 > /**
1053 > * Returns the real (inner-most) language mode at a given position.
1054 > * The result might be inaccurate. Use `forceTokenization` to ensure accurate tokens.
1055 > * @internal
1056 > */
1057 > getLanguageIdAtPosition(lineNumber: number, column: number): string;
1058 >
1059 > /**
1060 > * Get the word under or besides `position`.
1061 > * @param position The position to look for a word.
1062 > * @return The word under or besides `position`. Might be null.
1063 > */
1064 > getWordAtPosition(position: IPosition): IWordAtPosition | null;
1065 >
1066 > /**
1067 > * Get the word under or besides `position` trimmed to `position`.column
1068 > * @param position The position to look for a word.
1069 > * @return The word under or besides `position`. Will never be null.
1070 > */
1071 > getWordUntilPosition(position: IPosition): IWordAtPosition;
1072 >
1073 > /**
1074 > * Change the decorations. The callback will be called with a change accessor
1075 > * that becomes invalid as soon as the callback finishes executing.
1076 > * This allows for all events to be queued up until the change
1077 > * is completed. Returns whatever the callback returns.
1078 > * @param ownerId Identifies the editor id in which these decorations should appear. If no `ownerId` is provided, the decorations will appear in all editors that attach this model.
1079 > * @internal
1080 > */
1081 > changeDecorations<T>(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T, ownerId?: number): T | null;
1082 >
1083 > /**
1084 > * Perform a minimum amount of operations, in order to transform the decorations
1085 > * identified by `oldDecorations` to the decorations described by `newDecorations`
1086 > * and returns the new identifiers associated with the resulting decorations.
1087 > *
1088 > * @param oldDecorations Array containing previous decorations identifiers.
1089 > * @param newDecorations Array describing what decorations should result after the call.
1090 > * @param ownerId Identifies the editor id in which these decorations should appear. If no `ownerId` is provided, the decorations will appear in all editors that attach this model.
1091 > * @return An array containing the new decorations identifiers.
1092 > */
1093 > deltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[], ownerId?: number): string[];
1094 >
1095 > /**
1096 > * Remove all decorations that have been added with this specific ownerId.
1097 > * @param ownerId The owner id to search for.
1098 > * @internal
1099 > */
1100 > removeAllDecorationsWithOwnerId(ownerId: number): void;
1101 >
1102 > /**
1103 > * Get the options associated with a decoration.
1104 > * @param id The decoration id.
1105 > * @return The decoration options or null if the decoration was not found.
1106 > */
1107 > getDecorationOptions(id: string): IModelDecorationOptions | null;
1108 >
1109 > /**
1110 > * Get the range associated with a decoration.
1111 > * @param id The decoration id.
1112 > * @return The decoration range or null if the decoration was not found.
1113 > */
1114 > getDecorationRange(id: string): Range | null;
1115 >
1116 > /**
1117 > * Gets all the decorations for the line `lineNumber` as an array.
1118 > * @param lineNumber The line number
1119 > * @param ownerId If set, it will ignore decorations belonging to other owners.
1120 > * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors).
1121 > * @param filterFontDecorations If set, it will ignore font decorations.
1122 > * @return An array with the decorations
1123 > */
1124 > getLineDecorations(lineNumber: number, ownerId?: number, filterOutValidation?: boolean, filterFontDecorations?: boolean): IModelDecoration[];
1125 >
1126 > /**
1127 > * Gets all the font decorations for the line `lineNumber` as an array.
1128 > * @param ownerId If set, it will ignore decorations belonging to other owners.
1129 > * @internal
1130 > */
1131 > getFontDecorationsInRange(range: IRange, ownerId?: number): IModelDecoration[];
1132 >
1133 > /**
1134 > * Gets all the decorations for the lines between `startLineNumber` and `endLineNumber` as an array.
1135 > * @param startLineNumber The start line number
1136 > * @param endLineNumber The end line number
1137 > * @param ownerId If set, it will ignore decorations belonging to other owners.
1138 > * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors).
1139 > * @param filterFontDecorations If set, it will ignore font decorations.
1140 > * @return An array with the decorations
1141 > */
1142 > getLinesDecorations(startLineNumber: number, endLineNumber: number, ownerId?: number, filterOutValidation?: boolean, filterFontDecorations?: boolean): IModelDecoration[];
1143 >
1144 > /**
1145 > * Gets all the decorations in a range as an array. Only `startLineNumber` and `endLineNumber` from `range` are used for filtering.
1146 > * So for now it returns all the decorations on the same line as `range`.
1147 > * @param range The range to search in
1148 > * @param ownerId If set, it will ignore decorations belonging to other owners.
1149 > * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors).
1150 > * @param filterFontDecorations If set, it will ignore font decorations.
1151 > * @param onlyMinimapDecorations If set, it will return only decorations that render in the minimap.
1152 > * @param onlyMarginDecorations If set, it will return only decorations that render in the glyph margin.
1153 > * @return An array with the decorations
1154 > */
1155 > getDecorationsInRange(range: IRange, ownerId?: number, filterOutValidation?: boolean, filterFontDecorations?: boolean, onlyMinimapDecorations?: boolean, onlyMarginDecorations?: boolean): IModelDecoration[];
1156 >
1157 > /**
1158 > * Gets all the decorations as an array.
1159 > * @param ownerId If set, it will ignore decorations belonging to other owners.
1160 > * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors).
1161 > * @param filterFontDecorations If set, it will ignore font decorations.
1162 > */
1163 > getAllDecorations(ownerId?: number, filterOutValidation?: boolean, filterFontDecorations?: boolean): IModelDecoration[];
1164 >
1165 > /**
1166 > * Gets all decorations that render in the glyph margin as an array.
1167 > * @param ownerId If set, it will ignore decorations belonging to other owners.
1168 > */
1169 > getAllMarginDecorations(ownerId?: number): IModelDecoration[];
1170 >
1171 > /**
1172 > * Gets all the decorations that should be rendered in the overview ruler as an array.
1173 > * @param ownerId If set, it will ignore decorations belonging to other owners.
1174 > * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors).
1175 > * @param filterFontDecorations If set, it will ignore font decorations.
1176 > */
1177 > getOverviewRulerDecorations(ownerId?: number, filterOutValidation?: boolean, filterFontDecorations?: boolean): IModelDecoration[];
1178 >
1179 > /**
1180 > * Gets all the decorations that contain injected text.
1181 > * @param ownerId If set, it will ignore decorations belonging to other owners.
1182 > */
1183 > getInjectedTextDecorations(ownerId?: number): IModelDecoration[];
1184 >
1185 > /**
1186 > * Gets all the decorations that contain custom line heights.
1187 > * @param ownerId If set, it will ignore decorations belonging to other owners.
1188 > */
1189 > getCustomLineHeightsDecorations(ownerId?: number): IModelDecoration[];
1190 >
1191 > /**
1192 > * Gets all the decorations that contain custom line heights.
1193 > * @param range The range to search in
1194 > * @param ownerId If set, it will ignore decorations belonging to other owners.
1195 > */
1196 > getCustomLineHeightsDecorationsInRange(range: Range, ownerId?: number): IModelDecoration[];
1197 >
1198 > /**
1199 > * @internal
1200 > */
1201 > _getTrackedRange(id: string): Range | null;
1202 >
1203 > /**
1204 > * @internal
1205 > */
1206 > _setTrackedRange(id: string | null, newRange: null, newStickiness: TrackedRangeStickiness): null;
1207 > /**
1208 > * @internal
1209 > */
1210 > _setTrackedRange(id: string | null, newRange: Range, newStickiness: TrackedRangeStickiness): string;
1211 >
1212 > /**
1213 > * Normalize a string containing whitespace according to indentation rules (converts to spaces or to tabs).
1214 > */
1215 > normalizeIndentation(str: string): string;
1216 >
1217 > /**
1218 > * Change the options of this model.
1219 > */
1220 > updateOptions(newOpts: ITextModelUpdateOptions): void;
1221 >
1222 > /**
1223 > * Detect the indentation options for this model from its content.
1224 > */
1225 > detectIndentation(defaultInsertSpaces: boolean, defaultTabSize: number): void;
1226 >
1227 > /**
1228 > * Close the current undo-redo element.
1229 > * This offers a way to create an undo/redo stop point.
1230 > */
1231 > pushStackElement(): void;
1232 >
1233 > /**
1234 > * Open the current undo-redo element.
1235 > * This offers a way to remove the current undo/redo stop point.
1236 > */
1237 > popStackElement(): void;
1238 >
1239 > /**
1240 > * @internal
1241 > */
1242 > edit(edit: TextEdit, options?: { reason?: TextModelEditSource }): void;
1243 >
1244 > /**
1245 > * Push edit operations, basically editing the model. This is the preferred way
1246 > * of editing the model. The edit operations will land on the undo stack.
1247 > * @param beforeCursorState The cursor state before the edit operations. This cursor state will be returned when `undo` or `redo` are invoked.
1248 > * @param editOperations The edit operations.
1249 > * @param cursorStateComputer A callback that can compute the resulting cursors state after the edit operations have been executed.
1250 > * @return The cursor state returned by the `cursorStateComputer`.
1251 > */
1252 > pushEditOperations(beforeCursorState: Selection[] | null, editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[] | null;
1253 > /**
1254 > * @internal
1255 > */
1256 > pushEditOperations(beforeCursorState: Selection[] | null, editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer, group?: UndoRedoGroup, reason?: TextModelEditSource): Selection[] | null;
1257 >
1258 > /**
1259 > * Change the end of line sequence. This is the preferred way of
1260 > * changing the eol sequence. This will land on the undo stack.
1261 > */
1262 > pushEOL(eol: EndOfLineSequence): void;
1263 >
1264 > /**
1265 > * Edit the model without adding the edits to the undo stack.
1266 > * This can have dire consequences on the undo stack! See @pushEditOperations for the preferred way.
1267 > * @param operations The edit operations.
1268 > * @return If desired, the inverse edit operations, that, when applied, will bring the model back to the previous state.
1269 > */
1270 > applyEdits(operations: readonly IIdentifiedSingleEditOperation[]): void;
1271 > /** @internal */
1272 > applyEdits(operations: readonly IIdentifiedSingleEditOperation[], reason: TextModelEditSource): void;
1273 > applyEdits(operations: readonly IIdentifiedSingleEditOperation[], computeUndoEdits: false): void;
1274 > applyEdits(operations: readonly IIdentifiedSingleEditOperation[], computeUndoEdits: true): IValidEditOperation[];
1275 >
1276 > /**
1277 > * Change the end of line sequence without recording in the undo stack.
1278 > * This can have dire consequences on the undo stack! See @pushEOL for the preferred way.
1279 > */
1280 > setEOL(eol: EndOfLineSequence): void;
1281 >
1282 > /**
1283 > * @internal
1284 > */
1285 > _applyUndo(changes: TextChange[], eol: EndOfLineSequence, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void;
1286 >
1287 > /**
1288 > * @internal
1289 > */
1290 > _applyRedo(changes: TextChange[], eol: EndOfLineSequence, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void;
1291 >
1292 > /**
1293 > * Undo edit operations until the previous undo/redo point.
1294 > * The inverse edit operations will be pushed on the redo stack.
1295 > */
1296 > undo(): void | Promise<void>;
1297 >
1298 > /**
1299 > * Is there anything in the undo stack?
1300 > */
1301 > canUndo(): boolean;
1302 >
1303 > /**
1304 > * Redo edit operations until the next undo/redo point.
1305 > * The inverse edit operations will be pushed on the undo stack.
1306 > */
1307 > redo(): void | Promise<void>;
1308 >
1309 > /**
1310 > * Is there anything in the redo stack?
1311 > */
1312 > canRedo(): boolean;
1313 >
1314 > /**
1315 > * An event emitted when the contents of the model have changed.
1316 > * @event
1317 > */
1318 > onDidChangeContent(listener: (e: IModelContentChangedEvent) => void): IDisposable;
1319 > /**
1320 > * An event emitted when decorations of the model have changed.
1321 > * @event
1322 > */
1323 > readonly onDidChangeDecorations: Event<IModelDecorationsChangedEvent>;
1324 > /**
1325 > * An event emitted when line heights from decorations changes.
1326 > * This event is emitted only when adding, removing or changing a decoration
1327 > * and not when doing edits in the model (i.e. when decoration ranges change)
1328 > * @internal
1329 > * @event
1330 > */
1331 > readonly onDidChangeLineHeight: Event<ModelLineHeightChangedEvent>;
1332 > /**
1333 > * An event emitted when the font from decorations changes.
1334 > * This event is emitted only when adding, removing or changing a decoration
1335 > * and not when doing edits in the model (i.e. when decoration ranges change)
1336 > * @internal
1337 > * @event
1338 > */
1339 > readonly onDidChangeFont: Event<ModelFontChangedEvent>;
1340 > /**
1341 > * An event emitted when the model options have changed.
1342 > * @event
1343 > */
1344 > readonly onDidChangeOptions: Event<IModelOptionsChangedEvent>;
1345 > /**
1346 > * An event emitted when the language associated with the model has changed.
1347 > * @event
1348 > */
1349 > readonly onDidChangeLanguage: Event<IModelLanguageChangedEvent>;
1350 > /**
1351 > * An event emitted when the language configuration associated with the model has changed.
1352 > * @event
1353 > */
1354 > readonly onDidChangeLanguageConfiguration: Event<IModelLanguageConfigurationChangedEvent>;
1355 > /**
1356 > * An event emitted when the tokens associated with the model have changed.
1357 > * @event
1358 > * @internal
1359 > */
1360 > readonly onDidChangeTokens: Event<IModelTokensChangedEvent>;
1361 > /**
1362 > * An event emitted when the model has been attached to the first editor or detached from the last editor.
1363 > * @event
1364 > */
1365 > readonly onDidChangeAttached: Event<void>;
1366 > /**
1367 > * An event emitted right before disposing the model.
1368 > * @event
1369 > */
1370 > readonly onWillDispose: Event<void>;
1371 >
1372 > /**
1373 > * Destroy this model.
1374 > */
1375 > dispose(): void;
1376 >
1377 > /**
1378 > * @internal
1379 > */
1380 > onBeforeAttached(): IAttachedView;
1381 >
1382 > /**
1383 > * @internal
1384 > */
1385 > onBeforeDetached(view: IAttachedView): void;
1386 >
1387 > /**
1388 > * Returns if this model is attached to an editor or not.
1389 > */
1390 > isAttachedToEditor(): boolean;
1391 >
1392 > /**
1393 > * Returns the count of editors this model is attached to.
1394 > * @internal
1395 > */
1396 > getAttachedEditorCount(): number;
1397 >
1398 > /**
1399 > * Among all positions that are projected to the same position in the underlying text model as
1400 > * the given position, select a unique position as indicated by the affinity.
1401 > *
1402 > * PositionAffinity.Left:
1403 > * The normalized position must be equal or left to the requested position.
1404 > *
1405 > * PositionAffinity.Right:
1406 > * The normalized position must be equal or right to the requested position.
1407 > *
1408 > * @internal
1409 > */
1410 > normalizePosition(position: Position, affinity: PositionAffinity): Position;
1411 >
1412 > /**
1413 > * Gets the column at which indentation stops at a given line.
1414 > * @internal
1415 > */
1416 > getLineIndentColumn(lineNumber: number): number;
1417 >
1418 > /**
1419 > * Returns an object that can be used to query brackets.
1420 > * @internal
1421 > */
1422 > readonly bracketPairs: IBracketPairsTextModelPart;
1423 >
1424 > /**
1425 > * Returns an object that can be used to query indent guides.
1426 > * @internal
1427 > */
1428 > readonly guides: IGuidesTextModelPart;
1429 >
1430 > /**
1431 > * @internal
1432 > */
1433 > readonly tokenization: ITokenizationTextModelPart;
1434 > }
1435 >
1436 > /**
1437 > * @internal
1438 > */
1439 > export function isITextModel(obj: IEditorModel): obj is ITextModel {
1440 return Boolean(obj && (obj as ITextModel).uri);
1441 }
1442 > model.ts
1443 > /**
1444 > * @internal
1445 > */
1446 > export interface IAttachedView {
1447 > /**
1448 > * @param stabilized Indicates if the visible lines are probably going to change soon or can be considered stable.
1449 > * Is true on reveal range and false on scroll.
1450 > * Tokenizers should tokenize synchronously if stabilized is true.
1451 > */
1452 > setVisibleLines(visibleLines: { startLineNumber: number; endLineNumber: number }[], stabilized: boolean): void;
1453 > }
1454 >
1455 > export const enum PositionAffinity {
1456 > /**
1457 > * Prefers the left most position.
1458 > */
1459 > Left = 0,
1460 >
1461 > /**
1462 > * Prefers the right most position.
1463 > */
1464 > Right = 1,
1465 >
1466 > /**
1467 > * No preference.
1468 > */
1469 > None = 2,
1470 >
1471 > /**
1472 > * If the given position is on injected text, prefers the position left of it.
1473 > */
1474 > LeftOfInjectedText = 3,
1475 >
1476 > /**
1477 > * If the given position is on injected text, prefers the position right of it.
1478 > */
1479 > RightOfInjectedText = 4,
1480 > }
1481 >
1482 > /**
1483 > * @internal
1484 > */
1485 > export interface ITextBufferBuilder {
1486 > acceptChunk(chunk: string): void;
1487 > finish(): ITextBufferFactory;
1488 > }
1489 >
1490 > /**
1491 > * @internal
1492 > */
1493 > export interface ITextBufferFactory {
1494 > create(defaultEOL: DefaultEndOfLine): { textBuffer: ITextBuffer; disposable: IDisposable };
1495 > getFirstLineText(lengthLimit: number): string;
1496 > }
1497 >
1498 > /**
1499 > * @internal
1500 > */
1501 > export const enum ModelConstants {
1502 > FIRST_LINE_DETECTION_LENGTH_LIMIT = 1000
1503 > }
1504 >
1505 > /**
1506 > * @internal
1507 > */
1508 > export class ValidAnnotatedEditOperation implements IIdentifiedSingleEditOperation {
1509 > constructor(
1510 public readonly identifier: ISingleEditOperationIdentifier | null,
1511 public readonly range: Range,
1515 public readonly _isTracked: boolean,
1516 ) { }
1517 > } model.ts
1518 >
1519 > /**
1520 > * @internal
1521 > *
1522 > * `lineNumber` is 1 based.
1523 > */
1524 > export interface IReadonlyTextBuffer {
1525 > readonly onDidChangeContent: Event<void>;
1526 > equals(other: ITextBuffer): boolean;
1527 > mightContainRTL(): boolean;
1528 > mightContainUnusualLineTerminators(): boolean;
1529 > resetMightContainUnusualLineTerminators(): void;
1530 > mightContainNonBasicASCII(): boolean;
1531 > getBOM(): string;
1532 > getEOL(): string;
1533 >
1534 > getOffsetAt(lineNumber: number, column: number): number;
1535 > getPositionAt(offset: number): Position;
1536 > getRangeAt(offset: number, length: number): Range;
1537 >
1538 > getValueInRange(range: Range, eol: EndOfLinePreference): string;
1539 > createSnapshot(preserveBOM: boolean): ITextSnapshot;
1540 > getValueLengthInRange(range: Range, eol: EndOfLinePreference): number;
1541 > getCharacterCountInRange(range: Range, eol: EndOfLinePreference): number;
1542 > getLength(): number;
1543 > getLineCount(): number;
1544 > getLinesContent(): string[];
1545 > getLineContent(lineNumber: number): string;
1546 > getLineCharCode(lineNumber: number, index: number): number;
1547 > getCharCode(offset: number): number;
1548 > getLineLength(lineNumber: number): number;
1549 > getLineMinColumn(lineNumber: number): number;
1550 > getLineMaxColumn(lineNumber: number): number;
1551 > getLineFirstNonWhitespaceColumn(lineNumber: number): number;
1552 > getLineLastNonWhitespaceColumn(lineNumber: number): number;
1553 > findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[];
1554 >
1555 > /**
1556 > * Get nearest chunk of text after `offset` in the text buffer.
1557 > */
1558 > getNearestChunk(offset: number): string;
1559 > }
1560 >
1561 > /**
1562 > * @internal
1563 > */
1564 > export class SearchData {
1565 >
1566 > /**
1567 > * The regex to search for. Always defined.
1568 > */
1569 > public readonly regex: RegExp;
1570 > /**
1571 > * The word separator classifier.
1572 > */
1573 > public readonly wordSeparators: WordCharacterClassifier | null;
1574 > /**
1575 > * The simple string to search for (if possible).
1576 > */
1577 > public readonly simpleSearch: string | null;
1578 >
1579 > constructor(regex: RegExp, wordSeparators: WordCharacterClassifier | null, simpleSearch: string | null) {
1580 this.regex = regex;
1581 this.wordSeparators = wordSeparators;
1582 this.simpleSearch = simpleSearch;
1583 }
1584 > } model.ts
1585 >
1586 > /**
1587 > * @internal
1588 > */
1589 > export interface ITextBuffer extends IReadonlyTextBuffer, IDisposable {
1590 > setEOL(newEOL: '\r\n' | '\n'): void;
1591 > applyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean, computeUndoEdits: boolean): ApplyEditsResult;
1592 > }
1593 >
1594 > /**
1595 > * @internal
1596 > */
1597 > export class ApplyEditsResult {
1598 >
1599 > constructor(
1600 public readonly reverseEdits: IValidEditOperation[] | null,
1601 public readonly changes: IInternalModelContentChange[],
1602 public readonly trimAutoWhitespaceLineNumbers: number[] | null
1603 ) { }
1604 > model.ts
1605 > }
1606 >
1607 > /**
1608 > * @internal
1609 > */
1610 > export interface IInternalModelContentChange extends IModelContentChange {
1611 > range: Range;
1612 > forceMoveMarkers: boolean;
1613 > }
1614 >
1615 > /**
1616 > * @internal
1617 > */
1618 > export function shouldSynchronizeModel(model: ITextModel): boolean {
1619 return (
1620 !model.isTooLargeForSyncing() && !model.isForSimpleWidget
src/vs/base/common/event.ts 849 covered LOC · 97 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- event.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 { CancelablePromise } from './async.js';
7 > import { CancellationToken } from './cancellation.js';
8 > import { diffSets } from './collections.js';
9 > import { onUnexpectedError } from './errors.js';
10 > import { createSingleCallFunction } from './functional.js';
11 > import { combinedDisposable, Disposable, DisposableMap, DisposableStore, IDisposable, toDisposable } from './lifecycle.js';
12 > import { LinkedList } from './linkedList.js';
13 > import { IObservable, IObservableWithChange, IObserver } from './observable.js';
14 > import { env } from './process.js';
15 > import { StopWatch } from './stopwatch.js';
16 > import { MicrotaskDelay } from './symbols.js';
17 >
18 >
19 > // -----------------------------------------------------------------------------------------------------------------------
20 > // Uncomment the next line to print warnings whenever an emitter with listeners is disposed. That is a sign of code smell.
21 > // -----------------------------------------------------------------------------------------------------------------------
22 > const _enableDisposeWithListenerWarning = false
23 > // || Boolean("TRUE") // causes a linter warning so that it cannot be pushed
24 > ;
25 >
26 >
27 > // -----------------------------------------------------------------------------------------------------------------------
28 > // Uncomment the next line to print warnings whenever a snapshotted event is used repeatedly without cleanup.
29 > // See https://github.com/microsoft/vscode/issues/142851
30 > // -----------------------------------------------------------------------------------------------------------------------
31 > const _enableSnapshotPotentialLeakWarning = false
32 > // || Boolean("TRUE") // causes a linter warning so that it cannot be pushed
33 > ;
34 >
35 >
36 > const _bufferLeakWarnCountThreshold = 100;
37 > const _bufferLeakWarnTimeThreshold = 60_000; // 1 minute
38 >
39 function _isBufferLeakWarningEnabled(): boolean {
40 return !!env['VSCODE_DEV'];
41 }
42 > event.ts
43 > /**
44 > * An event with zero or one parameters that can be subscribed to. The event is a function itself.
45 > */
46 > export interface Event<T> {
47 > (listener: (e: T) => unknown, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable;
48 > }
49 >
50 > export namespace Event {
51 > export const None: Event<any> = () => Disposable.None;
52 >
53 > function _addLeakageTraceLogic(options: EmitterOptions) {
54 if (_enableSnapshotPotentialLeakWarning) {
55 const { onDidAddListener: origListenerDidAdd } = options;
65 }
66 }
67 > event.ts
68 > /**
69 > * Given an event, returns another event which debounces calls and defers the listeners to a later task via a shared
70 > * `setTimeout`. The event is converted into a signal (`Event<void>`) to avoid additional object creation as a
71 > * result of merging events and to try prevent race conditions that could arise when using related deferred and
72 > * non-deferred events.
73 > *
74 > * This is useful for deferring non-critical work (eg. general UI updates) to ensure it does not block critical work
75 > * (eg. latency of keypress to text rendered).
76 > *
77 > * *NOTE* that this function returns an `Event` and it MUST be called with a `DisposableStore` whenever the returned
78 > * event is accessible to "third parties", e.g the event is a public property. Otherwise a leaked listener on the
79 > * returned event causes this utility to leak a listener on the original event.
80 > *
81 > * @param event The event source for the new event.
82 > * @param flushOnListenerRemove Whether to fire all debounced events when a listener is removed. If this is not
83 > * specified, some events could go missing. Use this if it's important that all events are processed, even if the
84 > * listener gets disposed before the debounced event fires.
85 > * @param disposable A disposable store to add the new EventEmitter to.
86 > */
87 > export function defer(event: Event<unknown>, flushOnListenerRemove?: boolean, disposable?: DisposableStore): Event<void> {
88 return debounce<unknown, void>(event, () => void 0, 0, undefined, flushOnListenerRemove ?? true, undefined, disposable);
89 }
90 > event.ts
91 > /**
92 > * Given an event, returns another event which only fires once.
93 > *
94 > * @param event The event source for the new event.
95 > */
96 > export function once<T>(event: Event<T>): Event<T> {
97 return (listener, thisArgs = null, disposables?) => {
98 // we need this, in case the event fires during the listener call
118 };
119 }
120 > event.ts
121 > /**
122 > * Given an event, returns another event which only fires once, and only when the condition is met.
123 > *
124 > * @param event The event source for the new event.
125 > */
126 > export function onceIf<T>(event: Event<T>, condition: (e: T) => boolean): Event<T> {
127 return Event.once(Event.filter(event, condition));
128 }
129 > event.ts
130 > /**
131 > * Maps an event of one type into an event of another type using a mapping function, similar to how
132 > * `Array.prototype.map` works.
133 > *
134 > * *NOTE* that this function returns an `Event` and it MUST be called with a `DisposableStore` whenever the returned
135 > * event is accessible to "third parties", e.g the event is a public property. Otherwise a leaked listener on the
136 > * returned event causes this utility to leak a listener on the original event.
137 > *
138 > * @param event The event source for the new event.
139 > * @param map The mapping function.
140 > * @param disposable A disposable store to add the new EventEmitter to.
141 > */
142 > export function map<I, O>(event: Event<I>, map: (i: I) => O, disposable?: DisposableStore): Event<O> {
143 return snapshot((listener, thisArgs = null, disposables?) => event(i => listener.call(thisArgs, map(i)), null, disposables), disposable);
144 }
145 > event.ts
146 > /**
147 > * Wraps an event in another event that performs some function on the event object before firing.
148 > *
149 > * *NOTE* that this function returns an `Event` and it MUST be called with a `DisposableStore` whenever the returned
150 > * event is accessible to "third parties", e.g the event is a public property. Otherwise a leaked listener on the
151 > * returned event causes this utility to leak a listener on the original event.
152 > *
153 > * @param event The event source for the new event.
154 > * @param each The function to perform on the event object.
155 > * @param disposable A disposable store to add the new EventEmitter to.
156 > */
157 > export function forEach<I>(event: Event<I>, each: (i: I) => void, disposable?: DisposableStore): Event<I> {
158 return snapshot((listener, thisArgs = null, disposables?) => event(i => { each(i); listener.call(thisArgs, i); }, null, disposables), disposable);
159 }
160 > event.ts
161 > /**
162 > * Wraps an event in another event that fires only when some condition is met.
163 > *
164 > * *NOTE* that this function returns an `Event` and it MUST be called with a `DisposableStore` whenever the returned
165 > * event is accessible to "third parties", e.g the event is a public property. Otherwise a leaked listener on the
166 > * returned event causes this utility to leak a listener on the original event.
167 > *
168 > * @param event The event source for the new event.
169 > * @param filter The filter function that defines the condition. The event will fire for the object if this function
170 > * returns true.
171 > * @param disposable A disposable store to add the new EventEmitter to.
172 > */
173 > export function filter<T, U>(event: Event<T | U>, filter: (e: T | U) => e is T, disposable?: DisposableStore): Event<T>;
174 > export function filter<T>(event: Event<T>, filter: (e: T) => boolean, disposable?: DisposableStore): Event<T>;
175 > export function filter<T, R>(event: Event<T | R>, filter: (e: T | R) => e is R, disposable?: DisposableStore): Event<R>;
176 > export function filter<T>(event: Event<T>, filter: (e: T) => boolean, disposable?: DisposableStore): Event<T> {
177 return snapshot((listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables), disposable);
178 }
179 > event.ts
180 > /**
181 > * Given an event, returns the same event but typed as `Event<void>`.
182 > */
183 > export function signal<T>(event: Event<T>): Event<void> {
184 return event as Event<any> as Event<void>;
185 }
186 > event.ts
187 > /**
188 > * Given a collection of events, returns a single event which emits whenever any of the provided events emit.
189 > */
190 > export function any<T>(...events: Event<T>[]): Event<T>;
191 > export function any(...events: Event<any>[]): Event<void>;
192 > export function any<T>(...events: Event<T>[]): Event<T> {
193 return (listener, thisArgs = null, disposables?) => {
194 const disposable = combinedDisposable(...events.map(event => event(e => listener.call(thisArgs, e))));
196 };
197 }
198 > event.ts
199 > /**
200 > * *NOTE* that this function returns an `Event` and it MUST be called with a `DisposableStore` whenever the returned
201 > * event is accessible to "third parties", e.g the event is a public property. Otherwise a leaked listener on the
202 > * returned event causes this utility to leak a listener on the original event.
203 > */
204 > export function reduce<I, O>(event: Event<I>, merge: (last: O | undefined, event: I) => O, initial?: O, disposable?: DisposableStore): Event<O> {
205 let output: O | undefined = initial;
206
210 }, disposable);
211 }
212 > event.ts
213 > function snapshot<T>(event: Event<T>, disposable: DisposableStore | undefined): Event<T> {
214 let listener: IDisposable | undefined;
215
233 return emitter.event;
234 }
235 > event.ts
236 > /**
237 > * Adds the IDisposable to the store if it's set, and returns it. Useful to
238 > * Event function implementation.
239 > */
240 > function addAndReturnDisposable<T extends IDisposable>(d: T, store: DisposableStore | IDisposable[] | undefined): T {
241 if (store instanceof Array) {
242 store.push(d);
246 return d;
247 }
248 > event.ts
249 > /**
250 > * Given an event, creates a new emitter that event that will debounce events based on {@link delay} and give an
251 > * array event object of all events that fired.
252 > *
253 > * *NOTE* that this function returns an `Event` and it MUST be called with a `DisposableStore` whenever the returned
254 > * event is accessible to "third parties", e.g the event is a public property. Otherwise a leaked listener on the
255 > * returned event causes this utility to leak a listener on the original event.
256 > *
257 > * @param event The original event to debounce.
258 > * @param merge A function that reduces all events into a single event.
259 > * @param delay The number of milliseconds to debounce.
260 > * @param leading Whether to fire a leading event without debouncing.
261 > * @param flushOnListenerRemove Whether to fire all debounced events when a listener is removed. If this is not
262 > * specified, some events could go missing. Use this if it's important that all events are processed, even if the
263 > * listener gets disposed before the debounced event fires.
264 > * @param leakWarningThreshold See {@link EmitterOptions.leakWarningThreshold}.
265 > * @param disposable A disposable store to register the debounce emitter to.
266 > */
267 > export function debounce<T>(event: Event<T>, merge: (last: T | undefined, event: T) => T, delay?: number | typeof MicrotaskDelay, leading?: boolean, flushOnListenerRemove?: boolean, leakWarningThreshold?: number, disposable?: DisposableStore): Event<T>;
268 > export function debounce<I, O>(event: Event<I>, merge: (last: O | undefined, event: I) => O, delay?: number | typeof MicrotaskDelay, leading?: boolean, flushOnListenerRemove?: boolean, leakWarningThreshold?: number, disposable?: DisposableStore): Event<O>;
269 > export function debounce<I, O>(event: Event<I>, merge: (last: O | undefined, event: I) => O, delay: number | typeof MicrotaskDelay = 100, leading = false, flushOnListenerRemove = false, leakWarningThreshold?: number, disposable?: DisposableStore): Event<O> {
270 let subscription: IDisposable;
271 let output: O | undefined = undefined;
330 return emitter.event;
331 }
332 > event.ts
333 > /**
334 > * Debounces an event, firing after some delay (default=0) with an array of all event original objects.
335 > *
336 > * *NOTE* that this function returns an `Event` and it MUST be called with a `DisposableStore` whenever the returned
337 > * event is accessible to "third parties", e.g the event is a public property. Otherwise a leaked listener on the
338 > * returned event causes this utility to leak a listener on the original event.
339 > *
340 > * @param event The event source for the new event.
341 > * @param delay The number of milliseconds to debounce.
342 > * @param flushOnListenerRemove Whether to fire all debounced events when a listener is removed. If this is not
343 > * specified, some events could go missing. Use this if it's important that all events are processed, even if the
344 > * listener gets disposed before the debounced event fires.
345 > * @param disposable A disposable store to add the new EventEmitter to.
346 > */
347 > export function accumulate<T>(event: Event<T>, delay: number | typeof MicrotaskDelay = 0, flushOnListenerRemove?: boolean, disposable?: DisposableStore): Event<T[]> {
348 return Event.debounce<T, T[]>(event, (last, e) => {
349 if (!last) {
354 }, delay, undefined, flushOnListenerRemove ?? true, undefined, disposable);
355 }
356 > event.ts
357 > /**
358 > * Throttles an event, ensuring the event is fired at most once during the specified delay period.
359 > * Unlike debounce, throttle will fire immediately on the leading edge and/or after the delay on the trailing edge.
360 > *
361 > * *NOTE* that this function returns an `Event` and it MUST be called with a `DisposableStore` whenever the returned
362 > * event is accessible to "third parties", e.g the event is a public property. Otherwise a leaked listener on the
363 > * returned event causes this utility to leak a listener on the original event.
364 > *
365 > * @param event The event source for the new event.
366 > * @param merge An accumulator function that merges events if multiple occur during the throttle period.
367 > * @param delay The number of milliseconds to throttle.
368 > * @param leading Whether to fire on the leading edge (immediately on first event).
369 > * @param trailing Whether to fire on the trailing edge (after delay with the last value).
370 > * @param leakWarningThreshold See {@link EmitterOptions.leakWarningThreshold}.
371 > * @param disposable A disposable store to register the throttle emitter to.
372 > */
373 > export function throttle<T>(event: Event<T>, merge: (last: T | undefined, event: T) => T, delay?: number | typeof MicrotaskDelay, leading?: boolean, trailing?: boolean, leakWarningThreshold?: number, disposable?: DisposableStore): Event<T>;
374 > export function throttle<I, O>(event: Event<I>, merge: (last: O | undefined, event: I) => O, delay?: number | typeof MicrotaskDelay, leading?: boolean, trailing?: boolean, leakWarningThreshold?: number, disposable?: DisposableStore): Event<O>;
375 > export function throttle<I, O>(event: Event<I>, merge: (last: O | undefined, event: I) => O, delay: number | typeof MicrotaskDelay = 100, leading = true, trailing = true, leakWarningThreshold?: number, disposable?: DisposableStore): Event<O> {
376 let subscription: IDisposable;
377 let output: O | undefined = undefined;
437 return emitter.event;
438 }
439 > event.ts
440 > /**
441 > * Filters an event such that some condition is _not_ met more than once in a row, effectively ensuring duplicate
442 > * event objects from different sources do not fire the same event object.
443 > *
444 > * *NOTE* that this function returns an `Event` and it MUST be called with a `DisposableStore` whenever the returned
445 > * event is accessible to "third parties", e.g the event is a public property. Otherwise a leaked listener on the
446 > * returned event causes this utility to leak a listener on the original event.
447 > *
448 > * @param event The event source for the new event.
449 > * @param equals The equality condition.
450 > * @param disposable A disposable store to add the new EventEmitter to.
451 > *
452 > * @example
453 > * ```
454 > * // Fire only one time when a single window is opened or focused
455 > * Event.latch(Event.any(onDidOpenWindow, onDidFocusWindow))
456 > * ```
457 > */
458 > export function latch<T>(event: Event<T>, equals: (a: T, b: T) => boolean = (a, b) => a === b, disposable?: DisposableStore): Event<T> {
459 let firstCall = true;
460 let cache: T;
467 }, disposable);
468 }
469 > event.ts
470 > /**
471 > * Splits an event whose parameter is a union type into 2 separate events for each type in the union.
472 > *
473 > * *NOTE* that this function returns an `Event` and it MUST be called with a `DisposableStore` whenever the returned
474 > * event is accessible to "third parties", e.g the event is a public property. Otherwise a leaked listener on the
475 > * returned event causes this utility to leak a listener on the original event.
476 > *
477 > * @example
478 > * ```
479 > * const event = new EventEmitter<number | undefined>().event;
480 > * const [numberEvent, undefinedEvent] = Event.split(event, isUndefined);
481 > * ```
482 > *
483 > * @param event The event source for the new event.
484 > * @param isT A function that determines what event is of the first type.
485 > * @param disposable A disposable store to add the new EventEmitter to.
486 > */
487 > export function split<T, U>(event: Event<T | U>, isT: (e: T | U) => e is T, disposable?: DisposableStore): [Event<T>, Event<U>] {
488 return [
489 Event.filter(event, isT, disposable),
491 ];
492 }
493 > event.ts
494 > /**
495 > * Buffers an event until it has a listener attached.
496 > *
497 > * *NOTE* that this function returns an `Event` and it MUST be called with a `DisposableStore` whenever the returned
498 > * event is accessible to "third parties", e.g the event is a public property. Otherwise a leaked listener on the
499 > * returned event causes this utility to leak a listener on the original event.
500 > *
501 > * @param event The event source for the new event.
502 > * @param debugName A name for this buffer, used in leak detection warnings.
503 > * @param flushAfterTimeout Determines whether to flush the buffer after a timeout immediately or after a
504 > * `setTimeout` when the first event listener is added.
505 > * @param _buffer Internal: A source event array used for tests.
506 > *
507 > * @example
508 > * ```
509 > * // Start accumulating events, when the first listener is attached, flush
510 > * // the event after a timeout such that multiple listeners attached before
511 > * // the timeout would receive the event
512 > * this.onInstallExtension = Event.buffer(service.onInstallExtension, 'onInstallExtension', true);
513 > * ```
514 > */
515 > export function buffer<T>(event: Event<T>, debugName: string, flushAfterTimeout = false, _buffer: T[] = [], disposable?: DisposableStore): Event<T> {
516 let buffer: T[] | null = _buffer.slice();
517
600 return emitter.event;
601 }
602 > /** event.ts
603 > * Wraps the event in an {@link IChainableEvent}, allowing a more functional programming style.
604 > *
605 > * @example
606 > * ```
607 > * // Normal
608 > * const onEnterPressNormal = Event.filter(
609 > * Event.map(onKeyPress.event, e => new StandardKeyboardEvent(e)),
610 > * e.keyCode === KeyCode.Enter
611 > * ).event;
612 > *
613 > * // Using chain
614 > * const onEnterPressChain = Event.chain(onKeyPress.event, $ => $
615 > * .map(e => new StandardKeyboardEvent(e))
616 > * .filter(e => e.keyCode === KeyCode.Enter)
617 > * );
618 > * ```
619 > */
620 > export function chain<T, R>(event: Event<T>, sythensize: ($: IChainableSythensis<T>) => IChainableSythensis<R>): Event<R> {
621 const fn: Event<R> = (listener, thisArgs, disposables) => {
622 const cs = sythensize(new ChainableSynthesis()) as ChainableSynthesis;
631 return fn;
632 }
633 > event.ts
634 > const HaltChainable = Symbol('HaltChainable');
635 >
636 > class ChainableSynthesis implements IChainableSythensis<any> {
637 private readonly steps: ((input: any) => unknown)[] = [];
638 > event.ts
639 > map<O>(fn: (i: any) => O): this {
640 this.steps.push(fn);
641 return this;
642 }
643 > event.ts
644 > forEach(fn: (i: any) => void): this {
645 this.steps.push(v => {
646 fn(v);
649 return this;
650 }
651 > event.ts
652 > filter(fn: (e: any) => boolean): this {
653 this.steps.push(v => fn(v) ? v : HaltChainable);
654 return this;
655 }
656 > event.ts
657 > reduce<R>(merge: (last: R | undefined, event: any) => R, initial?: R | undefined): this {
658 let last = initial;
659 this.steps.push(v => {
663 return this;
664 }
665 > event.ts
666 > latch(equals: (a: any, b: any) => boolean = (a, b) => a === b): ChainableSynthesis {
667 let firstCall = true;
668 let cache: any;
676 return this;
677 }
678 > event.ts
679 > public evaluate(value: any) {
680 for (const step of this.steps) {
681 value = step(value);
687 return value;
688 }
689 > } event.ts
690 >
691 > export interface IChainableSythensis<T> {
692 > map<O>(fn: (i: T) => O): IChainableSythensis<O>;
693 > forEach(fn: (i: T) => void): IChainableSythensis<T>;
694 > filter<R extends T>(fn: (e: T) => e is R): IChainableSythensis<R>;
695 > filter(fn: (e: T) => boolean): IChainableSythensis<T>;
696 > reduce<R>(merge: (last: R, event: T) => R, initial: R): IChainableSythensis<R>;
697 > reduce<R>(merge: (last: R | undefined, event: T) => R): IChainableSythensis<R>;
698 > latch(equals?: (a: T, b: T) => boolean): IChainableSythensis<T>;
699 > }
700 >
701 > export interface NodeEventEmitter {
702 > on(event: string | symbol, listener: Function): unknown;
703 > removeListener(event: string | symbol, listener: Function): unknown;
704 > }
705 >
706 > /**
707 > * Creates an {@link Event} from a node event emitter.
708 > */
709 > export function fromNodeEventEmitter<T>(emitter: NodeEventEmitter, eventName: string, map: (...args: any[]) => T = id => id): Event<T> {
710 const fn = (...args: unknown[]) => result.fire(map(...args));
711 const onFirstListenerAdd = () => emitter.on(eventName, fn);
715 return result.event;
716 }
717 > event.ts
718 > export interface DOMEventEmitter {
719 > addEventListener(event: string | symbol, listener: Function): void;
720 > removeEventListener(event: string | symbol, listener: Function): void;
721 > }
722 >
723 > /**
724 > * Creates an {@link Event} from a DOM event emitter.
725 > */
726 > export function fromDOMEventEmitter<T>(emitter: DOMEventEmitter, eventName: string, map: (...args: any[]) => T = id => id): Event<T> {
727 const fn = (...args: unknown[]) => result.fire(map(...args));
728 const onFirstListenerAdd = () => emitter.addEventListener(eventName, fn);
732 return result.event;
733 }
734 > event.ts
735 > /**
736 > * Creates a promise out of an event, using the {@link Event.once} helper.
737 > */
738 > export function toPromise<T>(event: Event<T>, disposables?: IDisposable[] | DisposableStore): CancelablePromise<T> {
739 let cancelRef: () => void;
740 let listener: IDisposable;
756 return promise;
757 }
758 > event.ts
759 > /**
760 > * A convenience function for forwarding an event to another emitter which
761 > * improves readability.
762 > *
763 > * This is similar to {@link Relay} but allows instantiating and forwarding
764 > * on a single line and also allows for multiple source events.
765 > * @param from The event to forward.
766 > * @param to The emitter to forward the event to.
767 > * @example
768 > * Event.forward(event, emitter);
769 > * // equivalent to
770 > * event(e => emitter.fire(e));
771 > * // equivalent to
772 > * event(emitter.fire, emitter);
773 > */
774 > export function forward<T>(from: Event<T>, to: Emitter<T>): IDisposable {
775 return from(e => to.fire(e));
776 }
777 > event.ts
778 > /**
779 > * Adds a listener to an event and calls the listener immediately with undefined as the event object.
780 > *
781 > * @example
782 > * ```
783 > * // Initialize the UI and update it when dataChangeEvent fires
784 > * runAndSubscribe(dataChangeEvent, () => this._updateUI());
785 > * ```
786 > */
787 > export function runAndSubscribe<T>(event: Event<T>, handler: (e: T) => unknown, initial: T): IDisposable;
788 > export function runAndSubscribe<T>(event: Event<T>, handler: (e: T | undefined) => unknown): IDisposable;
789 > export function runAndSubscribe<T>(event: Event<T>, handler: (e: T | undefined) => unknown, initial?: T): IDisposable {
790 handler(initial);
791 return event(e => handler(e));
792 }
793 > event.ts
794 > class EmitterObserver<T> implements IObserver {
795 >
796 > readonly emitter: Emitter<T>;
797 >
798 > private _counter = 0;
799 > private _hasChanged = false;
800 >
801 > constructor(readonly _observable: IObservable<T>, store: DisposableStore | undefined) {
802 const options: EmitterOptions = {
803 onWillAddFirstListener: () => {
819 }
820 }
821 > event.ts
822 > beginUpdate<T>(_observable: IObservable<T>): void {
823 // assert(_observable === this.obs);
824 this._counter++;
825 }
826 > event.ts
827 > handlePossibleChange<T>(_observable: IObservable<T>): void {
828 // assert(_observable === this.obs);
829 }
830 > event.ts
831 > handleChange<T, TChange>(_observable: IObservableWithChange<T, TChange>, _change: TChange): void {
832 // assert(_observable === this.obs);
833 this._hasChanged = true;
834 }
835 > event.ts
836 > endUpdate<T>(_observable: IObservable<T>): void {
837 // assert(_observable === this.obs);
838 this._counter--;
845 }
846 }
847 > } event.ts
848 >
849 > /**
850 > * Creates an event emitter that is fired when the observable changes.
851 > * Each listeners subscribes to the emitter.
852 > */
853 > export function fromObservable<T>(obs: IObservable<T>, store?: DisposableStore): Event<T> {
854 const observer = new EmitterObserver(obs, store);
855 return observer.emitter.event;
856 }
857 > event.ts
858 > /**
859 > * Each listener is attached to the observable directly.
860 > */
861 > export function fromObservableLight(observable: IObservable<unknown>): Event<void> {
862 return (listener, thisArgs, disposables) => {
863 let count = 0;
897 };
898 }
899 > } event.ts
900 >
901 > export interface EmitterOptions {
902 > /**
903 > * Optional function that's called *before* the very first listener is added
904 > */
905 > onWillAddFirstListener?: Function;
906 > /**
907 > * Optional function that's called *after* the very first listener is added
908 > */
909 > onDidAddFirstListener?: Function;
910 > /**
911 > * Optional function that's called after a listener is added
912 > */
913 > onDidAddListener?: Function;
914 > /**
915 > * Optional function that's called *after* remove the very last listener
916 > */
917 > onDidRemoveLastListener?: Function;
918 > /**
919 > * Optional function that's called *before* a listener is removed
920 > */
921 > onWillRemoveListener?: Function;
922 > /**
923 > * Optional function that's called when a listener throws an error. Defaults to
924 > * {@link onUnexpectedError}
925 > */
926 > onListenerError?: (e: any) => void;
927 > /**
928 > * Number of listeners that are allowed before assuming a leak. Default to
929 > * a globally configured value
930 > *
931 > * @see setGlobalLeakWarningThreshold
932 > */
933 > leakWarningThreshold?: number;
934 > /**
935 > * Human-readable name for the emitter, included in leak warning error
936 > * messages to help identify which emitter is leaking in telemetry.
937 > */
938 > leakWarningName?: string;
939 > /**
940 > * Pass in a delivery queue, which is useful for ensuring
941 > * in order event delivery across multiple emitters.
942 > */
943 > deliveryQueue?: EventDeliveryQueue;
944 >
945 > /** ONLY enable this during development */
946 > _profName?: string;
947 > }
948 >
949 >
950 > export class EventProfiling {
951 >
952 > static readonly all = new Set<EventProfiling>();
953 >
954 > private static _idPool = 0;
955 >
956 > readonly name: string;
957 > public listenerCount: number = 0;
958 > public invocationCount = 0;
959 > public elapsedOverall = 0;
960 > public durations: number[] = [];
961 >
962 > private _stopWatch?: StopWatch;
963 >
964 > constructor(name: string) {
965 this.name = `${name}_${EventProfiling._idPool++}`;
966 EventProfiling.all.add(this);
967 }
968 > event.ts
969 > start(listenerCount: number): void {
970 this._stopWatch = new StopWatch();
971 this.listenerCount = listenerCount;
972 }
973 > event.ts
974 > stop(): void {
975 if (this._stopWatch) {
976 const elapsed = this._stopWatch.elapsed();
981 }
982 }
983 > } event.ts
984 >
985 > let _globalLeakWarningThreshold = -1;
986 > export function setGlobalLeakWarningThreshold(n: number): IDisposable {
987 const oldValue = _globalLeakWarningThreshold;
988 _globalLeakWarningThreshold = n;
993 };
994 }
995 > event.ts
996 > class LeakageMonitor {
997 >
998 > private static _idPool = 1;
999 >
1000 > private _stacks: Map<string, number> | undefined;
1001 > private _warnCountdown: number = 0;
1002 >
1003 > constructor(
1004 private readonly _errorHandler: (err: Error) => void,
1005 readonly threshold: number,
1006 readonly name: string = (LeakageMonitor._idPool++).toString(16).padStart(3, '0')
1007 ) { }
1008 > event.ts
1009 > dispose(): void {
1010 this._stacks?.clear();
1011 }
1012 > event.ts
1013 > check(stack: Stacktrace, listenerCount: number): undefined | (() => void) {
1014
1015 const threshold = this.threshold;
1046 };
1047 }
1048 > event.ts
1049 > getMostFrequentStack(): [string, number] | undefined {
1050 if (!this._stacks) {
1051 return undefined;
1061 return topStack;
1062 }
1063 > } event.ts
1064 >
1065 > class Stacktrace {
1066 >
1067 > static create() {
1068 > const err = new Error();
1069 > return new Stacktrace(err.stack ?? '');
1070 > }
1071 >
1072 > private constructor(readonly value: string) { }
1073 >
1074 > print() {
1075 console.warn(this.value.split('\n').slice(2).join('\n'));
1076 }
1077 > } event.ts
1078 >
1079 > // error that is logged when going over the configured listener threshold
1080 > export class ListenerLeakError extends Error {
1081 > readonly kind: string;
1082 > readonly listenerCount: number;
1083 > /**
1084 > * The detailed message including listener count and most frequent stack.
1085 > * Available locally for debugging but intentionally not used as the error
1086 > * `message`. When `emitterName` is provided, errors group by emitter name
1087 > * and kind in telemetry; otherwise they group by kind alone.
1088 > */
1089 > readonly details: string;
1090 > constructor(kind: 'dominated' | 'popular', details: string, stack: string, listenerCount: number, emitterName?: string) {
1091 super(emitterName
1092 ? `[${emitterName}] potential listener LEAK detected, ${kind}`
1098 this.stack = stack;
1099 }
1100 > event.ts
1101 > static is(err: unknown): err is ListenerLeakError {
1102 return err instanceof ListenerLeakError
1103 || (err instanceof Error && typeof (err as Error & { kind: unknown; listenerCount: unknown }).kind === 'string' && typeof (err as Error & { kind: unknown; listenerCount: unknown }).listenerCount === 'number');
1104 }
1105 > } event.ts
1106 >
1107 > // SEVERE error that is logged when having gone way over the configured listener
1108 > // threshold so that the emitter refuses to accept more listeners
1109 > export class ListenerRefusalError extends ListenerLeakError {
1110 > constructor(kind: 'dominated' | 'popular', details: string, stack: string, listenerCount: number, emitterName?: string) {
1111 super(kind, details, stack, listenerCount, emitterName);
1112 this.name = 'ListenerRefusalError';
1113 }
1114 > } event.ts
1115 >
1116 > let id = 0;
1117 > class UniqueContainer<T> {
1118 > stack?: Stacktrace;
1119 > public id = id++;
1120 > constructor(public readonly value: T) { }
1121 > }
1122 > const compactionThreshold = 2;
1123 >
1124 > type ListenerContainer<T> = UniqueContainer<(data: T) => void>;
1125 > type ListenerOrListeners<T> = (ListenerContainer<T> | undefined)[] | ListenerContainer<T>;
1126 >
1127 > const forEachListener = <T>(listeners: ListenerOrListeners<T>, fn: (c: ListenerContainer<T>) => void) => {
1128 if (listeners instanceof UniqueContainer) {
1129 fn(listeners);
1137 }
1138 };
1139 > event.ts
1140 > /**
1141 > * The Emitter can be used to expose an Event to the public
1142 > * to fire it from the insides.
1143 > * Sample:
1144 > class Document {
1145 >
1146 > private readonly _onDidChange = new Emitter<(value:string)=>any>();
1147 >
1148 > public onDidChange = this._onDidChange.event;
1149 >
1150 > // getter-style
1151 > // get onDidChange(): Event<(value:string)=>any> {
1152 > // return this._onDidChange.event;
1153 > // }
1154 >
1155 > private _doIt() {
1156 > //...
1157 > this._onDidChange.fire(value);
1158 > }
1159 > }
1160 > */
1161 > export class Emitter<T> {
1162 >
1163 > private readonly _options?: EmitterOptions;
1164 > private readonly _leakageMon?: LeakageMonitor;
1165 > private readonly _perfMon?: EventProfiling;
1166 > private _disposed?: true;
1167 > private _event?: Event<T>;
1168 >
1169 > /**
1170 > * A listener, or list of listeners. A single listener is the most common
1171 > * for event emitters (#185789), so we optimize that special case to avoid
1172 > * wrapping it in an array (just like Node.js itself.)
1173 > *
1174 > * A list of listeners never 'downgrades' back to a plain function if
1175 > * listeners are removed, for two reasons:
1176 > *
1177 > * 1. That's complicated (especially with the deliveryQueue)
1178 > * 2. A listener with >1 listener is likely to have >1 listener again at
1179 > * some point, and swapping between arrays and functions may[citation needed]
1180 > * introduce unnecessary work and garbage.
1181 > *
1182 > * The array listeners can be 'sparse', to avoid reallocating the array
1183 > * whenever any listener is added or removed. If more than `1 / compactionThreshold`
1184 > * of the array is empty, only then is it resized.
1185 > */
1186 > protected _listeners?: ListenerOrListeners<T>;
1187 >
1188 > /**
1189 > * Always to be defined if _listeners is an array. It's no longer a true
1190 > * queue, but holds the dispatching 'state'. If `fire()` is called on an
1191 > * emitter, any work left in the _deliveryQueue is finished first.
1192 > */
1193 > private _deliveryQueue?: EventDeliveryQueuePrivate;
1194 > protected _size = 0;
1195 >
1196 > constructor(options?: EmitterOptions) {
1197 > this._options = options; event.ts
1198 > this._leakageMon = (_globalLeakWarningThreshold > 0 || this._options?.leakWarningThreshold)
1199 ? new LeakageMonitor(options?.onListenerError ?? onUnexpectedError, this._options?.leakWarningThreshold ?? _globalLeakWarningThreshold, this._options?.leakWarningName) :
1200 > undefined; event.ts
1201 > this._perfMon = this._options?._profName ? new EventProfiling(this._options._profName) : undefined;
1202 > this._deliveryQueue = this._options?.deliveryQueue as EventDeliveryQueuePrivate | undefined;
1203 > }
1204 > event.ts
1205 > dispose() {
1206 if (!this._disposed) {
1207 this._disposed = true;
1235 }
1236 }
1237 > event.ts
1238 > /**
1239 > * For the public to allow to subscribe
1240 > * to events from this Emitter
1241 > */
1242 > get event(): Event<T> {
1243 > this._event ??= (callback: (e: T) => unknown, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => { event.ts
1244 if (this._leakageMon && this._size > this._leakageMon.threshold ** 2) {
1245 const message = `[${this._leakageMon.name}] REFUSES to accept new listeners because it exceeded its threshold by far (${this._size} vs ${this._leakageMon.threshold})`;
1301 return result;
1302 };
1303 > event.ts
1304 > return this._event;
1305 > }
1306 > event.ts
1307 > private _removeListener(listener: ListenerContainer<T>) {
1308 this._options?.onWillRemoveListener?.(this);
1309
1349 }
1350 }
1351 > event.ts
1352 > private _deliver(listener: undefined | UniqueContainer<(value: T) => void>, value: T) {
1353 if (!listener) {
1354 return;
1367 }
1368 }
1369 > event.ts
1370 > /** Delivers items in the queue. Assumes the queue is ready to go. */
1371 > private _deliverQueue(dq: EventDeliveryQueuePrivate) {
1372 const listeners = dq.current!._listeners! as (ListenerContainer<T> | undefined)[];
1373 while (dq.i < dq.end) {
1377 dq.reset();
1378 }
1379 > event.ts
1380 > /**
1381 > * To be kept private to fire an event to
1382 > * subscribers
1383 > */
1384 > fire(event: T): void {
1385 if (this._deliveryQueue?.current) {
1386 this._deliverQueue(this._deliveryQueue);
1402 this._perfMon?.stop();
1403 }
1404 > event.ts
1405 > hasListeners(): boolean {
1406 return this._size > 0;
1407 }
1408 > } event.ts
1409 >
1410 > export interface EventDeliveryQueue {
1411 > _isEventDeliveryQueue: true;
1412 > }
1413 >
1414 > export const createEventDeliveryQueue = (): EventDeliveryQueue => new EventDeliveryQueuePrivate();
1415 >
1416 class EventDeliveryQueuePrivate implements EventDeliveryQueue {
1417 declare _isEventDeliveryQueue: true;
1426 */
1427 public end = 0;
1428 > event.ts
1429 > /**
1430 > * Emitter currently being dispatched on. Emitter._listeners is always an array.
1431 > */
1432 > public current?: Emitter<any>;
1433 > /**
1434 > * Currently emitting value. Defined whenever `current` is.
1435 > */
1436 > public value?: unknown;
1437 >
1438 > public enqueue<T>(emitter: Emitter<T>, value: T, end: number) {
1439 this.i = 0;
1440 this.end = end;
1442 this.value = value;
1443 }
1444 > event.ts
1445 > public reset() {
1446 this.i = this.end; // force any current emission loop to stop, mainly for during dispose
1447 this.current = undefined;
1448 this.value = undefined;
1449 }
1450 > } event.ts
1451 >
1452 > export interface IWaitUntil {
1453 > token: CancellationToken;
1454 > waitUntil(thenable: Promise<unknown>): void;
1455 > }
1456 >
1457 > export type IWaitUntilData<T> = Omit<Omit<T, 'waitUntil'>, 'token'>;
1458 >
1459 > export class AsyncEmitter<T extends IWaitUntil> extends Emitter<T> {
1460 >
1461 > private _asyncDeliveryQueue?: LinkedList<[(ev: T) => void, IWaitUntilData<T>]>;
1462 >
1463 > async fireAsync(data: IWaitUntilData<T>, token: CancellationToken, promiseJoin?: (p: Promise<unknown>, listener: Function) => Promise<unknown>): Promise<void> {
1464 if (!this._listeners) {
1465 return;
1512 }
1513 }
1514 > } event.ts
1515 >
1516 >
1517 > export class PauseableEmitter<T> extends Emitter<T> {
1518 >
1519 > private _isPaused = 0;
1520 > protected _eventQueue = new LinkedList<T>();
1521 > private _mergeFn?: (input: T[]) => T;
1522 >
1523 > public get isPaused(): boolean {
1524 > return this._isPaused !== 0;
1525 > }
1526 >
1527 > constructor(options?: EmitterOptions & { merge?: (input: T[]) => T }) {
1528 super(options);
1529 this._mergeFn = options?.merge;
1530 }
1531 > event.ts
1532 > pause(): void {
1533 this._isPaused++;
1534 }
1535 > event.ts
1536 > resume(): void {
1537 if (this._isPaused !== 0 && --this._isPaused === 0) {
1538 if (this._mergeFn) {
1554 }
1555 }
1556 > event.ts
1557 > override fire(event: T): void {
1558 if (this._size) {
1559 if (this._isPaused !== 0) {
1564 }
1565 }
1566 > } event.ts
1567 >
1568 > export class DebounceEmitter<T> extends PauseableEmitter<T> {
1569 >
1570 > private readonly _delay: number;
1571 > private _handle: Timeout | undefined;
1572 >
1573 > constructor(options: EmitterOptions & { merge: (input: T[]) => T; delay?: number }) {
1574 super(options);
1575 this._delay = options.delay ?? 100;
1576 }
1577 > event.ts
1578 > override fire(event: T): void {
1579 if (!this._handle) {
1580 this.pause();
1586 super.fire(event);
1587 }
1588 > } event.ts
1589 >
1590 > /**
1591 > * An emitter which queue all events and then process them at the
1592 > * end of the event loop.
1593 > */
1594 > export class MicrotaskEmitter<T> extends Emitter<T> {
1595 > private _queuedEvents: T[] = [];
1596 > private _mergeFn?: (input: T[]) => T;
1597 >
1598 > constructor(options?: EmitterOptions & { merge?: (input: T[]) => T }) {
1599 super(options);
1600 this._mergeFn = options?.merge;
1601 }
1602 > override fire(event: T): void { event.ts
1603
1604 if (!this.hasListeners()) {
1618 }
1619 }
1620 > } event.ts
1621 >
1622 > /**
1623 > * An event emitter that multiplexes many events into a single event.
1624 > *
1625 > * @example Listen to the `onData` event of all `Thing`s, dynamically adding and removing `Thing`s
1626 > * to the multiplexer as needed.
1627 > *
1628 > * ```typescript
1629 > * const anythingDataMultiplexer = new EventMultiplexer<{ data: string }>();
1630 > *
1631 > * const thingListeners = DisposableMap<Thing, IDisposable>();
1632 > *
1633 > * thingService.onDidAddThing(thing => {
1634 > * thingListeners.set(thing, anythingDataMultiplexer.add(thing.onData);
1635 > * });
1636 > * thingService.onDidRemoveThing(thing => {
1637 > * thingListeners.deleteAndDispose(thing);
1638 > * });
1639 > *
1640 > * anythingDataMultiplexer.event(e => {
1641 > * console.log('Something fired data ' + e.data)
1642 > * });
1643 > * ```
1644 > */
1645 > export class EventMultiplexer<T> implements IDisposable {
1646 >
1647 > private readonly emitter: Emitter<T>;
1648 > private hasListeners = false;
1649 > private events: { event: Event<T>; listener: IDisposable | null }[] = [];
1650 >
1651 > constructor() {
1652 this.emitter = new Emitter<T>({
1653 onWillAddFirstListener: () => this.onFirstListenerAdd(),
1655 });
1656 }
1657 > event.ts
1658 > get event(): Event<T> {
1659 return this.emitter.event;
1660 }
1661 > event.ts
1662 > add(event: Event<T>): IDisposable {
1663 const e = { event: event, listener: null };
1664 this.events.push(e);
1679 return toDisposable(createSingleCallFunction(dispose));
1680 }
1681 > event.ts
1682 > private onFirstListenerAdd(): void {
1683 this.hasListeners = true;
1684 this.events.forEach(e => this.hook(e));
1685 }
1686 > event.ts
1687 > private onLastListenerRemove(): void {
1688 this.hasListeners = false;
1689 this.events.forEach(e => this.unhook(e));
1690 }
1691 > event.ts
1692 > private hook(e: { event: Event<T>; listener: IDisposable | null }): void {
1693 e.listener = e.event(r => this.emitter.fire(r));
1694 }
1695 > event.ts
1696 > private unhook(e: { event: Event<T>; listener: IDisposable | null }): void {
1697 e.listener?.dispose();
1698 e.listener = null;
1699 }
1700 > event.ts
1701 > dispose(): void {
1702 this.emitter.dispose();
1703
1707 this.events = [];
1708 }
1709 > } event.ts
1710 >
1711 > export interface IDynamicListEventMultiplexer<TEventType> extends IDisposable {
1712 > readonly event: Event<TEventType>;
1713 > }
1714 > export class DynamicListEventMultiplexer<TItem, TEventType> implements IDynamicListEventMultiplexer<TEventType> {
1715 > private readonly _store = new DisposableStore();
1716 >
1717 > readonly event: Event<TEventType>;
1718 >
1719 > constructor(
1720 items: TItem[],
1721 onAddItem: Event<TItem>,
1747 this.event = multiplexer.event;
1748 }
1749 > event.ts
1750 > dispose() {
1751 this._store.dispose();
1752 }
1753 > } event.ts
1754 >
1755 > /**
1756 > * The EventBufferer is useful in situations in which you want
1757 > * to delay firing your events during some code.
1758 > * You can wrap that code and be sure that the event will not
1759 > * be fired during that wrap.
1760 > *
1761 > * ```
1762 > * const emitter: Emitter;
1763 > * const delayer = new EventDelayer();
1764 > * const delayedEvent = delayer.wrapEvent(emitter.event);
1765 > *
1766 > * delayedEvent(console.log);
1767 > *
1768 > * delayer.bufferEvents(() => {
1769 > * emitter.fire(); // event will not be fired yet
1770 > * });
1771 > *
1772 > * // event will only be fired at this point
1773 > * ```
1774 > */
1775 > export class EventBufferer {
1776
1777 private data: { buffers: Function[] }[] = [];
1778 > event.ts
1779 > wrapEvent<T>(event: Event<T>): Event<T>;
1780 > wrapEvent<T>(event: Event<T>, reduce: (last: T | undefined, event: T) => T): Event<T>;
1781 > wrapEvent<T, O>(event: Event<T>, reduce: (last: O | undefined, event: T) => O, initial: O): Event<O>;
1782 > wrapEvent<T, O>(event: Event<T>, reduce?: (last: T | O | undefined, event: T) => T | O, initial?: O): Event<O | T> {
1783 return (listener, thisArgs?, disposables?) => {
1784 return event(i => {
1832 };
1833 }
1834 > event.ts
1835 > bufferEvents<R = void>(fn: () => R): R {
1836 const data = { buffers: new Array<Function>() };
1837 this.data.push(data);
1841 return r;
1842 }
1843 > } event.ts
1844 >
1845 > /**
1846 > * A Relay is an event forwarder which functions as a replugabble event pipe.
1847 > * Once created, you can connect an input event to it and it will simply forward
1848 > * events from that input event through its own `event` property. The `input`
1849 > * can be changed at any point in time.
1850 > */
1851 > export class Relay<T> implements IDisposable {
1852
1853 private listening = false;
1867
1868 readonly event: Event<T> = this.emitter.event;
1869 > event.ts
1870 > set input(event: Event<T>) {
1871 this.inputEvent = event;
1872
1876 }
1877 }
1878 > event.ts
1879 > dispose() {
1880 this.inputEventListener.dispose();
1881 this.emitter.dispose();
1882 }
1883 > } event.ts
1884 >
1885 > export interface IValueWithChangeEvent<T> {
1886 > readonly onDidChange: Event<void>;
1887 > get value(): T;
1888 > }
1889 >
1890 > export class ValueWithChangeEvent<T> implements IValueWithChangeEvent<T> {
1891 > public static const<T>(value: T): IValueWithChangeEvent<T> {
1892 > return new ConstValueWithChangeEvent(value);
1893 > }
1894 >
1895 > private readonly _onDidChange = new Emitter<void>();
1896 > readonly onDidChange: Event<void> = this._onDidChange.event;
1897 >
1898 > constructor(private _value: T) { }
1899 >
1900 > get value(): T {
1901 return this._value;
1902 }
1903 > event.ts
1904 > set value(value: T) {
1905 if (value !== this._value) {
1906 this._value = value;
1908 }
1909 }
1910 > } event.ts
1911 >
1912 > class ConstValueWithChangeEvent<T> implements IValueWithChangeEvent<T> {
1913 > public readonly onDidChange: Event<void> = Event.None;
1914 >
1915 > constructor(readonly value: T) { }
1916 > }
1917 >
1918 > /**
1919 > * @param handleItem Is called for each item in the set (but only the first time the item is seen in the set).
1920 > * The returned disposable is disposed if the item is no longer in the set.
1921 > */
1922 > export function trackSetChanges<T>(getData: () => ReadonlySet<T>, onDidChangeData: Event<unknown>, handleItem: (d: T) => IDisposable): IDisposable {
1923 const map = new DisposableMap<T, IDisposable>();
1924 let oldData = new Set(getData());
1942 return store;
1943 }
1944 > event.ts
1945 >
1946 function addToDisposables(result: IDisposable, disposables: DisposableStore | IDisposable[] | undefined) {
1947 if (disposables instanceof DisposableStore) {
1951 }
1952 }
1953 > event.ts
1954 function disposeAndRemove(result: IDisposable, disposables: DisposableStore | IDisposable[] | undefined) {
1955 if (disposables instanceof DisposableStore) {
src/vs/platform/contextkey/common/contextkey.ts 832 covered LOC · 218 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- contextkey.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 { Event } from '../../../base/common/event.js';
8 > import { isChrome, isEdge, isFirefox, isLinux, isMacintosh, isSafari, isWeb, isWindows } from '../../../base/common/platform.js';
9 > import { isFalsyOrWhitespace } from '../../../base/common/strings.js';
10 > import { Scanner, LexingError, Token, TokenType } from './scanner.js';
11 > import { createDecorator } from '../../instantiation/common/instantiation.js';
12 > import { localize } from '../../../nls.js';
13 > import { IDisposable } from '../../../base/common/lifecycle.js';
14 > import { illegalArgument } from '../../../base/common/errors.js';
15 >
16 > const CONSTANT_VALUES = new Map<string, boolean>();
17 > CONSTANT_VALUES.set('false', false);
18 > CONSTANT_VALUES.set('true', true);
19 > CONSTANT_VALUES.set('isMac', isMacintosh);
20 > CONSTANT_VALUES.set('isLinux', isLinux);
21 > CONSTANT_VALUES.set('isWindows', isWindows);
22 > CONSTANT_VALUES.set('isWeb', isWeb);
23 > CONSTANT_VALUES.set('isMacNative', isMacintosh && !isWeb);
24 > CONSTANT_VALUES.set('isEdge', isEdge);
25 > CONSTANT_VALUES.set('isFirefox', isFirefox);
26 > CONSTANT_VALUES.set('isChrome', isChrome);
27 > CONSTANT_VALUES.set('isSafari', isSafari);
28 >
29 > /** allow register constant context keys that are known only after startup; requires running `substituteConstants` on the context key - https://github.com/microsoft/vscode/issues/174218#issuecomment-1437972127 */
30 > export function setConstant(key: string, value: boolean) {
31 if (CONSTANT_VALUES.get(key) !== undefined) { throw illegalArgument('contextkey.setConstant(k, v) invoked with already set constant `k`'); }
32
33 CONSTANT_VALUES.set(key, value);
34 }
36 > const hasOwnProperty = Object.prototype.hasOwnProperty;
37 >
38 > export const enum ContextKeyExprType {
39 > False = 0,
40 > True = 1,
41 > Defined = 2,
42 > Not = 3,
43 > Equals = 4,
44 > NotEquals = 5,
45 > And = 6,
46 > Regex = 7,
47 > NotRegex = 8,
48 > Or = 9,
49 > In = 10,
50 > NotIn = 11,
51 > Greater = 12,
52 > GreaterEquals = 13,
53 > Smaller = 14,
54 > SmallerEquals = 15,
55 > }
56 >
57 > export interface IContextKeyExprMapper {
58 > mapDefined(key: string): ContextKeyExpression;
59 > mapNot(key: string): ContextKeyExpression;
60 > mapEquals(key: string, value: any): ContextKeyExpression;
61 > mapNotEquals(key: string, value: any): ContextKeyExpression;
62 > mapGreater(key: string, value: any): ContextKeyExpression;
63 > mapGreaterEquals(key: string, value: any): ContextKeyExpression;
64 > mapSmaller(key: string, value: any): ContextKeyExpression;
65 > mapSmallerEquals(key: string, value: any): ContextKeyExpression;
66 > mapRegex(key: string, regexp: RegExp | null): ContextKeyRegexExpr;
67 > mapIn(key: string, valueKey: string): ContextKeyInExpr;
68 > mapNotIn(key: string, valueKey: string): ContextKeyNotInExpr;
69 > }
70 >
71 > export interface IContextKeyExpression {
72 > cmp(other: ContextKeyExpression): number;
73 > equals(other: ContextKeyExpression): boolean;
74 > substituteConstants(): ContextKeyExpression | undefined;
75 > evaluate(context: IContext): boolean;
76 > serialize(): string;
77 > keys(): string[];
78 > map(mapFnc: IContextKeyExprMapper): ContextKeyExpression;
79 > negate(): ContextKeyExpression;
80 >
81 > }
82 >
83 > export type ContextKeyExpression = (
84 > ContextKeyFalseExpr | ContextKeyTrueExpr | ContextKeyDefinedExpr | ContextKeyNotExpr
85 > | ContextKeyEqualsExpr | ContextKeyNotEqualsExpr | ContextKeyRegexExpr
86 > | ContextKeyNotRegexExpr | ContextKeyAndExpr | ContextKeyOrExpr | ContextKeyInExpr
87 > | ContextKeyNotInExpr | ContextKeyGreaterExpr | ContextKeyGreaterEqualsExpr
88 > | ContextKeySmallerExpr | ContextKeySmallerEqualsExpr
89 > );
90 >
91 >
92 > /*
93 >
94 > Syntax grammar:
95 >
96 > ```ebnf
97 >
98 > expression ::= or
99 >
100 > or ::= and { '||' and }*
101 >
102 > and ::= term { '&&' term }*
103 >
104 > term ::=
105 > | '!' (KEY | true | false | parenthesized)
106 > | primary
107 >
108 > primary ::=
109 > | 'true'
110 > | 'false'
111 > | parenthesized
112 > | KEY '=~' REGEX
113 > | KEY [ ('==' | '!=' | '<' | '<=' | '>' | '>=' | 'not' 'in' | 'in') value ]
114 >
115 > parenthesized ::=
116 > | '(' expression ')'
117 >
118 > value ::=
119 > | 'true'
120 > | 'false'
121 > | 'in' // we support `in` as a value because there's an extension that uses it, ie "when": "languageId == in"
122 > | VALUE // matched by the same regex as KEY; consider putting the value in single quotes if it's a string (e.g., with spaces)
123 > | SINGLE_QUOTED_STR
124 > | EMPTY_STR // this allows "when": "foo == " which's used by existing extensions
125 >
126 > ```
127 > */
128 >
129 > export type ParserConfig = {
130 > /**
131 > * with this option enabled, the parser can recover from regex parsing errors, e.g., unescaped slashes: `/src//` is accepted as `/src\//` would be
132 > */
133 > regexParsingWithErrorRecovery: boolean;
134 > };
135 >
136 > const defaultConfig: ParserConfig = {
137 > regexParsingWithErrorRecovery: true
138 > };
139 >
140 > export type ParsingError = {
141 > message: string;
142 > offset: number;
143 > lexeme: string;
144 > additionalInfo?: string;
145 > };
146 >
147 > const errorEmptyString = localize('contextkey.parser.error.emptyString', "Empty context key expression");
148 > const hintEmptyString = localize('contextkey.parser.error.emptyString.hint', "Did you forget to write an expression? You can also put 'false' or 'true' to always evaluate to false or true, respectively.");
149 > const errorNoInAfterNot = localize('contextkey.parser.error.noInAfterNot', "'in' after 'not'.");
150 > const errorClosingParenthesis = localize('contextkey.parser.error.closingParenthesis', "closing parenthesis ')'");
151 > const errorUnexpectedToken = localize('contextkey.parser.error.unexpectedToken', "Unexpected token");
152 > const hintUnexpectedToken = localize('contextkey.parser.error.unexpectedToken.hint', "Did you forget to put && or || before the token?");
153 > const errorUnexpectedEOF = localize('contextkey.parser.error.unexpectedEOF', "Unexpected end of expression");
154 > const hintUnexpectedEOF = localize('contextkey.parser.error.unexpectedEOF.hint', "Did you forget to put a context key?");
155 >
156 > /**
157 > * A parser for context key expressions.
158 > *
159 > * Example:
160 > * ```ts
161 > * const parser = new Parser();
162 > * const expr = parser.parse('foo == "bar" && baz == true');
163 > *
164 > * if (expr === undefined) {
165 > * // there were lexing or parsing errors
166 > * // process lexing errors with `parser.lexingErrors`
167 > * // process parsing errors with `parser.parsingErrors`
168 > * } else {
169 > * // expr is a valid expression
170 > * }
171 > * ```
172 > */
173 > export class Parser {
174 > // Note: this doesn't produce an exact syntax tree but a normalized one
175 > // ContextKeyExpression's that we use as AST nodes do not expose constructors that do not normalize
176 >
177 > private static _parseError = new Error();
178 >
179 > // lifetime note: `_scanner` lives as long as the parser does, i.e., is not reset between calls to `parse`
180 > private readonly _scanner = new Scanner();
181 >
182 > // lifetime note: `_tokens`, `_current`, and `_parsingErrors` must be reset between calls to `parse`
183 > private _tokens: Token[] = [];
184 > private _current = 0; // invariant: 0 <= this._current < this._tokens.length ; any incrementation of this value must first call `_isAtEnd`
185 > private _parsingErrors: ParsingError[] = [];
186 >
187 > get lexingErrors(): Readonly<LexingError[]> {
188 return this._scanner.errors;
189 }
191 > get parsingErrors(): Readonly<ParsingError[]> {
192 return this._parsingErrors;
193 }
195 > constructor(private readonly _config: ParserConfig = defaultConfig) {
196 > }
197 >
198 > /**
199 > * Parse a context key expression.
200 > *
201 > * @param input the expression to parse
202 > * @returns the parsed expression or `undefined` if there's an error - call `lexingErrors` and `parsingErrors` to see the errors
203 > */
204 > parse(input: string): ContextKeyExpression | undefined {
205
206 if (input === '') {
231 }
232 }
234 > private _expr(): ContextKeyExpression | undefined {
235 return this._or();
236 }
238 > private _or(): ContextKeyExpression | undefined {
239 const expr = [this._and()];
240
246 return expr.length === 1 ? expr[0] : ContextKeyExpr.or(...expr);
247 }
249 > private _and(): ContextKeyExpression | undefined {
250 const expr = [this._term()];
251
257 return expr.length === 1 ? expr[0] : ContextKeyExpr.and(...expr);
258 }
260 > private _term(): ContextKeyExpression | undefined {
261 if (this._matchOne(TokenType.Neg)) {
262 const peek = this._peek();
283 return this._primary();
284 }
286 > private _primary(): ContextKeyExpression | undefined {
287
288 const peek = this._peek();
498 }
499 }
501 > private _value(): string {
502 const token = this._peek();
503 switch (token.type) {
521 }
522 }
524 > private _flagsGYRe = /g|y/g;
525 > private _removeFlagsGY(flags: string): string {
526 return flags.replaceAll(this._flagsGYRe, '');
527 }
529 > // careful: this can throw if current token is the initial one (ie index = 0)
530 > private _previous() {
531 return this._tokens[this._current - 1];
532 }
534 > private _matchOne(token: TokenType) {
535 if (this._check(token)) {
536 this._advance();
540 return false;
541 }
543 > private _advance() {
544 if (!this._isAtEnd()) {
545 this._current++;
547 return this._previous();
548 }
550 > private _consume(type: TokenType, message: string) {
551 if (this._check(type)) {
552 return this._advance();
555 throw this._errExpectedButGot(message, this._peek());
556 }
558 > private _errExpectedButGot(expected: string, got: Token, additionalInfo?: string) {
559 const message = localize('contextkey.parser.error.expectedButGot', "Expected: {0}\nReceived: '{1}'.", expected, Scanner.getLexeme(got));
560 const offset = got.offset;
563 return Parser._parseError;
564 }
566 > private _check(type: TokenType) {
567 return this._peek().type === type;
568 }
570 > private _peek() {
571 return this._tokens[this._current];
572 }
574 > private _isAtEnd() {
575 return this._peek().type === TokenType.EOF;
576 }
577 > } contextkey.ts
578 >
579 > export abstract class ContextKeyExpr {
580 >
581 > public static false(): ContextKeyExpression {
582 return ContextKeyFalseExpr.INSTANCE;
583 }
584 > public static true(): ContextKeyExpression { contextkey.ts
585 return ContextKeyTrueExpr.INSTANCE;
586 }
587 > public static has(key: string): ContextKeyExpression { contextkey.ts
588 return ContextKeyDefinedExpr.create(key);
589 }
590 > public static equals(key: string, value: any): ContextKeyExpression { contextkey.ts
591 return ContextKeyEqualsExpr.create(key, value);
592 }
593 > public static notEquals(key: string, value: any): ContextKeyExpression { contextkey.ts
594 return ContextKeyNotEqualsExpr.create(key, value);
595 }
596 > public static regex(key: string, value: RegExp): ContextKeyExpression { contextkey.ts
597 return ContextKeyRegexExpr.create(key, value);
598 }
599 > public static in(key: string, value: string): ContextKeyExpression { contextkey.ts
600 return ContextKeyInExpr.create(key, value);
601 }
602 > public static notIn(key: string, value: string): ContextKeyExpression { contextkey.ts
603 return ContextKeyNotInExpr.create(key, value);
604 }
605 > public static not(key: string): ContextKeyExpression { contextkey.ts
606 return ContextKeyNotExpr.create(key);
607 }
608 > public static and(...expr: Array<ContextKeyExpression | undefined | null>): ContextKeyExpression | undefined { contextkey.ts
609 return ContextKeyAndExpr.create(expr, null, true);
610 }
611 > public static or(...expr: Array<ContextKeyExpression | undefined | null>): ContextKeyExpression | undefined { contextkey.ts
612 return ContextKeyOrExpr.create(expr, null, true);
613 }
614 > public static greater(key: string, value: number): ContextKeyExpression { contextkey.ts
615 return ContextKeyGreaterExpr.create(key, value);
616 }
617 > public static greaterEquals(key: string, value: number): ContextKeyExpression { contextkey.ts
618 return ContextKeyGreaterEqualsExpr.create(key, value);
619 }
620 > public static smaller(key: string, value: number): ContextKeyExpression { contextkey.ts
621 return ContextKeySmallerExpr.create(key, value);
622 }
623 > public static smallerEquals(key: string, value: number): ContextKeyExpression { contextkey.ts
624 return ContextKeySmallerEqualsExpr.create(key, value);
625 }
627 > private static _parser = new Parser({ regexParsingWithErrorRecovery: false });
628 > public static deserialize(serialized: string | null | undefined): ContextKeyExpression | undefined {
629 if (serialized === undefined || serialized === null) { // an empty string needs to be handled by the parser to get a corresponding parsing error reported
630 return undefined;
634 return expr;
635 }
637 > }
638 >
639 >
640 > export function validateWhenClauses(whenClauses: string[]): any {
641
642 const parser = new Parser({ regexParsingWithErrorRecovery: false }); // we run with no recovery to guide users to use correct regexes
664 });
665 }
667 > export function expressionsAreEqualWithConstantSubstitution(a: ContextKeyExpression | null | undefined, b: ContextKeyExpression | null | undefined): boolean {
668 const aExpr = a ? a.substituteConstants() : undefined;
669 const bExpr = b ? b.substituteConstants() : undefined;
676 return aExpr.equals(bExpr);
677 }
679 function cmp(a: ContextKeyExpression, b: ContextKeyExpression): number {
680 return a.cmp(b);
681 }
683 > export class ContextKeyFalseExpr implements IContextKeyExpression {
684 > public static INSTANCE = new ContextKeyFalseExpr();
685 >
686 > public readonly type = ContextKeyExprType.False;
687 >
688 > protected constructor() {
689 > }
690 >
691 > public cmp(other: ContextKeyExpression): number {
692 return this.type - other.type;
693 }
695 > public equals(other: ContextKeyExpression): boolean {
696 return (other.type === this.type);
697 }
699 > public substituteConstants(): ContextKeyExpression | undefined {
700 return this;
701 }
703 > public evaluate(context: IContext): boolean {
704 return false;
705 }
707 > public serialize(): string {
708 return 'false';
709 }
711 > public keys(): string[] {
712 return [];
713 }
715 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
716 return this;
717 }
719 > public negate(): ContextKeyExpression {
720 return ContextKeyTrueExpr.INSTANCE;
721 }
722 > } contextkey.ts
723 >
724 > export class ContextKeyTrueExpr implements IContextKeyExpression {
725 > public static INSTANCE = new ContextKeyTrueExpr();
726 >
727 > public readonly type = ContextKeyExprType.True;
728 >
729 > protected constructor() {
730 > }
731 >
732 > public cmp(other: ContextKeyExpression): number {
733 return this.type - other.type;
734 }
736 > public equals(other: ContextKeyExpression): boolean {
737 return (other.type === this.type);
738 }
740 > public substituteConstants(): ContextKeyExpression | undefined {
741 return this;
742 }
744 > public evaluate(context: IContext): boolean {
745 return true;
746 }
748 > public serialize(): string {
749 return 'true';
750 }
752 > public keys(): string[] {
753 return [];
754 }
756 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
757 return this;
758 }
760 > public negate(): ContextKeyExpression {
761 return ContextKeyFalseExpr.INSTANCE;
762 }
763 > } contextkey.ts
764 >
765 > export class ContextKeyDefinedExpr implements IContextKeyExpression {
766 > public static create(key: string, negated: ContextKeyExpression | null = null): ContextKeyExpression {
767 > const constantValue = CONSTANT_VALUES.get(key);
768 > if (typeof constantValue === 'boolean') {
769 > return constantValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE; contextkey.ts
770 > }
771 > return new ContextKeyDefinedExpr(key, negated); contextkey.ts
772 > }
773 >
774 > public readonly type = ContextKeyExprType.Defined;
775 >
776 > protected constructor(
777 > readonly key: string, contextkey.ts
778 > private negated: ContextKeyExpression | null
779 > ) {
780 > }
782 > public cmp(other: ContextKeyExpression): number {
783 if (other.type !== this.type) {
784 return this.type - other.type;
786 return cmp1(this.key, other.key);
787 }
789 > public equals(other: ContextKeyExpression): boolean {
790 if (other.type === this.type) {
791 return (this.key === other.key);
793 return false;
794 }
796 > public substituteConstants(): ContextKeyExpression | undefined {
797 const constantValue = CONSTANT_VALUES.get(this.key);
798 if (typeof constantValue === 'boolean') {
801 return this;
802 }
804 > public evaluate(context: IContext): boolean {
805 return (!!context.getValue(this.key));
806 }
808 > public serialize(): string {
809 return this.key;
810 }
812 > public keys(): string[] {
813 return [this.key];
814 }
816 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
817 return mapFnc.mapDefined(this.key);
818 }
820 > public negate(): ContextKeyExpression {
821 if (!this.negated) {
822 this.negated = ContextKeyNotExpr.create(this.key, this);
824 return this.negated;
825 }
826 > } contextkey.ts
827 >
828 > export class ContextKeyEqualsExpr implements IContextKeyExpression {
829 >
830 > public static create(key: string, value: any, negated: ContextKeyExpression | null = null): ContextKeyExpression {
831 > if (typeof value === 'boolean') {
832 > return (value ? ContextKeyDefinedExpr.create(key, negated) : ContextKeyNotExpr.create(key, negated)); contextkey.ts
833 > }
834 > const constantValue = CONSTANT_VALUES.get(key); contextkey.ts
835 > if (typeof constantValue === 'boolean') {
836 > const trueValue = constantValue ? 'true' : 'false'; contextkey.ts
837 > return (value === trueValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE);
838 > }
839 > return new ContextKeyEqualsExpr(key, value, negated); contextkey.ts
840 > } contextkey.ts
841 >
842 > public readonly type = ContextKeyExprType.Equals;
843 >
844 > private constructor(
845 private readonly key: string,
846 private readonly value: any,
848 ) {
849 }
851 > public cmp(other: ContextKeyExpression): number {
852 if (other.type !== this.type) {
853 return this.type - other.type;
855 return cmp2(this.key, this.value, other.key, other.value);
856 }
858 > public equals(other: ContextKeyExpression): boolean {
859 if (other.type === this.type) {
860 return (this.key === other.key && this.value === other.value);
862 return false;
863 }
865 > public substituteConstants(): ContextKeyExpression | undefined {
866 const constantValue = CONSTANT_VALUES.get(this.key);
867 if (typeof constantValue === 'boolean') {
871 return this;
872 }
874 > public evaluate(context: IContext): boolean {
875 // Intentional ==
876 // eslint-disable-next-line eqeqeq
877 return (context.getValue(this.key) == this.value);
878 }
880 > public serialize(): string {
881 return `${this.key} == '${this.value}'`;
882 }
884 > public keys(): string[] {
885 return [this.key];
886 }
888 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
889 return mapFnc.mapEquals(this.key, this.value);
890 }
892 > public negate(): ContextKeyExpression {
893 if (!this.negated) {
894 this.negated = ContextKeyNotEqualsExpr.create(this.key, this.value, this);
896 return this.negated;
897 }
898 > } contextkey.ts
899 >
900 > export class ContextKeyInExpr implements IContextKeyExpression {
901 >
902 > public static create(key: string, valueKey: string): ContextKeyInExpr {
903 > return new ContextKeyInExpr(key, valueKey);
904 > }
905 >
906 > public readonly type = ContextKeyExprType.In;
907 > private negated: ContextKeyExpression | null = null;
908 >
909 > private constructor(
910 private readonly key: string,
911 private readonly valueKey: string,
912 ) {
913 }
915 > public cmp(other: ContextKeyExpression): number {
916 if (other.type !== this.type) {
917 return this.type - other.type;
919 return cmp2(this.key, this.valueKey, other.key, other.valueKey);
920 }
922 > public equals(other: ContextKeyExpression): boolean {
923 if (other.type === this.type) {
924 return (this.key === other.key && this.valueKey === other.valueKey);
926 return false;
927 }
929 > public substituteConstants(): ContextKeyExpression | undefined {
930 return this;
931 }
933 > public evaluate(context: IContext): boolean {
934 const source = context.getValue(this.valueKey);
935
964 return false;
965 }
967 > public serialize(): string {
968 return `${this.key} in '${this.valueKey}'`;
969 }
971 > public keys(): string[] {
972 return [this.key, this.valueKey];
973 }
975 > public map(mapFnc: IContextKeyExprMapper): ContextKeyInExpr {
976 return mapFnc.mapIn(this.key, this.valueKey);
977 }
979 > public negate(): ContextKeyExpression {
980 if (!this.negated) {
981 this.negated = ContextKeyNotInExpr.create(this.key, this.valueKey);
983 return this.negated;
984 }
985 > } contextkey.ts
986 >
987 > export class ContextKeyNotInExpr implements IContextKeyExpression {
988 >
989 > public static create(key: string, valueKey: string): ContextKeyNotInExpr {
990 > return new ContextKeyNotInExpr(key, valueKey);
991 > }
992 >
993 > public readonly type = ContextKeyExprType.NotIn;
994 >
995 > private readonly _negated: ContextKeyInExpr;
996 >
997 > private constructor(
998 private readonly key: string,
999 private readonly valueKey: string,
1001 this._negated = ContextKeyInExpr.create(key, valueKey);
1002 }
1003 > contextkey.ts
1004 > public cmp(other: ContextKeyExpression): number {
1005 if (other.type !== this.type) {
1006 return this.type - other.type;
1008 return this._negated.cmp(other._negated);
1009 }
1010 > contextkey.ts
1011 > public equals(other: ContextKeyExpression): boolean {
1012 if (other.type === this.type) {
1013 return this._negated.equals(other._negated);
1015 return false;
1016 }
1017 > contextkey.ts
1018 > public substituteConstants(): ContextKeyExpression | undefined {
1019 return this;
1020 }
1021 > contextkey.ts
1022 > public evaluate(context: IContext): boolean {
1023 return !this._negated.evaluate(context);
1024 }
1025 > contextkey.ts
1026 > public serialize(): string {
1027 return `${this.key} not in '${this.valueKey}'`;
1028 }
1029 > contextkey.ts
1030 > public keys(): string[] {
1031 return this._negated.keys();
1032 }
1033 > contextkey.ts
1034 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
1035 return mapFnc.mapNotIn(this.key, this.valueKey);
1036 }
1037 > contextkey.ts
1038 > public negate(): ContextKeyExpression {
1039 return this._negated;
1040 }
1041 > } contextkey.ts
1042 >
1043 > export class ContextKeyNotEqualsExpr implements IContextKeyExpression {
1044 >
1045 > public static create(key: string, value: any, negated: ContextKeyExpression | null = null): ContextKeyExpression {
1046 > if (typeof value === 'boolean') {
1047 > if (value) { contextkey.ts
1048 > return ContextKeyNotExpr.create(key, negated); contextkey.ts
1049 > }
1050 > return ContextKeyDefinedExpr.create(key, negated); contextkey.ts
1051 > }
1052 > const constantValue = CONSTANT_VALUES.get(key); contextkey.ts
1053 > if (typeof constantValue === 'boolean') {
1054 > const falseValue = constantValue ? 'true' : 'false'; contextkey.ts
1055 > return (value === falseValue ? ContextKeyFalseExpr.INSTANCE : ContextKeyTrueExpr.INSTANCE);
1056 > }
1057 > return new ContextKeyNotEqualsExpr(key, value, negated); contextkey.ts
1058 > } contextkey.ts
1059 >
1060 > public readonly type = ContextKeyExprType.NotEquals;
1061 >
1062 > private constructor(
1063 private readonly key: string,
1064 private readonly value: any,
1066 ) {
1067 }
1068 > contextkey.ts
1069 > public cmp(other: ContextKeyExpression): number {
1070 if (other.type !== this.type) {
1071 return this.type - other.type;
1073 return cmp2(this.key, this.value, other.key, other.value);
1074 }
1075 > contextkey.ts
1076 > public equals(other: ContextKeyExpression): boolean {
1077 if (other.type === this.type) {
1078 return (this.key === other.key && this.value === other.value);
1080 return false;
1081 }
1082 > contextkey.ts
1083 > public substituteConstants(): ContextKeyExpression | undefined {
1084 const constantValue = CONSTANT_VALUES.get(this.key);
1085 if (typeof constantValue === 'boolean') {
1089 return this;
1090 }
1091 > contextkey.ts
1092 > public evaluate(context: IContext): boolean {
1093 // Intentional !=
1094 // eslint-disable-next-line eqeqeq
1095 return (context.getValue(this.key) != this.value);
1096 }
1097 > contextkey.ts
1098 > public serialize(): string {
1099 return `${this.key} != '${this.value}'`;
1100 }
1101 > contextkey.ts
1102 > public keys(): string[] {
1103 return [this.key];
1104 }
1105 > contextkey.ts
1106 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
1107 return mapFnc.mapNotEquals(this.key, this.value);
1108 }
1109 > contextkey.ts
1110 > public negate(): ContextKeyExpression {
1111 if (!this.negated) {
1112 this.negated = ContextKeyEqualsExpr.create(this.key, this.value, this);
1114 return this.negated;
1115 }
1116 > } contextkey.ts
1117 >
1118 > export class ContextKeyNotExpr implements IContextKeyExpression {
1119 >
1120 > public static create(key: string, negated: ContextKeyExpression | null = null): ContextKeyExpression {
1121 > const constantValue = CONSTANT_VALUES.get(key);
1122 > if (typeof constantValue === 'boolean') {
1123 > return (constantValue ? ContextKeyFalseExpr.INSTANCE : ContextKeyTrueExpr.INSTANCE); contextkey.ts
1124 > }
1125 > return new ContextKeyNotExpr(key, negated); contextkey.ts
1126 > }
1127 >
1128 > public readonly type = ContextKeyExprType.Not;
1129 >
1130 > private constructor(
1131 private readonly key: string,
1132 private negated: ContextKeyExpression | null
1133 ) {
1134 }
1135 > contextkey.ts
1136 > public cmp(other: ContextKeyExpression): number {
1137 if (other.type !== this.type) {
1138 return this.type - other.type;
1140 return cmp1(this.key, other.key);
1141 }
1142 > contextkey.ts
1143 > public equals(other: ContextKeyExpression): boolean {
1144 if (other.type === this.type) {
1145 return (this.key === other.key);
1147 return false;
1148 }
1149 > contextkey.ts
1150 > public substituteConstants(): ContextKeyExpression | undefined {
1151 const constantValue = CONSTANT_VALUES.get(this.key);
1152 if (typeof constantValue === 'boolean') {
1155 return this;
1156 }
1157 > contextkey.ts
1158 > public evaluate(context: IContext): boolean {
1159 return (!context.getValue(this.key));
1160 }
1161 > contextkey.ts
1162 > public serialize(): string {
1163 return `!${this.key}`;
1164 }
1165 > contextkey.ts
1166 > public keys(): string[] {
1167 return [this.key];
1168 }
1169 > contextkey.ts
1170 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
1171 return mapFnc.mapNot(this.key);
1172 }
1173 > contextkey.ts
1174 > public negate(): ContextKeyExpression {
1175 if (!this.negated) {
1176 this.negated = ContextKeyDefinedExpr.create(this.key, this);
1178 return this.negated;
1179 }
1180 > } contextkey.ts
1181 >
1182 function withFloatOrStr<T extends ContextKeyExpression>(value: any, callback: (value: number | string) => T): T | ContextKeyFalseExpr {
1183 if (typeof value === 'string') {
1192 return ContextKeyFalseExpr.INSTANCE;
1193 }
1194 > contextkey.ts
1195 > export class ContextKeyGreaterExpr implements IContextKeyExpression {
1196 >
1197 > public static create(key: string, _value: any, negated: ContextKeyExpression | null = null): ContextKeyExpression {
1198 > return withFloatOrStr(_value, (value) => new ContextKeyGreaterExpr(key, value, negated));
1199 > }
1200 >
1201 > public readonly type = ContextKeyExprType.Greater;
1202 >
1203 > private constructor(
1204 private readonly key: string,
1205 private readonly value: number | string,
1206 private negated: ContextKeyExpression | null
1207 ) { }
1208 > contextkey.ts
1209 > public cmp(other: ContextKeyExpression): number {
1210 if (other.type !== this.type) {
1211 return this.type - other.type;
1213 return cmp2(this.key, this.value, other.key, other.value);
1214 }
1215 > contextkey.ts
1216 > public equals(other: ContextKeyExpression): boolean {
1217 if (other.type === this.type) {
1218 return (this.key === other.key && this.value === other.value);
1220 return false;
1221 }
1222 > contextkey.ts
1223 > public substituteConstants(): ContextKeyExpression | undefined {
1224 return this;
1225 }
1226 > contextkey.ts
1227 > public evaluate(context: IContext): boolean {
1228 if (typeof this.value === 'string') {
1229 return false;
1231 return (parseFloat(context.getValue<any>(this.key)) > this.value);
1232 }
1233 > contextkey.ts
1234 > public serialize(): string {
1235 return `${this.key} > ${this.value}`;
1236 }
1237 > contextkey.ts
1238 > public keys(): string[] {
1239 return [this.key];
1240 }
1241 > contextkey.ts
1242 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
1243 return mapFnc.mapGreater(this.key, this.value);
1244 }
1245 > contextkey.ts
1246 > public negate(): ContextKeyExpression {
1247 if (!this.negated) {
1248 this.negated = ContextKeySmallerEqualsExpr.create(this.key, this.value, this);
1250 return this.negated;
1251 }
1252 > } contextkey.ts
1253 >
1254 > export class ContextKeyGreaterEqualsExpr implements IContextKeyExpression {
1255 >
1256 > public static create(key: string, _value: any, negated: ContextKeyExpression | null = null): ContextKeyExpression {
1257 > return withFloatOrStr(_value, (value) => new ContextKeyGreaterEqualsExpr(key, value, negated));
1258 > }
1259 >
1260 > public readonly type = ContextKeyExprType.GreaterEquals;
1261 >
1262 > private constructor(
1263 private readonly key: string,
1264 private readonly value: number | string,
1265 private negated: ContextKeyExpression | null
1266 ) { }
1267 > contextkey.ts
1268 > public cmp(other: ContextKeyExpression): number {
1269 if (other.type !== this.type) {
1270 return this.type - other.type;
1272 return cmp2(this.key, this.value, other.key, other.value);
1273 }
1274 > contextkey.ts
1275 > public equals(other: ContextKeyExpression): boolean {
1276 if (other.type === this.type) {
1277 return (this.key === other.key && this.value === other.value);
1279 return false;
1280 }
1281 > contextkey.ts
1282 > public substituteConstants(): ContextKeyExpression | undefined {
1283 return this;
1284 }
1285 > contextkey.ts
1286 > public evaluate(context: IContext): boolean {
1287 if (typeof this.value === 'string') {
1288 return false;
1290 return (parseFloat(context.getValue<any>(this.key)) >= this.value);
1291 }
1292 > contextkey.ts
1293 > public serialize(): string {
1294 return `${this.key} >= ${this.value}`;
1295 }
1296 > contextkey.ts
1297 > public keys(): string[] {
1298 return [this.key];
1299 }
1300 > contextkey.ts
1301 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
1302 return mapFnc.mapGreaterEquals(this.key, this.value);
1303 }
1304 > contextkey.ts
1305 > public negate(): ContextKeyExpression {
1306 if (!this.negated) {
1307 this.negated = ContextKeySmallerExpr.create(this.key, this.value, this);
1309 return this.negated;
1310 }
1311 > } contextkey.ts
1312 >
1313 > export class ContextKeySmallerExpr implements IContextKeyExpression {
1314 >
1315 > public static create(key: string, _value: any, negated: ContextKeyExpression | null = null): ContextKeyExpression {
1316 > return withFloatOrStr(_value, (value) => new ContextKeySmallerExpr(key, value, negated));
1317 > }
1318 >
1319 > public readonly type = ContextKeyExprType.Smaller;
1320 >
1321 > private constructor(
1322 private readonly key: string,
1323 private readonly value: number | string,
1325 ) {
1326 }
1327 > contextkey.ts
1328 > public cmp(other: ContextKeyExpression): number {
1329 if (other.type !== this.type) {
1330 return this.type - other.type;
1332 return cmp2(this.key, this.value, other.key, other.value);
1333 }
1334 > contextkey.ts
1335 > public equals(other: ContextKeyExpression): boolean {
1336 if (other.type === this.type) {
1337 return (this.key === other.key && this.value === other.value);
1339 return false;
1340 }
1341 > contextkey.ts
1342 > public substituteConstants(): ContextKeyExpression | undefined {
1343 return this;
1344 }
1345 > contextkey.ts
1346 > public evaluate(context: IContext): boolean {
1347 if (typeof this.value === 'string') {
1348 return false;
1350 return (parseFloat(context.getValue<any>(this.key)) < this.value);
1351 }
1352 > contextkey.ts
1353 > public serialize(): string {
1354 return `${this.key} < ${this.value}`;
1355 }
1356 > contextkey.ts
1357 > public keys(): string[] {
1358 return [this.key];
1359 }
1360 > contextkey.ts
1361 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
1362 return mapFnc.mapSmaller(this.key, this.value);
1363 }
1364 > contextkey.ts
1365 > public negate(): ContextKeyExpression {
1366 if (!this.negated) {
1367 this.negated = ContextKeyGreaterEqualsExpr.create(this.key, this.value, this);
1369 return this.negated;
1370 }
1371 > } contextkey.ts
1372 >
1373 > export class ContextKeySmallerEqualsExpr implements IContextKeyExpression {
1374 >
1375 > public static create(key: string, _value: any, negated: ContextKeyExpression | null = null): ContextKeyExpression {
1376 > return withFloatOrStr(_value, (value) => new ContextKeySmallerEqualsExpr(key, value, negated));
1377 > }
1378 >
1379 > public readonly type = ContextKeyExprType.SmallerEquals;
1380 >
1381 > private constructor(
1382 private readonly key: string,
1383 private readonly value: number | string,
1385 ) {
1386 }
1387 > contextkey.ts
1388 > public cmp(other: ContextKeyExpression): number {
1389 if (other.type !== this.type) {
1390 return this.type - other.type;
1392 return cmp2(this.key, this.value, other.key, other.value);
1393 }
1394 > contextkey.ts
1395 > public equals(other: ContextKeyExpression): boolean {
1396 if (other.type === this.type) {
1397 return (this.key === other.key && this.value === other.value);
1399 return false;
1400 }
1401 > contextkey.ts
1402 > public substituteConstants(): ContextKeyExpression | undefined {
1403 return this;
1404 }
1405 > contextkey.ts
1406 > public evaluate(context: IContext): boolean {
1407 if (typeof this.value === 'string') {
1408 return false;
1410 return (parseFloat(context.getValue<any>(this.key)) <= this.value);
1411 }
1412 > contextkey.ts
1413 > public serialize(): string {
1414 return `${this.key} <= ${this.value}`;
1415 }
1416 > contextkey.ts
1417 > public keys(): string[] {
1418 return [this.key];
1419 }
1420 > contextkey.ts
1421 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
1422 return mapFnc.mapSmallerEquals(this.key, this.value);
1423 }
1424 > contextkey.ts
1425 > public negate(): ContextKeyExpression {
1426 if (!this.negated) {
1427 this.negated = ContextKeyGreaterExpr.create(this.key, this.value, this);
1429 return this.negated;
1430 }
1431 > } contextkey.ts
1432 >
1433 > export class ContextKeyRegexExpr implements IContextKeyExpression {
1434 >
1435 > public static create(key: string, regexp: RegExp | null): ContextKeyRegexExpr {
1436 > return new ContextKeyRegexExpr(key, regexp);
1437 > }
1438 >
1439 > public readonly type = ContextKeyExprType.Regex;
1440 > private negated: ContextKeyExpression | null = null;
1441 >
1442 > private constructor(
1443 private readonly key: string,
1444 private readonly regexp: RegExp | null
1446 //
1447 }
1448 > contextkey.ts
1449 > public cmp(other: ContextKeyExpression): number {
1450 if (other.type !== this.type) {
1451 return this.type - other.type;
1467 return 0;
1468 }
1469 > contextkey.ts
1470 > public equals(other: ContextKeyExpression): boolean {
1471 if (other.type === this.type) {
1472 const thisSource = this.regexp ? this.regexp.source : '';
1476 return false;
1477 }
1478 > contextkey.ts
1479 > public substituteConstants(): ContextKeyExpression | undefined {
1480 return this;
1481 }
1482 > contextkey.ts
1483 > public evaluate(context: IContext): boolean {
1484 const value = context.getValue<any>(this.key);
1485 return this.regexp ? this.regexp.test(value) : false;
1486 }
1487 > contextkey.ts
1488 > public serialize(): string {
1489 const value = this.regexp
1490 ? `/${this.regexp.source}/${this.regexp.flags}`
1492 return `${this.key} =~ ${value}`;
1493 }
1494 > contextkey.ts
1495 > public keys(): string[] {
1496 return [this.key];
1497 }
1498 > contextkey.ts
1499 > public map(mapFnc: IContextKeyExprMapper): ContextKeyRegexExpr {
1500 return mapFnc.mapRegex(this.key, this.regexp);
1501 }
1502 > contextkey.ts
1503 > public negate(): ContextKeyExpression {
1504 if (!this.negated) {
1505 this.negated = ContextKeyNotRegexExpr.create(this);
1507 return this.negated;
1508 }
1509 > } contextkey.ts
1510 >
1511 > export class ContextKeyNotRegexExpr implements IContextKeyExpression {
1512 >
1513 > public static create(actual: ContextKeyRegexExpr): ContextKeyExpression {
1514 > return new ContextKeyNotRegexExpr(actual);
1515 > }
1516 >
1517 > public readonly type = ContextKeyExprType.NotRegex;
1518 >
1519 > private constructor(private readonly _actual: ContextKeyRegexExpr) {
1520 //
1521 }
1522 > contextkey.ts
1523 > public cmp(other: ContextKeyExpression): number {
1524 if (other.type !== this.type) {
1525 return this.type - other.type;
1527 return this._actual.cmp(other._actual);
1528 }
1529 > contextkey.ts
1530 > public equals(other: ContextKeyExpression): boolean {
1531 if (other.type === this.type) {
1532 return this._actual.equals(other._actual);
1534 return false;
1535 }
1536 > contextkey.ts
1537 > public substituteConstants(): ContextKeyExpression | undefined {
1538 return this;
1539 }
1540 > contextkey.ts
1541 > public evaluate(context: IContext): boolean {
1542 return !this._actual.evaluate(context);
1543 }
1544 > contextkey.ts
1545 > public serialize(): string {
1546 return `!(${this._actual.serialize()})`;
1547 }
1548 > contextkey.ts
1549 > public keys(): string[] {
1550 return this._actual.keys();
1551 }
1552 > contextkey.ts
1553 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
1554 return new ContextKeyNotRegexExpr(this._actual.map(mapFnc));
1555 }
1556 > contextkey.ts
1557 > public negate(): ContextKeyExpression {
1558 return this._actual;
1559 }
1560 > } contextkey.ts
1561 >
1562 > /**
1563 > * @returns the same instance if nothing changed.
1564 > */
1565 function eliminateConstantsInArray(arr: ContextKeyExpression[]): (ContextKeyExpression | undefined)[] {
1566 // Allocate array only if there is a difference
1591 return newArr;
1592 }
1593 > contextkey.ts
1594 > export class ContextKeyAndExpr implements IContextKeyExpression {
1595 >
1596 > public static create(_expr: ReadonlyArray<ContextKeyExpression | null | undefined>, negated: ContextKeyExpression | null, extraRedundantCheck: boolean): ContextKeyExpression | undefined {
1597 > return ContextKeyAndExpr._normalizeArr(_expr, negated, extraRedundantCheck);
1598 > }
1599 >
1600 > public readonly type = ContextKeyExprType.And;
1601 >
1602 > private constructor(
1603 public readonly expr: ContextKeyExpression[],
1604 private negated: ContextKeyExpression | null
1605 ) {
1606 }
1607 > contextkey.ts
1608 > public cmp(other: ContextKeyExpression): number {
1609 if (other.type !== this.type) {
1610 return this.type - other.type;
1624 return 0;
1625 }
1626 > contextkey.ts
1627 > public equals(other: ContextKeyExpression): boolean {
1628 if (other.type === this.type) {
1629 if (this.expr.length !== other.expr.length) {
1639 return false;
1640 }
1641 > contextkey.ts
1642 > public substituteConstants(): ContextKeyExpression | undefined {
1643 const exprArr = eliminateConstantsInArray(this.expr);
1644 if (exprArr === this.expr) {
1648 return ContextKeyAndExpr.create(exprArr, this.negated, false);
1649 }
1650 > contextkey.ts
1651 > public evaluate(context: IContext): boolean {
1652 for (let i = 0, len = this.expr.length; i < len; i++) {
1653 if (!this.expr[i].evaluate(context)) {
1657 return true;
1658 }
1659 > contextkey.ts
1660 > private static _normalizeArr(arr: ReadonlyArray<ContextKeyExpression | null | undefined>, negated: ContextKeyExpression | null, extraRedundantCheck: boolean): ContextKeyExpression | undefined {
1661 const expr: ContextKeyExpression[] = [];
1662 let hasTrue = false;
1762 return new ContextKeyAndExpr(expr, negated);
1763 }
1764 > contextkey.ts
1765 > public serialize(): string {
1766 return this.expr.map(e => e.serialize()).join(' && ');
1767 }
1768 > contextkey.ts
1769 > public keys(): string[] {
1770 const result: string[] = [];
1771 for (const expr of this.expr) {
1774 return result;
1775 }
1776 > contextkey.ts
1777 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
1778 return new ContextKeyAndExpr(this.expr.map(expr => expr.map(mapFnc)), null);
1779 }
1780 > contextkey.ts
1781 > public negate(): ContextKeyExpression {
1782 if (!this.negated) {
1783 const result: ContextKeyExpression[] = [];
1789 return this.negated;
1790 }
1791 > } contextkey.ts
1792 >
1793 > export class ContextKeyOrExpr implements IContextKeyExpression {
1794 >
1795 > public static create(_expr: ReadonlyArray<ContextKeyExpression | null | undefined>, negated: ContextKeyExpression | null, extraRedundantCheck: boolean): ContextKeyExpression | undefined {
1796 > return ContextKeyOrExpr._normalizeArr(_expr, negated, extraRedundantCheck);
1797 > }
1798 >
1799 > public readonly type = ContextKeyExprType.Or;
1800 >
1801 > private constructor(
1802 public readonly expr: ContextKeyExpression[],
1803 private negated: ContextKeyExpression | null
1804 ) {
1805 }
1806 > contextkey.ts
1807 > public cmp(other: ContextKeyExpression): number {
1808 if (other.type !== this.type) {
1809 return this.type - other.type;
1823 return 0;
1824 }
1825 > contextkey.ts
1826 > public equals(other: ContextKeyExpression): boolean {
1827 if (other.type === this.type) {
1828 if (this.expr.length !== other.expr.length) {
1838 return false;
1839 }
1840 > contextkey.ts
1841 > public substituteConstants(): ContextKeyExpression | undefined {
1842 const exprArr = eliminateConstantsInArray(this.expr);
1843 if (exprArr === this.expr) {
1847 return ContextKeyOrExpr.create(exprArr, this.negated, false);
1848 }
1849 > contextkey.ts
1850 > public evaluate(context: IContext): boolean {
1851 for (let i = 0, len = this.expr.length; i < len; i++) {
1852 if (this.expr[i].evaluate(context)) {
1856 return false;
1857 }
1858 > contextkey.ts
1859 > private static _normalizeArr(arr: ReadonlyArray<ContextKeyExpression | null | undefined>, negated: ContextKeyExpression | null, extraRedundantCheck: boolean): ContextKeyExpression | undefined {
1860 let expr: ContextKeyExpression[] = [];
1861 let hasFalse = false;
1932 return new ContextKeyOrExpr(expr, negated);
1933 }
1934 > contextkey.ts
1935 > public serialize(): string {
1936 return this.expr.map(e => e.serialize()).join(' || ');
1937 }
1938 > contextkey.ts
1939 > public keys(): string[] {
1940 const result: string[] = [];
1941 for (const expr of this.expr) {
1944 return result;
1945 }
1946 > contextkey.ts
1947 > public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression {
1948 return new ContextKeyOrExpr(this.expr.map(expr => expr.map(mapFnc)), null);
1949 }
1950 > contextkey.ts
1951 > public negate(): ContextKeyExpression {
1952 if (!this.negated) {
1953 const result: ContextKeyExpression[] = [];
1976 return this.negated;
1977 }
1978 > } contextkey.ts
1979 >
1980 > export interface ContextKeyInfo {
1981 > readonly key: string;
1982 > readonly type?: string;
1983 > readonly description?: string;
1984 > }
1985 >
1986 > export class RawContextKey<T extends ContextKeyValue> extends ContextKeyDefinedExpr {
1987 >
1988 > private static _info: ContextKeyInfo[] = [];
1989 >
1990 > static all(): IterableIterator<ContextKeyInfo> {
1991 return RawContextKey._info.values();
1992 }
1993 > contextkey.ts
1994 > private readonly _defaultValue: T | undefined;
1995 >
1996 > constructor(key: string, defaultValue: T | undefined, metaOrHide?: string | true | { type: string; description: string }) {
1997 > super(key, null); contextkey.ts
1998 > this._defaultValue = defaultValue;
1999 >
2000 > // collect all context keys into a central place
2001 > if (typeof metaOrHide === 'object') {
2002 RawContextKey._info.push({ ...metaOrHide, key });
2003 > } else if (metaOrHide !== true) { contextkey.ts
2004 > RawContextKey._info.push({ key, description: metaOrHide, type: defaultValue !== null && defaultValue !== undefined ? typeof defaultValue : undefined }); contextkey.ts
2005 > }
2006 > } contextkey.ts
2007 > contextkey.ts
2008 > public bindTo(target: IContextKeyService): IContextKey<T> {
2009 return target.createKey(this.key, this._defaultValue);
2010 }
2011 > contextkey.ts
2012 > public getValue(target: IContextKeyService): T | undefined {
2013 return target.getContextKeyValue<T>(this.key);
2014 }
2015 > contextkey.ts
2016 > public toNegated(): ContextKeyExpression {
2017 return this.negate();
2018 }
2019 > contextkey.ts
2020 > public isEqualTo(value: any): ContextKeyExpression {
2021 return ContextKeyEqualsExpr.create(this.key, value);
2022 }
2023 > contextkey.ts
2024 > public notEqualsTo(value: any): ContextKeyExpression {
2025 return ContextKeyNotEqualsExpr.create(this.key, value);
2026 }
2027 > contextkey.ts
2028 > public greater(value: any): ContextKeyExpression {
2029 return ContextKeyGreaterExpr.create(this.key, value);
2030 }
2031 > } contextkey.ts
2032 >
2033 > export type ContextKeyValue = null | undefined | boolean | number | string
2034 > | Array<null | undefined | boolean | number | string>
2035 > | Record<string, null | undefined | boolean | number | string>;
2036 >
2037 > export interface IContext {
2038 > getValue<T extends ContextKeyValue = ContextKeyValue>(key: string): T | undefined;
2039 > }
2040 >
2041 > export interface IContextKey<T extends ContextKeyValue = ContextKeyValue> {
2042 > set(value: T): void;
2043 > reset(): void;
2044 > get(): T | undefined;
2045 > }
2046 >
2047 > export interface IContextKeyServiceTarget {
2048 > parentElement: IContextKeyServiceTarget | null;
2049 > setAttribute(attr: string, value: string): void;
2050 > removeAttribute(attr: string): void;
2051 > hasAttribute(attr: string): boolean;
2052 > getAttribute(attr: string): string | null;
2053 > }
2054 >
2055 > export const IContextKeyService = createDecorator<IContextKeyService>('contextKeyService');
2056 >
2057 > export interface IReadableSet<T> {
2058 > has(value: T): boolean;
2059 > }
2060 >
2061 > export interface IContextKeyChangeEvent {
2062 > affectsSome(keys: IReadableSet<string>): boolean;
2063 > allKeysContainedIn(keys: IReadableSet<string>): boolean;
2064 > }
2065 >
2066 > export type IScopedContextKeyService = IContextKeyService & IDisposable;
2067 >
2068 > export interface IContextKeyService {
2069 > readonly _serviceBrand: undefined;
2070 >
2071 > readonly onDidChangeContext: Event<IContextKeyChangeEvent>;
2072 > bufferChangeEvents(callback: Function): void;
2073 >
2074 > createKey<T extends ContextKeyValue>(key: string, defaultValue: T | undefined): IContextKey<T>;
2075 > contextMatchesRules(rules: ContextKeyExpression | undefined): boolean;
2076 > getContextKeyValue<T>(key: string): T | undefined;
2077 >
2078 > createScoped(target: IContextKeyServiceTarget): IScopedContextKeyService;
2079 > createOverlay(overlay: Iterable<[string, any]>): IContextKeyService;
2080 > getContext(target: IContextKeyServiceTarget | null): IContext;
2081 >
2082 > updateParent(parentContextKeyService: IContextKeyService): void;
2083 > }
2084 >
2085 function cmp1(key1: string, key2: string): number {
2086 if (key1 < key2) {
2092 return 0;
2093 }
2094 > contextkey.ts
2095 function cmp2(key1: string, value1: any, key2: string, value2: any): number {
2096 if (key1 < key2) {
2108 return 0;
2109 }
2110 > contextkey.ts
2111 > /**
2112 > * Returns true if it is provable `p` implies `q`.
2113 > */
2114 > export function implies(p: ContextKeyExpression, q: ContextKeyExpression): boolean {
2115
2116 if (p.type === ContextKeyExprType.False || q.type === ContextKeyExprType.True) {
2152 return p.equals(q);
2153 }
2154 > contextkey.ts
2155 > /**
2156 > * Returns true if all elements in `p` are also present in `q`.
2157 > * The two arrays are assumed to be sorted
2158 > */
2159 function allElementsIncluded(p: ContextKeyExpression[], q: ContextKeyExpression[]): boolean {
2160 let pIndex = 0;
2175 return (pIndex === p.length);
2176 }
2177 > contextkey.ts
2178 function getTerminals(node: ContextKeyExpression) {
2179 if (node.type === ContextKeyExprType.Or) {
src/vs/base/common/strings.ts 508 covered LOC · 107 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- strings.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 { LRUCachedFunction } from './cache.js';
7 > import { CharCode } from './charCode.js';
8 > import { Lazy } from './lazy.js';
9 > import { Constants } from './uint.js';
10 >
11 > export function isFalsyOrWhitespace(str: string | undefined): boolean {
12 if (!str || typeof str !== 'string') {
13 return true;
15 return str.trim().length === 0;
16 }
17 > strings.ts
18 > const _formatRegexp = /{(\d+)}/g;
19 >
20 > /**
21 > * Helper to produce a string with a variable number of arguments. Insert variable segments
22 > * into the string using the {n} notation where N is the index of the argument following the string.
23 > * @param value string to which formatting is applied
24 > * @param args replacements for {n}-entries
25 > */
26 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
27 > export function format(value: string, ...args: any[]): string {
28 if (args.length === 0) {
29 return value;
36 });
37 }
38 > strings.ts
39 > const _format2Regexp = /{([^}]+)}/g;
40 >
41 > /**
42 > * Helper to create a string from a template and a string record.
43 > * Similar to `format` but with objects instead of positional arguments.
44 > */
45 > export function format2(template: string, values: Record<string, unknown>): string {
46 if (Object.keys(values).length === 0) {
47 return template;
49 return template.replace(_format2Regexp, (match, group) => (values[group] ?? match) as string);
50 }
51 > strings.ts
52 > /**
53 > * Encodes the given value so that it can be used as literal value in html attributes.
54 > *
55 > * In other words, computes `$val`, such that `attr` in `<div attr="$val" />` has the runtime value `value`.
56 > * This prevents XSS injection.
57 > */
58 > export function htmlAttributeEncodeValue(value: string): string {
59 return value.replace(/[<>"'&]/g, ch => {
60 switch (ch) {
68 });
69 }
70 > strings.ts
71 > /**
72 > * Converts HTML characters inside the string to use entities instead. Makes the string safe from
73 > * being used e.g. in HTMLElement.innerHTML.
74 > */
75 > export function escape(html: string): string {
76 return html.replace(/[<>&]/g, function (match) {
77 switch (match) {
83 });
84 }
85 > strings.ts
86 > /**
87 > * Escapes regular expression characters in a given string
88 > */
89 > export function escapeRegExpCharacters(value: string): string {
90 return value.replace(/[\\\{\}\*\+\?\|\^\$\.\[\]\(\)]/g, '\\$&');
91 }
92 > strings.ts
93 > /**
94 > * Counts how often `substr` occurs inside `value`.
95 > */
96 > export function count(value: string, substr: string): number {
97 let result = 0;
98 let index = value.indexOf(substr);
103 return result;
104 }
105 > strings.ts
106 > export function truncate(value: string, maxLength: number, suffix = Ellipsis): string {
107 if (value.length <= maxLength) {
108 return value;
111 return `${value.substr(0, maxLength)}${suffix}`;
112 }
113 > strings.ts
114 > export function truncateMiddle(value: string, maxLength: number, suffix = Ellipsis): string {
115 if (value.length <= maxLength) {
116 return value;
122 return `${value.substr(0, prefixLength)}${suffix}${value.substr(value.length - suffixLength)}`;
123 }
124 > strings.ts
125 > /**
126 > * Removes all occurrences of needle from the beginning and end of haystack.
127 > * @param haystack string to trim
128 > * @param needle the thing to trim (default is a blank)
129 > */
130 > export function trim(haystack: string, needle: string = ' '): string {
131 const trimmed = ltrim(haystack, needle);
132 return rtrim(trimmed, needle);
133 }
134 > strings.ts
135 > /**
136 > * Removes all occurrences of needle from the beginning of haystack.
137 > * @param haystack string to trim
138 > * @param needle the thing to trim
139 > */
140 > export function ltrim(haystack: string, needle: string): string {
141 if (!haystack || !needle) {
142 return haystack;
157 return haystack.substring(offset);
158 }
159 > strings.ts
160 > /**
161 > * Removes all occurrences of needle from the end of haystack.
162 > * @param haystack string to trim
163 > * @param needle the thing to trim
164 > */
165 > export function rtrim(haystack: string, needle: string): string {
166 if (!haystack || !needle) {
167 return haystack;
187 return haystack.substring(0, offset);
188 }
189 > strings.ts
190 > export function convertSimple2RegExpPattern(pattern: string): string {
191 return pattern.replace(/[\-\\\{\}\+\?\|\^\$\.\,\[\]\(\)\#\s]/g, '\\$&').replace(/[\*]/g, '.*');
192 }
193 > strings.ts
194 > export interface RegExpOptions {
195 > matchCase?: boolean;
196 > wholeWord?: boolean;
197 > multiline?: boolean;
198 > global?: boolean;
199 > unicode?: boolean;
200 > }
201 >
202 > export function createRegExp(searchString: string, isRegex: boolean, options: RegExpOptions = {}): RegExp {
203 if (!searchString) {
204 throw new Error('Cannot create regex from empty string');
231 return new RegExp(searchString, modifiers);
232 }
233 > strings.ts
234 > export function regExpLeadsToEndlessLoop(regexp: RegExp): boolean {
235 // Exit early if it's one of these special cases which are meant to match
236 // against an empty string
244 return !!(match && regexp.lastIndex === 0);
245 }
246 > strings.ts
247 > export function joinStrings(items: (string | undefined | null | false)[], separator: string): string {
248 return items.filter(item => item !== undefined && item !== null && item !== false).join(separator);
249 }
250 > strings.ts
251 > export function splitLines(str: string): string[] {
252 return str.split(/\r\n|\r|\n/);
253 }
254 > strings.ts
255 > export function splitLinesIncludeSeparators(str: string): string[] {
256 const linesWithSeparators: string[] = [];
257 const splitLinesAndSeparators = str.split(/(\r\n|\r|\n)/);
261 return linesWithSeparators;
262 }
263 > strings.ts
264 > export function indexOfPattern(str: string, re: RegExp) {
265 const match = re.exec(str);
266 if (match) {
269 return -1;
270 }
271 > strings.ts
272 > /**
273 > * Returns first index of the string that is not whitespace.
274 > * If string is empty or contains only whitespaces, returns -1
275 > */
276 > export function firstNonWhitespaceIndex(str: string): number {
277 > for (let i = 0, len = str.length; i < len; i++) { strings.ts
278 > const chCode = str.charCodeAt(i); strings.ts
279 > if (chCode !== CharCode.Space && chCode !== CharCode.Tab) {
280 > return i; strings.ts
281 > }
282 > } strings.ts
283 return -1;
284 }
285 > strings.ts
286 > /**
287 > * Returns the leading whitespace of the string.
288 > * If the string contains only whitespaces, returns entire string
289 > */
290 > export function getLeadingWhitespace(str: string, start: number = 0, end: number = str.length): string {
291 for (let i = start; i < end; i++) {
292 const chCode = str.charCodeAt(i);
297 return str.substring(start, end);
298 }
299 > strings.ts
300 > /**
301 > * Returns last index of the string that is not whitespace.
302 > * If string is empty or contains only whitespaces, returns -1
303 > */
304 > export function lastNonWhitespaceIndex(str: string, startIndex: number = str.length - 1): number {
305 for (let i = startIndex; i >= 0; i--) {
306 const chCode = str.charCodeAt(i);
311 return -1;
312 }
313 > strings.ts
314 > export function getIndentationLength(str: string): number {
315 const idx = firstNonWhitespaceIndex(str);
316 if (idx === -1) { return str.length; }
317 return idx;
318 }
319 > strings.ts
320 > /**
321 > * Function that works identically to String.prototype.replace, except, the
322 > * replace function is allowed to be async and return a Promise.
323 > */
324 > export function replaceAsync(str: string, search: RegExp, replacer: (match: string, ...args: unknown[]) => Promise<string>): Promise<string> {
325 const parts: (string | Promise<string>)[] = [];
326
340 return Promise.all(parts).then(p => p.join(''));
341 }
342 > strings.ts
343 > export function compare(a: string, b: string): number {
344 if (a < b) {
345 return -1;
350 }
351 }
352 > strings.ts
353 > export function compareSubstring(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {
354 for (; aStart < aEnd && bStart < bEnd; aStart++, bStart++) {
355 const codeA = a.charCodeAt(aStart);
370 return 0;
371 }
372 > strings.ts
373 > export function compareIgnoreCase(a: string, b: string): number {
374 return compareSubstringIgnoreCase(a, b, 0, a.length, 0, b.length);
375 }
376 > strings.ts
377 > export function compareSubstringIgnoreCase(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {
378
379 for (; aStart < aEnd && bStart < bEnd; aStart++, bStart++) {
421 return 0;
422 }
423 > strings.ts
424 > export function isAsciiDigit(code: number): boolean {
425 return code >= CharCode.Digit0 && code <= CharCode.Digit9;
426 }
427 > strings.ts
428 > export function isLowerAsciiLetter(code: number): boolean {
429 return code >= CharCode.a && code <= CharCode.z;
430 }
431 > strings.ts
432 > export function isUpperAsciiLetter(code: number): boolean {
433 return code >= CharCode.A && code <= CharCode.Z;
434 }
435 > strings.ts
436 > export function equalsIgnoreCase(a: string, b: string): boolean {
437 return a.length === b.length && compareSubstringIgnoreCase(a, b) === 0;
438 }
439 > strings.ts
440 > export function equals(a: string | undefined, b: string | undefined, ignoreCase?: boolean): boolean {
441 return a === b || (!!ignoreCase && a !== undefined && b !== undefined && equalsIgnoreCase(a, b));
442 }
443 > strings.ts
444 > export function startsWithIgnoreCase(str: string, candidate: string): boolean {
445 const len = candidate.length;
446 return len <= str.length && compareSubstringIgnoreCase(str, candidate, 0, len) === 0;
447 }
448 > strings.ts
449 > export function endsWithIgnoreCase(str: string, candidate: string): boolean {
450 const len = str.length;
451 const start = len - candidate.length;
452 return start >= 0 && compareSubstringIgnoreCase(str, candidate, start, len) === 0;
453 }
454 > strings.ts
455 > /**
456 > * @returns the length of the common prefix of the two strings.
457 > */
458 > export function commonPrefixLength(a: string, b: string): number {
459
460 const len = Math.min(a.length, b.length);
469 return len;
470 }
471 > strings.ts
472 > /**
473 > * @returns the length of the common suffix of the two strings.
474 > */
475 > export function commonSuffixLength(a: string, b: string): number {
476
477 const len = Math.min(a.length, b.length);
489 return len;
490 }
491 > strings.ts
492 > /**
493 > * See http://en.wikipedia.org/wiki/Surrogate_pair
494 > */
495 > export function isHighSurrogate(charCode: number): boolean {
496 > return (0xD800 <= charCode && charCode <= 0xDBFF); strings.ts
497 > }
498 > strings.ts
499 > /**
500 > * See http://en.wikipedia.org/wiki/Surrogate_pair
501 > */
502 > export function isLowSurrogate(charCode: number): boolean {
503 return (0xDC00 <= charCode && charCode <= 0xDFFF);
504 }
505 > strings.ts
506 > /**
507 > * See http://en.wikipedia.org/wiki/Surrogate_pair
508 > */
509 > export function computeCodePoint(highSurrogate: number, lowSurrogate: number): number {
510 return ((highSurrogate - 0xD800) << 10) + (lowSurrogate - 0xDC00) + 0x10000;
511 }
512 > strings.ts
513 > /**
514 > * get the code point that begins at offset `offset`
515 > */
516 > export function getNextCodePoint(str: string, len: number, offset: number): number {
517 const charCode = str.charCodeAt(offset);
518 if (isHighSurrogate(charCode) && offset + 1 < len) {
524 return charCode;
525 }
526 > strings.ts
527 > /**
528 > * get the code point that ends right before offset `offset`
529 > */
530 function getPrevCodePoint(str: string, offset: number): number {
531 const charCode = str.charCodeAt(offset - 1);
538 return charCode;
539 }
540 > strings.ts
541 > export class CodePointIterator {
542 >
543 > private readonly _str: string;
544 > private readonly _len: number;
545 > private _offset: number;
546 >
547 > public get offset(): number {
548 return this._offset;
549 }
550 > strings.ts
551 > constructor(str: string, offset: number = 0) {
552 this._str = str;
553 this._len = str.length;
554 this._offset = offset;
555 }
556 > strings.ts
557 > public setOffset(offset: number): void {
558 this._offset = offset;
559 }
560 > strings.ts
561 > public prevCodePoint(): number {
562 const codePoint = getPrevCodePoint(this._str, this._offset);
563 this._offset -= (codePoint >= Constants.UNICODE_SUPPLEMENTARY_PLANE_BEGIN ? 2 : 1);
564 return codePoint;
565 }
566 > strings.ts
567 > public nextCodePoint(): number {
568 const codePoint = getNextCodePoint(this._str, this._len, this._offset);
569 this._offset += (codePoint >= Constants.UNICODE_SUPPLEMENTARY_PLANE_BEGIN ? 2 : 1);
570 return codePoint;
571 }
572 > strings.ts
573 > public eol(): boolean {
574 return (this._offset >= this._len);
575 }
576 > } strings.ts
577 >
578 > export class GraphemeIterator {
579 >
580 > private readonly _iterator: CodePointIterator;
581 >
582 > public get offset(): number {
583 return this._iterator.offset;
584 }
585 > strings.ts
586 > constructor(str: string, offset: number = 0) {
587 this._iterator = new CodePointIterator(str, offset);
588 }
589 > strings.ts
590 > public nextGraphemeLength(): number {
591 const graphemeBreakTree = GraphemeBreakTree.getInstance();
592 const iterator = this._iterator;
606 return (iterator.offset - initialOffset);
607 }
608 > strings.ts
609 > public prevGraphemeLength(): number {
610 const graphemeBreakTree = GraphemeBreakTree.getInstance();
611 const iterator = this._iterator;
625 return (initialOffset - iterator.offset);
626 }
627 > strings.ts
628 > public eol(): boolean {
629 return this._iterator.eol();
630 }
631 > } strings.ts
632 >
633 > export function nextCharLength(str: string, initialOffset: number): number {
634 const iterator = new GraphemeIterator(str, initialOffset);
635 return iterator.nextGraphemeLength();
636 }
637 > strings.ts
638 > export function prevCharLength(str: string, initialOffset: number): number {
639 const iterator = new GraphemeIterator(str, initialOffset);
640 return iterator.prevGraphemeLength();
641 }
642 > strings.ts
643 > export function getCharContainingOffset(str: string, offset: number): [number, number] {
644 if (offset > 0 && isLowSurrogate(str.charCodeAt(offset))) {
645 offset--;
649 return [startOffset, endOffset];
650 }
651 > strings.ts
652 > export function charCount(str: string): number {
653 const iterator = new GraphemeIterator(str);
654 let length = 0;
659 return length;
660 }
661 > strings.ts
662 > let CONTAINS_RTL: RegExp | undefined = undefined;
663 >
664 function makeContainsRtl() {
665 // Generated using https://github.com/alexdima/unicode-utils/blob/main/rtl-test.js
666 return /(?:[\u05BE\u05C0\u05C3\u05C6\u05D0-\u05F4\u0608\u060B\u060D\u061B-\u064A\u066D-\u066F\u0671-\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u0710\u0712-\u072F\u074D-\u07A5\u07B1-\u07EA\u07F4\u07F5\u07FA\u07FE-\u0815\u081A\u0824\u0828\u0830-\u0858\u085E-\u088E\u08A0-\u08C9\u200F\uFB1D\uFB1F-\uFB28\uFB2A-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFC\uFE70-\uFEFC]|\uD802[\uDC00-\uDD1B\uDD20-\uDE00\uDE10-\uDE35\uDE40-\uDEE4\uDEEB-\uDF35\uDF40-\uDFFF]|\uD803[\uDC00-\uDD23\uDE80-\uDEA9\uDEAD-\uDF45\uDF51-\uDF81\uDF86-\uDFF6]|\uD83A[\uDC00-\uDCCF\uDD00-\uDD43\uDD4B-\uDFFF]|\uD83B[\uDC00-\uDEBB])/;
667 }
668 > strings.ts
669 > /**
670 > * Returns true if `str` contains any Unicode character that is classified as "R" or "AL".
671 > */
672 > export function containsRTL(str: string): boolean {
673 if (!CONTAINS_RTL) {
674 CONTAINS_RTL = makeContainsRtl();
677 return CONTAINS_RTL.test(str);
678 }
679 > strings.ts
680 > const IS_BASIC_ASCII = /^[\t\n\r\x20-\x7E]*$/;
681 > /**
682 > * Returns true if `str` contains only basic ASCII characters in the range 32 - 126 (including 32 and 126) or \n, \r, \t
683 > */
684 > export function isBasicASCII(str: string): boolean {
685 return IS_BASIC_ASCII.test(str);
686 }
687 > strings.ts
688 > export const UNUSUAL_LINE_TERMINATORS = /[\u2028\u2029]/; // LINE SEPARATOR (LS) or PARAGRAPH SEPARATOR (PS)
689 > /**
690 > * Returns true if `str` contains unusual line terminators, like LS or PS
691 > */
692 > export function containsUnusualLineTerminators(str: string): boolean {
693 return UNUSUAL_LINE_TERMINATORS.test(str);
694 }
695 > strings.ts
696 > export function isFullWidthCharacter(charCode: number): boolean {
697 > // Do a cheap trick to better support wrapping of wide characters, treat them as 2 columns strings.ts
698 > // http://jrgraphix.net/research/unicode_blocks.php
699 > // 2E80 - 2EFF CJK Radicals Supplement
700 > // 2F00 - 2FDF Kangxi Radicals
701 > // 2FF0 - 2FFF Ideographic Description Characters
702 > // 3000 - 303F CJK Symbols and Punctuation
703 > // 3040 - 309F Hiragana
704 > // 30A0 - 30FF Katakana
705 > // 3100 - 312F Bopomofo
706 > // 3130 - 318F Hangul Compatibility Jamo
707 > // 3190 - 319F Kanbun
708 > // 31A0 - 31BF Bopomofo Extended
709 > // 31F0 - 31FF Katakana Phonetic Extensions
710 > // 3200 - 32FF Enclosed CJK Letters and Months
711 > // 3300 - 33FF CJK Compatibility
712 > // 3400 - 4DBF CJK Unified Ideographs Extension A
713 > // 4DC0 - 4DFF Yijing Hexagram Symbols
714 > // 4E00 - 9FFF CJK Unified Ideographs
715 > // A000 - A48F Yi Syllables
716 > // A490 - A4CF Yi Radicals
717 > // AC00 - D7AF Hangul Syllables
718 > // [IGNORE] D800 - DB7F High Surrogates
719 > // [IGNORE] DB80 - DBFF High Private Use Surrogates
720 > // [IGNORE] DC00 - DFFF Low Surrogates
721 > // [IGNORE] E000 - F8FF Private Use Area
722 > // F900 - FAFF CJK Compatibility Ideographs
723 > // [IGNORE] FB00 - FB4F Alphabetic Presentation Forms
724 > // [IGNORE] FB50 - FDFF Arabic Presentation Forms-A
725 > // [IGNORE] FE00 - FE0F Variation Selectors
726 > // [IGNORE] FE20 - FE2F Combining Half Marks
727 > // [IGNORE] FE30 - FE4F CJK Compatibility Forms
728 > // [IGNORE] FE50 - FE6F Small Form Variants
729 > // [IGNORE] FE70 - FEFF Arabic Presentation Forms-B
730 > // FF00 - FFEF Halfwidth and Fullwidth Forms
731 > // [https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms]
732 > // of which FF01 - FF5E fullwidth ASCII of 21 to 7E
733 > // and FFE0 - FFE6 fullwidth symbol variants
734 > // [IGNORE] and FF65 - FFDC halfwidth of Katakana and Hangul
735 > // [IGNORE] FFF0 - FFFF Specials
736 > return (
737 > (charCode >= 0x2E80 && charCode <= 0xD7AF)
738 > || (charCode >= 0xF900 && charCode <= 0xFAFF)
739 > || (charCode >= 0xFF01 && charCode <= 0xFF5E)
740 > || (charCode >= 0xFFE0 && charCode <= 0xFFE6)
741 > );
742 > }
743 > strings.ts
744 > /**
745 > * A fast function (therefore imprecise) to check if code points are emojis.
746 > * Generated using https://github.com/alexdima/unicode-utils/blob/main/emoji-test.js
747 > */
748 > export function isEmojiImprecise(x: number): boolean {
749 return (
750 (x >= 0x1F1E6 && x <= 0x1F1FF) || (x === 8986) || (x === 8987) || (x === 9200)
755 );
756 }
757 > strings.ts
758 > /**
759 > * Given a string and a max length returns a shorted version. Shorting
760 > * happens at favorable positions - such as whitespace or punctuation characters.
761 > * The return value can be longer than the given value of `n`. Leading whitespace is always trimmed.
762 > */
763 > export function lcut(text: string, n: number, prefix = ''): string {
764 const trimmed = text.trimStart();
765
785 return prefix + trimmed.substring(i).trimStart();
786 }
787 > strings.ts
788 > /**
789 > * Given a string and a max length returns a shortened version keeping the beginning.
790 > * Shortening happens at favorable positions - such as whitespace or punctuation characters.
791 > * Trailing whitespace is always trimmed.
792 > */
793 > export function rcut(text: string, n: number, suffix = ''): string {
794 const trimmed = text.trimEnd();
795
832 return result + suffix;
833 }
834 > strings.ts
835 > // Defacto standard: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
836 > const CSI_SEQUENCE = /(?:\x1b\[|\x9b)[=?>!]?[\d;:]*["$#'* ]?[a-zA-Z@^`{}|~]/;
837 > const OSC_SEQUENCE = /(?:\x1b\]|\x9d).*?(?:\x1b\\|\x07|\x9c)/;
838 > const ESC_SEQUENCE = /\x1b(?:[ #%\(\)\*\+\-\.\/]?[a-zA-Z0-9\|}~@])/;
839 > const CONTROL_SEQUENCES = new RegExp('(?:' + [
840 > CSI_SEQUENCE.source,
841 > OSC_SEQUENCE.source,
842 > ESC_SEQUENCE.source,
843 > ].join('|') + ')', 'g');
844 >
845 > /** Iterates over parts of a string with CSI sequences */
846 > export function* forAnsiStringParts(str: string) {
847 let last = 0;
848 for (const match of str.matchAll(CONTROL_SEQUENCES)) {
859 }
860 }
861 > strings.ts
862 > /**
863 > * Strips ANSI escape sequences from a string.
864 > * @param str The dastringa stringo strip the ANSI escape sequences from.
865 > *
866 > * @example
867 > * removeAnsiEscapeCodes('\u001b[31mHello, World!\u001b[0m');
868 > * // 'Hello, World!'
869 > */
870 > export function removeAnsiEscapeCodes(str: string): string {
871 if (str) {
872 str = str.replace(CONTROL_SEQUENCES, '');
875 return str;
876 }
877 > strings.ts
878 > const PROMPT_NON_PRINTABLE = /\\\[.*?\\\]/g;
879 >
880 > /**
881 > * Strips ANSI escape sequences from a UNIX-style prompt string (eg. `$PS1`).
882 > * @param str The string to strip the ANSI escape sequences from.
883 > *
884 > * @example
885 > * removeAnsiEscapeCodesFromPrompt('\n\\[\u001b[01;34m\\]\\w\\[\u001b[00m\\]\n\\[\u001b[1;32m\\]> \\[\u001b[0m\\]');
886 > * // '\n\\w\n> '
887 > */
888 > export function removeAnsiEscapeCodesFromPrompt(str: string): string {
889 return removeAnsiEscapeCodes(str).replace(PROMPT_NON_PRINTABLE, '');
890 }
891 > strings.ts
892 >
893 > // -- UTF-8 BOM
894 >
895 > export const UTF8_BOM_CHARACTER = String.fromCharCode(CharCode.UTF8_BOM);
896 >
897 > export function startsWithUTF8BOM(str: string): boolean {
898 return !!(str && str.length > 0 && str.charCodeAt(0) === CharCode.UTF8_BOM);
899 }
900 > strings.ts
901 > export function stripUTF8BOM(str: string): string {
902 return startsWithUTF8BOM(str) ? str.substr(1) : str;
903 }
904 > strings.ts
905 > /**
906 > * Checks if the characters of the provided query string are included in the
907 > * target string. The characters do not have to be contiguous within the string.
908 > */
909 > export function fuzzyContains(target: string, query: string): boolean {
910 if (!target || !query) {
911 return false; // return early if target or query are undefined
936 return true;
937 }
938 > strings.ts
939 > export function containsUppercaseCharacter(target: string, ignoreEscapedChars = false): boolean {
940 if (!target) {
941 return false;
948 return target.toLowerCase() !== target;
949 }
950 > strings.ts
951 > export function uppercaseFirstLetter(str: string): string {
952 return str.charAt(0).toUpperCase() + str.slice(1);
953 }
954 > strings.ts
955 > export function getNLines(str: string, n = 1): string {
956 if (n === 0) {
957 return '';
974 return str.substr(0, idx);
975 }
976 > strings.ts
977 > /**
978 > * Produces 'a'-'z', followed by 'A'-'Z'... followed by 'a'-'z', etc.
979 > */
980 > export function singleLetterHash(n: number): string {
981 const LETTERS_CNT = (CharCode.Z - CharCode.A + 1);
982
989 return String.fromCharCode(CharCode.A + n - LETTERS_CNT);
990 }
991 > strings.ts
992 > //#region Unicode Grapheme Break
993 >
994 > export function getGraphemeBreakType(codePoint: number): GraphemeBreakType {
995 const graphemeBreakTree = GraphemeBreakTree.getInstance();
996 return graphemeBreakTree.getGraphemeBreakType(codePoint);
997 }
998 > strings.ts
999 function breakBetweenGraphemeBreakType(breakTypeA: GraphemeBreakType, breakTypeB: GraphemeBreakType): boolean {
1000 // http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules
1076 return true;
1077 }
1078 > strings.ts
1079 > export const enum GraphemeBreakType {
1080 > Other = 0,
1081 > Prepend = 1,
1082 > CR = 2,
1083 > LF = 3,
1084 > Control = 4,
1085 > Extend = 5,
1086 > Regional_Indicator = 6,
1087 > SpacingMark = 7,
1088 > L = 8,
1089 > V = 9,
1090 > T = 10,
1091 > LV = 11,
1092 > LVT = 12,
1093 > ZWJ = 13,
1094 > Extended_Pictographic = 14
1095 > }
1096 >
1097 > class GraphemeBreakTree {
1098 >
1099 > private static _INSTANCE: GraphemeBreakTree | null = null;
1100 > public static getInstance(): GraphemeBreakTree {
1101 if (!GraphemeBreakTree._INSTANCE) {
1102 GraphemeBreakTree._INSTANCE = new GraphemeBreakTree();
1104 return GraphemeBreakTree._INSTANCE;
1105 }
1106 > strings.ts
1107 > private readonly _data: number[];
1108 >
1109 > constructor() {
1110 this._data = getGraphemeBreakRawData();
1111 }
1112 > strings.ts
1113 > public getGraphemeBreakType(codePoint: number): GraphemeBreakType {
1114 // !!! Let's make 7bit ASCII a bit faster: 0..31
1115 if (codePoint < 32) {
1145 return GraphemeBreakType.Other;
1146 }
1147 > } strings.ts
1148 >
1149 function getGraphemeBreakRawData(): number[] {
1150 // generated using https://github.com/alexdima/unicode-utils/blob/main/grapheme-break.js
1151 return JSON.parse('[0,0,0,51229,51255,12,44061,44087,12,127462,127487,6,7083,7085,5,47645,47671,12,54813,54839,12,128678,128678,14,3270,3270,5,9919,9923,14,45853,45879,12,49437,49463,12,53021,53047,12,71216,71218,7,128398,128399,14,129360,129374,14,2519,2519,5,4448,4519,9,9742,9742,14,12336,12336,14,44957,44983,12,46749,46775,12,48541,48567,12,50333,50359,12,52125,52151,12,53917,53943,12,69888,69890,5,73018,73018,5,127990,127990,14,128558,128559,14,128759,128760,14,129653,129655,14,2027,2035,5,2891,2892,7,3761,3761,5,6683,6683,5,8293,8293,4,9825,9826,14,9999,9999,14,43452,43453,5,44509,44535,12,45405,45431,12,46301,46327,12,47197,47223,12,48093,48119,12,48989,49015,12,49885,49911,12,50781,50807,12,51677,51703,12,52573,52599,12,53469,53495,12,54365,54391,12,65279,65279,4,70471,70472,7,72145,72147,7,119173,119179,5,127799,127818,14,128240,128244,14,128512,128512,14,128652,128652,14,128721,128722,14,129292,129292,14,129445,129450,14,129734,129743,14,1476,1477,5,2366,2368,7,2750,2752,7,3076,3076,5,3415,3415,5,4141,4144,5,6109,6109,5,6964,6964,5,7394,7400,5,9197,9198,14,9770,9770,14,9877,9877,14,9968,9969,14,10084,10084,14,43052,43052,5,43713,43713,5,44285,44311,12,44733,44759,12,45181,45207,12,45629,45655,12,46077,46103,12,46525,46551,12,46973,46999,12,47421,47447,12,47869,47895,12,48317,48343,12,48765,48791,12,49213,49239,12,49661,49687,12,50109,50135,12,50557,50583,12,51005,51031,12,51453,51479,12,51901,51927,12,52349,52375,12,52797,52823,12,53245,53271,12,53693,53719,12,54141,54167,12,54589,54615,12,55037,55063,12,69506,69509,5,70191,70193,5,70841,70841,7,71463,71467,5,72330,72342,5,94031,94031,5,123628,123631,5,127763,127765,14,127941,127941,14,128043,128062,14,128302,128317,14,128465,128467,14,128539,128539,14,128640,128640,14,128662,128662,14,128703,128703,14,128745,128745,14,129004,129007,14,129329,129330,14,129402,129402,14,129483,129483,14,129686,129704,14,130048,131069,14,173,173,4,1757,1757,1,2200,2207,5,2434,2435,7,2631,2632,5,2817,2817,5,3008,3008,5,3201,3201,5,3387,3388,5,3542,3542,5,3902,3903,7,4190,4192,5,6002,6003,5,6439,6440,5,6765,6770,7,7019,7027,5,7154,7155,7,8205,8205,13,8505,8505,14,9654,9654,14,9757,9757,14,9792,9792,14,9852,9853,14,9890,9894,14,9937,9937,14,9981,9981,14,10035,10036,14,11035,11036,14,42654,42655,5,43346,43347,7,43587,43587,5,44006,44007,7,44173,44199,12,44397,44423,12,44621,44647,12,44845,44871,12,45069,45095,12,45293,45319,12,45517,45543,12,45741,45767,12,45965,45991,12,46189,46215,12,46413,46439,12,46637,46663,12,46861,46887,12,47085,47111,12,47309,47335,12,47533,47559,12,47757,47783,12,47981,48007,12,48205,48231,12,48429,48455,12,48653,48679,12,48877,48903,12,49101,49127,12,49325,49351,12,49549,49575,12,49773,49799,12,49997,50023,12,50221,50247,12,50445,50471,12,50669,50695,12,50893,50919,12,51117,51143,12,51341,51367,12,51565,51591,12,51789,51815,12,52013,52039,12,52237,52263,12,52461,52487,12,52685,52711,12,52909,52935,12,53133,53159,12,53357,53383,12,53581,53607,12,53805,53831,12,54029,54055,12,54253,54279,12,54477,54503,12,54701,54727,12,54925,54951,12,55149,55175,12,68101,68102,5,69762,69762,7,70067,70069,7,70371,70378,5,70720,70721,7,71087,71087,5,71341,71341,5,71995,71996,5,72249,72249,7,72850,72871,5,73109,73109,5,118576,118598,5,121505,121519,5,127245,127247,14,127568,127569,14,127777,127777,14,127872,127891,14,127956,127967,14,128015,128016,14,128110,128172,14,128259,128259,14,128367,128368,14,128424,128424,14,128488,128488,14,128530,128532,14,128550,128551,14,128566,128566,14,128647,128647,14,128656,128656,14,128667,128673,14,128691,128693,14,128715,128715,14,128728,128732,14,128752,128752,14,128765,128767,14,129096,129103,14,129311,129311,14,129344,129349,14,129394,129394,14,129413,129425,14,129466,129471,14,129511,129535,14,129664,129666,14,129719,129722,14,129760,129767,14,917536,917631,5,13,13,2,1160,1161,5,1564,1564,4,1807,1807,1,2085,2087,5,2307,2307,7,2382,2383,7,2497,2500,5,2563,2563,7,2677,2677,5,2763,2764,7,2879,2879,5,2914,2915,5,3021,3021,5,3142,3144,5,3263,3263,5,3285,3286,5,3398,3400,7,3530,3530,5,3633,3633,5,3864,3865,5,3974,3975,5,4155,4156,7,4229,4230,5,5909,5909,7,6078,6085,7,6277,6278,5,6451,6456,7,6744,6750,5,6846,6846,5,6972,6972,5,7074,7077,5,7146,7148,7,7222,7223,5,7416,7417,5,8234,8238,4,8417,8417,5,9000,9000,14,9203,9203,14,9730,9731,14,9748,9749,14,9762,9763,14,9776,9783,14,9800,9811,14,9831,9831,14,9872,9873,14,9882,9882,14,9900,9903,14,9929,9933,14,9941,9960,14,9974,9974,14,9989,9989,14,10006,10006,14,10062,10062,14,10160,10160,14,11647,11647,5,12953,12953,14,43019,43019,5,43232,43249,5,43443,43443,5,43567,43568,7,43696,43696,5,43765,43765,7,44013,44013,5,44117,44143,12,44229,44255,12,44341,44367,12,44453,44479,12,44565,44591,12,44677,44703,12,44789,44815,12,44901,44927,12,45013,45039,12,45125,45151,12,45237,45263,12,45349,45375,12,45461,45487,12,45573,45599,12,45685,45711,12,45797,45823,12,45909,45935,12,46021,46047,12,46133,46159,12,46245,46271,12,46357,46383,12,46469,46495,12,46581,46607,12,46693,46719,12,46805,46831,12,46917,46943,12,47029,47055,12,47141,47167,12,47253,47279,12,47365,47391,12,47477,47503,12,47589,47615,12,47701,47727,12,47813,47839,12,47925,47951,12,48037,48063,12,48149,48175,12,48261,48287,12,48373,48399,12,48485,48511,12,48597,48623,12,48709,48735,12,48821,48847,12,48933,48959,12,49045,49071,12,49157,49183,12,49269,49295,12,49381,49407,12,49493,49519,12,49605,49631,12,49717,49743,12,49829,49855,12,49941,49967,12,50053,50079,12,50165,50191,12,50277,50303,12,50389,50415,12,50501,50527,12,50613,50639,12,50725,50751,12,50837,50863,12,50949,50975,12,51061,51087,12,51173,51199,12,51285,51311,12,51397,51423,12,51509,51535,12,51621,51647,12,51733,51759,12,51845,51871,12,51957,51983,12,52069,52095,12,52181,52207,12,52293,52319,12,52405,52431,12,52517,52543,12,52629,52655,12,52741,52767,12,52853,52879,12,52965,52991,12,53077,53103,12,53189,53215,12,53301,53327,12,53413,53439,12,53525,53551,12,53637,53663,12,53749,53775,12,53861,53887,12,53973,53999,12,54085,54111,12,54197,54223,12,54309,54335,12,54421,54447,12,54533,54559,12,54645,54671,12,54757,54783,12,54869,54895,12,54981,55007,12,55093,55119,12,55243,55291,10,66045,66045,5,68325,68326,5,69688,69702,5,69817,69818,5,69957,69958,7,70089,70092,5,70198,70199,5,70462,70462,5,70502,70508,5,70750,70750,5,70846,70846,7,71100,71101,5,71230,71230,7,71351,71351,5,71737,71738,5,72000,72000,7,72160,72160,5,72273,72278,5,72752,72758,5,72882,72883,5,73031,73031,5,73461,73462,7,94192,94193,7,119149,119149,7,121403,121452,5,122915,122916,5,126980,126980,14,127358,127359,14,127535,127535,14,127759,127759,14,127771,127771,14,127792,127793,14,127825,127867,14,127897,127899,14,127945,127945,14,127985,127986,14,128000,128007,14,128021,128021,14,128066,128100,14,128184,128235,14,128249,128252,14,128266,128276,14,128335,128335,14,128379,128390,14,128407,128419,14,128444,128444,14,128481,128481,14,128499,128499,14,128526,128526,14,128536,128536,14,128543,128543,14,128556,128556,14,128564,128564,14,128577,128580,14,128643,128645,14,128649,128649,14,128654,128654,14,128660,128660,14,128664,128664,14,128675,128675,14,128686,128689,14,128695,128696,14,128705,128709,14,128717,128719,14,128725,128725,14,128736,128741,14,128747,128748,14,128755,128755,14,128762,128762,14,128981,128991,14,129009,129023,14,129160,129167,14,129296,129304,14,129320,129327,14,129340,129342,14,129356,129356,14,129388,129392,14,129399,129400,14,129404,129407,14,129432,129442,14,129454,129455,14,129473,129474,14,129485,129487,14,129648,129651,14,129659,129660,14,129671,129679,14,129709,129711,14,129728,129730,14,129751,129753,14,129776,129782,14,917505,917505,4,917760,917999,5,10,10,3,127,159,4,768,879,5,1471,1471,5,1536,1541,1,1648,1648,5,1767,1768,5,1840,1866,5,2070,2073,5,2137,2139,5,2274,2274,1,2363,2363,7,2377,2380,7,2402,2403,5,2494,2494,5,2507,2508,7,2558,2558,5,2622,2624,7,2641,2641,5,2691,2691,7,2759,2760,5,2786,2787,5,2876,2876,5,2881,2884,5,2901,2902,5,3006,3006,5,3014,3016,7,3072,3072,5,3134,3136,5,3157,3158,5,3260,3260,5,3266,3266,5,3274,3275,7,3328,3329,5,3391,3392,7,3405,3405,5,3457,3457,5,3536,3537,7,3551,3551,5,3636,3642,5,3764,3772,5,3895,3895,5,3967,3967,7,3993,4028,5,4146,4151,5,4182,4183,7,4226,4226,5,4253,4253,5,4957,4959,5,5940,5940,7,6070,6070,7,6087,6088,7,6158,6158,4,6432,6434,5,6448,6449,7,6679,6680,5,6742,6742,5,6754,6754,5,6783,6783,5,6912,6915,5,6966,6970,5,6978,6978,5,7042,7042,7,7080,7081,5,7143,7143,7,7150,7150,7,7212,7219,5,7380,7392,5,7412,7412,5,8203,8203,4,8232,8232,4,8265,8265,14,8400,8412,5,8421,8432,5,8617,8618,14,9167,9167,14,9200,9200,14,9410,9410,14,9723,9726,14,9733,9733,14,9745,9745,14,9752,9752,14,9760,9760,14,9766,9766,14,9774,9774,14,9786,9786,14,9794,9794,14,9823,9823,14,9828,9828,14,9833,9850,14,9855,9855,14,9875,9875,14,9880,9880,14,9885,9887,14,9896,9897,14,9906,9916,14,9926,9927,14,9935,9935,14,9939,9939,14,9962,9962,14,9972,9972,14,9978,9978,14,9986,9986,14,9997,9997,14,10002,10002,14,10017,10017,14,10055,10055,14,10071,10071,14,10133,10135,14,10548,10549,14,11093,11093,14,12330,12333,5,12441,12442,5,42608,42610,5,43010,43010,5,43045,43046,5,43188,43203,7,43302,43309,5,43392,43394,5,43446,43449,5,43493,43493,5,43571,43572,7,43597,43597,7,43703,43704,5,43756,43757,5,44003,44004,7,44009,44010,7,44033,44059,12,44089,44115,12,44145,44171,12,44201,44227,12,44257,44283,12,44313,44339,12,44369,44395,12,44425,44451,12,44481,44507,12,44537,44563,12,44593,44619,12,44649,44675,12,44705,44731,12,44761,44787,12,44817,44843,12,44873,44899,12,44929,44955,12,44985,45011,12,45041,45067,12,45097,45123,12,45153,45179,12,45209,45235,12,45265,45291,12,45321,45347,12,45377,45403,12,45433,45459,12,45489,45515,12,45545,45571,12,45601,45627,12,45657,45683,12,45713,45739,12,45769,45795,12,45825,45851,12,45881,45907,12,45937,45963,12,45993,46019,12,46049,46075,12,46105,46131,12,46161,46187,12,46217,46243,12,46273,46299,12,46329,46355,12,46385,46411,12,46441,46467,12,46497,46523,12,46553,46579,12,46609,46635,12,46665,46691,12,46721,46747,12,46777,46803,12,46833,46859,12,46889,46915,12,46945,46971,12,47001,47027,12,47057,47083,12,47113,47139,12,47169,47195,12,47225,47251,12,47281,47307,12,47337,47363,12,47393,47419,12,47449,47475,12,47505,47531,12,47561,47587,12,47617,47643,12,47673,47699,12,47729,47755,12,47785,47811,12,47841,47867,12,47897,47923,12,47953,47979,12,48009,48035,12,48065,48091,12,48121,48147,12,48177,48203,12,48233,48259,12,48289,48315,12,48345,48371,12,48401,48427,12,48457,48483,12,48513,48539,12,48569,48595,12,48625,48651,12,48681,48707,12,48737,48763,12,48793,48819,12,48849,48875,12,48905,48931,12,48961,48987,12,49017,49043,12,49073,49099,12,49129,49155,12,49185,49211,12,49241,49267,12,49297,49323,12,49353,49379,12,49409,49435,12,49465,49491,12,49521,49547,12,49577,49603,12,49633,49659,12,49689,49715,12,49745,49771,12,49801,49827,12,49857,49883,12,49913,49939,12,49969,49995,12,50025,50051,12,50081,50107,12,50137,50163,12,50193,50219,12,50249,50275,12,50305,50331,12,50361,50387,12,50417,50443,12,50473,50499,12,50529,50555,12,50585,50611,12,50641,50667,12,50697,50723,12,50753,50779,12,50809,50835,12,50865,50891,12,50921,50947,12,50977,51003,12,51033,51059,12,51089,51115,12,51145,51171,12,51201,51227,12,51257,51283,12,51313,51339,12,51369,51395,12,51425,51451,12,51481,51507,12,51537,51563,12,51593,51619,12,51649,51675,12,51705,51731,12,51761,51787,12,51817,51843,12,51873,51899,12,51929,51955,12,51985,52011,12,52041,52067,12,52097,52123,12,52153,52179,12,52209,52235,12,52265,52291,12,52321,52347,12,52377,52403,12,52433,52459,12,52489,52515,12,52545,52571,12,52601,52627,12,52657,52683,12,52713,52739,12,52769,52795,12,52825,52851,12,52881,52907,12,52937,52963,12,52993,53019,12,53049,53075,12,53105,53131,12,53161,53187,12,53217,53243,12,53273,53299,12,53329,53355,12,53385,53411,12,53441,53467,12,53497,53523,12,53553,53579,12,53609,53635,12,53665,53691,12,53721,53747,12,53777,53803,12,53833,53859,12,53889,53915,12,53945,53971,12,54001,54027,12,54057,54083,12,54113,54139,12,54169,54195,12,54225,54251,12,54281,54307,12,54337,54363,12,54393,54419,12,54449,54475,12,54505,54531,12,54561,54587,12,54617,54643,12,54673,54699,12,54729,54755,12,54785,54811,12,54841,54867,12,54897,54923,12,54953,54979,12,55009,55035,12,55065,55091,12,55121,55147,12,55177,55203,12,65024,65039,5,65520,65528,4,66422,66426,5,68152,68154,5,69291,69292,5,69633,69633,5,69747,69748,5,69811,69814,5,69826,69826,5,69932,69932,7,70016,70017,5,70079,70080,7,70095,70095,5,70196,70196,5,70367,70367,5,70402,70403,7,70464,70464,5,70487,70487,5,70709,70711,7,70725,70725,7,70833,70834,7,70843,70844,7,70849,70849,7,71090,71093,5,71103,71104,5,71227,71228,7,71339,71339,5,71344,71349,5,71458,71461,5,71727,71735,5,71985,71989,7,71998,71998,5,72002,72002,7,72154,72155,5,72193,72202,5,72251,72254,5,72281,72283,5,72344,72345,5,72766,72766,7,72874,72880,5,72885,72886,5,73023,73029,5,73104,73105,5,73111,73111,5,92912,92916,5,94095,94098,5,113824,113827,4,119142,119142,7,119155,119162,4,119362,119364,5,121476,121476,5,122888,122904,5,123184,123190,5,125252,125258,5,127183,127183,14,127340,127343,14,127377,127386,14,127491,127503,14,127548,127551,14,127744,127756,14,127761,127761,14,127769,127769,14,127773,127774,14,127780,127788,14,127796,127797,14,127820,127823,14,127869,127869,14,127894,127895,14,127902,127903,14,127943,127943,14,127947,127950,14,127972,127972,14,127988,127988,14,127992,127994,14,128009,128011,14,128019,128019,14,128023,128041,14,128064,128064,14,128102,128107,14,128174,128181,14,128238,128238,14,128246,128247,14,128254,128254,14,128264,128264,14,128278,128299,14,128329,128330,14,128348,128359,14,128371,128377,14,128392,128393,14,128401,128404,14,128421,128421,14,128433,128434,14,128450,128452,14,128476,128478,14,128483,128483,14,128495,128495,14,128506,128506,14,128519,128520,14,128528,128528,14,128534,128534,14,128538,128538,14,128540,128542,14,128544,128549,14,128552,128555,14,128557,128557,14,128560,128563,14,128565,128565,14,128567,128576,14,128581,128591,14,128641,128642,14,128646,128646,14,128648,128648,14,128650,128651,14,128653,128653,14,128655,128655,14,128657,128659,14,128661,128661,14,128663,128663,14,128665,128666,14,128674,128674,14,128676,128677,14,128679,128685,14,128690,128690,14,128694,128694,14,128697,128702,14,128704,128704,14,128710,128714,14,128716,128716,14,128720,128720,14,128723,128724,14,128726,128727,14,128733,128735,14,128742,128744,14,128746,128746,14,128749,128751,14,128753,128754,14,128756,128758,14,128761,128761,14,128763,128764,14,128884,128895,14,128992,129003,14,129008,129008,14,129036,129039,14,129114,129119,14,129198,129279,14,129293,129295,14,129305,129310,14,129312,129319,14,129328,129328,14,129331,129338,14,129343,129343,14,129351,129355,14,129357,129359,14,129375,129387,14,129393,129393,14,129395,129398,14,129401,129401,14,129403,129403,14,129408,129412,14,129426,129431,14,129443,129444,14,129451,129453,14,129456,129465,14,129472,129472,14,129475,129482,14,129484,129484,14,129488,129510,14,129536,129647,14,129652,129652,14,129656,129658,14,129661,129663,14,129667,129670,14,129680,129685,14,129705,129708,14,129712,129718,14,129723,129727,14,129731,129733,14,129744,129750,14,129754,129759,14,129768,129775,14,129783,129791,14,917504,917504,4,917506,917535,4,917632,917759,4,918000,921599,4,0,9,4,11,12,4,14,31,4,169,169,14,174,174,14,1155,1159,5,1425,1469,5,1473,1474,5,1479,1479,5,1552,1562,5,1611,1631,5,1750,1756,5,1759,1764,5,1770,1773,5,1809,1809,5,1958,1968,5,2045,2045,5,2075,2083,5,2089,2093,5,2192,2193,1,2250,2273,5,2275,2306,5,2362,2362,5,2364,2364,5,2369,2376,5,2381,2381,5,2385,2391,5,2433,2433,5,2492,2492,5,2495,2496,7,2503,2504,7,2509,2509,5,2530,2531,5,2561,2562,5,2620,2620,5,2625,2626,5,2635,2637,5,2672,2673,5,2689,2690,5,2748,2748,5,2753,2757,5,2761,2761,7,2765,2765,5,2810,2815,5,2818,2819,7,2878,2878,5,2880,2880,7,2887,2888,7,2893,2893,5,2903,2903,5,2946,2946,5,3007,3007,7,3009,3010,7,3018,3020,7,3031,3031,5,3073,3075,7,3132,3132,5,3137,3140,7,3146,3149,5,3170,3171,5,3202,3203,7,3262,3262,7,3264,3265,7,3267,3268,7,3271,3272,7,3276,3277,5,3298,3299,5,3330,3331,7,3390,3390,5,3393,3396,5,3402,3404,7,3406,3406,1,3426,3427,5,3458,3459,7,3535,3535,5,3538,3540,5,3544,3550,7,3570,3571,7,3635,3635,7,3655,3662,5,3763,3763,7,3784,3789,5,3893,3893,5,3897,3897,5,3953,3966,5,3968,3972,5,3981,3991,5,4038,4038,5,4145,4145,7,4153,4154,5,4157,4158,5,4184,4185,5,4209,4212,5,4228,4228,7,4237,4237,5,4352,4447,8,4520,4607,10,5906,5908,5,5938,5939,5,5970,5971,5,6068,6069,5,6071,6077,5,6086,6086,5,6089,6099,5,6155,6157,5,6159,6159,5,6313,6313,5,6435,6438,7,6441,6443,7,6450,6450,5,6457,6459,5,6681,6682,7,6741,6741,7,6743,6743,7,6752,6752,5,6757,6764,5,6771,6780,5,6832,6845,5,6847,6862,5,6916,6916,7,6965,6965,5,6971,6971,7,6973,6977,7,6979,6980,7,7040,7041,5,7073,7073,7,7078,7079,7,7082,7082,7,7142,7142,5,7144,7145,5,7149,7149,5,7151,7153,5,7204,7211,7,7220,7221,7,7376,7378,5,7393,7393,7,7405,7405,5,7415,7415,7,7616,7679,5,8204,8204,5,8206,8207,4,8233,8233,4,8252,8252,14,8288,8292,4,8294,8303,4,8413,8416,5,8418,8420,5,8482,8482,14,8596,8601,14,8986,8987,14,9096,9096,14,9193,9196,14,9199,9199,14,9201,9202,14,9208,9210,14,9642,9643,14,9664,9664,14,9728,9729,14,9732,9732,14,9735,9741,14,9743,9744,14,9746,9746,14,9750,9751,14,9753,9756,14,9758,9759,14,9761,9761,14,9764,9765,14,9767,9769,14,9771,9773,14,9775,9775,14,9784,9785,14,9787,9791,14,9793,9793,14,9795,9799,14,9812,9822,14,9824,9824,14,9827,9827,14,9829,9830,14,9832,9832,14,9851,9851,14,9854,9854,14,9856,9861,14,9874,9874,14,9876,9876,14,9878,9879,14,9881,9881,14,9883,9884,14,9888,9889,14,9895,9895,14,9898,9899,14,9904,9905,14,9917,9918,14,9924,9925,14,9928,9928,14,9934,9934,14,9936,9936,14,9938,9938,14,9940,9940,14,9961,9961,14,9963,9967,14,9970,9971,14,9973,9973,14,9975,9977,14,9979,9980,14,9982,9985,14,9987,9988,14,9992,9996,14,9998,9998,14,10000,10001,14,10004,10004,14,10013,10013,14,10024,10024,14,10052,10052,14,10060,10060,14,10067,10069,14,10083,10083,14,10085,10087,14,10145,10145,14,10175,10175,14,11013,11015,14,11088,11088,14,11503,11505,5,11744,11775,5,12334,12335,5,12349,12349,14,12951,12951,14,42607,42607,5,42612,42621,5,42736,42737,5,43014,43014,5,43043,43044,7,43047,43047,7,43136,43137,7,43204,43205,5,43263,43263,5,43335,43345,5,43360,43388,8,43395,43395,7,43444,43445,7,43450,43451,7,43454,43456,7,43561,43566,5,43569,43570,5,43573,43574,5,43596,43596,5,43644,43644,5,43698,43700,5,43710,43711,5,43755,43755,7,43758,43759,7,43766,43766,5,44005,44005,5,44008,44008,5,44012,44012,7,44032,44032,11,44060,44060,11,44088,44088,11,44116,44116,11,44144,44144,11,44172,44172,11,44200,44200,11,44228,44228,11,44256,44256,11,44284,44284,11,44312,44312,11,44340,44340,11,44368,44368,11,44396,44396,11,44424,44424,11,44452,44452,11,44480,44480,11,44508,44508,11,44536,44536,11,44564,44564,11,44592,44592,11,44620,44620,11,44648,44648,11,44676,44676,11,44704,44704,11,44732,44732,11,44760,44760,11,44788,44788,11,44816,44816,11,44844,44844,11,44872,44872,11,44900,44900,11,44928,44928,11,44956,44956,11,44984,44984,11,45012,45012,11,45040,45040,11,45068,45068,11,45096,45096,11,45124,45124,11,45152,45152,11,45180,45180,11,45208,45208,11,45236,45236,11,45264,45264,11,45292,45292,11,45320,45320,11,45348,45348,11,45376,45376,11,45404,45404,11,45432,45432,11,45460,45460,11,45488,45488,11,45516,45516,11,45544,45544,11,45572,45572,11,45600,45600,11,45628,45628,11,45656,45656,11,45684,45684,11,45712,45712,11,45740,45740,11,45768,45768,11,45796,45796,11,45824,45824,11,45852,45852,11,45880,45880,11,45908,45908,11,45936,45936,11,45964,45964,11,45992,45992,11,46020,46020,11,46048,46048,11,46076,46076,11,46104,46104,11,46132,46132,11,46160,46160,11,46188,46188,11,46216,46216,11,46244,46244,11,46272,46272,11,46300,46300,11,46328,46328,11,46356,46356,11,46384,46384,11,46412,46412,11,46440,46440,11,46468,46468,11,46496,46496,11,46524,46524,11,46552,46552,11,46580,46580,11,46608,46608,11,46636,46636,11,46664,46664,11,46692,46692,11,46720,46720,11,46748,46748,11,46776,46776,11,46804,46804,11,46832,46832,11,46860,46860,11,46888,46888,11,46916,46916,11,46944,46944,11,46972,46972,11,47000,47000,11,47028,47028,11,47056,47056,11,47084,47084,11,47112,47112,11,47140,47140,11,47168,47168,11,47196,47196,11,47224,47224,11,47252,47252,11,47280,47280,11,47308,47308,11,47336,47336,11,47364,47364,11,47392,47392,11,47420,47420,11,47448,47448,11,47476,47476,11,47504,47504,11,47532,47532,11,47560,47560,11,47588,47588,11,47616,47616,11,47644,47644,11,47672,47672,11,47700,47700,11,47728,47728,11,47756,47756,11,47784,47784,11,47812,47812,11,47840,47840,11,47868,47868,11,47896,47896,11,47924,47924,11,47952,47952,11,47980,47980,11,48008,48008,11,48036,48036,11,48064,48064,11,48092,48092,11,48120,48120,11,48148,48148,11,48176,48176,11,48204,48204,11,48232,48232,11,48260,48260,11,48288,48288,11,48316,48316,11,48344,48344,11,48372,48372,11,48400,48400,11,48428,48428,11,48456,48456,11,48484,48484,11,48512,48512,11,48540,48540,11,48568,48568,11,48596,48596,11,48624,48624,11,48652,48652,11,48680,48680,11,48708,48708,11,48736,48736,11,48764,48764,11,48792,48792,11,48820,48820,11,48848,48848,11,48876,48876,11,48904,48904,11,48932,48932,11,48960,48960,11,48988,48988,11,49016,49016,11,49044,49044,11,49072,49072,11,49100,49100,11,49128,49128,11,49156,49156,11,49184,49184,11,49212,49212,11,49240,49240,11,49268,49268,11,49296,49296,11,49324,49324,11,49352,49352,11,49380,49380,11,49408,49408,11,49436,49436,11,49464,49464,11,49492,49492,11,49520,49520,11,49548,49548,11,49576,49576,11,49604,49604,11,49632,49632,11,49660,49660,11,49688,49688,11,49716,49716,11,49744,49744,11,49772,49772,11,49800,49800,11,49828,49828,11,49856,49856,11,49884,49884,11,49912,49912,11,49940,49940,11,49968,49968,11,49996,49996,11,50024,50024,11,50052,50052,11,50080,50080,11,50108,50108,11,50136,50136,11,50164,50164,11,50192,50192,11,50220,50220,11,50248,50248,11,50276,50276,11,50304,50304,11,50332,50332,11,50360,50360,11,50388,50388,11,50416,50416,11,50444,50444,11,50472,50472,11,50500,50500,11,50528,50528,11,50556,50556,11,50584,50584,11,50612,50612,11,50640,50640,11,50668,50668,11,50696,50696,11,50724,50724,11,50752,50752,11,50780,50780,11,50808,50808,11,50836,50836,11,50864,50864,11,50892,50892,11,50920,50920,11,50948,50948,11,50976,50976,11,51004,51004,11,51032,51032,11,51060,51060,11,51088,51088,11,51116,51116,11,51144,51144,11,51172,51172,11,51200,51200,11,51228,51228,11,51256,51256,11,51284,51284,11,51312,51312,11,51340,51340,11,51368,51368,11,51396,51396,11,51424,51424,11,51452,51452,11,51480,51480,11,51508,51508,11,51536,51536,11,51564,51564,11,51592,51592,11,51620,51620,11,51648,51648,11,51676,51676,11,51704,51704,11,51732,51732,11,51760,51760,11,51788,51788,11,51816,51816,11,51844,51844,11,51872,51872,11,51900,51900,11,51928,51928,11,51956,51956,11,51984,51984,11,52012,52012,11,52040,52040,11,52068,52068,11,52096,52096,11,52124,52124,11,52152,52152,11,52180,52180,11,52208,52208,11,52236,52236,11,52264,52264,11,52292,52292,11,52320,52320,11,52348,52348,11,52376,52376,11,52404,52404,11,52432,52432,11,52460,52460,11,52488,52488,11,52516,52516,11,52544,52544,11,52572,52572,11,52600,52600,11,52628,52628,11,52656,52656,11,52684,52684,11,52712,52712,11,52740,52740,11,52768,52768,11,52796,52796,11,52824,52824,11,52852,52852,11,52880,52880,11,52908,52908,11,52936,52936,11,52964,52964,11,52992,52992,11,53020,53020,11,53048,53048,11,53076,53076,11,53104,53104,11,53132,53132,11,53160,53160,11,53188,53188,11,53216,53216,11,53244,53244,11,53272,53272,11,53300,53300,11,53328,53328,11,53356,53356,11,53384,53384,11,53412,53412,11,53440,53440,11,53468,53468,11,53496,53496,11,53524,53524,11,53552,53552,11,53580,53580,11,53608,53608,11,53636,53636,11,53664,53664,11,53692,53692,11,53720,53720,11,53748,53748,11,53776,53776,11,53804,53804,11,53832,53832,11,53860,53860,11,53888,53888,11,53916,53916,11,53944,53944,11,53972,53972,11,54000,54000,11,54028,54028,11,54056,54056,11,54084,54084,11,54112,54112,11,54140,54140,11,54168,54168,11,54196,54196,11,54224,54224,11,54252,54252,11,54280,54280,11,54308,54308,11,54336,54336,11,54364,54364,11,54392,54392,11,54420,54420,11,54448,54448,11,54476,54476,11,54504,54504,11,54532,54532,11,54560,54560,11,54588,54588,11,54616,54616,11,54644,54644,11,54672,54672,11,54700,54700,11,54728,54728,11,54756,54756,11,54784,54784,11,54812,54812,11,54840,54840,11,54868,54868,11,54896,54896,11,54924,54924,11,54952,54952,11,54980,54980,11,55008,55008,11,55036,55036,11,55064,55064,11,55092,55092,11,55120,55120,11,55148,55148,11,55176,55176,11,55216,55238,9,64286,64286,5,65056,65071,5,65438,65439,5,65529,65531,4,66272,66272,5,68097,68099,5,68108,68111,5,68159,68159,5,68900,68903,5,69446,69456,5,69632,69632,7,69634,69634,7,69744,69744,5,69759,69761,5,69808,69810,7,69815,69816,7,69821,69821,1,69837,69837,1,69927,69931,5,69933,69940,5,70003,70003,5,70018,70018,7,70070,70078,5,70082,70083,1,70094,70094,7,70188,70190,7,70194,70195,7,70197,70197,7,70206,70206,5,70368,70370,7,70400,70401,5,70459,70460,5,70463,70463,7,70465,70468,7,70475,70477,7,70498,70499,7,70512,70516,5,70712,70719,5,70722,70724,5,70726,70726,5,70832,70832,5,70835,70840,5,70842,70842,5,70845,70845,5,70847,70848,5,70850,70851,5,71088,71089,7,71096,71099,7,71102,71102,7,71132,71133,5,71219,71226,5,71229,71229,5,71231,71232,5,71340,71340,7,71342,71343,7,71350,71350,7,71453,71455,5,71462,71462,7,71724,71726,7,71736,71736,7,71984,71984,5,71991,71992,7,71997,71997,7,71999,71999,1,72001,72001,1,72003,72003,5,72148,72151,5,72156,72159,7,72164,72164,7,72243,72248,5,72250,72250,1,72263,72263,5,72279,72280,7,72324,72329,1,72343,72343,7,72751,72751,7,72760,72765,5,72767,72767,5,72873,72873,7,72881,72881,7,72884,72884,7,73009,73014,5,73020,73021,5,73030,73030,1,73098,73102,7,73107,73108,7,73110,73110,7,73459,73460,5,78896,78904,4,92976,92982,5,94033,94087,7,94180,94180,5,113821,113822,5,118528,118573,5,119141,119141,5,119143,119145,5,119150,119154,5,119163,119170,5,119210,119213,5,121344,121398,5,121461,121461,5,121499,121503,5,122880,122886,5,122907,122913,5,122918,122922,5,123566,123566,5,125136,125142,5,126976,126979,14,126981,127182,14,127184,127231,14,127279,127279,14,127344,127345,14,127374,127374,14,127405,127461,14,127489,127490,14,127514,127514,14,127538,127546,14,127561,127567,14,127570,127743,14,127757,127758,14,127760,127760,14,127762,127762,14,127766,127768,14,127770,127770,14,127772,127772,14,127775,127776,14,127778,127779,14,127789,127791,14,127794,127795,14,127798,127798,14,127819,127819,14,127824,127824,14,127868,127868,14,127870,127871,14,127892,127893,14,127896,127896,14,127900,127901,14,127904,127940,14,127942,127942,14,127944,127944,14,127946,127946,14,127951,127955,14,127968,127971,14,127973,127984,14,127987,127987,14,127989,127989,14,127991,127991,14,127995,127999,5,128008,128008,14,128012,128014,14,128017,128018,14,128020,128020,14,128022,128022,14,128042,128042,14,128063,128063,14,128065,128065,14,128101,128101,14,128108,128109,14,128173,128173,14,128182,128183,14,128236,128237,14,128239,128239,14,128245,128245,14,128248,128248,14,128253,128253,14,128255,128258,14,128260,128263,14,128265,128265,14,128277,128277,14,128300,128301,14,128326,128328,14,128331,128334,14,128336,128347,14,128360,128366,14,128369,128370,14,128378,128378,14,128391,128391,14,128394,128397,14,128400,128400,14,128405,128406,14,128420,128420,14,128422,128423,14,128425,128432,14,128435,128443,14,128445,128449,14,128453,128464,14,128468,128475,14,128479,128480,14,128482,128482,14,128484,128487,14,128489,128494,14,128496,128498,14,128500,128505,14,128507,128511,14,128513,128518,14,128521,128525,14,128527,128527,14,128529,128529,14,128533,128533,14,128535,128535,14,128537,128537,14]');
1152 }
1153 > strings.ts
1154 > //#endregion
1155 >
1156 > /**
1157 > * Computes the offset after performing a left delete on the given string,
1158 > * while considering unicode grapheme/emoji rules.
1159 > */
1160 > export function getLeftDeleteOffset(offset: number, str: string): number {
1161 if (offset === 0) {
1162 return 0;
1174 return iterator.offset;
1175 }
1176 > strings.ts
1177 function getOffsetBeforeLastEmojiComponent(initialOffset: number, str: string): number | undefined {
1178 // See https://www.unicode.org/reports/tr51/tr51-14.html#EBNF_and_Regex for the
1210 return resultOffset;
1211 }
1212 > strings.ts
1213 function isEmojiModifier(codePoint: number): boolean {
1214 return 0x1F3FB <= codePoint && codePoint <= 0x1F3FF;
1215 }
1216 > strings.ts
1217 > const enum CodePoint {
1218 > zwj = 0x200D,
1219 >
1220 > /**
1221 > * Variation Selector-16 (VS16)
1222 > */
1223 > emojiVariantSelector = 0xFE0F,
1224 >
1225 > /**
1226 > * Combining Enclosing Keycap
1227 > */
1228 > enclosingKeyCap = 0x20E3,
1229 >
1230 > space = 0x0020,
1231 > }
1232 >
1233 > export const noBreakWhitespace = '\xa0';
1234 >
1235 > export class AmbiguousCharacters {
1236 > private static readonly ambiguousCharacterData = new Lazy<
1237 > Record<
1238 > string | '_common' | '_default',
1239 > /* code point -> ascii code point */ number[]
1240 > >
1241 > >(() => {
1242 // Generated using https://github.com/hediet/vscode-unicode-data
1243 // Stored as key1, value1, key2, value2, ...
1245 '{\"_common\":[8232,32,8233,32,5760,32,8192,32,8193,32,8194,32,8195,32,8196,32,8197,32,8198,32,8200,32,8201,32,8202,32,8287,32,8199,32,8239,32,2042,95,65101,95,65102,95,65103,95,8208,45,8209,45,8210,45,65112,45,1748,45,8259,45,727,45,8722,45,10134,45,11450,45,1549,44,1643,44,184,44,42233,44,894,59,2307,58,2691,58,1417,58,1795,58,1796,58,5868,58,65072,58,6147,58,6153,58,8282,58,1475,58,760,58,42889,58,8758,58,720,58,42237,58,451,33,11601,33,660,63,577,63,2429,63,5038,63,42731,63,119149,46,8228,46,1793,46,1794,46,42510,46,68176,46,1632,46,1776,46,42232,46,1373,96,65287,96,8219,96,1523,96,8242,96,1370,96,8175,96,65344,96,900,96,8189,96,8125,96,8127,96,8190,96,697,96,884,96,712,96,714,96,715,96,756,96,699,96,701,96,700,96,702,96,42892,96,1497,96,2036,96,2037,96,5194,96,5836,96,94033,96,94034,96,65339,91,10088,40,10098,40,12308,40,64830,40,65341,93,10089,41,10099,41,12309,41,64831,41,10100,123,119060,123,10101,125,65342,94,8270,42,1645,42,8727,42,66335,42,5941,47,8257,47,8725,47,8260,47,9585,47,10187,47,10744,47,119354,47,12755,47,12339,47,11462,47,20031,47,12035,47,65340,92,65128,92,8726,92,10189,92,10741,92,10745,92,119311,92,119355,92,12756,92,20022,92,12034,92,42872,38,708,94,710,94,5869,43,10133,43,66203,43,8249,60,10094,60,706,60,119350,60,5176,60,5810,60,5120,61,11840,61,12448,61,42239,61,8250,62,10095,62,707,62,119351,62,5171,62,94015,62,8275,126,732,126,8128,126,8764,126,65372,124,65293,45,118002,50,120784,50,120794,50,120804,50,120814,50,120824,50,130034,50,42842,50,423,50,1000,50,42564,50,5311,50,42735,50,119302,51,118003,51,120785,51,120795,51,120805,51,120815,51,120825,51,130035,51,42923,51,540,51,439,51,42858,51,11468,51,1248,51,94011,51,71882,51,118004,52,120786,52,120796,52,120806,52,120816,52,120826,52,130036,52,5070,52,71855,52,118005,53,120787,53,120797,53,120807,53,120817,53,120827,53,130037,53,444,53,71867,53,118006,54,120788,54,120798,54,120808,54,120818,54,120828,54,130038,54,11474,54,5102,54,71893,54,119314,55,118007,55,120789,55,120799,55,120809,55,120819,55,120829,55,130039,55,66770,55,71878,55,2819,56,2538,56,2666,56,125131,56,118008,56,120790,56,120800,56,120810,56,120820,56,120830,56,130040,56,547,56,546,56,66330,56,2663,57,2920,57,2541,57,3437,57,118009,57,120791,57,120801,57,120811,57,120821,57,120831,57,130041,57,42862,57,11466,57,71884,57,71852,57,71894,57,9082,97,65345,97,119834,97,119886,97,119938,97,119990,97,120042,97,120094,97,120146,97,120198,97,120250,97,120302,97,120354,97,120406,97,120458,97,593,97,945,97,120514,97,120572,97,120630,97,120688,97,120746,97,65313,65,117974,65,119808,65,119860,65,119912,65,119964,65,120016,65,120068,65,120120,65,120172,65,120224,65,120276,65,120328,65,120380,65,120432,65,913,65,120488,65,120546,65,120604,65,120662,65,120720,65,5034,65,5573,65,42222,65,94016,65,66208,65,119835,98,119887,98,119939,98,119991,98,120043,98,120095,98,120147,98,120199,98,120251,98,120303,98,120355,98,120407,98,120459,98,388,98,5071,98,5234,98,5551,98,65314,66,8492,66,117975,66,119809,66,119861,66,119913,66,120017,66,120069,66,120121,66,120173,66,120225,66,120277,66,120329,66,120381,66,120433,66,42932,66,914,66,120489,66,120547,66,120605,66,120663,66,120721,66,5108,66,5623,66,42192,66,66178,66,66209,66,66305,66,65347,99,8573,99,119836,99,119888,99,119940,99,119992,99,120044,99,120096,99,120148,99,120200,99,120252,99,120304,99,120356,99,120408,99,120460,99,7428,99,1010,99,11429,99,43951,99,66621,99,128844,67,71913,67,71922,67,65315,67,8557,67,8450,67,8493,67,117976,67,119810,67,119862,67,119914,67,119966,67,120018,67,120174,67,120226,67,120278,67,120330,67,120382,67,120434,67,1017,67,11428,67,5087,67,42202,67,66210,67,66306,67,66581,67,66844,67,8574,100,8518,100,119837,100,119889,100,119941,100,119993,100,120045,100,120097,100,120149,100,120201,100,120253,100,120305,100,120357,100,120409,100,120461,100,1281,100,5095,100,5231,100,42194,100,8558,68,8517,68,117977,68,119811,68,119863,68,119915,68,119967,68,120019,68,120071,68,120123,68,120175,68,120227,68,120279,68,120331,68,120383,68,120435,68,5024,68,5598,68,5610,68,42195,68,8494,101,65349,101,8495,101,8519,101,119838,101,119890,101,119942,101,120046,101,120098,101,120150,101,120202,101,120254,101,120306,101,120358,101,120410,101,120462,101,43826,101,1213,101,8959,69,65317,69,8496,69,117978,69,119812,69,119864,69,119916,69,120020,69,120072,69,120124,69,120176,69,120228,69,120280,69,120332,69,120384,69,120436,69,917,69,120492,69,120550,69,120608,69,120666,69,120724,69,11577,69,5036,69,42224,69,71846,69,71854,69,66182,69,119839,102,119891,102,119943,102,119995,102,120047,102,120099,102,120151,102,120203,102,120255,102,120307,102,120359,102,120411,102,120463,102,43829,102,42905,102,383,102,7837,102,1412,102,119315,70,8497,70,117979,70,119813,70,119865,70,119917,70,120021,70,120073,70,120125,70,120177,70,120229,70,120281,70,120333,70,120385,70,120437,70,42904,70,988,70,120778,70,5556,70,42205,70,71874,70,71842,70,66183,70,66213,70,66853,70,65351,103,8458,103,119840,103,119892,103,119944,103,120048,103,120100,103,120152,103,120204,103,120256,103,120308,103,120360,103,120412,103,120464,103,609,103,7555,103,397,103,1409,103,117980,71,119814,71,119866,71,119918,71,119970,71,120022,71,120074,71,120126,71,120178,71,120230,71,120282,71,120334,71,120386,71,120438,71,1292,71,5056,71,5107,71,42198,71,65352,104,8462,104,119841,104,119945,104,119997,104,120049,104,120101,104,120153,104,120205,104,120257,104,120309,104,120361,104,120413,104,120465,104,1211,104,1392,104,5058,104,65320,72,8459,72,8460,72,8461,72,117981,72,119815,72,119867,72,119919,72,120023,72,120179,72,120231,72,120283,72,120335,72,120387,72,120439,72,919,72,120494,72,120552,72,120610,72,120668,72,120726,72,11406,72,5051,72,5500,72,42215,72,66255,72,731,105,9075,105,65353,105,8560,105,8505,105,8520,105,119842,105,119894,105,119946,105,119998,105,120050,105,120102,105,120154,105,120206,105,120258,105,120310,105,120362,105,120414,105,120466,105,120484,105,618,105,617,105,953,105,8126,105,890,105,120522,105,120580,105,120638,105,120696,105,120754,105,1110,105,42567,105,1231,105,43893,105,5029,105,71875,105,65354,106,8521,106,119843,106,119895,106,119947,106,119999,106,120051,106,120103,106,120155,106,120207,106,120259,106,120311,106,120363,106,120415,106,120467,106,1011,106,1112,106,65322,74,117983,74,119817,74,119869,74,119921,74,119973,74,120025,74,120077,74,120129,74,120181,74,120233,74,120285,74,120337,74,120389,74,120441,74,42930,74,895,74,1032,74,5035,74,5261,74,42201,74,119844,107,119896,107,119948,107,120000,107,120052,107,120104,107,120156,107,120208,107,120260,107,120312,107,120364,107,120416,107,120468,107,8490,75,65323,75,117984,75,119818,75,119870,75,119922,75,119974,75,120026,75,120078,75,120130,75,120182,75,120234,75,120286,75,120338,75,120390,75,120442,75,922,75,120497,75,120555,75,120613,75,120671,75,120729,75,11412,75,5094,75,5845,75,42199,75,66840,75,1472,108,8739,73,9213,73,65512,73,1633,108,1777,73,66336,108,125127,108,118001,108,120783,73,120793,73,120803,73,120813,73,120823,73,130033,73,65321,73,8544,73,8464,73,8465,73,117982,108,119816,73,119868,73,119920,73,120024,73,120128,73,120180,73,120232,73,120284,73,120336,73,120388,73,120440,73,65356,108,8572,73,8467,108,119845,108,119897,108,119949,108,120001,108,120053,108,120105,73,120157,73,120209,73,120261,73,120313,73,120365,73,120417,73,120469,73,448,73,120496,73,120554,73,120612,73,120670,73,120728,73,11410,73,1030,73,1216,73,1493,108,1503,108,1575,108,126464,108,126592,108,65166,108,65165,108,1994,108,11599,73,5825,73,42226,73,93992,73,66186,124,66313,124,119338,76,8556,76,8466,76,117985,76,119819,76,119871,76,119923,76,120027,76,120079,76,120131,76,120183,76,120235,76,120287,76,120339,76,120391,76,120443,76,11472,76,5086,76,5290,76,42209,76,93974,76,71843,76,71858,76,66587,76,66854,76,65325,77,8559,77,8499,77,117986,77,119820,77,119872,77,119924,77,120028,77,120080,77,120132,77,120184,77,120236,77,120288,77,120340,77,120392,77,120444,77,924,77,120499,77,120557,77,120615,77,120673,77,120731,77,1018,77,11416,77,5047,77,5616,77,5846,77,42207,77,66224,77,66321,77,119847,110,119899,110,119951,110,120003,110,120055,110,120107,110,120159,110,120211,110,120263,110,120315,110,120367,110,120419,110,120471,110,1400,110,1404,110,65326,78,8469,78,117987,78,119821,78,119873,78,119925,78,119977,78,120029,78,120081,78,120185,78,120237,78,120289,78,120341,78,120393,78,120445,78,925,78,120500,78,120558,78,120616,78,120674,78,120732,78,11418,78,42208,78,66835,78,3074,111,3202,111,3330,111,3458,111,2406,111,2662,111,2790,111,3046,111,3174,111,3302,111,3430,111,3664,111,3792,111,4160,111,1637,111,1781,111,65359,111,8500,111,119848,111,119900,111,119952,111,120056,111,120108,111,120160,111,120212,111,120264,111,120316,111,120368,111,120420,111,120472,111,7439,111,7441,111,43837,111,959,111,120528,111,120586,111,120644,111,120702,111,120760,111,963,111,120532,111,120590,111,120648,111,120706,111,120764,111,11423,111,4351,111,1413,111,1505,111,1607,111,126500,111,126564,111,126596,111,65259,111,65260,111,65258,111,65257,111,1726,111,64428,111,64429,111,64427,111,64426,111,1729,111,64424,111,64425,111,64423,111,64422,111,1749,111,3360,111,4125,111,66794,111,71880,111,71895,111,66604,111,1984,79,2534,79,2918,79,12295,79,70864,79,71904,79,118000,79,120782,79,120792,79,120802,79,120812,79,120822,79,130032,79,65327,79,117988,79,119822,79,119874,79,119926,79,119978,79,120030,79,120082,79,120134,79,120186,79,120238,79,120290,79,120342,79,120394,79,120446,79,927,79,120502,79,120560,79,120618,79,120676,79,120734,79,11422,79,1365,79,11604,79,4816,79,2848,79,66754,79,42227,79,71861,79,66194,79,66219,79,66564,79,66838,79,9076,112,65360,112,119849,112,119901,112,119953,112,120005,112,120057,112,120109,112,120161,112,120213,112,120265,112,120317,112,120369,112,120421,112,120473,112,961,112,120530,112,120544,112,120588,112,120602,112,120646,112,120660,112,120704,112,120718,112,120762,112,120776,112,11427,112,65328,80,8473,80,117989,80,119823,80,119875,80,119927,80,119979,80,120031,80,120083,80,120187,80,120239,80,120291,80,120343,80,120395,80,120447,80,929,80,120504,80,120562,80,120620,80,120678,80,120736,80,11426,80,5090,80,5229,80,42193,80,66197,80,119850,113,119902,113,119954,113,120006,113,120058,113,120110,113,120162,113,120214,113,120266,113,120318,113,120370,113,120422,113,120474,113,1307,113,1379,113,1382,113,8474,81,117990,81,119824,81,119876,81,119928,81,119980,81,120032,81,120084,81,120188,81,120240,81,120292,81,120344,81,120396,81,120448,81,11605,81,119851,114,119903,114,119955,114,120007,114,120059,114,120111,114,120163,114,120215,114,120267,114,120319,114,120371,114,120423,114,120475,114,43847,114,43848,114,7462,114,11397,114,43905,114,119318,82,8475,82,8476,82,8477,82,117991,82,119825,82,119877,82,119929,82,120033,82,120189,82,120241,82,120293,82,120345,82,120397,82,120449,82,422,82,5025,82,5074,82,66740,82,5511,82,42211,82,94005,82,65363,115,119852,115,119904,115,119956,115,120008,115,120060,115,120112,115,120164,115,120216,115,120268,115,120320,115,120372,115,120424,115,120476,115,42801,115,445,115,1109,115,43946,115,71873,115,66632,115,65331,83,117992,83,119826,83,119878,83,119930,83,119982,83,120034,83,120086,83,120138,83,120190,83,120242,83,120294,83,120346,83,120398,83,120450,83,1029,83,1359,83,5077,83,5082,83,42210,83,94010,83,66198,83,66592,83,119853,116,119905,116,119957,116,120009,116,120061,116,120113,116,120165,116,120217,116,120269,116,120321,116,120373,116,120425,116,120477,116,8868,84,10201,84,128872,84,65332,84,117993,84,119827,84,119879,84,119931,84,119983,84,120035,84,120087,84,120139,84,120191,84,120243,84,120295,84,120347,84,120399,84,120451,84,932,84,120507,84,120565,84,120623,84,120681,84,120739,84,11430,84,5026,84,42196,84,93962,84,71868,84,66199,84,66225,84,66325,84,119854,117,119906,117,119958,117,120010,117,120062,117,120114,117,120166,117,120218,117,120270,117,120322,117,120374,117,120426,117,120478,117,42911,117,7452,117,43854,117,43858,117,651,117,965,117,120534,117,120592,117,120650,117,120708,117,120766,117,1405,117,66806,117,71896,117,8746,85,8899,85,117994,85,119828,85,119880,85,119932,85,119984,85,120036,85,120088,85,120140,85,120192,85,120244,85,120296,85,120348,85,120400,85,120452,85,1357,85,4608,85,66766,85,5196,85,42228,85,94018,85,71864,85,8744,118,8897,118,65366,118,8564,118,119855,118,119907,118,119959,118,120011,118,120063,118,120115,118,120167,118,120219,118,120271,118,120323,118,120375,118,120427,118,120479,118,7456,118,957,118,120526,118,120584,118,120642,118,120700,118,120758,118,1141,118,1496,118,71430,118,43945,118,71872,118,119309,86,1639,86,1783,86,8548,86,117995,86,119829,86,119881,86,119933,86,119985,86,120037,86,120089,86,120141,86,120193,86,120245,86,120297,86,120349,86,120401,86,120453,86,1140,86,11576,86,5081,86,5167,86,42719,86,42214,86,93960,86,71840,86,66845,86,623,119,119856,119,119908,119,119960,119,120012,119,120064,119,120116,119,120168,119,120220,119,120272,119,120324,119,120376,119,120428,119,120480,119,7457,119,1121,119,1309,119,1377,119,71434,119,71438,119,71439,119,43907,119,71910,87,71919,87,117996,87,119830,87,119882,87,119934,87,119986,87,120038,87,120090,87,120142,87,120194,87,120246,87,120298,87,120350,87,120402,87,120454,87,1308,87,5043,87,5076,87,42218,87,5742,120,10539,120,10540,120,10799,120,65368,120,8569,120,119857,120,119909,120,119961,120,120013,120,120065,120,120117,120,120169,120,120221,120,120273,120,120325,120,120377,120,120429,120,120481,120,5441,120,5501,120,5741,88,9587,88,66338,88,71916,88,65336,88,8553,88,117997,88,119831,88,119883,88,119935,88,119987,88,120039,88,120091,88,120143,88,120195,88,120247,88,120299,88,120351,88,120403,88,120455,88,42931,88,935,88,120510,88,120568,88,120626,88,120684,88,120742,88,11436,88,11613,88,5815,88,42219,88,66192,88,66228,88,66327,88,66855,88,611,121,7564,121,65369,121,119858,121,119910,121,119962,121,120014,121,120066,121,120118,121,120170,121,120222,121,120274,121,120326,121,120378,121,120430,121,120482,121,655,121,7935,121,43866,121,947,121,8509,121,120516,121,120574,121,120632,121,120690,121,120748,121,1199,121,4327,121,71900,121,65337,89,117998,89,119832,89,119884,89,119936,89,119988,89,120040,89,120092,89,120144,89,120196,89,120248,89,120300,89,120352,89,120404,89,120456,89,933,89,978,89,120508,89,120566,89,120624,89,120682,89,120740,89,11432,89,1198,89,5033,89,5053,89,42220,89,94019,89,71844,89,66226,89,119859,122,119911,122,119963,122,120015,122,120067,122,120119,122,120171,122,120223,122,120275,122,120327,122,120379,122,120431,122,120483,122,7458,122,43923,122,71876,122,71909,90,66293,90,65338,90,8484,90,8488,90,117999,90,119833,90,119885,90,119937,90,119989,90,120041,90,120197,90,120249,90,120301,90,120353,90,120405,90,120457,90,918,90,120493,90,120551,90,120609,90,120667,90,120725,90,5059,90,42204,90,71849,90,65282,34,65283,35,65284,36,65285,37,65286,38,65290,42,65291,43,65294,46,65295,47,65296,48,65298,50,65299,51,65300,52,65301,53,65302,54,65303,55,65304,56,65305,57,65308,60,65309,61,65310,62,65312,64,65316,68,65318,70,65319,71,65324,76,65329,81,65330,82,65333,85,65334,86,65335,87,65343,95,65346,98,65348,100,65350,102,65355,107,65357,109,65358,110,65361,113,65362,114,65364,116,65365,117,65367,119,65370,122,65371,123,65373,125,119846,109],\"_default\":[160,32,8211,45,65374,126,8218,44,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41,65292,44,65297,49,65307,59,65311,63],\"cs\":[65374,126,8218,44,65306,58,65281,33,8216,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41,65292,44,65297,49,65307,59,65311,63],\"de\":[65374,126,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41,65292,44,65297,49,65307,59,65311,63],\"es\":[8211,45,65374,126,8218,44,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41,65292,44,65297,49,65307,59,65311,63],\"fr\":[65374,126,8218,44,65306,58,65281,33,8216,96,8245,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41,65292,44,65297,49,65307,59,65311,63],\"it\":[160,32,8211,45,65374,126,8218,44,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41,65292,44,65297,49,65307,59,65311,63],\"ja\":[8211,45,8218,44,65281,33,8216,96,8245,96,180,96,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65292,44,65297,49,65307,59],\"ko\":[8211,45,65374,126,8218,44,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41,65292,44,65297,49,65307,59,65311,63],\"pl\":[65374,126,65306,58,65281,33,8216,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41,65292,44,65297,49,65307,59,65311,63],\"pt-BR\":[65374,126,8218,44,65306,58,65281,33,8216,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41,65292,44,65297,49,65307,59,65311,63],\"qps-ploc\":[160,32,8211,45,65374,126,8218,44,65306,58,65281,33,8216,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41,65292,44,65297,49,65307,59,65311,63],\"ru\":[65374,126,8218,44,65306,58,65281,33,8216,96,8245,96,180,96,12494,47,305,105,921,73,1009,112,215,120,65288,40,65289,41,65292,44,65297,49,65307,59,65311,63],\"tr\":[160,32,8211,45,65374,126,8218,44,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41,65292,44,65297,49,65307,59,65311,63],\"zh-hans\":[160,32,65374,126,8218,44,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65297,49],\"zh-hant\":[8211,45,65374,126,8218,44,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89]}'
1246 );
1247 > }); strings.ts
1248 >
1249 > private static readonly cache = new LRUCachedFunction<string, AmbiguousCharacters>((localesStr) => {
1250 const locales = localesStr.split(',');
1251
1304
1305 return new AmbiguousCharacters(map);
1306 > }); strings.ts
1307 >
1308 > public static getInstance(locales: Iterable<string>): AmbiguousCharacters {
1309 return AmbiguousCharacters.cache.get(Array.from(locales).join(','));
1310 }
1311 > strings.ts
1312 > private static _locales = new Lazy<string[]>(() =>
1313 Object.keys(AmbiguousCharacters.ambiguousCharacterData.value).filter(
1314 (k) => !k.startsWith('_')
1315 )
1316 > ); strings.ts
1317 > public static getLocales(): string[] {
1318 return AmbiguousCharacters._locales.value;
1319 }
1320 > strings.ts
1321 > private constructor(
1322 private readonly confusableDictionary: Map<number, number>
1323 ) { }
1324 > strings.ts
1325 > public isAmbiguous(codePoint: number): boolean {
1326 return this.confusableDictionary.has(codePoint);
1327 }
1328 > strings.ts
1329 > public containsAmbiguousCharacter(str: string): boolean {
1330 for (let i = 0; i < str.length; i++) {
1331 const codePoint = str.codePointAt(i);
1336 return false;
1337 }
1338 > strings.ts
1339 > /**
1340 > * Returns the non basic ASCII code point that the given code point can be confused,
1341 > * or undefined if such code point does note exist.
1342 > */
1343 > public getPrimaryConfusable(codePoint: number): number | undefined {
1344 return this.confusableDictionary.get(codePoint);
1345 }
1346 > strings.ts
1347 > public getConfusableCodePoints(): ReadonlySet<number> {
1348 return new Set(this.confusableDictionary.keys());
1349 }
1350 > } strings.ts
1351 >
1352 > export class InvisibleCharacters {
1353 > private static getRawData(): Record<string | '_common', number[]> {
1354 // Generated using https://github.com/hediet/vscode-unicode-data
1355 return JSON.parse('{\"_common\":[11,12,13,127,847,1564,4447,4448,6068,6069,6155,6156,6157,6158,7355,7356,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8204,8205,8206,8207,8234,8235,8236,8237,8238,8239,8287,8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,10240,12644,65024,65025,65026,65027,65028,65029,65030,65031,65032,65033,65034,65035,65036,65037,65038,65039,65279,65440,65520,65521,65522,65523,65524,65525,65526,65527,65528,65532,78844,119155,119156,119157,119158,119159,119160,119161,119162,917504,917505,917506,917507,917508,917509,917510,917511,917512,917513,917514,917515,917516,917517,917518,917519,917520,917521,917522,917523,917524,917525,917526,917527,917528,917529,917530,917531,917532,917533,917534,917535,917536,917537,917538,917539,917540,917541,917542,917543,917544,917545,917546,917547,917548,917549,917550,917551,917552,917553,917554,917555,917556,917557,917558,917559,917560,917561,917562,917563,917564,917565,917566,917567,917568,917569,917570,917571,917572,917573,917574,917575,917576,917577,917578,917579,917580,917581,917582,917583,917584,917585,917586,917587,917588,917589,917590,917591,917592,917593,917594,917595,917596,917597,917598,917599,917600,917601,917602,917603,917604,917605,917606,917607,917608,917609,917610,917611,917612,917613,917614,917615,917616,917617,917618,917619,917620,917621,917622,917623,917624,917625,917626,917627,917628,917629,917630,917631,917760,917761,917762,917763,917764,917765,917766,917767,917768,917769,917770,917771,917772,917773,917774,917775,917776,917777,917778,917779,917780,917781,917782,917783,917784,917785,917786,917787,917788,917789,917790,917791,917792,917793,917794,917795,917796,917797,917798,917799,917800,917801,917802,917803,917804,917805,917806,917807,917808,917809,917810,917811,917812,917813,917814,917815,917816,917817,917818,917819,917820,917821,917822,917823,917824,917825,917826,917827,917828,917829,917830,917831,917832,917833,917834,917835,917836,917837,917838,917839,917840,917841,917842,917843,917844,917845,917846,917847,917848,917849,917850,917851,917852,917853,917854,917855,917856,917857,917858,917859,917860,917861,917862,917863,917864,917865,917866,917867,917868,917869,917870,917871,917872,917873,917874,917875,917876,917877,917878,917879,917880,917881,917882,917883,917884,917885,917886,917887,917888,917889,917890,917891,917892,917893,917894,917895,917896,917897,917898,917899,917900,917901,917902,917903,917904,917905,917906,917907,917908,917909,917910,917911,917912,917913,917914,917915,917916,917917,917918,917919,917920,917921,917922,917923,917924,917925,917926,917927,917928,917929,917930,917931,917932,917933,917934,917935,917936,917937,917938,917939,917940,917941,917942,917943,917944,917945,917946,917947,917948,917949,917950,917951,917952,917953,917954,917955,917956,917957,917958,917959,917960,917961,917962,917963,917964,917965,917966,917967,917968,917969,917970,917971,917972,917973,917974,917975,917976,917977,917978,917979,917980,917981,917982,917983,917984,917985,917986,917987,917988,917989,917990,917991,917992,917993,917994,917995,917996,917997,917998,917999],\"cs\":[173,8203,12288],\"de\":[173,8203,12288],\"es\":[8203,12288],\"fr\":[173,8203,12288],\"it\":[160,173,12288],\"ja\":[173],\"ko\":[173,12288],\"pl\":[173,8203,12288],\"pt-BR\":[173,8203,12288],\"qps-ploc\":[160,173,8203,12288],\"ru\":[173,12288],\"tr\":[160,173,8203,12288],\"zh-hans\":[160,173,8203,12288],\"zh-hant\":[173,12288]}');
1356 }
1357 > strings.ts
1358 > private static _data: Set<number> | undefined = undefined;
1359 >
1360 > private static getData() {
1361 if (!this._data) {
1362 this._data = new Set([...Object.values(InvisibleCharacters.getRawData())].flat());
1364 return this._data;
1365 }
1366 > strings.ts
1367 > public static isInvisibleCharacter(codePoint: number): boolean {
1368 return InvisibleCharacters.getData().has(codePoint);
1369 }
1370 > strings.ts
1371 > public static containsInvisibleCharacter(str: string): boolean {
1372 for (let i = 0; i < str.length; i++) {
1373 const codePoint = str.codePointAt(i);
1378 return false;
1379 }
1380 > strings.ts
1381 > public static get codePoints(): ReadonlySet<number> {
1382 return InvisibleCharacters.getData();
1383 }
1384 > } strings.ts
1385 >
1386 > export const Ellipsis = '\u2026';
1387 >
1388 > /**
1389 > * Convert a Unicode string to a string in which each 16-bit unit occupies only one byte
1390 > *
1391 > * From https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/btoa
1392 > */
1393 function toBinary(str: string): string {
1394 const codeUnits = new Uint16Array(str.length);
1403 return binary;
1404 }
1405 > strings.ts
1406 > /**
1407 > * Version of the global `btoa` function that handles multi-byte characters instead
1408 > * of throwing an exception.
1409 > */
1410 >
1411 > export function multibyteAwareBtoa(str: string): string {
1412 return btoa(toBinary(str));
1413 }
src/vs/base/common/lifecycle.ts 479 covered LOC · 98 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- lifecycle.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 { compareBy, numberComparator } from './arrays.js';
7 > import { groupBy } from './collections.js';
8 > import { SetMap, ResourceMap } from './map.js';
9 > import { URI } from './uri.js';
10 > import { createSingleCallFunction } from './functional.js';
11 > import { Iterable } from './iterator.js';
12 > import { BugIndicatingError, onUnexpectedError } from './errors.js';
13 >
14 > // #region Disposable Tracking
15 >
16 > /**
17 > * Enables logging of potentially leaked disposables.
18 > *
19 > * A disposable is considered leaked if it is not disposed or not registered as the child of
20 > * another disposable. This tracking is very simple an only works for classes that either
21 > * extend Disposable or use a DisposableStore. This means there are a lot of false positives.
22 > */
23 > const TRACK_DISPOSABLES = false;
24 > let disposableTracker: IDisposableTracker | null = null;
25 >
26 > export interface IDisposableTracker {
27 > /**
28 > * Is called on construction of a disposable.
29 > */
30 > trackDisposable(disposable: IDisposable): void;
31 >
32 > /**
33 > * Is called when a disposable is registered as child of another disposable (e.g. {@link DisposableStore}).
34 > * If parent is `null`, the disposable is removed from its former parent.
35 > */
36 > setParent(child: IDisposable, parent: IDisposable | null): void;
37 >
38 > /**
39 > * Is called after a disposable is disposed.
40 > */
41 > markAsDisposed(disposable: IDisposable): void;
42 >
43 > /**
44 > * Indicates that the given object is a singleton which does not need to be disposed.
45 > */
46 > markAsSingleton(disposable: IDisposable): void;
47 > }
48 >
49 > export class GCBasedDisposableTracker implements IDisposableTracker {
50
51 private readonly _registry = new FinalizationRegistry<string>(heldValue => {
52 console.warn(`[LEAKED DISPOSABLE] ${heldValue}`);
53 });
55 > trackDisposable(disposable: IDisposable): void {
56 const stack = new Error('CREATED via:').stack!;
57 this._registry.register(disposable, stack, disposable);
58 }
60 > setParent(child: IDisposable, parent: IDisposable | null): void {
61 if (parent) {
62 this._registry.unregister(child);
65 }
66 }
68 > markAsDisposed(disposable: IDisposable): void {
69 this._registry.unregister(disposable);
70 }
72 > markAsSingleton(disposable: IDisposable): void {
73 this._registry.unregister(disposable);
74 }
75 > } lifecycle.ts
76 >
77 > export interface DisposableInfo {
78 > value: IDisposable;
79 > source: string | null;
80 > parent: IDisposable | null;
81 > isSingleton: boolean;
82 > idx: number;
83 > }
84 >
85 > export class DisposableTracker implements IDisposableTracker {
86 > private static idx = 0; lifecycle.ts
87 >
88 > private readonly livingDisposables = new Map<IDisposable, DisposableInfo>();
90 > private getDisposableData(d: IDisposable): DisposableInfo {
91 let val = this.livingDisposables.get(d);
92 if (!val) {
96 return val;
97 }
99 > trackDisposable(d: IDisposable): void {
100 const data = this.getDisposableData(d);
101 if (!data.source) {
104 }
105 }
106 > lifecycle.ts
107 > setParent(child: IDisposable, parent: IDisposable | null): void {
108 const data = this.getDisposableData(child);
109 data.parent = parent;
110 }
111 > lifecycle.ts
112 > markAsDisposed(x: IDisposable): void {
113 > this.livingDisposables.delete(x); lifecycle.ts
114 > }
115 > lifecycle.ts
116 > markAsSingleton(disposable: IDisposable): void {
117 this.getDisposableData(disposable).isSingleton = true;
118 }
119 > lifecycle.ts
120 > private getRootParent(data: DisposableInfo, cache: Map<DisposableInfo, DisposableInfo>): DisposableInfo {
121 const cacheValue = cache.get(data);
122 if (cacheValue) {
128 return result;
129 }
130 > lifecycle.ts
131 > getTrackedDisposables(): IDisposable[] {
132 const rootParentCache = new Map<DisposableInfo, DisposableInfo>();
133
138 return leaking;
139 }
140 > lifecycle.ts
141 > computeLeakingDisposables(maxReported = 10, preComputedLeaks?: DisposableInfo[]): { leaks: DisposableInfo[]; details: string } | undefined {
142 > let uncoveredLeakingObjs: DisposableInfo[] | undefined; lifecycle.ts
143 > if (preComputedLeaks) {
144 uncoveredLeakingObjs = preComputedLeaks;
145 > } else { lifecycle.ts
146 > const rootParentCache = new Map<DisposableInfo, DisposableInfo>();
147 >
148 > const leakingObjects = [...this.livingDisposables.values()]
149 > .filter((info) => info.source !== null && !this.getRootParent(info, rootParentCache).isSingleton);
150 >
151 > if (leakingObjects.length === 0) {
152 > return; lifecycle.ts
153 > }
154 const leakingObjsSet = new Set(leakingObjects.map(o => o.value));
155
162 throw new Error('There are cyclic diposable chains!');
163 }
164 > } lifecycle.ts
165
166 if (!uncoveredLeakingObjs) {
224
225 return { leaks: uncoveredLeakingObjs, details: message };
226 > } lifecycle.ts
227 > } lifecycle.ts
228 >
229 > export function setDisposableTracker(tracker: IDisposableTracker | null): void {
230 > disposableTracker = tracker; lifecycle.ts
231 > }
232 > lifecycle.ts
233 > if (TRACK_DISPOSABLES) {
234 const __is_disposable_tracked__ = '__is_disposable_tracked__';
235 setDisposableTracker(new class implements IDisposableTracker {
268 });
269 }
270 > lifecycle.ts
271 > export function trackDisposable<T extends IDisposable>(x: T): T {
272 > disposableTracker?.trackDisposable(x); lifecycle.ts
273 > return x;
274 > }
275 > lifecycle.ts
276 > export function markAsDisposed(disposable: IDisposable): void {
277 > disposableTracker?.markAsDisposed(disposable); lifecycle.ts
278 > }
279 > lifecycle.ts
280 function setParentOfDisposable(child: IDisposable, parent: IDisposable | null): void {
281 disposableTracker?.setParent(child, parent);
282 }
283 > lifecycle.ts
284 function setParentOfDisposables(children: IDisposable[], parent: IDisposable | null): void {
285 if (!disposableTracker) {
290 }
291 }
292 > lifecycle.ts
293 > /**
294 > * Indicates that the given object is a singleton which does not need to be disposed.
295 > */
296 > export function markAsSingleton<T extends IDisposable>(singleton: T): T {
297 disposableTracker?.markAsSingleton(singleton);
298 return singleton;
299 }
300 > lifecycle.ts
301 > // #endregion
302 >
303 > /**
304 > * An object that performs a cleanup operation when `.dispose()` is called.
305 > *
306 > * Some examples of how disposables are used:
307 > *
308 > * - An event listener that removes itself when `.dispose()` is called.
309 > * - A resource such as a file system watcher that cleans up the resource when `.dispose()` is called.
310 > * - The return value from registering a provider. When `.dispose()` is called, the provider is unregistered.
311 > */
312 > export interface IDisposable {
313 > dispose(): void;
314 > }
315 >
316 > /**
317 > * Check if `thing` is {@link IDisposable disposable}.
318 > */
319 > export function isDisposable<E>(thing: E): thing is E & IDisposable {
320 // eslint-disable-next-line local/code-no-any-casts
321 return typeof thing === 'object' && thing !== null && typeof (<IDisposable><any>thing).dispose === 'function' && (<IDisposable><any>thing).dispose.length === 0;
322 }
323 > lifecycle.ts
324 > /**
325 > * Disposes of the value(s) passed in.
326 > */
327 > export function dispose<T extends IDisposable>(disposable: T): T;
328 > export function dispose<T extends IDisposable>(disposable: T | undefined): T | undefined;
329 > export function dispose<T extends IDisposable, A extends Iterable<T> = Iterable<T>>(disposables: A): A;
330 > export function dispose<T extends IDisposable>(disposables: Array<T>): Array<T>;
331 > export function dispose<T extends IDisposable>(disposables: ReadonlyArray<T>): ReadonlyArray<T>;
332 > export function dispose<T extends IDisposable>(arg: T | Iterable<T> | undefined): any {
333 if (Iterable.is(arg)) {
334 const errors: any[] = [];
356 }
357 }
358 > lifecycle.ts
359 > export function disposeIfDisposable<T extends IDisposable | object>(disposables: Array<T>): Array<T> {
360 for (const d of disposables) {
361 if (isDisposable(d)) {
365 return [];
366 }
367 > lifecycle.ts
368 > /**
369 > * Combine multiple disposable values into a single {@link IDisposable}.
370 > */
371 > export function combinedDisposable(...disposables: IDisposable[]): IDisposable {
372 const parent = toDisposable(() => dispose(disposables));
373 setParentOfDisposables(disposables, parent);
374 return parent;
375 }
376 > lifecycle.ts
377 > class FunctionDisposable implements IDisposable {
378 > private _isDisposed: boolean;
379 > private readonly _fn: () => void;
380 >
381 > constructor(fn: () => void) {
382 this._isDisposed = false;
383 this._fn = fn;
384 trackDisposable(this);
385 }
386 > lifecycle.ts
387 > dispose() {
388 if (this._isDisposed) {
389 return;
396 this._fn();
397 }
398 > } lifecycle.ts
399 >
400 > /**
401 > * Turn a function that implements dispose into an {@link IDisposable}.
402 > *
403 > * @param fn Clean up function, guaranteed to be called only **once**.
404 > */
405 > export function toDisposable(fn: () => void): IDisposable {
406 return new FunctionDisposable(fn);
407 }
408 > lifecycle.ts
409 > /**
410 > * Manages a collection of disposable values.
411 > *
412 > * This is the preferred way to manage multiple disposables. A `DisposableStore` is safer to work with than an
413 > * `IDisposable[]` as it considers edge cases, such as registering the same value multiple times or adding an item to a
414 > * store that has already been disposed of.
415 > */
416 > export class DisposableStore implements IDisposable {
417 >
418 > static DISABLE_DISPOSED_WARNING = false;
419 >
420 > private readonly _toDispose = new Set<IDisposable>();
421 > private _isDisposed = false;
422 >
423 > constructor() {
424 > trackDisposable(this); lifecycle.ts
425 > }
426 > lifecycle.ts
427 > /**
428 > * Dispose of all registered disposables and mark this object as disposed.
429 > *
430 > * Any future disposables added to this object will be disposed of on `add`.
431 > */
432 > public dispose(): void {
433 > if (this._isDisposed) { lifecycle.ts
434 return;
435 }
436 > lifecycle.ts
437 > markAsDisposed(this);
438 > this._isDisposed = true;
439 > this.clear();
440 > }
441 > lifecycle.ts
442 > /**
443 > * @return `true` if this object has been disposed of.
444 > */
445 > public get isDisposed(): boolean {
446 return this._isDisposed;
447 }
448 > lifecycle.ts
449 > /**
450 > * Dispose of all registered disposables but do not mark this object as disposed.
451 > */
452 > public clear(): void {
453 > if (this._toDispose.size === 0) { lifecycle.ts
454 > return; lifecycle.ts
455 > }
456
457 try {
460 this._toDispose.clear();
461 }
462 > } lifecycle.ts
463 > lifecycle.ts
464 > /**
465 > * Add a new {@link IDisposable disposable} to the collection.
466 > */
467 > public add<T extends IDisposable>(o: T): T {
468 if (!o || o === Disposable.None) {
469 return o;
484 return o;
485 }
486 > lifecycle.ts
487 > /**
488 > * Deletes a disposable from store and disposes of it. This will not throw or warn and proceed to dispose the
489 > * disposable even when the disposable is not part in the store.
490 > */
491 > public delete<T extends IDisposable>(o: T): void {
492 if (!o) {
493 return;
499 o.dispose();
500 }
501 > lifecycle.ts
502 > /**
503 > * Deletes the value from the store, but does not dispose it.
504 > */
505 > public deleteAndLeak<T extends IDisposable>(o: T): void {
506 if (!o) {
507 return;
511 }
512 }
513 > lifecycle.ts
514 > public assertNotDisposed(): void {
515 if (this._isDisposed) {
516 onUnexpectedError(new BugIndicatingError('Object disposed'));
517 }
518 }
519 > } lifecycle.ts
520 >
521 > /**
522 > * Abstract base class for a {@link IDisposable disposable} object.
523 > *
524 > * Subclasses can {@linkcode _register} disposables that will be automatically cleaned up when this object is disposed of.
525 > */
526 > export abstract class Disposable implements IDisposable {
527 >
528 > /**
529 > * A disposable that does nothing when it is disposed of.
530 > *
531 > * TODO: This should not be a static property.
532 > */
533 > static readonly None = Object.freeze<IDisposable>({ dispose() { } });
534 >
535 > protected readonly _store = new DisposableStore();
536 >
537 > constructor() {
538 trackDisposable(this);
539 setParentOfDisposable(this._store, this);
540 }
541 > lifecycle.ts
542 > public dispose(): void {
543 markAsDisposed(this);
544
545 this._store.dispose();
546 }
547 > lifecycle.ts
548 > /**
549 > * Adds `o` to the collection of disposables managed by this object.
550 > */
551 > protected _register<T extends IDisposable>(o: T): T {
552 if ((o as unknown as Disposable) === this) {
553 throw new Error('Cannot register a disposable on itself!');
555 return this._store.add(o);
556 }
557 > } lifecycle.ts
558 >
559 > /**
560 > * Manages the lifecycle of a disposable value that may be changed.
561 > *
562 > * This ensures that when the disposable value is changed, the previously held disposable is disposed of. You can
563 > * also register a `MutableDisposable` on a `Disposable` to ensure it is automatically cleaned up.
564 > */
565 > export class MutableDisposable<T extends IDisposable> implements IDisposable {
566 > private _value?: T;
567 > private _isDisposed = false;
568 >
569 > constructor() {
570 trackDisposable(this);
571 }
572 > lifecycle.ts
573 > /**
574 > * Get the currently held disposable value, or `undefined` if this MutableDisposable has been disposed
575 > */
576 > get value(): T | undefined {
577 return this._isDisposed ? undefined : this._value;
578 }
579 > lifecycle.ts
580 > /**
581 > * Set a new disposable value.
582 > *
583 > * Behaviour:
584 > * - If the MutableDisposable has been disposed, the setter is a no-op.
585 > * - If the new value is strictly equal to the current value, the setter is a no-op.
586 > * - Otherwise the previous value (if any) is disposed and the new value is stored.
587 > *
588 > * Related helpers:
589 > * - clear() resets the value to `undefined` (and disposes the previous value).
590 > * - clearAndLeak() returns the old value without disposing it and removes its parent.
591 > */
592 > set value(value: T | undefined) {
593 if (this._isDisposed || value === this._value) {
594 return;
601 this._value = value;
602 }
603 > lifecycle.ts
604 > /**
605 > * Resets the stored value and disposed of the previously stored value.
606 > */
607 > clear(): void {
608 this.value = undefined;
609 }
610 > lifecycle.ts
611 > dispose(): void {
612 this._isDisposed = true;
613 markAsDisposed(this);
615 this._value = undefined;
616 }
617 > lifecycle.ts
618 > /**
619 > * Clears the value, but does not dispose it.
620 > * The old value is returned.
621 > */
622 > clearAndLeak(): T | undefined {
623 const oldValue = this._value;
624 this._value = undefined;
628 return oldValue;
629 }
630 > } lifecycle.ts
631 >
632 > /**
633 > * Manages the lifecycle of a disposable value that may be changed like {@link MutableDisposable}, but the value must
634 > * exist and cannot be undefined.
635 > */
636 > export class MandatoryMutableDisposable<T extends IDisposable> implements IDisposable {
637 > private readonly _disposable = new MutableDisposable<T>();
638 > private _isDisposed = false;
639 >
640 > constructor(initialValue: T) {
641 this._disposable.value = initialValue;
642 }
643 > lifecycle.ts
644 > get value(): T {
645 return this._disposable.value!;
646 }
647 > lifecycle.ts
648 > set value(value: T) {
649 if (this._isDisposed || value === this._disposable.value) {
650 return;
652 this._disposable.value = value;
653 }
654 > lifecycle.ts
655 > dispose() {
656 this._isDisposed = true;
657 this._disposable.dispose();
658 }
659 > } lifecycle.ts
660 >
661 > export class RefCountedDisposable {
662 >
663 > private _counter: number = 1;
664 >
665 > constructor(
666 private readonly _disposable: IDisposable,
667 ) { }
668 > lifecycle.ts
669 > acquire() {
670 this._counter++;
671 return this;
672 }
673 > lifecycle.ts
674 > release() {
675 if (--this._counter === 0) {
676 this._disposable.dispose();
678 return this;
679 }
680 > } lifecycle.ts
681 >
682 > export interface IReference<T> extends IDisposable {
683 > readonly object: T;
684 > }
685 >
686 > export abstract class ReferenceCollection<T> {
687
688 private readonly references: Map<string, { readonly object: T; counter: number }> = new Map();
689 > lifecycle.ts
690 > acquire(key: string, ...args: unknown[]): IReference<T> {
691 let reference = this.references.get(key);
692
708 return { object, dispose };
709 }
710 > lifecycle.ts
711 > protected abstract createReferencedObject(key: string, ...args: unknown[]): T;
712 > protected abstract destroyReferencedObject(key: string, object: T): void;
713 > }
714 >
715 > /**
716 > * Unwraps a reference collection of promised values. Makes sure
717 > * references are disposed whenever promises get rejected.
718 > */
719 > export class AsyncReferenceCollection<T> {
720 >
721 > constructor(private referenceCollection: ReferenceCollection<Promise<T>>) { }
722 >
723 > async acquire(key: string, ...args: unknown[]): Promise<IReference<T>> {
724 const ref = this.referenceCollection.acquire(key, ...args);
725
736 }
737 }
738 > } lifecycle.ts
739 >
740 > export class ImmortalReference<T> implements IReference<T> {
741 > constructor(public object: T) { }
742 > dispose(): void { /* noop */ }
743 > }
744 >
745 > export function disposeOnReturn(fn: (store: DisposableStore) => void): void {
746 const store = new DisposableStore();
747 try {
751 }
752 }
753 > lifecycle.ts
754 > /**
755 > * A map the manages the lifecycle of the values that it stores.
756 > */
757 > export class DisposableMap<K, V extends IDisposable = IDisposable> implements IDisposable {
758 >
759 > private readonly _store: Map<K, V>;
760 > private _isDisposed = false;
761 >
762 > constructor(store: Map<K, V> = new Map<K, V>()) {
763 this._store = store;
764 trackDisposable(this);
765 }
766 > lifecycle.ts
767 > /**
768 > * Disposes of all stored values and mark this object as disposed.
769 > *
770 > * Trying to use this object after it has been disposed of is an error.
771 > */
772 > dispose(): void {
773 markAsDisposed(this);
774 this._isDisposed = true;
775 this.clearAndDisposeAll();
776 }
777 > lifecycle.ts
778 > /**
779 > * Disposes of all stored values and clear the map, but DO NOT mark this object as disposed.
780 > */
781 > clearAndDisposeAll(): void {
782 if (!this._store.size) {
783 return;
790 }
791 }
792 > lifecycle.ts
793 > has(key: K): boolean {
794 return this._store.has(key);
795 }
796 > lifecycle.ts
797 > get size(): number {
798 return this._store.size;
799 }
800 > lifecycle.ts
801 > get(key: K): V | undefined {
802 return this._store.get(key);
803 }
804 > lifecycle.ts
805 > set(key: K, value: V, skipDisposeOnOverwrite = false): void {
806 if (this._isDisposed) {
807 console.warn(new Error('Trying to add a disposable to a DisposableMap that has already been disposed of. The added object will be leaked!').stack);
815 setParentOfDisposable(value, this);
816 }
817 > lifecycle.ts
818 > /**
819 > * Delete the value stored for `key` from this map and also dispose of it.
820 > */
821 > deleteAndDispose(key: K): void {
822 this._store.get(key)?.dispose();
823 this._store.delete(key);
824 }
825 > lifecycle.ts
826 > /**
827 > * Delete the value stored for `key` from this map but return it. The caller is
828 > * responsible for disposing of the value.
829 > */
830 > deleteAndLeak(key: K): V | undefined {
831 const value = this._store.get(key);
832 if (value) {
836 return value;
837 }
838 > lifecycle.ts
839 > keys(): IterableIterator<K> {
840 return this._store.keys();
841 }
842 > lifecycle.ts
843 > values(): IterableIterator<V> {
844 return this._store.values();
845 }
846 > lifecycle.ts
847 > [Symbol.iterator](): IterableIterator<[K, V]> {
848 return this._store[Symbol.iterator]();
849 }
850 > } lifecycle.ts
851 >
852 > /**
853 > * A set that manages the lifecycle of the values that it stores.
854 > */
855 > export class DisposableSet<V extends IDisposable = IDisposable> implements IDisposable {
856 >
857 > private readonly _store: Set<V>;
858 > private _isDisposed = false;
859 >
860 > constructor(store: Set<V> = new Set<V>()) {
861 this._store = store;
862 trackDisposable(this);
863 }
864 > lifecycle.ts
865 > /**
866 > * Disposes of all stored values and mark this object as disposed.
867 > *
868 > * Trying to use this object after it has been disposed of is an error.
869 > */
870 > dispose(): void {
871 markAsDisposed(this);
872 this._isDisposed = true;
873 this.clearAndDisposeAll();
874 }
875 > lifecycle.ts
876 > /**
877 > * Disposes of all stored values and clear the set, but DO NOT mark this object as disposed.
878 > */
879 > clearAndDisposeAll(): void {
880 if (!this._store.size) {
881 return;
888 }
889 }
890 > lifecycle.ts
891 > has(value: V): boolean {
892 return this._store.has(value);
893 }
894 > lifecycle.ts
895 > get size(): number {
896 return this._store.size;
897 }
898 > lifecycle.ts
899 > add(value: V): void {
900 if (this._isDisposed) {
901 console.warn(new Error('Trying to add a disposable to a DisposableSet that has already been disposed of. The added object will be leaked!').stack);
905 setParentOfDisposable(value, this);
906 }
907 > lifecycle.ts
908 > /**
909 > * Delete the value from this set and also dispose of it.
910 > */
911 > deleteAndDispose(value: V): void {
912 if (this._store.delete(value)) {
913 value.dispose();
914 }
915 }
916 > lifecycle.ts
917 > /**
918 > * Delete the value from this set but return it. The caller is
919 > * responsible for disposing of the value.
920 > */
921 > deleteAndLeak(value: V): V | undefined {
922 if (this._store.delete(value)) {
923 setParentOfDisposable(value, null);
926 return undefined;
927 }
928 > lifecycle.ts
929 > values(): IterableIterator<V> {
930 return this._store.values();
931 }
932 > lifecycle.ts
933 > [Symbol.iterator](): IterableIterator<V> {
934 return this._store[Symbol.iterator]();
935 }
936 > } lifecycle.ts
937 >
938 > /**
939 > * Call `then` on a Promise, unless the returned disposable is disposed.
940 > */
941 > export function thenIfNotDisposed<T>(promise: Promise<T>, then: (result: T) => void): IDisposable {
942 let disposed = false;
943 promise.then(result => {
951 });
952 }
953 > lifecycle.ts
954 > /**
955 > * Call `then` on a promise that resolves to a {@link IDisposable}, then either register the
956 > * disposable or register it to the {@link DisposableStore}, depending on whether the store is
957 > * disposed or not.
958 > */
959 > export function thenRegisterOrDispose<T extends IDisposable>(promise: Promise<T>, store: DisposableStore): Promise<T> {
960 return promise.then(disposable => {
961 if (store.isDisposed) {
967 });
968 }
969 > lifecycle.ts
970 > export class DisposableResourceMap<V extends IDisposable = IDisposable> extends DisposableMap<URI, V> {
971 > constructor() {
972 super(new ResourceMap());
973 }
974 > } lifecycle.ts
src/vs/base/common/charCode.ts 450 covered LOC · 1 range

Open complete file

1 > /*--------------------------------------------------------------------------------------------- charCode.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 > // Names from https://blog.codinghorror.com/ascii-pronunciation-rules-for-programmers/
7 >
8 > /**
9 > * An inlined enum containing useful character codes (to be used with String.charCodeAt).
10 > * Please leave the const keyword such that it gets inlined when compiled to JavaScript!
11 > */
12 > export const enum CharCode {
13 > Null = 0,
14 > /**
15 > * The `\b` character.
16 > */
17 > Backspace = 8,
18 > /**
19 > * The `\t` character.
20 > */
21 > Tab = 9,
22 > /**
23 > * The `\n` character.
24 > */
25 > LineFeed = 10,
26 > /**
27 > * The `\r` character.
28 > */
29 > CarriageReturn = 13,
30 > Space = 32,
31 > /**
32 > * The `!` character.
33 > */
34 > ExclamationMark = 33,
35 > /**
36 > * The `"` character.
37 > */
38 > DoubleQuote = 34,
39 > /**
40 > * The `#` character.
41 > */
42 > Hash = 35,
43 > /**
44 > * The `$` character.
45 > */
46 > DollarSign = 36,
47 > /**
48 > * The `%` character.
49 > */
50 > PercentSign = 37,
51 > /**
52 > * The `&` character.
53 > */
54 > Ampersand = 38,
55 > /**
56 > * The `'` character.
57 > */
58 > SingleQuote = 39,
59 > /**
60 > * The `(` character.
61 > */
62 > OpenParen = 40,
63 > /**
64 > * The `)` character.
65 > */
66 > CloseParen = 41,
67 > /**
68 > * The `*` character.
69 > */
70 > Asterisk = 42,
71 > /**
72 > * The `+` character.
73 > */
74 > Plus = 43,
75 > /**
76 > * The `,` character.
77 > */
78 > Comma = 44,
79 > /**
80 > * The `-` character.
81 > */
82 > Dash = 45,
83 > /**
84 > * The `.` character.
85 > */
86 > Period = 46,
87 > /**
88 > * The `/` character.
89 > */
90 > Slash = 47,
91 >
92 > Digit0 = 48,
93 > Digit1 = 49,
94 > Digit2 = 50,
95 > Digit3 = 51,
96 > Digit4 = 52,
97 > Digit5 = 53,
98 > Digit6 = 54,
99 > Digit7 = 55,
100 > Digit8 = 56,
101 > Digit9 = 57,
102 >
103 > /**
104 > * The `:` character.
105 > */
106 > Colon = 58,
107 > /**
108 > * The `;` character.
109 > */
110 > Semicolon = 59,
111 > /**
112 > * The `<` character.
113 > */
114 > LessThan = 60,
115 > /**
116 > * The `=` character.
117 > */
118 > Equals = 61,
119 > /**
120 > * The `>` character.
121 > */
122 > GreaterThan = 62,
123 > /**
124 > * The `?` character.
125 > */
126 > QuestionMark = 63,
127 > /**
128 > * The `@` character.
129 > */
130 > AtSign = 64,
131 >
132 > A = 65,
133 > B = 66,
134 > C = 67,
135 > D = 68,
136 > E = 69,
137 > F = 70,
138 > G = 71,
139 > H = 72,
140 > I = 73,
141 > J = 74,
142 > K = 75,
143 > L = 76,
144 > M = 77,
145 > N = 78,
146 > O = 79,
147 > P = 80,
148 > Q = 81,
149 > R = 82,
150 > S = 83,
151 > T = 84,
152 > U = 85,
153 > V = 86,
154 > W = 87,
155 > X = 88,
156 > Y = 89,
157 > Z = 90,
158 >
159 > /**
160 > * The `[` character.
161 > */
162 > OpenSquareBracket = 91,
163 > /**
164 > * The `\` character.
165 > */
166 > Backslash = 92,
167 > /**
168 > * The `]` character.
169 > */
170 > CloseSquareBracket = 93,
171 > /**
172 > * The `^` character.
173 > */
174 > Caret = 94,
175 > /**
176 > * The `_` character.
177 > */
178 > Underline = 95,
179 > /**
180 > * The ``(`)`` character.
181 > */
182 > BackTick = 96,
183 >
184 > a = 97,
185 > b = 98,
186 > c = 99,
187 > d = 100,
188 > e = 101,
189 > f = 102,
190 > g = 103,
191 > h = 104,
192 > i = 105,
193 > j = 106,
194 > k = 107,
195 > l = 108,
196 > m = 109,
197 > n = 110,
198 > o = 111,
199 > p = 112,
200 > q = 113,
201 > r = 114,
202 > s = 115,
203 > t = 116,
204 > u = 117,
205 > v = 118,
206 > w = 119,
207 > x = 120,
208 > y = 121,
209 > z = 122,
210 >
211 > /**
212 > * The `{` character.
213 > */
214 > OpenCurlyBrace = 123,
215 > /**
216 > * The `|` character.
217 > */
218 > Pipe = 124,
219 > /**
220 > * The `}` character.
221 > */
222 > CloseCurlyBrace = 125,
223 > /**
224 > * The `~` character.
225 > */
226 > Tilde = 126,
227 >
228 > /**
229 > * The &nbsp; (no-break space) character.
230 > * Unicode Character 'NO-BREAK SPACE' (U+00A0)
231 > */
232 > NoBreakSpace = 160,
233 >
234 > U_Combining_Grave_Accent = 0x0300, // U+0300 Combining Grave Accent
235 > U_Combining_Acute_Accent = 0x0301, // U+0301 Combining Acute Accent
236 > U_Combining_Circumflex_Accent = 0x0302, // U+0302 Combining Circumflex Accent
237 > U_Combining_Tilde = 0x0303, // U+0303 Combining Tilde
238 > U_Combining_Macron = 0x0304, // U+0304 Combining Macron
239 > U_Combining_Overline = 0x0305, // U+0305 Combining Overline
240 > U_Combining_Breve = 0x0306, // U+0306 Combining Breve
241 > U_Combining_Dot_Above = 0x0307, // U+0307 Combining Dot Above
242 > U_Combining_Diaeresis = 0x0308, // U+0308 Combining Diaeresis
243 > U_Combining_Hook_Above = 0x0309, // U+0309 Combining Hook Above
244 > U_Combining_Ring_Above = 0x030A, // U+030A Combining Ring Above
245 > U_Combining_Double_Acute_Accent = 0x030B, // U+030B Combining Double Acute Accent
246 > U_Combining_Caron = 0x030C, // U+030C Combining Caron
247 > U_Combining_Vertical_Line_Above = 0x030D, // U+030D Combining Vertical Line Above
248 > U_Combining_Double_Vertical_Line_Above = 0x030E, // U+030E Combining Double Vertical Line Above
249 > U_Combining_Double_Grave_Accent = 0x030F, // U+030F Combining Double Grave Accent
250 > U_Combining_Candrabindu = 0x0310, // U+0310 Combining Candrabindu
251 > U_Combining_Inverted_Breve = 0x0311, // U+0311 Combining Inverted Breve
252 > U_Combining_Turned_Comma_Above = 0x0312, // U+0312 Combining Turned Comma Above
253 > U_Combining_Comma_Above = 0x0313, // U+0313 Combining Comma Above
254 > U_Combining_Reversed_Comma_Above = 0x0314, // U+0314 Combining Reversed Comma Above
255 > U_Combining_Comma_Above_Right = 0x0315, // U+0315 Combining Comma Above Right
256 > U_Combining_Grave_Accent_Below = 0x0316, // U+0316 Combining Grave Accent Below
257 > U_Combining_Acute_Accent_Below = 0x0317, // U+0317 Combining Acute Accent Below
258 > U_Combining_Left_Tack_Below = 0x0318, // U+0318 Combining Left Tack Below
259 > U_Combining_Right_Tack_Below = 0x0319, // U+0319 Combining Right Tack Below
260 > U_Combining_Left_Angle_Above = 0x031A, // U+031A Combining Left Angle Above
261 > U_Combining_Horn = 0x031B, // U+031B Combining Horn
262 > U_Combining_Left_Half_Ring_Below = 0x031C, // U+031C Combining Left Half Ring Below
263 > U_Combining_Up_Tack_Below = 0x031D, // U+031D Combining Up Tack Below
264 > U_Combining_Down_Tack_Below = 0x031E, // U+031E Combining Down Tack Below
265 > U_Combining_Plus_Sign_Below = 0x031F, // U+031F Combining Plus Sign Below
266 > U_Combining_Minus_Sign_Below = 0x0320, // U+0320 Combining Minus Sign Below
267 > U_Combining_Palatalized_Hook_Below = 0x0321, // U+0321 Combining Palatalized Hook Below
268 > U_Combining_Retroflex_Hook_Below = 0x0322, // U+0322 Combining Retroflex Hook Below
269 > U_Combining_Dot_Below = 0x0323, // U+0323 Combining Dot Below
270 > U_Combining_Diaeresis_Below = 0x0324, // U+0324 Combining Diaeresis Below
271 > U_Combining_Ring_Below = 0x0325, // U+0325 Combining Ring Below
272 > U_Combining_Comma_Below = 0x0326, // U+0326 Combining Comma Below
273 > U_Combining_Cedilla = 0x0327, // U+0327 Combining Cedilla
274 > U_Combining_Ogonek = 0x0328, // U+0328 Combining Ogonek
275 > U_Combining_Vertical_Line_Below = 0x0329, // U+0329 Combining Vertical Line Below
276 > U_Combining_Bridge_Below = 0x032A, // U+032A Combining Bridge Below
277 > U_Combining_Inverted_Double_Arch_Below = 0x032B, // U+032B Combining Inverted Double Arch Below
278 > U_Combining_Caron_Below = 0x032C, // U+032C Combining Caron Below
279 > U_Combining_Circumflex_Accent_Below = 0x032D, // U+032D Combining Circumflex Accent Below
280 > U_Combining_Breve_Below = 0x032E, // U+032E Combining Breve Below
281 > U_Combining_Inverted_Breve_Below = 0x032F, // U+032F Combining Inverted Breve Below
282 > U_Combining_Tilde_Below = 0x0330, // U+0330 Combining Tilde Below
283 > U_Combining_Macron_Below = 0x0331, // U+0331 Combining Macron Below
284 > U_Combining_Low_Line = 0x0332, // U+0332 Combining Low Line
285 > U_Combining_Double_Low_Line = 0x0333, // U+0333 Combining Double Low Line
286 > U_Combining_Tilde_Overlay = 0x0334, // U+0334 Combining Tilde Overlay
287 > U_Combining_Short_Stroke_Overlay = 0x0335, // U+0335 Combining Short Stroke Overlay
288 > U_Combining_Long_Stroke_Overlay = 0x0336, // U+0336 Combining Long Stroke Overlay
289 > U_Combining_Short_Solidus_Overlay = 0x0337, // U+0337 Combining Short Solidus Overlay
290 > U_Combining_Long_Solidus_Overlay = 0x0338, // U+0338 Combining Long Solidus Overlay
291 > U_Combining_Right_Half_Ring_Below = 0x0339, // U+0339 Combining Right Half Ring Below
292 > U_Combining_Inverted_Bridge_Below = 0x033A, // U+033A Combining Inverted Bridge Below
293 > U_Combining_Square_Below = 0x033B, // U+033B Combining Square Below
294 > U_Combining_Seagull_Below = 0x033C, // U+033C Combining Seagull Below
295 > U_Combining_X_Above = 0x033D, // U+033D Combining X Above
296 > U_Combining_Vertical_Tilde = 0x033E, // U+033E Combining Vertical Tilde
297 > U_Combining_Double_Overline = 0x033F, // U+033F Combining Double Overline
298 > U_Combining_Grave_Tone_Mark = 0x0340, // U+0340 Combining Grave Tone Mark
299 > U_Combining_Acute_Tone_Mark = 0x0341, // U+0341 Combining Acute Tone Mark
300 > U_Combining_Greek_Perispomeni = 0x0342, // U+0342 Combining Greek Perispomeni
301 > U_Combining_Greek_Koronis = 0x0343, // U+0343 Combining Greek Koronis
302 > U_Combining_Greek_Dialytika_Tonos = 0x0344, // U+0344 Combining Greek Dialytika Tonos
303 > U_Combining_Greek_Ypogegrammeni = 0x0345, // U+0345 Combining Greek Ypogegrammeni
304 > U_Combining_Bridge_Above = 0x0346, // U+0346 Combining Bridge Above
305 > U_Combining_Equals_Sign_Below = 0x0347, // U+0347 Combining Equals Sign Below
306 > U_Combining_Double_Vertical_Line_Below = 0x0348, // U+0348 Combining Double Vertical Line Below
307 > U_Combining_Left_Angle_Below = 0x0349, // U+0349 Combining Left Angle Below
308 > U_Combining_Not_Tilde_Above = 0x034A, // U+034A Combining Not Tilde Above
309 > U_Combining_Homothetic_Above = 0x034B, // U+034B Combining Homothetic Above
310 > U_Combining_Almost_Equal_To_Above = 0x034C, // U+034C Combining Almost Equal To Above
311 > U_Combining_Left_Right_Arrow_Below = 0x034D, // U+034D Combining Left Right Arrow Below
312 > U_Combining_Upwards_Arrow_Below = 0x034E, // U+034E Combining Upwards Arrow Below
313 > U_Combining_Grapheme_Joiner = 0x034F, // U+034F Combining Grapheme Joiner
314 > U_Combining_Right_Arrowhead_Above = 0x0350, // U+0350 Combining Right Arrowhead Above
315 > U_Combining_Left_Half_Ring_Above = 0x0351, // U+0351 Combining Left Half Ring Above
316 > U_Combining_Fermata = 0x0352, // U+0352 Combining Fermata
317 > U_Combining_X_Below = 0x0353, // U+0353 Combining X Below
318 > U_Combining_Left_Arrowhead_Below = 0x0354, // U+0354 Combining Left Arrowhead Below
319 > U_Combining_Right_Arrowhead_Below = 0x0355, // U+0355 Combining Right Arrowhead Below
320 > U_Combining_Right_Arrowhead_And_Up_Arrowhead_Below = 0x0356, // U+0356 Combining Right Arrowhead And Up Arrowhead Below
321 > U_Combining_Right_Half_Ring_Above = 0x0357, // U+0357 Combining Right Half Ring Above
322 > U_Combining_Dot_Above_Right = 0x0358, // U+0358 Combining Dot Above Right
323 > U_Combining_Asterisk_Below = 0x0359, // U+0359 Combining Asterisk Below
324 > U_Combining_Double_Ring_Below = 0x035A, // U+035A Combining Double Ring Below
325 > U_Combining_Zigzag_Above = 0x035B, // U+035B Combining Zigzag Above
326 > U_Combining_Double_Breve_Below = 0x035C, // U+035C Combining Double Breve Below
327 > U_Combining_Double_Breve = 0x035D, // U+035D Combining Double Breve
328 > U_Combining_Double_Macron = 0x035E, // U+035E Combining Double Macron
329 > U_Combining_Double_Macron_Below = 0x035F, // U+035F Combining Double Macron Below
330 > U_Combining_Double_Tilde = 0x0360, // U+0360 Combining Double Tilde
331 > U_Combining_Double_Inverted_Breve = 0x0361, // U+0361 Combining Double Inverted Breve
332 > U_Combining_Double_Rightwards_Arrow_Below = 0x0362, // U+0362 Combining Double Rightwards Arrow Below
333 > U_Combining_Latin_Small_Letter_A = 0x0363, // U+0363 Combining Latin Small Letter A
334 > U_Combining_Latin_Small_Letter_E = 0x0364, // U+0364 Combining Latin Small Letter E
335 > U_Combining_Latin_Small_Letter_I = 0x0365, // U+0365 Combining Latin Small Letter I
336 > U_Combining_Latin_Small_Letter_O = 0x0366, // U+0366 Combining Latin Small Letter O
337 > U_Combining_Latin_Small_Letter_U = 0x0367, // U+0367 Combining Latin Small Letter U
338 > U_Combining_Latin_Small_Letter_C = 0x0368, // U+0368 Combining Latin Small Letter C
339 > U_Combining_Latin_Small_Letter_D = 0x0369, // U+0369 Combining Latin Small Letter D
340 > U_Combining_Latin_Small_Letter_H = 0x036A, // U+036A Combining Latin Small Letter H
341 > U_Combining_Latin_Small_Letter_M = 0x036B, // U+036B Combining Latin Small Letter M
342 > U_Combining_Latin_Small_Letter_R = 0x036C, // U+036C Combining Latin Small Letter R
343 > U_Combining_Latin_Small_Letter_T = 0x036D, // U+036D Combining Latin Small Letter T
344 > U_Combining_Latin_Small_Letter_V = 0x036E, // U+036E Combining Latin Small Letter V
345 > U_Combining_Latin_Small_Letter_X = 0x036F, // U+036F Combining Latin Small Letter X
346 >
347 > /**
348 > * Unicode Character 'LINE SEPARATOR' (U+2028)
349 > * http://www.fileformat.info/info/unicode/char/2028/index.htm
350 > */
351 > LINE_SEPARATOR = 0x2028,
352 > /**
353 > * Unicode Character 'PARAGRAPH SEPARATOR' (U+2029)
354 > * http://www.fileformat.info/info/unicode/char/2029/index.htm
355 > */
356 > PARAGRAPH_SEPARATOR = 0x2029,
357 > /**
358 > * Unicode Character 'NEXT LINE' (U+0085)
359 > * http://www.fileformat.info/info/unicode/char/0085/index.htm
360 > */
361 > NEXT_LINE = 0x0085,
362 >
363 > // http://www.fileformat.info/info/unicode/category/Sk/list.htm
364 > U_CIRCUMFLEX = 0x005E, // U+005E CIRCUMFLEX
365 > U_GRAVE_ACCENT = 0x0060, // U+0060 GRAVE ACCENT
366 > U_DIAERESIS = 0x00A8, // U+00A8 DIAERESIS
367 > U_MACRON = 0x00AF, // U+00AF MACRON
368 > U_ACUTE_ACCENT = 0x00B4, // U+00B4 ACUTE ACCENT
369 > U_CEDILLA = 0x00B8, // U+00B8 CEDILLA
370 > U_MODIFIER_LETTER_LEFT_ARROWHEAD = 0x02C2, // U+02C2 MODIFIER LETTER LEFT ARROWHEAD
371 > U_MODIFIER_LETTER_RIGHT_ARROWHEAD = 0x02C3, // U+02C3 MODIFIER LETTER RIGHT ARROWHEAD
372 > U_MODIFIER_LETTER_UP_ARROWHEAD = 0x02C4, // U+02C4 MODIFIER LETTER UP ARROWHEAD
373 > U_MODIFIER_LETTER_DOWN_ARROWHEAD = 0x02C5, // U+02C5 MODIFIER LETTER DOWN ARROWHEAD
374 > U_MODIFIER_LETTER_CENTRED_RIGHT_HALF_RING = 0x02D2, // U+02D2 MODIFIER LETTER CENTRED RIGHT HALF RING
375 > U_MODIFIER_LETTER_CENTRED_LEFT_HALF_RING = 0x02D3, // U+02D3 MODIFIER LETTER CENTRED LEFT HALF RING
376 > U_MODIFIER_LETTER_UP_TACK = 0x02D4, // U+02D4 MODIFIER LETTER UP TACK
377 > U_MODIFIER_LETTER_DOWN_TACK = 0x02D5, // U+02D5 MODIFIER LETTER DOWN TACK
378 > U_MODIFIER_LETTER_PLUS_SIGN = 0x02D6, // U+02D6 MODIFIER LETTER PLUS SIGN
379 > U_MODIFIER_LETTER_MINUS_SIGN = 0x02D7, // U+02D7 MODIFIER LETTER MINUS SIGN
380 > U_BREVE = 0x02D8, // U+02D8 BREVE
381 > U_DOT_ABOVE = 0x02D9, // U+02D9 DOT ABOVE
382 > U_RING_ABOVE = 0x02DA, // U+02DA RING ABOVE
383 > U_OGONEK = 0x02DB, // U+02DB OGONEK
384 > U_SMALL_TILDE = 0x02DC, // U+02DC SMALL TILDE
385 > U_DOUBLE_ACUTE_ACCENT = 0x02DD, // U+02DD DOUBLE ACUTE ACCENT
386 > U_MODIFIER_LETTER_RHOTIC_HOOK = 0x02DE, // U+02DE MODIFIER LETTER RHOTIC HOOK
387 > U_MODIFIER_LETTER_CROSS_ACCENT = 0x02DF, // U+02DF MODIFIER LETTER CROSS ACCENT
388 > U_MODIFIER_LETTER_EXTRA_HIGH_TONE_BAR = 0x02E5, // U+02E5 MODIFIER LETTER EXTRA-HIGH TONE BAR
389 > U_MODIFIER_LETTER_HIGH_TONE_BAR = 0x02E6, // U+02E6 MODIFIER LETTER HIGH TONE BAR
390 > U_MODIFIER_LETTER_MID_TONE_BAR = 0x02E7, // U+02E7 MODIFIER LETTER MID TONE BAR
391 > U_MODIFIER_LETTER_LOW_TONE_BAR = 0x02E8, // U+02E8 MODIFIER LETTER LOW TONE BAR
392 > U_MODIFIER_LETTER_EXTRA_LOW_TONE_BAR = 0x02E9, // U+02E9 MODIFIER LETTER EXTRA-LOW TONE BAR
393 > U_MODIFIER_LETTER_YIN_DEPARTING_TONE_MARK = 0x02EA, // U+02EA MODIFIER LETTER YIN DEPARTING TONE MARK
394 > U_MODIFIER_LETTER_YANG_DEPARTING_TONE_MARK = 0x02EB, // U+02EB MODIFIER LETTER YANG DEPARTING TONE MARK
395 > U_MODIFIER_LETTER_UNASPIRATED = 0x02ED, // U+02ED MODIFIER LETTER UNASPIRATED
396 > U_MODIFIER_LETTER_LOW_DOWN_ARROWHEAD = 0x02EF, // U+02EF MODIFIER LETTER LOW DOWN ARROWHEAD
397 > U_MODIFIER_LETTER_LOW_UP_ARROWHEAD = 0x02F0, // U+02F0 MODIFIER LETTER LOW UP ARROWHEAD
398 > U_MODIFIER_LETTER_LOW_LEFT_ARROWHEAD = 0x02F1, // U+02F1 MODIFIER LETTER LOW LEFT ARROWHEAD
399 > U_MODIFIER_LETTER_LOW_RIGHT_ARROWHEAD = 0x02F2, // U+02F2 MODIFIER LETTER LOW RIGHT ARROWHEAD
400 > U_MODIFIER_LETTER_LOW_RING = 0x02F3, // U+02F3 MODIFIER LETTER LOW RING
401 > U_MODIFIER_LETTER_MIDDLE_GRAVE_ACCENT = 0x02F4, // U+02F4 MODIFIER LETTER MIDDLE GRAVE ACCENT
402 > U_MODIFIER_LETTER_MIDDLE_DOUBLE_GRAVE_ACCENT = 0x02F5, // U+02F5 MODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT
403 > U_MODIFIER_LETTER_MIDDLE_DOUBLE_ACUTE_ACCENT = 0x02F6, // U+02F6 MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT
404 > U_MODIFIER_LETTER_LOW_TILDE = 0x02F7, // U+02F7 MODIFIER LETTER LOW TILDE
405 > U_MODIFIER_LETTER_RAISED_COLON = 0x02F8, // U+02F8 MODIFIER LETTER RAISED COLON
406 > U_MODIFIER_LETTER_BEGIN_HIGH_TONE = 0x02F9, // U+02F9 MODIFIER LETTER BEGIN HIGH TONE
407 > U_MODIFIER_LETTER_END_HIGH_TONE = 0x02FA, // U+02FA MODIFIER LETTER END HIGH TONE
408 > U_MODIFIER_LETTER_BEGIN_LOW_TONE = 0x02FB, // U+02FB MODIFIER LETTER BEGIN LOW TONE
409 > U_MODIFIER_LETTER_END_LOW_TONE = 0x02FC, // U+02FC MODIFIER LETTER END LOW TONE
410 > U_MODIFIER_LETTER_SHELF = 0x02FD, // U+02FD MODIFIER LETTER SHELF
411 > U_MODIFIER_LETTER_OPEN_SHELF = 0x02FE, // U+02FE MODIFIER LETTER OPEN SHELF
412 > U_MODIFIER_LETTER_LOW_LEFT_ARROW = 0x02FF, // U+02FF MODIFIER LETTER LOW LEFT ARROW
413 > U_GREEK_LOWER_NUMERAL_SIGN = 0x0375, // U+0375 GREEK LOWER NUMERAL SIGN
414 > U_GREEK_TONOS = 0x0384, // U+0384 GREEK TONOS
415 > U_GREEK_DIALYTIKA_TONOS = 0x0385, // U+0385 GREEK DIALYTIKA TONOS
416 > U_GREEK_KORONIS = 0x1FBD, // U+1FBD GREEK KORONIS
417 > U_GREEK_PSILI = 0x1FBF, // U+1FBF GREEK PSILI
418 > U_GREEK_PERISPOMENI = 0x1FC0, // U+1FC0 GREEK PERISPOMENI
419 > U_GREEK_DIALYTIKA_AND_PERISPOMENI = 0x1FC1, // U+1FC1 GREEK DIALYTIKA AND PERISPOMENI
420 > U_GREEK_PSILI_AND_VARIA = 0x1FCD, // U+1FCD GREEK PSILI AND VARIA
421 > U_GREEK_PSILI_AND_OXIA = 0x1FCE, // U+1FCE GREEK PSILI AND OXIA
422 > U_GREEK_PSILI_AND_PERISPOMENI = 0x1FCF, // U+1FCF GREEK PSILI AND PERISPOMENI
423 > U_GREEK_DASIA_AND_VARIA = 0x1FDD, // U+1FDD GREEK DASIA AND VARIA
424 > U_GREEK_DASIA_AND_OXIA = 0x1FDE, // U+1FDE GREEK DASIA AND OXIA
425 > U_GREEK_DASIA_AND_PERISPOMENI = 0x1FDF, // U+1FDF GREEK DASIA AND PERISPOMENI
426 > U_GREEK_DIALYTIKA_AND_VARIA = 0x1FED, // U+1FED GREEK DIALYTIKA AND VARIA
427 > U_GREEK_DIALYTIKA_AND_OXIA = 0x1FEE, // U+1FEE GREEK DIALYTIKA AND OXIA
428 > U_GREEK_VARIA = 0x1FEF, // U+1FEF GREEK VARIA
429 > U_GREEK_OXIA = 0x1FFD, // U+1FFD GREEK OXIA
430 > U_GREEK_DASIA = 0x1FFE, // U+1FFE GREEK DASIA
431 >
432 > U_IDEOGRAPHIC_FULL_STOP = 0x3002, // U+3002 IDEOGRAPHIC FULL STOP
433 > U_LEFT_CORNER_BRACKET = 0x300C, // U+300C LEFT CORNER BRACKET
434 > U_RIGHT_CORNER_BRACKET = 0x300D, // U+300D RIGHT CORNER BRACKET
435 > U_LEFT_BLACK_LENTICULAR_BRACKET = 0x3010, // U+3010 LEFT BLACK LENTICULAR BRACKET
436 > U_RIGHT_BLACK_LENTICULAR_BRACKET = 0x3011, // U+3011 RIGHT BLACK LENTICULAR BRACKET
437 >
438 >
439 > U_OVERLINE = 0x203E, // Unicode Character 'OVERLINE'
440 >
441 > /**
442 > * UTF-8 BOM
443 > * Unicode Character 'ZERO WIDTH NO-BREAK SPACE' (U+FEFF)
444 > * http://www.fileformat.info/info/unicode/char/feff/index.htm
445 > */
446 > UTF8_BOM = 65279,
447 >
448 > U_FULLWIDTH_SEMICOLON = 0xFF1B, // U+FF1B FULLWIDTH SEMICOLON
449 > U_FULLWIDTH_COMMA = 0xFF0C, // U+FF0C FULLWIDTH COMMA
450 > }
src/vs/editor/common/textModelEvents.ts 438 covered LOC · 25 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- textModelEvents.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 { IPosition } from './core/position.js';
7 > import { IRange, Range } from './core/range.js';
8 > import { Selection } from './core/selection.js';
9 > import { IModelDecoration, InjectedTextOptions } from './model.js';
10 > import { IModelContentChange } from './model/mirrorTextModel.js';
11 > import { AnnotationsUpdate } from './model/tokens/annotations.js';
12 > import { TextModelEditSource } from './textModelEditSource.js';
13 >
14 > /**
15 > * An event describing that the current language associated with a model has changed.
16 > */
17 > export interface IModelLanguageChangedEvent {
18 > /**
19 > * Previous language
20 > */
21 > readonly oldLanguage: string;
22 > /**
23 > * New language
24 > */
25 > readonly newLanguage: string;
26 >
27 > /**
28 > * Source of the call that caused the event.
29 > */
30 > readonly source: string;
31 > }
32 >
33 > /**
34 > * An event describing that the language configuration associated with a model has changed.
35 > */
36 > export interface IModelLanguageConfigurationChangedEvent {
37 > }
38 >
39 > /**
40 > * An event describing a change in the text of a model.
41 > */
42 > export interface IModelContentChangedEvent {
43 > /**
44 > * The changes are ordered from the end of the document to the beginning, so they should be safe to apply in sequence.
45 > */
46 > readonly changes: IModelContentChange[];
47 > /**
48 > * The (new) end-of-line character.
49 > */
50 > readonly eol: string;
51 > /**
52 > * The new version id the model has transitioned to.
53 > */
54 > readonly versionId: number;
55 > /**
56 > * Flag that indicates that this event was generated while undoing.
57 > */
58 > readonly isUndoing: boolean;
59 > /**
60 > * Flag that indicates that this event was generated while redoing.
61 > */
62 > readonly isRedoing: boolean;
63 > /**
64 > * Flag that indicates that all decorations were lost with this edit.
65 > * The model has been reset to a new value.
66 > */
67 > readonly isFlush: boolean;
68 >
69 > /**
70 > * Flag that indicates that this event describes an eol change.
71 > */
72 > readonly isEolChange: boolean;
73 >
74 > /**
75 > * Detailed reason information for the change
76 > * @internal
77 > */
78 > readonly detailedReasons: TextModelEditSource[];
79 >
80 > /**
81 > * The sum of these lengths equals changes.length.
82 > * The length of this array must equal the length of detailedReasons.
83 > */
84 > readonly detailedReasonsChangeLengths: number[];
85 > }
86 >
87 > export interface ISerializedModelContentChangedEvent {
88 > /**
89 > * The changes are ordered from the end of the document to the beginning, so they should be safe to apply in sequence.
90 > */
91 > readonly changes: IModelContentChange[];
92 > /**
93 > * The (new) end-of-line character.
94 > */
95 > readonly eol: string;
96 > /**
97 > * The new version id the model has transitioned to.
98 > */
99 > readonly versionId: number;
100 > /**
101 > * Flag that indicates that this event was generated while undoing.
102 > */
103 > readonly isUndoing: boolean;
104 > /**
105 > * Flag that indicates that this event was generated while redoing.
106 > */
107 > readonly isRedoing: boolean;
108 > /**
109 > * Flag that indicates that all decorations were lost with this edit.
110 > * The model has been reset to a new value.
111 > */
112 > readonly isFlush: boolean;
113 >
114 > /**
115 > * Flag that indicates that this event describes an eol change.
116 > */
117 > readonly isEolChange: boolean;
118 >
119 > /**
120 > * Detailed reason information for the change
121 > * @internal
122 > */
123 > readonly detailedReason: Record<string, unknown> | undefined;
124 > }
125 >
126 > /**
127 > * An event describing that model decorations have changed.
128 > */
129 > export interface IModelDecorationsChangedEvent {
130 > readonly affectsMinimap: boolean;
131 > readonly affectsOverviewRuler: boolean;
132 > readonly affectsGlyphMargin: boolean;
133 > readonly affectsLineNumber: boolean;
134 > }
135 >
136 > /**
137 > * An event describing that some ranges of lines have been tokenized (their tokens have changed).
138 > * @internal
139 > */
140 > export interface IModelTokensChangedEvent {
141 > readonly semanticTokensApplied: boolean;
142 > readonly ranges: {
143 > /**
144 > * The start of the range (inclusive)
145 > */
146 > readonly fromLineNumber: number;
147 > /**
148 > * The end of the range (inclusive)
149 > */
150 > readonly toLineNumber: number;
151 > }[];
152 > }
153 >
154 > /**
155 > * @internal
156 > */
157 > export interface IFontTokenOption {
158 > /**
159 > * Font family of the token.
160 > */
161 > readonly fontFamily?: string;
162 > /**
163 > * Font size of the token.
164 > */
165 > readonly fontSizeMultiplier?: number;
166 > /**
167 > * Line height of the token.
168 > */
169 > readonly lineHeightMultiplier?: number;
170 > }
171 >
172 > /**
173 > * An event describing a token font change event
174 > * @internal
175 > */
176 > export interface IModelFontTokensChangedEvent {
177 > changes: FontTokensUpdate;
178 > }
179 >
180 > /**
181 > * @internal
182 > */
183 > export type FontTokensUpdate = AnnotationsUpdate<IFontTokenOption | undefined>;
184 >
185 > /**
186 > * @internal
187 > */
188 > export function serializeFontTokenOptions(): (options: IFontTokenOption) => IFontTokenOption {
189 return (annotation: IFontTokenOption) => {
190 return {
195 };
196 }
198 > /**
199 > * @internal
200 > */
201 > export function deserializeFontTokenOptions(): (options: IFontTokenOption) => IFontTokenOption {
202 return (annotation: IFontTokenOption) => {
203 return {
208 };
209 }
211 > export interface IModelOptionsChangedEvent {
212 > readonly tabSize: boolean;
213 > readonly indentSize: boolean;
214 > readonly insertSpaces: boolean;
215 > readonly trimAutoWhitespace: boolean;
216 > }
217 >
218 > /**
219 > * @internal
220 > */
221 > export const enum RawContentChangedType {
222 > Flush = 1,
223 > LineChanged = 2,
224 > LinesDeleted = 3,
225 > LinesInserted = 4,
226 > EOLChanged = 5
227 > }
228 >
229 > /**
230 > * An event describing that a model has been reset to a new value.
231 > * @internal
232 > */
233 > export class ModelRawFlush {
234 public readonly changeType = RawContentChangedType.Flush;
236 >
237 > /**
238 > * Represents text injected on a line
239 > * @internal
240 > */
241 > export class LineInjectedText {
242 > public static applyInjectedText(lineText: string, injectedTexts: LineInjectedText[] | null): string {
243 > if (!injectedTexts || injectedTexts.length === 0) {
244 > return lineText;
245 > }
246 let result = '';
247 let lastOriginalOffset = 0;
253 result += lineText.substring(lastOriginalOffset);
254 return result;
256 >
257 > public static fromDecorations(decorations: IModelDecoration[]): LineInjectedText[] {
258 const result: LineInjectedText[] = [];
259 for (const decoration of decorations) {
288 return result;
289 }
291 > constructor(
292 public readonly ownerId: number,
293 public readonly lineNumber: number,
296 public readonly order: number
297 ) { }
299 > public withText(text: string): LineInjectedText {
300 return new LineInjectedText(this.ownerId, this.lineNumber, this.column, { ...this.options, content: text }, this.order);
301 }
303 >
304 > /**
305 > * An event describing that a line has changed in a model.
306 > * @internal
307 > */
308 > export class ModelRawLineChanged {
309 > public readonly changeType = RawContentChangedType.LineChanged;
310 > /**
311 > * The line number that has changed (before the change was applied).
312 > */
313 > public readonly lineNumber: number;
314 > /**
315 > * The new line number the old one is mapped to (after the change was applied).
316 > */
317 > public readonly lineNumberPostEdit: number;
318 >
319 > constructor(lineNumber: number, lineNumberPostEdit: number) {
320 this.lineNumber = lineNumber;
321 this.lineNumberPostEdit = lineNumberPostEdit;
322 }
324 >
325 >
326 > /**
327 > * An event describing that a line height has changed in the model.
328 > * @internal
329 > */
330 > export class ModelLineHeightChanged {
331 > /**
332 > * Editor owner ID
333 > */
334 > public readonly ownerId: number;
335 > /**
336 > * The decoration ID that has changed.
337 > */
338 > public readonly decorationId: string;
339 > /**
340 > * The line that has changed.
341 > */
342 > public readonly lineNumber: number;
343 > /**
344 > * The line height on the line.
345 > */
346 > public readonly lineHeightMultiplier: number | null;
347 >
348 > constructor(ownerId: number, decorationId: string, lineNumber: number, lineHeightMultiplier: number | null) {
349 this.ownerId = ownerId;
350 this.decorationId = decorationId;
352 this.lineHeightMultiplier = lineHeightMultiplier;
353 }
355 >
356 > /**
357 > * An event describing that a line height has changed in the model.
358 > * @internal
359 > */
360 > export class ModelFontChanged {
361 > /**
362 > * Editor owner ID
363 > */
364 > public readonly ownerId: number;
365 > /**
366 > * The line that has changed.
367 > */
368 > public readonly lineNumber: number;
369 >
370 > constructor(ownerId: number, lineNumber: number) {
371 this.ownerId = ownerId;
372 this.lineNumber = lineNumber;
373 }
375 >
376 > /**
377 > * An event describing that line(s) have been deleted in a model.
378 > * @internal
379 > */
380 > export class ModelRawLinesDeleted {
381 > public readonly changeType = RawContentChangedType.LinesDeleted;
382 > /**
383 > * At what line the deletion began (inclusive).
384 > */
385 > public readonly fromLineNumber: number;
386 > /**
387 > * At what line the deletion stopped (inclusive).
388 > */
389 > public readonly toLineNumber: number;
390 > /**
391 > * The last unmodified line in the updated buffer after the deletion is made.
392 > */
393 > public readonly lastUntouchedLinePostEdit: number;
394 >
395 > constructor(fromLineNumber: number, toLineNumber: number, lastUntouchedLinePostEdit: number) {
396 this.fromLineNumber = fromLineNumber;
397 this.toLineNumber = toLineNumber;
398 this.lastUntouchedLinePostEdit = lastUntouchedLinePostEdit;
399 }
401 >
402 > /**
403 > * An event describing that line(s) have been inserted in a model.
404 > * @internal
405 > */
406 > export class ModelRawLinesInserted {
407 > public readonly changeType = RawContentChangedType.LinesInserted;
408 > /**
409 > * Before what line did the insertion begin
410 > */
411 > public readonly fromLineNumber: number;
412 > /**
413 > * The actual start line number in the updated buffer where the newly inserted content can be found.
414 > */
415 > public readonly fromLineNumberPostEdit: number;
416 > /**
417 > * The count of inserted lines.
418 > */
419 > public readonly count: number;
420 > /**
421 > * `toLineNumber` - `fromLineNumber` + 1 denotes the number of lines that were inserted
422 > */
423 > public get toLineNumber(): number {
424 > return this.fromLineNumber + this.count - 1;
425 > }
426 > /**
427 > * The actual end line number of the insertion in the updated buffer.
428 > */
429 > public get toLineNumberPostEdit(): number {
430 return this.fromLineNumberPostEdit + this.count - 1;
431 }
433 > constructor(fromLineNumber: number, fromLineNumberPostEdit: number, count: number) {
434 this.fromLineNumber = fromLineNumber;
435 this.fromLineNumberPostEdit = fromLineNumberPostEdit;
436 this.count = count;
437 }
439 >
440 > /**
441 > * An event describing that a model has had its EOL changed.
442 > * @internal
443 > */
444 > export class ModelRawEOLChanged {
445 public readonly changeType = RawContentChangedType.EOLChanged;
447 >
448 > /**
449 > * @internal
450 > */
451 > export type ModelRawChange = ModelRawFlush | ModelRawLineChanged | ModelRawLinesDeleted | ModelRawLinesInserted | ModelRawEOLChanged;
452 >
453 > /**
454 > * An event describing a change in the text of a model.
455 > * @internal
456 > */
457 > export class ModelRawContentChangedEvent {
458 >
459 > public readonly changes: ModelRawChange[];
460 > /**
461 > * The new version id the model has transitioned to.
462 > */
463 > public readonly versionId: number;
464 > /**
465 > * Flag that indicates that this event was generated while undoing.
466 > */
467 > public readonly isUndoing: boolean;
468 > /**
469 > * Flag that indicates that this event was generated while redoing.
470 > */
471 > public readonly isRedoing: boolean;
472 >
473 > public resultingSelection: Selection[] | null;
474 >
475 > constructor(changes: ModelRawChange[], versionId: number, isUndoing: boolean, isRedoing: boolean) {
476 this.changes = changes;
477 this.versionId = versionId;
480 this.resultingSelection = null;
481 }
483 > public containsEvent(type: RawContentChangedType): boolean {
484 for (let i = 0, len = this.changes.length; i < len; i++) {
485 const change = this.changes[i];
490 return false;
491 }
493 > public static merge(a: ModelRawContentChangedEvent, b: ModelRawContentChangedEvent): ModelRawContentChangedEvent {
494 const changes = ([] as ModelRawChange[]).concat(a.changes).concat(b.changes);
495 const versionId = b.versionId;
498 return new ModelRawContentChangedEvent(changes, versionId, isUndoing, isRedoing);
499 }
501 >
502 > /**
503 > * An event describing a change in injected text.
504 > * @internal
505 > */
506 > export class ModelInjectedTextChangedEvent {
507 >
508 > public readonly changes: ModelRawLineChanged[];
509 >
510 > constructor(changes: ModelRawLineChanged[]) {
511 this.changes = changes;
512 }
514 >
515 > /**
516 > * An event describing a change of a line height.
517 > * @internal
518 > */
519 > export class ModelLineHeightChangedEvent {
520 >
521 > public readonly changes: ModelLineHeightChanged[];
522 >
523 > constructor(changes: ModelLineHeightChanged[]) {
524 this.changes = changes;
525 }
527 > public affects(rangeOrPosition: IRange | IPosition) {
528 if (Range.isIRange(rangeOrPosition)) {
529 for (const change of this.changes) {
542 }
543 }
545 >
546 > /**
547 > * An event describing a change in fonts.
548 > * @internal
549 > */
550 > export class ModelFontChangedEvent {
551 >
552 > public readonly changes: ModelFontChanged[];
553 >
554 > constructor(changes: ModelFontChanged[]) {
555 this.changes = changes;
556 }
558 >
559 > /**
560 > * @internal
561 > */
562 > export class InternalModelContentChangeEvent {
563 > constructor(
564 public readonly rawContentChangedEvent: ModelRawContentChangedEvent,
565 public readonly contentChangedEvent: IModelContentChangedEvent,
566 ) { }
568 > public merge(other: InternalModelContentChangeEvent): InternalModelContentChangeEvent {
569 const rawContentChangedEvent = ModelRawContentChangedEvent.merge(this.rawContentChangedEvent, other.rawContentChangedEvent);
570 const contentChangedEvent = InternalModelContentChangeEvent._mergeChangeEvents(this.contentChangedEvent, other.contentChangedEvent);
571 return new InternalModelContentChangeEvent(rawContentChangedEvent, contentChangedEvent);
572 }
574 > private static _mergeChangeEvents(a: IModelContentChangedEvent, b: IModelContentChangedEvent): IModelContentChangedEvent {
575 const changes = ([] as IModelContentChange[]).concat(a.changes).concat(b.changes);
576 const eol = b.eol;
src/vs/base/common/arrays.ts 404 covered LOC · 72 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- arrays.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 { findFirstIdxMonotonousOrArrLen } from './arraysFind.js';
7 > import { CancellationToken } from './cancellation.js';
8 > import { CancellationError } from './errors.js';
9 > import { ISplice } from './sequence.js';
10 >
11 > /**
12 > * Returns the last entry and the initial N-1 entries of the array, as a tuple of [rest, last].
13 > *
14 > * The array must have at least one element.
15 > *
16 > * @param arr The input array
17 > * @returns A tuple of [rest, last] where rest is all but the last element and last is the last element
18 > * @throws Error if the array is empty
19 > */
20 > export function tail<T>(arr: T[]): [T[], T] {
21 if (arr.length === 0) {
22 throw new Error('Invalid tail call');
25 return [arr.slice(0, arr.length - 1), arr[arr.length - 1]];
26 }
27 > arrays.ts
28 > export function equals<T>(one: ReadonlyArray<T> | undefined, other: ReadonlyArray<T> | undefined, itemEquals: (a: T, b: T) => boolean = (a, b) => a === b): boolean {
29 if (one === other) {
30 return true;
47 return true;
48 }
49 > arrays.ts
50 > /**
51 > * Remove the element at `index` by replacing it with the last element. This is faster than `splice`
52 > * but changes the order of the array
53 > */
54 > export function removeFastWithoutKeepingOrder<T>(array: T[], index: number) {
55 const last = array.length - 1;
56 if (index < last) {
59 array.pop();
60 }
61 > arrays.ts
62 > /**
63 > * Performs a binary search algorithm over a sorted array.
64 > *
65 > * @param array The array being searched.
66 > * @param key The value we search for.
67 > * @param comparator A function that takes two array elements and returns zero
68 > * if they are equal, a negative number if the first element precedes the
69 > * second one in the sorting order, or a positive number if the second element
70 > * precedes the first one.
71 > * @return See {@link binarySearch2}
72 > */
73 > export function binarySearch<T>(array: ReadonlyArray<T>, key: T, comparator: (op1: T, op2: T) => number): number {
74 return binarySearch2(array.length, i => comparator(array[i], key));
75 }
76 > arrays.ts
77 > /**
78 > * Performs a binary search algorithm over a sorted collection. Useful for cases
79 > * when we need to perform a binary search over something that isn't actually an
80 > * array, and converting data to an array would defeat the use of binary search
81 > * in the first place.
82 > *
83 > * @param length The collection length.
84 > * @param compareToKey A function that takes an index of an element in the
85 > * collection and returns zero if the value at this index is equal to the
86 > * search key, a negative number if the value precedes the search key in the
87 > * sorting order, or a positive number if the search key precedes the value.
88 > * @return A non-negative index of an element, if found. If not found, the
89 > * result is -(n+1) (or ~n, using bitwise notation), where n is the index
90 > * where the key should be inserted to maintain the sorting order.
91 > */
92 > export function binarySearch2(length: number, compareToKey: (index: number) => number): number {
93 let low = 0,
94 high = length - 1;
107 return -(low + 1);
108 }
109 > arrays.ts
110 > type Compare<T> = (a: T, b: T) => number;
111 >
112 > /**
113 > * Finds the nth smallest element in the array using quickselect algorithm.
114 > * The data does not need to be sorted.
115 > *
116 > * @param nth The zero-based index of the element to find (0 = smallest, 1 = second smallest, etc.)
117 > * @param data The unsorted array
118 > * @param compare A comparator function that defines the sort order
119 > * @returns The nth smallest element
120 > * @throws TypeError if nth is >= data.length
121 > */
122 > export function quickSelect<T>(nth: number, data: T[], compare: Compare<T>): T {
123
124 nth = nth | 0;
152 }
153 }
154 > arrays.ts
155 > export function groupBy<T>(data: ReadonlyArray<T>, compare: (a: T, b: T) => number): T[][] {
156 const result: T[][] = [];
157 let currentGroup: T[] | undefined = undefined;
166 return result;
167 }
168 > arrays.ts
169 > /**
170 > * Splits the given items into a list of (non-empty) groups.
171 > * `shouldBeGrouped` is used to decide if two consecutive items should be in the same group.
172 > * The order of the items is preserved.
173 > */
174 > export function* groupAdjacentBy<T>(items: Iterable<T>, shouldBeGrouped: (item1: T, item2: T) => boolean): Iterable<T[]> {
175 let currentGroup: T[] | undefined;
176 let last: T | undefined;
190 }
191 }
192 > arrays.ts
193 > export function forEachAdjacent<T>(arr: T[], f: (item1: T | undefined, item2: T | undefined) => void): void {
194 for (let i = 0; i <= arr.length; i++) {
195 f(i === 0 ? undefined : arr[i - 1], i === arr.length ? undefined : arr[i]);
196 }
197 }
198 > arrays.ts
199 > export function forEachWithNeighbors<T>(arr: T[], f: (before: T | undefined, element: T, after: T | undefined) => void): void {
200 for (let i = 0; i < arr.length; i++) {
201 f(i === 0 ? undefined : arr[i - 1], arr[i], i + 1 === arr.length ? undefined : arr[i + 1]);
202 }
203 }
204 > arrays.ts
205 > export function concatArrays<T extends any[]>(...arrays: T): T[number][number][] {
206 return [].concat(...arrays);
207 }
208 > arrays.ts
209 > interface IMutableSplice<T> extends ISplice<T> {
210 > readonly toInsert: T[];
211 > deleteCount: number;
212 > }
213 >
214 > /**
215 > * Diffs two *sorted* arrays and computes the splices which apply the diff.
216 > */
217 > export function sortedDiff<T>(before: ReadonlyArray<T>, after: ReadonlyArray<T>, compare: (a: T, b: T) => number): ISplice<T>[] {
218 const result: IMutableSplice<T>[] = [];
219
266 return result;
267 }
268 > arrays.ts
269 > /**
270 > * Takes two *sorted* arrays and computes their delta (removed, added elements).
271 > * Finishes in `Math.min(before.length, after.length)` steps.
272 > */
273 > export function delta<T>(before: ReadonlyArray<T>, after: ReadonlyArray<T>, compare: (a: T, b: T) => number): { removed: T[]; added: T[] } {
274 const splices = sortedDiff(before, after, compare);
275 const removed: T[] = [];
283 return { removed, added };
284 }
285 > arrays.ts
286 > /**
287 > * Returns the top N elements from the array.
288 > *
289 > * Faster than sorting the entire array when the array is a lot larger than N.
290 > *
291 > * @param array The unsorted array.
292 > * @param compare A sort function for the elements.
293 > * @param n The number of elements to return.
294 > * @return The first n elements from array when sorted with compare.
295 > */
296 > export function top<T>(array: ReadonlyArray<T>, compare: (a: T, b: T) => number, n: number): T[] {
297 if (n === 0) {
298 return [];
302 return result;
303 }
304 > arrays.ts
305 > /**
306 > * Asynchronous variant of `top()` allowing for splitting up work in batches between which the event loop can run.
307 > *
308 > * Returns the top N elements from the array.
309 > *
310 > * Faster than sorting the entire array when the array is a lot larger than N.
311 > *
312 > * @param array The unsorted array.
313 > * @param compare A sort function for the elements.
314 > * @param n The number of elements to return.
315 > * @param batch The number of elements to examine before yielding to the event loop.
316 > * @return The first n elements from array when sorted with compare.
317 > */
318 > export function topAsync<T>(array: T[], compare: (a: T, b: T) => number, n: number, batch: number, token?: CancellationToken): Promise<T[]> {
319 if (n === 0) {
320 return Promise.resolve([]);
339 });
340 }
341 > arrays.ts
342 function topStep<T>(array: ReadonlyArray<T>, compare: (a: T, b: T) => number, result: T[], i: number, m: number): void {
343 for (const n = result.length; i < m; i++) {
350 }
351 }
352 > arrays.ts
353 > /**
354 > * @returns New array with all falsy values removed. The original array IS NOT modified.
355 > */
356 > export function coalesce<T>(array: ReadonlyArray<T | undefined | null>): T[] {
357 return array.filter((e): e is T => !!e);
358 }
359 > arrays.ts
360 > /**
361 > * Remove all falsy values from `array`. The original array IS modified.
362 > */
363 > export function coalesceInPlace<T>(array: Array<T | undefined | null>): asserts array is Array<T> {
364 let to = 0;
365 for (let i = 0; i < array.length; i++) {
371 array.length = to;
372 }
373 > arrays.ts
374 > /**
375 > * @deprecated Use `Array.copyWithin` instead
376 > */
377 > export function move(array: unknown[], from: number, to: number): void {
378 array.splice(to, 0, array.splice(from, 1)[0]);
379 }
380 > arrays.ts
381 > /**
382 > * @returns false if the provided object is an array and not empty.
383 > */
384 > export function isFalsyOrEmpty(obj: unknown): boolean {
385 return !Array.isArray(obj) || obj.length === 0;
386 }
387 > arrays.ts
388 > /**
389 > * @returns True if the provided object is an array and has at least one element.
390 > */
391 > export function isNonEmptyArray<T>(obj: T[] | undefined | null): obj is T[];
392 > export function isNonEmptyArray<T>(obj: readonly T[] | undefined | null): obj is readonly T[];
393 > export function isNonEmptyArray<T>(obj: T[] | readonly T[] | undefined | null): obj is T[] | readonly T[] {
394 return Array.isArray(obj) && obj.length > 0;
395 }
396 > arrays.ts
397 > /**
398 > * Removes duplicates from the given array. The optional keyFn allows to specify
399 > * how elements are checked for equality by returning an alternate value for each.
400 > */
401 > export function distinct<T>(array: ReadonlyArray<T>, keyFn: (value: T) => unknown = value => value): T[] {
402 const seen = new Set<any>();
403
411 });
412 }
413 > arrays.ts
414 > export function uniqueFilter<T, R>(keyFn: (t: T) => R): (t: T) => boolean {
415 const seen = new Set<R>();
416
426 };
427 }
428 > arrays.ts
429 > export function commonPrefixLength<T>(one: ReadonlyArray<T>, other: ReadonlyArray<T>, equals: (a: T, b: T) => boolean = (a, b) => a === b): number {
430 let result = 0;
431
436 return result;
437 }
438 > arrays.ts
439 > export function range(to: number): number[];
440 > export function range(from: number, to: number): number[];
441 > export function range(arg: number, to?: number): number[] {
442 let from = typeof to === 'number' ? arg : 0;
443
463 return result;
464 }
465 > arrays.ts
466 > export function index<T>(array: ReadonlyArray<T>, indexer: (t: T) => string): { [key: string]: T };
467 > export function index<T, R>(array: ReadonlyArray<T>, indexer: (t: T) => string, mapper: (t: T) => R): { [key: string]: R };
468 > export function index<T, R>(array: ReadonlyArray<T>, indexer: (t: T) => string, mapper?: (t: T) => R): { [key: string]: R } {
469 return array.reduce((r, t) => {
470 r[indexer(t)] = mapper ? mapper(t) : t;
472 }, Object.create(null));
473 }
474 > arrays.ts
475 > /**
476 > * Inserts an element into an array. Returns a function which, when
477 > * called, will remove that element from the array.
478 > *
479 > * @deprecated In almost all cases, use a `Set<T>` instead.
480 > */
481 > export function insert<T>(array: T[], element: T): () => void {
482 array.push(element);
483
484 return () => remove(array, element);
485 }
486 > arrays.ts
487 > /**
488 > * Removes an element from an array if it can be found.
489 > *
490 > * @deprecated In almost all cases, use a `Set<T>` instead.
491 > */
492 > export function remove<T>(array: T[], element: T): T | undefined {
493 const index = array.indexOf(element);
494 if (index > -1) {
500 return undefined;
501 }
502 > arrays.ts
503 > /**
504 > * Insert `insertArr` inside `target` at `insertIndex`.
505 > * Please don't touch unless you understand https://jsperf.com/inserting-an-array-within-an-array
506 > */
507 > export function arrayInsert<T>(target: T[], insertIndex: number, insertArr: T[]): T[] {
508 const before = target.slice(0, insertIndex);
509 const after = target.slice(insertIndex);
510 return before.concat(insertArr, after);
511 }
512 > arrays.ts
513 > /**
514 > * Uses Fisher-Yates shuffle to shuffle the given array
515 > */
516 > export function shuffle<T>(array: T[], _seed?: number): void {
517 let rand: () => number;
518
536 }
537 }
538 > arrays.ts
539 > /**
540 > * Pushes an element to the start of the array, if found.
541 > */
542 > export function pushToStart<T>(arr: T[], value: T): void {
543 const index = arr.indexOf(value);
544
548 }
549 }
550 > arrays.ts
551 > /**
552 > * Pushes an element to the end of the array, if found.
553 > */
554 > export function pushToEnd<T>(arr: T[], value: T): void {
555 const index = arr.indexOf(value);
556
560 }
561 }
562 > arrays.ts
563 > export function pushMany<T>(arr: T[], items: ReadonlyArray<T>): void {
564 for (const item of items) {
565 arr.push(item);
566 }
567 }
568 > arrays.ts
569 > export function mapArrayOrNot<T, U>(items: T | T[], fn: (_: T) => U): U | U[] {
570 return Array.isArray(items) ?
571 items.map(fn) :
572 fn(items);
573 }
574 > arrays.ts
575 > export function mapFilter<T, U>(array: ReadonlyArray<T>, fn: (t: T) => U | undefined): U[] {
576 const result: U[] = [];
577 for (const item of array) {
583 return result;
584 }
585 > arrays.ts
586 > export function withoutDuplicates<T>(array: ReadonlyArray<T>): T[] {
587 const s = new Set(array);
588 return Array.from(s);
589 }
590 > arrays.ts
591 > export function asArray<T>(x: T | T[]): T[];
592 > export function asArray<T>(x: T | readonly T[]): readonly T[];
593 > export function asArray<T>(x: T | T[]): T[] {
594 return Array.isArray(x) ? x : [x];
595 }
596 > arrays.ts
597 > export function getRandomElement<T>(arr: T[]): T | undefined {
598 return arr[Math.floor(Math.random() * arr.length)];
599 }
600 > arrays.ts
601 > /**
602 > * Insert the new items in the array.
603 > * @param array The original array.
604 > * @param start The zero-based location in the array from which to start inserting elements.
605 > * @param newItems The items to be inserted
606 > */
607 > export function insertInto<T>(array: T[], start: number, newItems: T[]): void {
608 const startIdx = getActualStartIndex(array, start);
609 const originalLength = array.length;
619 }
620 }
621 > arrays.ts
622 > /**
623 > * Removes elements from an array and inserts new elements in their place, returning the deleted elements. Alternative to the native Array.splice method, it
624 > * can only support limited number of items due to the maximum call stack size limit.
625 > * @param array The original array.
626 > * @param start The zero-based location in the array from which to start removing elements.
627 > * @param deleteCount The number of elements to remove.
628 > * @returns An array containing the elements that were deleted.
629 > */
630 > export function splice<T>(array: T[], start: number, deleteCount: number, newItems: T[]): T[] {
631 const index = getActualStartIndex(array, start);
632 let result = array.splice(index, deleteCount);
638 return result;
639 }
640 > arrays.ts
641 > /**
642 > * Determine the actual start index (same logic as the native splice() or slice())
643 > * If greater than the length of the array, start will be set to the length of the array. In this case, no element will be deleted but the method will behave as an adding function, adding as many element as item[n*] provided.
644 > * If negative, it will begin that many elements from the end of the array. (In this case, the origin -1, meaning -n is the index of the nth last element, and is therefore equivalent to the index of array.length - n.) If array.length + start is less than 0, it will begin from index 0.
645 > * @param array The target array.
646 > * @param start The operation index.
647 > */
648 function getActualStartIndex<T>(array: T[], start: number): number {
649 return start < 0 ? Math.max(start + array.length, 0) : Math.min(start, array.length);
650 }
651 > arrays.ts
652 >
653 >
654 > /**
655 > * When comparing two values,
656 > * a negative number indicates that the first value is less than the second,
657 > * a positive number indicates that the first value is greater than the second,
658 > * and zero indicates that neither is the case.
659 > */
660 > export type CompareResult = number;
661 >
662 > export namespace CompareResult {
663 > export function isLessThan(result: CompareResult): boolean {
664 return result < 0;
665 }
666 > arrays.ts
667 > export function isLessThanOrEqual(result: CompareResult): boolean {
668 return result <= 0;
669 }
670 > arrays.ts
671 > export function isGreaterThan(result: CompareResult): boolean {
672 return result > 0;
673 }
674 > arrays.ts
675 > export function isNeitherLessOrGreaterThan(result: CompareResult): boolean {
676 return result === 0;
677 }
678 > arrays.ts
679 > export const greaterThan = 1;
680 > export const lessThan = -1;
681 > export const neitherLessOrGreaterThan = 0;
682 > }
683 >
684 > /**
685 > * A comparator `c` defines a total order `<=` on `T` as following:
686 > * `c(a, b) <= 0` iff `a` <= `b`.
687 > * We also have `c(a, b) == 0` iff `c(b, a) == 0`.
688 > */
689 > export type Comparator<T> = (a: T, b: T) => CompareResult;
690 >
691 > export function compareBy<TItem, TCompareBy>(selector: (item: TItem) => TCompareBy, comparator: Comparator<TCompareBy>): Comparator<TItem> {
692 return (a, b) => comparator(selector(a), selector(b));
693 }
694 > arrays.ts
695 > export function tieBreakComparators<TItem>(...comparators: Comparator<TItem>[]): Comparator<TItem> {
696 return (item1, item2) => {
697 for (const comparator of comparators) {
704 };
705 }
706 > arrays.ts
707 > /**
708 > * The natural order on numbers.
709 > */
710 > export const numberComparator: Comparator<number> = (a, b) => a - b;
711 >
712 > export const booleanComparator: Comparator<boolean> = (a, b) => numberComparator(a ? 1 : 0, b ? 1 : 0);
713 >
714 > export function reverseOrder<TItem>(comparator: Comparator<TItem>): Comparator<TItem> {
715 return (a, b) => -comparator(a, b);
716 }
717 > arrays.ts
718 > /**
719 > * Returns a new comparator that treats `undefined` as the smallest value.
720 > * All other values are compared using the given comparator.
721 > */
722 > export function compareUndefinedSmallest<T>(comparator: Comparator<T>): Comparator<T | undefined> {
723 return (a, b) => {
724 if (a === undefined) {
731 };
732 }
733 > arrays.ts
734 > export class ArrayQueue<T> {
735 > private readonly items: readonly T[];
736 > private firstIdx = 0;
737 > private lastIdx: number;
738 >
739 > /**
740 > * Constructs a queue that is backed by the given array. Runtime is O(1).
741 > */
742 > constructor(items: readonly T[]) {
743 this.items = items;
744 this.lastIdx = this.items.length - 1;
745 }
746 > arrays.ts
747 > get length(): number {
748 return this.lastIdx - this.firstIdx + 1;
749 }
750 > arrays.ts
751 > /**
752 > * Consumes elements from the beginning of the queue as long as the predicate returns true.
753 > * If no elements were consumed, `null` is returned. Has a runtime of O(result.length).
754 > */
755 > takeWhile(predicate: (value: T) => boolean): T[] | null {
756 // P(k) := k <= this.lastIdx && predicate(this.items[k])
757 // Find s := min { k | k >= this.firstIdx && !P(k) } and return this.data[this.firstIdx...s)
765 return result;
766 }
767 > arrays.ts
768 > /**
769 > * Consumes elements from the end of the queue as long as the predicate returns true.
770 > * If no elements were consumed, `null` is returned.
771 > * The result has the same order as the underlying array!
772 > */
773 > takeFromEndWhile(predicate: (value: T) => boolean): T[] | null {
774 // P(k) := this.firstIdx >= k && predicate(this.items[k])
775 // Find s := max { k | k <= this.lastIdx && !P(k) } and return this.data(s...this.lastIdx]
783 return result;
784 }
785 > arrays.ts
786 > peek(): T | undefined {
787 if (this.length === 0) {
788 return undefined;
790 return this.items[this.firstIdx];
791 }
792 > arrays.ts
793 > peekLast(): T | undefined {
794 if (this.length === 0) {
795 return undefined;
797 return this.items[this.lastIdx];
798 }
799 > arrays.ts
800 > dequeue(): T | undefined {
801 const result = this.items[this.firstIdx];
802 this.firstIdx++;
803 return result;
804 }
805 > arrays.ts
806 > removeLast(): T | undefined {
807 const result = this.items[this.lastIdx];
808 this.lastIdx--;
809 return result;
810 }
811 > arrays.ts
812 > takeCount(count: number): T[] {
813 const result = this.items.slice(this.firstIdx, this.firstIdx + count);
814 this.firstIdx += count;
815 return result;
816 }
817 > } arrays.ts
818 >
819 > /**
820 > * This class is faster than an iterator and array for lazy computed data.
821 > */
822 > export class CallbackIterable<T> {
823 > public static readonly empty = new CallbackIterable<never>(_callback => { });
824 >
825 > constructor(
826 > /**
827 > * Calls the callback for every item.
828 > * Stops when the callback returns false.
829 > */
830 > public readonly iterate: (callback: (item: T) => boolean) => void
831 > ) {
832 > }
833 >
834 > forEach(handler: (item: T) => void) {
835 this.iterate(item => { handler(item); return true; });
836 }
837 > arrays.ts
838 > toArray(): T[] {
839 const result: T[] = [];
840 this.iterate(item => { result.push(item); return true; });
841 return result;
842 }
843 > arrays.ts
844 > filter(predicate: (item: T) => boolean): CallbackIterable<T> {
845 return new CallbackIterable(cb => this.iterate(item => predicate(item) ? cb(item) : true));
846 }
847 > arrays.ts
848 > map<TResult>(mapFn: (item: T) => TResult): CallbackIterable<TResult> {
849 return new CallbackIterable<TResult>(cb => this.iterate(item => cb(mapFn(item))));
850 }
851 > arrays.ts
852 > some(predicate: (item: T) => boolean): boolean {
853 let result = false;
854 this.iterate(item => { result = predicate(item); return !result; });
855 return result;
856 }
857 > arrays.ts
858 > findFirst(predicate: (item: T) => boolean): T | undefined {
859 let result: T | undefined;
860 this.iterate(item => {
867 return result;
868 }
869 > arrays.ts
870 > findLast(predicate: (item: T) => boolean): T | undefined {
871 let result: T | undefined;
872 this.iterate(item => {
878 return result;
879 }
880 > arrays.ts
881 > findLastMaxBy(comparator: Comparator<T>): T | undefined {
882 let result: T | undefined;
883 let first = true;
891 return result;
892 }
893 > } arrays.ts
894 >
895 > /**
896 > * Represents a re-arrangement of items in an array.
897 > */
898 > export class Permutation {
899 > constructor(private readonly _indexMap: readonly number[]) { }
900 >
901 > /**
902 > * Returns a permutation that sorts the given array according to the given compare function.
903 > */
904 > public static createSortPermutation<T>(arr: readonly T[], compareFn: (a: T, b: T) => number): Permutation {
905 const sortIndices = Array.from(arr.keys()).sort((index1, index2) => compareFn(arr[index1], arr[index2]));
906 return new Permutation(sortIndices);
907 }
908 > arrays.ts
909 > /**
910 > * Returns a new array with the elements of the given array re-arranged according to this permutation.
911 > */
912 > apply<T>(arr: readonly T[]): T[] {
913 return arr.map((_, index) => arr[this._indexMap[index]]);
914 }
915 > arrays.ts
916 > /**
917 > * Returns a new permutation that undoes the re-arrangement of this permutation.
918 > */
919 > inverse(): Permutation {
920 const inverseIndexMap = this._indexMap.slice();
921 for (let i = 0; i < this._indexMap.length; i++) {
924 return new Permutation(inverseIndexMap);
925 }
926 > } arrays.ts
927 >
928 > /**
929 > * Asynchronous variant of `Array.find()`, returning the first element in
930 > * the array for which the predicate returns true.
931 > *
932 > * This implementation does not bail early and waits for all promises to
933 > * resolve before returning.
934 > */
935 export async function findAsync<T>(array: readonly T[], predicate: (element: T, index: number) => Promise<boolean>): Promise<T | undefined> {
936 const results = await Promise.all(array.map(
940 return results.find(r => r.ok)?.element;
941 }
942 > arrays.ts
943 > export function sum(array: readonly number[]): number {
944 return array.reduce((acc, value) => acc + value, 0);
945 }
946 > arrays.ts
947 > export function sumBy<T>(array: readonly T[], selector: (value: T) => number): number {
948 return array.reduce((acc, value) => acc + selector(value), 0);
949 }
src/vs/base/common/map.ts 313 covered LOC · 97 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- map.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 { URI } from './uri.js';
7 >
8 > export function getOrSet<K, V>(map: Map<K, V>, key: K, value: V): V {
9 let result = map.get(key);
10 if (result === undefined) {
15 return result;
16 }
17 > map.ts
18 > export function mapToString<K, V>(map: Map<K, V>): string {
19 const entries: string[] = [];
20 map.forEach((value, key) => {
24 return `Map(${map.size}) {${entries.join(', ')}}`;
25 }
26 > map.ts
27 > export function setToString<K>(set: Set<K>): string {
28 const entries: K[] = [];
29 set.forEach(value => {
33 return `Set(${set.size}) {${entries.join(', ')}}`;
34 }
35 > map.ts
36 > interface ResourceMapKeyFn {
37 > (resource: URI): string;
38 > }
39 >
40 > class ResourceMapEntry<T> {
41 > constructor(readonly uri: URI, readonly value: T) { }
42 > }
43 >
44 function isEntries<T>(arg: ResourceMap<T> | ResourceMapKeyFn | readonly (readonly [URI, T])[] | undefined): arg is readonly (readonly [URI, T])[] {
45 return Array.isArray(arg);
46 }
47 > map.ts
48 > export class ResourceMap<T> implements Map<URI, T> {
49 >
50 > private static readonly defaultToKey = (resource: URI) => resource.toString();
51 >
52 > readonly [Symbol.toStringTag] = 'ResourceMap';
53 >
54 > private readonly map: Map<string, ResourceMapEntry<T>>;
55 > private readonly toKey: ResourceMapKeyFn;
56 >
57 > /**
58 > *
59 > * @param toKey Custom uri identity function, e.g use an existing `IExtUri#getComparison`-util
60 > */
61 > constructor(toKey?: ResourceMapKeyFn);
62 >
63 > /**
64 > *
65 > * @param other Another resource which this maps is created from
66 > * @param toKey Custom uri identity function, e.g use an existing `IExtUri#getComparison`-util
67 > */
68 > constructor(other?: ResourceMap<T>, toKey?: ResourceMapKeyFn);
69 >
70 > /**
71 > *
72 > * @param other Another resource which this maps is created from
73 > * @param toKey Custom uri identity function, e.g use an existing `IExtUri#getComparison`-util
74 > */
75 > constructor(entries?: readonly (readonly [URI, T])[], toKey?: ResourceMapKeyFn);
76 >
77 > constructor(arg?: ResourceMap<T> | ResourceMapKeyFn | readonly (readonly [URI, T])[], toKey?: ResourceMapKeyFn) {
78 if (arg instanceof ResourceMap) {
79 this.map = new Map(arg.map);
91 }
92 }
93 > map.ts
94 > set(resource: URI, value: T): this {
95 this.map.set(this.toKey(resource), new ResourceMapEntry(resource, value));
96 return this;
97 }
98 > map.ts
99 > get(resource: URI): T | undefined {
100 return this.map.get(this.toKey(resource))?.value;
101 }
102 > map.ts
103 > has(resource: URI): boolean {
104 return this.map.has(this.toKey(resource));
105 }
106 > map.ts
107 > get size(): number {
108 return this.map.size;
109 }
110 > map.ts
111 > clear(): void {
112 this.map.clear();
113 }
114 > map.ts
115 > delete(resource: URI): boolean {
116 return this.map.delete(this.toKey(resource));
117 }
118 > map.ts
119 > forEach(clb: (value: T, key: URI, map: Map<URI, T>) => void, thisArg?: object): void {
120 if (typeof thisArg !== 'undefined') {
121 clb = clb.bind(thisArg);
125 }
126 }
127 > map.ts
128 > *values(): MapIterator<T> {
129 for (const entry of this.map.values()) {
130 yield entry.value;
131 }
132 }
133 > map.ts
134 > *keys(): MapIterator<URI> {
135 for (const entry of this.map.values()) {
136 yield entry.uri;
137 }
138 }
139 > map.ts
140 > *entries(): MapIterator<[URI, T]> {
141 for (const entry of this.map.values()) {
142 yield [entry.uri, entry.value];
143 }
144 }
145 > map.ts
146 > *[Symbol.iterator](): MapIterator<[URI, T]> {
147 for (const [, entry] of this.map) {
148 yield [entry.uri, entry.value];
149 }
150 }
151 > } map.ts
152 >
153 > export class ResourceSet implements Set<URI> {
154 >
155 > readonly [Symbol.toStringTag]: string = 'ResourceSet';
156 >
157 > private readonly _map: ResourceMap<URI>;
158 >
159 > constructor(toKey?: ResourceMapKeyFn);
160 > constructor(entries: readonly URI[], toKey?: ResourceMapKeyFn);
161 > constructor(entriesOrKey?: readonly URI[] | ResourceMapKeyFn, toKey?: ResourceMapKeyFn) {
162 if (!entriesOrKey || typeof entriesOrKey === 'function') {
163 this._map = new ResourceMap(entriesOrKey);
167 }
168 }
169 > map.ts
170 >
171 > get size(): number {
172 return this._map.size;
173 }
174 > map.ts
175 > add(value: URI): this {
176 this._map.set(value, value);
177 return this;
178 }
179 > map.ts
180 > clear(): void {
181 this._map.clear();
182 }
183 > map.ts
184 > delete(value: URI): boolean {
185 return this._map.delete(value);
186 }
187 > map.ts
188 > forEach(callbackfn: (value: URI, value2: URI, set: Set<URI>) => void, thisArg?: unknown): void {
189 this._map.forEach((_value, key) => callbackfn.call(thisArg, key, key, this));
190 }
191 > map.ts
192 > has(value: URI): boolean {
193 return this._map.has(value);
194 }
195 > map.ts
196 > entries(): SetIterator<[URI, URI]> {
197 return this._map.entries() as unknown as SetIterator<[URI, URI]>;
198 }
199 > map.ts
200 > keys(): SetIterator<URI> {
201 return this._map.keys() as unknown as SetIterator<URI>;
202 }
203 > map.ts
204 > values(): SetIterator<URI> {
205 return this._map.keys() as unknown as SetIterator<URI>;
206 }
207 > map.ts
208 > [Symbol.iterator](): SetIterator<URI> {
209 return this.keys();
210 }
211 > } map.ts
212 >
213 >
214 > interface Item<K, V> {
215 > previous: Item<K, V> | undefined;
216 > next: Item<K, V> | undefined;
217 > key: K;
218 > value: V;
219 > }
220 >
221 > export const enum Touch {
222 > None = 0,
223 > AsOld = 1,
224 > AsNew = 2
225 > }
226 >
227 > export class LinkedMap<K, V> implements Map<K, V> {
228 >
229 > readonly [Symbol.toStringTag] = 'LinkedMap';
230 >
231 > private _map: Map<K, Item<K, V>>;
232 > private _head: Item<K, V> | undefined;
233 > private _tail: Item<K, V> | undefined;
234 > private _size: number;
235 >
236 > private _state: number;
237 >
238 > constructor() {
239 this._map = new Map<K, Item<K, V>>();
240 this._head = undefined;
243 this._state = 0;
244 }
245 > map.ts
246 > clear(): void {
247 this._map.clear();
248 this._head = undefined;
251 this._state++;
252 }
253 > map.ts
254 > isEmpty(): boolean {
255 return !this._head && !this._tail;
256 }
257 > map.ts
258 > get size(): number {
259 return this._size;
260 }
261 > map.ts
262 > get first(): V | undefined {
263 return this._head?.value;
264 }
265 > map.ts
266 > get last(): V | undefined {
267 return this._tail?.value;
268 }
269 > map.ts
270 > has(key: K): boolean {
271 return this._map.has(key);
272 }
273 > map.ts
274 > get(key: K, touch: Touch = Touch.None): V | undefined {
275 const item = this._map.get(key);
276 if (!item) {
282 return item.value;
283 }
284 > map.ts
285 > set(key: K, value: V, touch: Touch = Touch.None): this {
286 let item = this._map.get(key);
287 if (item) {
311 return this;
312 }
313 > map.ts
314 > delete(key: K): boolean {
315 return !!this.remove(key);
316 }
317 > map.ts
318 > remove(key: K): V | undefined {
319 const item = this._map.get(key);
320 if (!item) {
326 return item.value;
327 }
328 > map.ts
329 > shift(): V | undefined {
330 if (!this._head && !this._tail) {
331 return undefined;
340 return item.value;
341 }
342 > map.ts
343 > forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: unknown): void {
344 const state = this._state;
345 let current = this._head;
356 }
357 }
358 > map.ts
359 > keys(): MapIterator<K> {
360 const map = this;
361 const state = this._state;
381 return iterator;
382 }
383 > map.ts
384 > values(): MapIterator<V> {
385 const map = this;
386 const state = this._state;
406 return iterator;
407 }
408 > map.ts
409 > entries(): MapIterator<[K, V]> {
410 const map = this;
411 const state = this._state;
431 return iterator;
432 }
433 > map.ts
434 > [Symbol.iterator](): MapIterator<[K, V]> {
435 return this.entries();
436 }
437 > map.ts
438 > protected trimOld(newSize: number) {
439 if (newSize >= this.size) {
440 return;
458 this._state++;
459 }
460 > map.ts
461 > protected trimNew(newSize: number) {
462 if (newSize >= this.size) {
463 return;
481 this._state++;
482 }
483 > map.ts
484 > private addItemFirst(item: Item<K, V>): void {
485 // First time Insert
486 if (!this._head && !this._tail) {
495 this._state++;
496 }
497 > map.ts
498 > private addItemLast(item: Item<K, V>): void {
499 // First time Insert
500 if (!this._head && !this._tail) {
509 this._state++;
510 }
511 > map.ts
512 > private removeItem(item: Item<K, V>): void {
513 if (item === this._head && item === this._tail) {
514 this._head = undefined;
546 this._state++;
547 }
548 > map.ts
549 > private touch(item: Item<K, V>, touch: Touch): void {
550 if (!this._head || !this._tail) {
551 throw new Error('Invalid list');
608 }
609 }
610 > map.ts
611 > toJSON(): [K, V][] {
612 const data: [K, V][] = [];
613
618 return data;
619 }
620 > map.ts
621 > fromJSON(data: [K, V][]): void {
622 this.clear();
623
626 }
627 }
628 > } map.ts
629 >
630 > abstract class Cache<K, V> extends LinkedMap<K, V> {
631 >
632 > protected _limit: number;
633 > protected _ratio: number;
634 >
635 > constructor(limit: number, ratio: number = 1) {
636 super();
637 this._limit = limit;
638 this._ratio = Math.min(Math.max(0, ratio), 1);
639 }
640 > map.ts
641 > get limit(): number {
642 return this._limit;
643 }
644 > map.ts
645 > set limit(limit: number) {
646 this._limit = limit;
647 this.checkTrim();
648 }
649 > map.ts
650 > get ratio(): number {
651 return this._ratio;
652 }
653 > map.ts
654 > set ratio(ratio: number) {
655 this._ratio = Math.min(Math.max(0, ratio), 1);
656 this.checkTrim();
657 }
658 > map.ts
659 > override get(key: K, touch: Touch = Touch.AsNew): V | undefined {
660 return super.get(key, touch);
661 }
662 > map.ts
663 > peek(key: K): V | undefined {
664 return super.get(key, Touch.None);
665 }
666 > map.ts
667 > override set(key: K, value: V): this {
668 super.set(key, value, Touch.AsNew);
669 return this;
670 }
671 > map.ts
672 > protected checkTrim() {
673 if (this.size > this._limit) {
674 this.trim(Math.round(this._limit * this._ratio));
675 }
676 }
677 > map.ts
678 > protected abstract trim(newSize: number): void;
679 > }
680 >
681 > export class LRUCache<K, V> extends Cache<K, V> {
682 >
683 > constructor(limit: number, ratio: number = 1) {
684 super(limit, ratio);
685 }
686 > map.ts
687 > protected override trim(newSize: number) {
688 this.trimOld(newSize);
689 }
690 > map.ts
691 > override set(key: K, value: V): this {
692 super.set(key, value);
693 this.checkTrim();
694 return this;
695 }
696 > } map.ts
697 >
698 > export class MRUCache<K, V> extends Cache<K, V> {
699 >
700 > constructor(limit: number, ratio: number = 1) {
701 super(limit, ratio);
702 }
703 > map.ts
704 > protected override trim(newSize: number) {
705 this.trimNew(newSize);
706 }
707 > map.ts
708 > override set(key: K, value: V): this {
709 if (this._limit <= this.size && !this.has(key)) {
710 this.trim(Math.round(this._limit * this._ratio) - 1);
714 return this;
715 }
716 > } map.ts
717 >
718 > export class CounterSet<T> {
719
720 private map = new Map<T, number>();
721 > map.ts
722 > add(value: T): CounterSet<T> {
723 this.map.set(value, (this.map.get(value) || 0) + 1);
724 return this;
725 }
726 > map.ts
727 > delete(value: T): boolean {
728 let counter = this.map.get(value) || 0;
729
742 return true;
743 }
744 > map.ts
745 > has(value: T): boolean {
746 return this.map.has(value);
747 }
748 > } map.ts
749 >
750 > /**
751 > * A map that allows access both by keys and values.
752 > * **NOTE**: values need to be unique.
753 > */
754 > export class BidirectionalMap<K, V> {
755 >
756 > private readonly _m1 = new Map<K, V>();
757 > private readonly _m2 = new Map<V, K>();
758 >
759 > constructor(entries?: readonly (readonly [K, V])[]) {
760 if (entries) {
761 for (const [key, value] of entries) {
764 }
765 }
766 > map.ts
767 > clear(): void {
768 this._m1.clear();
769 this._m2.clear();
770 }
771 > map.ts
772 > set(key: K, value: V): void {
773 this._m1.set(key, value);
774 this._m2.set(value, key);
775 }
776 > map.ts
777 > get(key: K): V | undefined {
778 return this._m1.get(key);
779 }
780 > map.ts
781 > getKey(value: V): K | undefined {
782 return this._m2.get(value);
783 }
784 > map.ts
785 > delete(key: K): boolean {
786 const value = this._m1.get(key);
787 if (value === undefined) {
792 return true;
793 }
794 > map.ts
795 > forEach(callbackfn: (value: V, key: K, map: BidirectionalMap<K, V>) => void, thisArg?: unknown): void {
796 this._m1.forEach((value, key) => {
797 callbackfn.call(thisArg, value, key, this);
798 });
799 }
800 > map.ts
801 > keys(): IterableIterator<K> {
802 return this._m1.keys();
803 }
804 > map.ts
805 > values(): IterableIterator<V> {
806 return this._m1.values();
807 }
808 > } map.ts
809 >
810 > export class SetMap<K, V> {
811
812 private map = new Map<K, Set<V>>();
813 > map.ts
814 > add(key: K, value: V): void {
815 let values = this.map.get(key);
816
822 values.add(value);
823 }
824 > map.ts
825 > delete(key: K, value: V): void {
826 const values = this.map.get(key);
827
836 }
837 }
838 > map.ts
839 > forEach(key: K, fn: (value: V) => void): void {
840 const values = this.map.get(key);
841
846 values.forEach(fn);
847 }
848 > map.ts
849 > get(key: K): ReadonlySet<V> {
850 const values = this.map.get(key);
851 if (!values) {
854 return values;
855 }
856 > } map.ts
857 >
858 > export function mapsStrictEqualIgnoreOrder(a: Map<unknown, unknown>, b: Map<unknown, unknown>): boolean {
859 if (a === b) {
860 return true;
879 return true;
880 }
881 > map.ts
882 > /**
883 > * A map that is addressable with an arbitrary number of keys. This is useful in high performance
884 > * scenarios where creating a composite key whenever the data is accessed is too expensive. For
885 > * example for a very hot function, constructing a string like `first-second-third` for every call
886 > * will cause a significant hit to performance.
887 > */
888 > export class NKeyMap<TValue, TKeys extends (string | boolean | number)[]> {
889 private _data: Map<any, any> = new Map();
890 > map.ts
891 > /**
892 > * Sets a value on the map. Note that unlike a standard `Map`, the first argument is the value.
893 > * This is because the spread operator is used for the keys and must be last..
894 > * @param value The value to set.
895 > * @param keys The keys for the value.
896 > */
897 > public set(value: TValue, ...keys: [...TKeys]): void {
898 let currentMap = this._data;
899 for (let i = 0; i < keys.length - 1; i++) {
907 currentMap.set(keys[keys.length - 1], value);
908 }
909 > map.ts
910 > public get(...keys: [...TKeys]): TValue | undefined {
911 let currentMap = this._data;
912 for (let i = 0; i < keys.length - 1; i++) {
919 return currentMap.get(keys[keys.length - 1]);
920 }
921 > map.ts
922 > public delete(...keys: [...TKeys]): boolean {
923 const maps: Map<any, any>[] = [this._data];
924 let currentMap = this._data;
939 return deleted;
940 }
941 > map.ts
942 > public deleteAll(...keys: Partial<TKeys>): boolean {
943 if (keys.length === 0) {
944 const hadData = this._data.size > 0;
964 return deleted;
965 }
966 > map.ts
967 > public clear(): void {
968 this._data.clear();
969 }
970 > map.ts
971 > public *getAll(...keys: Partial<TKeys>): IterableIterator<TValue> {
972 let currentMap = this._data;
973 for (const key of keys) {
980 yield* this._values(currentMap);
981 }
982 > map.ts
983 > public *values(): IterableIterator<TValue> {
984 yield* this._values(this._data);
985 }
986 > map.ts
987 > private *_values(map: Map<any, any>): IterableIterator<TValue> {
988 for (const value of map.values()) {
989 if (value instanceof Map) {
994 }
995 }
996 > map.ts
997 > /**
998 > * Get a textual representation of the map for debugging purposes.
999 > */
1000 > public toString(): string {
1001 const printMap = (map: Map<any, any>, depth: number): string => {
1002 let result = '';
1014 return printMap(this._data, 0);
1015 }
1016 > } map.ts
src/vs/base/common/types.ts 284 covered LOC · 24 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- types.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 { assert } from './assert.js';
7 >
8 > /**
9 > * @returns whether the provided parameter is a JavaScript String or not.
10 > */
11 > export function isString(str: unknown): str is string {
12 return (typeof str === 'string');
13 }
14 > types.ts
15 > /**
16 > * @returns whether the provided parameter is a JavaScript Array and each element in the array is a string.
17 > */
18 > export function isStringArray(value: unknown): value is string[] {
19 return isArrayOf(value, isString);
20 }
21 > types.ts
22 > /**
23 > * @returns whether the provided parameter is a JavaScript Array and each element in the array satisfies the provided type guard.
24 > */
25 > export function isArrayOf<T>(value: unknown, check: (item: unknown) => item is T): value is T[] {
26 return Array.isArray(value) && value.every(check);
27 }
28 > types.ts
29 > /**
30 > * @returns whether the provided parameter is of type `object` but **not**
31 > * `null`, an `array`, a `regexp`, nor a `date`.
32 > */
33 > export function isObject(obj: unknown): obj is Object {
34 // The method can't do a type cast since there are type (like strings) which
35 // are subclasses of any put not positvely matched by the function. Hence type
41 && !(obj instanceof Date);
42 }
43 > types.ts
44 > /**
45 > * @returns whether the provided parameter is of type `Buffer` or Uint8Array dervived type
46 > */
47 > export function isTypedArray(obj: unknown): obj is Object {
48 const TypedArray = Object.getPrototypeOf(Uint8Array);
49 return typeof obj === 'object'
50 && obj instanceof TypedArray;
51 }
52 > types.ts
53 > /**
54 > * In **contrast** to just checking `typeof` this will return `false` for `NaN`.
55 > * @returns whether the provided parameter is a JavaScript Number or not.
56 > */
57 > export function isNumber(obj: unknown): obj is number {
58 return (typeof obj === 'number' && !isNaN(obj));
59 }
60 > types.ts
61 > /**
62 > * @returns whether the provided parameter is an Iterable, casting to the given generic
63 > */
64 > export function isIterable<T>(obj: unknown): obj is Iterable<T> {
65 // eslint-disable-next-line local/code-no-any-casts
66 return !!obj && typeof (obj as any)[Symbol.iterator] === 'function';
67 }
68 > types.ts
69 > /**
70 > * @returns whether the provided parameter is an Iterable, casting to the given generic
71 > */
72 > export function isAsyncIterable<T>(obj: unknown): obj is AsyncIterable<T> {
73 // eslint-disable-next-line local/code-no-any-casts
74 return !!obj && typeof (obj as any)[Symbol.asyncIterator] === 'function';
75 }
76 > types.ts
77 > /**
78 > * @returns whether the provided parameter is a JavaScript Boolean or not.
79 > */
80 > export function isBoolean(obj: unknown): obj is boolean {
81 return (obj === true || obj === false);
82 }
83 > types.ts
84 > /**
85 > * @returns whether the provided parameter is undefined.
86 > */
87 > export function isUndefined(obj: unknown): obj is undefined {
88 return (typeof obj === 'undefined');
89 }
90 > types.ts
91 > /**
92 > * @returns whether the provided parameter is defined.
93 > */
94 > export function isDefined<T>(arg: T | null | undefined): arg is T {
95 return !isUndefinedOrNull(arg);
96 }
97 > types.ts
98 > /**
99 > * @returns whether the provided parameter is undefined or null.
100 > */
101 > export function isUndefinedOrNull(obj: unknown): obj is undefined | null {
102 return (isUndefined(obj) || obj === null);
103 }
104 > types.ts
105 >
106 > export function assertType(condition: unknown, type?: string): asserts condition {
107 if (!condition) {
108 throw new Error(type ? `Unexpected type, expected '${type}'` : 'Unexpected type');
109 }
110 }
111 > types.ts
112 > /**
113 > * Asserts that the argument passed in is neither undefined nor null.
114 > *
115 > * @see {@link assertDefined} for a similar utility that leverages TS assertion functions to narrow down the type of `arg` to be non-nullable.
116 > */
117 > export function assertReturnsDefined<T>(arg: T | null | undefined): NonNullable<T> {
118 assert(
119 arg !== null && arg !== undefined,
123 return arg;
124 }
125 > types.ts
126 > /**
127 > * Asserts that a provided `value` is `defined` - not `null` or `undefined`,
128 > * throwing an error with the provided error or error message, while also
129 > * narrowing down the type of the `value` to be `NonNullable` using TS
130 > * assertion functions.
131 > *
132 > * @throws if the provided `value` is `null` or `undefined`.
133 > *
134 > * ## Examples
135 > *
136 > * ```typescript
137 > * // an assert with an error message
138 > * assertDefined('some value', 'String constant is not defined o_O.');
139 > *
140 > * // `throws!` the provided error
141 > * assertDefined(null, new Error('Should throw this error.'));
142 > *
143 > * // narrows down the type of `someValue` to be non-nullable
144 > * const someValue: string | undefined | null = blackbox();
145 > * assertDefined(someValue, 'Some value must be defined.');
146 > * console.log(someValue.length); // now type of `someValue` is `string`
147 > * ```
148 > *
149 > * @see {@link assertReturnsDefined} for a similar utility but without assertion.
150 > * @see {@link https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions typescript-3-7.html#assertion-functions}
151 > */
152 > export function assertDefined<T>(value: T, error: string | NonNullable<Error>): asserts value is NonNullable<T> {
153 if (value === null || value === undefined) {
154 const errorToThrow = typeof error === 'string' ? new Error(error) : error;
157 }
158 }
159 > types.ts
160 > /**
161 > * Asserts that each argument passed in is neither undefined nor null.
162 > */
163 > export function assertReturnsAllDefined<T1, T2>(t1: T1 | null | undefined, t2: T2 | null | undefined): [T1, T2];
164 > export function assertReturnsAllDefined<T1, T2, T3>(t1: T1 | null | undefined, t2: T2 | null | undefined, t3: T3 | null | undefined): [T1, T2, T3];
165 > export function assertReturnsAllDefined<T1, T2, T3, T4>(t1: T1 | null | undefined, t2: T2 | null | undefined, t3: T3 | null | undefined, t4: T4 | null | undefined): [T1, T2, T3, T4];
166 > export function assertReturnsAllDefined(...args: (unknown | null | undefined)[]): unknown[] {
167 const result = [];
168
179 return result;
180 }
181 > types.ts
182 > /**
183 > * Checks if the provided value is one of the vales in the provided list.
184 > *
185 > * ## Examples
186 > *
187 > * ```typescript
188 > * // note! item type is a `subset of string`
189 > * type TItem = ':' | '.' | '/';
190 > *
191 > * // note! item is type of `string` here
192 > * const item: string = ':';
193 > * // list of the items to check against
194 > * const list: TItem[] = [':', '.'];
195 > *
196 > * // ok
197 > * assert(
198 > * isOneOf(item, list),
199 > * 'Must succeed.',
200 > * );
201 > *
202 > * // `item` is of `TItem` type now
203 > * ```
204 > */
205 > export const isOneOf = <TType, TSubtype extends TType>(
206 value: TType,
207 validValues: readonly TSubtype[],
211 return validValues.includes(<TSubtype>value);
212 };
213 > types.ts
214 > /**
215 > * Compile-time type check of a variable.
216 > */
217 > export function typeCheck<T = never>(_thing: NoInfer<T>): void { }
218 >
219 > const hasOwnProperty = Object.prototype.hasOwnProperty;
220 >
221 > /**
222 > * @returns whether the provided parameter is an empty JavaScript Object or not.
223 > */
224 > export function isEmptyObject(obj: unknown): obj is object {
225 if (!isObject(obj)) {
226 return false;
235 return true;
236 }
237 > types.ts
238 > /**
239 > * @returns whether the provided parameter is a JavaScript Function or not.
240 > */
241 > export function isFunction(obj: unknown): obj is Function {
242 return (typeof obj === 'function');
243 }
244 > types.ts
245 > /**
246 > * @returns whether the provided parameters is are JavaScript Function or not.
247 > */
248 > export function areFunctions(...objects: unknown[]): boolean {
249 return objects.length > 0 && objects.every(isFunction);
250 }
251 > types.ts
252 > export type TypeConstraint = string | Function;
253 >
254 > export function validateConstraints(args: unknown[], constraints: Array<TypeConstraint | undefined>): void {
255 const len = Math.min(args.length, constraints.length);
256 for (let i = 0; i < len; i++) {
258 }
259 }
260 > types.ts
261 > export function validateConstraint(arg: unknown, constraint: TypeConstraint | undefined): void {
262
263 if (isString(constraint)) {
283 }
284 }
285 > types.ts
286 > /**
287 > * Helper type assertion that safely upcasts a type to a supertype.
288 > *
289 > * This can be used to make sure the argument correctly conforms to the subtype while still being able to pass it
290 > * to contexts that expects the supertype.
291 > */
292 > export function upcast<Base, Sub extends Base = Base>(x: Sub): Base {
293 return x;
294 }
295 > types.ts
296 > type AddFirstParameterToFunction<T, TargetFunctionsReturnType, FirstParameter> = T extends (...args: any[]) => TargetFunctionsReturnType ?
297 > // Function: add param to function
298 > (firstArg: FirstParameter, ...args: Parameters<T>) => ReturnType<T> :
299 >
300 > // Else: just leave as is
301 > T;
302 >
303 > /**
304 > * Allows to add a first parameter to functions of a type.
305 > */
306 > export type AddFirstParameterToFunctions<Target, TargetFunctionsReturnType, FirstParameter> = {
307 > // For every property
308 > [K in keyof Target]: AddFirstParameterToFunction<Target[K], TargetFunctionsReturnType, FirstParameter>;
309 > };
310 >
311 > /**
312 > * Given an object with all optional properties, requires at least one to be defined.
313 > * i.e. AtLeastOne<MyObject>;
314 > */
315 > export type AtLeastOne<T, U = { [K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U];
316 >
317 > /**
318 > * Only picks the non-optional properties of a type.
319 > */
320 > export type OmitOptional<T> = { [K in keyof T as T[K] extends Required<T>[K] ? K : never]: T[K] };
321 >
322 > /**
323 > * A type that removed readonly-less from all properties of `T`
324 > */
325 > export type Mutable<T> = {
326 > -readonly [P in keyof T]: T[P]
327 > };
328 >
329 > /**
330 > * A type that adds readonly to all properties of T, recursively.
331 > */
332 > export type DeepImmutable<T> = T extends (infer U)[]
333 > ? ReadonlyArray<DeepImmutable<U>>
334 > : T extends ReadonlyArray<infer U>
335 > ? ReadonlyArray<DeepImmutable<U>>
336 > : T extends Map<infer K, infer V>
337 > ? ReadonlyMap<K, DeepImmutable<V>>
338 > : T extends Set<infer U>
339 > ? ReadonlySet<DeepImmutable<U>>
340 > : T extends object
341 > ? {
342 > readonly [K in keyof T]: DeepImmutable<T[K]>;
343 > }
344 > : T;
345 >
346 > /**
347 > * A single object or an array of the objects.
348 > */
349 > export type SingleOrMany<T> = T | T[];
350 >
351 > /**
352 > * Given a `type X = { foo?: string }` checking that an object `satisfies X`
353 > * will ensure each property was explicitly defined, ensuring no properties
354 > * are omitted or forgotten.
355 > */
356 > export type WithDefinedProps<T> = { [K in keyof Required<T>]: T[K] };
357 >
358 >
359 > /**
360 > * A type that recursively makes all properties of `T` required
361 > */
362 > export type DeepRequiredNonNullable<T> = {
363 > [P in keyof T]-?: T[P] extends object ? DeepRequiredNonNullable<T[P]> : Required<NonNullable<T[P]>>;
364 > };
365 >
366 >
367 > /**
368 > * Represents a type that is a partial version of a given type `T`, where all properties are optional and can be deeply nested.
369 > */
370 > export type DeepPartial<T> = {
371 > [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : Partial<T[P]>;
372 > };
373 >
374 > /**
375 > * Represents a type that is a partial version of a given type `T`, except a subset.
376 > */
377 > export type PartialExcept<T, K extends keyof T> = Partial<Omit<T, K>> & Pick<T, K>;
378 >
379 >
380 > type KeysOfUnionType<T> = T extends T ? keyof T : never;
381 > type FilterType<T, TTest> = T extends TTest ? T : never;
382 > type MakeOptionalAndTrue<T extends object> = { [K in keyof T]?: true };
383 >
384 > /**
385 > * Type guard that checks if an object has specific keys and narrows the type accordingly.
386 > *
387 > * @param x - The object to check
388 > * @param key - An object with boolean values indicating which keys to check for
389 > * @returns true if all specified keys exist in the object, false otherwise
390 > *
391 > * @example
392 > * ```typescript
393 > * type A = { a: string };
394 > * type B = { b: number };
395 > * const obj: A | B = getObject();
396 > *
397 > * if (hasKey(obj, { a: true })) {
398 > * // obj is now narrowed to type A
399 > * console.log(obj.a);
400 > * }
401 > * ```
402 > */
403 > export function hasKey<T extends object, TKeys extends MakeOptionalAndTrue<T>>(x: T, key: TKeys): x is FilterType<T, { [K in KeysOfUnionType<T> & keyof TKeys]: unknown }> {
404 for (const k in key) {
405 if (!(k in x)) {
src/vs/base/common/uri.ts 283 covered LOC · 27 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- uri.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 './charCode.js';
7 > import { MarshalledId } from './marshallingIds.js';
8 > import * as paths from './path.js';
9 > import { isWindows } from './platform.js';
10 >
11 > const _schemePattern = /^\w[\w\d+.-]*$/;
12 > const _singleSlashStart = /^\//;
13 > const _doubleSlashStart = /^\/\//;
14 >
15 function _validateUri(ret: URI, _strict?: boolean): void {
16
47 }
48 }
49 > uri.ts
50 > // for a while we allowed uris *without* schemes and this is the migration
51 > // for them, e.g. an uri without scheme and without strict-mode warns and falls
52 > // back to the file-scheme. that should cause the least carnage and still be a
53 > // clear warning
54 function _schemeFix(scheme: string, _strict: boolean): string {
55 if (!scheme && !_strict) {
58 return scheme;
59 }
60 > uri.ts
61 > // implements a bit of https://tools.ietf.org/html/rfc3986#section-5
62 function _referenceResolution(scheme: string, path: string): string {
63
79 return path;
80 }
81 > uri.ts
82 > const _empty = '';
83 > const _slash = '/';
84 > const _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
85 >
86 > /**
87 > * Uniform Resource Identifier (URI) http://tools.ietf.org/html/rfc3986.
88 > * This class is a simple parser which creates the basic component parts
89 > * (http://tools.ietf.org/html/rfc3986#section-3) with minimal validation
90 > * and encoding.
91 > *
92 > * ```txt
93 > * foo://example.com:8042/over/there?name=ferret#nose
94 > * \_/ \______________/\_________/ \_________/ \__/
95 > * | | | | |
96 > * scheme authority path query fragment
97 > * | _____________________|__
98 > * / \ / \
99 > * urn:example:animal:ferret:nose
100 > * ```
101 > */
102 > export class URI implements UriComponents {
103 >
104 > static isUri(thing: unknown): thing is URI {
105 if (thing instanceof URI) {
106 return true;
118 && typeof (<URI>thing).toString === 'function';
119 }
120 > uri.ts
121 > /**
122 > * scheme is the 'http' part of 'http://www.example.com/some/path?query#fragment'.
123 > * The part before the first colon.
124 > */
125 > readonly scheme: string;
126 >
127 > /**
128 > * authority is the 'www.example.com' part of 'http://www.example.com/some/path?query#fragment'.
129 > * The part between the first double slashes and the next slash.
130 > */
131 > readonly authority: string;
132 >
133 > /**
134 > * path is the '/some/path' part of 'http://www.example.com/some/path?query#fragment'.
135 > */
136 > readonly path: string;
137 >
138 > /**
139 > * query is the 'query' part of 'http://www.example.com/some/path?query#fragment'.
140 > */
141 > readonly query: string;
142 >
143 > /**
144 > * fragment is the 'fragment' part of 'http://www.example.com/some/path?query#fragment'.
145 > */
146 > readonly fragment: string;
147 >
148 > /**
149 > * @internal
150 > */
151 > protected constructor(scheme: string, authority?: string, path?: string, query?: string, fragment?: string, _strict?: boolean);
152 >
153 > /**
154 > * @internal
155 > */
156 > protected constructor(components: UriComponents);
157 >
158 > /**
159 > * @internal
160 > */
161 > protected constructor(schemeOrData: string | UriComponents, authority?: string, path?: string, query?: string, fragment?: string, _strict: boolean = false) {
162
163 if (typeof schemeOrData === 'object') {
180 }
181 }
182 > uri.ts
183 > // ---- filesystem path -----------------------
184 >
185 > /**
186 > * Returns a string representing the corresponding file system path of this URI.
187 > * Will handle UNC paths, normalizes windows drive letters to lower-case, and uses the
188 > * platform specific path separator.
189 > *
190 > * * Will *not* validate the path for invalid characters and semantics.
191 > * * Will *not* look at the scheme of this URI.
192 > * * The result shall *not* be used for display purposes but for accessing a file on disk.
193 > *
194 > *
195 > * The *difference* to `URI#path` is the use of the platform specific separator and the handling
196 > * of UNC paths. See the below sample of a file-uri with an authority (UNC path).
197 > *
198 > * ```ts
199 > const u = URI.parse('file://server/c$/folder/file.txt')
200 > u.authority === 'server'
201 > u.path === '/shares/c$/file.txt'
202 > u.fsPath === '\\server\c$\folder\file.txt'
203 > ```
204 > *
205 > * Using `URI#path` to read a file (using fs-apis) would not be enough because parts of the path,
206 > * namely the server name, would be missing. Therefore `URI#fsPath` exists - it's sugar to ease working
207 > * with URIs that represent files on disk (`file` scheme).
208 > */
209 > get fsPath(): string {
210 // if (this.scheme !== 'file') {
211 // console.warn(`[UriError] calling fsPath with scheme ${this.scheme}`);
213 return uriToFsPath(this, false);
214 }
215 > uri.ts
216 > // ---- modify to new -------------------------
217 >
218 > with(change: { scheme?: string; authority?: string | null; path?: string | null; query?: string | null; fragment?: string | null }): URI {
219
220 if (!change) {
260 return new Uri(scheme, authority, path, query, fragment);
261 }
262 > uri.ts
263 > // ---- parse & validate ------------------------
264 >
265 > /**
266 > * Creates a new URI from a string, e.g. `http://www.example.com/some/path`,
267 > * `file:///usr/home`, or `scheme:with/path`.
268 > *
269 > * @param value A string which represents an URI (see `URI#toString`).
270 > */
271 > static parse(value: string, _strict: boolean = false): URI {
272 const match = _regexp.exec(value);
273 if (!match) {
283 );
284 }
285 > uri.ts
286 > /**
287 > * Creates a new URI from a file system path, e.g. `c:\my\files`,
288 > * `/usr/home`, or `\\server\share\some\path`.
289 > *
290 > * The *difference* between `URI#parse` and `URI#file` is that the latter treats the argument
291 > * as path, not as stringified-uri. E.g. `URI.file(path)` is **not the same as**
292 > * `URI.parse('file://' + path)` because the path might contain characters that are
293 > * interpreted (# and ?). See the following sample:
294 > * ```ts
295 > const good = URI.file('/coding/c#/project1');
296 > good.scheme === 'file';
297 > good.path === '/coding/c#/project1';
298 > good.fragment === '';
299 > const bad = URI.parse('file://' + '/coding/c#/project1');
300 > bad.scheme === 'file';
301 > bad.path === '/coding/c'; // path is now broken
302 > bad.fragment === '/project1';
303 > ```
304 > *
305 > * @param path A file system path (see `URI#fsPath`)
306 > */
307 > static file(path: string): URI {
308
309 let authority = _empty;
331 return new Uri('file', authority, path, _empty, _empty);
332 }
333 > uri.ts
334 > /**
335 > * Creates new URI from uri components.
336 > *
337 > * Unless `strict` is `true` the scheme is defaults to be `file`. This function performs
338 > * validation and should be used for untrusted uri components retrieved from storage,
339 > * user input, command arguments etc
340 > */
341 > static from(components: UriComponents, strict?: boolean): URI {
342 const result = new Uri(
343 components.scheme,
350 return result;
351 }
352 > uri.ts
353 > /**
354 > * Join a URI path with path fragments and normalizes the resulting path.
355 > *
356 > * @param uri The input URI.
357 > * @param pathFragment The path fragment to add to the URI path.
358 > * @returns The resulting URI.
359 > */
360 > static joinPath(uri: URI, ...pathFragment: string[]): URI {
361 if (!uri.path) {
362 throw new Error(`[UriError]: cannot call joinPath on URI without path: ${uri.toString()}`);
370 return uri.with({ path: newPath });
371 }
372 > uri.ts
373 > // ---- printing/externalize ---------------------------
374 >
375 > /**
376 > * Creates a string representation for this URI. It's guaranteed that calling
377 > * `URI.parse` with the result of this function creates an URI which is equal
378 > * to this URI.
379 > *
380 > * * The result shall *not* be used for display purposes but for externalization or transport.
381 > * * The result will be encoded using the percentage encoding and encoding happens mostly
382 > * ignore the scheme-specific encoding rules.
383 > *
384 > * @param skipEncoding Do not encode the result, default is `false`
385 > */
386 > toString(skipEncoding: boolean = false): string {
387 return _asFormatted(this, skipEncoding);
388 }
389 > uri.ts
390 > toJSON(): UriComponents {
391 return this;
392 }
393 > uri.ts
394 > /**
395 > * A helper function to revive URIs.
396 > *
397 > * **Note** that this function should only be used when receiving URI#toJSON generated data
398 > * and that it doesn't do any validation. Use {@link URI.from} when received "untrusted"
399 > * uri components such as command arguments or data from storage.
400 > *
401 > * @param data The URI components or URI to revive.
402 > * @returns The revived URI or undefined or null.
403 > */
404 > static revive(data: UriComponents | URI): URI;
405 > static revive(data: UriComponents | URI | undefined): URI | undefined;
406 > static revive(data: UriComponents | URI | null): URI | null;
407 > static revive(data: UriComponents | URI | undefined | null): URI | undefined | null;
408 > static revive(data: UriComponents | URI | undefined | null): URI | undefined | null {
409 if (!data) {
410 return data;
418 }
419 }
420 > uri.ts
421 > [Symbol.for('debug.description')]() {
422 return `URI(${this.toString()})`;
423 }
424 > } uri.ts
425 >
426 > export interface UriComponents {
427 > scheme: string;
428 > authority?: string;
429 > path?: string;
430 > query?: string;
431 > fragment?: string;
432 > }
433 >
434 > export function isUriComponents(thing: unknown): thing is UriComponents {
435 if (!thing || typeof thing !== 'object') {
436 return false;
442 && (typeof (<UriComponents>thing).fragment === 'string' || typeof (<UriComponents>thing).fragment === 'undefined');
443 }
444 > uri.ts
445 > interface UriState extends UriComponents {
446 > $mid: MarshalledId.Uri;
447 > external?: string;
448 > fsPath?: string;
449 > _sep?: 1;
450 > }
451 >
452 > const _pathSepMarker = isWindows ? 1 : undefined;
453 >
454 > // This class exists so that URI is compatible with vscode.Uri (API).
455 class Uri extends URI {
456
457 _formatted: string | null = null;
458 _fsPath: string | null = null;
459 > uri.ts
460 > override get fsPath(): string {
461 if (!this._fsPath) {
462 this._fsPath = uriToFsPath(this, false);
464 return this._fsPath;
465 }
466 > uri.ts
467 > override toString(skipEncoding: boolean = false): string {
468 if (!skipEncoding) {
469 if (!this._formatted) {
476 }
477 }
478 > uri.ts
479 > override toJSON(): UriComponents {
480 // eslint-disable-next-line local/code-no-dangerous-type-assertions
481 const res = <UriState>{
512 return res;
513 }
514 > } uri.ts
515 >
516 > // reserved characters: https://tools.ietf.org/html/rfc3986#section-2.2
517 > const encodeTable: { [ch: number]: string } = {
518 > [CharCode.Colon]: '%3A', // gen-delims
519 > [CharCode.Slash]: '%2F',
520 > [CharCode.QuestionMark]: '%3F',
521 > [CharCode.Hash]: '%23',
522 > [CharCode.OpenSquareBracket]: '%5B',
523 > [CharCode.CloseSquareBracket]: '%5D',
524 > [CharCode.AtSign]: '%40',
525 >
526 > [CharCode.ExclamationMark]: '%21', // sub-delims
527 > [CharCode.DollarSign]: '%24',
528 > [CharCode.Ampersand]: '%26',
529 > [CharCode.SingleQuote]: '%27',
530 > [CharCode.OpenParen]: '%28',
531 > [CharCode.CloseParen]: '%29',
532 > [CharCode.Asterisk]: '%2A',
533 > [CharCode.Plus]: '%2B',
534 > [CharCode.Comma]: '%2C',
535 > [CharCode.Semicolon]: '%3B',
536 > [CharCode.Equals]: '%3D',
537 >
538 > [CharCode.Space]: '%20',
539 > };
540 >
541 function encodeURIComponentFast(uriComponent: string, isPath: boolean, isAuthority: boolean): string {
542 let res: string | undefined = undefined;
602 return res !== undefined ? res : uriComponent;
603 }
604 > uri.ts
605 function encodeURIComponentMinimal(path: string): string {
606 let res: string | undefined = undefined;
620 return res !== undefined ? res : path;
621 }
622 > uri.ts
623 > /**
624 > * Compute `fsPath` for the given uri
625 > */
626 > export function uriToFsPath(uri: URI, keepDriveLetterCasing: boolean): string {
627
628 let value: string;
650 return value;
651 }
652 > uri.ts
653 > /**
654 > * Create the external version of a uri
655 > */
656 function _asFormatted(uri: URI, skipEncoding: boolean): string {
657
723 return res;
724 }
725 > uri.ts
726 > // --- decode
727 >
728 function decodeURIComponentGraceful(str: string): string {
729 try {
737 }
738 }
739 > uri.ts
740 > const _rEncodedAsHex = /(%[0-9A-Za-z][0-9A-Za-z])+/g;
741 >
742 function percentDecode(str: string): string {
743 if (!str.match(_rEncodedAsHex)) {
746 return str.replace(_rEncodedAsHex, (match) => decodeURIComponentGraceful(match));
747 }
748 > uri.ts
749 > /**
750 > * Mapped-type that replaces all occurrences of URI with UriComponents
751 > */
752 > export type UriDto<T> = { [K in keyof T]: T[K] extends URI
753 > ? UriComponents
754 > : UriDto<T[K]> };
src/vs/editor/common/core/range.ts 247 covered LOC · 40 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- range.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 { IPosition, Position } from './position.js';
7 >
8 > /**
9 > * A range in the editor. This interface is suitable for serialization.
10 > */
11 > export interface IRange {
12 > /**
13 > * Line number on which the range starts (starts at 1).
14 > */
15 > readonly startLineNumber: number;
16 > /**
17 > * Column on which the range starts in line `startLineNumber` (starts at 1).
18 > */
19 > readonly startColumn: number;
20 > /**
21 > * Line number on which the range ends.
22 > */
23 > readonly endLineNumber: number;
24 > /**
25 > * Column on which the range ends in line `endLineNumber`.
26 > */
27 > readonly endColumn: number;
28 > }
29 >
30 > /**
31 > * A range in the editor. (startLineNumber,startColumn) is <= (endLineNumber,endColumn)
32 > */
33 > export class Range {
34 >
35 > /**
36 > * Line number on which the range starts (starts at 1).
37 > */
38 > public readonly startLineNumber: number;
39 > /**
40 > * Column on which the range starts in line `startLineNumber` (starts at 1).
41 > */
42 > public readonly startColumn: number;
43 > /**
44 > * Line number on which the range ends.
45 > */
46 > public readonly endLineNumber: number;
47 > /**
48 > * Column on which the range ends in line `endLineNumber`.
49 > */
50 > public readonly endColumn: number;
51 >
52 > constructor(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number) {
53 if ((startLineNumber > endLineNumber) || (startLineNumber === endLineNumber && startColumn > endColumn)) {
54 this.startLineNumber = endLineNumber;
63 }
64 }
65 > range.ts
66 > /**
67 > * Test if this range is empty.
68 > */
69 > public isEmpty(): boolean {
70 return Range.isEmpty(this);
71 }
72 > range.ts
73 > /**
74 > * Test if `range` is empty.
75 > */
76 > public static isEmpty(range: IRange): boolean {
77 return (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn);
78 }
79 > range.ts
80 > /**
81 > * Test if position is in this range. If the position is at the edges, will return true.
82 > */
83 > public containsPosition(position: IPosition): boolean {
84 return Range.containsPosition(this, position);
85 }
86 > range.ts
87 > /**
88 > * Test if `position` is in `range`. If the position is at the edges, will return true.
89 > */
90 > public static containsPosition(range: IRange, position: IPosition): boolean {
91 if (position.lineNumber < range.startLineNumber || position.lineNumber > range.endLineNumber) {
92 return false;
100 return true;
101 }
102 > range.ts
103 > /**
104 > * Test if `position` is in `range`. If the position is at the edges, will return false.
105 > * @internal
106 > */
107 > public static strictContainsPosition(range: IRange, position: IPosition): boolean {
108 if (position.lineNumber < range.startLineNumber || position.lineNumber > range.endLineNumber) {
109 return false;
117 return true;
118 }
119 > range.ts
120 > /**
121 > * Test if range is in this range. If the range is equal to this range, will return true.
122 > */
123 > public containsRange(range: IRange): boolean {
124 return Range.containsRange(this, range);
125 }
126 > range.ts
127 > /**
128 > * Test if `otherRange` is in `range`. If the ranges are equal, will return true.
129 > */
130 > public static containsRange(range: IRange, otherRange: IRange): boolean {
131 if (otherRange.startLineNumber < range.startLineNumber || otherRange.endLineNumber < range.startLineNumber) {
132 return false;
143 return true;
144 }
145 > range.ts
146 > /**
147 > * Test if `range` is strictly in this range. `range` must start after and end before this range for the result to be true.
148 > */
149 > public strictContainsRange(range: IRange): boolean {
150 return Range.strictContainsRange(this, range);
151 }
152 > range.ts
153 > /**
154 > * Test if `otherRange` is strictly in `range` (must start after, and end before). If the ranges are equal, will return false.
155 > */
156 > public static strictContainsRange(range: IRange, otherRange: IRange): boolean {
157 if (otherRange.startLineNumber < range.startLineNumber || otherRange.endLineNumber < range.startLineNumber) {
158 return false;
169 return true;
170 }
171 > range.ts
172 > /**
173 > * A reunion of the two ranges.
174 > * The smallest position will be used as the start point, and the largest one as the end point.
175 > */
176 > public plusRange(range: IRange): Range {
177 return Range.plusRange(this, range);
178 }
179 > range.ts
180 > /**
181 > * A reunion of the two ranges.
182 > * The smallest position will be used as the start point, and the largest one as the end point.
183 > */
184 > public static plusRange(a: IRange, b: IRange): Range {
185 let startLineNumber: number;
186 let startColumn: number;
212 return new Range(startLineNumber, startColumn, endLineNumber, endColumn);
213 }
214 > range.ts
215 > /**
216 > * A intersection of the two ranges.
217 > */
218 > public intersectRanges(range: IRange): Range | null {
219 return Range.intersectRanges(this, range);
220 }
221 > range.ts
222 > /**
223 > * A intersection of the two ranges.
224 > */
225 > public static intersectRanges(a: IRange, b: IRange): Range | null {
226 let resultStartLineNumber = a.startLineNumber;
227 let resultStartColumn = a.startColumn;
256 return new Range(resultStartLineNumber, resultStartColumn, resultEndLineNumber, resultEndColumn);
257 }
258 > range.ts
259 > /**
260 > * Test if this range equals other.
261 > */
262 > public equalsRange(other: IRange | null | undefined): boolean {
263 return Range.equalsRange(this, other);
264 }
265 > range.ts
266 > /**
267 > * Test if range `a` equals `b`.
268 > */
269 > public static equalsRange(a: IRange | null | undefined, b: IRange | null | undefined): boolean {
270 if (!a && !b) {
271 return true;
280 );
281 }
282 > range.ts
283 > /**
284 > * Return the end position (which will be after or equal to the start position)
285 > */
286 > public getEndPosition(): Position {
287 return Range.getEndPosition(this);
288 }
289 > range.ts
290 > /**
291 > * Return the end position (which will be after or equal to the start position)
292 > */
293 > public static getEndPosition(range: IRange): Position {
294 return new Position(range.endLineNumber, range.endColumn);
295 }
296 > range.ts
297 > /**
298 > * Return the start position (which will be before or equal to the end position)
299 > */
300 > public getStartPosition(): Position {
301 return Range.getStartPosition(this);
302 }
303 > range.ts
304 > /**
305 > * Return the start position (which will be before or equal to the end position)
306 > */
307 > public static getStartPosition(range: IRange): Position {
308 return new Position(range.startLineNumber, range.startColumn);
309 }
310 > range.ts
311 > /**
312 > * Transform to a user presentable string representation.
313 > */
314 > public toString(): string {
315 return '[' + this.startLineNumber + ',' + this.startColumn + ' -> ' + this.endLineNumber + ',' + this.endColumn + ']';
316 }
317 > range.ts
318 > /**
319 > * Create a new range using this range's start position, and using endLineNumber and endColumn as the end position.
320 > */
321 > public setEndPosition(endLineNumber: number, endColumn: number): Range {
322 return new Range(this.startLineNumber, this.startColumn, endLineNumber, endColumn);
323 }
324 > range.ts
325 > /**
326 > * Create a new range using this range's end position, and using startLineNumber and startColumn as the start position.
327 > */
328 > public setStartPosition(startLineNumber: number, startColumn: number): Range {
329 return new Range(startLineNumber, startColumn, this.endLineNumber, this.endColumn);
330 }
331 > range.ts
332 > /**
333 > * Create a new empty range using this range's start position.
334 > */
335 > public collapseToStart(): Range {
336 return Range.collapseToStart(this);
337 }
338 > range.ts
339 > /**
340 > * Create a new empty range using this range's start position.
341 > */
342 > public static collapseToStart(range: IRange): Range {
343 return new Range(range.startLineNumber, range.startColumn, range.startLineNumber, range.startColumn);
344 }
345 > range.ts
346 > /**
347 > * Create a new empty range using this range's end position.
348 > */
349 > public collapseToEnd(): Range {
350 return Range.collapseToEnd(this);
351 }
352 > range.ts
353 > /**
354 > * Create a new empty range using this range's end position.
355 > */
356 > public static collapseToEnd(range: IRange): Range {
357 return new Range(range.endLineNumber, range.endColumn, range.endLineNumber, range.endColumn);
358 }
359 > range.ts
360 > /**
361 > * Moves the range by the given amount of lines.
362 > */
363 > public delta(lineCount: number): Range {
364 return new Range(this.startLineNumber + lineCount, this.startColumn, this.endLineNumber + lineCount, this.endColumn);
365 }
366 > range.ts
367 > /**
368 > * Test if this range starts and ends on the same line.
369 > */
370 > public isSingleLine(): boolean {
371 return this.startLineNumber === this.endLineNumber;
372 }
373 > range.ts
374 > // ---
375 >
376 > public static fromPositions(start: IPosition, end: IPosition = start): Range {
377 return new Range(start.lineNumber, start.column, end.lineNumber, end.column);
378 }
379 > range.ts
380 > /**
381 > * Create a `Range` from an `IRange`.
382 > */
383 > public static lift(range: undefined | null): null;
384 > public static lift(range: IRange): Range;
385 > public static lift(range: IRange | undefined | null): Range | null;
386 > public static lift(range: IRange | undefined | null): Range | null {
387 if (!range) {
388 return null;
390 return new Range(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn);
391 }
392 > range.ts
393 > /**
394 > * Test if `obj` is an `IRange`.
395 > */
396 > public static isIRange(obj: unknown): obj is IRange {
397 return (
398 !!obj
403 );
404 }
405 > range.ts
406 > /**
407 > * Test if the two ranges are touching in any way.
408 > */
409 > public static areIntersectingOrTouching(a: IRange, b: IRange): boolean {
410 // Check if `a` is before `b`
411 if (a.endLineNumber < b.startLineNumber || (a.endLineNumber === b.startLineNumber && a.endColumn < b.startColumn)) {
421 return true;
422 }
423 > range.ts
424 > /**
425 > * Test if the two ranges are intersecting. If the ranges are touching it returns true.
426 > */
427 > public static areIntersecting(a: IRange, b: IRange): boolean {
428 // Check if `a` is before `b`
429 if (a.endLineNumber < b.startLineNumber || (a.endLineNumber === b.startLineNumber && a.endColumn <= b.startColumn)) {
439 return true;
440 }
441 > range.ts
442 > /**
443 > * Test if the two ranges are intersecting, but not touching at all.
444 > */
445 > public static areOnlyIntersecting(a: IRange, b: IRange): boolean {
446 // Check if `a` is before `b`
447 if (a.endLineNumber < (b.startLineNumber - 1) || (a.endLineNumber === b.startLineNumber && a.endColumn < (b.startColumn - 1))) {
457 return true;
458 }
459 > range.ts
460 > /**
461 > * A function that compares ranges, useful for sorting ranges
462 > * It will first compare ranges on the startPosition and then on the endPosition
463 > */
464 > public static compareRangesUsingStarts(a: IRange | null | undefined, b: IRange | null | undefined): number {
465 if (a && b) {
466 const aStartLineNumber = a.startLineNumber | 0;
490 return aExists - bExists;
491 }
492 > range.ts
493 > /**
494 > * A function that compares ranges, useful for sorting ranges
495 > * It will first compare ranges on the endPosition and then on the startPosition
496 > */
497 > public static compareRangesUsingEnds(a: IRange, b: IRange): number {
498 if (a.endLineNumber === b.endLineNumber) {
499 if (a.endColumn === b.endColumn) {
507 return a.endLineNumber - b.endLineNumber;
508 }
509 > range.ts
510 > /**
511 > * Test if the range spans multiple lines.
512 > */
513 > public static spansMultipleLines(range: IRange): boolean {
514 return range.endLineNumber > range.startLineNumber;
515 }
516 > range.ts
517 > public toJSON(): IRange {
518 return this;
519 }
520 > } range.ts
src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts 215 covered LOC · 37 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- monospaceLineBreaksComputer.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 * as strings from '../../../base/common/strings.js';
8 > import { WrappingIndent, IComputedEditorOptions, EditorOption } from '../config/editorOptions.js';
9 > import { CharacterClassifier } from '../core/characterClassifier.js';
10 > import { FontInfo } from '../config/fontInfo.js';
11 > import { LineInjectedText } from '../textModelEvents.js';
12 > import { InjectedTextOptions } from '../model.js';
13 > import { ILineBreaksComputerFactory, ILineBreaksComputer, ModelLineProjectionData, ILineBreaksComputerContext } from '../modelLineProjectionData.js';
14 >
15 > export class MonospaceLineBreaksComputerFactory implements ILineBreaksComputerFactory {
16 > public static create(options: IComputedEditorOptions): MonospaceLineBreaksComputerFactory {
17 return new MonospaceLineBreaksComputerFactory(
18 options.get(EditorOption.wordWrapBreakBeforeCharacters),
20 );
21 }
23 > private readonly classifier: WrappingCharacterClassifier;
24 >
25 > constructor(breakBeforeChars: string, breakAfterChars: string) {
26 > this.classifier = new WrappingCharacterClassifier(breakBeforeChars, breakAfterChars);
27 > }
28 >
29 > public createLineBreaksComputer(context: ILineBreaksComputerContext, fontInfo: FontInfo, tabSize: number, wrappingColumn: number, wrappingIndent: WrappingIndent, wordBreak: 'normal' | 'keepAll', wrapOnEscapedLineFeeds: boolean): ILineBreaksComputer {
30 > const lineNumbers: number[] = [];
31 > const previousBreakingData: (ModelLineProjectionData | null)[] = [];
32 > return {
33 > addRequest: (lineNumber: number, previousLineBreakData: ModelLineProjectionData | null) => {
34 > lineNumbers.push(lineNumber);
35 > previousBreakingData.push(previousLineBreakData);
36 > },
37 > finalize: () => {
38 > const columnsForFullWidthChar = fontInfo.typicalFullwidthCharacterWidth / fontInfo.typicalHalfwidthCharacterWidth;
39 > const result: (ModelLineProjectionData | null)[] = [];
40 > for (let i = 0, len = lineNumbers.length; i < len; i++) {
41 > const lineNumber = lineNumbers[i];
42 > const injectedText = context.getLineInjectedText(lineNumber);
43 > const lineText = context.getLineContent(lineNumber);
44 > const previousLineBreakData = previousBreakingData[i];
45 > const isLineFeedWrappingEnabled = wrapOnEscapedLineFeeds && lineText.includes('"') && lineText.includes('\\n');
46 > if (previousLineBreakData && !previousLineBreakData.injectionOptions && !injectedText && !isLineFeedWrappingEnabled) {
47 result[i] = createLineBreaksFromPreviousLineBreaks(this.classifier, previousLineBreakData, lineText, tabSize, wrappingColumn, columnsForFullWidthChar, wrappingIndent, wordBreak);
49 > result[i] = createLineBreaks(this.classifier, lineText, injectedText, tabSize, wrappingColumn, columnsForFullWidthChar, wrappingIndent, wordBreak, isLineFeedWrappingEnabled);
50 > }
51 > }
52 > arrPool1.length = 0;
53 > arrPool2.length = 0;
54 > return result;
55 > }
56 > };
57 > }
58 > }
59 >
60 > const enum CharacterClass {
61 > NONE = 0,
62 > BREAK_BEFORE = 1,
63 > BREAK_AFTER = 2,
64 > BREAK_IDEOGRAPHIC = 3 // for Han and Kana.
65 > }
66 >
67 > class WrappingCharacterClassifier extends CharacterClassifier<CharacterClass> {
68 >
69 > constructor(BREAK_BEFORE: string, BREAK_AFTER: string) {
70 > super(CharacterClass.NONE);
71 >
72 > for (let i = 0; i < BREAK_BEFORE.length; i++) {
73 > this.set(BREAK_BEFORE.charCodeAt(i), CharacterClass.BREAK_BEFORE); monospaceLineBreaksComputer.ts
74 > }
76 > for (let i = 0; i < BREAK_AFTER.length; i++) {
77 > this.set(BREAK_AFTER.charCodeAt(i), CharacterClass.BREAK_AFTER);
78 > }
79 > }
80 >
81 > public override get(charCode: number): CharacterClass {
82 > if (charCode >= 0 && charCode < 256) {
83 > return <CharacterClass>this._asciiMap[charCode]; monospaceLineBreaksComputer.ts
85 // Initialize CharacterClass.BREAK_IDEOGRAPHIC for these Unicode ranges:
86 // 1. CJK Unified Ideographs (0x4E00 -- 0x9FFF)
97 return <CharacterClass>(this._map.get(charCode) || this._defaultValue);
98 }
100 > }
101 >
102 > let arrPool1: number[] = [];
103 > let arrPool2: number[] = [];
104 >
105 function createLineBreaksFromPreviousLineBreaks(classifier: WrappingCharacterClassifier, previousBreakingData: ModelLineProjectionData, lineText: string, tabSize: number, firstLineBreakColumn: number, columnsForFullWidthChar: number, wrappingIndent: WrappingIndent, wordBreak: 'normal' | 'keepAll'): ModelLineProjectionData | null {
106 if (firstLineBreakColumn === -1) {
356 return previousBreakingData;
357 }
359 > function createLineBreaks(classifier: WrappingCharacterClassifier, _lineText: string, injectedTexts: LineInjectedText[] | null, tabSize: number, firstLineBreakColumn: number, columnsForFullWidthChar: number, wrappingIndent: WrappingIndent, wordBreak: 'normal' | 'keepAll', wrapOnEscapedLineFeeds: boolean): ModelLineProjectionData | null {
360 > const lineText = LineInjectedText.applyInjectedText(_lineText, injectedTexts);
361 >
362 > let injectionOptions: InjectedTextOptions[] | null;
363 > let injectionOffsets: number[] | null;
364 > if (injectedTexts && injectedTexts.length > 0) {
365 injectionOptions = injectedTexts.map(t => t.options);
366 injectionOffsets = injectedTexts.map(text => text.column - 1);
368 > injectionOptions = null;
369 > injectionOffsets = null;
370 > }
371 >
372 > if (firstLineBreakColumn === -1) {
373 if (!injectionOptions) {
374 return null;
378 return new ModelLineProjectionData(injectionOffsets, injectionOptions, [lineText.length], [], 0);
379 }
381 > const len = lineText.length;
382 > if (len <= 1) {
383 if (!injectionOptions) {
384 return null;
388 return new ModelLineProjectionData(injectionOffsets, injectionOptions, [lineText.length], [], 0);
389 }
391 > const isKeepAll = (wordBreak === 'keepAll');
392 > const wrappedTextIndentLength = computeWrappedTextIndentLength(lineText, tabSize, firstLineBreakColumn, columnsForFullWidthChar, wrappingIndent);
393 > const wrappedLineBreakColumn = firstLineBreakColumn - wrappedTextIndentLength;
394 >
395 > const breakingOffsets: number[] = [];
396 > const breakingOffsetsVisibleColumn: number[] = [];
397 > let breakingOffsetsCount: number = 0;
398 > let breakOffset = 0;
399 > let breakOffsetVisibleColumn = 0;
400 >
401 > let breakingColumn = firstLineBreakColumn;
402 > let prevCharCode = lineText.charCodeAt(0);
403 > let prevCharCodeClass = classifier.get(prevCharCode);
404 > let visibleColumn = computeCharWidth(prevCharCode, 0, tabSize, columnsForFullWidthChar);
405 >
406 > let startOffset = 1;
407 > if (strings.isHighSurrogate(prevCharCode)) {
408 // A surrogate pair must always be considered as a single unit, so it is never to be broken
409 visibleColumn += 1;
412 startOffset++;
413 }
415 > for (let i = startOffset; i < len; i++) {
416 > const charStartOffset = i;
417 > const charCode = lineText.charCodeAt(i);
418 > let charCodeClass: CharacterClass;
419 > let charWidth: number;
420 > let wrapEscapedLineFeed = false;
421 >
422 > if (strings.isHighSurrogate(charCode)) {
423 // A surrogate pair must always be considered as a single unit, so it is never to be broken
424 i++;
425 charCodeClass = CharacterClass.NONE;
426 charWidth = 2;
428 > charCodeClass = classifier.get(charCode); monospaceLineBreaksComputer.ts
429 > charWidth = computeCharWidth(charCode, visibleColumn, tabSize, columnsForFullWidthChar);
430 > }
432 > // literal \n shall trigger a softwrap
433 > if (wrapOnEscapedLineFeeds && isEscapedLineBreakAtPosition(lineText, i)) {
434 breakOffset = charStartOffset;
435 breakOffsetVisibleColumn = visibleColumn;
436 wrapEscapedLineFeed = true;
437 > } else if (canBreak(prevCharCode, prevCharCodeClass, charCode, charCodeClass, isKeepAll)) { monospaceLineBreaksComputer.ts
438 > breakOffset = charStartOffset; monospaceLineBreaksComputer.ts
439 > breakOffsetVisibleColumn = visibleColumn;
440 > }
442 > visibleColumn += charWidth;
443 >
444 > // check if adding character at `i` will go over the breaking column
445 > if (visibleColumn > breakingColumn || wrapEscapedLineFeed) {
446 > // We need to break at least before character at `i`: monospaceLineBreaksComputer.ts
447 >
448 > if (breakOffset === 0 || visibleColumn - breakOffsetVisibleColumn > wrappedLineBreakColumn) {
449 // Cannot break at `breakOffset`, must break at `i`
450 breakOffset = charStartOffset;
451 breakOffsetVisibleColumn = visibleColumn - charWidth;
452 }
454 > breakingOffsets[breakingOffsetsCount] = breakOffset;
455 > breakingOffsetsVisibleColumn[breakingOffsetsCount] = breakOffsetVisibleColumn;
456 > breakingOffsetsCount++;
457 > breakingColumn = breakOffsetVisibleColumn + wrappedLineBreakColumn;
458 > breakOffset = 0;
459 > }
461 > prevCharCode = charCode;
462 > prevCharCodeClass = charCodeClass;
463 > }
464 >
465 > if (breakingOffsetsCount === 0 && (!injectedTexts || injectedTexts.length === 0)) {
466 return null;
467 }
469 > // Add last segment
470 > breakingOffsets[breakingOffsetsCount] = len;
471 > breakingOffsetsVisibleColumn[breakingOffsetsCount] = visibleColumn;
472 >
473 > return new ModelLineProjectionData(injectionOffsets, injectionOptions, breakingOffsets, breakingOffsetsVisibleColumn, wrappedTextIndentLength);
474 > }
476 > function computeCharWidth(charCode: number, visibleColumn: number, tabSize: number, columnsForFullWidthChar: number): number {
477 > if (charCode === CharCode.Tab) {
478 return (tabSize - (visibleColumn % tabSize));
479 }
480 > if (strings.isFullWidthCharacter(charCode)) { monospaceLineBreaksComputer.ts
481 return columnsForFullWidthChar;
482 }
483 > if (charCode < 32) { monospaceLineBreaksComputer.ts
484 // when using `editor.renderControlCharacters`, the substitutions are often wide
485 return columnsForFullWidthChar;
486 }
488 > }
490 function tabCharacterWidth(visibleColumn: number, tabSize: number): number {
491 return (tabSize - (visibleColumn % tabSize));
492 }
494 > /**
495 > * Checks if the current position in the text should trigger a soft wrap due to escaped line feeds.
496 > * This handles the wrapOnEscapedLineFeeds feature which allows \n sequences in strings to trigger wrapping.
497 > */
498 function isEscapedLineBreakAtPosition(lineText: string, i: number): boolean {
499 if (i >= 2 && lineText.charAt(i - 1) === 'n') {
510 return false;
511 }
513 > /**
514 > * Kinsoku Shori : Don't break after a leading character, like an open bracket
515 > * Kinsoku Shori : Don't break before a trailing character, like a period
516 > */
517 > function canBreak(prevCharCode: number, prevCharCodeClass: CharacterClass, charCode: number, charCodeClass: CharacterClass, isKeepAll: boolean): boolean {
518 > return (
519 > charCode !== CharCode.Space
520 > && (
521 > (prevCharCodeClass === CharacterClass.BREAK_AFTER && charCodeClass !== CharacterClass.BREAK_AFTER) // break at the end of multiple BREAK_AFTER
522 > || (prevCharCodeClass !== CharacterClass.BREAK_BEFORE && charCodeClass === CharacterClass.BREAK_BEFORE) // break at the start of multiple BREAK_BEFORE monospaceLineBreaksComputer.ts
523 > || (!isKeepAll && prevCharCodeClass === CharacterClass.BREAK_IDEOGRAPHIC && charCodeClass !== CharacterClass.BREAK_AFTER)
524 > || (!isKeepAll && charCodeClass === CharacterClass.BREAK_IDEOGRAPHIC && prevCharCodeClass !== CharacterClass.BREAK_BEFORE)
526 > );
527 > }
528 >
529 > function computeWrappedTextIndentLength(lineText: string, tabSize: number, firstLineBreakColumn: number, columnsForFullWidthChar: number, wrappingIndent: WrappingIndent): number {
530 > let wrappedTextIndentLength = 0;
531 > if (wrappingIndent !== WrappingIndent.None) {
532 > const firstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(lineText); monospaceLineBreaksComputer.ts
533 > if (firstNonWhitespaceIndex !== -1) {
534 > // Track existing indent
535 >
536 > for (let i = 0; i < firstNonWhitespaceIndex; i++) {
537 const charWidth = (lineText.charCodeAt(i) === CharCode.Tab ? tabCharacterWidth(wrappedTextIndentLength, tabSize) : 1);
538 wrappedTextIndentLength += charWidth;
539 }
541 > // Increase indent of continuation lines, if desired
542 > const numberOfAdditionalTabs = (wrappingIndent === WrappingIndent.DeepIndent ? 2 : wrappingIndent === WrappingIndent.Indent ? 1 : 0);
543 > for (let i = 0; i < numberOfAdditionalTabs; i++) {
544 const charWidth = tabCharacterWidth(wrappedTextIndentLength, tabSize);
545 wrappedTextIndentLength += charWidth;
546 }
548 > // Force sticking to beginning of line if no character would fit except for the indentation
549 > if (wrappedTextIndentLength + columnsForFullWidthChar > firstLineBreakColumn) {
550 wrappedTextIndentLength = 0;
551 }
553 > }
554 > return wrappedTextIndentLength; monospaceLineBreaksComputer.ts
555 > }
src/vs/nls.ts 211 covered LOC · 17 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- nls.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 function getNLSMessages(): string[] {
7 return globalThis._VSCODE_NLS_MESSAGES;
8 }
9 > nls.ts
10 > export function getNLSLanguage(): string | undefined {
11 > return globalThis._VSCODE_NLS_LANGUAGE;
12 > }
13 >
14 > declare const document: { location?: { hash?: string } } | undefined;
15 > const isPseudo = getNLSLanguage() === 'pseudo' || (typeof document !== 'undefined' && document.location && typeof document.location.hash === 'string' && document.location.hash.indexOf('pseudo=true') >= 0);
16 >
17 > export interface ILocalizeInfo {
18 > key: string;
19 > comment: string[];
20 > }
21 >
22 > export interface ILocalizedString {
23 > original: string;
24 > value: string;
25 > }
26 >
27 > function _format(message: string, args: (string | number | boolean | undefined | null)[]): string { nls.ts
28 > let result: string;
29 >
30 > if (args.length === 0) {
31 > result = message; nls.ts
32 > } else { nls.ts
33 > result = message.replace(/\{(\d+)\}/g, (match, rest) => { nls.ts
34 > const index = rest[0];
35 > const arg = args[index];
36 > let result = match;
37 > if (typeof arg === 'string') {
38 > result = arg; nls.ts
39 > } else if (typeof arg === 'number' || typeof arg === 'boolean' || arg === void 0 || arg === null) { nls.ts
40 result = String(arg);
41 }
42 > return result; nls.ts
43 > });
44 > }
45 > nls.ts
46 > if (isPseudo) {
47 // FF3B and FF3D is the Unicode zenkaku representation for [ and ]
48 result = '\uFF3B' + result.replace(/[aouei]/g, '$&$&') + '\uFF3D';
49 }
50 > nls.ts
51 > return result;
52 > }
53 > nls.ts
54 > /**
55 > * Marks a string to be localized. Returns the localized string.
56 > *
57 > * @param info The {@linkcode ILocalizeInfo} which describes the id and comments associated with the localized string.
58 > * @param message The string to localize
59 > * @param args The arguments to the string
60 > *
61 > * @note `message` can contain `{n}` notation where it is replaced by the nth value in `...args`
62 > * @example `localize({ key: 'sayHello', comment: ['Welcomes user'] }, 'hello {0}', name)`
63 > *
64 > * @returns string The localized string.
65 > */
66 > export function localize(info: ILocalizeInfo, message: string, ...args: (string | number | boolean | undefined | null)[]): string;
67 >
68 > /**
69 > * Marks a string to be localized. Returns the localized string.
70 > *
71 > * @param key The key to use for localizing the string
72 > * @param message The string to localize
73 > * @param args The arguments to the string
74 > *
75 > * @note `message` can contain `{n}` notation where it is replaced by the nth value in `...args`
76 > * @example For example, `localize('sayHello', 'hello {0}', name)`
77 > *
78 > * @returns string The localized string.
79 > */
80 > export function localize(key: string, message: string, ...args: (string | number | boolean | undefined | null)[]): string;
81 >
82 > /**
83 > * @skipMangle
84 > */
85 > export function localize(data: ILocalizeInfo | string /* | number when built */, message: string /* | null when built */, ...args: (string | number | boolean | undefined | null)[]): string {
86 > if (typeof data === 'number') { nls.ts
87 return _format(lookupMessage(data, message), args);
88 }
89 > return _format(message, args); nls.ts
90 > }
91 > nls.ts
92 > /**
93 > * Only used when built: Looks up the message in the global NLS table.
94 > * This table is being made available as a global through bootstrapping
95 > * depending on the target context.
96 > */
97 function lookupMessage(index: number, fallback: string | null): string {
98 const message = getNLSMessages()?.[index];
105 return message;
106 }
107 > nls.ts
108 > /**
109 > * Marks a string to be localized. Returns an {@linkcode ILocalizedString}
110 > * which contains the localized string and the original string.
111 > *
112 > * @param info The {@linkcode ILocalizeInfo} which describes the id and comments associated with the localized string.
113 > * @param message The string to localize
114 > * @param args The arguments to the string
115 > *
116 > * @note `message` can contain `{n}` notation where it is replaced by the nth value in `...args`
117 > * @example `localize2({ key: 'sayHello', comment: ['Welcomes user'] }, 'hello {0}', name)`
118 > *
119 > * @returns ILocalizedString which contains the localized string and the original string.
120 > */
121 > export function localize2(info: ILocalizeInfo, message: string, ...args: (string | number | boolean | undefined | null)[]): ILocalizedString;
122 >
123 > /**
124 > * Marks a string to be localized. Returns an {@linkcode ILocalizedString}
125 > * which contains the localized string and the original string.
126 > *
127 > * @param key The key to use for localizing the string
128 > * @param message The string to localize
129 > * @param args The arguments to the string
130 > *
131 > * @note `message` can contain `{n}` notation where it is replaced by the nth value in `...args`
132 > * @example `localize('sayHello', 'hello {0}', name)`
133 > *
134 > * @returns ILocalizedString which contains the localized string and the original string.
135 > */
136 > export function localize2(key: string, message: string, ...args: (string | number | boolean | undefined | null)[]): ILocalizedString;
137 >
138 > /**
139 > * @skipMangle
140 > */
141 > export function localize2(data: ILocalizeInfo | string /* | number when built */, originalMessage: string, ...args: (string | number | boolean | undefined | null)[]): ILocalizedString {
142 let message: string;
143 if (typeof data === 'number') {
154 };
155 }
156 > nls.ts
157 > export interface INLSLanguagePackConfiguration {
158 >
159 > /**
160 > * The path to the translations config file that contains pointers to
161 > * all message bundles for `main` and extensions.
162 > */
163 > readonly translationsConfigFile: string;
164 >
165 > /**
166 > * The path to the file containing the translations for this language
167 > * pack as flat string array.
168 > */
169 > readonly messagesFile: string;
170 >
171 > /**
172 > * The path to the file that can be used to signal a corrupt language
173 > * pack, for example when reading the `messagesFile` fails. This will
174 > * instruct the application to re-create the cache on next startup.
175 > */
176 > readonly corruptMarkerFile: string;
177 > }
178 >
179 > export interface INLSConfiguration {
180 >
181 > /**
182 > * Locale as defined in `argv.json` or `app.getLocale()`.
183 > */
184 > readonly userLocale: string;
185 >
186 > /**
187 > * Locale as defined by the OS (e.g. `app.getPreferredSystemLanguages()`).
188 > */
189 > readonly osLocale: string;
190 >
191 > /**
192 > * The actual language of the UI that ends up being used considering `userLocale`
193 > * and `osLocale`.
194 > */
195 > readonly resolvedLanguage: string;
196 >
197 > /**
198 > * Defined if a language pack is used that is not the
199 > * default english language pack. This requires a language
200 > * pack to be installed as extension.
201 > */
202 > readonly languagePack?: INLSLanguagePackConfiguration;
203 >
204 > /**
205 > * The path to the file containing the default english messages
206 > * as flat string array. The file is only present in built
207 > * versions of the application.
208 > */
209 > readonly defaultMessagesFile: string;
210 >
211 > /**
212 > * Below properties are deprecated and only there to continue support
213 > * for `vscode-nls` module that depends on them.
214 > * Refs https://github.com/microsoft/vscode-nls/blob/main/src/node/main.ts#L36-L46
215 > */
216 > /** @deprecated */
217 > readonly locale: string;
218 > /** @deprecated */
219 > readonly availableLanguages: Record<string, string>;
220 > /** @deprecated */
221 > readonly _languagePackSupport?: boolean;
222 > /** @deprecated */
223 > readonly _languagePackId?: string;
224 > /** @deprecated */
225 > readonly _translationsConfigFile?: string;
226 > /** @deprecated */
227 > readonly _cacheRoot?: string;
228 > /** @deprecated */
229 > readonly _resolvedLanguagePackCoreLocation?: string;
230 > /** @deprecated */
231 > readonly _corruptedFile?: string;
232 > }
233 >
234 > export interface ILanguagePack {
235 > readonly hash: string;
236 > readonly label: string | undefined;
237 > readonly extensions: {
238 > readonly extensionIdentifier: { readonly id: string; readonly uuid?: string };
239 > readonly version: string;
240 > }[];
241 > readonly translations: Record<string, string | undefined>;
242 > }
243 >
244 > export type ILanguagePacks = Record<string, ILanguagePack | undefined>;
src/vs/editor/common/config/fontInfo.ts 208 covered LOC · 5 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- fontInfo.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 * as platform from '../../../base/common/platform.js';
7 > import { EditorOption, FindComputedEditorOptionValueById } from './editorOptions.js';
8 > import { EditorZoom } from './editorZoom.js';
9 >
10 > /**
11 > * Determined from empirical observations.
12 > * @internal
13 > */
14 > export const GOLDEN_LINE_HEIGHT_RATIO = platform.isMacintosh ? 1.5 : 1.35;
15 >
16 > /**
17 > * @internal
18 > */
19 > export const MINIMUM_LINE_HEIGHT = 8;
20 >
21 > /**
22 > * @internal
23 > */
24 > export interface IValidatedEditorOptions {
25 > get<T extends EditorOption>(id: T): FindComputedEditorOptionValueById<T>;
26 > }
27 >
28 > export class BareFontInfo {
29 > readonly _bareFontInfoBrand: void = undefined;
30 >
31 > /**
32 > * @internal
33 > */
34 > public static _create(fontFamily: string, fontWeight: string, fontSize: number, fontFeatureSettings: string, fontVariationSettings: string, lineHeight: number, letterSpacing: number, pixelRatio: number, ignoreEditorZoom: boolean): BareFontInfo {
35 > if (lineHeight === 0) {
36 > lineHeight = GOLDEN_LINE_HEIGHT_RATIO * fontSize;
37 > } else if (lineHeight < MINIMUM_LINE_HEIGHT) {
38 > // Values too small to be line heights in pixels are in ems.
39 > lineHeight = lineHeight * fontSize;
40 > }
41 >
42 > // Enforce integer, minimum constraints
43 > lineHeight = Math.round(lineHeight);
44 > if (lineHeight < MINIMUM_LINE_HEIGHT) {
45 > lineHeight = MINIMUM_LINE_HEIGHT;
46 > }
47 >
48 > const editorZoomLevelMultiplier = 1 + (ignoreEditorZoom ? 0 : EditorZoom.getZoomLevel() * 0.1);
49 > fontSize *= editorZoomLevelMultiplier;
50 > lineHeight *= editorZoomLevelMultiplier;
51 >
52 > if (fontVariationSettings === FONT_VARIATION_TRANSLATE) {
53 > if (fontWeight === 'normal' || fontWeight === 'bold') {
54 > fontVariationSettings = FONT_VARIATION_OFF;
55 > } else {
56 > const fontWeightAsNumber = parseInt(fontWeight, 10);
57 > fontVariationSettings = `'wght' ${fontWeightAsNumber}`;
58 > fontWeight = 'normal';
59 > }
60 > }
61 >
62 > return new BareFontInfo({
63 > pixelRatio: pixelRatio,
64 > fontFamily: fontFamily,
65 > fontWeight: fontWeight,
66 > fontSize: fontSize,
67 > fontFeatureSettings: fontFeatureSettings,
68 > fontVariationSettings,
69 > lineHeight: lineHeight,
70 > letterSpacing: letterSpacing
71 > });
72 > }
73 >
74 > readonly pixelRatio: number;
75 > readonly fontFamily: string;
76 > readonly fontWeight: string;
77 > readonly fontSize: number;
78 > readonly fontFeatureSettings: string;
79 > readonly fontVariationSettings: string;
80 > readonly lineHeight: number;
81 > readonly letterSpacing: number;
82 >
83 > /**
84 > * @internal
85 > */
86 > protected constructor(opts: {
87 > pixelRatio: number;
88 > fontFamily: string;
89 > fontWeight: string;
90 > fontSize: number;
91 > fontFeatureSettings: string;
92 > fontVariationSettings: string;
93 > lineHeight: number;
94 > letterSpacing: number;
95 > }) {
96 > this.pixelRatio = opts.pixelRatio;
97 > this.fontFamily = String(opts.fontFamily);
98 > this.fontWeight = String(opts.fontWeight);
99 > this.fontSize = opts.fontSize;
100 > this.fontFeatureSettings = opts.fontFeatureSettings;
101 > this.fontVariationSettings = opts.fontVariationSettings;
102 > this.lineHeight = opts.lineHeight | 0;
103 > this.letterSpacing = opts.letterSpacing;
104 > }
105 >
106 > /**
107 > * @internal
108 > */
109 > public getId(): string {
110 return `${this.pixelRatio}-${this.fontFamily}-${this.fontWeight}-${this.fontSize}-${this.fontFeatureSettings}-${this.fontVariationSettings}-${this.lineHeight}-${this.letterSpacing}`;
111 }
112 > fontInfo.ts
113 > /**
114 > * @internal
115 > */
116 > public getMassagedFontFamily(): string {
117 const fallbackFontFamily = EDITOR_FONT_DEFAULTS.fontFamily;
118 const fontFamily = BareFontInfo._wrapInQuotes(this.fontFamily);
122 return fontFamily;
123 }
124 > fontInfo.ts
125 > private static _wrapInQuotes(fontFamily: string): string {
126 if (/[,"']/.test(fontFamily)) {
127 // Looks like the font family might be already escaped
134 return fontFamily;
135 }
136 > } fontInfo.ts
137 >
138 > // change this whenever `FontInfo` members are changed
139 > export const SERIALIZED_FONT_INFO_VERSION = 2;
140 >
141 > export class FontInfo extends BareFontInfo {
142 > readonly _editorStylingBrand: void = undefined;
143 >
144 > readonly version: number = SERIALIZED_FONT_INFO_VERSION;
145 > readonly isTrusted: boolean;
146 > readonly isMonospace: boolean;
147 > readonly typicalHalfwidthCharacterWidth: number;
148 > readonly typicalFullwidthCharacterWidth: number;
149 > readonly canUseHalfwidthRightwardsArrow: boolean;
150 > readonly spaceWidth: number;
151 > readonly middotWidth: number;
152 > readonly wsmiddotWidth: number;
153 > readonly maxDigitWidth: number;
154 >
155 > /**
156 > * @internal
157 > */
158 > constructor(opts: {
159 > pixelRatio: number;
160 > fontFamily: string;
161 > fontWeight: string;
162 > fontSize: number;
163 > fontFeatureSettings: string;
164 > fontVariationSettings: string;
165 > lineHeight: number;
166 > letterSpacing: number;
167 > isMonospace: boolean;
168 > typicalHalfwidthCharacterWidth: number;
169 > typicalFullwidthCharacterWidth: number;
170 > canUseHalfwidthRightwardsArrow: boolean;
171 > spaceWidth: number;
172 > middotWidth: number;
173 > wsmiddotWidth: number;
174 > maxDigitWidth: number;
175 > }, isTrusted: boolean) {
176 > super(opts);
177 > this.isTrusted = isTrusted;
178 > this.isMonospace = opts.isMonospace;
179 > this.typicalHalfwidthCharacterWidth = opts.typicalHalfwidthCharacterWidth;
180 > this.typicalFullwidthCharacterWidth = opts.typicalFullwidthCharacterWidth;
181 > this.canUseHalfwidthRightwardsArrow = opts.canUseHalfwidthRightwardsArrow;
182 > this.spaceWidth = opts.spaceWidth;
183 > this.middotWidth = opts.middotWidth;
184 > this.wsmiddotWidth = opts.wsmiddotWidth;
185 > this.maxDigitWidth = opts.maxDigitWidth;
186 > }
187 >
188 > /**
189 > * @internal
190 > */
191 > public equals(other: FontInfo): boolean {
192 return (
193 this.fontFamily === other.fontFamily
207 );
208 }
209 > } fontInfo.ts
210 > /**
211 > * @internal
212 > */
213 > export const FONT_VARIATION_OFF = 'normal';
214 > /**
215 > * @internal
216 > */
217 > export const FONT_VARIATION_TRANSLATE = 'translate';
218 >
219 > /**
220 > * @internal
221 > */
222 > export const DEFAULT_WINDOWS_FONT_FAMILY = 'Consolas, \'Courier New\', monospace';
223 > /**
224 > * @internal
225 > */
226 > export const DEFAULT_MAC_FONT_FAMILY = 'Menlo, Monaco, \'Courier New\', monospace';
227 > /**
228 > * @internal
229 > */
230 > export const DEFAULT_LINUX_FONT_FAMILY = '\'Droid Sans Mono\', monospace';
231 > /**
232 > * @internal
233 > */
234 > export const EDITOR_FONT_DEFAULTS = {
235 > fontFamily: (
236 > platform.isMacintosh ? DEFAULT_MAC_FONT_FAMILY : (platform.isWindows ? DEFAULT_WINDOWS_FONT_FAMILY : DEFAULT_LINUX_FONT_FAMILY)
237 > ),
238 > fontWeight: 'normal',
239 > fontSize: (
240 > platform.isMacintosh ? 12 : 14
241 > ),
242 > lineHeight: 0,
243 > letterSpacing: 0,
244 > };
src/vs/base/common/scrollable.ts 205 covered LOC · 32 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- scrollable.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 { Emitter, Event } from './event.js';
7 > import { Disposable, IDisposable } from './lifecycle.js';
8 >
9 > export const enum ScrollbarVisibility {
10 > Auto = 1,
11 > Hidden = 2,
12 > Visible = 3
13 > }
14 >
15 > export interface ScrollEvent {
16 > inSmoothScrolling: boolean;
17 >
18 > oldWidth: number;
19 > oldScrollWidth: number;
20 > oldScrollLeft: number;
21 >
22 > width: number;
23 > scrollWidth: number;
24 > scrollLeft: number;
25 >
26 > oldHeight: number;
27 > oldScrollHeight: number;
28 > oldScrollTop: number;
29 >
30 > height: number;
31 > scrollHeight: number;
32 > scrollTop: number;
33 >
34 > widthChanged: boolean;
35 > scrollWidthChanged: boolean;
36 > scrollLeftChanged: boolean;
37 >
38 > heightChanged: boolean;
39 > scrollHeightChanged: boolean;
40 > scrollTopChanged: boolean;
41 > }
42 >
43 > export class ScrollState implements IScrollDimensions, IScrollPosition {
44 > _scrollStateBrand: void = undefined;
45 >
46 > public readonly rawScrollLeft: number;
47 > public readonly rawScrollTop: number;
48 >
49 > public readonly width: number;
50 > public readonly scrollWidth: number;
51 > public readonly scrollLeft: number;
52 > public readonly height: number;
53 > public readonly scrollHeight: number;
54 > public readonly scrollTop: number;
55 >
56 > constructor(
57 private readonly _forceIntegerValues: boolean,
58 width: number,
102 this.scrollTop = scrollTop;
103 }
105 > public equals(other: ScrollState): boolean {
106 return (
107 this.rawScrollLeft === other.rawScrollLeft
115 );
116 }
118 > public withScrollDimensions(update: INewScrollDimensions, useRawScrollPositions: boolean): ScrollState {
119 return new ScrollState(
120 this._forceIntegerValues,
127 );
128 }
130 > public withScrollPosition(update: INewScrollPosition): ScrollState {
131 return new ScrollState(
132 this._forceIntegerValues,
139 );
140 }
142 > public createScrollEvent(previous: ScrollState, inSmoothScrolling: boolean): ScrollEvent {
143 const widthChanged = (this.width !== previous.width);
144 const scrollWidthChanged = (this.scrollWidth !== previous.scrollWidth);
176 };
177 }
179 > }
180 >
181 > export interface IScrollDimensions {
182 > readonly width: number;
183 > readonly scrollWidth: number;
184 > readonly height: number;
185 > readonly scrollHeight: number;
186 > }
187 > export interface INewScrollDimensions {
188 > width?: number;
189 > scrollWidth?: number;
190 > height?: number;
191 > scrollHeight?: number;
192 > }
193 >
194 > export interface IScrollPosition {
195 > readonly scrollLeft: number;
196 > readonly scrollTop: number;
197 > }
198 > export interface ISmoothScrollPosition {
199 > readonly scrollLeft: number;
200 > readonly scrollTop: number;
201 >
202 > readonly width: number;
203 > readonly height: number;
204 > }
205 > export interface INewScrollPosition {
206 > scrollLeft?: number;
207 > scrollTop?: number;
208 > }
209 >
210 > export interface IScrollableOptions {
211 > /**
212 > * Define if the scroll values should always be integers.
213 > */
214 > forceIntegerValues: boolean;
215 > /**
216 > * Set the duration (ms) used for smooth scroll animations.
217 > */
218 > smoothScrollDuration: number;
219 > /**
220 > * A function to schedule an update at the next frame (used for smooth scroll animations).
221 > */
222 > scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable;
223 > }
224 >
225 > export class Scrollable extends Disposable {
226 >
227 > _scrollableBrand: void = undefined;
228 >
229 > private _smoothScrollDuration: number;
230 > private readonly _scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable;
231 > private _state: ScrollState;
232 > private _smoothScrolling: SmoothScrollingOperation | null;
233 >
234 > private _onScroll = this._register(new Emitter<ScrollEvent>());
235 > public readonly onScroll: Event<ScrollEvent> = this._onScroll.event;
236 >
237 > constructor(options: IScrollableOptions) {
238 super();
239
243 this._smoothScrolling = null;
244 }
246 > public override dispose(): void {
247 if (this._smoothScrolling) {
248 this._smoothScrolling.dispose();
251 super.dispose();
252 }
254 > public setSmoothScrollDuration(smoothScrollDuration: number): void {
255 this._smoothScrollDuration = smoothScrollDuration;
256 }
258 > public validateScrollPosition(scrollPosition: INewScrollPosition): IScrollPosition {
259 return this._state.withScrollPosition(scrollPosition);
260 }
262 > public getScrollDimensions(): IScrollDimensions {
263 return this._state;
264 }
266 > public setScrollDimensions(dimensions: INewScrollDimensions, useRawScrollPositions: boolean): void {
267 const newState = this._state.withScrollDimensions(dimensions, useRawScrollPositions);
268 this._setState(newState, Boolean(this._smoothScrolling));
271 this._smoothScrolling?.acceptScrollDimensions(this._state);
272 }
274 > /**
275 > * Returns the final scroll position that the instance will have once the smooth scroll animation concludes.
276 > * If no scroll animation is occurring, it will return the current scroll position instead.
277 > */
278 > public getFutureScrollPosition(): IScrollPosition {
279 if (this._smoothScrolling) {
280 return this._smoothScrolling.to;
282 return this._state;
283 }
285 > /**
286 > * Returns the current scroll position.
287 > * Note: This result might be an intermediate scroll position, as there might be an ongoing smooth scroll animation.
288 > */
289 > public getCurrentScrollPosition(): IScrollPosition {
290 return this._state;
291 }
293 > public setScrollPositionNow(update: INewScrollPosition): void {
294 // no smooth scrolling requested
295 const newState = this._state.withScrollPosition(update);
303 this._setState(newState, false);
304 }
306 > public setScrollPositionSmooth(update: INewScrollPosition, reuseAnimation?: boolean): void {
307 if (this._smoothScrollDuration === 0) {
308 // Smooth scrolling not supported.
348 });
349 }
351 > public hasPendingScrollAnimation(): boolean {
352 return Boolean(this._smoothScrolling);
353 }
355 > private _performSmoothScrolling(): void {
356 if (!this._smoothScrolling) {
357 return;
383 });
384 }
386 > private _setState(newState: ScrollState, inSmoothScrolling: boolean): void {
387 const oldState = this._state;
388 if (oldState.equals(newState)) {
393 this._onScroll.fire(this._state.createScrollEvent(oldState, inSmoothScrolling));
394 }
395 > } scrollable.ts
396 >
397 > export class SmoothScrollingUpdate {
398 >
399 > public readonly scrollLeft: number;
400 > public readonly scrollTop: number;
401 > public readonly isDone: boolean;
402 >
403 > constructor(scrollLeft: number, scrollTop: number, isDone: boolean) {
404 this.scrollLeft = scrollLeft;
405 this.scrollTop = scrollTop;
406 this.isDone = isDone;
407 }
409 > }
410 >
411 > interface IAnimation {
412 > (completion: number): number;
413 > }
414 >
415 function createEaseOutCubic(from: number, to: number): IAnimation {
416 const delta = to - from;
419 };
420 }
422 function createComposed(a: IAnimation, b: IAnimation, cut: number): IAnimation {
423 return function (completion: number): number {
428 };
429 }
431 > export class SmoothScrollingOperation {
432 >
433 > public readonly from: ISmoothScrollPosition;
434 > public to: ISmoothScrollPosition;
435 > public readonly duration: number;
436 > public readonly startTime: number;
437 > public animationFrameDisposable: IDisposable | null;
438 >
439 > private scrollLeft!: IAnimation;
440 > private scrollTop!: IAnimation;
441 >
442 > constructor(from: ISmoothScrollPosition, to: ISmoothScrollPosition, startTime: number, duration: number) {
443 this.from = from;
444 this.to = to;
450 this._initAnimations();
451 }
453 > private _initAnimations(): void {
454 this.scrollLeft = this._initAnimation(this.from.scrollLeft, this.to.scrollLeft, this.to.width);
455 this.scrollTop = this._initAnimation(this.from.scrollTop, this.to.scrollTop, this.to.height);
456 }
458 > private _initAnimation(from: number, to: number, viewportSize: number): IAnimation {
459 const delta = Math.abs(from - to);
460 if (delta > 2.5 * viewportSize) {
472 return createEaseOutCubic(from, to);
473 }
475 > public dispose(): void {
476 if (this.animationFrameDisposable !== null) {
477 this.animationFrameDisposable.dispose();
479 }
480 }
482 > public acceptScrollDimensions(state: ScrollState): void {
483 this.to = state.withScrollPosition(this.to);
484 this._initAnimations();
485 }
487 > public tick(): SmoothScrollingUpdate {
488 return this._tick(Date.now());
489 }
491 > protected _tick(now: number): SmoothScrollingUpdate {
492 const completion = (now - this.startTime) / this.duration;
493
500 return new SmoothScrollingUpdate(this.to.scrollLeft, this.to.scrollTop, true);
501 }
503 > public combine(from: ISmoothScrollPosition, to: ISmoothScrollPosition, duration: number): SmoothScrollingOperation {
504 return SmoothScrollingOperation.start(from, to, duration);
505 }
507 > public static start(from: ISmoothScrollPosition, to: ISmoothScrollPosition, duration: number): SmoothScrollingOperation {
508 // +10 / -10 : pretend the animation already started for a quicker response to a scroll request
509 duration = duration + 10;
512 return new SmoothScrollingOperation(from, to, startTime, duration);
513 }
514 > } scrollable.ts
515 >
516 function easeInCubic(t: number) {
517 return Math.pow(t, 3);
518 }
520 function easeOutCubic(t: number) {
521 return 1 - easeInCubic(1 - t);
src/vs/platform/contextkey/common/scanner.ts 203 covered LOC · 58 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- scanner.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 { illegalState } from '../../../base/common/errors.js';
8 > import { localize } from '../../../nls.js';
9 >
10 > export const enum TokenType {
11 > LParen,
12 > RParen,
13 > Neg,
14 > Eq,
15 > NotEq,
16 > Lt,
17 > LtEq,
18 > Gt,
19 > GtEq,
20 > RegexOp,
21 > RegexStr,
22 > True,
23 > False,
24 > In,
25 > Not,
26 > And,
27 > Or,
28 > Str,
29 > QuotedStr,
30 > Error,
31 > EOF,
32 > }
33 >
34 > export type Token =
35 > | { type: TokenType.LParen; offset: number }
36 > | { type: TokenType.RParen; offset: number }
37 > | { type: TokenType.Neg; offset: number }
38 > | { type: TokenType.Eq; offset: number; isTripleEq: boolean }
39 > | { type: TokenType.NotEq; offset: number; isTripleEq: boolean }
40 > | { type: TokenType.Lt; offset: number }
41 > | { type: TokenType.LtEq; offset: number }
42 > | { type: TokenType.Gt; offset: number }
43 > | { type: TokenType.GtEq; offset: number }
44 > | { type: TokenType.RegexOp; offset: number }
45 > | { type: TokenType.RegexStr; offset: number; lexeme: string }
46 > | { type: TokenType.True; offset: number }
47 > | { type: TokenType.False; offset: number }
48 > | { type: TokenType.In; offset: number }
49 > | { type: TokenType.Not; offset: number }
50 > | { type: TokenType.And; offset: number }
51 > | { type: TokenType.Or; offset: number }
52 > | { type: TokenType.Str; offset: number; lexeme: string }
53 > | { type: TokenType.QuotedStr; offset: number; lexeme: string }
54 > | { type: TokenType.Error; offset: number; lexeme: string }
55 > | { type: TokenType.EOF; offset: number };
56 >
57 > type KeywordTokenType = TokenType.Not | TokenType.In | TokenType.False | TokenType.True;
58 > type TokenTypeWithoutLexeme =
59 > TokenType.LParen |
60 > TokenType.RParen |
61 > TokenType.Neg |
62 > TokenType.Lt |
63 > TokenType.LtEq |
64 > TokenType.Gt |
65 > TokenType.GtEq |
66 > TokenType.RegexOp |
67 > TokenType.True |
68 > TokenType.False |
69 > TokenType.In |
70 > TokenType.Not |
71 > TokenType.And |
72 > TokenType.Or |
73 > TokenType.EOF;
74 >
75 > /**
76 > * Example:
77 > * `foo == bar'` - note how single quote doesn't have a corresponding closing quote,
78 > * so it's reported as unexpected
79 > */
80 > export type LexingError = {
81 > offset: number; /** note that this doesn't take into account escape characters from the original encoding of the string, e.g., within an extension manifest file's JSON encoding */
82 > lexeme: string;
83 > additionalInfo?: string;
84 > };
85 >
86 function hintDidYouMean(...meant: string[]) {
87 switch (meant.length) {
96 }
97 }
98 > scanner.ts
99 > const hintDidYouForgetToOpenOrCloseQuote = localize('contextkey.scanner.hint.didYouForgetToOpenOrCloseQuote', "Did you forget to open or close the quote?");
100 > const hintDidYouForgetToEscapeSlash = localize('contextkey.scanner.hint.didYouForgetToEscapeSlash', "Did you forget to escape the '/' (slash) character? Put two backslashes before it to escape, e.g., '\\\\/\'.");
101 >
102 > /**
103 > * A simple scanner for context keys.
104 > *
105 > * Example:
106 > *
107 > * ```ts
108 > * const scanner = new Scanner().reset('resourceFileName =~ /docker/ && !config.docker.enabled');
109 > * const tokens = [...scanner];
110 > * if (scanner.errorTokens.length > 0) {
111 > * scanner.errorTokens.forEach(err => console.error(`Unexpected token at ${err.offset}: ${err.lexeme}\nHint: ${err.additional}`));
112 > * } else {
113 > * // process tokens
114 > * }
115 > * ```
116 > */
117 > export class Scanner {
118 >
119 > static getLexeme(token: Token): string {
120 > switch (token.type) {
121 > case TokenType.LParen:
122 > return '('; scanner.ts
123 > case TokenType.RParen: scanner.ts
124 > return ')'; scanner.ts
125 > case TokenType.Neg: scanner.ts
126 > return '!'; scanner.ts
127 > case TokenType.Eq: scanner.ts
128 > return token.isTripleEq ? '===' : '=='; scanner.ts
129 > case TokenType.NotEq: scanner.ts
130 > return token.isTripleEq ? '!==' : '!='; scanner.ts
131 > case TokenType.Lt: scanner.ts
132 > return '<'; scanner.ts
133 > case TokenType.LtEq: scanner.ts
134 > return '<='; scanner.ts
135 > case TokenType.Gt: scanner.ts
136 > return '>'; scanner.ts
137 > case TokenType.GtEq: scanner.ts
138 > return '>='; scanner.ts
139 > case TokenType.RegexOp: scanner.ts
140 > return '=~'; scanner.ts
141 > case TokenType.RegexStr: scanner.ts
142 > return token.lexeme; scanner.ts
143 > case TokenType.True: scanner.ts
144 > return 'true'; scanner.ts
145 > case TokenType.False: scanner.ts
146 > return 'false'; scanner.ts
147 > case TokenType.In: scanner.ts
148 > return 'in'; scanner.ts
149 > case TokenType.Not: scanner.ts
150 > return 'not'; scanner.ts
151 > case TokenType.And: scanner.ts
152 > return '&&'; scanner.ts
153 > case TokenType.Or: scanner.ts
154 > return '||'; scanner.ts
155 > case TokenType.Str: scanner.ts
156 > return token.lexeme; scanner.ts
157 > case TokenType.QuotedStr: scanner.ts
158 > return token.lexeme; scanner.ts
159 > case TokenType.Error: scanner.ts
160 > return token.lexeme; scanner.ts
161 > case TokenType.EOF: scanner.ts
162 > return 'EOF'; scanner.ts
163 > default: scanner.ts
164 > throw illegalState(`unhandled token type: ${JSON.stringify(token)}; have you forgotten to add a case?`); scanner.ts
165 > } scanner.ts
166 > }
167 >
168 > private static _regexFlags = new Set(['i', 'g', 's', 'm', 'y', 'u'].map(ch => ch.charCodeAt(0)));
169 >
170 > private static _keywords = new Map<string, KeywordTokenType>([
171 > ['not', TokenType.Not],
172 > ['in', TokenType.In],
173 > ['false', TokenType.False],
174 > ['true', TokenType.True],
175 > ]);
176 >
177 > private _input: string = '';
178 > private _start: number = 0;
179 > private _current: number = 0;
180 > private _tokens: Token[] = [];
181 > private _errors: LexingError[] = [];
182 >
183 > get errors(): Readonly<LexingError[]> {
184 return this._errors;
185 }
186 > scanner.ts
187 > reset(value: string) {
188 this._input = value;
189
195 return this;
196 }
197 > scanner.ts
198 > scan() {
199 while (!this._isAtEnd()) {
200
267 return Array.from(this._tokens);
268 }
269 > scanner.ts
270 > private _match(expected: number): boolean {
271 if (this._isAtEnd()) {
272 return false;
278 return true;
279 }
280 > scanner.ts
281 > private _advance(): number {
282 return this._input.charCodeAt(this._current++);
283 }
284 > scanner.ts
285 > private _peek(): number {
286 return this._isAtEnd() ? CharCode.Null : this._input.charCodeAt(this._current);
287 }
288 > scanner.ts
289 > private _addToken(type: TokenTypeWithoutLexeme) {
290 this._tokens.push({ type, offset: this._start });
291 }
292 > scanner.ts
293 > private _error(additional?: string) {
294 const offset = this._start;
295 const lexeme = this._input.substring(this._start, this._current);
298 this._tokens.push(errToken);
299 }
300 > scanner.ts
301 > // u - unicode, y - sticky // TODO@ulugbekna: we accept double quotes as part of the string rather than as a delimiter (to preserve old parser's behavior)
302 > private stringRe = /[a-zA-Z0-9_<>\-\./\\:\*\?\+\[\]\^,#@;"%\$\p{L}-]+/uy;
303 > private _string() {
304 this.stringRe.lastIndex = this._start;
305 const match = this.stringRe.exec(this._input);
315 }
316 }
317 > scanner.ts
318 > // captures the lexeme without the leading and trailing '
319 > private _quotedString() {
320 while (this._peek() !== CharCode.SingleQuote && !this._isAtEnd()) { // TODO@ulugbekna: add support for escaping ' ?
321 this._advance();
332 this._tokens.push({ type: TokenType.QuotedStr, lexeme: this._input.substring(this._start + 1, this._current - 1), offset: this._start + 1 });
333 }
334 > scanner.ts
335 > /*
336 > * Lexing a regex expression: /.../[igsmyu]*
337 > * Based on https://github.com/microsoft/TypeScript/blob/9247ef115e617805983740ba795d7a8164babf89/src/compiler/scanner.ts#L2129-L2181
338 > *
339 > * Note that we want slashes within a regex to be escaped, e.g., /file:\\/\\/\\// should match `file:///`
340 > */
341 > private _regex() {
342 let p = this._current;
343
378 this._tokens.push({ type: TokenType.RegexStr, lexeme, offset: this._start });
379 }
380 > scanner.ts
381 > private _isAtEnd() {
382 return this._current >= this._input.length;
383 }
384 > } scanner.ts
src/vs/base/common/platform.ts 189 covered LOC · 12 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- platform.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 * as nls from '../../nls.js';
7 >
8 > export const LANGUAGE_DEFAULT = 'en';
9 >
10 > let _isWindows = false;
11 > let _isMacintosh = false;
12 > let _isLinux = false;
13 > let _isLinuxSnap = false;
14 > let _isNative = false;
15 > let _isWeb = false;
16 > let _isElectron = false;
17 > let _isIOS = false;
18 > let _isCI = false;
19 > let _isMobile = false;
20 > let _locale: string | undefined = undefined;
21 > let _language: string = LANGUAGE_DEFAULT;
22 > let _platformLocale: string = LANGUAGE_DEFAULT;
23 > let _translationsConfigFile: string | undefined = undefined;
24 > let _userAgent: string | undefined = undefined;
25 >
26 > export interface IProcessEnvironment {
27 > [key: string]: string | undefined;
28 > }
29 >
30 > /**
31 > * This interface is intentionally not identical to node.js
32 > * process because it also works in sandboxed environments
33 > * where the process object is implemented differently. We
34 > * define the properties here that we need for `platform`
35 > * to work and nothing else.
36 > */
37 > export interface INodeProcess {
38 > platform: string;
39 > arch: string;
40 > env: IProcessEnvironment;
41 > versions?: {
42 > node?: string;
43 > electron?: string;
44 > chrome?: string;
45 > };
46 > type?: string;
47 > cwd: () => string;
48 > }
49 >
50 > declare const process: INodeProcess;
51 >
52 > const $globalThis: any = globalThis;
53 >
54 > let nodeProcess: INodeProcess | undefined = undefined;
55 > if (typeof $globalThis.vscode !== 'undefined' && typeof $globalThis.vscode.process !== 'undefined') {
56 // Native environment (sandboxed)
57 nodeProcess = $globalThis.vscode.process;
58 > } else if (typeof process !== 'undefined' && typeof process?.versions?.node === 'string') { platform.ts
59 > // Native environment (non-sandboxed)
60 > nodeProcess = process;
61 > }
62 >
63 > const isElectronProcess = typeof nodeProcess?.versions?.electron === 'string';
64 > const isElectronRenderer = isElectronProcess && nodeProcess?.type === 'renderer';
65 >
66 > interface INavigator {
67 > userAgent: string;
68 > maxTouchPoints?: number;
69 > language: string;
70 > }
71 > declare const navigator: INavigator;
72 >
73 > // Native environment
74 > if (typeof nodeProcess === 'object') {
75 > _isWindows = (nodeProcess.platform === 'win32');
76 > _isMacintosh = (nodeProcess.platform === 'darwin');
77 > _isLinux = (nodeProcess.platform === 'linux');
78 > _isLinuxSnap = _isLinux && !!nodeProcess.env['SNAP'] && !!nodeProcess.env['SNAP_REVISION'];
79 > _isElectron = isElectronProcess;
80 > _isCI = !!nodeProcess.env['CI'] || !!nodeProcess.env['BUILD_ARTIFACTSTAGINGDIRECTORY'] || !!nodeProcess.env['GITHUB_WORKSPACE'];
81 > _locale = LANGUAGE_DEFAULT;
82 > _language = LANGUAGE_DEFAULT;
83 > const rawNlsConfig = nodeProcess.env['VSCODE_NLS_CONFIG'];
84 > if (rawNlsConfig) {
85 try {
86 const nlsConfig: nls.INLSConfiguration = JSON.parse(rawNlsConfig);
113 console.error('Unable to resolve platform.');
114 }
115 > platform.ts
116 > export const enum Platform {
117 > Web,
118 > Mac,
119 > Linux,
120 > Windows
121 > }
122 > export type PlatformName = 'Web' | 'Windows' | 'Mac' | 'Linux';
123 >
124 > export function PlatformToString(platform: Platform): PlatformName {
125 switch (platform) {
126 case Platform.Web: return 'Web';
130 }
131 }
132 > platform.ts
133 > let _platform: Platform = Platform.Web;
134 > if (_isMacintosh) {
135 _platform = Platform.Mac;
136 > } else if (_isWindows) { platform.ts
137 _platform = Platform.Windows;
138 > } else if (_isLinux) { platform.ts
139 > _platform = Platform.Linux;
140 > }
141 >
142 > export const isWindows = _isWindows;
143 > export const isMacintosh = _isMacintosh;
144 > export const isLinux = _isLinux;
145 > export const isLinuxSnap = _isLinuxSnap;
146 > export const isNative = _isNative;
147 > export const isElectron = _isElectron;
148 > export const isWeb = _isWeb;
149 > export const isWebWorker = (_isWeb && typeof $globalThis.importScripts === 'function');
150 > export const webWorkerOrigin = isWebWorker ? $globalThis.origin : undefined;
151 > export const isIOS = _isIOS;
152 > export const isMobile = _isMobile;
153 > /**
154 > * Whether we run inside a CI environment, such as
155 > * GH actions or Azure Pipelines.
156 > */
157 > export const isCI = _isCI;
158 > export const platform = _platform;
159 > export const userAgent = _userAgent;
160 >
161 > /**
162 > * The language used for the user interface. The format of
163 > * the string is all lower case (e.g. zh-tw for Traditional
164 > * Chinese or de for German)
165 > */
166 > export const language = _language;
167 >
168 > export namespace Language {
169 >
170 > export function value(): string {
171 return language;
172 }
173 > platform.ts
174 > export function isDefaultVariant(): boolean {
175 if (language.length === 2) {
176 return language === 'en';
181 }
182 }
183 > platform.ts
184 > export function isDefault(): boolean {
185 return language === 'en';
186 }
187 > } platform.ts
188 >
189 > /**
190 > * Desktop: The OS locale or the locale specified by --locale or `argv.json`.
191 > * Web: matches `platformLocale`.
192 > *
193 > * The UI is not necessarily shown in the provided locale.
194 > */
195 > export const locale = _locale;
196 >
197 > /**
198 > * This will always be set to the OS/browser's locale regardless of
199 > * what was specified otherwise. The format of the string is all
200 > * lower case (e.g. zh-tw for Traditional Chinese). The UI is not
201 > * necessarily shown in the provided locale.
202 > */
203 > export const platformLocale = _platformLocale;
204 >
205 > /**
206 > * The translations that are available through language packs.
207 > */
208 > export const translationsConfigFile = _translationsConfigFile;
209 >
210 > export const setTimeout0IsFaster = (typeof $globalThis.postMessage === 'function' && !$globalThis.importScripts);
211 >
212 > /**
213 > * See https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#:~:text=than%204%2C%20then-,set%20timeout%20to%204,-.
214 > *
215 > * Works similarly to `setTimeout(0)` but doesn't suffer from the 4ms artificial delay
216 > * that browsers set when the nesting level is > 5.
217 > */
218 > export const setTimeout0 = (() => {
219 > if (setTimeout0IsFaster) {
220 interface IQueueElement {
221 id: number;
246 };
247 }
248 > return (callback: () => void) => setTimeout(callback); platform.ts
249 > })();
250 >
251 > export const enum OperatingSystem {
252 > Windows = 1,
253 > Macintosh = 2,
254 > Linux = 3
255 > }
256 > export const OS = (_isMacintosh || _isIOS ? OperatingSystem.Macintosh : (_isWindows ? OperatingSystem.Windows : OperatingSystem.Linux));
257 >
258 > let _isLittleEndian = true;
259 > let _isLittleEndianComputed = false;
260 > export function isLittleEndian(): boolean {
261 if (!_isLittleEndianComputed) {
262 _isLittleEndianComputed = true;
269 return _isLittleEndian;
270 }
271 > platform.ts
272 > export const isChrome = !!(userAgent && userAgent.indexOf('Chrome') >= 0);
273 > export const isFirefox = !!(userAgent && userAgent.indexOf('Firefox') >= 0);
274 > export const isSafari = !!(!isChrome && (userAgent && userAgent.indexOf('Safari') >= 0));
275 > export const isEdge = !!(userAgent && userAgent.indexOf('Edg/') >= 0);
276 > export const isAndroid = !!(userAgent && userAgent.indexOf('Android') >= 0);
277 > export const hasElectronUserAgent = !!(userAgent && userAgent.indexOf('Electron') >= 0);
278 >
279 > export function isTahoeOrNewer(osVersion: string): boolean {
280 return parseFloat(osVersion) >= 25;
281 }
src/vs/base/common/errors.ts 183 covered LOC · 32 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- errors.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 interface ErrorListenerCallback {
7 > (error: any): void;
8 > }
9 >
10 > export interface ErrorListenerUnbind {
11 > (): void;
12 > }
13 >
14 > // Avoid circular dependency on EventEmitter by implementing a subset of the interface.
15 > export class ErrorHandler {
16 > private unexpectedErrorHandler: (e: any) => void;
17 > private listeners: ErrorListenerCallback[];
18 >
19 > constructor() {
20 >
21 > this.listeners = [];
22 >
23 > this.unexpectedErrorHandler = function (e: any) {
24 setTimeout(() => {
25 if (e.stack) {
34 }, 0);
35 };
36 > } errors.ts
37 >
38 > addListener(listener: ErrorListenerCallback): ErrorListenerUnbind {
39 this.listeners.push(listener);
40
43 };
44 }
45 > errors.ts
46 > private emit(e: any): void {
47 this.listeners.forEach((listener) => {
48 listener(e);
49 });
50 }
51 > errors.ts
52 > private _removeListener(listener: ErrorListenerCallback): void {
53 this.listeners.splice(this.listeners.indexOf(listener), 1);
54 }
55 > errors.ts
56 > setUnexpectedErrorHandler(newUnexpectedErrorHandler: (e: any) => void): void {
57 > this.unexpectedErrorHandler = newUnexpectedErrorHandler;
58 > }
59 >
60 > getUnexpectedErrorHandler(): (e: any) => void {
61 return this.unexpectedErrorHandler;
62 }
63 > errors.ts
64 > onUnexpectedError(e: any): void {
65 this.unexpectedErrorHandler(e);
66 this.emit(e);
67 }
68 > errors.ts
69 > // For external errors, we don't want the listeners to be called
70 > onUnexpectedExternalError(e: any): void {
71 this.unexpectedErrorHandler(e);
72 }
73 > } errors.ts
74 >
75 > export const errorHandler = new ErrorHandler();
76 >
77 > /** @skipMangle */
78 > export function setUnexpectedErrorHandler(newUnexpectedErrorHandler: (e: any) => void): void {
79 > errorHandler.setUnexpectedErrorHandler(newUnexpectedErrorHandler);
80 > }
81 >
82 > /**
83 > * Returns if the error is a SIGPIPE error. SIGPIPE errors should generally be
84 > * logged at most once, to avoid a loop.
85 > *
86 > * @see https://github.com/microsoft/vscode-remote-release/issues/6481
87 > */
88 > export function isSigPipeError(e: unknown): e is Error {
89 if (!e || typeof e !== 'object') {
90 return false;
94 return cast.code === 'EPIPE' && cast.syscall?.toUpperCase() === 'WRITE';
95 }
96 > errors.ts
97 > /**
98 > * This function should only be called with errors that indicate a bug in the product.
99 > * E.g. buggy extensions/invalid user-input/network issues should not be able to trigger this code path.
100 > * If they are, this indicates there is also a bug in the product.
101 > */
102 > export function onBugIndicatingError(e: any): undefined {
103 errorHandler.onUnexpectedError(e);
104 return undefined;
105 }
106 > errors.ts
107 > export function onUnexpectedError(e: any): undefined {
108 // ignore errors from cancelled promises
109 if (!isCancellationError(e)) {
112 return undefined;
113 }
114 > errors.ts
115 > export function onUnexpectedExternalError(e: any): undefined {
116 // ignore errors from cancelled promises
117 if (!isCancellationError(e)) {
120 return undefined;
121 }
122 > errors.ts
123 > type ObjectWithCode = {
124 > readonly code: unknown;
125 > };
126 >
127 function hasErrorCode(error: object): error is ObjectWithCode {
128 return Object.hasOwn(error, 'code');
129 }
130 > errors.ts
131 > export function getErrorCode(error: unknown): string | undefined {
132 if (!error || typeof error !== 'object' || !hasErrorCode(error)) {
133 return undefined;
136 return typeof code === 'string' || typeof code === 'number' ? String(code) : undefined;
137 }
138 > errors.ts
139 > export interface SerializedError {
140 > readonly $isError: true;
141 > readonly name: string;
142 > readonly message: string;
143 > readonly stack: string;
144 > readonly noTelemetry: boolean;
145 > readonly code?: string;
146 > readonly cause?: SerializedError;
147 > }
148 >
149 > type ErrorWithCode = Error & {
150 > code: string | undefined;
151 > };
152 >
153 > export function transformErrorForSerialization(error: Error): SerializedError;
154 > export function transformErrorForSerialization(error: any): any;
155 > export function transformErrorForSerialization(error: any): any {
156 if (error instanceof Error) {
157 const { name, message, cause } = error;
172 return error;
173 }
174 > errors.ts
175 > export function transformErrorFromSerialization(data: SerializedError): Error {
176 let error: Error;
177 if (data.noTelemetry) {
191 return error;
192 }
193 > errors.ts
194 > // see https://github.com/v8/v8/wiki/Stack%20Trace%20API#basic-stack-traces
195 > export interface V8CallSite {
196 > getThis(): unknown;
197 > getTypeName(): string | null;
198 > getFunction(): Function | undefined;
199 > getFunctionName(): string | null;
200 > getMethodName(): string | null;
201 > getFileName(): string | null;
202 > getLineNumber(): number | null;
203 > getColumnNumber(): number | null;
204 > getEvalOrigin(): string | undefined;
205 > isToplevel(): boolean;
206 > isEval(): boolean;
207 > isNative(): boolean;
208 > isConstructor(): boolean;
209 > toString(): string;
210 > }
211 >
212 > export const canceledName = 'Canceled';
213 >
214 > /**
215 > * Checks if the given error is a promise in canceled state
216 > */
217 > export function isCancellationError(error: any): boolean {
218 if (error instanceof CancellationError) {
219 return true;
221 return error instanceof Error && error.name === canceledName && error.message === canceledName;
222 }
223 > errors.ts
224 > // !!!IMPORTANT!!!
225 > // Do NOT change this class because it is also used as an API-type.
226 > export class CancellationError extends Error {
227 > constructor() {
228 super(canceledName);
229 this.name = this.message;
230 }
231 > } errors.ts
232 >
233 > export class PendingMigrationError extends Error {
234 >
235 > private static readonly _name = 'PendingMigrationError';
236 >
237 > static is(error: unknown): error is PendingMigrationError {
238 return error instanceof PendingMigrationError || (error instanceof Error && error.name === PendingMigrationError._name);
239 }
240 > errors.ts
241 > constructor(message: string) {
242 super(message);
243 this.name = PendingMigrationError._name;
244 }
245 > } errors.ts
246 >
247 > /**
248 > * @deprecated use {@link CancellationError `new CancellationError()`} instead
249 > */
250 > export function canceled(): Error {
251 const error = new Error(canceledName);
252 error.name = error.message;
253 return error;
254 }
255 > errors.ts
256 > export function illegalArgument(name?: string): Error {
257 if (name) {
258 return new Error(`Illegal argument: ${name}`);
261 }
262 }
263 > errors.ts
264 > export function illegalState(name?: string): Error {
265 if (name) {
266 return new Error(`Illegal state: ${name}`);
269 }
270 }
271 > errors.ts
272 > export class ReadonlyError extends TypeError {
273 > constructor(name?: string) {
274 super(name ? `${name} is read-only and cannot be changed` : 'Cannot change read-only property');
275 }
276 > } errors.ts
277 >
278 > export function getErrorMessage(err: any): string {
279 if (!err) {
280 return 'Error';
291 return String(err);
292 }
293 > errors.ts
294 > export class NotImplementedError extends Error {
295 > constructor(message?: string) {
296 super('NotImplemented');
297 if (message) {
299 }
300 }
301 > } errors.ts
302 >
303 > export class NotSupportedError extends Error {
304 > constructor(message?: string) {
305 super('NotSupported');
306 if (message) {
308 }
309 }
310 > } errors.ts
311 >
312 > export class ExpectedError extends Error {
313 readonly isExpected = true;
314 > } errors.ts
315 >
316 > /**
317 > * Error that when thrown won't be logged in telemetry as an unhandled error.
318 > */
319 > export class ErrorNoTelemetry extends Error {
320 > override readonly name: string;
321 >
322 > constructor(msg?: string) {
323 super(msg);
324 this.name = 'CodeExpectedError';
325 }
326 > errors.ts
327 > public static fromError(err: Error): ErrorNoTelemetry {
328 if (err instanceof ErrorNoTelemetry) {
329 return err;
335 return result;
336 }
337 > errors.ts
338 > public static isErrorNoTelemetry(err: Error): err is ErrorNoTelemetry {
339 return err.name === 'CodeExpectedError';
340 }
341 > } errors.ts
342 >
343 > /**
344 > * This error indicates a bug.
345 > * Do not throw this for invalid user input.
346 > * Only catch this error to recover gracefully from bugs.
347 > */
348 > export class BugIndicatingError extends Error {
349 > constructor(message?: string) {
350 super(message || 'An unexpected bug occurred.');
351 Object.setPrototypeOf(this, BugIndicatingError.prototype);
src/vs/base/common/path.ts 177 covered LOC · 31 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- path.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 > // NOTE: VSCode's copy of nodejs path library to be usable in common (non-node) namespace
7 > // Copied from: https://github.com/nodejs/node/commits/v22.15.0/lib/path.js
8 > // Excluding: the change that adds primordials
9 > // (https://github.com/nodejs/node/commit/187a862d221dec42fa9a5c4214e7034d9092792f and others)
10 > // Excluding: the change that adds glob matching
11 > // (https://github.com/nodejs/node/commit/57b8b8e18e5e2007114c63b71bf0baedc01936a6)
12 >
13 > /**
14 > * Copyright Joyent, Inc. and other Node contributors.
15 > *
16 > * Permission is hereby granted, free of charge, to any person obtaining a
17 > * copy of this software and associated documentation files (the
18 > * "Software"), to deal in the Software without restriction, including
19 > * without limitation the rights to use, copy, modify, merge, publish,
20 > * distribute, sublicense, and/or sell copies of the Software, and to permit
21 > * persons to whom the Software is furnished to do so, subject to the
22 > * following conditions:
23 > *
24 > * The above copyright notice and this permission notice shall be included
25 > * in all copies or substantial portions of the Software.
26 > *
27 > * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
28 > * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 > * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
30 > * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
31 > * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
32 > * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
33 > * USE OR OTHER DEALINGS IN THE SOFTWARE.
34 > */
35 >
36 > import * as process from './process.js';
37 >
38 > const CHAR_UPPERCASE_A = 65;/* A */
39 > const CHAR_LOWERCASE_A = 97; /* a */
40 > const CHAR_UPPERCASE_Z = 90; /* Z */
41 > const CHAR_LOWERCASE_Z = 122; /* z */
42 > const CHAR_DOT = 46; /* . */
43 > const CHAR_FORWARD_SLASH = 47; /* / */
44 > const CHAR_BACKWARD_SLASH = 92; /* \ */
45 > const CHAR_COLON = 58; /* : */
46 > const CHAR_QUESTION_MARK = 63; /* ? */
47 >
48 > class ErrorInvalidArgType extends Error {
49 > code: 'ERR_INVALID_ARG_TYPE';
50 > constructor(name: string, expected: string, actual: unknown) {
51 // determiner: 'must be' or 'must not be'
52 let determiner;
66 this.code = 'ERR_INVALID_ARG_TYPE';
67 }
68 > } path.ts
69 >
70 function validateObject(pathObject: object, name: string) {
71 if (pathObject === null || typeof pathObject !== 'object') {
73 }
74 }
75 > path.ts
76 function validateString(value: string, name: string) {
77 if (typeof value !== 'string') {
79 }
80 }
81 > path.ts
82 > const platformIsWin32 = (process.platform === 'win32');
83 >
84 function isPathSeparator(code: number | undefined) {
85 return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
86 }
87 > path.ts
88 function isPosixPathSeparator(code: number | undefined) {
89 return code === CHAR_FORWARD_SLASH;
90 }
91 > path.ts
92 function isWindowsDeviceRoot(code: number) {
93 return (code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) ||
94 (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z);
95 }
96 > path.ts
97 > // Resolves . and .. elements in a path with directory names
98 function normalizeString(path: string, allowAboveRoot: boolean, separator: string, isPathSeparator: (code?: number) => boolean) {
99 let res = '';
163 return res;
164 }
165 > path.ts
166 function formatExt(ext: string): string {
167 return ext ? `${ext[0] === '.' ? '' : '.'}${ext}` : '';
168 }
169 > path.ts
170 function _format(sep: string, pathObject: ParsedPath) {
171 validateObject(pathObject, 'pathObject');
178 return dir === pathObject.root ? `${dir}${base}` : `${dir}${sep}${base}`;
179 }
180 > path.ts
181 > export interface ParsedPath {
182 > root: string;
183 > dir: string;
184 > base: string;
185 > ext: string;
186 > name: string;
187 > }
188 >
189 > export interface IPath {
190 > normalize(path: string): string;
191 > isAbsolute(path: string): boolean;
192 > join(...paths: string[]): string;
193 > resolve(...pathSegments: string[]): string;
194 > relative(from: string, to: string): string;
195 > dirname(path: string): string;
196 > basename(path: string, suffix?: string): string;
197 > extname(path: string): string;
198 > format(pathObject: ParsedPath): string;
199 > parse(path: string): ParsedPath;
200 > toNamespacedPath(path: string): string;
201 > sep: '\\' | '/';
202 > delimiter: string;
203 > win32: IPath | null;
204 > posix: IPath | null;
205 > }
206 >
207 > export const win32: IPath = {
208 > // path.resolve([from ...], to)
209 > resolve(...pathSegments: string[]): string {
210 let resolvedDevice = '';
211 let resolvedTail = '';
343 `${resolvedDevice}${resolvedTail}` || '.';
344 },
345 > path.ts
346 > normalize(path: string): string {
347 validateString(path, 'path');
348 const len = path.length;
450 return isAbsolute ? `${device}\\${tail}` : `${device}${tail}`;
451 },
452 > path.ts
453 > isAbsolute(path: string): boolean {
454 validateString(path, 'path');
455 const len = path.length;
466 isPathSeparator(path.charCodeAt(2)));
467 },
468 > path.ts
469 > join(...paths: string[]): string {
470 if (paths.length === 0) {
471 return '.';
536 return win32.normalize(joined);
537 },
538 > path.ts
539 >
540 > // It will solve the relative path from `from` to `to`, for instance:
541 > // from = 'C:\\orandea\\test\\aaa'
542 > // to = 'C:\\orandea\\impl\\bbb'
543 > // The output of the function should be: '..\\..\\impl\\bbb'
544 > relative(from: string, to: string): string {
545 validateString(from, 'from');
546 validateString(to, 'to');
699 return toOrig.slice(toStart, toEnd);
700 },
701 > path.ts
702 > toNamespacedPath(path: string): string {
703 // Note: this will *probably* throw somewhere.
704 if (typeof path !== 'string' || path.length === 0) {
730 return resolvedPath;
731 },
732 > path.ts
733 > dirname(path: string): string {
734 validateString(path, 'path');
735 const len = path.length;
818 return path.slice(0, end);
819 },
820 > path.ts
821 > basename(path: string, suffix?: string): string {
822 if (suffix !== undefined) {
823 validateString(suffix, 'suffix');
906 return path.slice(start, end);
907 },
908 > path.ts
909 > extname(path: string): string {
910 validateString(path, 'path');
911 let start = 0;
972 return path.slice(startDot, end);
973 },
974 > path.ts
975 > format: _format.bind(null, '\\'),
976 >
977 > parse(path) {
978 validateString(path, 'path');
979
1126 return ret;
1127 },
1128 > path.ts
1129 > sep: '\\',
1130 > delimiter: ';',
1131 > win32: null,
1132 > posix: null
1133 > };
1134 >
1135 > const posixCwd = (() => {
1136 > if (platformIsWin32) {
1137 // Converts Windows' backslash path separators to POSIX forward slashes
1138 // and truncates any drive indicator
1143 };
1144 }
1145 > path.ts
1146 > // We're already on POSIX, no need for any transformations
1147 > return () => process.cwd();
1148 > })();
1149 >
1150 > export const posix: IPath = {
1151 > // path.resolve([from ...], to)
1152 > resolve(...pathSegments: string[]): string {
1153 let resolvedPath = '';
1154 let resolvedAbsolute = false;
1186 return resolvedPath.length > 0 ? resolvedPath : '.';
1187 },
1188 > path.ts
1189 > normalize(path: string): string {
1190 validateString(path, 'path');
1191
1213 return isAbsolute ? `/${path}` : path;
1214 },
1215 > path.ts
1216 > isAbsolute(path: string): boolean {
1217 validateString(path, 'path');
1218 return path.length > 0 && path.charCodeAt(0) === CHAR_FORWARD_SLASH;
1219 },
1220 > path.ts
1221 > join(...paths: string[]): string {
1222 if (paths.length === 0) {
1223 return '.';
1239 return posix.normalize(path.join('/'));
1240 },
1241 > path.ts
1242 > relative(from: string, to: string): string {
1243 validateString(from, 'from');
1244 validateString(to, 'to');
1312 return `${out}${to.slice(toStart + lastCommonSep)}`;
1313 },
1314 > path.ts
1315 > toNamespacedPath(path: string): string {
1316 // Non-op on posix systems
1317 return path;
1318 },
1319 > path.ts
1320 > dirname(path: string): string {
1321 validateString(path, 'path');
1322 if (path.length === 0) {
1346 return path.slice(0, end);
1347 },
1348 > path.ts
1349 > basename(path: string, suffix?: string): string {
1350 if (suffix !== undefined) {
1351 validateString(suffix, 'suffix');
1426 return path.slice(start, end);
1427 },
1428 > path.ts
1429 > extname(path: string): string {
1430 validateString(path, 'path');
1431 let startDot = -1;
1480 return path.slice(startDot, end);
1481 },
1482 > path.ts
1483 > format: _format.bind(null, '/'),
1484 >
1485 > parse(path: string): ParsedPath {
1486 validateString(path, 'path');
1487
1565 return ret;
1566 },
1567 > path.ts
1568 > sep: '/',
1569 > delimiter: ':',
1570 > win32: null,
1571 > posix: null
1572 > };
1573 >
1574 > posix.win32 = win32.win32 = win32;
1575 > posix.posix = win32.posix = posix;
1576 >
1577 > export const normalize = (platformIsWin32 ? win32.normalize : posix.normalize);
1578 > export const isAbsolute = (platformIsWin32 ? win32.isAbsolute : posix.isAbsolute);
1579 > export const join = (platformIsWin32 ? win32.join : posix.join);
1580 > export const resolve = (platformIsWin32 ? win32.resolve : posix.resolve);
1581 > export const relative = (platformIsWin32 ? win32.relative : posix.relative);
1582 > export const dirname = (platformIsWin32 ? win32.dirname : posix.dirname);
1583 > export const basename = (platformIsWin32 ? win32.basename : posix.basename);
1584 > export const extname = (platformIsWin32 ? win32.extname : posix.extname);
1585 > export const format = (platformIsWin32 ? win32.format : posix.format);
1586 > export const parse = (platformIsWin32 ? win32.parse : posix.parse);
1587 > export const toNamespacedPath = (platformIsWin32 ? win32.toNamespacedPath : posix.toNamespacedPath);
1588 > export const sep = (platformIsWin32 ? win32.sep : posix.sep);
1589 > export const delimiter = (platformIsWin32 ? win32.delimiter : posix.delimiter);
src/vs/editor/common/modelLineProjectionData.ts 152 covered LOC · 26 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- modelLineProjectionData.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 { assertNever } from '../../base/common/assert.js';
7 > import { WrappingIndent } from './config/editorOptions.js';
8 > import { FontInfo } from './config/fontInfo.js';
9 > import { Position } from './core/position.js';
10 > import { InjectedTextCursorStops, InjectedTextOptions, PositionAffinity } from './model.js';
11 > import { LineInjectedText } from './textModelEvents.js';
12 >
13 > /**
14 > * *input*:
15 > * ```
16 > * xxxxxxxxxxxxxxxxxxxxxxxxxxx
17 > * ```
18 > *
19 > * -> Applying injections `[i...i]`, *inputWithInjections*:
20 > * ```
21 > * xxxxxx[iiiiiiiiii]xxxxxxxxxxxxxxxxx[ii]xxxx
22 > * ```
23 > *
24 > * -> breaking at offsets `|` in `xxxxxx[iiiiiii|iii]xxxxxxxxxxx|xxxxxx[ii]xxxx|`:
25 > * ```
26 > * xxxxxx[iiiiiii
27 > * iii]xxxxxxxxxxx
28 > * xxxxxx[ii]xxxx
29 > * ```
30 > *
31 > * -> applying wrappedTextIndentLength, *output*:
32 > * ```
33 > * xxxxxx[iiiiiii
34 > * iii]xxxxxxxxxxx
35 > * xxxxxx[ii]xxxx
36 > * ```
37 > */
38 > export class ModelLineProjectionData {
39 > constructor(
40 > public injectionOffsets: number[] | null, modelLineProjectionData.ts
41 > /**
42 > * `injectionOptions.length` must equal `injectionOffsets.length`
43 > */
44 > public injectionOptions: InjectedTextOptions[] | null,
45 > /**
46 > * Refers to offsets after applying injections to the source.
47 > * The last break offset indicates the length of the source after applying injections.
48 > */
49 > public breakOffsets: number[],
50 > /**
51 > * Refers to offsets after applying injections
52 > */
53 > public breakOffsetsVisibleColumn: number[],
54 > public wrappedTextIndentLength: number
55 > ) {
56 > }
58 > public getOutputLineCount(): number {
59 return this.breakOffsets.length;
60 }
62 > public getMinOutputOffset(outputLineIndex: number): number {
63 if (outputLineIndex > 0) {
64 return this.wrappedTextIndentLength;
66 return 0;
67 }
69 > public getLineLength(outputLineIndex: number): number {
70 // These offsets refer to model text with injected text.
71 const startOffset = outputLineIndex > 0 ? this.breakOffsets[outputLineIndex - 1] : 0;
78 return lineLength;
79 }
81 > public getMaxOutputOffset(outputLineIndex: number): number {
82 return this.getLineLength(outputLineIndex);
83 }
85 > public translateToInputOffset(outputLineIndex: number, outputOffset: number): number {
86 if (outputLineIndex > 0) {
87 outputOffset = Math.max(0, outputOffset - this.wrappedTextIndentLength);
108 return offsetInInput;
109 }
111 > public translateToOutputPosition(inputOffset: number, affinity: PositionAffinity = PositionAffinity.None): OutputPosition {
112 > let inputOffsetInInputWithInjection = inputOffset; modelLineProjectionData.ts
113 > if (this.injectionOffsets !== null) {
114 for (let i = 0; i < this.injectionOffsets.length; i++) {
115 if (inputOffset < this.injectionOffsets[i]) {
124 }
125 }
127 > return this.offsetInInputWithInjectionsToOutputPosition(inputOffsetInInputWithInjection, affinity);
128 > }
130 > private offsetInInputWithInjectionsToOutputPosition(offsetInInputWithInjections: number, affinity: PositionAffinity = PositionAffinity.None): OutputPosition {
131 > let low = 0; modelLineProjectionData.ts
132 > let high = this.breakOffsets.length - 1;
133 > let mid = 0;
134 > let midStart = 0;
135 >
136 > while (low <= high) {
137 > mid = low + ((high - low) / 2) | 0;
138 >
139 > const midStop = this.breakOffsets[mid];
140 > midStart = mid > 0 ? this.breakOffsets[mid - 1] : 0;
141 >
142 > if (affinity === PositionAffinity.Left) {
143 if (offsetInInputWithInjections <= midStart) {
144 high = mid - 1;
148 break;
149 }
151 > if (offsetInInputWithInjections < midStart) {
152 > high = mid - 1; modelLineProjectionData.ts
153 > } else if (offsetInInputWithInjections >= midStop) { modelLineProjectionData.ts
154 > low = mid + 1;
155 > } else {
156 > break;
157 > }
158 > }
159 > }
160 >
161 > let outputOffset = offsetInInputWithInjections - midStart;
162 > if (mid > 0) {
163 > outputOffset += this.wrappedTextIndentLength;
164 > }
165 >
166 > return new OutputPosition(mid, outputOffset);
167 > }
169 > public normalizeOutputPosition(outputLineIndex: number, outputOffset: number, affinity: PositionAffinity): OutputPosition {
170 if (this.injectionOffsets !== null) {
171 const offsetInInputWithInjections = this.outputPositionToOffsetInInputWithInjections(outputLineIndex, outputOffset);
191 return new OutputPosition(outputLineIndex, outputOffset);
192 }
194 > private outputPositionToOffsetInInputWithInjections(outputLineIndex: number, outputOffset: number): number {
195 if (outputLineIndex > 0) {
196 outputOffset = Math.max(0, outputOffset - this.wrappedTextIndentLength);
199 return result;
200 }
202 > private normalizeOffsetInInputWithInjectionsAroundInjections(offsetInInputWithInjections: number, affinity: PositionAffinity): number {
203 const injectedText = this.getInjectedTextAtOffset(offsetInInputWithInjections);
204 if (!injectedText) {
253 assertNever(affinity);
254 }
256 > public getInjectedText(outputLineIndex: number, outputOffset: number): InjectedText | null {
257 const offset = this.outputPositionToOffsetInInputWithInjections(outputLineIndex, outputOffset);
258 const injectedText = this.getInjectedTextAtOffset(offset);
264 };
265 }
267 > private getInjectedTextAtOffset(offsetInInputWithInjections: number): { injectedTextIndex: number; offsetInInputWithInjections: number; length: number } | undefined {
268 const injectionOffsets = this.injectionOffsets;
269 const injectionOptions = this.injectionOptions;
296 return undefined;
297 }
299 >
300 function hasRightCursorStop(cursorStop: InjectedTextCursorStops | null | undefined): boolean {
301 if (cursorStop === null || cursorStop === undefined) { return true; }
306 return cursorStop === InjectedTextCursorStops.Left || cursorStop === InjectedTextCursorStops.Both;
307 }
309 > export class InjectedText {
310 > constructor(public readonly options: InjectedTextOptions) { }
311 > }
312 >
313 > export class OutputPosition {
314 > outputLineIndex: number;
315 > outputOffset: number;
316 >
317 > constructor(outputLineIndex: number, outputOffset: number) {
318 > this.outputLineIndex = outputLineIndex; modelLineProjectionData.ts
319 > this.outputOffset = outputOffset;
320 > }
322 > toString(): string {
323 return `${this.outputLineIndex}:${this.outputOffset}`;
324 }
326 > toPosition(baseLineNumber: number): Position {
327 return new Position(baseLineNumber + this.outputLineIndex, this.outputOffset + 1);
328 }
330 >
331 > export interface ILineBreaksComputerContext {
332 > getLineContent(lineNumber: number): string;
333 > getLineInjectedText(lineNumber: number): LineInjectedText[] | null;
334 > }
335 >
336 > export interface ILineBreaksComputerFactory {
337 > createLineBreaksComputer(context: ILineBreaksComputerContext, fontInfo: FontInfo, tabSize: number, wrappingColumn: number, wrappingIndent: WrappingIndent, wordBreak: 'normal' | 'keepAll', wrapOnEscapedLineFeeds: boolean): ILineBreaksComputer;
338 > }
339 >
340 > export interface ILineBreaksComputer {
341 > /**
342 > * Pass in `previousLineBreakData` if the only difference is in breaking columns!!!
343 > */
344 > addRequest(lineNumber: number, previousLineBreakData: ModelLineProjectionData | null): void;
345 > finalize(): (ModelLineProjectionData | null)[];
346 > }
src/vs/editor/common/core/position.ts 113 covered LOC · 16 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- position.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 > /**
7 > * A position in the editor. This interface is suitable for serialization.
8 > */
9 > export interface IPosition {
10 > /**
11 > * line number (starts at 1)
12 > */
13 > readonly lineNumber: number;
14 > /**
15 > * column (the first character in a line is between column 1 and column 2)
16 > */
17 > readonly column: number;
18 > }
19 >
20 > /**
21 > * A position in the editor.
22 > */
23 > export class Position {
24 > /**
25 > * line number (starts at 1)
26 > */
27 > public readonly lineNumber: number;
28 > /**
29 > * column (the first character in a line is between column 1 and column 2)
30 > */
31 > public readonly column: number;
32 >
33 > constructor(lineNumber: number, column: number) {
34 this.lineNumber = lineNumber;
35 this.column = column;
36 }
38 > /**
39 > * Create a new position from this position.
40 > *
41 > * @param newLineNumber new line number
42 > * @param newColumn new column
43 > */
44 > with(newLineNumber: number = this.lineNumber, newColumn: number = this.column): Position {
45 if (newLineNumber === this.lineNumber && newColumn === this.column) {
46 return this;
49 }
50 }
52 > /**
53 > * Derive a new position from this position.
54 > *
55 > * @param deltaLineNumber line number delta
56 > * @param deltaColumn column delta
57 > */
58 > delta(deltaLineNumber: number = 0, deltaColumn: number = 0): Position {
59 return this.with(Math.max(1, this.lineNumber + deltaLineNumber), Math.max(1, this.column + deltaColumn));
60 }
62 > /**
63 > * Test if this position equals other position
64 > */
65 > public equals(other: IPosition): boolean {
66 return Position.equals(this, other);
67 }
69 > /**
70 > * Test if position `a` equals position `b`
71 > */
72 > public static equals(a: IPosition | null, b: IPosition | null): boolean {
73 if (!a && !b) {
74 return true;
81 );
82 }
84 > /**
85 > * Test if this position is before other position.
86 > * If the two positions are equal, the result will be false.
87 > */
88 > public isBefore(other: IPosition): boolean {
89 return Position.isBefore(this, other);
90 }
92 > /**
93 > * Test if position `a` is before position `b`.
94 > * If the two positions are equal, the result will be false.
95 > */
96 > public static isBefore(a: IPosition, b: IPosition): boolean {
97 if (a.lineNumber < b.lineNumber) {
98 return true;
103 return a.column < b.column;
104 }
105 > position.ts
106 > /**
107 > * Test if this position is before other position.
108 > * If the two positions are equal, the result will be true.
109 > */
110 > public isBeforeOrEqual(other: IPosition): boolean {
111 return Position.isBeforeOrEqual(this, other);
112 }
113 > position.ts
114 > /**
115 > * Test if position `a` is before position `b`.
116 > * If the two positions are equal, the result will be true.
117 > */
118 > public static isBeforeOrEqual(a: IPosition, b: IPosition): boolean {
119 if (a.lineNumber < b.lineNumber) {
120 return true;
125 return a.column <= b.column;
126 }
127 > position.ts
128 > /**
129 > * A function that compares positions, useful for sorting
130 > */
131 > public static compare(a: IPosition, b: IPosition): number {
132 const aLineNumber = a.lineNumber | 0;
133 const bLineNumber = b.lineNumber | 0;
141 return aLineNumber - bLineNumber;
142 }
143 > position.ts
144 > /**
145 > * Clone this position.
146 > */
147 > public clone(): Position {
148 return new Position(this.lineNumber, this.column);
149 }
150 > position.ts
151 > /**
152 > * Convert to a human-readable representation.
153 > */
154 > public toString(): string {
155 return '(' + this.lineNumber + ',' + this.column + ')';
156 }
157 > position.ts
158 > // ---
159 >
160 > /**
161 > * Create a `Position` from an `IPosition`.
162 > */
163 > public static lift(pos: IPosition): Position {
164 return new Position(pos.lineNumber, pos.column);
165 }
166 > position.ts
167 > /**
168 > * Test if `obj` is an `IPosition`.
169 > */
170 > public static isIPosition(obj: unknown): obj is IPosition {
171 return (
172 !!obj
175 );
176 }
177 > position.ts
178 > public toJSON(): IPosition {
179 return {
180 lineNumber: this.lineNumber,
src/vs/platform/instantiation/common/instantiation.ts 111 covered LOC · 5 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- instantiation.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 { DisposableStore } from '../../../base/common/lifecycle.js';
7 > import * as descriptors from './descriptors.js';
8 > import { ServiceCollection } from './serviceCollection.js';
9 >
10 > // ------ internal util
11 >
12 > export namespace _util {
13 >
14 > export const serviceIds = new Map<string, ServiceIdentifier<any>>();
15 >
16 > export const DI_TARGET = '$di$target';
17 > export const DI_DEPENDENCIES = '$di$dependencies';
18 >
19 > export function getServiceDependencies(ctor: DI_TARGET_OBJ): { id: ServiceIdentifier<any>; index: number }[] {
20 return ctor[DI_DEPENDENCIES] || [];
21 }
23 > export interface DI_TARGET_OBJ extends Function {
24 > [DI_TARGET]: Function;
25 > [DI_DEPENDENCIES]: { id: ServiceIdentifier<any>; index: number }[];
26 > }
27 > }
28 >
29 > // --- interfaces ------
30 >
31 > export type BrandedService = { _serviceBrand: undefined };
32 >
33 > export interface IConstructorSignature<T, Args extends any[] = []> {
34 > new <Services extends BrandedService[]>(...args: [...Args, ...Services]): T;
35 > }
36 >
37 > export interface ServicesAccessor {
38 > get<T>(id: ServiceIdentifier<T>): T;
39 > }
40 >
41 > export const IInstantiationService = createDecorator<IInstantiationService>('instantiationService');
42 >
43 > /**
44 > * Given a list of arguments as a tuple, attempt to extract the leading, non-service arguments
45 > * to their own tuple.
46 > */
47 > export type GetLeadingNonServiceArgs<TArgs extends any[]> =
48 > TArgs extends [] ? []
49 > : TArgs extends [...infer TFirst, BrandedService] ? GetLeadingNonServiceArgs<TFirst>
50 > : TArgs;
51 >
52 > export interface IInstantiationService {
53 >
54 > readonly _serviceBrand: undefined;
55 >
56 > /**
57 > * Synchronously creates an instance that is denoted by the descriptor
58 > */
59 > createInstance<T>(descriptor: descriptors.SyncDescriptor0<T>): T;
60 > createInstance<Ctor extends new (...args: any[]) => unknown, R extends InstanceType<Ctor>>(ctor: Ctor, ...args: GetLeadingNonServiceArgs<ConstructorParameters<Ctor>>): R;
61 >
62 > /**
63 > * Calls a function with a service accessor.
64 > */
65 > invokeFunction<R, TS extends any[] = []>(fn: (accessor: ServicesAccessor, ...args: TS) => R, ...args: TS): R;
66 >
67 > /**
68 > * Creates a child of this service which inherits all current services
69 > * and adds/overwrites the given services.
70 > *
71 > * NOTE that the returned child is `disposable` and should be disposed when not used
72 > * anymore. This will also dispose all the services that this service has created.
73 > */
74 > createChild(services: ServiceCollection, store?: DisposableStore): IInstantiationService;
75 >
76 > /**
77 > * Disposes this instantiation service.
78 > *
79 > * - Will dispose all services that this instantiation service has created.
80 > * - Will dispose all its children but not its parent.
81 > * - Will NOT dispose services-instances that this service has been created with
82 > * - Will NOT dispose consumer-instances this service has created
83 > */
84 > dispose(): void;
85 > }
86 >
87 >
88 > /**
89 > * Identifies a service of type `T`.
90 > */
91 > export interface ServiceIdentifier<T> {
92 > (...args: any[]): void;
93 > type: T;
94 > }
95 >
96 >
97 function storeServiceDependency(id: ServiceIdentifier<unknown>, target: Function, index: number): void {
98 if ((target as _util.DI_TARGET_OBJ)[_util.DI_TARGET] === target) {
103 }
104 }
106 > /**
107 > * The *only* valid way to create a {{ServiceIdentifier}}.
108 > */
109 > export function createDecorator<T>(serviceId: string): ServiceIdentifier<T> {
110 >
111 > if (_util.serviceIds.has(serviceId)) {
112 return _util.serviceIds.get(serviceId)!;
113 }
115 > const id = function (target: Function, key: string, index: number) {
116 if (arguments.length !== 3) {
117 throw new Error('@IServiceName-decorator can only be used to decorate a parameter');
119 storeServiceDependency(id, target, index);
120 } as ServiceIdentifier<T>;
122 > id.toString = () => serviceId;
123 >
124 > _util.serviceIds.set(serviceId, id);
125 > return id;
126 > }
127 >
128 > export function refineServiceDecorator<T1, T extends T1>(serviceIdentifier: ServiceIdentifier<T1>): ServiceIdentifier<T> {
129 return <ServiceIdentifier<T>>serviceIdentifier;
130 }
src/vs/base/common/arraysFind.ts 95 covered LOC · 16 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- arraysFind.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 { Comparator } from './arrays.js';
7 >
8 > export function findLast<T, R extends T>(array: readonly T[], predicate: (item: T, index: number) => item is R, fromIndex?: number): R | undefined;
9 > export function findLast<T>(array: readonly T[], predicate: (item: T, index: number) => unknown, fromIndex?: number): T | undefined;
10 > export function findLast<T>(array: readonly T[], predicate: (item: T, index: number) => unknown, fromIndex = array.length - 1): T | undefined {
11 const idx = findLastIdx(array, predicate, fromIndex);
12 if (idx === -1) {
15 return array[idx];
16 }
18 > export function findLastIdx<T>(array: readonly T[], predicate: (item: T, index: number) => unknown, fromIndex = array.length - 1): number {
19 for (let i = fromIndex; i >= 0; i--) {
20 const element = array[i];
27 return -1;
28 }
30 > export function findFirst<T, R extends T>(array: readonly T[], predicate: (item: T, index: number) => item is R, fromIndex?: number): R | undefined;
31 > export function findFirst<T>(array: readonly T[], predicate: (item: T, index: number) => unknown, fromIndex?: number): T | undefined;
32 > export function findFirst<T>(array: readonly T[], predicate: (item: T, index: number) => unknown, fromIndex = 0): T | undefined {
33 const idx = findFirstIdx(array, predicate, fromIndex);
34 if (idx === -1) {
37 return array[idx];
38 }
40 > export function findFirstIdx<T>(array: readonly T[], predicate: (item: T, index: number) => unknown, fromIndex = 0): number {
41 for (let i = fromIndex; i < array.length; i++) {
42 const element = array[i];
49 return -1;
50 }
52 > /**
53 > * Finds the last item where predicate is true using binary search.
54 > * `predicate` must be monotonous, i.e. `arr.map(predicate)` must be like `[true, ..., true, false, ..., false]`!
55 > *
56 > * @returns `undefined` if no item matches, otherwise the last item that matches the predicate.
57 > */
58 > export function findLastMonotonous<T>(array: readonly T[], predicate: (item: T) => boolean): T | undefined {
59 const idx = findLastIdxMonotonous(array, predicate);
60 return idx === -1 ? undefined : array[idx];
61 }
63 > /**
64 > * Finds the last item where predicate is true using binary search.
65 > * `predicate` must be monotonous, i.e. `arr.map(predicate)` must be like `[true, ..., true, false, ..., false]`!
66 > *
67 > * @returns `startIdx - 1` if predicate is false for all items, otherwise the index of the last item that matches the predicate.
68 > */
69 > export function findLastIdxMonotonous<T>(array: readonly T[], predicate: (item: T) => boolean, startIdx = 0, endIdxEx = array.length): number {
70 let i = startIdx;
71 let j = endIdxEx;
80 return i - 1;
81 }
83 > /**
84 > * Finds the first item where predicate is true using binary search.
85 > * `predicate` must be monotonous, i.e. `arr.map(predicate)` must be like `[false, ..., false, true, ..., true]`!
86 > *
87 > * @returns `undefined` if no item matches, otherwise the first item that matches the predicate.
88 > */
89 > export function findFirstMonotonous<T>(array: readonly T[], predicate: (item: T) => boolean): T | undefined {
90 const idx = findFirstIdxMonotonousOrArrLen(array, predicate);
91 return idx === array.length ? undefined : array[idx];
92 }
94 > /**
95 > * Finds the first item where predicate is true using binary search.
96 > * `predicate` must be monotonous, i.e. `arr.map(predicate)` must be like `[false, ..., false, true, ..., true]`!
97 > *
98 > * @returns `endIdxEx` if predicate is false for all items, otherwise the index of the first item that matches the predicate.
99 > */
100 > export function findFirstIdxMonotonousOrArrLen<T>(array: readonly T[], predicate: (item: T) => boolean, startIdx = 0, endIdxEx = array.length): number {
101 let i = startIdx;
102 let j = endIdxEx;
111 return i;
112 }
114 > export function findFirstIdxMonotonous<T>(array: readonly T[], predicate: (item: T) => boolean, startIdx = 0, endIdxEx = array.length): number {
115 const idx = findFirstIdxMonotonousOrArrLen(array, predicate, startIdx, endIdxEx);
116 return idx === array.length ? -1 : idx;
117 }
119 > /**
120 > * Use this when
121 > * * You have a sorted array
122 > * * You query this array with a monotonous predicate to find the last item that has a certain property.
123 > * * You query this array multiple times with monotonous predicates that get weaker and weaker.
124 > */
125 > export class MonotonousArray<T> {
126 > public static assertInvariants = false;
127 >
128 > private _findLastMonotonousLastIdx = 0;
129 > private _prevFindLastPredicate: ((item: T) => boolean) | undefined;
130 >
131 > constructor(private readonly _array: readonly T[]) {
132 }
134 > /**
135 > * The predicate must be monotonous, i.e. `arr.map(predicate)` must be like `[true, ..., true, false, ..., false]`!
136 > * For subsequent calls, current predicate must be weaker than (or equal to) the previous predicate, i.e. more entries must be `true`.
137 > */
138 > findLastMonotonous(predicate: (item: T) => boolean): T | undefined {
139 if (MonotonousArray.assertInvariants) {
140 if (this._prevFindLastPredicate) {
152 return idx === -1 ? undefined : this._array[idx];
153 }
154 > } arraysFind.ts
155 >
156 > /**
157 > * Returns the first item that is equal to or greater than every other item.
158 > */
159 > export function findFirstMax<T>(array: readonly T[], comparator: Comparator<T>): T | undefined {
160 if (array.length === 0) {
161 return undefined;
171 return max;
172 }
174 > /**
175 > * Returns the last item that is equal to or greater than every other item.
176 > */
177 > export function findLastMax<T>(array: readonly T[], comparator: Comparator<T>): T | undefined {
178 if (array.length === 0) {
179 return undefined;
189 return max;
190 }
192 > /**
193 > * Returns the first item that is equal to or less than every other item.
194 > */
195 > export function findFirstMin<T>(array: readonly T[], comparator: Comparator<T>): T | undefined {
196 return findFirstMax(array, (a, b) => -comparator(a, b));
197 }
199 > export function findMaxIdx<T>(array: readonly T[], comparator: Comparator<T>): number {
200 if (array.length === 0) {
201 return -1;
211 return maxIdx;
212 }
214 > /**
215 > * Returns the first mapped value of the array which is not undefined.
216 > */
217 > export function mapFindFirst<T, R>(items: Iterable<T>, mapFn: (value: T) => R | undefined): R | undefined {
218 for (const value of items) {
219 const mapped = mapFn(value);
src/vs/base/common/cancellation.ts 90 covered LOC · 18 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- cancellation.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 { Emitter, Event } from './event.js';
7 > import { DisposableStore, IDisposable } from './lifecycle.js';
8 >
9 > export interface CancellationToken {
10 >
11 > /**
12 > * A flag signalling is cancellation has been requested.
13 > */
14 > readonly isCancellationRequested: boolean;
15 >
16 > /**
17 > * An event which fires when cancellation is requested. This event
18 > * only ever fires `once` as cancellation can only happen once. Listeners
19 > * that are registered after cancellation will be called (next event loop run),
20 > * but also only once.
21 > *
22 > * @event
23 > */
24 > readonly onCancellationRequested: (listener: (e: void) => unknown, thisArgs?: unknown, disposables?: IDisposable[]) => IDisposable;
25 > }
26 >
27 > const shortcutEvent: Event<void> = Object.freeze(function (callback, context?): IDisposable {
28 const handle = setTimeout(callback.bind(context), 0);
29 return { dispose() { clearTimeout(handle); } };
30 });
32 > export namespace CancellationToken {
33 >
34 > export function isCancellationToken(thing: unknown): thing is CancellationToken {
35 if (thing === CancellationToken.None || thing === CancellationToken.Cancelled) {
36 return true;
45 && typeof (thing as CancellationToken).onCancellationRequested === 'function';
46 }
48 >
49 > export const None = Object.freeze<CancellationToken>({
50 > isCancellationRequested: false,
51 > onCancellationRequested: Event.None
52 > });
53 >
54 > export const Cancelled = Object.freeze<CancellationToken>({
55 > isCancellationRequested: true,
56 > onCancellationRequested: shortcutEvent
57 > });
58 > }
59 >
60 class MutableToken implements CancellationToken {
61
62 private _isCancelled: boolean = false;
63 private _emitter: Emitter<void> | null = null;
65 > public cancel() {
66 if (!this._isCancelled) {
67 this._isCancelled = true;
72 }
73 }
75 > get isCancellationRequested(): boolean {
76 return this._isCancelled;
77 }
79 > get onCancellationRequested(): Event<void> {
80 if (this._isCancelled) {
81 return shortcutEvent;
86 return this._emitter.event;
87 }
89 > public dispose(): void {
90 if (this._emitter) {
91 this._emitter.dispose();
93 }
94 }
96 >
97 > export class CancellationTokenSource {
98 >
99 > private _token?: CancellationToken = undefined;
100 > private _parentListener?: IDisposable = undefined;
101 >
102 > constructor(parent?: CancellationToken) {
103 this._parentListener = parent && parent.onCancellationRequested(this.cancel, this);
104 }
106 > get token(): CancellationToken {
107 if (!this._token) {
108 // be lazy and create the token only when
112 return this._token;
113 }
115 > cancel(): void {
116 if (!this._token) {
117 // save an object by returning the default
125 }
126 }
128 > dispose(cancel: boolean = false): void {
129 if (cancel) {
130 this.cancel();
140 }
141 }
142 > } cancellation.ts
143 >
144 > export function cancelOnDispose(store: DisposableStore): CancellationToken {
145 const source = new CancellationTokenSource();
146 store.add({ dispose() { source.cancel(); } });
147 return source.token;
148 }
150 > /**
151 > * A pool that aggregates multiple cancellation tokens. The pool's own token
152 > * (accessible via `pool.token`) is cancelled only after every token added
153 > * to the pool has been cancelled. Adding tokens after the pool token has
154 > * been cancelled has no effect.
155 > */
156 > export class CancellationTokenPool {
157
158 private readonly _source = new CancellationTokenSource();
162 private _cancelled: number = 0;
163 private _isDone: boolean = false;
165 > get token(): CancellationToken {
166 return this._source.token;
167 }
169 > /**
170 > * Add a token to the pool. If the token is already cancelled it is counted
171 > * immediately. Tokens added after the pool token has been cancelled are ignored.
172 > */
173 > add(token: CancellationToken): void {
174 if (this._isDone) {
175 return;
191 this._listeners.add(d);
192 }
194 > private _check(): void {
195 if (!this._isDone && this._total > 0 && this._total === this._cancelled) {
196 this._isDone = true;
src/vs/base/common/cache.ts 88 covered LOC · 9 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- cache.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 { CancellationToken, CancellationTokenSource } from './cancellation.js';
7 > import { IDisposable } from './lifecycle.js';
8 >
9 > export interface CacheResult<T> extends IDisposable {
10 > promise: Promise<T>;
11 > }
12 >
13 > export class Cache<T> {
14 >
15 > private result: CacheResult<T> | null = null;
16 > constructor(private task: (ct: CancellationToken) => Promise<T>) { }
17 >
18 > get(): CacheResult<T> {
19 if (this.result) {
20 return this.result;
35 return this.result;
36 }
37 > } cache.ts
38 >
39 > export function identity<T>(t: T): T {
40 return t;
41 }
42 > cache.ts
43 > interface ICacheOptions<TArg> {
44 > /**
45 > * The cache key is used to identify the cache entry.
46 > * Strict equality is used to compare cache keys.
47 > */
48 > getCacheKey: (arg: TArg) => unknown;
49 > }
50 >
51 > /**
52 > * Uses a LRU cache to make a given parametrized function cached.
53 > * Caches just the last key/value.
54 > */
55 > export class LRUCachedFunction<TArg, TComputed> {
56 > private lastCache: TComputed | undefined = undefined;
57 > private lastArgKey: unknown | undefined = undefined;
58 >
59 > private readonly _fn: (arg: TArg) => TComputed;
60 > private readonly _computeKey: (arg: TArg) => unknown;
61 >
62 > constructor(fn: (arg: TArg) => TComputed);
63 > constructor(options: ICacheOptions<TArg>, fn: (arg: TArg) => TComputed);
64 > constructor(arg1: ICacheOptions<TArg> | ((arg: TArg) => TComputed), arg2?: (arg: TArg) => TComputed) {
65 > if (typeof arg1 === 'function') {
66 > this._fn = arg1;
67 > this._computeKey = identity;
68 > } else {
69 this._fn = arg2!;
70 this._computeKey = arg1.getCacheKey;
71 }
72 > } cache.ts
73 >
74 > public get(arg: TArg): TComputed {
75 const key = this._computeKey(arg);
76 if (this.lastArgKey !== key) {
80 return this.lastCache!;
81 }
82 > } cache.ts
83 >
84 > /**
85 > * Uses an unbounded cache to memoize the results of the given function.
86 > */
87 > export class CachedFunction<TArg, TComputed> {
88 > private readonly _map = new Map<TArg, TComputed>();
89 > private readonly _map2 = new Map<unknown, TComputed>();
90 > public get cachedValues(): ReadonlyMap<TArg, TComputed> {
91 > return this._map;
92 > }
93 >
94 > private readonly _fn: (arg: TArg) => TComputed;
95 > private readonly _computeKey: (arg: TArg) => unknown;
96 >
97 > constructor(fn: (arg: TArg) => TComputed);
98 > constructor(options: ICacheOptions<TArg>, fn: (arg: TArg) => TComputed);
99 > constructor(arg1: ICacheOptions<TArg> | ((arg: TArg) => TComputed), arg2?: (arg: TArg) => TComputed) {
100 if (typeof arg1 === 'function') {
101 this._fn = arg1;
106 }
107 }
108 > cache.ts
109 > public get(arg: TArg): TComputed {
110 const key = this._computeKey(arg);
111 if (this._map2.has(key)) {
118 return value;
119 }
120 > } cache.ts
121 >
122 > /**
123 > * Uses an unbounded cache to memoize the results of the given function.
124 > */
125 > export class WeakCachedFunction<TArg, TComputed> {
126 > private readonly _map = new WeakMap<WeakKey, TComputed>();
127 >
128 > private readonly _fn: (arg: TArg) => TComputed;
129 > private readonly _computeKey: (arg: TArg) => unknown;
130 >
131 > constructor(fn: (arg: TArg) => TComputed);
132 > constructor(options: ICacheOptions<TArg>, fn: (arg: TArg) => TComputed);
133 > constructor(arg1: ICacheOptions<TArg> | ((arg: TArg) => TComputed), arg2?: (arg: TArg) => TComputed) {
134 if (typeof arg1 === 'function') {
135 this._fn = arg1;
140 }
141 }
142 > cache.ts
143 > public get(arg: TArg): TComputed {
144 const key = this._computeKey(arg) as WeakKey;
145 if (this._map.has(key)) {
151 return value;
152 }
153 > } cache.ts
src/vs/base/common/collections.ts 74 covered LOC · 18 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- collections.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 > /**
7 > * An interface for a JavaScript object that
8 > * acts a dictionary. The keys are strings.
9 > */
10 > export type IStringDictionary<V> = Record<string, V>;
11 >
12 > /**
13 > * An interface for a JavaScript object that
14 > * acts a dictionary. The keys are numbers.
15 > */
16 > export type INumberDictionary<V> = Record<number, V>;
17 >
18 > /**
19 > * Groups the collection into a dictionary based on the provided
20 > * group function.
21 > */
22 > export function groupBy<K extends string | number | symbol, V>(data: readonly V[], groupFn: (element: V) => K): Partial<Record<K, V[]>> {
23 const result: Partial<Record<K, V[]>> = Object.create(null);
24 for (const element of data) {
32 return result;
33 }
35 > export function groupByMap<K, V>(data: V[], groupFn: (element: V) => K): Map<K, V[]> {
36 const result = new Map<K, V[]>();
37 for (const element of data) {
46 return result;
47 }
49 > export function diffSets<T>(before: ReadonlySet<T>, after: ReadonlySet<T>): { removed: T[]; added: T[] } {
50 const removed: T[] = [];
51 const added: T[] = [];
62 return { removed, added };
63 }
65 > /**
66 > * Checks whether two sets contain exactly the same elements.
67 > *
68 > * @param a - The first set.
69 > * @param b - The second set.
70 > * @returns `true` if both sets have the same size and every element of `a` is also in `b`.
71 > */
72 > export function equalSets<T>(a: ReadonlySet<T>, b: ReadonlySet<T>): boolean {
73 if (a === b) {
74 return true;
84 return true;
85 }
87 > export function diffMaps<K, V>(before: Map<K, V>, after: Map<K, V>): { removed: V[]; added: V[] } {
88 const removed: V[] = [];
89 const added: V[] = [];
100 return { removed, added };
101 }
103 > /**
104 > * Computes the intersection of two sets.
105 > *
106 > * @param setA - The first set.
107 > * @param setB - The second iterable.
108 > * @returns A new set containing the elements that are in both `setA` and `setB`.
109 > */
110 > export function intersection<T>(setA: Set<T>, setB: Iterable<T>): Set<T> {
111 const result = new Set<T>();
112 for (const elem of setB) {
117 return result;
118 }
120 > export class SetWithKey<T> implements Set<T> {
121 > private _map = new Map<unknown, T>();
122 >
123 > constructor(values: T[], private toKey: (t: T) => unknown) {
124 for (const value of values) {
125 this.add(value);
126 }
127 }
129 > get size(): number {
130 return this._map.size;
131 }
133 > add(value: T): this {
134 const key = this.toKey(value);
135 this._map.set(key, value);
136 return this;
137 }
139 > delete(value: T): boolean {
140 return this._map.delete(this.toKey(value));
141 }
143 > has(value: T): boolean {
144 return this._map.has(this.toKey(value));
145 }
147 > *entries(): SetIterator<[T, T]> {
148 for (const entry of this._map.values()) {
149 yield [entry, entry];
150 }
151 }
153 > keys(): SetIterator<T> {
154 return this.values();
155 }
157 > *values(): SetIterator<T> {
158 for (const entry of this._map.values()) {
159 yield entry;
160 }
161 }
163 > clear(): void {
164 this._map.clear();
165 }
167 > forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: unknown): void {
168 this._map.forEach(entry => callbackfn.call(thisArg, entry, entry, this));
169 }
171 > [Symbol.iterator](): SetIterator<T> {
172 return this.values();
173 }
175 > [Symbol.toStringTag]: string = 'SetWithKey';
176 > }
src/vs/editor/common/core/wordHelper.ts 70 covered LOC · 5 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- wordHelper.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 { Iterable } from '../../../base/common/iterator.js';
7 > import { toDisposable } from '../../../base/common/lifecycle.js';
8 > import { LinkedList } from '../../../base/common/linkedList.js';
9 >
10 > export const USUAL_WORD_SEPARATORS = '`~!@#$%^&*()-=+[{]}\\|;:\'",.<>/?';
11 >
12 > /**
13 > * Word inside a model.
14 > */
15 > export interface IWordAtPosition {
16 > /**
17 > * The word.
18 > */
19 > readonly word: string;
20 > /**
21 > * The column where the word starts.
22 > */
23 > readonly startColumn: number;
24 > /**
25 > * The column where the word ends.
26 > */
27 > readonly endColumn: number;
28 > }
29 >
30 > /**
31 > * Create a word definition regular expression based on default word separators.
32 > * Optionally provide allowed separators that should be included in words.
33 > *
34 > * The default would look like this:
35 > * /(-?\d*\.\d\w*)|([^\`\~\!\@\#\$\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g
36 > */
37 > function createWordRegExp(allowInWords: string = ''): RegExp {
38 > let source = '(-?\\d*\\.\\d\\w*)|([^';
39 > for (const sep of USUAL_WORD_SEPARATORS) {
40 > if (allowInWords.indexOf(sep) >= 0) {
41 continue;
42 }
43 > source += '\\' + sep; wordHelper.ts
44 > }
45 > source += '\\s]+)';
46 > return new RegExp(source, 'g');
47 > }
48 >
49 > // catches numbers (including floating numbers) in the first group, and alphanum in the second
50 > export const DEFAULT_WORD_REGEXP = createWordRegExp();
51 >
52 > export function ensureValidWordDefinition(wordDefinition?: RegExp | null): RegExp {
53 let result: RegExp = DEFAULT_WORD_REGEXP;
54
75 return result;
76 }
78 >
79 > export interface IGetWordAtTextConfig {
80 > maxLen: number;
81 > windowSize: number;
82 > timeBudget: number;
83 > }
84 >
85 >
86 > const _defaultConfig = new LinkedList<IGetWordAtTextConfig>();
87 > _defaultConfig.unshift({
88 > maxLen: 1000,
89 > windowSize: 15,
90 > timeBudget: 150
91 > });
92 >
93 > export function setDefaultGetWordAtTextConfig(value: IGetWordAtTextConfig) {
94 const rm = _defaultConfig.unshift(value);
95 return toDisposable(rm);
96 }
98 > export function getWordAtText(column: number, wordDefinition: RegExp, text: string, textOffset: number, config?: IGetWordAtTextConfig): IWordAtPosition | null {
99 // Ensure the regex has the 'g' flag, otherwise this will loop forever
100 wordDefinition = ensureValidWordDefinition(wordDefinition);
161 return null;
162 }
164 function _findRegexMatchEnclosingPosition(wordDefinition: RegExp, text: string, pos: number, stopPos: number): RegExpExecArray | null {
165 let match: RegExpExecArray | null;
src/vs/editor/common/core/characterClassifier.ts 69 covered LOC · 15 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- characterClassifier.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 { toUint8 } from '../../../base/common/uint.js';
7 >
8 > /**
9 > * A fast character classifier that uses a compact array for ASCII values.
10 > */
11 > export class CharacterClassifier<T extends number> {
12 > /**
13 > * Maintain a compact (fully initialized ASCII map for quickly classifying ASCII characters - used more often in code).
14 > */
15 > protected readonly _asciiMap: Uint8Array;
16 >
17 > /**
18 > * The entire map (sparse array).
19 > */
20 > protected readonly _map: Map<number, number>;
21 >
22 > protected readonly _defaultValue: number;
23 >
24 > constructor(_defaultValue: T) {
25 > const defaultValue = toUint8(_defaultValue); characterClassifier.ts
26 >
27 > this._defaultValue = defaultValue;
28 > this._asciiMap = CharacterClassifier._createAsciiMap(defaultValue);
29 > this._map = new Map<number, number>();
30 > }
32 > private static _createAsciiMap(defaultValue: number): Uint8Array {
33 > const asciiMap = new Uint8Array(256); characterClassifier.ts
34 > asciiMap.fill(defaultValue);
35 > return asciiMap;
36 > }
38 > public set(charCode: number, _value: T): void {
39 > const value = toUint8(_value); characterClassifier.ts
40 >
41 > if (charCode >= 0 && charCode < 256) {
42 > this._asciiMap[charCode] = value;
43 > } else {
44 > this._map.set(charCode, value); characterClassifier.ts
45 > }
48 > public get(charCode: number): T {
49 if (charCode >= 0 && charCode < 256) {
50 return <T>this._asciiMap[charCode];
53 }
54 }
56 > public clear() {
57 this._asciiMap.fill(this._defaultValue);
58 this._map.clear();
59 }
61 >
62 > const enum Boolean {
63 > False = 0,
64 > True = 1
65 > }
66 >
67 > export class CharacterSet {
68 >
69 > private readonly _actual: CharacterClassifier<Boolean>;
70 >
71 > constructor() {
72 this._actual = new CharacterClassifier<Boolean>(Boolean.False);
73 }
75 > public add(charCode: number): void {
76 this._actual.set(charCode, Boolean.True);
77 }
79 > public has(charCode: number): boolean {
80 return (this._actual.get(charCode) === Boolean.True);
81 }
83 > public clear(): void {
84 return this._actual.clear();
85 }
src/vs/base/common/objects.ts 65 covered LOC · 13 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- objects.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 { isTypedArray, isObject, isUndefinedOrNull } from './types.js';
7 >
8 > export function deepClone<T>(obj: T): T {
9 if (!obj || typeof obj !== 'object') {
10 return obj;
19 return result;
20 }
21 > objects.ts
22 > export function deepFreeze<T>(obj: T): T {
23 if (!obj || typeof obj !== 'object') {
24 return obj;
39 return obj;
40 }
41 > objects.ts
42 > const _hasOwnProperty = Object.prototype.hasOwnProperty;
43 >
44 >
45 > export function cloneAndChange(obj: any, changer: (orig: any) => any): any {
46 return _cloneAndChange(obj, changer, new Set());
47 }
48 > objects.ts
49 function _cloneAndChange(obj: any, changer: (orig: any) => any, seen: Set<any>): any {
50 if (isUndefinedOrNull(obj)) {
82 return obj;
83 }
84 > objects.ts
85 > /**
86 > * Copies all properties of source into destination. The optional parameter "overwrite" allows to control
87 > * if existing properties on the destination should be overwritten or not. Defaults to true (overwrite).
88 > */
89 > export function mixin(destination: any, source: any, overwrite: boolean = true): any {
90 if (!isObject(destination)) {
91 return source;
109 return destination;
110 }
111 > objects.ts
112 > export function equals(one: any, other: any): boolean {
113 if (one === other) {
114 return true;
162 return true;
163 }
164 > objects.ts
165 > /**
166 > * Calls `JSON.Stringify` with a replacer to break apart any circular references.
167 > * This prevents `JSON`.stringify` from throwing the exception
168 > * "Uncaught TypeError: Converting circular structure to JSON"
169 > */
170 > export function safeStringify(obj: any): string {
171 const seen = new Set<any>();
172 return JSON.stringify(obj, (key, value) => {
184 });
185 }
186 > objects.ts
187 > /**
188 > * Like `JSON.stringify`, but with deterministic ordering of object keys so that
189 > * structurally equal inputs always produce the same string. Useful for cache
190 > * keys derived from arbitrary object payloads.
191 > *
192 > * - Object keys are sorted at every level of nesting.
193 > * - Properties whose value is `undefined` are omitted (matching `JSON.stringify`).
194 > * - Circular references are replaced with the string `"[Circular]"` to avoid
195 > * throwing.
196 > * - A top-level `undefined` returns the string `'undefined'`; any other
197 > * stringification failure returns the empty string.
198 > */
199 > export function stableStringify(value: unknown): string {
200 if (value === undefined) {
201 return 'undefined';
207 }
208 }
209 > objects.ts
210 function _stableStringify(value: unknown, seen: WeakSet<object>): string {
211 if (value === null || typeof value !== 'object') {
230 return '{' + parts.join(',') + '}';
231 }
232 > objects.ts
233 > type obj = { [key: string]: any };
234 > /**
235 > * Returns an object that has keys for each value that is different in the base object. Keys
236 > * that do not exist in the target but in the base object are not considered.
237 > *
238 > * Note: This is not a deep-diffing method, so the values are strictly taken into the resulting
239 > * object if they differ.
240 > *
241 > * @param base the object to diff against
242 > * @param obj the object to use for diffing
243 > */
244 > export function distinct(base: obj, target: obj): obj {
245 const result = Object.create(null);
246
261 return result;
262 }
263 > objects.ts
264 > export function getCaseInsensitive(target: obj, key: string): unknown {
265 const lowercaseKey = key.toLowerCase();
266 const equivalentKey = Object.keys(target).find(k => k.toLowerCase() === lowercaseKey);
267 return equivalentKey ? target[equivalentKey] : target[key];
268 }
269 > objects.ts
270 > export function filter(obj: obj, predicate: (key: string, value: any) => boolean): obj {
271 const result = Object.create(null);
272 for (const [key, value] of Object.entries(obj)) {
277 return result;
278 }
279 > objects.ts
280 > export function mapValues<T extends {}, R>(obj: T, fn: (value: T[keyof T], key: string) => R): { [K in keyof T]: R } {
281 const result: { [key: string]: R } = {};
282 for (const [key, value] of Object.entries(obj)) {
src/vs/base/common/iterator.ts 63 covered LOC · 22 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- iterator.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 { isIterable } from './types.js';
7 >
8 > export namespace Iterable {
9 >
10 > export function is<T = unknown>(thing: unknown): thing is Iterable<T> {
11 return !!thing && typeof thing === 'object' && typeof (thing as Iterable<T>)[Symbol.iterator] === 'function';
12 }
14 > const _empty: Iterable<never> = Object.freeze([]);
15 > export function empty<T = never>(): readonly never[] {
16 return _empty as readonly never[];
17 }
19 > export function* single<T>(element: T): Iterable<T> {
20 yield element;
21 }
23 > export function wrap<T>(iterableOrElement: Iterable<T> | T): Iterable<T> {
24 if (is(iterableOrElement)) {
25 return iterableOrElement;
28 }
29 }
31 > export function from<T>(iterable: Iterable<T> | undefined | null): Iterable<T> {
32 return iterable ?? (_empty as Iterable<T>);
33 }
35 > export function* reverse<T>(array: ReadonlyArray<T>): Iterable<T> {
36 for (let i = array.length - 1; i >= 0; i--) {
37 yield array[i];
38 }
39 }
41 > export function isEmpty<T>(iterable: Iterable<T> | undefined | null): boolean {
42 return !iterable || iterable[Symbol.iterator]().next().done === true;
43 }
45 > export function first<T>(iterable: Iterable<T>): T | undefined {
46 return iterable[Symbol.iterator]().next().value;
47 }
49 > export function some<T>(iterable: Iterable<T>, predicate: (t: T, i: number) => unknown): boolean {
50 let i = 0;
51 for (const element of iterable) {
56 return false;
57 }
59 > export function every<T>(iterable: Iterable<T>, predicate: (t: T, i: number) => unknown): boolean {
60 let i = 0;
61 for (const element of iterable) {
66 return true;
67 }
69 > export function find<T, R extends T>(iterable: Iterable<T>, predicate: (t: T) => t is R): R | undefined;
70 > export function find<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): T | undefined;
71 > export function find<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): T | undefined {
72 for (const element of iterable) {
73 if (predicate(element)) {
78 return undefined;
79 }
81 > export function filter<T, R extends T>(iterable: Iterable<T>, predicate: (t: T) => t is R): Iterable<R>;
82 > export function filter<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): Iterable<T>;
83 > export function* filter<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): Iterable<T> {
84 for (const element of iterable) {
85 if (predicate(element)) {
88 }
89 }
91 > export function* map<T, R>(iterable: Iterable<T>, fn: (t: T, index: number) => R): Iterable<R> {
92 let index = 0;
93 for (const element of iterable) {
95 }
96 }
98 > export function* flatMap<T, R>(iterable: Iterable<T>, fn: (t: T, index: number) => Iterable<R>): Iterable<R> {
99 let index = 0;
100 for (const element of iterable) {
102 }
103 }
104 > iterator.ts
105 > export function* concat<T>(...iterables: (Iterable<T> | T)[]): Iterable<T> {
106 for (const item of iterables) {
107 if (isIterable(item)) {
112 }
113 }
114 > iterator.ts
115 > export function reduce<T, R>(iterable: Iterable<T>, reducer: (previousValue: R, currentValue: T) => R, initialValue: R): R {
116 let value = initialValue;
117 for (const element of iterable) {
120 return value;
121 }
122 > iterator.ts
123 > export function length<T>(iterable: Iterable<T>): number {
124 let count = 0;
125 for (const _ of iterable) {
128 return count;
129 }
130 > iterator.ts
131 > /**
132 > * Returns an iterable slice of the array, with the same semantics as `array.slice()`.
133 > */
134 > export function* slice<T>(arr: ReadonlyArray<T>, from: number, to = arr.length): Iterable<T> {
135 if (from < -arr.length) {
136 from = 0;
150 }
151 }
152 > iterator.ts
153 > /**
154 > * Consumes `atMost` elements from iterable and returns the consumed elements,
155 > * and an iterable for the rest of the elements.
156 > */
157 > export function consume<T>(iterable: Iterable<T>, atMost: number = Number.POSITIVE_INFINITY): [T[], Iterable<T>] {
158 const consumed: T[] = [];
159
176 return [consumed, { [Symbol.iterator]() { return iterator; } }];
177 }
178 > iterator.ts
179 > export async function asyncToArray<T>(iterable: AsyncIterable<T>): Promise<T[]> {
180 const result: T[] = [];
181 for await (const item of iterable) {
184 return result;
185 }
186 > iterator.ts
187 > export async function asyncToArrayFlat<T>(iterable: AsyncIterable<T[]>): Promise<T[]> {
188 let result: T[] = [];
189 for await (const item of iterable) {
src/vs/base/common/linkedList.ts 61 covered LOC · 18 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- linkedList.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 > class Node<E> {
7 >
8 > static readonly Undefined = new Node<unknown>(undefined);
9 >
10 > element: E;
11 > next: Node<E> | typeof Node.Undefined;
12 > prev: Node<E> | typeof Node.Undefined;
13 >
14 > constructor(element: E) {
15 > this.element = element;
16 > this.next = Node.Undefined;
17 > this.prev = Node.Undefined;
18 > }
19 > }
20 >
21 > export class LinkedList<E> {
23 > private _first: Node<E> | typeof Node.Undefined = Node.Undefined;
24 > private _last: Node<E> | typeof Node.Undefined = Node.Undefined;
25 > private _size: number = 0;
27 > get size(): number {
28 return this._size;
29 }
31 > isEmpty(): boolean {
32 return this._first === Node.Undefined;
33 }
35 > clear(): void {
36 let node = this._first;
37 while (node !== Node.Undefined) {
46 this._size = 0;
47 }
49 > unshift(element: E): () => void {
50 > return this._insert(element, false); linkedList.ts
51 > }
53 > push(element: E): () => void {
54 return this._insert(element, true);
55 }
57 > private _insert(element: E, atTheEnd: boolean): () => void {
58 > const newNode = new Node(element); linkedList.ts
59 > if (this._first === Node.Undefined) {
60 > this._first = newNode;
61 > this._last = newNode;
62 >
63 > } else if (atTheEnd) {
64 // push
65 const oldLast = this._last;
75 oldFirst.prev = newNode;
76 }
77 > this._size += 1; linkedList.ts
78 >
79 > let didRemove = false;
80 > return () => {
81 if (!didRemove) {
82 didRemove = true;
84 }
85 };
86 > } linkedList.ts
88 > shift(): E | undefined {
89 if (this._first === Node.Undefined) {
90 return undefined;
95 }
96 }
98 > pop(): E | undefined {
99 if (this._last === Node.Undefined) {
100 return undefined;
105 }
106 }
108 > peek(): E | undefined {
109 if (this._last === Node.Undefined) {
110 return undefined;
114 }
115 }
117 > private _remove(node: Node<E> | typeof Node.Undefined): void {
118 if (node.prev !== Node.Undefined && node.next !== Node.Undefined) {
119 // middle
141 this._size -= 1;
142 }
144 > *[Symbol.iterator](): Iterator<E> {
145 let node = this._first;
146 while (node !== Node.Undefined) {
src/vs/base/test/common/utils.ts 56 covered LOC · 13 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- utils.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 { DisposableStore, DisposableTracker, IDisposable, setDisposableTracker } from '../../common/lifecycle.js';
7 > import { join } from '../../common/path.js';
8 > import { isWindows } from '../../common/platform.js';
9 > import { URI } from '../../common/uri.js';
10 >
11 > export type ValueCallback<T = any> = (value: T | Promise<T>) => void;
12 >
13 > export function toResource(this: any, path: string): URI {
14 if (isWindows) {
15 return URI.file(join('C:\\', btoa(this.test.fullTitle()), path));
18 return URI.file(join('/', btoa(this.test.fullTitle()), path));
19 }
20 > utils.ts
21 > export function suiteRepeat(n: number, description: string, callback: (this: any) => void): void {
22 for (let i = 0; i < n; i++) {
23 suite(`${description} (iteration ${i})`, callback);
24 }
25 }
26 > utils.ts
27 > export function testRepeat(n: number, description: string, callback: (this: any) => any): void {
28 for (let i = 0; i < n; i++) {
29 test(`${description} (iteration ${i})`, callback);
30 }
31 }
32 > utils.ts
33 export async function assertThrowsAsync(block: () => any, message: string | Error = 'Missing expected exception'): Promise<void> {
34 try {
41 throw err;
42 }
43 > utils.ts
44 > /**
45 > * Use this function to ensure that all disposables are cleaned up at the end of each test in the current suite.
46 > *
47 > * Use `markAsSingleton` if disposable singletons are created lazily that are allowed to outlive the test.
48 > * Make sure that the singleton properly registers all child disposables so that they are excluded too.
49 > *
50 > * @returns A {@link DisposableStore} that can optionally be used to track disposables in the test.
51 > * This will be automatically disposed on test teardown.
52 > */
53 > export function ensureNoDisposablesAreLeakedInTestSuite(): Pick<DisposableStore, 'add'> {
54 > let tracker: DisposableTracker | undefined;
55 > let store: DisposableStore;
56 > setup(() => {
57 > store = new DisposableStore(); utils.ts
58 > tracker = new DisposableTracker();
59 > setDisposableTracker(tracker);
60 > }); utils.ts
61 >
62 > teardown(function (this: import('mocha').Context) {
63 > store.dispose(); utils.ts
64 > setDisposableTracker(null);
65 > if (this.currentTest?.state !== 'failed') {
66 > const result = tracker!.computeLeakingDisposables();
67 > if (result) {
68 console.error(result.details);
69 throw new Error(`There are ${result.leaks.length} undisposed disposables!${result.details}`);
70 }
71 > } utils.ts
72 > }); utils.ts
73 >
74 > // Wrap store as the suite function is called before it's initialized
75 > const testContext = {
76 > add<T extends IDisposable>(o: T): T {
77 return store.add(o);
78 }
79 > }; utils.ts
80 > return testContext;
81 > }
82 >
83 > export function throwIfDisposablesAreLeaked(body: () => void, logToConsole = true): void {
84 const tracker = new DisposableTracker();
85 setDisposableTracker(tracker);
88 computeLeakingDisposables(tracker, logToConsole);
89 }
90 > utils.ts
91 export async function throwIfDisposablesAreLeakedAsync(body: () => Promise<void>): Promise<void> {
92 const tracker = new DisposableTracker();
96 computeLeakingDisposables(tracker);
97 }
98 > utils.ts
99 function computeLeakingDisposables(tracker: DisposableTracker, logToConsole = true) {
100 const result = tracker.computeLeakingDisposables();
src/vs/base/common/process.ts 53 covered LOC · 3 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- process.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 { INodeProcess, isMacintosh, isWindows } from './platform.js';
7 >
8 > let safeProcess: Omit<INodeProcess, 'arch'> & { arch: string | undefined };
9 > declare const process: INodeProcess;
10 >
11 > // Native sandbox environment
12 > const vscodeGlobal = (globalThis as { vscode?: { process?: INodeProcess } }).vscode;
13 > if (typeof vscodeGlobal !== 'undefined' && typeof vscodeGlobal.process !== 'undefined') {
14 const sandboxProcess: INodeProcess = vscodeGlobal.process;
15 safeProcess = {
20 };
21 }
22 > process.ts
23 > // Native node.js environment
24 > else if (typeof process !== 'undefined' && typeof process?.versions?.node === 'string') {
25 > safeProcess = {
26 > get platform() { return process.platform; },
27 > get arch() { return process.arch; },
28 > get env() { return process.env; },
29 > cwd() { return process.env['VSCODE_CWD'] || process.cwd(); }
30 > };
31 }
32
44 };
45 }
46 > process.ts
47 > /**
48 > * Provides safe access to the `cwd` property in node.js, sandboxed or web
49 > * environments.
50 > *
51 > * Note: in web, this property is hardcoded to be `/`.
52 > *
53 > * @skipMangle
54 > */
55 > export const cwd = safeProcess.cwd;
56 >
57 > /**
58 > * Provides safe access to the `env` property in node.js, sandboxed or web
59 > * environments.
60 > *
61 > * Note: in web, this property is hardcoded to be `{}`.
62 > */
63 > export const env = safeProcess.env;
64 >
65 > /**
66 > * Provides safe access to the `platform` property in node.js, sandboxed or web
67 > * environments.
68 > */
69 > export const platform = safeProcess.platform;
70 >
71 > /**
72 > * Provides safe access to the `arch` method in node.js, sandboxed or web
73 > * environments.
74 > * Note: `arch` is `undefined` in web
75 > */
76 > export const arch = safeProcess.arch;
src/vs/platform/accessibility/common/accessibility.ts 49 covered LOC · 2 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- accessibility.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 { Event } from '../../../base/common/event.js';
7 > import { RawContextKey } from '../../contextkey/common/contextkey.js';
8 > import { createDecorator } from '../../instantiation/common/instantiation.js';
9 >
10 > export const IAccessibilityService = createDecorator<IAccessibilityService>('accessibilityService');
11 >
12 > export interface IAccessibilityService {
13 > readonly _serviceBrand: undefined;
14 >
15 > readonly onDidChangeScreenReaderOptimized: Event<void>;
16 > readonly onDidChangeReducedMotion: Event<void>;
17 > readonly onDidChangeReducedTransparency: Event<void>;
18 >
19 > alwaysUnderlineAccessKeys(): Promise<boolean>;
20 > isScreenReaderOptimized(): boolean;
21 > isMotionReduced(): boolean;
22 > isTransparencyReduced(): boolean;
23 > getAccessibilitySupport(): AccessibilitySupport;
24 > setAccessibilitySupport(accessibilitySupport: AccessibilitySupport): void;
25 > alert(message: string): void;
26 > status(message: string): void;
27 > }
28 >
29 > export const enum AccessibilitySupport {
30 > /**
31 > * This should be the browser case where it is not known if a screen reader is attached or no.
32 > */
33 > Unknown = 0,
34 >
35 > Disabled = 1,
36 >
37 > Enabled = 2
38 > }
39 >
40 > export const CONTEXT_ACCESSIBILITY_MODE_ENABLED = new RawContextKey<boolean>('accessibilityModeEnabled', false);
41 >
42 > export interface IAccessibilityInformation {
43 > label: string;
44 > role?: string;
45 > }
46 >
47 > export function isAccessibilityInformation(obj: unknown): obj is IAccessibilityInformation {
48 if (!obj || typeof obj !== 'object') {
49 return false;
54 && (typeof candidate.role === 'undefined' || typeof candidate.role === 'string');
55 }
57 > export const ACCESSIBLE_VIEW_SHOWN_STORAGE_PREFIX = 'ACCESSIBLE_VIEW_SHOWN_';
src/vs/base/common/assert.ts 48 covered LOC · 7 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- assert.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 { BugIndicatingError, onUnexpectedError } from './errors.js';
7 >
8 > /**
9 > * Throws an error with the provided message if the provided value does not evaluate to a true Javascript value.
10 > *
11 > * @deprecated Use `assert(...)` instead.
12 > * This method is usually used like this:
13 > * ```ts
14 > * import * as assert from 'vs/base/common/assert';
15 > * assert.ok(...);
16 > * ```
17 > *
18 > * However, `assert` in that example is a user chosen name.
19 > * There is no tooling for generating such an import statement.
20 > * Thus, the `assert(...)` function should be used instead.
21 > */
22 > export function ok(value?: unknown, message?: string) {
23 if (!value) {
24 throw new Error(message ? `Assertion failed (${message})` : 'Assertion Failed');
25 }
26 }
27 > assert.ts
28 > export function assertNever(value: never, message = 'Unreachable'): never {
29 throw new Error(message);
30 }
31 > assert.ts
32 > export function softAssertNever(value: never): void {
33 // no-op
34 }
35 > assert.ts
36 > /**
37 > * Asserts that a condition is `truthy`.
38 > *
39 > * @throws provided {@linkcode messageOrError} if the {@linkcode condition} is `falsy`.
40 > *
41 > * @param condition The condition to assert.
42 > * @param messageOrError An error message or error object to throw if condition is `falsy`.
43 > */
44 > export function assert(
45 condition: boolean,
46 messageOrError: string | Error = 'unexpected state',
55 }
56 }
57 > assert.ts
58 > /**
59 > * Like assert, but doesn't throw.
60 > */
61 > export function softAssert(condition: boolean, message = 'Soft Assertion Failed'): void {
62 if (!condition) {
63 onUnexpectedError(new BugIndicatingError(message));
64 }
65 }
66 > assert.ts
67 > /**
68 > * condition must be side-effect free!
69 > */
70 > export function assertFn(condition: () => boolean): void {
71 if (!condition()) {
72 // eslint-disable-next-line no-debugger
77 }
78 }
79 > assert.ts
80 > export function checkAdjacentItems<T>(items: readonly T[], predicate: (item1: T, item2: T) => boolean): boolean {
81 let i = 0;
82 while (i < items.length - 1) {
src/vs/base/common/uint.ts 47 covered LOC · 5 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- uint.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 const enum Constants {
7 > /**
8 > * MAX SMI (SMall Integer) as defined in v8.
9 > * one bit is lost for boxing/unboxing flag.
10 > * one bit is lost for sign flag.
11 > * See https://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/#tagged-values
12 > */
13 > MAX_SAFE_SMALL_INTEGER = 1 << 30,
14 >
15 > /**
16 > * MIN SMI (SMall Integer) as defined in v8.
17 > * one bit is lost for boxing/unboxing flag.
18 > * one bit is lost for sign flag.
19 > * See https://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/#tagged-values
20 > */
21 > MIN_SAFE_SMALL_INTEGER = -(1 << 30),
22 >
23 > /**
24 > * Max unsigned integer that fits on 8 bits.
25 > */
26 > MAX_UINT_8 = 255, // 2^8 - 1
27 >
28 > /**
29 > * Max unsigned integer that fits on 16 bits.
30 > */
31 > MAX_UINT_16 = 65535, // 2^16 - 1
32 >
33 > /**
34 > * Max unsigned integer that fits on 32 bits.
35 > */
36 > MAX_UINT_32 = 4294967295, // 2^32 - 1
37 >
38 > UNICODE_SUPPLEMENTARY_PLANE_BEGIN = 0x010000
39 > }
40 >
41 > export function toUint8(v: number): number {
42 > if (v < 0) { uint.ts
43 return 0;
44 }
45 > if (v > Constants.MAX_UINT_8) { uint.ts
46 return Constants.MAX_UINT_8;
47 }
48 > return v | 0; uint.ts
49 > }
50 > uint.ts
51 > export function toUint32(v: number): number {
52 if (v < 0) {
53 return 0;
src/vs/base/common/lazy.ts 39 covered LOC · 4 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- lazy.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 > enum LazyValueState {
7 > Uninitialized,
8 > Running,
9 > Completed,
10 > }
11 >
12 > export class Lazy<T> {
13 >
14 > private _state = LazyValueState.Uninitialized;
15 > private _value?: T;
16 > private _error: Error | undefined;
17 >
18 > constructor(
19 > private readonly executor: () => T, lazy.ts
20 > ) { }
21 > lazy.ts
22 > /**
23 > * True if the lazy value has been resolved.
24 > */
25 > get hasValue(): boolean { return this._state === LazyValueState.Completed; }
26 >
27 > /**
28 > * Get the wrapped value.
29 > *
30 > * This will force evaluation of the lazy value if it has not been resolved yet. Lazy values are only
31 > * resolved once. `getValue` will re-throw exceptions that are hit while resolving the value
32 > */
33 > get value(): T {
34 if (this._state === LazyValueState.Uninitialized) {
35 this._state = LazyValueState.Running;
50 return this._value!;
51 }
52 > lazy.ts
53 > /**
54 > * Get the wrapped value without forcing evaluation.
55 > */
56 > get rawValue(): T | undefined { return this._value; }
57 > }
src/vs/base/common/marshallingIds.ts 33 covered LOC · 1 range

Open complete file

1 > /*--------------------------------------------------------------------------------------------- marshallingIds.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 const enum MarshalledId {
7 > Uri = 1,
8 > Regexp,
9 > ScmResource,
10 > ScmResourceGroup,
11 > ScmProvider,
12 > CommentController,
13 > CommentThread,
14 > CommentThreadInstance,
15 > CommentThreadReply,
16 > CommentNode,
17 > CommentThreadNode,
18 > TimelineActionContext,
19 > NotebookCellActionContext,
20 > NotebookActionContext,
21 > TerminalContext,
22 > TestItemContext,
23 > Date,
24 > TestMessageMenuArgs,
25 > ChatViewContext,
26 > LanguageModelToolResult,
27 > LanguageModelTextPart,
28 > LanguageModelThinkingPart,
29 > LanguageModelPromptTsxPart,
30 > LanguageModelDataPart,
31 > AgentSessionContext,
32 > ChatResponsePullRequestPart,
33 > }
src/vs/base/common/stopwatch.ts 25 covered LOC · 6 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- stopwatch.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 > declare const globalThis: { performance: { now(): number } };
7 > const performanceNow = globalThis.performance.now.bind(globalThis.performance);
8 >
9 > export class StopWatch {
10 >
11 > private _startTime: number;
12 > private _stopTime: number;
13 >
14 > private readonly _now: () => number;
15 >
16 > public static create(highResolution?: boolean): StopWatch {
17 return new StopWatch(highResolution);
18 }
20 > constructor(highResolution?: boolean) {
21 this._now = highResolution === false ? Date.now : performanceNow;
22 this._startTime = this._now();
23 this._stopTime = -1;
24 }
26 > public stop(): void {
27 this._stopTime = this._now();
28 }
30 > public reset(): void {
31 this._startTime = this._now();
32 this._stopTime = -1;
33 }
35 > public elapsed(): number {
36 if (this._stopTime !== -1) {
37 return this._stopTime - this._startTime;
39 return this._now() - this._startTime;
40 }
41 > } stopwatch.ts
src/vs/editor/common/config/editorZoom.ts 24 covered LOC · 3 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- editorZoom.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 { Emitter, Event } from '../../../base/common/event.js';
7 >
8 > export interface IEditorZoom {
9 > readonly onDidChangeZoomLevel: Event<number>;
10 > getZoomLevel(): number;
11 > setZoomLevel(zoomLevel: number): void;
12 > }
13 >
14 > export const EditorZoom: IEditorZoom = new class implements IEditorZoom {
15 >
16 > private _zoomLevel: number = 0;
17 >
18 > private readonly _onDidChangeZoomLevel = new Emitter<number>();
19 > public readonly onDidChangeZoomLevel: Event<number> = this._onDidChangeZoomLevel.event;
20 >
21 > public getZoomLevel(): number {
22 return this._zoomLevel;
23 }
25 > public setZoomLevel(zoomLevel: number): void {
26 zoomLevel = Math.min(Math.max(-5, zoomLevel), 20);
27 if (this._zoomLevel === zoomLevel) {
32 this._onDidChangeZoomLevel.fire(this._zoomLevel);
33 }
34 > }; editorZoom.ts
src/vs/editor/common/core/misc/textModelDefaults.ts 17 covered LOC · 1 range

Open complete file

1 > /*--------------------------------------------------------------------------------------------- textModelDefaults.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 const EDITOR_MODEL_DEFAULTS = {
7 > tabSize: 4,
8 > indentSize: 4,
9 > insertSpaces: true,
10 > detectIndentation: true,
11 > trimAutoWhitespace: true,
12 > largeFileOptimizations: true,
13 > bracketPairColorizationOptions: {
14 > enabled: true,
15 > independentColorPoolPerBracketType: false,
16 > },
17 > };
src/vs/base/common/functional.ts 9 covered LOC · 1 range

Open complete file

1 > /*--------------------------------------------------------------------------------------------- functional.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 > /**
7 > * Given a function, returns a function that is only calling that function once.
8 > */
9 > export function createSingleCallFunction<T extends Function>(this: unknown, fn: T, fnDidRunCallback?: () => void): T {
10 const _this = this;
11 let didCall = false;