未验证 提交 aa66fbf2 编写于 作者: A Alex Dima

Avoid computing undo edits if not necessary

上级 f4f93a67
......@@ -1092,9 +1092,11 @@ export interface ITextModel {
* Edit the model without adding the edits to the undo stack.
* This can have dire consequences on the undo stack! See @pushEditOperations for the preferred way.
* @param operations The edit operations.
* @return The inverse edit operations, that, when applied, will bring the model back to the previous state.
* @return If desired, the inverse edit operations, that, when applied, will bring the model back to the previous state.
*/
applyEdits(operations: IIdentifiedSingleEditOperation[]): IValidEditOperation[];
applyEdits(operations: IIdentifiedSingleEditOperation[]): void;
applyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: false): void;
applyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: true): IValidEditOperation[];
/**
* Change the end of line sequence without recording in the undo stack.
......@@ -1299,7 +1301,7 @@ export interface ITextBuffer {
export class ApplyEditsResult {
constructor(
public readonly reverseEdits: IValidEditOperation[],
public readonly reverseEdits: IValidEditOperation[] | null,
public readonly changes: IInternalModelContentChange[],
public readonly trimAutoWhitespaceLineNumbers: number[] | null
) { }
......
......@@ -326,7 +326,7 @@ export class EditStack {
public pushEditOperation(beforeCursorState: Selection[] | null, editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer | null): Selection[] | null {
const editStackElement = this._getOrCreateEditStackElement(beforeCursorState);
const inverseEditOperations = this._model.applyEdits(editOperations);
const inverseEditOperations = this._model.applyEdits(editOperations, true);
const afterCursorState = EditStack._computeCursorState(cursorStateComputer, inverseEditOperations);
editStackElement.append(this._model, inverseEditOperations, getModelEOL(this._model), this._model.getAlternativeVersionId(), afterCursorState);
return afterCursorState;
......
......@@ -261,6 +261,20 @@ 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.isBeforeOrEqual(rangeEnd)) {
if (nextRangeStart.isBefore(rangeEnd)) {
// overlapping ranges
throw new Error('Overlapping ranges are not allowed!');
}
hasTouchingRanges = true;
}
}
if (canReduceOperations) {
operations = this._reduceOperations(operations);
}
......@@ -289,24 +303,11 @@ export class PieceTreeTextBuffer implements ITextBuffer {
}
}
let reverseOperations: IReverseSingleEditOperation[] = [];
let reverseOperations: IReverseSingleEditOperation[] | null = null;
if (computeUndoEdits) {
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.isBeforeOrEqual(rangeEnd)) {
if (nextRangeStart.isBefore(rangeEnd)) {
// overlapping ranges
throw new Error('Overlapping ranges are not allowed!');
}
hasTouchingRanges = true;
}
}
let reverseRangeDeltaOffset = 0;
reverseOperations = [];
for (let i = 0; i < operations.length; i++) {
const op = operations[i];
const reverseRange = reverseRanges[i];
......
......@@ -1330,18 +1330,22 @@ export class TextModel extends Disposable implements model.ITextModel {
}
}
public applyEdits(rawOperations: model.IIdentifiedSingleEditOperation[], computeUndoEdits: boolean = true): model.IValidEditOperation[] {
public applyEdits(operations: model.IIdentifiedSingleEditOperation[]): void;
public applyEdits(operations: model.IIdentifiedSingleEditOperation[], computeUndoEdits: false): void;
public applyEdits(operations: model.IIdentifiedSingleEditOperation[], computeUndoEdits: true): model.IValidEditOperation[];
public applyEdits(rawOperations: model.IIdentifiedSingleEditOperation[], computeUndoEdits: boolean = false): void | model.IValidEditOperation[] {
try {
this._onDidChangeDecorations.beginDeferredEmit();
this._eventEmitter.beginDeferredEmit();
return this._doApplyEdits(this._validateEditOperations(rawOperations), computeUndoEdits);
const operations = this._validateEditOperations(rawOperations);
return this._doApplyEdits(operations, computeUndoEdits);
} finally {
this._eventEmitter.endDeferredEmit();
this._onDidChangeDecorations.endDeferredEmit();
}
}
private _doApplyEdits(rawOperations: model.ValidAnnotatedEditOperation[], computeUndoEdits: boolean): model.IValidEditOperation[] {
private _doApplyEdits(rawOperations: model.ValidAnnotatedEditOperation[], computeUndoEdits: boolean): void | model.IValidEditOperation[] {
const oldLineCount = this._buffer.getLineCount();
const result = this._buffer.applyEdits(rawOperations, this._options.trimAutoWhitespace, computeUndoEdits);
......@@ -1419,7 +1423,7 @@ export class TextModel extends Disposable implements model.ITextModel {
);
}
return result.reverseEdits;
return (result.reverseEdits === null ? undefined : result.reverseEdits);
}
public undo(): void {
......
......@@ -1104,7 +1104,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => {
{ range: new Range(3, 1, 3, 6), text: null, },
{ range: new Range(2, 1, 3, 1), text: null, },
{ range: new Range(3, 6, 3, 6), text: '\nline2' }
]);
], true);
model.applyEdits(undoEdits);
......
......@@ -17,7 +17,7 @@ export function testApplyEditsWithSyncedModels(original: string[], edits: IIdent
assertSyncedModels(originalStr, (model, assertMirrorModels) => {
// Apply edits & collect inverse edits
let inverseEdits = model.applyEdits(edits);
let inverseEdits = model.applyEdits(edits, true);
// Assert edits produced expected result
assert.deepEqual(model.getValue(EndOfLinePreference.LF), expectedStr);
......@@ -25,7 +25,7 @@ export function testApplyEditsWithSyncedModels(original: string[], edits: IIdent
assertMirrorModels();
// Apply the inverse edits
let inverseInverseEdits = model.applyEdits(inverseEdits);
let inverseInverseEdits = model.applyEdits(inverseEdits, true);
// Assert the inverse edits brought back model to original state
assert.deepEqual(model.getValue(EndOfLinePreference.LF), originalStr);
......
......@@ -330,7 +330,7 @@ suite('Editor Model - Model', () => {
let res = thisModel.applyEdits([
{ range: new Range(2, 1, 2, 1), text: 'a' },
{ range: new Range(1, 1, 1, 1), text: 'b' },
]);
], true);
assert.deepEqual(res[0].range, new Range(2, 1, 2, 2));
assert.deepEqual(res[1].range, new Range(1, 1, 1, 2));
......
......@@ -50,14 +50,14 @@ suite('Editor Model - Model Edit Operation', () => {
function assertSingleEditOp(singleEditOp: IIdentifiedSingleEditOperation, editedLines: string[]) {
let editOp = [singleEditOp];
let inverseEditOp = model.applyEdits(editOp);
let inverseEditOp = model.applyEdits(editOp, true);
assert.equal(model.getLineCount(), editedLines.length);
for (let i = 0; i < editedLines.length; i++) {
assert.equal(model.getLineContent(i + 1), editedLines[i]);
}
let originalOp = model.applyEdits(inverseEditOp);
let originalOp = model.applyEdits(inverseEditOp, true);
assert.equal(model.getLineCount(), 5);
assert.equal(model.getLineContent(1), LINE1);
......
......@@ -1902,9 +1902,11 @@ declare namespace monaco.editor {
* Edit the model without adding the edits to the undo stack.
* This can have dire consequences on the undo stack! See @pushEditOperations for the preferred way.
* @param operations The edit operations.
* @return The inverse edit operations, that, when applied, will bring the model back to the previous state.
* @return If desired, the inverse edit operations, that, when applied, will bring the model back to the previous state.
*/
applyEdits(operations: IIdentifiedSingleEditOperation[]): IValidEditOperation[];
applyEdits(operations: IIdentifiedSingleEditOperation[]): void;
applyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: false): void;
applyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: true): IValidEditOperation[];
/**
* Change the end of line sequence without recording in the undo stack.
* This can have dire consequences on the undo stack! See @pushEOL for the preferred way.
......
......@@ -399,7 +399,7 @@ export class BulkEditPreviewProvider implements ITextModelContentProvider {
}
// apply new edits and keep (future) undo edits
const newEdits = this._operations.getFileEdits(uri);
const newUndoEdits = model.applyEdits(newEdits);
const newUndoEdits = model.applyEdits(newEdits, true);
this._modelPreviewEdits.set(model.id, newUndoEdits);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册