diff --git a/src/vs/editor/common/model/mirrorTextModel.ts b/src/vs/editor/common/model/mirrorTextModel.ts index 26a31412fa732..4fefa551a1aca 100644 --- a/src/vs/editor/common/model/mirrorTextModel.ts +++ b/src/vs/editor/common/model/mirrorTextModel.ts @@ -23,6 +23,14 @@ export interface IModelChangedEvent { * The new version id the model has transitioned to. */ readonly versionId: number; + /** + * Flag that indicates that this event was generated while undoing. + */ + readonly isUndoing: boolean; + /** + * Flag that indicates that this event was generated while redoing. + */ + readonly isRedoing: boolean; } export interface IMirrorTextModel { diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index f5cdab665a5ad..f6022c9f52f79 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -10130,6 +10130,14 @@ declare module 'vscode' { readonly text: string; } + export enum TextDocumentChangeReason { + /** The text change is caused by an undo operation. */ + Undo = 1, + + /** The text change is caused by an redo operation. */ + Redo = 2, + } + /** * An event describing a transactional {@link TextDocument document} change. */ @@ -10144,6 +10152,12 @@ declare module 'vscode' { * An array of content changes. */ readonly contentChanges: readonly TextDocumentContentChangeEvent[]; + + /** + * The reason why the document was changed. + * Is undefined if the reason is not known. + */ + readonly reason?: TextDocumentChangeReason; } /** diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 97823cf6c3f40..22080ab47fc62 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1239,6 +1239,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I TextEditorLineNumbersStyle: extHostTypes.TextEditorLineNumbersStyle, TextEditorRevealType: extHostTypes.TextEditorRevealType, TextEditorSelectionChangeKind: extHostTypes.TextEditorSelectionChangeKind, + TextDocumentChangeReason: extHostTypes.TextDocumentChangeReason, ThemeColor: extHostTypes.ThemeColor, ThemeIcon: extHostTypes.ThemeIcon, TreeItem: extHostTypes.TreeItem, diff --git a/src/vs/workbench/api/common/extHostDocuments.ts b/src/vs/workbench/api/common/extHostDocuments.ts index dcf170acd9253..4f13102856602 100644 --- a/src/vs/workbench/api/common/extHostDocuments.ts +++ b/src/vs/workbench/api/common/extHostDocuments.ts @@ -14,6 +14,7 @@ import * as TypeConverters from 'vs/workbench/api/common/extHostTypeConverters'; import type * as vscode from 'vscode'; import { assertIsDefined } from 'vs/base/common/types'; import { deepFreeze } from 'vs/base/common/objects'; +import { TextDocumentChangeReason } from 'vs/workbench/api/common/extHostTypes'; export class ExtHostDocuments implements ExtHostDocumentsShape { @@ -134,7 +135,8 @@ export class ExtHostDocuments implements ExtHostDocumentsShape { data._acceptIsDirty(isDirty); this._onDidChangeDocument.fire({ document: data.document, - contentChanges: [] + contentChanges: [], + reason: undefined }); } @@ -146,6 +148,14 @@ export class ExtHostDocuments implements ExtHostDocumentsShape { } data._acceptIsDirty(isDirty); data.onEvents(events); + + let reason: vscode.TextDocumentChangeReason | undefined = undefined; + if (events.isUndoing) { + reason = TextDocumentChangeReason.Undo; + } else if (events.isRedoing) { + reason = TextDocumentChangeReason.Redo; + } + this._onDidChangeDocument.fire(deepFreeze({ document: data.document, contentChanges: events.changes.map((change) => { @@ -155,7 +165,8 @@ export class ExtHostDocuments implements ExtHostDocumentsShape { rangeLength: change.rangeLength, text: change.text }; - }) + }), + reason })); } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 704417acf9c22..2cc35df7c9882 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -1590,6 +1590,11 @@ export enum TextEditorSelectionChangeKind { Command = 3 } +export enum TextDocumentChangeReason { + Undo = 1, + Redo = 2, +} + /** * These values match very carefully the values of `TrackedRangeStickiness` */ diff --git a/src/vs/workbench/test/browser/api/extHostDocumentData.test.ts b/src/vs/workbench/test/browser/api/extHostDocumentData.test.ts index c1a5af90538a4..228f929ca15fb 100644 --- a/src/vs/workbench/test/browser/api/extHostDocumentData.test.ts +++ b/src/vs/workbench/test/browser/api/extHostDocumentData.test.ts @@ -104,6 +104,8 @@ suite('ExtHostDocumentData', () => { }], eol: undefined!, versionId: undefined!, + isRedoing: false, + isUndoing: false, }); // line didn't change @@ -161,6 +163,8 @@ suite('ExtHostDocumentData', () => { }], eol: undefined!, versionId: undefined!, + isRedoing: false, + isUndoing: false, }); assertOffsetAt(0, 1, 1); @@ -179,6 +183,8 @@ suite('ExtHostDocumentData', () => { }], eol: undefined!, versionId: undefined!, + isRedoing: false, + isUndoing: false, }); assertOffsetAt(0, 1, 1); @@ -197,6 +203,8 @@ suite('ExtHostDocumentData', () => { }], eol: undefined!, versionId: undefined!, + isRedoing: false, + isUndoing: false, }); assertOffsetAt(0, 1, 1); @@ -218,6 +226,8 @@ suite('ExtHostDocumentData', () => { }], eol: undefined!, versionId: undefined!, + isRedoing: false, + isUndoing: false, }); assertOffsetAt(0, 1, 1); @@ -398,6 +408,8 @@ suite('ExtHostDocumentData updates line mapping', () => { }], eol: eol!, versionId: undefined!, + isRedoing: false, + isUndoing: false, }; } @@ -423,7 +435,7 @@ suite('ExtHostDocumentData updates line mapping', () => { 'and this is line number two', 'it is followed by #3', 'and finished with the fourth.', - ], { changes: [], eol: undefined!, versionId: 7 }); + ], { changes: [], eol: undefined!, versionId: 7, isRedoing: false, isUndoing: false }); }); test('after remove', () => { diff --git a/src/vs/workbench/test/browser/api/extHostDocumentSaveParticipant.test.ts b/src/vs/workbench/test/browser/api/extHostDocumentSaveParticipant.test.ts index b41dc067fb32b..c8973417b2337 100644 --- a/src/vs/workbench/test/browser/api/extHostDocumentSaveParticipant.test.ts +++ b/src/vs/workbench/test/browser/api/extHostDocumentSaveParticipant.test.ts @@ -306,7 +306,9 @@ suite('ExtHostDocumentSaveParticipant', () => { text: 'bar' }], eol: undefined!, - versionId: 2 + versionId: 2, + isRedoing: false, + isUndoing: false, }, true); e.waitUntil(Promise.resolve([TextEdit.insert(new Position(0, 0), 'bar')])); @@ -338,7 +340,9 @@ suite('ExtHostDocumentSaveParticipant', () => { rangeLength: undefined!, }], eol: undefined!, - versionId: documents.getDocumentData(uri)!.version + 1 + versionId: documents.getDocumentData(uri)!.version + 1, + isRedoing: false, + isUndoing: false, }, true); // } } diff --git a/src/vs/workbench/test/browser/api/extHostNotebookConcatDocument.test.ts b/src/vs/workbench/test/browser/api/extHostNotebookConcatDocument.test.ts index b9c704ae5bfa1..6ff7b0f14af5c 100644 --- a/src/vs/workbench/test/browser/api/extHostNotebookConcatDocument.test.ts +++ b/src/vs/workbench/test/browser/api/extHostNotebookConcatDocument.test.ts @@ -334,7 +334,9 @@ suite('NotebookConcatDocument', function () { rangeLength: 6, rangeOffset: 12, text: 'Hi' - }] + }], + isRedoing: false, + isUndoing: false, }, false); assertLines(doc, 'Hello', 'World', 'Hi World!', 'Hallo', 'Welt', 'Hallo Welt!'); assertLocation(doc, new Position(2, 12), new Location(notebook.apiNotebook.cellAt(0).document.uri, new Position(2, 9)), false);