| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
- return c > 3 && r && Object.defineProperty(target, key, r), r;
- };
- var __param = (this && this.__param) || function (paramIndex, decorator) {
- return function (target, key) { decorator(target, key, paramIndex); }
- };
- import { ArrayQueue, pushMany } from '../../../base/common/arrays.js';
- import { Color } from '../../../base/common/color.js';
- import { onUnexpectedError } from '../../../base/common/errors.js';
- import { Emitter } from '../../../base/common/event.js';
- import { combinedDisposable, Disposable } from '../../../base/common/lifecycle.js';
- import * as strings from '../../../base/common/strings.js';
- import { URI } from '../../../base/common/uri.js';
- import { countEOL } from '../core/eolCounter.js';
- import { normalizeIndentation } from '../core/indentation.js';
- import { Position } from '../core/position.js';
- import { Range } from '../core/range.js';
- import { Selection } from '../core/selection.js';
- import { EDITOR_MODEL_DEFAULTS } from '../core/textModelDefaults.js';
- import { ILanguageService } from '../languages/language.js';
- import { ILanguageConfigurationService } from '../languages/languageConfigurationRegistry.js';
- import * as model from '../model.js';
- import { BracketPairsTextModelPart } from './bracketPairsTextModelPart/bracketPairsImpl.js';
- import { ColorizedBracketPairsDecorationProvider } from './bracketPairsTextModelPart/colorizedBracketPairsDecorationProvider.js';
- import { EditStack } from './editStack.js';
- import { GuidesTextModelPart } from './guidesTextModelPart.js';
- import { guessIndentation } from './indentationGuesser.js';
- import { IntervalNode, IntervalTree, recomputeMaxEnd } from './intervalTree.js';
- import { PieceTreeTextBuffer } from './pieceTreeTextBuffer/pieceTreeTextBuffer.js';
- import { PieceTreeTextBufferBuilder } from './pieceTreeTextBuffer/pieceTreeTextBufferBuilder.js';
- import { SearchParams, TextModelSearch } from './textModelSearch.js';
- import { TokenizationTextModelPart } from './tokenizationTextModelPart.js';
- import { InternalModelContentChangeEvent, LineInjectedText, ModelInjectedTextChangedEvent, ModelRawContentChangedEvent, ModelRawEOLChanged, ModelRawFlush, ModelRawLineChanged, ModelRawLinesDeleted, ModelRawLinesInserted } from '../textModelEvents.js';
- import { IUndoRedoService } from '../../../platform/undoRedo/common/undoRedo.js';
- export function createTextBufferFactory(text) {
- const builder = new PieceTreeTextBufferBuilder();
- builder.acceptChunk(text);
- return builder.finish();
- }
- export function createTextBufferFactoryFromSnapshot(snapshot) {
- const builder = new PieceTreeTextBufferBuilder();
- let chunk;
- while (typeof (chunk = snapshot.read()) === 'string') {
- builder.acceptChunk(chunk);
- }
- return builder.finish();
- }
- export function createTextBuffer(value, defaultEOL) {
- let factory;
- if (typeof value === 'string') {
- factory = createTextBufferFactory(value);
- }
- else if (model.isITextSnapshot(value)) {
- factory = createTextBufferFactoryFromSnapshot(value);
- }
- else {
- factory = value;
- }
- return factory.create(defaultEOL);
- }
- let MODEL_ID = 0;
- const LIMIT_FIND_COUNT = 999;
- export const LONG_LINE_BOUNDARY = 10000;
- class TextModelSnapshot {
- constructor(source) {
- this._source = source;
- this._eos = false;
- }
- read() {
- if (this._eos) {
- return null;
- }
- const result = [];
- let resultCnt = 0;
- let resultLength = 0;
- do {
- const tmp = this._source.read();
- if (tmp === null) {
- // end-of-stream
- this._eos = true;
- if (resultCnt === 0) {
- return null;
- }
- else {
- return result.join('');
- }
- }
- if (tmp.length > 0) {
- result[resultCnt++] = tmp;
- resultLength += tmp.length;
- }
- if (resultLength >= 64 * 1024) {
- return result.join('');
- }
- } while (true);
- }
- }
- const invalidFunc = () => { throw new Error(`Invalid change accessor`); };
- let TextModel = class TextModel extends Disposable {
- constructor(source, languageId, creationOptions, associatedResource = null, _undoRedoService, _languageService, _languageConfigurationService) {
- super();
- this._undoRedoService = _undoRedoService;
- this._languageService = _languageService;
- this._languageConfigurationService = _languageConfigurationService;
- //#region Events
- this._onWillDispose = this._register(new Emitter());
- this.onWillDispose = this._onWillDispose.event;
- this._onDidChangeDecorations = this._register(new DidChangeDecorationsEmitter(affectedInjectedTextLines => this.handleBeforeFireDecorationsChangedEvent(affectedInjectedTextLines)));
- this.onDidChangeDecorations = this._onDidChangeDecorations.event;
- this._onDidChangeOptions = this._register(new Emitter());
- this.onDidChangeOptions = this._onDidChangeOptions.event;
- this._onDidChangeAttached = this._register(new Emitter());
- this.onDidChangeAttached = this._onDidChangeAttached.event;
- this._onDidChangeInjectedText = this._register(new Emitter());
- this._eventEmitter = this._register(new DidChangeContentEmitter());
- this._deltaDecorationCallCnt = 0;
- // Generate a new unique model id
- MODEL_ID++;
- this.id = '$model' + MODEL_ID;
- this.isForSimpleWidget = creationOptions.isForSimpleWidget;
- if (typeof associatedResource === 'undefined' || associatedResource === null) {
- this._associatedResource = URI.parse('inmemory://model/' + MODEL_ID);
- }
- else {
- this._associatedResource = associatedResource;
- }
- this._attachedEditorCount = 0;
- const { textBuffer, disposable } = createTextBuffer(source, creationOptions.defaultEOL);
- this._buffer = textBuffer;
- this._bufferDisposable = disposable;
- this._options = TextModel.resolveOptions(this._buffer, creationOptions);
- this._bracketPairs = this._register(new BracketPairsTextModelPart(this, this._languageConfigurationService));
- this._guidesTextModelPart = this._register(new GuidesTextModelPart(this, this._languageConfigurationService));
- this._decorationProvider = this._register(new ColorizedBracketPairsDecorationProvider(this));
- this._tokenizationTextModelPart = new TokenizationTextModelPart(this._languageService, this._languageConfigurationService, this, this._bracketPairs, languageId);
- const bufferLineCount = this._buffer.getLineCount();
- const bufferTextLength = this._buffer.getValueLengthInRange(new Range(1, 1, bufferLineCount, this._buffer.getLineLength(bufferLineCount) + 1), 0 /* model.EndOfLinePreference.TextDefined */);
- // !!! Make a decision in the ctor and permanently respect this decision !!!
- // If a model is too large at construction time, it will never get tokenized,
- // under no circumstances.
- if (creationOptions.largeFileOptimizations) {
- this._isTooLargeForTokenization = ((bufferTextLength > TextModel.LARGE_FILE_SIZE_THRESHOLD)
- || (bufferLineCount > TextModel.LARGE_FILE_LINE_COUNT_THRESHOLD));
- }
- else {
- this._isTooLargeForTokenization = false;
- }
- this._isTooLargeForSyncing = (bufferTextLength > TextModel.MODEL_SYNC_LIMIT);
- this._versionId = 1;
- this._alternativeVersionId = 1;
- this._initialUndoRedoSnapshot = null;
- this._isDisposed = false;
- this.__isDisposing = false;
- this._instanceId = strings.singleLetterHash(MODEL_ID);
- this._lastDecorationId = 0;
- this._decorations = Object.create(null);
- this._decorationsTree = new DecorationsTrees();
- this._commandManager = new EditStack(this, this._undoRedoService);
- this._isUndoing = false;
- this._isRedoing = false;
- this._trimAutoWhitespaceLines = null;
- this._register(this._decorationProvider.onDidChange(() => {
- this._onDidChangeDecorations.beginDeferredEmit();
- this._onDidChangeDecorations.fire();
- this._onDidChangeDecorations.endDeferredEmit();
- }));
- }
- static resolveOptions(textBuffer, options) {
- if (options.detectIndentation) {
- const guessedIndentation = guessIndentation(textBuffer, options.tabSize, options.insertSpaces);
- return new model.TextModelResolvedOptions({
- tabSize: guessedIndentation.tabSize,
- indentSize: guessedIndentation.tabSize,
- insertSpaces: guessedIndentation.insertSpaces,
- trimAutoWhitespace: options.trimAutoWhitespace,
- defaultEOL: options.defaultEOL,
- bracketPairColorizationOptions: options.bracketPairColorizationOptions,
- });
- }
- return new model.TextModelResolvedOptions({
- tabSize: options.tabSize,
- indentSize: options.indentSize,
- insertSpaces: options.insertSpaces,
- trimAutoWhitespace: options.trimAutoWhitespace,
- defaultEOL: options.defaultEOL,
- bracketPairColorizationOptions: options.bracketPairColorizationOptions,
- });
- }
- get onDidChangeLanguage() { return this._tokenizationTextModelPart.onDidChangeLanguage; }
- get onDidChangeLanguageConfiguration() { return this._tokenizationTextModelPart.onDidChangeLanguageConfiguration; }
- get onDidChangeTokens() { return this._tokenizationTextModelPart.onDidChangeTokens; }
- onDidChangeContent(listener) {
- return this._eventEmitter.slowEvent((e) => listener(e.contentChangedEvent));
- }
- onDidChangeContentOrInjectedText(listener) {
- return combinedDisposable(this._eventEmitter.fastEvent(e => listener(e)), this._onDidChangeInjectedText.event(e => listener(e)));
- }
- _isDisposing() { return this.__isDisposing; }
- get tokenization() { return this._tokenizationTextModelPart; }
- get bracketPairs() { return this._bracketPairs; }
- get guides() { return this._guidesTextModelPart; }
- dispose() {
- this.__isDisposing = true;
- this._onWillDispose.fire();
- this._tokenizationTextModelPart.dispose();
- this._isDisposed = true;
- super.dispose();
- this._bufferDisposable.dispose();
- this.__isDisposing = false;
- // Manually release reference to previous text buffer to avoid large leaks
- // in case someone leaks a TextModel reference
- const emptyDisposedTextBuffer = new PieceTreeTextBuffer([], '', '\n', false, false, true, true);
- emptyDisposedTextBuffer.dispose();
- this._buffer = emptyDisposedTextBuffer;
- this._bufferDisposable = Disposable.None;
- }
- _assertNotDisposed() {
- if (this._isDisposed) {
- throw new Error('Model is disposed!');
- }
- }
- _emitContentChangedEvent(rawChange, change) {
- if (this.__isDisposing) {
- // Do not confuse listeners by emitting any event after disposing
- return;
- }
- this._tokenizationTextModelPart.handleDidChangeContent(change);
- this._bracketPairs.handleDidChangeContent(change);
- this._eventEmitter.fire(new InternalModelContentChangeEvent(rawChange, change));
- }
- setValue(value) {
- this._assertNotDisposed();
- if (value === null) {
- // There's nothing to do
- return;
- }
- const { textBuffer, disposable } = createTextBuffer(value, this._options.defaultEOL);
- this._setValueFromTextBuffer(textBuffer, disposable);
- }
- _createContentChanged2(range, rangeOffset, rangeLength, text, isUndoing, isRedoing, isFlush) {
- return {
- changes: [{
- range: range,
- rangeOffset: rangeOffset,
- rangeLength: rangeLength,
- text: text,
- }],
- eol: this._buffer.getEOL(),
- versionId: this.getVersionId(),
- isUndoing: isUndoing,
- isRedoing: isRedoing,
- isFlush: isFlush
- };
- }
- _setValueFromTextBuffer(textBuffer, textBufferDisposable) {
- this._assertNotDisposed();
- const oldFullModelRange = this.getFullModelRange();
- const oldModelValueLength = this.getValueLengthInRange(oldFullModelRange);
- const endLineNumber = this.getLineCount();
- const endColumn = this.getLineMaxColumn(endLineNumber);
- this._buffer = textBuffer;
- this._bufferDisposable.dispose();
- this._bufferDisposable = textBufferDisposable;
- this._increaseVersionId();
- // Flush all tokens
- this._tokenizationTextModelPart.flush();
- // Destroy all my decorations
- this._decorations = Object.create(null);
- this._decorationsTree = new DecorationsTrees();
- // Destroy my edit history and settings
- this._commandManager.clear();
- this._trimAutoWhitespaceLines = null;
- this._emitContentChangedEvent(new ModelRawContentChangedEvent([
- new ModelRawFlush()
- ], this._versionId, false, false), this._createContentChanged2(new Range(1, 1, endLineNumber, endColumn), 0, oldModelValueLength, this.getValue(), false, false, true));
- }
- setEOL(eol) {
- this._assertNotDisposed();
- const newEOL = (eol === 1 /* model.EndOfLineSequence.CRLF */ ? '\r\n' : '\n');
- if (this._buffer.getEOL() === newEOL) {
- // Nothing to do
- return;
- }
- const oldFullModelRange = this.getFullModelRange();
- const oldModelValueLength = this.getValueLengthInRange(oldFullModelRange);
- const endLineNumber = this.getLineCount();
- const endColumn = this.getLineMaxColumn(endLineNumber);
- this._onBeforeEOLChange();
- this._buffer.setEOL(newEOL);
- this._increaseVersionId();
- this._onAfterEOLChange();
- this._emitContentChangedEvent(new ModelRawContentChangedEvent([
- new ModelRawEOLChanged()
- ], this._versionId, false, false), this._createContentChanged2(new Range(1, 1, endLineNumber, endColumn), 0, oldModelValueLength, this.getValue(), false, false, false));
- }
- _onBeforeEOLChange() {
- // Ensure all decorations get their `range` set.
- this._decorationsTree.ensureAllNodesHaveRanges(this);
- }
- _onAfterEOLChange() {
- // Transform back `range` to offsets
- const versionId = this.getVersionId();
- const allDecorations = this._decorationsTree.collectNodesPostOrder();
- for (let i = 0, len = allDecorations.length; i < len; i++) {
- const node = allDecorations[i];
- const range = node.range; // the range is defined due to `_onBeforeEOLChange`
- const delta = node.cachedAbsoluteStart - node.start;
- const startOffset = this._buffer.getOffsetAt(range.startLineNumber, range.startColumn);
- const endOffset = this._buffer.getOffsetAt(range.endLineNumber, range.endColumn);
- node.cachedAbsoluteStart = startOffset;
- node.cachedAbsoluteEnd = endOffset;
- node.cachedVersionId = versionId;
- node.start = startOffset - delta;
- node.end = endOffset - delta;
- recomputeMaxEnd(node);
- }
- }
- onBeforeAttached() {
- this._attachedEditorCount++;
- if (this._attachedEditorCount === 1) {
- this._tokenizationTextModelPart.handleDidChangeAttached();
- this._onDidChangeAttached.fire(undefined);
- }
- }
- onBeforeDetached() {
- this._attachedEditorCount--;
- if (this._attachedEditorCount === 0) {
- this._tokenizationTextModelPart.handleDidChangeAttached();
- this._onDidChangeAttached.fire(undefined);
- }
- }
- isAttachedToEditor() {
- return this._attachedEditorCount > 0;
- }
- getAttachedEditorCount() {
- return this._attachedEditorCount;
- }
- isTooLargeForSyncing() {
- return this._isTooLargeForSyncing;
- }
- isTooLargeForTokenization() {
- return this._isTooLargeForTokenization;
- }
- isDisposed() {
- return this._isDisposed;
- }
- isDominatedByLongLines() {
- this._assertNotDisposed();
- if (this.isTooLargeForTokenization()) {
- // Cannot word wrap huge files anyways, so it doesn't really matter
- return false;
- }
- let smallLineCharCount = 0;
- let longLineCharCount = 0;
- const lineCount = this._buffer.getLineCount();
- for (let lineNumber = 1; lineNumber <= lineCount; lineNumber++) {
- const lineLength = this._buffer.getLineLength(lineNumber);
- if (lineLength >= LONG_LINE_BOUNDARY) {
- longLineCharCount += lineLength;
- }
- else {
- smallLineCharCount += lineLength;
- }
- }
- return (longLineCharCount > smallLineCharCount);
- }
- get uri() {
- return this._associatedResource;
- }
- //#region Options
- getOptions() {
- this._assertNotDisposed();
- return this._options;
- }
- getFormattingOptions() {
- return {
- tabSize: this._options.indentSize,
- insertSpaces: this._options.insertSpaces
- };
- }
- updateOptions(_newOpts) {
- this._assertNotDisposed();
- const tabSize = (typeof _newOpts.tabSize !== 'undefined') ? _newOpts.tabSize : this._options.tabSize;
- const indentSize = (typeof _newOpts.indentSize !== 'undefined') ? _newOpts.indentSize : this._options.indentSize;
- const insertSpaces = (typeof _newOpts.insertSpaces !== 'undefined') ? _newOpts.insertSpaces : this._options.insertSpaces;
- const trimAutoWhitespace = (typeof _newOpts.trimAutoWhitespace !== 'undefined') ? _newOpts.trimAutoWhitespace : this._options.trimAutoWhitespace;
- const bracketPairColorizationOptions = (typeof _newOpts.bracketColorizationOptions !== 'undefined') ? _newOpts.bracketColorizationOptions : this._options.bracketPairColorizationOptions;
- const newOpts = new model.TextModelResolvedOptions({
- tabSize: tabSize,
- indentSize: indentSize,
- insertSpaces: insertSpaces,
- defaultEOL: this._options.defaultEOL,
- trimAutoWhitespace: trimAutoWhitespace,
- bracketPairColorizationOptions,
- });
- if (this._options.equals(newOpts)) {
- return;
- }
- const e = this._options.createChangeEvent(newOpts);
- this._options = newOpts;
- this._bracketPairs.handleDidChangeOptions(e);
- this._decorationProvider.handleDidChangeOptions(e);
- this._onDidChangeOptions.fire(e);
- }
- detectIndentation(defaultInsertSpaces, defaultTabSize) {
- this._assertNotDisposed();
- const guessedIndentation = guessIndentation(this._buffer, defaultTabSize, defaultInsertSpaces);
- this.updateOptions({
- insertSpaces: guessedIndentation.insertSpaces,
- tabSize: guessedIndentation.tabSize,
- indentSize: guessedIndentation.tabSize, // TODO@Alex: guess indentSize independent of tabSize
- });
- }
- normalizeIndentation(str) {
- this._assertNotDisposed();
- return normalizeIndentation(str, this._options.indentSize, this._options.insertSpaces);
- }
- //#endregion
- //#region Reading
- getVersionId() {
- this._assertNotDisposed();
- return this._versionId;
- }
- mightContainRTL() {
- return this._buffer.mightContainRTL();
- }
- mightContainUnusualLineTerminators() {
- return this._buffer.mightContainUnusualLineTerminators();
- }
- removeUnusualLineTerminators(selections = null) {
- const matches = this.findMatches(strings.UNUSUAL_LINE_TERMINATORS.source, false, true, false, null, false, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */);
- this._buffer.resetMightContainUnusualLineTerminators();
- this.pushEditOperations(selections, matches.map(m => ({ range: m.range, text: null })), () => null);
- }
- mightContainNonBasicASCII() {
- return this._buffer.mightContainNonBasicASCII();
- }
- getAlternativeVersionId() {
- this._assertNotDisposed();
- return this._alternativeVersionId;
- }
- getInitialUndoRedoSnapshot() {
- this._assertNotDisposed();
- return this._initialUndoRedoSnapshot;
- }
- getOffsetAt(rawPosition) {
- this._assertNotDisposed();
- const position = this._validatePosition(rawPosition.lineNumber, rawPosition.column, 0 /* StringOffsetValidationType.Relaxed */);
- return this._buffer.getOffsetAt(position.lineNumber, position.column);
- }
- getPositionAt(rawOffset) {
- this._assertNotDisposed();
- const offset = (Math.min(this._buffer.getLength(), Math.max(0, rawOffset)));
- return this._buffer.getPositionAt(offset);
- }
- _increaseVersionId() {
- this._versionId = this._versionId + 1;
- this._alternativeVersionId = this._versionId;
- }
- _overwriteVersionId(versionId) {
- this._versionId = versionId;
- }
- _overwriteAlternativeVersionId(newAlternativeVersionId) {
- this._alternativeVersionId = newAlternativeVersionId;
- }
- _overwriteInitialUndoRedoSnapshot(newInitialUndoRedoSnapshot) {
- this._initialUndoRedoSnapshot = newInitialUndoRedoSnapshot;
- }
- getValue(eol, preserveBOM = false) {
- this._assertNotDisposed();
- const fullModelRange = this.getFullModelRange();
- const fullModelValue = this.getValueInRange(fullModelRange, eol);
- if (preserveBOM) {
- return this._buffer.getBOM() + fullModelValue;
- }
- return fullModelValue;
- }
- createSnapshot(preserveBOM = false) {
- return new TextModelSnapshot(this._buffer.createSnapshot(preserveBOM));
- }
- getValueLength(eol, preserveBOM = false) {
- this._assertNotDisposed();
- const fullModelRange = this.getFullModelRange();
- const fullModelValue = this.getValueLengthInRange(fullModelRange, eol);
- if (preserveBOM) {
- return this._buffer.getBOM().length + fullModelValue;
- }
- return fullModelValue;
- }
- getValueInRange(rawRange, eol = 0 /* model.EndOfLinePreference.TextDefined */) {
- this._assertNotDisposed();
- return this._buffer.getValueInRange(this.validateRange(rawRange), eol);
- }
- getValueLengthInRange(rawRange, eol = 0 /* model.EndOfLinePreference.TextDefined */) {
- this._assertNotDisposed();
- return this._buffer.getValueLengthInRange(this.validateRange(rawRange), eol);
- }
- getCharacterCountInRange(rawRange, eol = 0 /* model.EndOfLinePreference.TextDefined */) {
- this._assertNotDisposed();
- return this._buffer.getCharacterCountInRange(this.validateRange(rawRange), eol);
- }
- getLineCount() {
- this._assertNotDisposed();
- return this._buffer.getLineCount();
- }
- getLineContent(lineNumber) {
- this._assertNotDisposed();
- if (lineNumber < 1 || lineNumber > this.getLineCount()) {
- throw new Error('Illegal value for lineNumber');
- }
- return this._buffer.getLineContent(lineNumber);
- }
- getLineLength(lineNumber) {
- this._assertNotDisposed();
- if (lineNumber < 1 || lineNumber > this.getLineCount()) {
- throw new Error('Illegal value for lineNumber');
- }
- return this._buffer.getLineLength(lineNumber);
- }
- getLinesContent() {
- this._assertNotDisposed();
- return this._buffer.getLinesContent();
- }
- getEOL() {
- this._assertNotDisposed();
- return this._buffer.getEOL();
- }
- getEndOfLineSequence() {
- this._assertNotDisposed();
- return (this._buffer.getEOL() === '\n'
- ? 0 /* model.EndOfLineSequence.LF */
- : 1 /* model.EndOfLineSequence.CRLF */);
- }
- getLineMinColumn(lineNumber) {
- this._assertNotDisposed();
- return 1;
- }
- getLineMaxColumn(lineNumber) {
- this._assertNotDisposed();
- if (lineNumber < 1 || lineNumber > this.getLineCount()) {
- throw new Error('Illegal value for lineNumber');
- }
- return this._buffer.getLineLength(lineNumber) + 1;
- }
- getLineFirstNonWhitespaceColumn(lineNumber) {
- this._assertNotDisposed();
- if (lineNumber < 1 || lineNumber > this.getLineCount()) {
- throw new Error('Illegal value for lineNumber');
- }
- return this._buffer.getLineFirstNonWhitespaceColumn(lineNumber);
- }
- getLineLastNonWhitespaceColumn(lineNumber) {
- this._assertNotDisposed();
- if (lineNumber < 1 || lineNumber > this.getLineCount()) {
- throw new Error('Illegal value for lineNumber');
- }
- return this._buffer.getLineLastNonWhitespaceColumn(lineNumber);
- }
- /**
- * Validates `range` is within buffer bounds, but allows it to sit in between surrogate pairs, etc.
- * Will try to not allocate if possible.
- */
- _validateRangeRelaxedNoAllocations(range) {
- const linesCount = this._buffer.getLineCount();
- const initialStartLineNumber = range.startLineNumber;
- const initialStartColumn = range.startColumn;
- let startLineNumber = Math.floor((typeof initialStartLineNumber === 'number' && !isNaN(initialStartLineNumber)) ? initialStartLineNumber : 1);
- let startColumn = Math.floor((typeof initialStartColumn === 'number' && !isNaN(initialStartColumn)) ? initialStartColumn : 1);
- if (startLineNumber < 1) {
- startLineNumber = 1;
- startColumn = 1;
- }
- else if (startLineNumber > linesCount) {
- startLineNumber = linesCount;
- startColumn = this.getLineMaxColumn(startLineNumber);
- }
- else {
- if (startColumn <= 1) {
- startColumn = 1;
- }
- else {
- const maxColumn = this.getLineMaxColumn(startLineNumber);
- if (startColumn >= maxColumn) {
- startColumn = maxColumn;
- }
- }
- }
- const initialEndLineNumber = range.endLineNumber;
- const initialEndColumn = range.endColumn;
- let endLineNumber = Math.floor((typeof initialEndLineNumber === 'number' && !isNaN(initialEndLineNumber)) ? initialEndLineNumber : 1);
- let endColumn = Math.floor((typeof initialEndColumn === 'number' && !isNaN(initialEndColumn)) ? initialEndColumn : 1);
- if (endLineNumber < 1) {
- endLineNumber = 1;
- endColumn = 1;
- }
- else if (endLineNumber > linesCount) {
- endLineNumber = linesCount;
- endColumn = this.getLineMaxColumn(endLineNumber);
- }
- else {
- if (endColumn <= 1) {
- endColumn = 1;
- }
- else {
- const maxColumn = this.getLineMaxColumn(endLineNumber);
- if (endColumn >= maxColumn) {
- endColumn = maxColumn;
- }
- }
- }
- if (initialStartLineNumber === startLineNumber
- && initialStartColumn === startColumn
- && initialEndLineNumber === endLineNumber
- && initialEndColumn === endColumn
- && range instanceof Range
- && !(range instanceof Selection)) {
- return range;
- }
- return new Range(startLineNumber, startColumn, endLineNumber, endColumn);
- }
- _isValidPosition(lineNumber, column, validationType) {
- if (typeof lineNumber !== 'number' || typeof column !== 'number') {
- return false;
- }
- if (isNaN(lineNumber) || isNaN(column)) {
- return false;
- }
- if (lineNumber < 1 || column < 1) {
- return false;
- }
- if ((lineNumber | 0) !== lineNumber || (column | 0) !== column) {
- return false;
- }
- const lineCount = this._buffer.getLineCount();
- if (lineNumber > lineCount) {
- return false;
- }
- if (column === 1) {
- return true;
- }
- const maxColumn = this.getLineMaxColumn(lineNumber);
- if (column > maxColumn) {
- return false;
- }
- if (validationType === 1 /* StringOffsetValidationType.SurrogatePairs */) {
- // !!At this point, column > 1
- const charCodeBefore = this._buffer.getLineCharCode(lineNumber, column - 2);
- if (strings.isHighSurrogate(charCodeBefore)) {
- return false;
- }
- }
- return true;
- }
- _validatePosition(_lineNumber, _column, validationType) {
- const lineNumber = Math.floor((typeof _lineNumber === 'number' && !isNaN(_lineNumber)) ? _lineNumber : 1);
- const column = Math.floor((typeof _column === 'number' && !isNaN(_column)) ? _column : 1);
- const lineCount = this._buffer.getLineCount();
- if (lineNumber < 1) {
- return new Position(1, 1);
- }
- if (lineNumber > lineCount) {
- return new Position(lineCount, this.getLineMaxColumn(lineCount));
- }
- if (column <= 1) {
- return new Position(lineNumber, 1);
- }
- const maxColumn = this.getLineMaxColumn(lineNumber);
- if (column >= maxColumn) {
- return new Position(lineNumber, maxColumn);
- }
- if (validationType === 1 /* StringOffsetValidationType.SurrogatePairs */) {
- // If the position would end up in the middle of a high-low surrogate pair,
- // we move it to before the pair
- // !!At this point, column > 1
- const charCodeBefore = this._buffer.getLineCharCode(lineNumber, column - 2);
- if (strings.isHighSurrogate(charCodeBefore)) {
- return new Position(lineNumber, column - 1);
- }
- }
- return new Position(lineNumber, column);
- }
- validatePosition(position) {
- const validationType = 1 /* StringOffsetValidationType.SurrogatePairs */;
- this._assertNotDisposed();
- // Avoid object allocation and cover most likely case
- if (position instanceof Position) {
- if (this._isValidPosition(position.lineNumber, position.column, validationType)) {
- return position;
- }
- }
- return this._validatePosition(position.lineNumber, position.column, validationType);
- }
- _isValidRange(range, validationType) {
- const startLineNumber = range.startLineNumber;
- const startColumn = range.startColumn;
- const endLineNumber = range.endLineNumber;
- const endColumn = range.endColumn;
- if (!this._isValidPosition(startLineNumber, startColumn, 0 /* StringOffsetValidationType.Relaxed */)) {
- return false;
- }
- if (!this._isValidPosition(endLineNumber, endColumn, 0 /* StringOffsetValidationType.Relaxed */)) {
- return false;
- }
- if (validationType === 1 /* StringOffsetValidationType.SurrogatePairs */) {
- const charCodeBeforeStart = (startColumn > 1 ? this._buffer.getLineCharCode(startLineNumber, startColumn - 2) : 0);
- const charCodeBeforeEnd = (endColumn > 1 && endColumn <= this._buffer.getLineLength(endLineNumber) ? this._buffer.getLineCharCode(endLineNumber, endColumn - 2) : 0);
- const startInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeStart);
- const endInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeEnd);
- if (!startInsideSurrogatePair && !endInsideSurrogatePair) {
- return true;
- }
- return false;
- }
- return true;
- }
- validateRange(_range) {
- const validationType = 1 /* StringOffsetValidationType.SurrogatePairs */;
- this._assertNotDisposed();
- // Avoid object allocation and cover most likely case
- if ((_range instanceof Range) && !(_range instanceof Selection)) {
- if (this._isValidRange(_range, validationType)) {
- return _range;
- }
- }
- const start = this._validatePosition(_range.startLineNumber, _range.startColumn, 0 /* StringOffsetValidationType.Relaxed */);
- const end = this._validatePosition(_range.endLineNumber, _range.endColumn, 0 /* StringOffsetValidationType.Relaxed */);
- const startLineNumber = start.lineNumber;
- const startColumn = start.column;
- const endLineNumber = end.lineNumber;
- const endColumn = end.column;
- if (validationType === 1 /* StringOffsetValidationType.SurrogatePairs */) {
- const charCodeBeforeStart = (startColumn > 1 ? this._buffer.getLineCharCode(startLineNumber, startColumn - 2) : 0);
- const charCodeBeforeEnd = (endColumn > 1 && endColumn <= this._buffer.getLineLength(endLineNumber) ? this._buffer.getLineCharCode(endLineNumber, endColumn - 2) : 0);
- const startInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeStart);
- const endInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeEnd);
- if (!startInsideSurrogatePair && !endInsideSurrogatePair) {
- return new Range(startLineNumber, startColumn, endLineNumber, endColumn);
- }
- if (startLineNumber === endLineNumber && startColumn === endColumn) {
- // do not expand a collapsed range, simply move it to a valid location
- return new Range(startLineNumber, startColumn - 1, endLineNumber, endColumn - 1);
- }
- if (startInsideSurrogatePair && endInsideSurrogatePair) {
- // expand range at both ends
- return new Range(startLineNumber, startColumn - 1, endLineNumber, endColumn + 1);
- }
- if (startInsideSurrogatePair) {
- // only expand range at the start
- return new Range(startLineNumber, startColumn - 1, endLineNumber, endColumn);
- }
- // only expand range at the end
- return new Range(startLineNumber, startColumn, endLineNumber, endColumn + 1);
- }
- return new Range(startLineNumber, startColumn, endLineNumber, endColumn);
- }
- modifyPosition(rawPosition, offset) {
- this._assertNotDisposed();
- const candidate = this.getOffsetAt(rawPosition) + offset;
- return this.getPositionAt(Math.min(this._buffer.getLength(), Math.max(0, candidate)));
- }
- getFullModelRange() {
- this._assertNotDisposed();
- const lineCount = this.getLineCount();
- return new Range(1, 1, lineCount, this.getLineMaxColumn(lineCount));
- }
- findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount) {
- return this._buffer.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount);
- }
- findMatches(searchString, rawSearchScope, isRegex, matchCase, wordSeparators, captureMatches, limitResultCount = LIMIT_FIND_COUNT) {
- this._assertNotDisposed();
- let searchRanges = null;
- if (rawSearchScope !== null) {
- if (!Array.isArray(rawSearchScope)) {
- rawSearchScope = [rawSearchScope];
- }
- if (rawSearchScope.every((searchScope) => Range.isIRange(searchScope))) {
- searchRanges = rawSearchScope.map((searchScope) => this.validateRange(searchScope));
- }
- }
- if (searchRanges === null) {
- searchRanges = [this.getFullModelRange()];
- }
- searchRanges = searchRanges.sort((d1, d2) => d1.startLineNumber - d2.startLineNumber || d1.startColumn - d2.startColumn);
- const uniqueSearchRanges = [];
- uniqueSearchRanges.push(searchRanges.reduce((prev, curr) => {
- if (Range.areIntersecting(prev, curr)) {
- return prev.plusRange(curr);
- }
- uniqueSearchRanges.push(prev);
- return curr;
- }));
- let matchMapper;
- if (!isRegex && searchString.indexOf('\n') < 0) {
- // not regex, not multi line
- const searchParams = new SearchParams(searchString, isRegex, matchCase, wordSeparators);
- const searchData = searchParams.parseSearchRequest();
- if (!searchData) {
- return [];
- }
- matchMapper = (searchRange) => this.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount);
- }
- else {
- matchMapper = (searchRange) => TextModelSearch.findMatches(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchRange, captureMatches, limitResultCount);
- }
- return uniqueSearchRanges.map(matchMapper).reduce((arr, matches) => arr.concat(matches), []);
- }
- findNextMatch(searchString, rawSearchStart, isRegex, matchCase, wordSeparators, captureMatches) {
- this._assertNotDisposed();
- const searchStart = this.validatePosition(rawSearchStart);
- if (!isRegex && searchString.indexOf('\n') < 0) {
- const searchParams = new SearchParams(searchString, isRegex, matchCase, wordSeparators);
- const searchData = searchParams.parseSearchRequest();
- if (!searchData) {
- return null;
- }
- const lineCount = this.getLineCount();
- let searchRange = new Range(searchStart.lineNumber, searchStart.column, lineCount, this.getLineMaxColumn(lineCount));
- let ret = this.findMatchesLineByLine(searchRange, searchData, captureMatches, 1);
- TextModelSearch.findNextMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches);
- if (ret.length > 0) {
- return ret[0];
- }
- searchRange = new Range(1, 1, searchStart.lineNumber, this.getLineMaxColumn(searchStart.lineNumber));
- ret = this.findMatchesLineByLine(searchRange, searchData, captureMatches, 1);
- if (ret.length > 0) {
- return ret[0];
- }
- return null;
- }
- return TextModelSearch.findNextMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches);
- }
- findPreviousMatch(searchString, rawSearchStart, isRegex, matchCase, wordSeparators, captureMatches) {
- this._assertNotDisposed();
- const searchStart = this.validatePosition(rawSearchStart);
- return TextModelSearch.findPreviousMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches);
- }
- //#endregion
- //#region Editing
- pushStackElement() {
- this._commandManager.pushStackElement();
- }
- popStackElement() {
- this._commandManager.popStackElement();
- }
- pushEOL(eol) {
- const currentEOL = (this.getEOL() === '\n' ? 0 /* model.EndOfLineSequence.LF */ : 1 /* model.EndOfLineSequence.CRLF */);
- if (currentEOL === eol) {
- return;
- }
- try {
- this._onDidChangeDecorations.beginDeferredEmit();
- this._eventEmitter.beginDeferredEmit();
- if (this._initialUndoRedoSnapshot === null) {
- this._initialUndoRedoSnapshot = this._undoRedoService.createSnapshot(this.uri);
- }
- this._commandManager.pushEOL(eol);
- }
- finally {
- this._eventEmitter.endDeferredEmit();
- this._onDidChangeDecorations.endDeferredEmit();
- }
- }
- _validateEditOperation(rawOperation) {
- if (rawOperation instanceof model.ValidAnnotatedEditOperation) {
- return rawOperation;
- }
- return new model.ValidAnnotatedEditOperation(rawOperation.identifier || null, this.validateRange(rawOperation.range), rawOperation.text, rawOperation.forceMoveMarkers || false, rawOperation.isAutoWhitespaceEdit || false, rawOperation._isTracked || false);
- }
- _validateEditOperations(rawOperations) {
- const result = [];
- for (let i = 0, len = rawOperations.length; i < len; i++) {
- result[i] = this._validateEditOperation(rawOperations[i]);
- }
- return result;
- }
- pushEditOperations(beforeCursorState, editOperations, cursorStateComputer) {
- try {
- this._onDidChangeDecorations.beginDeferredEmit();
- this._eventEmitter.beginDeferredEmit();
- return this._pushEditOperations(beforeCursorState, this._validateEditOperations(editOperations), cursorStateComputer);
- }
- finally {
- this._eventEmitter.endDeferredEmit();
- this._onDidChangeDecorations.endDeferredEmit();
- }
- }
- _pushEditOperations(beforeCursorState, editOperations, cursorStateComputer) {
- if (this._options.trimAutoWhitespace && this._trimAutoWhitespaceLines) {
- // Go through each saved line number and insert a trim whitespace edit
- // if it is safe to do so (no conflicts with other edits).
- const incomingEdits = editOperations.map((op) => {
- return {
- range: this.validateRange(op.range),
- text: op.text
- };
- });
- // Sometimes, auto-formatters change ranges automatically which can cause undesired auto whitespace trimming near the cursor
- // We'll use the following heuristic: if the edits occur near the cursor, then it's ok to trim auto whitespace
- let editsAreNearCursors = true;
- if (beforeCursorState) {
- for (let i = 0, len = beforeCursorState.length; i < len; i++) {
- const sel = beforeCursorState[i];
- let foundEditNearSel = false;
- for (let j = 0, lenJ = incomingEdits.length; j < lenJ; j++) {
- const editRange = incomingEdits[j].range;
- const selIsAbove = editRange.startLineNumber > sel.endLineNumber;
- const selIsBelow = sel.startLineNumber > editRange.endLineNumber;
- if (!selIsAbove && !selIsBelow) {
- foundEditNearSel = true;
- break;
- }
- }
- if (!foundEditNearSel) {
- editsAreNearCursors = false;
- break;
- }
- }
- }
- if (editsAreNearCursors) {
- for (let i = 0, len = this._trimAutoWhitespaceLines.length; i < len; i++) {
- const trimLineNumber = this._trimAutoWhitespaceLines[i];
- const maxLineColumn = this.getLineMaxColumn(trimLineNumber);
- let allowTrimLine = true;
- for (let j = 0, lenJ = incomingEdits.length; j < lenJ; j++) {
- const editRange = incomingEdits[j].range;
- const editText = incomingEdits[j].text;
- if (trimLineNumber < editRange.startLineNumber || trimLineNumber > editRange.endLineNumber) {
- // `trimLine` is completely outside this edit
- continue;
- }
- // At this point:
- // editRange.startLineNumber <= trimLine <= editRange.endLineNumber
- if (trimLineNumber === editRange.startLineNumber && editRange.startColumn === maxLineColumn
- && editRange.isEmpty() && editText && editText.length > 0 && editText.charAt(0) === '\n') {
- // This edit inserts a new line (and maybe other text) after `trimLine`
- continue;
- }
- if (trimLineNumber === editRange.startLineNumber && editRange.startColumn === 1
- && editRange.isEmpty() && editText && editText.length > 0 && editText.charAt(editText.length - 1) === '\n') {
- // This edit inserts a new line (and maybe other text) before `trimLine`
- continue;
- }
- // Looks like we can't trim this line as it would interfere with an incoming edit
- allowTrimLine = false;
- break;
- }
- if (allowTrimLine) {
- const trimRange = new Range(trimLineNumber, 1, trimLineNumber, maxLineColumn);
- editOperations.push(new model.ValidAnnotatedEditOperation(null, trimRange, null, false, false, false));
- }
- }
- }
- this._trimAutoWhitespaceLines = null;
- }
- if (this._initialUndoRedoSnapshot === null) {
- this._initialUndoRedoSnapshot = this._undoRedoService.createSnapshot(this.uri);
- }
- return this._commandManager.pushEditOperation(beforeCursorState, editOperations, cursorStateComputer);
- }
- _applyUndo(changes, eol, resultingAlternativeVersionId, resultingSelection) {
- const edits = changes.map((change) => {
- const rangeStart = this.getPositionAt(change.newPosition);
- const rangeEnd = this.getPositionAt(change.newEnd);
- return {
- range: new Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column),
- text: change.oldText
- };
- });
- this._applyUndoRedoEdits(edits, eol, true, false, resultingAlternativeVersionId, resultingSelection);
- }
- _applyRedo(changes, eol, resultingAlternativeVersionId, resultingSelection) {
- const edits = changes.map((change) => {
- const rangeStart = this.getPositionAt(change.oldPosition);
- const rangeEnd = this.getPositionAt(change.oldEnd);
- return {
- range: new Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column),
- text: change.newText
- };
- });
- this._applyUndoRedoEdits(edits, eol, false, true, resultingAlternativeVersionId, resultingSelection);
- }
- _applyUndoRedoEdits(edits, eol, isUndoing, isRedoing, resultingAlternativeVersionId, resultingSelection) {
- try {
- this._onDidChangeDecorations.beginDeferredEmit();
- this._eventEmitter.beginDeferredEmit();
- this._isUndoing = isUndoing;
- this._isRedoing = isRedoing;
- this.applyEdits(edits, false);
- this.setEOL(eol);
- this._overwriteAlternativeVersionId(resultingAlternativeVersionId);
- }
- finally {
- this._isUndoing = false;
- this._isRedoing = false;
- this._eventEmitter.endDeferredEmit(resultingSelection);
- this._onDidChangeDecorations.endDeferredEmit();
- }
- }
- applyEdits(rawOperations, computeUndoEdits = false) {
- try {
- this._onDidChangeDecorations.beginDeferredEmit();
- this._eventEmitter.beginDeferredEmit();
- const operations = this._validateEditOperations(rawOperations);
- return this._doApplyEdits(operations, computeUndoEdits);
- }
- finally {
- this._eventEmitter.endDeferredEmit();
- this._onDidChangeDecorations.endDeferredEmit();
- }
- }
- _doApplyEdits(rawOperations, computeUndoEdits) {
- const oldLineCount = this._buffer.getLineCount();
- const result = this._buffer.applyEdits(rawOperations, this._options.trimAutoWhitespace, computeUndoEdits);
- const newLineCount = this._buffer.getLineCount();
- const contentChanges = result.changes;
- this._trimAutoWhitespaceLines = result.trimAutoWhitespaceLineNumbers;
- if (contentChanges.length !== 0) {
- // We do a first pass to update tokens and decorations
- // because we want to read decorations in the second pass
- // where we will emit content change events
- // and we want to read the final decorations
- for (let i = 0, len = contentChanges.length; i < len; i++) {
- const change = contentChanges[i];
- const [eolCount, firstLineLength, lastLineLength] = countEOL(change.text);
- this._tokenizationTextModelPart.acceptEdit(change.range, change.text, eolCount, firstLineLength, lastLineLength);
- this._decorationsTree.acceptReplace(change.rangeOffset, change.rangeLength, change.text.length, change.forceMoveMarkers);
- }
- const rawContentChanges = [];
- this._increaseVersionId();
- let lineCount = oldLineCount;
- for (let i = 0, len = contentChanges.length; i < len; i++) {
- const change = contentChanges[i];
- const [eolCount] = countEOL(change.text);
- this._onDidChangeDecorations.fire();
- const startLineNumber = change.range.startLineNumber;
- const endLineNumber = change.range.endLineNumber;
- const deletingLinesCnt = endLineNumber - startLineNumber;
- const insertingLinesCnt = eolCount;
- const editingLinesCnt = Math.min(deletingLinesCnt, insertingLinesCnt);
- const changeLineCountDelta = (insertingLinesCnt - deletingLinesCnt);
- const currentEditStartLineNumber = newLineCount - lineCount - changeLineCountDelta + startLineNumber;
- const firstEditLineNumber = currentEditStartLineNumber;
- const lastInsertedLineNumber = currentEditStartLineNumber + insertingLinesCnt;
- const decorationsWithInjectedTextInEditedRange = this._decorationsTree.getInjectedTextInInterval(this, this.getOffsetAt(new Position(firstEditLineNumber, 1)), this.getOffsetAt(new Position(lastInsertedLineNumber, this.getLineMaxColumn(lastInsertedLineNumber))), 0);
- const injectedTextInEditedRange = LineInjectedText.fromDecorations(decorationsWithInjectedTextInEditedRange);
- const injectedTextInEditedRangeQueue = new ArrayQueue(injectedTextInEditedRange);
- for (let j = editingLinesCnt; j >= 0; j--) {
- const editLineNumber = startLineNumber + j;
- const currentEditLineNumber = currentEditStartLineNumber + j;
- injectedTextInEditedRangeQueue.takeFromEndWhile(r => r.lineNumber > currentEditLineNumber);
- const decorationsInCurrentLine = injectedTextInEditedRangeQueue.takeFromEndWhile(r => r.lineNumber === currentEditLineNumber);
- rawContentChanges.push(new ModelRawLineChanged(editLineNumber, this.getLineContent(currentEditLineNumber), decorationsInCurrentLine));
- }
- if (editingLinesCnt < deletingLinesCnt) {
- // Must delete some lines
- const spliceStartLineNumber = startLineNumber + editingLinesCnt;
- rawContentChanges.push(new ModelRawLinesDeleted(spliceStartLineNumber + 1, endLineNumber));
- }
- if (editingLinesCnt < insertingLinesCnt) {
- const injectedTextInEditedRangeQueue = new ArrayQueue(injectedTextInEditedRange);
- // Must insert some lines
- const spliceLineNumber = startLineNumber + editingLinesCnt;
- const cnt = insertingLinesCnt - editingLinesCnt;
- const fromLineNumber = newLineCount - lineCount - cnt + spliceLineNumber + 1;
- const injectedTexts = [];
- const newLines = [];
- for (let i = 0; i < cnt; i++) {
- const lineNumber = fromLineNumber + i;
- newLines[i] = this.getLineContent(lineNumber);
- injectedTextInEditedRangeQueue.takeWhile(r => r.lineNumber < lineNumber);
- injectedTexts[i] = injectedTextInEditedRangeQueue.takeWhile(r => r.lineNumber === lineNumber);
- }
- rawContentChanges.push(new ModelRawLinesInserted(spliceLineNumber + 1, startLineNumber + insertingLinesCnt, newLines, injectedTexts));
- }
- lineCount += changeLineCountDelta;
- }
- this._emitContentChangedEvent(new ModelRawContentChangedEvent(rawContentChanges, this.getVersionId(), this._isUndoing, this._isRedoing), {
- changes: contentChanges,
- eol: this._buffer.getEOL(),
- versionId: this.getVersionId(),
- isUndoing: this._isUndoing,
- isRedoing: this._isRedoing,
- isFlush: false
- });
- }
- return (result.reverseEdits === null ? undefined : result.reverseEdits);
- }
- undo() {
- return this._undoRedoService.undo(this.uri);
- }
- canUndo() {
- return this._undoRedoService.canUndo(this.uri);
- }
- redo() {
- return this._undoRedoService.redo(this.uri);
- }
- canRedo() {
- return this._undoRedoService.canRedo(this.uri);
- }
- //#endregion
- //#region Decorations
- handleBeforeFireDecorationsChangedEvent(affectedInjectedTextLines) {
- // This is called before the decoration changed event is fired.
- if (affectedInjectedTextLines === null || affectedInjectedTextLines.size === 0) {
- return;
- }
- const affectedLines = Array.from(affectedInjectedTextLines);
- const lineChangeEvents = affectedLines.map(lineNumber => new ModelRawLineChanged(lineNumber, this.getLineContent(lineNumber), this._getInjectedTextInLine(lineNumber)));
- this._onDidChangeInjectedText.fire(new ModelInjectedTextChangedEvent(lineChangeEvents));
- }
- changeDecorations(callback, ownerId = 0) {
- this._assertNotDisposed();
- try {
- this._onDidChangeDecorations.beginDeferredEmit();
- return this._changeDecorations(ownerId, callback);
- }
- finally {
- this._onDidChangeDecorations.endDeferredEmit();
- }
- }
- _changeDecorations(ownerId, callback) {
- const changeAccessor = {
- addDecoration: (range, options) => {
- return this._deltaDecorationsImpl(ownerId, [], [{ range: range, options: options }])[0];
- },
- changeDecoration: (id, newRange) => {
- this._changeDecorationImpl(id, newRange);
- },
- changeDecorationOptions: (id, options) => {
- this._changeDecorationOptionsImpl(id, _normalizeOptions(options));
- },
- removeDecoration: (id) => {
- this._deltaDecorationsImpl(ownerId, [id], []);
- },
- deltaDecorations: (oldDecorations, newDecorations) => {
- if (oldDecorations.length === 0 && newDecorations.length === 0) {
- // nothing to do
- return [];
- }
- return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations);
- }
- };
- let result = null;
- try {
- result = callback(changeAccessor);
- }
- catch (e) {
- onUnexpectedError(e);
- }
- // Invalidate change accessor
- changeAccessor.addDecoration = invalidFunc;
- changeAccessor.changeDecoration = invalidFunc;
- changeAccessor.changeDecorationOptions = invalidFunc;
- changeAccessor.removeDecoration = invalidFunc;
- changeAccessor.deltaDecorations = invalidFunc;
- return result;
- }
- deltaDecorations(oldDecorations, newDecorations, ownerId = 0) {
- this._assertNotDisposed();
- if (!oldDecorations) {
- oldDecorations = [];
- }
- if (oldDecorations.length === 0 && newDecorations.length === 0) {
- // nothing to do
- return [];
- }
- try {
- this._deltaDecorationCallCnt++;
- if (this._deltaDecorationCallCnt > 1) {
- console.warn(`Invoking deltaDecorations recursively could lead to leaking decorations.`);
- onUnexpectedError(new Error(`Invoking deltaDecorations recursively could lead to leaking decorations.`));
- }
- this._onDidChangeDecorations.beginDeferredEmit();
- return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations);
- }
- finally {
- this._onDidChangeDecorations.endDeferredEmit();
- this._deltaDecorationCallCnt--;
- }
- }
- _getTrackedRange(id) {
- return this.getDecorationRange(id);
- }
- _setTrackedRange(id, newRange, newStickiness) {
- const node = (id ? this._decorations[id] : null);
- if (!node) {
- if (!newRange) {
- // node doesn't exist, the request is to delete => nothing to do
- return null;
- }
- // node doesn't exist, the request is to set => add the tracked range
- return this._deltaDecorationsImpl(0, [], [{ range: newRange, options: TRACKED_RANGE_OPTIONS[newStickiness] }])[0];
- }
- if (!newRange) {
- // node exists, the request is to delete => delete node
- this._decorationsTree.delete(node);
- delete this._decorations[node.id];
- return null;
- }
- // node exists, the request is to set => change the tracked range and its options
- const range = this._validateRangeRelaxedNoAllocations(newRange);
- const startOffset = this._buffer.getOffsetAt(range.startLineNumber, range.startColumn);
- const endOffset = this._buffer.getOffsetAt(range.endLineNumber, range.endColumn);
- this._decorationsTree.delete(node);
- node.reset(this.getVersionId(), startOffset, endOffset, range);
- node.setOptions(TRACKED_RANGE_OPTIONS[newStickiness]);
- this._decorationsTree.insert(node);
- return node.id;
- }
- removeAllDecorationsWithOwnerId(ownerId) {
- if (this._isDisposed) {
- return;
- }
- const nodes = this._decorationsTree.collectNodesFromOwner(ownerId);
- for (let i = 0, len = nodes.length; i < len; i++) {
- const node = nodes[i];
- this._decorationsTree.delete(node);
- delete this._decorations[node.id];
- }
- }
- getDecorationOptions(decorationId) {
- const node = this._decorations[decorationId];
- if (!node) {
- return null;
- }
- return node.options;
- }
- getDecorationRange(decorationId) {
- const node = this._decorations[decorationId];
- if (!node) {
- return null;
- }
- return this._decorationsTree.getNodeRange(this, node);
- }
- getLineDecorations(lineNumber, ownerId = 0, filterOutValidation = false) {
- if (lineNumber < 1 || lineNumber > this.getLineCount()) {
- return [];
- }
- return this.getLinesDecorations(lineNumber, lineNumber, ownerId, filterOutValidation);
- }
- getLinesDecorations(_startLineNumber, _endLineNumber, ownerId = 0, filterOutValidation = false) {
- const lineCount = this.getLineCount();
- const startLineNumber = Math.min(lineCount, Math.max(1, _startLineNumber));
- const endLineNumber = Math.min(lineCount, Math.max(1, _endLineNumber));
- const endColumn = this.getLineMaxColumn(endLineNumber);
- const range = new Range(startLineNumber, 1, endLineNumber, endColumn);
- const decorations = this._getDecorationsInRange(range, ownerId, filterOutValidation);
- pushMany(decorations, this._decorationProvider.getDecorationsInRange(range, ownerId, filterOutValidation));
- return decorations;
- }
- getDecorationsInRange(range, ownerId = 0, filterOutValidation = false) {
- const validatedRange = this.validateRange(range);
- const decorations = this._getDecorationsInRange(validatedRange, ownerId, filterOutValidation);
- pushMany(decorations, this._decorationProvider.getDecorationsInRange(validatedRange, ownerId, filterOutValidation));
- return decorations;
- }
- getOverviewRulerDecorations(ownerId = 0, filterOutValidation = false) {
- return this._decorationsTree.getAll(this, ownerId, filterOutValidation, true);
- }
- getInjectedTextDecorations(ownerId = 0) {
- return this._decorationsTree.getAllInjectedText(this, ownerId);
- }
- _getInjectedTextInLine(lineNumber) {
- const startOffset = this._buffer.getOffsetAt(lineNumber, 1);
- const endOffset = startOffset + this._buffer.getLineLength(lineNumber);
- const result = this._decorationsTree.getInjectedTextInInterval(this, startOffset, endOffset, 0);
- return LineInjectedText.fromDecorations(result).filter(t => t.lineNumber === lineNumber);
- }
- getAllDecorations(ownerId = 0, filterOutValidation = false) {
- let result = this._decorationsTree.getAll(this, ownerId, filterOutValidation, false);
- result = result.concat(this._decorationProvider.getAllDecorations(ownerId, filterOutValidation));
- return result;
- }
- _getDecorationsInRange(filterRange, filterOwnerId, filterOutValidation) {
- const startOffset = this._buffer.getOffsetAt(filterRange.startLineNumber, filterRange.startColumn);
- const endOffset = this._buffer.getOffsetAt(filterRange.endLineNumber, filterRange.endColumn);
- return this._decorationsTree.getAllInInterval(this, startOffset, endOffset, filterOwnerId, filterOutValidation);
- }
- getRangeAt(start, end) {
- return this._buffer.getRangeAt(start, end - start);
- }
- _changeDecorationImpl(decorationId, _range) {
- const node = this._decorations[decorationId];
- if (!node) {
- return;
- }
- if (node.options.after) {
- const oldRange = this.getDecorationRange(decorationId);
- this._onDidChangeDecorations.recordLineAffectedByInjectedText(oldRange.endLineNumber);
- }
- if (node.options.before) {
- const oldRange = this.getDecorationRange(decorationId);
- this._onDidChangeDecorations.recordLineAffectedByInjectedText(oldRange.startLineNumber);
- }
- const range = this._validateRangeRelaxedNoAllocations(_range);
- const startOffset = this._buffer.getOffsetAt(range.startLineNumber, range.startColumn);
- const endOffset = this._buffer.getOffsetAt(range.endLineNumber, range.endColumn);
- this._decorationsTree.delete(node);
- node.reset(this.getVersionId(), startOffset, endOffset, range);
- this._decorationsTree.insert(node);
- this._onDidChangeDecorations.checkAffectedAndFire(node.options);
- if (node.options.after) {
- this._onDidChangeDecorations.recordLineAffectedByInjectedText(range.endLineNumber);
- }
- if (node.options.before) {
- this._onDidChangeDecorations.recordLineAffectedByInjectedText(range.startLineNumber);
- }
- }
- _changeDecorationOptionsImpl(decorationId, options) {
- const node = this._decorations[decorationId];
- if (!node) {
- return;
- }
- const nodeWasInOverviewRuler = (node.options.overviewRuler && node.options.overviewRuler.color ? true : false);
- const nodeIsInOverviewRuler = (options.overviewRuler && options.overviewRuler.color ? true : false);
- this._onDidChangeDecorations.checkAffectedAndFire(node.options);
- this._onDidChangeDecorations.checkAffectedAndFire(options);
- if (node.options.after || options.after) {
- const nodeRange = this._decorationsTree.getNodeRange(this, node);
- this._onDidChangeDecorations.recordLineAffectedByInjectedText(nodeRange.endLineNumber);
- }
- if (node.options.before || options.before) {
- const nodeRange = this._decorationsTree.getNodeRange(this, node);
- this._onDidChangeDecorations.recordLineAffectedByInjectedText(nodeRange.startLineNumber);
- }
- if (nodeWasInOverviewRuler !== nodeIsInOverviewRuler) {
- // Delete + Insert due to an overview ruler status change
- this._decorationsTree.delete(node);
- node.setOptions(options);
- this._decorationsTree.insert(node);
- }
- else {
- node.setOptions(options);
- }
- }
- _deltaDecorationsImpl(ownerId, oldDecorationsIds, newDecorations) {
- const versionId = this.getVersionId();
- const oldDecorationsLen = oldDecorationsIds.length;
- let oldDecorationIndex = 0;
- const newDecorationsLen = newDecorations.length;
- let newDecorationIndex = 0;
- const result = new Array(newDecorationsLen);
- while (oldDecorationIndex < oldDecorationsLen || newDecorationIndex < newDecorationsLen) {
- let node = null;
- if (oldDecorationIndex < oldDecorationsLen) {
- // (1) get ourselves an old node
- do {
- node = this._decorations[oldDecorationsIds[oldDecorationIndex++]];
- } while (!node && oldDecorationIndex < oldDecorationsLen);
- // (2) remove the node from the tree (if it exists)
- if (node) {
- if (node.options.after) {
- const nodeRange = this._decorationsTree.getNodeRange(this, node);
- this._onDidChangeDecorations.recordLineAffectedByInjectedText(nodeRange.endLineNumber);
- }
- if (node.options.before) {
- const nodeRange = this._decorationsTree.getNodeRange(this, node);
- this._onDidChangeDecorations.recordLineAffectedByInjectedText(nodeRange.startLineNumber);
- }
- this._decorationsTree.delete(node);
- this._onDidChangeDecorations.checkAffectedAndFire(node.options);
- }
- }
- if (newDecorationIndex < newDecorationsLen) {
- // (3) create a new node if necessary
- if (!node) {
- const internalDecorationId = (++this._lastDecorationId);
- const decorationId = `${this._instanceId};${internalDecorationId}`;
- node = new IntervalNode(decorationId, 0, 0);
- this._decorations[decorationId] = node;
- }
- // (4) initialize node
- const newDecoration = newDecorations[newDecorationIndex];
- const range = this._validateRangeRelaxedNoAllocations(newDecoration.range);
- const options = _normalizeOptions(newDecoration.options);
- const startOffset = this._buffer.getOffsetAt(range.startLineNumber, range.startColumn);
- const endOffset = this._buffer.getOffsetAt(range.endLineNumber, range.endColumn);
- node.ownerId = ownerId;
- node.reset(versionId, startOffset, endOffset, range);
- node.setOptions(options);
- if (node.options.after) {
- this._onDidChangeDecorations.recordLineAffectedByInjectedText(range.endLineNumber);
- }
- if (node.options.before) {
- this._onDidChangeDecorations.recordLineAffectedByInjectedText(range.startLineNumber);
- }
- this._onDidChangeDecorations.checkAffectedAndFire(options);
- this._decorationsTree.insert(node);
- result[newDecorationIndex] = node.id;
- newDecorationIndex++;
- }
- else {
- if (node) {
- delete this._decorations[node.id];
- }
- }
- }
- return result;
- }
- //#endregion
- //#region Tokenization
- // TODO move them to the tokenization part.
- getLanguageId() {
- return this.tokenization.getLanguageId();
- }
- setMode(languageId) {
- this.tokenization.setLanguageId(languageId);
- }
- getLanguageIdAtPosition(lineNumber, column) {
- return this.tokenization.getLanguageIdAtPosition(lineNumber, column);
- }
- getWordAtPosition(position) {
- return this._tokenizationTextModelPart.getWordAtPosition(position);
- }
- getWordUntilPosition(position) {
- return this._tokenizationTextModelPart.getWordUntilPosition(position);
- }
- //#endregion
- normalizePosition(position, affinity) {
- return position;
- }
- /**
- * Gets the column at which indentation stops at a given line.
- * @internal
- */
- getLineIndentColumn(lineNumber) {
- // Columns start with 1.
- return indentOfLine(this.getLineContent(lineNumber)) + 1;
- }
- };
- TextModel.MODEL_SYNC_LIMIT = 50 * 1024 * 1024; // 50 MB
- TextModel.LARGE_FILE_SIZE_THRESHOLD = 20 * 1024 * 1024; // 20 MB;
- TextModel.LARGE_FILE_LINE_COUNT_THRESHOLD = 300 * 1000; // 300K lines
- TextModel.DEFAULT_CREATION_OPTIONS = {
- isForSimpleWidget: false,
- tabSize: EDITOR_MODEL_DEFAULTS.tabSize,
- indentSize: EDITOR_MODEL_DEFAULTS.indentSize,
- insertSpaces: EDITOR_MODEL_DEFAULTS.insertSpaces,
- detectIndentation: false,
- defaultEOL: 1 /* model.DefaultEndOfLine.LF */,
- trimAutoWhitespace: EDITOR_MODEL_DEFAULTS.trimAutoWhitespace,
- largeFileOptimizations: EDITOR_MODEL_DEFAULTS.largeFileOptimizations,
- bracketPairColorizationOptions: EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions,
- };
- TextModel = __decorate([
- __param(4, IUndoRedoService),
- __param(5, ILanguageService),
- __param(6, ILanguageConfigurationService)
- ], TextModel);
- export { TextModel };
- function indentOfLine(line) {
- let indent = 0;
- for (const c of line) {
- if (c === ' ' || c === '\t') {
- indent++;
- }
- else {
- break;
- }
- }
- return indent;
- }
- //#region Decorations
- function isNodeInOverviewRuler(node) {
- return (node.options.overviewRuler && node.options.overviewRuler.color ? true : false);
- }
- function isNodeInjectedText(node) {
- return !!node.options.after || !!node.options.before;
- }
- class DecorationsTrees {
- constructor() {
- this._decorationsTree0 = new IntervalTree();
- this._decorationsTree1 = new IntervalTree();
- this._injectedTextDecorationsTree = new IntervalTree();
- }
- ensureAllNodesHaveRanges(host) {
- this.getAll(host, 0, false, false);
- }
- _ensureNodesHaveRanges(host, nodes) {
- for (const node of nodes) {
- if (node.range === null) {
- node.range = host.getRangeAt(node.cachedAbsoluteStart, node.cachedAbsoluteEnd);
- }
- }
- return nodes;
- }
- getAllInInterval(host, start, end, filterOwnerId, filterOutValidation) {
- const versionId = host.getVersionId();
- const result = this._intervalSearch(start, end, filterOwnerId, filterOutValidation, versionId);
- return this._ensureNodesHaveRanges(host, result);
- }
- _intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId) {
- const r0 = this._decorationsTree0.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId);
- const r1 = this._decorationsTree1.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId);
- const r2 = this._injectedTextDecorationsTree.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId);
- return r0.concat(r1).concat(r2);
- }
- getInjectedTextInInterval(host, start, end, filterOwnerId) {
- const versionId = host.getVersionId();
- const result = this._injectedTextDecorationsTree.intervalSearch(start, end, filterOwnerId, false, versionId);
- return this._ensureNodesHaveRanges(host, result).filter((i) => i.options.showIfCollapsed || !i.range.isEmpty());
- }
- getAllInjectedText(host, filterOwnerId) {
- const versionId = host.getVersionId();
- const result = this._injectedTextDecorationsTree.search(filterOwnerId, false, versionId);
- return this._ensureNodesHaveRanges(host, result).filter((i) => i.options.showIfCollapsed || !i.range.isEmpty());
- }
- getAll(host, filterOwnerId, filterOutValidation, overviewRulerOnly) {
- const versionId = host.getVersionId();
- const result = this._search(filterOwnerId, filterOutValidation, overviewRulerOnly, versionId);
- return this._ensureNodesHaveRanges(host, result);
- }
- _search(filterOwnerId, filterOutValidation, overviewRulerOnly, cachedVersionId) {
- if (overviewRulerOnly) {
- return this._decorationsTree1.search(filterOwnerId, filterOutValidation, cachedVersionId);
- }
- else {
- const r0 = this._decorationsTree0.search(filterOwnerId, filterOutValidation, cachedVersionId);
- const r1 = this._decorationsTree1.search(filterOwnerId, filterOutValidation, cachedVersionId);
- const r2 = this._injectedTextDecorationsTree.search(filterOwnerId, filterOutValidation, cachedVersionId);
- return r0.concat(r1).concat(r2);
- }
- }
- collectNodesFromOwner(ownerId) {
- const r0 = this._decorationsTree0.collectNodesFromOwner(ownerId);
- const r1 = this._decorationsTree1.collectNodesFromOwner(ownerId);
- const r2 = this._injectedTextDecorationsTree.collectNodesFromOwner(ownerId);
- return r0.concat(r1).concat(r2);
- }
- collectNodesPostOrder() {
- const r0 = this._decorationsTree0.collectNodesPostOrder();
- const r1 = this._decorationsTree1.collectNodesPostOrder();
- const r2 = this._injectedTextDecorationsTree.collectNodesPostOrder();
- return r0.concat(r1).concat(r2);
- }
- insert(node) {
- if (isNodeInjectedText(node)) {
- this._injectedTextDecorationsTree.insert(node);
- }
- else if (isNodeInOverviewRuler(node)) {
- this._decorationsTree1.insert(node);
- }
- else {
- this._decorationsTree0.insert(node);
- }
- }
- delete(node) {
- if (isNodeInjectedText(node)) {
- this._injectedTextDecorationsTree.delete(node);
- }
- else if (isNodeInOverviewRuler(node)) {
- this._decorationsTree1.delete(node);
- }
- else {
- this._decorationsTree0.delete(node);
- }
- }
- getNodeRange(host, node) {
- const versionId = host.getVersionId();
- if (node.cachedVersionId !== versionId) {
- this._resolveNode(node, versionId);
- }
- if (node.range === null) {
- node.range = host.getRangeAt(node.cachedAbsoluteStart, node.cachedAbsoluteEnd);
- }
- return node.range;
- }
- _resolveNode(node, cachedVersionId) {
- if (isNodeInjectedText(node)) {
- this._injectedTextDecorationsTree.resolveNode(node, cachedVersionId);
- }
- else if (isNodeInOverviewRuler(node)) {
- this._decorationsTree1.resolveNode(node, cachedVersionId);
- }
- else {
- this._decorationsTree0.resolveNode(node, cachedVersionId);
- }
- }
- acceptReplace(offset, length, textLength, forceMoveMarkers) {
- this._decorationsTree0.acceptReplace(offset, length, textLength, forceMoveMarkers);
- this._decorationsTree1.acceptReplace(offset, length, textLength, forceMoveMarkers);
- this._injectedTextDecorationsTree.acceptReplace(offset, length, textLength, forceMoveMarkers);
- }
- }
- function cleanClassName(className) {
- return className.replace(/[^a-z0-9\-_]/gi, ' ');
- }
- class DecorationOptions {
- constructor(options) {
- this.color = options.color || '';
- this.darkColor = options.darkColor || '';
- }
- }
- export class ModelDecorationOverviewRulerOptions extends DecorationOptions {
- constructor(options) {
- super(options);
- this._resolvedColor = null;
- this.position = (typeof options.position === 'number' ? options.position : model.OverviewRulerLane.Center);
- }
- getColor(theme) {
- if (!this._resolvedColor) {
- if (theme.type !== 'light' && this.darkColor) {
- this._resolvedColor = this._resolveColor(this.darkColor, theme);
- }
- else {
- this._resolvedColor = this._resolveColor(this.color, theme);
- }
- }
- return this._resolvedColor;
- }
- invalidateCachedColor() {
- this._resolvedColor = null;
- }
- _resolveColor(color, theme) {
- if (typeof color === 'string') {
- return color;
- }
- const c = color ? theme.getColor(color.id) : null;
- if (!c) {
- return '';
- }
- return c.toString();
- }
- }
- export class ModelDecorationMinimapOptions extends DecorationOptions {
- constructor(options) {
- super(options);
- this.position = options.position;
- }
- getColor(theme) {
- if (!this._resolvedColor) {
- if (theme.type !== 'light' && this.darkColor) {
- this._resolvedColor = this._resolveColor(this.darkColor, theme);
- }
- else {
- this._resolvedColor = this._resolveColor(this.color, theme);
- }
- }
- return this._resolvedColor;
- }
- invalidateCachedColor() {
- this._resolvedColor = undefined;
- }
- _resolveColor(color, theme) {
- if (typeof color === 'string') {
- return Color.fromHex(color);
- }
- return theme.getColor(color.id);
- }
- }
- export class ModelDecorationInjectedTextOptions {
- constructor(options) {
- this.content = options.content || '';
- this.inlineClassName = options.inlineClassName || null;
- this.inlineClassNameAffectsLetterSpacing = options.inlineClassNameAffectsLetterSpacing || false;
- this.attachedData = options.attachedData || null;
- this.cursorStops = options.cursorStops || null;
- }
- static from(options) {
- if (options instanceof ModelDecorationInjectedTextOptions) {
- return options;
- }
- return new ModelDecorationInjectedTextOptions(options);
- }
- }
- export class ModelDecorationOptions {
- constructor(options) {
- var _a, _b;
- this.description = options.description;
- this.blockClassName = options.blockClassName ? cleanClassName(options.blockClassName) : null;
- this.stickiness = options.stickiness || 0 /* model.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges */;
- this.zIndex = options.zIndex || 0;
- this.className = options.className ? cleanClassName(options.className) : null;
- this.hoverMessage = options.hoverMessage || null;
- this.glyphMarginHoverMessage = options.glyphMarginHoverMessage || null;
- this.isWholeLine = options.isWholeLine || false;
- this.showIfCollapsed = options.showIfCollapsed || false;
- this.collapseOnReplaceEdit = options.collapseOnReplaceEdit || false;
- this.overviewRuler = options.overviewRuler ? new ModelDecorationOverviewRulerOptions(options.overviewRuler) : null;
- this.minimap = options.minimap ? new ModelDecorationMinimapOptions(options.minimap) : null;
- this.glyphMarginClassName = options.glyphMarginClassName ? cleanClassName(options.glyphMarginClassName) : null;
- this.linesDecorationsClassName = options.linesDecorationsClassName ? cleanClassName(options.linesDecorationsClassName) : null;
- this.firstLineDecorationClassName = options.firstLineDecorationClassName ? cleanClassName(options.firstLineDecorationClassName) : null;
- this.marginClassName = options.marginClassName ? cleanClassName(options.marginClassName) : null;
- this.inlineClassName = options.inlineClassName ? cleanClassName(options.inlineClassName) : null;
- this.inlineClassNameAffectsLetterSpacing = options.inlineClassNameAffectsLetterSpacing || false;
- this.beforeContentClassName = options.beforeContentClassName ? cleanClassName(options.beforeContentClassName) : null;
- this.afterContentClassName = options.afterContentClassName ? cleanClassName(options.afterContentClassName) : null;
- this.after = options.after ? ModelDecorationInjectedTextOptions.from(options.after) : null;
- this.before = options.before ? ModelDecorationInjectedTextOptions.from(options.before) : null;
- this.hideInCommentTokens = (_a = options.hideInCommentTokens) !== null && _a !== void 0 ? _a : false;
- this.hideInStringTokens = (_b = options.hideInStringTokens) !== null && _b !== void 0 ? _b : false;
- }
- static register(options) {
- return new ModelDecorationOptions(options);
- }
- static createDynamic(options) {
- return new ModelDecorationOptions(options);
- }
- }
- ModelDecorationOptions.EMPTY = ModelDecorationOptions.register({ description: 'empty' });
- /**
- * The order carefully matches the values of the enum.
- */
- const TRACKED_RANGE_OPTIONS = [
- ModelDecorationOptions.register({ description: 'tracked-range-always-grows-when-typing-at-edges', stickiness: 0 /* model.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges */ }),
- ModelDecorationOptions.register({ description: 'tracked-range-never-grows-when-typing-at-edges', stickiness: 1 /* model.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */ }),
- ModelDecorationOptions.register({ description: 'tracked-range-grows-only-when-typing-before', stickiness: 2 /* model.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore */ }),
- ModelDecorationOptions.register({ description: 'tracked-range-grows-only-when-typing-after', stickiness: 3 /* model.TrackedRangeStickiness.GrowsOnlyWhenTypingAfter */ }),
- ];
- function _normalizeOptions(options) {
- if (options instanceof ModelDecorationOptions) {
- return options;
- }
- return ModelDecorationOptions.createDynamic(options);
- }
- export class DidChangeDecorationsEmitter extends Disposable {
- constructor(handleBeforeFire) {
- super();
- this.handleBeforeFire = handleBeforeFire;
- this._actual = this._register(new Emitter());
- this.event = this._actual.event;
- this._affectedInjectedTextLines = null;
- this._deferredCnt = 0;
- this._shouldFire = false;
- this._affectsMinimap = false;
- this._affectsOverviewRuler = false;
- }
- beginDeferredEmit() {
- this._deferredCnt++;
- }
- endDeferredEmit() {
- var _a;
- this._deferredCnt--;
- if (this._deferredCnt === 0) {
- if (this._shouldFire) {
- this.handleBeforeFire(this._affectedInjectedTextLines);
- const event = {
- affectsMinimap: this._affectsMinimap,
- affectsOverviewRuler: this._affectsOverviewRuler
- };
- this._shouldFire = false;
- this._affectsMinimap = false;
- this._affectsOverviewRuler = false;
- this._actual.fire(event);
- }
- (_a = this._affectedInjectedTextLines) === null || _a === void 0 ? void 0 : _a.clear();
- this._affectedInjectedTextLines = null;
- }
- }
- recordLineAffectedByInjectedText(lineNumber) {
- if (!this._affectedInjectedTextLines) {
- this._affectedInjectedTextLines = new Set();
- }
- this._affectedInjectedTextLines.add(lineNumber);
- }
- checkAffectedAndFire(options) {
- if (!this._affectsMinimap) {
- this._affectsMinimap = options.minimap && options.minimap.position ? true : false;
- }
- if (!this._affectsOverviewRuler) {
- this._affectsOverviewRuler = options.overviewRuler && options.overviewRuler.color ? true : false;
- }
- this._shouldFire = true;
- }
- fire() {
- this._affectsMinimap = true;
- this._affectsOverviewRuler = true;
- this._shouldFire = true;
- }
- }
- //#endregion
- export class DidChangeContentEmitter extends Disposable {
- constructor() {
- super();
- /**
- * Both `fastEvent` and `slowEvent` work the same way and contain the same events, but first we invoke `fastEvent` and then `slowEvent`.
- */
- this._fastEmitter = this._register(new Emitter());
- this.fastEvent = this._fastEmitter.event;
- this._slowEmitter = this._register(new Emitter());
- this.slowEvent = this._slowEmitter.event;
- this._deferredCnt = 0;
- this._deferredEvent = null;
- }
- beginDeferredEmit() {
- this._deferredCnt++;
- }
- endDeferredEmit(resultingSelection = null) {
- this._deferredCnt--;
- if (this._deferredCnt === 0) {
- if (this._deferredEvent !== null) {
- this._deferredEvent.rawContentChangedEvent.resultingSelection = resultingSelection;
- const e = this._deferredEvent;
- this._deferredEvent = null;
- this._fastEmitter.fire(e);
- this._slowEmitter.fire(e);
- }
- }
- }
- fire(e) {
- if (this._deferredCnt > 0) {
- if (this._deferredEvent) {
- this._deferredEvent = this._deferredEvent.merge(e);
- }
- else {
- this._deferredEvent = e;
- }
- return;
- }
- this._fastEmitter.fire(e);
- this._slowEmitter.fire(e);
- }
- }
|