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';