Skip to content

Commit aa66fbf

Browse files
committed
Avoid computing undo edits if not necessary
1 parent f4f93a6 commit aa66fbf

10 files changed

Lines changed: 41 additions & 32 deletions

File tree

src/vs/editor/common/model.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,9 +1092,11 @@ export interface ITextModel {
10921092
* Edit the model without adding the edits to the undo stack.
10931093
* This can have dire consequences on the undo stack! See @pushEditOperations for the preferred way.
10941094
* @param operations The edit operations.
1095-
* @return The inverse edit operations, that, when applied, will bring the model back to the previous state.
1095+
* @return If desired, the inverse edit operations, that, when applied, will bring the model back to the previous state.
10961096
*/
1097-
applyEdits(operations: IIdentifiedSingleEditOperation[]): IValidEditOperation[];
1097+
applyEdits(operations: IIdentifiedSingleEditOperation[]): void;
1098+
applyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: false): void;
1099+
applyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: true): IValidEditOperation[];
10981100

10991101
/**
11001102
* Change the end of line sequence without recording in the undo stack.
@@ -1299,7 +1301,7 @@ export interface ITextBuffer {
12991301
export class ApplyEditsResult {
13001302

13011303
constructor(
1302-
public readonly reverseEdits: IValidEditOperation[],
1304+
public readonly reverseEdits: IValidEditOperation[] | null,
13031305
public readonly changes: IInternalModelContentChange[],
13041306
public readonly trimAutoWhitespaceLineNumbers: number[] | null
13051307
) { }

src/vs/editor/common/model/editStack.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ export class EditStack {
326326

327327
public pushEditOperation(beforeCursorState: Selection[] | null, editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer | null): Selection[] | null {
328328
const editStackElement = this._getOrCreateEditStackElement(beforeCursorState);
329-
const inverseEditOperations = this._model.applyEdits(editOperations);
329+
const inverseEditOperations = this._model.applyEdits(editOperations, true);
330330
const afterCursorState = EditStack._computeCursorState(cursorStateComputer, inverseEditOperations);
331331
editStackElement.append(this._model, inverseEditOperations, getModelEOL(this._model), this._model.getAlternativeVersionId(), afterCursorState);
332332
return afterCursorState;

src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,20 @@ export class PieceTreeTextBuffer implements ITextBuffer {
261261
// Sort operations ascending
262262
operations.sort(PieceTreeTextBuffer._sortOpsAscending);
263263

264+
let hasTouchingRanges = false;
265+
for (let i = 0, count = operations.length - 1; i < count; i++) {
266+
let rangeEnd = operations[i].range.getEndPosition();
267+
let nextRangeStart = operations[i + 1].range.getStartPosition();
268+
269+
if (nextRangeStart.isBeforeOrEqual(rangeEnd)) {
270+
if (nextRangeStart.isBefore(rangeEnd)) {
271+
// overlapping ranges
272+
throw new Error('Overlapping ranges are not allowed!');
273+
}
274+
hasTouchingRanges = true;
275+
}
276+
}
277+
264278
if (canReduceOperations) {
265279
operations = this._reduceOperations(operations);
266280
}
@@ -289,24 +303,11 @@ export class PieceTreeTextBuffer implements ITextBuffer {
289303
}
290304
}
291305

292-
let reverseOperations: IReverseSingleEditOperation[] = [];
306+
let reverseOperations: IReverseSingleEditOperation[] | null = null;
293307
if (computeUndoEdits) {
294308

295-
let hasTouchingRanges = false;
296-
for (let i = 0, count = operations.length - 1; i < count; i++) {
297-
let rangeEnd = operations[i].range.getEndPosition();
298-
let nextRangeStart = operations[i + 1].range.getStartPosition();
299-
300-
if (nextRangeStart.isBeforeOrEqual(rangeEnd)) {
301-
if (nextRangeStart.isBefore(rangeEnd)) {
302-
// overlapping ranges
303-
throw new Error('Overlapping ranges are not allowed!');
304-
}
305-
hasTouchingRanges = true;
306-
}
307-
}
308-
309309
let reverseRangeDeltaOffset = 0;
310+
reverseOperations = [];
310311
for (let i = 0; i < operations.length; i++) {
311312
const op = operations[i];
312313
const reverseRange = reverseRanges[i];

src/vs/editor/common/model/textModel.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,18 +1330,22 @@ export class TextModel extends Disposable implements model.ITextModel {
13301330
}
13311331
}
13321332

1333-
public applyEdits(rawOperations: model.IIdentifiedSingleEditOperation[], computeUndoEdits: boolean = true): model.IValidEditOperation[] {
1333+
public applyEdits(operations: model.IIdentifiedSingleEditOperation[]): void;
1334+
public applyEdits(operations: model.IIdentifiedSingleEditOperation[], computeUndoEdits: false): void;
1335+
public applyEdits(operations: model.IIdentifiedSingleEditOperation[], computeUndoEdits: true): model.IValidEditOperation[];
1336+
public applyEdits(rawOperations: model.IIdentifiedSingleEditOperation[], computeUndoEdits: boolean = false): void | model.IValidEditOperation[] {
13341337
try {
13351338
this._onDidChangeDecorations.beginDeferredEmit();
13361339
this._eventEmitter.beginDeferredEmit();
1337-
return this._doApplyEdits(this._validateEditOperations(rawOperations), computeUndoEdits);
1340+
const operations = this._validateEditOperations(rawOperations);
1341+
return this._doApplyEdits(operations, computeUndoEdits);
13381342
} finally {
13391343
this._eventEmitter.endDeferredEmit();
13401344
this._onDidChangeDecorations.endDeferredEmit();
13411345
}
13421346
}
13431347

1344-
private _doApplyEdits(rawOperations: model.ValidAnnotatedEditOperation[], computeUndoEdits: boolean): model.IValidEditOperation[] {
1348+
private _doApplyEdits(rawOperations: model.ValidAnnotatedEditOperation[], computeUndoEdits: boolean): void | model.IValidEditOperation[] {
13451349

13461350
const oldLineCount = this._buffer.getLineCount();
13471351
const result = this._buffer.applyEdits(rawOperations, this._options.trimAutoWhitespace, computeUndoEdits);
@@ -1419,7 +1423,7 @@ export class TextModel extends Disposable implements model.ITextModel {
14191423
);
14201424
}
14211425

1422-
return result.reverseEdits;
1426+
return (result.reverseEdits === null ? undefined : result.reverseEdits);
14231427
}
14241428

14251429
public undo(): void {

src/vs/editor/test/common/model/editableTextModel.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1104,7 +1104,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => {
11041104
{ range: new Range(3, 1, 3, 6), text: null, },
11051105
{ range: new Range(2, 1, 3, 1), text: null, },
11061106
{ range: new Range(3, 6, 3, 6), text: '\nline2' }
1107-
]);
1107+
], true);
11081108

11091109
model.applyEdits(undoEdits);
11101110

src/vs/editor/test/common/model/editableTextModelTestUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ export function testApplyEditsWithSyncedModels(original: string[], edits: IIdent
1717

1818
assertSyncedModels(originalStr, (model, assertMirrorModels) => {
1919
// Apply edits & collect inverse edits
20-
let inverseEdits = model.applyEdits(edits);
20+
let inverseEdits = model.applyEdits(edits, true);
2121

2222
// Assert edits produced expected result
2323
assert.deepEqual(model.getValue(EndOfLinePreference.LF), expectedStr);
2424

2525
assertMirrorModels();
2626

2727
// Apply the inverse edits
28-
let inverseInverseEdits = model.applyEdits(inverseEdits);
28+
let inverseInverseEdits = model.applyEdits(inverseEdits, true);
2929

3030
// Assert the inverse edits brought back model to original state
3131
assert.deepEqual(model.getValue(EndOfLinePreference.LF), originalStr);

src/vs/editor/test/common/model/model.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ suite('Editor Model - Model', () => {
330330
let res = thisModel.applyEdits([
331331
{ range: new Range(2, 1, 2, 1), text: 'a' },
332332
{ range: new Range(1, 1, 1, 1), text: 'b' },
333-
]);
333+
], true);
334334

335335
assert.deepEqual(res[0].range, new Range(2, 1, 2, 2));
336336
assert.deepEqual(res[1].range, new Range(1, 1, 1, 2));

src/vs/editor/test/common/model/modelEditOperation.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ suite('Editor Model - Model Edit Operation', () => {
5050
function assertSingleEditOp(singleEditOp: IIdentifiedSingleEditOperation, editedLines: string[]) {
5151
let editOp = [singleEditOp];
5252

53-
let inverseEditOp = model.applyEdits(editOp);
53+
let inverseEditOp = model.applyEdits(editOp, true);
5454

5555
assert.equal(model.getLineCount(), editedLines.length);
5656
for (let i = 0; i < editedLines.length; i++) {
5757
assert.equal(model.getLineContent(i + 1), editedLines[i]);
5858
}
5959

60-
let originalOp = model.applyEdits(inverseEditOp);
60+
let originalOp = model.applyEdits(inverseEditOp, true);
6161

6262
assert.equal(model.getLineCount(), 5);
6363
assert.equal(model.getLineContent(1), LINE1);

src/vs/monaco.d.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,9 +1902,11 @@ declare namespace monaco.editor {
19021902
* Edit the model without adding the edits to the undo stack.
19031903
* This can have dire consequences on the undo stack! See @pushEditOperations for the preferred way.
19041904
* @param operations The edit operations.
1905-
* @return The inverse edit operations, that, when applied, will bring the model back to the previous state.
1905+
* @return If desired, the inverse edit operations, that, when applied, will bring the model back to the previous state.
19061906
*/
1907-
applyEdits(operations: IIdentifiedSingleEditOperation[]): IValidEditOperation[];
1907+
applyEdits(operations: IIdentifiedSingleEditOperation[]): void;
1908+
applyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: false): void;
1909+
applyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: true): IValidEditOperation[];
19081910
/**
19091911
* Change the end of line sequence without recording in the undo stack.
19101912
* This can have dire consequences on the undo stack! See @pushEOL for the preferred way.

src/vs/workbench/contrib/bulkEdit/browser/bulkEditPreview.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ export class BulkEditPreviewProvider implements ITextModelContentProvider {
399399
}
400400
// apply new edits and keep (future) undo edits
401401
const newEdits = this._operations.getFileEdits(uri);
402-
const newUndoEdits = model.applyEdits(newEdits);
402+
const newUndoEdits = model.applyEdits(newEdits, true);
403403
this._modelPreviewEdits.set(model.id, newUndoEdits);
404404
}
405405

0 commit comments

Comments
 (0)