From cf05245da603ad951d3f00320eee39eac5a78e5c Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 3 Jan 2018 16:51:29 +0200 Subject: [PATCH] Introduce ITextBuffer --- .../editor/common/model/editableTextModel.ts | 2 +- .../editor/common/model/indentationGuesser.ts | 4 +- src/vs/editor/common/model/modelLine.ts | 8 +-- src/vs/editor/common/model/textBuffer.ts | 68 ++++++++++--------- src/vs/editor/common/model/textModel.ts | 6 +- 5 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/vs/editor/common/model/editableTextModel.ts b/src/vs/editor/common/model/editableTextModel.ts index 54a4a8329fb..656d7b0b01a 100644 --- a/src/vs/editor/common/model/editableTextModel.ts +++ b/src/vs/editor/common/model/editableTextModel.ts @@ -170,7 +170,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito for (let i = 0, len = rawOperations.length; i < len; i++) { rawOperations[i].range = this.validateRange(rawOperations[i].range); } - const result = this._buffer._applyEdits(rawOperations, this._options.trimAutoWhitespace); + const result = this._buffer.applyEdits(rawOperations, this._options.trimAutoWhitespace); const rawContentChanges = result.rawChanges; const contentChanges = result.changes; this._trimAutoWhitespaceLines = result.trimAutoWhitespaceLineNumbers; diff --git a/src/vs/editor/common/model/indentationGuesser.ts b/src/vs/editor/common/model/indentationGuesser.ts index 56c6683c543..0ec4e0c63ef 100644 --- a/src/vs/editor/common/model/indentationGuesser.ts +++ b/src/vs/editor/common/model/indentationGuesser.ts @@ -5,7 +5,7 @@ 'use strict'; import { CharCode } from 'vs/base/common/charCode'; -import { TextBuffer } from 'vs/editor/common/model/textBuffer'; +import { ITextBuffer } from 'vs/editor/common/model/textBuffer'; export interface IIndentationGuesserTarget { getLineCount(): number; @@ -15,7 +15,7 @@ export interface IIndentationGuesserTarget { export class IndentationGuesserTextBufferTarget implements IIndentationGuesserTarget { constructor( - private readonly _buffer: TextBuffer + private readonly _buffer: ITextBuffer ) { } public getLineCount(): number { diff --git a/src/vs/editor/common/model/modelLine.ts b/src/vs/editor/common/model/modelLine.ts index f33043fd142..e674fe4b5f4 100644 --- a/src/vs/editor/common/model/modelLine.ts +++ b/src/vs/editor/common/model/modelLine.ts @@ -12,7 +12,7 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { IModelTokensChangedEvent } from 'vs/editor/common/model/textModelEvents'; import { onUnexpectedError } from 'vs/base/common/errors'; -import { TextBuffer } from 'vs/editor/common/model/textBuffer'; +import { ITextBuffer } from 'vs/editor/common/model/textBuffer'; import { TokenizationResult2 } from 'vs/editor/common/core/token'; import { nullTokenize2 } from 'vs/editor/common/modes/nullMode'; @@ -247,7 +247,7 @@ export class ModelLinesTokens { return (firstInvalidLineNumber >= lineNumber); } - public hasLinesToTokenize(buffer: TextBuffer): boolean { + public hasLinesToTokenize(buffer: ITextBuffer): boolean { return (this._invalidLineStartIndex < buffer.getLineCount()); } @@ -413,7 +413,7 @@ export class ModelLinesTokens { //#region Tokenization - public _tokenizeOneLine(buffer: TextBuffer, eventBuilder: ModelTokensChangedEventBuilder): number { + public _tokenizeOneLine(buffer: ITextBuffer, eventBuilder: ModelTokensChangedEventBuilder): number { if (!this.hasLinesToTokenize(buffer)) { return buffer.getLineCount() + 1; } @@ -422,7 +422,7 @@ export class ModelLinesTokens { return lineNumber; } - public _updateTokensUntilLine(buffer: TextBuffer, eventBuilder: ModelTokensChangedEventBuilder, lineNumber: number): void { + public _updateTokensUntilLine(buffer: ITextBuffer, eventBuilder: ModelTokensChangedEventBuilder, lineNumber: number): void { if (!this.tokenizationSupport) { this._invalidLineStartIndex = buffer.getLineCount(); return; diff --git a/src/vs/editor/common/model/textBuffer.ts b/src/vs/editor/common/model/textBuffer.ts index a0c14510677..af0f34a3c52 100644 --- a/src/vs/editor/common/model/textBuffer.ts +++ b/src/vs/editor/common/model/textBuffer.ts @@ -15,12 +15,31 @@ import { IValidatedEditOperation } from 'vs/editor/common/model/editableTextMode import { ModelRawChange, IModelContentChange, ModelRawLineChanged, ModelRawLinesDeleted, ModelRawLinesInserted } from 'vs/editor/common/model/textModelEvents'; export interface ITextBuffer { + equals(other: ITextSource): boolean; mightContainRTL(): boolean; mightContainNonBasicASCII(): boolean; getBOM(): string; + getEOL(): string; + + getOffsetAt(lineNumber: number, column: number): number; + getPositionAt(offset: number): Position; + getRangeAt(offset: number, length: number): Range; + + getValueInRange(range: Range, eol: editorCommon.EndOfLinePreference): string; + getValueLengthInRange(range: Range, eol: editorCommon.EndOfLinePreference): number; + getLineCount(): number; + getLinesContent(): string[]; + getLineContent(lineNumber: number): string; + getLineCharCode(lineNumber: number, index: number): number; + getLineLength(lineNumber: number): number; + getLineFirstNonWhitespaceColumn(lineNumber: number): number; + getLineLastNonWhitespaceColumn(lineNumber: number): number; + + setEOL(newEOL: string): void; + applyEdits(rawOperations: editorCommon.IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult; } -export class ApplyEditResult { +export class ApplyEditsResult { constructor( public readonly reverseEdits: editorCommon.IIdentifiedSingleEditOperation[], @@ -38,7 +57,7 @@ export interface IInternalModelContentChange extends IModelContentChange { forceMoveMarkers: boolean; } -export class TextBuffer { +export class TextBuffer implements ITextBuffer { private _lines: string[]; private _BOM: string; @@ -140,7 +159,7 @@ export class TextBuffer { throw new Error('Unknown EOL preference'); } - public getValueInRange(range: Range, eol: editorCommon.EndOfLinePreference = editorCommon.EndOfLinePreference.TextDefined): string { + public getValueInRange(range: Range, eol: editorCommon.EndOfLinePreference): string { if (range.isEmpty()) { return ''; } @@ -163,7 +182,7 @@ export class TextBuffer { return resultLines.join(lineEnding); } - public getValueLengthInRange(range: Range, eol: editorCommon.EndOfLinePreference = editorCommon.EndOfLinePreference.TextDefined): number { + public getValueLengthInRange(range: Range, eol: editorCommon.EndOfLinePreference): number { if (range.isEmpty()) { return 0; } @@ -197,14 +216,6 @@ export class TextBuffer { return this._lines[lineNumber - 1].length; } - public getLineMinColumn(lineNumber: number): number { - return 1; - } - - public getLineMaxColumn(lineNumber: number): number { - return this._lines[lineNumber - 1].length + 1; - } - public getLineFirstNonWhitespaceColumn(lineNumber: number): number { const result = strings.firstNonWhitespaceIndex(this._lines[lineNumber - 1]); if (result === -1) { @@ -244,9 +255,9 @@ export class TextBuffer { return -r; } - public _applyEdits(rawOperations: editorCommon.IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditResult { + public applyEdits(rawOperations: editorCommon.IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult { if (rawOperations.length === 0) { - return new ApplyEditResult([], [], [], []); + return new ApplyEditsResult([], [], [], []); } let mightContainRTL = this._mightContainRTL; @@ -272,7 +283,7 @@ export class TextBuffer { identifier: op.identifier, range: validatedRange, rangeOffset: this.getOffsetAt(validatedRange.startLineNumber, validatedRange.startColumn), - rangeLength: this.getValueLengthInRange(validatedRange), + rangeLength: this.getValueLengthInRange(validatedRange, editorCommon.EndOfLinePreference.TextDefined), lines: op.text ? op.text.split(/\r\n|\r|\n/) : null, forceMoveMarkers: op.forceMoveMarkers, isAutoWhitespaceEdit: op.isAutoWhitespaceEdit || false @@ -327,7 +338,7 @@ export class TextBuffer { reverseOperations[i] = { identifier: op.identifier, range: reverseRange, - text: this.getValueInRange(op.range), + text: this.getValueInRange(op.range, editorCommon.EndOfLinePreference.TextDefined), forceMoveMarkers: op.forceMoveMarkers }; } @@ -361,7 +372,7 @@ export class TextBuffer { } } - return new ApplyEditResult( + return new ApplyEditsResult( reverseOperations, rawContentChanges, contentChanges, @@ -438,7 +449,7 @@ export class TextBuffer { identifier: operations[0].identifier, range: entireEditRange, rangeOffset: this.getOffsetAt(entireEditRange.startLineNumber, entireEditRange.startColumn), - rangeLength: this.getValueLengthInRange(entireEditRange), + rangeLength: this.getValueLengthInRange(entireEditRange, editorCommon.EndOfLinePreference.TextDefined), lines: result.join('').split('\n'), forceMoveMarkers: forceMoveMarkers, isAutoWhitespaceEdit: false @@ -448,9 +459,7 @@ export class TextBuffer { private _setLineContent(lineNumber: number, content: string, rawContentChanges: ModelRawChange[]): void { this._lines[lineNumber - 1] = content; this._lineStarts.changeValue(lineNumber - 1, content.length + this._EOL.length); - rawContentChanges.push( - new ModelRawLineChanged(lineNumber, content) - ); + rawContentChanges.push(new ModelRawLineChanged(lineNumber, content)); } private _doApplyEdits(operations: IValidatedEditOperation[]): [ModelRawChange[], IInternalModelContentChange[]] { @@ -484,7 +493,7 @@ export class TextBuffer { if (editLineNumber === startLineNumber || editLineNumber === endLineNumber) { const editStartColumn = (editLineNumber === startLineNumber ? startColumn : 1); - const editEndColumn = (editLineNumber === endLineNumber ? endColumn : this.getLineMaxColumn(editLineNumber)); + const editEndColumn = (editLineNumber === endLineNumber ? endColumn : this.getLineLength(editLineNumber) + 1); editText = ( this._lines[editLineNumber - 1].substring(0, editStartColumn - 1) @@ -502,15 +511,13 @@ export class TextBuffer { const spliceStartLineNumber = startLineNumber + editingLinesCnt; const endLineRemains = this._lines[endLineNumber - 1].substring(endColumn - 1); - this._lines.splice(spliceStartLineNumber, endLineNumber - spliceStartLineNumber); - this._lineStarts.removeValues(spliceStartLineNumber, endLineNumber - spliceStartLineNumber); - // Reconstruct first line this._setLineContent(spliceStartLineNumber, this._lines[spliceStartLineNumber - 1] + endLineRemains, rawContentChanges); - rawContentChanges.push( - new ModelRawLinesDeleted(spliceStartLineNumber + 1, endLineNumber) - ); + this._lines.splice(spliceStartLineNumber, endLineNumber - spliceStartLineNumber); + this._lineStarts.removeValues(spliceStartLineNumber, endLineNumber - spliceStartLineNumber); + + rawContentChanges.push(new ModelRawLinesDeleted(spliceStartLineNumber + 1, endLineNumber)); } if (editingLinesCnt < insertingLinesCnt) { @@ -539,9 +546,7 @@ export class TextBuffer { this._lines = arrays.arrayInsert(this._lines, startLineNumber + editingLinesCnt, newLines); this._lineStarts.insertValues(startLineNumber + editingLinesCnt, newLinesLengths); - rawContentChanges.push( - new ModelRawLinesInserted(spliceLineNumber + 1, startLineNumber + insertingLinesCnt, newLines) - ); + rawContentChanges.push(new ModelRawLinesInserted(spliceLineNumber + 1, startLineNumber + insertingLinesCnt, newLines)); } const contentChangeRange = new Range(startLineNumber, startColumn, endLineNumber, endColumn); @@ -559,7 +564,6 @@ export class TextBuffer { return [rawContentChanges, contentChanges]; } - /** * Assumes `operations` are validated and sorted ascending */ diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 8a71299da20..2ea97d286a6 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -16,7 +16,7 @@ import { TextModelSearch, SearchParams } from 'vs/editor/common/model/textModelS import { TextSource, ITextSource, IRawTextSource, RawTextSource } from 'vs/editor/common/model/textSource'; import { IModelContentChangedEvent, ModelRawContentChangedEvent, ModelRawFlush, ModelRawEOLChanged, IModelOptionsChangedEvent, InternalModelContentChangeEvent } from 'vs/editor/common/model/textModelEvents'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; -import { TextBuffer } from 'vs/editor/common/model/textBuffer'; +import { TextBuffer, ITextBuffer } from 'vs/editor/common/model/textBuffer'; const LIMIT_FIND_COUNT = 999; export const LONG_LINE_BOUNDARY = 10000; @@ -95,7 +95,7 @@ export class TextModel extends Disposable implements editorCommon.ITextModel { private readonly _shouldSimplifyMode: boolean; protected readonly _isTooLargeForTokenization: boolean; - protected _buffer: TextBuffer; + protected _buffer: ITextBuffer; constructor(rawTextSource: IRawTextSource, creationOptions: editorCommon.ITextModelCreationOptions) { super(); @@ -467,7 +467,7 @@ export class TextModel extends Disposable implements editorCommon.ITextModel { if (lineNumber < 1 || lineNumber > this.getLineCount()) { throw new Error('Illegal value ' + lineNumber + ' for `lineNumber`'); } - return this._buffer.getLineMaxColumn(lineNumber); + return this._buffer.getLineLength(lineNumber) + 1; } public getLineFirstNonWhitespaceColumn(lineNumber: number): number { -- GitLab