mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-11 02:32:35 -05:00
Merge VS Code 1.23.1 (#1520)
This commit is contained in:
@@ -9,8 +9,11 @@ import { CharCode } from 'vs/base/common/charCode';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { ITextSnapshot } from 'vs/platform/files/common/files';
|
||||
import { leftest, righttest, updateTreeMetadata, rbDelete, fixInsert, NodeColor, SENTINEL, TreeNode } from 'vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase';
|
||||
import { SearchData, isValidMatch, Searcher, createFindMatch } from 'vs/editor/common/model/textModelSearch';
|
||||
import { FindMatch } from 'vs/editor/common/model';
|
||||
|
||||
// const lfRegex = new RegExp(/\r\n|\r|\n/g);
|
||||
export const AverageBufferSize = 65535;
|
||||
|
||||
export function createUintArray(arr: number[]): Uint32Array | Uint16Array {
|
||||
let r;
|
||||
@@ -33,7 +36,7 @@ export class LineStarts {
|
||||
) { }
|
||||
}
|
||||
|
||||
export function createLineStartsFast(str: string, readonly: boolean = true): Uint32Array | number[] {
|
||||
export function createLineStartsFast(str: string, readonly: boolean = true): Uint32Array | Uint16Array | number[] {
|
||||
let r: number[] = [0], rLength = 1;
|
||||
|
||||
for (let i = 0, len = str.length; i < len; i++) {
|
||||
@@ -309,7 +312,7 @@ export class PieceTreeBase {
|
||||
}
|
||||
|
||||
normalizeEOL(eol: '\r\n' | '\n') {
|
||||
let averageBufferSize = 65536;
|
||||
let averageBufferSize = AverageBufferSize;
|
||||
let min = averageBufferSize - Math.floor(averageBufferSize / 3);
|
||||
let max = min * 2;
|
||||
|
||||
@@ -446,7 +449,7 @@ export class PieceTreeBase {
|
||||
return new Position(1, 1);
|
||||
}
|
||||
|
||||
public getValueInRange(range: Range): string {
|
||||
public getValueInRange(range: Range, eol?: string): string {
|
||||
if (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) {
|
||||
return '';
|
||||
}
|
||||
@@ -454,7 +457,21 @@ export class PieceTreeBase {
|
||||
let startPosition = this.nodeAt2(range.startLineNumber, range.startColumn);
|
||||
let endPosition = this.nodeAt2(range.endLineNumber, range.endColumn);
|
||||
|
||||
return this.getValueInRange2(startPosition, endPosition);
|
||||
let value = this.getValueInRange2(startPosition, endPosition);
|
||||
if (eol) {
|
||||
if (eol !== this._EOL || !this._EOLNormalized) {
|
||||
return value.replace(/\r\n|\r|\n/g, eol);
|
||||
}
|
||||
|
||||
if (eol === this.getEOL() && this._EOLNormalized) {
|
||||
if (eol === '\r\n') {
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return value.replace(/\r\n|\r|\n/g, eol);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public getValueInRange2(startPosition: NodePosition, endPosition: NodePosition): string {
|
||||
@@ -520,11 +537,23 @@ export class PieceTreeBase {
|
||||
|
||||
public getLineCharCode(lineNumber: number, index: number): number {
|
||||
let nodePos = this.nodeAt2(lineNumber, index + 1);
|
||||
let buffer = this._buffers[nodePos.node.piece.bufferIndex];
|
||||
let startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);
|
||||
let targetOffset = startOffset + index;
|
||||
if (nodePos.remainder === nodePos.node.piece.length) {
|
||||
// the char we want to fetch is at the head of next node.
|
||||
let matchingNode = nodePos.node.next();
|
||||
if (!matchingNode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return buffer.buffer.charCodeAt(targetOffset);
|
||||
let buffer = this._buffers[matchingNode.piece.bufferIndex];
|
||||
let startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);
|
||||
return buffer.buffer.charCodeAt(startOffset);
|
||||
} else {
|
||||
let buffer = this._buffers[nodePos.node.piece.bufferIndex];
|
||||
let startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);
|
||||
let targetOffset = startOffset + nodePos.remainder;
|
||||
|
||||
return buffer.buffer.charCodeAt(targetOffset);
|
||||
}
|
||||
}
|
||||
|
||||
public getLineLength(lineNumber: number): number {
|
||||
@@ -535,6 +564,151 @@ export class PieceTreeBase {
|
||||
return this.getOffsetAt(lineNumber + 1, 1) - this.getOffsetAt(lineNumber, 1) - this._EOLLength;
|
||||
}
|
||||
|
||||
public findMatchesInNode(node: TreeNode, searcher: Searcher, startLineNumber: number, startColumn: number, startCursor: BufferCursor, endCursor: BufferCursor, searchData: SearchData, captureMatches: boolean, limitResultCount: number, resultLen: number, result: FindMatch[]) {
|
||||
let buffer = this._buffers[node.piece.bufferIndex];
|
||||
let startOffsetInBuffer = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);
|
||||
let start = this.offsetInBuffer(node.piece.bufferIndex, startCursor);
|
||||
let end = this.offsetInBuffer(node.piece.bufferIndex, endCursor);
|
||||
|
||||
let m: RegExpExecArray;
|
||||
// Reset regex to search from the beginning
|
||||
searcher.reset(start);
|
||||
let ret: BufferCursor = { line: 0, column: 0 };
|
||||
|
||||
do {
|
||||
m = searcher.next(buffer.buffer);
|
||||
|
||||
if (m) {
|
||||
if (m.index >= end) {
|
||||
return resultLen;
|
||||
}
|
||||
this.positionInBuffer(node, m.index - startOffsetInBuffer, ret);
|
||||
let lineFeedCnt = this.getLineFeedCnt(node.piece.bufferIndex, startCursor, ret);
|
||||
let retStartColumn = ret.line === startCursor.line ? ret.column - startCursor.column + startColumn : ret.column + 1;
|
||||
let retEndColumn = retStartColumn + m[0].length;
|
||||
result[resultLen++] = createFindMatch(new Range(startLineNumber + lineFeedCnt, retStartColumn, startLineNumber + lineFeedCnt, retEndColumn), m, captureMatches);
|
||||
|
||||
if (m.index + m[0].length >= end) {
|
||||
return resultLen;
|
||||
}
|
||||
if (resultLen >= limitResultCount) {
|
||||
return resultLen;
|
||||
}
|
||||
}
|
||||
|
||||
} while (m);
|
||||
|
||||
return resultLen;
|
||||
}
|
||||
|
||||
public findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[] {
|
||||
const result: FindMatch[] = [];
|
||||
let resultLen = 0;
|
||||
const searcher = new Searcher(searchData.wordSeparators, searchData.regex);
|
||||
|
||||
let startPostion = this.nodeAt2(searchRange.startLineNumber, searchRange.startColumn);
|
||||
if (startPostion === null) {
|
||||
return [];
|
||||
}
|
||||
let endPosition = this.nodeAt2(searchRange.endLineNumber, searchRange.endColumn);
|
||||
if (endPosition === null) {
|
||||
return [];
|
||||
}
|
||||
let start = this.positionInBuffer(startPostion.node, startPostion.remainder);
|
||||
let end = this.positionInBuffer(endPosition.node, endPosition.remainder);
|
||||
|
||||
if (startPostion.node === endPosition.node) {
|
||||
this.findMatchesInNode(startPostion.node, searcher, searchRange.startLineNumber, searchRange.startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
let startLineNumber = searchRange.startLineNumber;
|
||||
|
||||
let currentNode = startPostion.node;
|
||||
while (currentNode !== endPosition.node) {
|
||||
let lineBreakCnt = this.getLineFeedCnt(currentNode.piece.bufferIndex, start, currentNode.piece.end);
|
||||
|
||||
if (lineBreakCnt >= 1) {
|
||||
// last line break position
|
||||
let lineStarts = this._buffers[currentNode.piece.bufferIndex].lineStarts;
|
||||
let startOffsetInBuffer = this.offsetInBuffer(currentNode.piece.bufferIndex, currentNode.piece.start);
|
||||
let nextLineStartOffset = lineStarts[start.line + lineBreakCnt];
|
||||
let startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;
|
||||
resultLen = this.findMatchesInNode(currentNode, searcher, startLineNumber, startColumn, start, this.positionInBuffer(currentNode, nextLineStartOffset - startOffsetInBuffer), searchData, captureMatches, limitResultCount, resultLen, result);
|
||||
|
||||
if (resultLen >= limitResultCount) {
|
||||
return result;
|
||||
}
|
||||
|
||||
startLineNumber += lineBreakCnt;
|
||||
}
|
||||
|
||||
let startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;
|
||||
// search for the remaining content
|
||||
if (startLineNumber === searchRange.endLineNumber) {
|
||||
const text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);
|
||||
resultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);
|
||||
return result;
|
||||
}
|
||||
|
||||
resultLen = this._findMatchesInLine(searchData, searcher, this.getLineContent(startLineNumber).substr(startColumn), startLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);
|
||||
|
||||
if (resultLen >= limitResultCount) {
|
||||
return result;
|
||||
}
|
||||
|
||||
startLineNumber++;
|
||||
startPostion = this.nodeAt2(startLineNumber, 1);
|
||||
currentNode = startPostion.node;
|
||||
start = this.positionInBuffer(startPostion.node, startPostion.remainder);
|
||||
}
|
||||
|
||||
if (startLineNumber === searchRange.endLineNumber) {
|
||||
let startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;
|
||||
const text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);
|
||||
resultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);
|
||||
return result;
|
||||
}
|
||||
|
||||
let startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;
|
||||
resultLen = this.findMatchesInNode(endPosition.node, searcher, startLineNumber, startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private _findMatchesInLine(searchData: SearchData, searcher: Searcher, text: string, lineNumber: number, deltaOffset: number, resultLen: number, result: FindMatch[], captureMatches: boolean, limitResultCount: number): number {
|
||||
const wordSeparators = searchData.wordSeparators;
|
||||
if (!captureMatches && searchData.simpleSearch) {
|
||||
const searchString = searchData.simpleSearch;
|
||||
const searchStringLen = searchString.length;
|
||||
const textLength = text.length;
|
||||
|
||||
let lastMatchIndex = -searchStringLen;
|
||||
while ((lastMatchIndex = text.indexOf(searchString, lastMatchIndex + searchStringLen)) !== -1) {
|
||||
if (!wordSeparators || isValidMatch(wordSeparators, text, textLength, lastMatchIndex, searchStringLen)) {
|
||||
result[resultLen++] = new FindMatch(new Range(lineNumber, lastMatchIndex + 1 + deltaOffset, lineNumber, lastMatchIndex + 1 + searchStringLen + deltaOffset), null);
|
||||
if (resultLen >= limitResultCount) {
|
||||
return resultLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultLen;
|
||||
}
|
||||
|
||||
let m: RegExpExecArray;
|
||||
// Reset regex to search from the beginning
|
||||
searcher.reset(0);
|
||||
do {
|
||||
m = searcher.next(text);
|
||||
if (m) {
|
||||
result[resultLen++] = createFindMatch(new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset), m, captureMatches);
|
||||
if (resultLen >= limitResultCount) {
|
||||
return resultLen;
|
||||
}
|
||||
}
|
||||
} while (m);
|
||||
return resultLen;
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Piece Table
|
||||
@@ -551,7 +725,8 @@ export class PieceTreeBase {
|
||||
if (node.piece.bufferIndex === 0 &&
|
||||
piece.end.line === this._lastChangeBufferPos.line &&
|
||||
piece.end.column === this._lastChangeBufferPos.column &&
|
||||
(nodeStartOffset + piece.length === offset)
|
||||
(nodeStartOffset + piece.length === offset) &&
|
||||
value.length < AverageBufferSize
|
||||
) {
|
||||
// changed buffer
|
||||
this.appendToNode(node, value);
|
||||
@@ -608,19 +783,27 @@ export class PieceTreeBase {
|
||||
this.deleteNodeTail(node, insertPosInBuffer);
|
||||
}
|
||||
|
||||
let newPiece = this.createNewPiece(value);
|
||||
let newPieces = this.createNewPieces(value);
|
||||
if (newRightPiece.length > 0) {
|
||||
this.rbInsertRight(node, newRightPiece);
|
||||
}
|
||||
this.rbInsertRight(node, newPiece);
|
||||
|
||||
let tmpNode = node;
|
||||
for (let k = 0; k < newPieces.length; k++) {
|
||||
tmpNode = this.rbInsertRight(tmpNode, newPieces[k]);
|
||||
}
|
||||
this.deleteNodes(nodesToDel);
|
||||
} else {
|
||||
this.insertContentToNodeRight(value, node);
|
||||
}
|
||||
} else {
|
||||
// insert new node
|
||||
let piece = this.createNewPiece(value);
|
||||
this.rbInsertLeft(null, piece);
|
||||
let pieces = this.createNewPieces(value);
|
||||
let node = this.rbInsertLeft(null, pieces[0]);
|
||||
|
||||
for (let k = 1; k < pieces.length; k++) {
|
||||
node = this.rbInsertRight(node, pieces[k]);
|
||||
}
|
||||
}
|
||||
|
||||
// todo, this is too brutal. Total line feed count should be updated the same way as lf_left.
|
||||
@@ -726,8 +909,11 @@ export class PieceTreeBase {
|
||||
}
|
||||
}
|
||||
|
||||
let newPiece = this.createNewPiece(value);
|
||||
let newNode = this.rbInsertLeft(node, newPiece);
|
||||
let newPieces = this.createNewPieces(value);
|
||||
let newNode = this.rbInsertLeft(node, newPieces[newPieces.length - 1]);
|
||||
for (let k = newPieces.length - 2; k >= 0; k--) {
|
||||
newNode = this.rbInsertLeft(newNode, newPieces[k]);
|
||||
}
|
||||
this.validateCRLFWithPrevNode(newNode);
|
||||
this.deleteNodes(nodesToDel);
|
||||
}
|
||||
@@ -739,12 +925,18 @@ export class PieceTreeBase {
|
||||
value += '\n';
|
||||
}
|
||||
|
||||
let newPiece = this.createNewPiece(value);
|
||||
let newNode = this.rbInsertRight(node, newPiece);
|
||||
let newPieces = this.createNewPieces(value);
|
||||
let newNode = this.rbInsertRight(node, newPieces[0]);
|
||||
let tmpNode = newNode;
|
||||
|
||||
for (let k = 1; k < newPieces.length; k++) {
|
||||
tmpNode = this.rbInsertRight(tmpNode, newPieces[k]);
|
||||
}
|
||||
|
||||
this.validateCRLFWithPrevNode(newNode);
|
||||
}
|
||||
|
||||
positionInBuffer(node: TreeNode, remainder: number): BufferCursor {
|
||||
positionInBuffer(node: TreeNode, remainder: number, ret?: BufferCursor): BufferCursor {
|
||||
let piece = node.piece;
|
||||
let bufferIndex = node.piece.bufferIndex;
|
||||
let lineStarts = this._buffers[bufferIndex].lineStarts;
|
||||
@@ -780,6 +972,12 @@ export class PieceTreeBase {
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
ret.line = mid;
|
||||
ret.column = offset - midStart;
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
line: mid,
|
||||
column: offset - midStart
|
||||
@@ -827,7 +1025,47 @@ export class PieceTreeBase {
|
||||
}
|
||||
}
|
||||
|
||||
createNewPiece(text: string): Piece {
|
||||
createNewPieces(text: string): Piece[] {
|
||||
if (text.length > AverageBufferSize) {
|
||||
// the content is large, operations like substring, charCode becomes slow
|
||||
// so here we split it into smaller chunks, just like what we did for CR/LF normalization
|
||||
let newPieces = [];
|
||||
while (text.length > AverageBufferSize) {
|
||||
const lastChar = text.charCodeAt(AverageBufferSize - 1);
|
||||
let splitText;
|
||||
if (lastChar === CharCode.CarriageReturn || (lastChar >= 0xd800 && lastChar <= 0xdbff)) {
|
||||
// last character is \r or a high surrogate => keep it back
|
||||
splitText = text.substring(0, AverageBufferSize - 1);
|
||||
text = text.substring(AverageBufferSize - 1);
|
||||
} else {
|
||||
splitText = text.substring(0, AverageBufferSize);
|
||||
text = text.substring(AverageBufferSize);
|
||||
}
|
||||
|
||||
let lineStarts = createLineStartsFast(splitText);
|
||||
newPieces.push(new Piece(
|
||||
this._buffers.length, /* buffer index */
|
||||
{ line: 0, column: 0 },
|
||||
{ line: lineStarts.length - 1, column: splitText.length - lineStarts[lineStarts.length - 1] },
|
||||
lineStarts.length - 1,
|
||||
splitText.length
|
||||
));
|
||||
this._buffers.push(new StringBuffer(splitText, lineStarts));
|
||||
}
|
||||
|
||||
let lineStarts = createLineStartsFast(text);
|
||||
newPieces.push(new Piece(
|
||||
this._buffers.length, /* buffer index */
|
||||
{ line: 0, column: 0 },
|
||||
{ line: lineStarts.length - 1, column: text.length - lineStarts[lineStarts.length - 1] },
|
||||
lineStarts.length - 1,
|
||||
text.length
|
||||
));
|
||||
this._buffers.push(new StringBuffer(text, lineStarts));
|
||||
|
||||
return newPieces;
|
||||
}
|
||||
|
||||
let startOffset = this._buffers[0].buffer.length;
|
||||
const lineStarts = createLineStartsFast(text, false);
|
||||
|
||||
@@ -862,14 +1100,14 @@ export class PieceTreeBase {
|
||||
let endColumn = endOffset - this._buffers[0].lineStarts[endIndex];
|
||||
let endPos = { line: endIndex, column: endColumn };
|
||||
let newPiece = new Piece(
|
||||
0,
|
||||
0, /** todo */
|
||||
start,
|
||||
endPos,
|
||||
this.getLineFeedCnt(0, start, endPos),
|
||||
endOffset - startOffset
|
||||
);
|
||||
this._lastChangeBufferPos = endPos;
|
||||
return newPiece;
|
||||
return [newPiece];
|
||||
}
|
||||
|
||||
getLinesRawContent(): string {
|
||||
@@ -1352,8 +1590,8 @@ export class PieceTreeBase {
|
||||
}
|
||||
|
||||
// create new piece which contains \r\n
|
||||
let piece = this.createNewPiece('\r\n');
|
||||
this.rbInsertRight(prev, piece);
|
||||
let pieces = this.createNewPieces('\r\n');
|
||||
this.rbInsertRight(prev, pieces[0]);
|
||||
// delete empty nodes
|
||||
|
||||
for (let i = 0; i < nodesToDel.length; i++) {
|
||||
|
||||
@@ -7,10 +7,25 @@
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { IValidatedEditOperation } from 'vs/editor/common/model/linesTextBuffer/linesTextBuffer';
|
||||
import { PieceTreeBase, StringBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase';
|
||||
import { IIdentifiedSingleEditOperation, EndOfLinePreference, ITextBuffer, ApplyEditsResult, IInternalModelContentChange } from 'vs/editor/common/model';
|
||||
import { IIdentifiedSingleEditOperation, EndOfLinePreference, ITextBuffer, ApplyEditsResult, IInternalModelContentChange, FindMatch, ISingleEditOperationIdentifier } from 'vs/editor/common/model';
|
||||
import { ITextSnapshot } from 'vs/platform/files/common/files';
|
||||
import { SearchData } from 'vs/editor/common/model/textModelSearch';
|
||||
|
||||
export interface IValidatedEditOperation {
|
||||
sortIndex: number;
|
||||
identifier: ISingleEditOperationIdentifier;
|
||||
range: Range;
|
||||
rangeOffset: number;
|
||||
rangeLength: number;
|
||||
lines: string[];
|
||||
forceMoveMarkers: boolean;
|
||||
isAutoWhitespaceEdit: boolean;
|
||||
}
|
||||
|
||||
export interface IReverseSingleEditOperation extends IIdentifiedSingleEditOperation {
|
||||
sortIndex: number;
|
||||
}
|
||||
|
||||
export class PieceTreeTextBuffer implements ITextBuffer {
|
||||
private _pieceTree: PieceTreeBase;
|
||||
@@ -76,8 +91,7 @@ export class PieceTreeTextBuffer implements ITextBuffer {
|
||||
}
|
||||
|
||||
const lineEnding = this._getEndOfLine(eol);
|
||||
const text = this._pieceTree.getValueInRange(range);
|
||||
return text.replace(/\r\n|\r|\n/g, lineEnding);
|
||||
return this._pieceTree.getValueInRange(range, lineEnding);
|
||||
}
|
||||
|
||||
public getValueLengthInRange(range: Range, eol: EndOfLinePreference = EndOfLinePreference.TextDefined): number {
|
||||
@@ -192,13 +206,17 @@ export class PieceTreeTextBuffer implements ITextBuffer {
|
||||
// Sort operations ascending
|
||||
operations.sort(PieceTreeTextBuffer._sortOpsAscending);
|
||||
|
||||
let hasTouchingRanges = false;
|
||||
for (let i = 0, count = operations.length - 1; i < count; i++) {
|
||||
let rangeEnd = operations[i].range.getEndPosition();
|
||||
let nextRangeStart = operations[i + 1].range.getStartPosition();
|
||||
|
||||
if (nextRangeStart.isBefore(rangeEnd)) {
|
||||
// overlapping ranges
|
||||
throw new Error('Overlapping ranges are not allowed!');
|
||||
if (nextRangeStart.isBeforeOrEqual(rangeEnd)) {
|
||||
if (nextRangeStart.isBefore(rangeEnd)) {
|
||||
// overlapping ranges
|
||||
throw new Error('Overlapping ranges are not allowed!');
|
||||
}
|
||||
hasTouchingRanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,12 +247,13 @@ export class PieceTreeTextBuffer implements ITextBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
let reverseOperations: IIdentifiedSingleEditOperation[] = [];
|
||||
let reverseOperations: IReverseSingleEditOperation[] = [];
|
||||
for (let i = 0; i < operations.length; i++) {
|
||||
let op = operations[i];
|
||||
let reverseRange = reverseRanges[i];
|
||||
|
||||
reverseOperations[i] = {
|
||||
sortIndex: op.sortIndex,
|
||||
identifier: op.identifier,
|
||||
range: reverseRange,
|
||||
text: this.getValueInRange(op.range),
|
||||
@@ -242,6 +261,11 @@ export class PieceTreeTextBuffer implements ITextBuffer {
|
||||
};
|
||||
}
|
||||
|
||||
// Can only sort reverse operations when the order is not significant
|
||||
if (!hasTouchingRanges) {
|
||||
reverseOperations.sort((a, b) => a.sortIndex - b.sortIndex);
|
||||
}
|
||||
|
||||
this._mightContainRTL = mightContainRTL;
|
||||
this._mightContainNonBasicASCII = mightContainNonBasicASCII;
|
||||
|
||||
@@ -279,9 +303,9 @@ export class PieceTreeTextBuffer implements ITextBuffer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform operations such that they represent the same logic edit,
|
||||
* but that they also do not cause OOM crashes.
|
||||
*/
|
||||
* Transform operations such that they represent the same logic edit,
|
||||
* but that they also do not cause OOM crashes.
|
||||
*/
|
||||
private _reduceOperations(operations: IValidatedEditOperation[]): IValidatedEditOperation[] {
|
||||
if (operations.length < 1000) {
|
||||
// We know from empirical testing that a thousand edits work fine regardless of their shape.
|
||||
@@ -410,6 +434,10 @@ export class PieceTreeTextBuffer implements ITextBuffer {
|
||||
return contentChanges;
|
||||
}
|
||||
|
||||
findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[] {
|
||||
return this._pieceTree.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount);
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region helper
|
||||
|
||||
Reference in New Issue
Block a user