diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index d90103ef0f6..303d4d68e3a 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -129,11 +129,11 @@ let DIFF_EDITOR_ID = 0; export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDiffEditor { - public onDidChangeModelRawContent(listener: (e: editorCommon.IModelContentChangedEvent) => void): IDisposable { + public onDidChangeModelRawContent(listener: (e: editorCommon.IModelRawContentChangedEvent) => void): IDisposable { return this.addListener2(editorCommon.EventType.ModelRawContentChanged, listener); } - public onDidChangeModelContent(listener: (e: editorCommon.IModelContentChangedEvent2) => void): IDisposable { - return this.addListener2(editorCommon.EventType.ModelContentChanged2, listener); + public onDidChangeModelContent(listener: (e: editorCommon.IModelContentChangedEvent) => void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelContentChanged, listener); } public onDidChangeModelLanguage(listener: (e: editorCommon.IModelLanguageChangedEvent) => void): IDisposable { return this.addListener2(editorCommon.EventType.ModelLanguageChanged, listener); diff --git a/src/vs/editor/common/commonCodeEditor.ts b/src/vs/editor/common/commonCodeEditor.ts index 071db8bc5a0..f048f7d24bd 100644 --- a/src/vs/editor/common/commonCodeEditor.ts +++ b/src/vs/editor/common/commonCodeEditor.ts @@ -34,8 +34,8 @@ let EDITOR_ID = 0; export abstract class CommonCodeEditor extends EventEmitter implements editorCommon.ICommonCodeEditor { - public readonly onDidChangeModelRawContent: Event = fromEventEmitter(this, editorCommon.EventType.ModelRawContentChanged); - public readonly onDidChangeModelContent: Event = fromEventEmitter(this, editorCommon.EventType.ModelContentChanged2); + public readonly onDidChangeModelRawContent: Event = fromEventEmitter(this, editorCommon.EventType.ModelRawContentChanged); + public readonly onDidChangeModelContent: Event = fromEventEmitter(this, editorCommon.EventType.ModelContentChanged); public readonly onDidChangeModelLanguage: Event = fromEventEmitter(this, editorCommon.EventType.ModelLanguageChanged); public readonly onDidChangeModelOptions: Event = fromEventEmitter(this, editorCommon.EventType.ModelOptionsChanged); public readonly onDidChangeModelDecorations: Event = fromEventEmitter(this, editorCommon.EventType.ModelDecorationsChanged); @@ -785,8 +785,8 @@ export abstract class CommonCodeEditor extends EventEmitter implements editorCom this.emit(editorCommon.EventType.ModelRawContentChanged, e); break; - case editorCommon.EventType.ModelContentChanged2: - this.emit(editorCommon.EventType.ModelContentChanged2, e); + case editorCommon.EventType.ModelContentChanged: + this.emit(editorCommon.EventType.ModelContentChanged, e); break; case editorCommon.EventType.ModelOptionsChanged: diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index efe42dbb584..2e14941224a 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -143,7 +143,7 @@ export class Cursor extends EventEmitter { if (eventType === editorCommon.EventType.ModelRawContentChanged) { hadContentChange = true; - const changeEvent = event.getData(); + const changeEvent = event.getData(); if (changeEvent.changeType === editorCommon.EventType.ModelRawContentChangedFlush) { hadFlushEvent = true; diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index ced9f14851a..6b079681877 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -2363,12 +2363,12 @@ export interface IModel extends IReadOnlyModel, IEditableTextModel, ITextModelWi * @internal * @event */ - onDidChangeRawContent(listener: (e: IModelContentChangedEvent) => void): IDisposable; + onDidChangeRawContent(listener: (e: IModelRawContentChangedEvent) => void): IDisposable; /** * An event emitted when the contents of the model have changed. * @event */ - onDidChangeContent(listener: (e: IModelContentChangedEvent2) => void): IDisposable; + onDidChangeContent(listener: (e: IModelContentChangedEvent) => void): IDisposable; /** * An event emitted when decorations of the model have changed. * @event @@ -2444,10 +2444,7 @@ export interface IModelLanguageChangedEvent { readonly newLanguage: string; } -/** - * An event describing a change in the text of a model. - */ -export interface IModelContentChangedEvent2 { +export interface IModelContentChange { /** * The range that got replaced. */ @@ -2460,6 +2457,13 @@ export interface IModelContentChangedEvent2 { * The new text for the range. */ readonly text: string; +} + +/** + * An event describing a change in the text of a model. + */ +export interface IModelContentChangedEvent { + readonly changes: IModelContentChange[]; /** * The (new) end-of-line character. */ @@ -2467,7 +2471,7 @@ export interface IModelContentChangedEvent2 { /** * The new version id the model has transitioned to. */ - versionId: number; + readonly versionId: number; /** * Flag that indicates that this event was generated while undoing. */ @@ -2486,7 +2490,7 @@ export interface IModelContentChangedEvent2 { * An event describing a change in the text of a model. * @internal */ -export interface IModelContentChangedEvent { +export interface IModelRawContentChangedEvent { /** * The event type. It can be used to detect the actual event type: * EditorCommon.EventType.ModelContentChangedFlush => IModelContentChangedFlushEvent @@ -2513,13 +2517,13 @@ export interface IModelContentChangedEvent { * An event describing that a model has been reset to a new value. * @internal */ -export interface IModelContentChangedFlushEvent extends IModelContentChangedEvent { +export interface IModelRawContentChangedFlushEvent extends IModelRawContentChangedEvent { } /** * An event describing that a line has changed in a model. * @internal */ -export interface IModelContentChangedLineChangedEvent extends IModelContentChangedEvent { +export interface IModelRawContentChangedLineChangedEvent extends IModelRawContentChangedEvent { /** * The line that has changed. */ @@ -2533,7 +2537,7 @@ export interface IModelContentChangedLineChangedEvent extends IModelContentChang * An event describing that line(s) have been deleted in a model. * @internal */ -export interface IModelContentChangedLinesDeletedEvent extends IModelContentChangedEvent { +export interface IModelRawContentChangedLinesDeletedEvent extends IModelRawContentChangedEvent { /** * At what line the deletion began (inclusive). */ @@ -2547,7 +2551,7 @@ export interface IModelContentChangedLinesDeletedEvent extends IModelContentChan * An event describing that line(s) have been inserted in a model. * @internal */ -export interface IModelContentChangedLinesInsertedEvent extends IModelContentChangedEvent { +export interface IModelRawContentChangedLinesInsertedEvent extends IModelRawContentChangedEvent { /** * Before what line did the insertion begin */ @@ -3423,12 +3427,12 @@ export interface IEditor { * @internal * @event */ - onDidChangeModelRawContent(listener: (e: IModelContentChangedEvent) => void): IDisposable; + onDidChangeModelRawContent(listener: (e: IModelRawContentChangedEvent) => void): IDisposable; /** * An event emitted when the content of the current model has changed. * @event */ - onDidChangeModelContent(listener: (e: IModelContentChangedEvent2) => void): IDisposable; + onDidChangeModelContent(listener: (e: IModelContentChangedEvent) => void): IDisposable; /** * An event emitted when the language of the current model has changed. * @event @@ -4128,8 +4132,8 @@ export var EventType = { ModelTokensChanged: 'modelTokensChanged', ModelLanguageChanged: 'modelLanguageChanged', ModelOptionsChanged: 'modelOptionsChanged', - ModelRawContentChanged: 'contentChanged', - ModelContentChanged2: 'contentChanged2', + ModelContentChanged: 'contentChanged', + ModelRawContentChanged: 'rawContentChanged', ModelRawContentChangedFlush: 'flush', ModelRawContentChangedLinesDeleted: 'linesDeleted', ModelRawContentChangedLinesInserted: 'linesInserted', diff --git a/src/vs/editor/common/model/editableTextModel.ts b/src/vs/editor/common/model/editableTextModel.ts index 9a1b9b04692..1f412996508 100644 --- a/src/vs/editor/common/model/editableTextModel.ts +++ b/src/vs/editor/common/model/editableTextModel.ts @@ -37,11 +37,11 @@ export class EditableTextModel extends TextModelWithDecorations implements edito return new EditableTextModel([], RawTextSource.fromString(text), options, languageIdentifier); } - public onDidChangeRawContent(listener: (e: editorCommon.IModelContentChangedEvent) => void): IDisposable { + public onDidChangeRawContent(listener: (e: editorCommon.IModelRawContentChangedEvent) => void): IDisposable { return this.addListener2(editorCommon.EventType.ModelRawContentChanged, listener); } - public onDidChangeContent(listener: (e: editorCommon.IModelContentChangedEvent2) => void): IDisposable { - return this.addListener2(editorCommon.EventType.ModelContentChanged2, listener); + public onDidChangeContent(listener: (e: editorCommon.IModelContentChangedEvent) => void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelContentChanged, listener); } private _commandManager: EditStack; @@ -465,8 +465,8 @@ export class EditableTextModel extends TextModelWithDecorations implements edito // Sort operations descending operations.sort(EditableTextModel._sortOpsDescending); - let contentChangedEvents: editorCommon.IModelContentChangedEvent[] = []; - let contentChanged2Events: editorCommon.IModelContentChangedEvent2[] = []; + let contentChangedEvents: editorCommon.IModelRawContentChangedEvent[] = []; + let contentChanges: editorCommon.IModelContentChange[] = []; let lineEditsQueue: IIdentifiedLineEdit[] = []; let queueLineEdit = (lineEdit: IIdentifiedLineEdit) => { @@ -652,15 +652,10 @@ export class EditableTextModel extends TextModelWithDecorations implements edito contentChangedEvents.push(this._createLinesInsertedEvent(spliceLineNumber + 1, startLineNumber + insertingLinesCnt, newLinesContent.join('\n'))); } - contentChanged2Events.push({ + contentChanges.push({ range: new Range(startLineNumber, startColumn, endLineNumber, endColumn), rangeLength: op.rangeLength, - text: op.lines ? op.lines.join(this.getEOL()) : '', - eol: this._EOL, - versionId: -1, - isUndoing: this._isUndoing, - isRedoing: this._isRedoing, - isFlush: false + text: op.lines ? op.lines.join(this.getEOL()) : '' }); // console.log('AFTER:'); @@ -679,30 +674,33 @@ export class EditableTextModel extends TextModelWithDecorations implements edito this._lines[lineNumber - 1].updateLineNumber(markersTracker, lineNumber); } - if (contentChangedEvents.length !== 0 || contentChanged2Events.length !== 0) { + if (contentChangedEvents.length !== 0 || contentChanges.length !== 0) { if (contentChangedEvents.length === 0) { // Fabricate a fake line changed event to get an event out // This most likely occurs when there edit operations are no-ops contentChangedEvents.push(this._createLineChangedEvent(minTouchedLineNumber)); } - let versionBumps = Math.max(contentChangedEvents.length, contentChanged2Events.length); + let versionBumps = Math.max(contentChangedEvents.length, contentChanges.length); let finalVersionId = this.getVersionId() + versionBumps; this._setVersionId(finalVersionId); for (let i = contentChangedEvents.length - 1, versionId = finalVersionId; i >= 0; i-- , versionId--) { contentChangedEvents[i].versionId = versionId; } - for (let i = contentChanged2Events.length - 1, versionId = finalVersionId; i >= 0; i-- , versionId--) { - contentChanged2Events[i].versionId = versionId; - } for (let i = 0, len = contentChangedEvents.length; i < len; i++) { this.emit(editorCommon.EventType.ModelRawContentChanged, contentChangedEvents[i]); } - for (let i = 0, len = contentChanged2Events.length; i < len; i++) { - this.emit(editorCommon.EventType.ModelContentChanged2, contentChanged2Events[i]); - } + const e: editorCommon.IModelContentChangedEvent = { + changes: contentChanges, + eol: this._EOL, + versionId: finalVersionId, + isUndoing: this._isUndoing, + isRedoing: this._isRedoing, + isFlush: false + }; + this.emit(editorCommon.EventType.ModelContentChanged, e); } // this._assertLineNumbersOK(); @@ -824,7 +822,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito } } - private _createLineChangedEvent(lineNumber: number): editorCommon.IModelContentChangedLineChangedEvent { + private _createLineChangedEvent(lineNumber: number): editorCommon.IModelRawContentChangedLineChangedEvent { return { changeType: editorCommon.EventType.ModelRawContentChangedLineChanged, lineNumber: lineNumber, @@ -835,7 +833,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito }; } - private _createLinesDeletedEvent(fromLineNumber: number, toLineNumber: number): editorCommon.IModelContentChangedLinesDeletedEvent { + private _createLinesDeletedEvent(fromLineNumber: number, toLineNumber: number): editorCommon.IModelRawContentChangedLinesDeletedEvent { return { changeType: editorCommon.EventType.ModelRawContentChangedLinesDeleted, fromLineNumber: fromLineNumber, @@ -846,7 +844,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito }; } - private _createLinesInsertedEvent(fromLineNumber: number, toLineNumber: number, newLinesContent: string): editorCommon.IModelContentChangedLinesInsertedEvent { + private _createLinesInsertedEvent(fromLineNumber: number, toLineNumber: number, newLinesContent: string): editorCommon.IModelRawContentChangedLinesInsertedEvent { return { changeType: editorCommon.EventType.ModelRawContentChangedLinesInserted, fromLineNumber: fromLineNumber, diff --git a/src/vs/editor/common/model/mirrorModel2.ts b/src/vs/editor/common/model/mirrorModel2.ts index a5c1a9474e1..8e61ec3de69 100644 --- a/src/vs/editor/common/model/mirrorModel2.ts +++ b/src/vs/editor/common/model/mirrorModel2.ts @@ -5,22 +5,11 @@ 'use strict'; import URI from 'vs/base/common/uri'; -import { IPosition, IRange } from 'vs/editor/common/editorCommon'; +import { IPosition, IRange, IModelContentChange } from 'vs/editor/common/editorCommon'; import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; -export interface IModelChangedData { - /** - * The range that got replaced. - */ - readonly range: IRange; - /** - * The length of the range that got replaced. - */ - readonly rangeLength: number; - /** - * The new text for the range. - */ - readonly text: string; +export interface IModelChangedEvent { + readonly changes: IModelContentChange[]; /** * The (new) end-of-line character. */ @@ -58,34 +47,24 @@ export class MirrorModel2 { return this._lines.join(this._eol); } - onEvents(events: IModelChangedData[]): void { - let newEOL: string = null; - for (let i = 0, len = events.length; i < len; i++) { - let e = events[i]; - if (e.eol) { - newEOL = e.eol; - } - } - if (newEOL && newEOL !== this._eol) { - this._eol = newEOL; + onEvents(e: IModelChangedEvent): void { + if (e.eol && e.eol !== this._eol) { + this._eol = e.eol; this._lineStarts = null; } // Update my lines - let lastVersionId = -1; - for (let i = 0, len = events.length; i < len; i++) { - let e = events[i]; - - this._acceptDeleteRange(e.range); + const changes = e.changes; + for (let i = 0, len = changes.length; i < len; i++) { + const change = changes[i]; + this._acceptDeleteRange(change.range); this._acceptInsertText({ - lineNumber: e.range.startLineNumber, - column: e.range.startColumn - }, e.text); - lastVersionId = Math.max(lastVersionId, e.versionId); - } - if (lastVersionId !== -1) { - this._versionId = lastVersionId; + lineNumber: change.range.startLineNumber, + column: change.range.startColumn + }, change.text); } + + this._versionId = e.versionId; } protected _ensureLineStarts(): void { diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 5eade2b5edf..18dfeddd55d 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -89,7 +89,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo private _shouldDenyMode: boolean; constructor(allowedEventTypes: string[], rawTextSource: IRawTextSource, creationOptions: editorCommon.ITextModelCreationOptions) { - allowedEventTypes.push(editorCommon.EventType.ModelRawContentChanged, editorCommon.EventType.ModelOptionsChanged, editorCommon.EventType.ModelContentChanged2); + allowedEventTypes.push(editorCommon.EventType.ModelRawContentChanged, editorCommon.EventType.ModelOptionsChanged, editorCommon.EventType.ModelContentChanged); super(allowedEventTypes); const textModelData = TextModel.resolveCreationData(rawTextSource, creationOptions); @@ -298,7 +298,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo super.dispose(); } - private _createContentChangedFlushEvent(): editorCommon.IModelContentChangedFlushEvent { + private _createContentChangedFlushEvent(): editorCommon.IModelRawContentChangedFlushEvent { return { changeType: editorCommon.EventType.ModelRawContentChangedFlush, versionId: this._versionId, @@ -308,11 +308,13 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo }; } - protected _emitContentChanged2(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, rangeLength: number, text: string, isUndoing: boolean, isRedoing: boolean, isFlush: boolean): void { - const e: editorCommon.IModelContentChangedEvent2 = { - range: new Range(startLineNumber, startColumn, endLineNumber, endColumn), - rangeLength: rangeLength, - text: text, + private _emitContentChanged2(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, rangeLength: number, text: string, isUndoing: boolean, isRedoing: boolean, isFlush: boolean): void { + const e: editorCommon.IModelContentChangedEvent = { + changes: [{ + range: new Range(startLineNumber, startColumn, endLineNumber, endColumn), + rangeLength: rangeLength, + text: text, + }], eol: this._EOL, versionId: this.getVersionId(), isUndoing: isUndoing, @@ -320,7 +322,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo isFlush: isFlush }; if (!this._isDisposing) { - this.emit(editorCommon.EventType.ModelContentChanged2, e); + this.emit(editorCommon.EventType.ModelContentChanged, e); } } @@ -762,7 +764,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo return new Range(1, 1, lineCount, this.getLineMaxColumn(lineCount)); } - protected _emitModelContentChangedFlushEvent(e: editorCommon.IModelContentChangedFlushEvent): void { + protected _emitModelContentChangedFlushEvent(e: editorCommon.IModelRawContentChangedFlushEvent): void { if (!this._isDisposing) { this.emit(editorCommon.EventType.ModelRawContentChanged, e); } diff --git a/src/vs/editor/common/services/editorSimpleWorker.ts b/src/vs/editor/common/services/editorSimpleWorker.ts index 79d81f47cf3..79d8c1a328a 100644 --- a/src/vs/editor/common/services/editorSimpleWorker.ts +++ b/src/vs/editor/common/services/editorSimpleWorker.ts @@ -14,7 +14,7 @@ import { DiffComputer } from 'vs/editor/common/diff/diffComputer'; import { stringDiff } from 'vs/base/common/diff/diff'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { Position } from 'vs/editor/common/core/position'; -import { MirrorModel2 } from 'vs/editor/common/model/mirrorModel2'; +import { MirrorModel2, IModelChangedEvent } from 'vs/editor/common/model/mirrorModel2'; import { IInplaceReplaceSupportResult, ILink, ISuggestResult, ISuggestion, TextEdit } from 'vs/editor/common/modes'; import { computeLinks } from 'vs/editor/common/modes/linkComputer'; import { BasicInplaceReplace } from 'vs/editor/common/modes/supports/inplaceReplaceSupport'; @@ -528,12 +528,12 @@ export class EditorSimpleWorkerImpl extends BaseEditorSimpleWorker implements IR this._models[data.url] = new MirrorModel(URI.parse(data.url), data.lines, data.EOL, data.versionId); } - public acceptModelChanged(strURL: string, events: editorCommon.IModelContentChangedEvent2[]): void { + public acceptModelChanged(strURL: string, e: IModelChangedEvent): void { if (!this._models[strURL]) { return; } let model = this._models[strURL]; - model.onEvents(events); + model.onEvents(e); } public acceptRemovedModel(strURL: string): void { diff --git a/src/vs/editor/common/services/editorWorkerServiceImpl.ts b/src/vs/editor/common/services/editorWorkerServiceImpl.ts index 90ae2e8971b..d4708aaf3dd 100644 --- a/src/vs/editor/common/services/editorWorkerServiceImpl.ts +++ b/src/vs/editor/common/services/editorWorkerServiceImpl.ts @@ -236,22 +236,11 @@ class EditorModelManager extends Disposable { }); let toDispose: IDisposable[] = []; - toDispose.push(model.addBulkListener((events) => { - let changedEvents: editorCommon.IModelContentChangedEvent2[] = []; - for (let i = 0, len = events.length; i < len; i++) { - let e = events[i]; - switch (e.getType()) { - case editorCommon.EventType.ModelContentChanged2: - changedEvents.push(e.getData()); - break; - case editorCommon.EventType.ModelDispose: - this._stopModelSync(modelUrl); - return; - } - } - if (changedEvents.length > 0) { - this._proxy.acceptModelChanged(modelUrl.toString(), changedEvents); - } + toDispose.push(model.onDidChangeContent((e) => { + this._proxy.acceptModelChanged(modelUrl.toString(), e); + })); + toDispose.push(model.onWillDispose(() => { + this._stopModelSync(modelUrl); })); toDispose.push({ dispose: () => { diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index e008f03f01a..f0163c4bad2 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -300,26 +300,26 @@ export class ViewModel implements IViewModel { switch (e.getType()) { case editorCommon.EventType.ModelRawContentChanged: - let modelContentChangedEvent = data; + let modelContentChangedEvent = data; switch (modelContentChangedEvent.changeType) { case editorCommon.EventType.ModelRawContentChangedFlush: - this.onModelFlushed(eventsCollector, modelContentChangedEvent); + this.onModelFlushed(eventsCollector, modelContentChangedEvent); hadOtherModelChange = true; break; case editorCommon.EventType.ModelRawContentChangedLinesDeleted: - this.onModelLinesDeleted(eventsCollector, modelContentChangedEvent); + this.onModelLinesDeleted(eventsCollector, modelContentChangedEvent); hadOtherModelChange = true; break; case editorCommon.EventType.ModelRawContentChangedLinesInserted: - this.onModelLinesInserted(eventsCollector, modelContentChangedEvent); + this.onModelLinesInserted(eventsCollector, modelContentChangedEvent); hadOtherModelChange = true; break; case editorCommon.EventType.ModelRawContentChangedLineChanged: - hadModelLineChangeThatChangedLineMapping = this.onModelLineChanged(eventsCollector, modelContentChangedEvent); + hadModelLineChangeThatChangedLineMapping = this.onModelLineChanged(eventsCollector, modelContentChangedEvent); break; default: @@ -336,7 +336,7 @@ export class ViewModel implements IViewModel { // That's ok, a model tokens changed event will follow shortly break; - case editorCommon.EventType.ModelContentChanged2: + case editorCommon.EventType.ModelContentChanged: // Ignore break; @@ -409,14 +409,14 @@ export class ViewModel implements IViewModel { } // --- begin inbound event conversion - private onModelFlushed(eventsCollector: ViewEventsCollector, e: editorCommon.IModelContentChangedFlushEvent): void { + private onModelFlushed(eventsCollector: ViewEventsCollector, e: editorCommon.IModelRawContentChangedFlushEvent): void { this.lines.onModelFlushed(eventsCollector, e.versionId); this.decorations.reset(); } private onModelDecorationsChanged(eventsCollector: ViewEventsCollector, e: editorCommon.IModelDecorationsChangedEvent): void { this.decorations.onModelDecorationsChanged(eventsCollector, e); } - private onModelLinesDeleted(eventsCollector: ViewEventsCollector, e: editorCommon.IModelContentChangedLinesDeletedEvent): void { + private onModelLinesDeleted(eventsCollector: ViewEventsCollector, e: editorCommon.IModelRawContentChangedLinesDeletedEvent): void { this.lines.onModelLinesDeleted(eventsCollector, e.versionId, e.fromLineNumber, e.toLineNumber); } private onModelTokensChanged(eventsCollector: ViewEventsCollector, e: editorCommon.IModelTokensChangedEvent): void { @@ -434,11 +434,11 @@ export class ViewModel implements IViewModel { eventsCollector.emit(new viewEvents.ViewTokensChangedEvent(viewRanges)); } - private onModelLineChanged(eventsCollector: ViewEventsCollector, e: editorCommon.IModelContentChangedLineChangedEvent): boolean { + private onModelLineChanged(eventsCollector: ViewEventsCollector, e: editorCommon.IModelRawContentChangedLineChangedEvent): boolean { var lineMappingChanged = this.lines.onModelLineChanged(eventsCollector, e.versionId, e.lineNumber, e.detail); return lineMappingChanged; } - private onModelLinesInserted(eventsCollector: ViewEventsCollector, e: editorCommon.IModelContentChangedLinesInsertedEvent): void { + private onModelLinesInserted(eventsCollector: ViewEventsCollector, e: editorCommon.IModelRawContentChangedLinesInsertedEvent): void { this.lines.onModelLinesInserted(eventsCollector, e.versionId, e.fromLineNumber, e.toLineNumber, e.detail.split('\n')); } diff --git a/src/vs/editor/contrib/find/common/findModel.ts b/src/vs/editor/contrib/find/common/findModel.ts index 890bffc2a80..d8d910700bb 100644 --- a/src/vs/editor/contrib/find/common/findModel.ts +++ b/src/vs/editor/contrib/find/common/findModel.ts @@ -97,7 +97,7 @@ export class FindModelBoundToEditorModel { })); this._ignoreModelContentChanged = false; - this._toDispose.push(this._editor.onDidChangeModelRawContent((e: editorCommon.IModelContentChangedEvent) => { + this._toDispose.push(this._editor.onDidChangeModelRawContent((e: editorCommon.IModelRawContentChangedEvent) => { if (this._ignoreModelContentChanged) { return; } diff --git a/src/vs/editor/contrib/format/browser/formatActions.ts b/src/vs/editor/contrib/format/browser/formatActions.ts index 4844db9cb19..06dbea29a20 100644 --- a/src/vs/editor/contrib/format/browser/formatActions.ts +++ b/src/vs/editor/contrib/format/browser/formatActions.ts @@ -124,20 +124,20 @@ class FormatOnType implements editorCommon.IEditorContribution { // install a listener that checks if edits happens before the // position on which we format right now. If so, we won't // apply the format edits - var unbind = this.editor.onDidChangeModelRawContent((e: editorCommon.IModelContentChangedEvent) => { + var unbind = this.editor.onDidChangeModelRawContent((e: editorCommon.IModelRawContentChangedEvent) => { if (e.changeType === editorCommon.EventType.ModelRawContentChangedFlush) { // a model.setValue() was called canceled = true; } else if (e.changeType === editorCommon.EventType.ModelRawContentChangedLineChanged) { - var changedLine = (e).lineNumber; + var changedLine = (e).lineNumber; canceled = changedLine <= position.lineNumber; } else if (e.changeType === editorCommon.EventType.ModelRawContentChangedLinesInserted) { - var insertLine = (e).fromLineNumber; + var insertLine = (e).fromLineNumber; canceled = insertLine <= position.lineNumber; } else if (e.changeType === editorCommon.EventType.ModelRawContentChangedLinesDeleted) { - var deleteLine2 = (e).toLineNumber; + var deleteLine2 = (e).toLineNumber; canceled = deleteLine2 <= position.lineNumber; } diff --git a/src/vs/editor/contrib/snippet/common/snippetController.ts b/src/vs/editor/contrib/snippet/common/snippetController.ts index b0f1cd1aeb1..c4a6c0cc1e8 100644 --- a/src/vs/editor/contrib/snippet/common/snippetController.ts +++ b/src/vs/editor/contrib/snippet/common/snippetController.ts @@ -142,7 +142,7 @@ export class InsertSnippetController { // print(); this.listenersToRemove = []; - this.listenersToRemove.push(this.editor.onDidChangeModelRawContent((e: editorCommon.IModelContentChangedEvent) => { + this.listenersToRemove.push(this.editor.onDidChangeModelRawContent((e: editorCommon.IModelRawContentChangedEvent) => { // console.log('-------MODEL CHANGED'); // print(); if (this.isFinished) { @@ -153,22 +153,22 @@ export class InsertSnippetController { // a model.setValue() was called this.stopAll(); } else if (e.changeType === editorCommon.EventType.ModelRawContentChangedLineChanged) { - var changedLine = (e).lineNumber; + var changedLine = (e).lineNumber; var highlightRange = this.model.getDecorationRange(this.highlightDecorationId); if (changedLine < highlightRange.startLineNumber || changedLine > highlightRange.endLineNumber) { this.stopAll(); } } else if (e.changeType === editorCommon.EventType.ModelRawContentChangedLinesInserted) { - var insertLine = (e).fromLineNumber; + var insertLine = (e).fromLineNumber; var highlightRange = this.model.getDecorationRange(this.highlightDecorationId); if (insertLine < highlightRange.startLineNumber || insertLine > highlightRange.endLineNumber) { this.stopAll(); } } else if (e.changeType === editorCommon.EventType.ModelRawContentChangedLinesDeleted) { - var deleteLine1 = (e).fromLineNumber; - var deleteLine2 = (e).toLineNumber; + var deleteLine1 = (e).fromLineNumber; + var deleteLine2 = (e).toLineNumber; var highlightRange = this.model.getDecorationRange(this.highlightDecorationId); var deletedLinesAbove = (deleteLine2 < highlightRange.startLineNumber); diff --git a/src/vs/editor/test/common/controller/cursor.test.ts b/src/vs/editor/test/common/controller/cursor.test.ts index 4d1521314b5..683a30f2b79 100644 --- a/src/vs/editor/test/common/controller/cursor.test.ts +++ b/src/vs/editor/test/common/controller/cursor.test.ts @@ -2863,7 +2863,7 @@ suite('ElectricCharacter', () => { moveTo(cursor, 1, 5); let changeText: string = null; model.onDidChangeContent(e => { - changeText = e.text; + changeText = e.changes[0].text; }); cursorCommand(cursor, H.Type, { text: ')' }, 'keyboard'); assert.deepEqual(model.getLineContent(1), '(div)'); diff --git a/src/vs/editor/test/common/model/editableTextModel.test.ts b/src/vs/editor/test/common/model/editableTextModel.test.ts index 147ea94470f..ec36ecb4cc6 100644 --- a/src/vs/editor/test/common/model/editableTextModel.test.ts +++ b/src/vs/editor/test/common/model/editableTextModel.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { Range } from 'vs/editor/common/core/range'; -import { EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation, IModelContentChangedEvent2 } from 'vs/editor/common/editorCommon'; +import { EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation, IModelContentChangedEvent } from 'vs/editor/common/editorCommon'; import { EditableTextModel, IValidatedEditOperation } from 'vs/editor/common/model/editableTextModel'; import { MirrorModel2 } from 'vs/editor/common/model/mirrorModel2'; import { assertSyncedModels, testApplyEditsWithSyncedModels } from 'vs/editor/test/common/model/editableTextModelTestUtils'; @@ -1533,7 +1533,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { }, (model) => { var isFirstTime = true; - model.onDidChangeContent((e: IModelContentChangedEvent2) => { + model.onDidChangeContent((e: IModelContentChangedEvent) => { if (!isFirstTime) { return; } @@ -1556,13 +1556,13 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { let mirrorModel2 = new MirrorModel2(null, model.getLinesContent(), model.getEOL(), model.getVersionId()); let mirrorModel2PrevVersionId = model.getVersionId(); - model.onDidChangeContent((e: IModelContentChangedEvent2) => { + model.onDidChangeContent((e: IModelContentChangedEvent) => { let versionId = e.versionId; if (versionId < mirrorModel2PrevVersionId) { console.warn('Model version id did not advance between edits (2)'); } mirrorModel2PrevVersionId = versionId; - mirrorModel2.onEvents([e]); + mirrorModel2.onEvents(e); }); let assertMirrorModels = () => { diff --git a/src/vs/editor/test/common/model/editableTextModelTestUtils.ts b/src/vs/editor/test/common/model/editableTextModelTestUtils.ts index c890b590176..d9fd0db79b9 100644 --- a/src/vs/editor/test/common/model/editableTextModelTestUtils.ts +++ b/src/vs/editor/test/common/model/editableTextModelTestUtils.ts @@ -93,13 +93,13 @@ export function assertSyncedModels(text: string, callback: (model: EditableTextM var mirrorModel2 = new MirrorModel2(null, model.getLinesContent(), model.getEOL(), model.getVersionId()); var mirrorModel2PrevVersionId = model.getVersionId(); - model.onDidChangeContent((e: editorCommon.IModelContentChangedEvent2) => { + model.onDidChangeContent((e: editorCommon.IModelContentChangedEvent) => { let versionId = e.versionId; if (versionId < mirrorModel2PrevVersionId) { console.warn('Model version id did not advance between edits (2)'); } mirrorModel2PrevVersionId = versionId; - mirrorModel2.onEvents([e]); + mirrorModel2.onEvents(e); }); var assertMirrorModels = () => { diff --git a/src/vs/editor/test/common/model/model.test.ts b/src/vs/editor/test/common/model/model.test.ts index b4542ddfc1b..27648d267fa 100644 --- a/src/vs/editor/test/common/model/model.test.ts +++ b/src/vs/editor/test/common/model/model.test.ts @@ -9,8 +9,8 @@ import { EditOperation } from 'vs/editor/common/core/editOperation'; import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { - EventType, IModelContentChangedEvent, IModelContentChangedLineChangedEvent, - IModelContentChangedLinesDeletedEvent, IModelContentChangedLinesInsertedEvent + EventType, IModelRawContentChangedEvent, IModelRawContentChangedLineChangedEvent, + IModelRawContentChangedLinesDeletedEvent, IModelRawContentChangedLinesInsertedEvent } from 'vs/editor/common/editorCommon'; import { Model } from 'vs/editor/common/model/model'; @@ -104,7 +104,7 @@ suite('Editor Model - Model', () => { thisModel.onDidChangeRawContent((e) => { listenerCalls++; assert.equal(e.changeType, EventType.ModelRawContentChangedLineChanged); - assert.equal((e).lineNumber, 1); + assert.equal((e).lineNumber, 1); }); thisModel.applyEdits([EditOperation.insert(new Position(1, 1), 'foo ')]); assert.equal(listenerCalls, 1, 'listener calls'); @@ -120,15 +120,15 @@ suite('Editor Model - Model', () => { if (e.changeType === EventType.ModelRawContentChangedLineChanged) { if (order === 0) { assert.equal(++order, 1, 'ModelContentChangedLineChanged first'); - assert.equal((e).lineNumber, 1, 'ModelContentChangedLineChanged line number 1'); + assert.equal((e).lineNumber, 1, 'ModelContentChangedLineChanged line number 1'); } else { assert.equal(++order, 2, 'ModelContentChangedLineChanged first'); - assert.equal((e).lineNumber, 1, 'ModelContentChangedLineChanged line number 1'); + assert.equal((e).lineNumber, 1, 'ModelContentChangedLineChanged line number 1'); } } else if (e.changeType === EventType.ModelRawContentChangedLinesInserted) { assert.equal(++order, 3, 'ModelContentChangedLinesInserted second'); - assert.equal((e).fromLineNumber, 2, 'ModelContentChangedLinesInserted fromLineNumber'); - assert.equal((e).toLineNumber, 2, 'ModelContentChangedLinesInserted toLineNumber'); + assert.equal((e).fromLineNumber, 2, 'ModelContentChangedLinesInserted fromLineNumber'); + assert.equal((e).toLineNumber, 2, 'ModelContentChangedLinesInserted toLineNumber'); } else { assert.ok(false); } @@ -201,7 +201,7 @@ suite('Editor Model - Model', () => { thisModel.onDidChangeRawContent((e) => { listenerCalls++; assert.equal(e.changeType, EventType.ModelRawContentChangedLineChanged); - assert.equal((e).lineNumber, 1); + assert.equal((e).lineNumber, 1); }); thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 1, 2))]); assert.equal(listenerCalls, 1, 'listener calls'); @@ -212,7 +212,7 @@ suite('Editor Model - Model', () => { thisModel.onDidChangeRawContent((e) => { listenerCalls++; assert.equal(e.changeType, EventType.ModelRawContentChangedLineChanged); - assert.equal((e).lineNumber, 1); + assert.equal((e).lineNumber, 1); }); thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 1, 14))]); assert.equal(listenerCalls, 1, 'listener calls'); @@ -227,15 +227,15 @@ suite('Editor Model - Model', () => { if (e.changeType === EventType.ModelRawContentChangedLineChanged) { if (order === 0) { assert.equal(++order, 1); - assert.equal((e).lineNumber, 1); + assert.equal((e).lineNumber, 1); } else { assert.equal(++order, 2); - assert.equal((e).lineNumber, 1); + assert.equal((e).lineNumber, 1); } } else if (e.changeType === EventType.ModelRawContentChangedLinesDeleted) { assert.equal(++order, 3); - assert.equal((e).fromLineNumber, 2); - assert.equal((e).toLineNumber, 2); + assert.equal((e).fromLineNumber, 2); + assert.equal((e).toLineNumber, 2); } else { assert.ok(false); } @@ -255,15 +255,15 @@ suite('Editor Model - Model', () => { if (e.changeType === EventType.ModelRawContentChangedLineChanged) { if (order === 0) { assert.equal(++order, 1); - assert.equal((e).lineNumber, 1); + assert.equal((e).lineNumber, 1); } else { assert.equal(++order, 2); - assert.equal((e).lineNumber, 1); + assert.equal((e).lineNumber, 1); } } else if (e.changeType === EventType.ModelRawContentChangedLinesDeleted) { assert.equal(++order, 3); - assert.equal((e).fromLineNumber, 2); - assert.equal((e).toLineNumber, 3); + assert.equal((e).fromLineNumber, 2); + assert.equal((e).toLineNumber, 3); } else { assert.ok(false); } @@ -308,7 +308,7 @@ suite('Editor Model - Model', () => { // --------- setValue test('setValue eventing', () => { var listenerCalls = 0; - thisModel.onDidChangeRawContent((e: IModelContentChangedEvent) => { + thisModel.onDidChangeRawContent((e: IModelRawContentChangedEvent) => { listenerCalls++; assert.equal(e.changeType, EventType.ModelRawContentChangedFlush); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index e2408c1759f..d9f706b8f7e 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2382,7 +2382,7 @@ declare module monaco.editor { * An event emitted when the contents of the model have changed. * @event */ - onDidChangeContent(listener: (e: IModelContentChangedEvent2) => void): IDisposable; + onDidChangeContent(listener: (e: IModelContentChangedEvent) => void): IDisposable; /** * An event emitted when decorations of the model have changed. * @event @@ -2428,10 +2428,7 @@ declare module monaco.editor { readonly newLanguage: string; } - /** - * An event describing a change in the text of a model. - */ - export interface IModelContentChangedEvent2 { + export interface IModelContentChange { /** * The range that got replaced. */ @@ -2444,6 +2441,13 @@ declare module monaco.editor { * The new text for the range. */ readonly text: string; + } + + /** + * An event describing a change in the text of a model. + */ + export interface IModelContentChangedEvent { + readonly changes: IModelContentChange[]; /** * The (new) end-of-line character. */ @@ -2451,7 +2455,7 @@ declare module monaco.editor { /** * The new version id the model has transitioned to. */ - versionId: number; + readonly versionId: number; /** * Flag that indicates that this event was generated while undoing. */ @@ -2971,7 +2975,7 @@ declare module monaco.editor { * An event emitted when the content of the current model has changed. * @event */ - onDidChangeModelContent(listener: (e: IModelContentChangedEvent2) => void): IDisposable; + onDidChangeModelContent(listener: (e: IModelContentChangedEvent) => void): IDisposable; /** * An event emitted when the language of the current model has changed. * @event diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index bb9e97ab01f..a8745bb8407 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -38,7 +38,7 @@ import { IApplyEditsOptions, IUndoStopOptions, TextEditorRevealType, ITextEditor import { InternalTreeExplorerNodeContent } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel'; import { TaskSet } from 'vs/workbench/parts/tasks/common/tasks'; -import { IModelChangedData } from 'vs/editor/common/model/mirrorModel2'; +import { IModelChangedEvent } from 'vs/editor/common/model/mirrorModel2'; export interface IEnvironment { enableProposedApi: boolean; @@ -313,7 +313,7 @@ export abstract class ExtHostDocumentsShape { $acceptModelSaved(strURL: string): void { throw ni(); } $acceptModelDirty(strURL: string): void { throw ni(); } $acceptModelReverted(strURL: string): void { throw ni(); } - $acceptModelChanged(strURL: string, events: IModelChangedData[], isDirty: boolean): void { throw ni(); } + $acceptModelChanged(strURL: string, e: IModelChangedEvent, isDirty: boolean): void { throw ni(); } } export abstract class ExtHostDocumentSaveParticipantShape { diff --git a/src/vs/workbench/api/node/extHostDocuments.ts b/src/vs/workbench/api/node/extHostDocuments.ts index e043cd0e948..180e2ada0af 100644 --- a/src/vs/workbench/api/node/extHostDocuments.ts +++ b/src/vs/workbench/api/node/extHostDocuments.ts @@ -19,7 +19,7 @@ import { TextSource } from 'vs/editor/common/model/textSource'; import { MainContext, MainThreadDocumentsShape, ExtHostDocumentsShape } from './extHost.protocol'; import { ExtHostDocumentData, setWordDefinitionFor } from './extHostDocumentData'; import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors'; -import { IModelChangedData } from 'vs/editor/common/model/mirrorModel2'; +import { IModelChangedEvent } from 'vs/editor/common/model/mirrorModel2'; export class ExtHostDocuments extends ExtHostDocumentsShape { @@ -185,17 +185,17 @@ export class ExtHostDocuments extends ExtHostDocumentsShape { document._acceptIsDirty(false); } - public $acceptModelChanged(strURL: string, events: IModelChangedData[], isDirty: boolean): void { + public $acceptModelChanged(strURL: string, events: IModelChangedEvent, isDirty: boolean): void { let data = this._documentsAndEditors.getDocument(strURL); data._acceptIsDirty(isDirty); data.onEvents(events); this._onDidChangeDocument.fire({ document: data.document, - contentChanges: events.map((e) => { + contentChanges: events.changes.map((change) => { return { - range: TypeConverters.toRange(e.range), - rangeLength: e.rangeLength, - text: e.text + range: TypeConverters.toRange(change.range), + rangeLength: change.rangeLength, + text: change.text }; }) }); diff --git a/src/vs/workbench/api/node/mainThreadDocuments.ts b/src/vs/workbench/api/node/mainThreadDocuments.ts index 8ec1335287c..68e8ae99d00 100644 --- a/src/vs/workbench/api/node/mainThreadDocuments.ts +++ b/src/vs/workbench/api/node/mainThreadDocuments.ts @@ -6,7 +6,6 @@ import URI from 'vs/base/common/uri'; import { toErrorMessage } from 'vs/base/common/errorMessage'; -import { EmitterEvent } from 'vs/base/common/eventEmitter'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IThreadService } from 'vs/workbench/services/thread/common/threadService'; import { IDisposable, dispose, IReference } from 'vs/base/common/lifecycle'; @@ -158,7 +157,9 @@ export class MainThreadDocuments extends MainThreadDocumentsShape { } let modelUrl = model.uri; this._modelIsSynced[modelUrl.toString()] = true; - this._modelToDisposeMap[modelUrl.toString()] = model.addBulkListener((events) => this._onModelEvents(modelUrl, events)); + this._modelToDisposeMap[modelUrl.toString()] = model.onDidChangeContent((e) => { + this._proxy.$acceptModelChanged(modelUrl.toString(), e, this._textFileService.isDirty(modelUrl)); + }); } private _onModelModeChanged(event: { model: editorCommon.IModel; oldModeId: string; }): void { @@ -180,21 +181,6 @@ export class MainThreadDocuments extends MainThreadDocumentsShape { delete this._modelToDisposeMap[modelUrl]; } - private _onModelEvents(modelUrl: URI, events: EmitterEvent[]): void { - let changedEvents: editorCommon.IModelContentChangedEvent2[] = []; - for (let i = 0, len = events.length; i < len; i++) { - let e = events[i]; - switch (e.getType()) { - case editorCommon.EventType.ModelContentChanged2: - changedEvents.push(e.getData()); - break; - } - } - if (changedEvents.length > 0) { - this._proxy.$acceptModelChanged(modelUrl.toString(), changedEvents, this._textFileService.isDirty(modelUrl)); - } - } - // --- from extension host process $trySaveDocument(uri: URI): TPromise { diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index c678538d5c5..c2fc290e0ed 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -24,7 +24,7 @@ import { IDisposable, combinedDisposable, dispose } from 'vs/base/common/lifecyc import { IMessageService, Severity } from 'vs/platform/message/common/message'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; -import { IEditorAction, ICommonCodeEditor, IModelContentChangedEvent, IModelOptionsChangedEvent, IModelLanguageChangedEvent, ICursorPositionChangedEvent, EndOfLineSequence, EditorType, IModel, IDiffEditorModel, IEditor } from 'vs/editor/common/editorCommon'; +import { IEditorAction, ICommonCodeEditor, IModelRawContentChangedEvent, IModelOptionsChangedEvent, IModelLanguageChangedEvent, ICursorPositionChangedEvent, EndOfLineSequence, EditorType, IModel, IDiffEditorModel, IEditor } from 'vs/editor/common/editorCommon'; import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { TrimTrailingWhitespaceAction } from 'vs/editor/contrib/linesOperations/common/linesOperations'; import { IndentUsingSpaces, IndentUsingTabs, DetectIndentation, IndentationToSpacesAction, IndentationToTabsAction } from 'vs/editor/contrib/indentation/common/indentation'; @@ -504,7 +504,7 @@ export class EditorStatus implements IStatusbarItem { })); // Hook Listener for content changes - this.activeEditorListeners.push(control.onDidChangeModelRawContent((event: IModelContentChangedEvent) => { + this.activeEditorListeners.push(control.onDidChangeModelRawContent((event: IModelRawContentChangedEvent) => { this.onEOLChange(control); })); diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 88d55d9e8ed..21d511c7bef 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -16,7 +16,6 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import paths = require('vs/base/common/paths'); import diagnostics = require('vs/base/common/diagnostics'); import types = require('vs/base/common/types'); -import { EventType as EditorEventType } from 'vs/editor/common/editorCommon'; import { IMode } from 'vs/editor/common/modes'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, IModelSaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent } from 'vs/workbench/services/textfile/common/textfiles'; @@ -413,18 +412,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil this.setDirty(false); } - this.toDispose.push(this.textEditorModel.addBulkListener((events) => { - let hasContentChangeEvent = false; - for (let i = 0, len = events.length; i < len; i++) { - let eventType = events[i].getType(); - if (eventType === EditorEventType.ModelContentChanged2) { - hasContentChangeEvent = true; - break; - } - } - if (hasContentChangeEvent) { - this.onModelContentChanged(); - } + this.toDispose.push(this.textEditorModel.onDidChangeContent((e) => { + this.onModelContentChanged(); })); return this; diff --git a/src/vs/workbench/test/electron-browser/api/extHostDocumentData.test.ts b/src/vs/workbench/test/electron-browser/api/extHostDocumentData.test.ts index b5a318b7ba1..ed10c28ba9a 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostDocumentData.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostDocumentData.test.ts @@ -9,10 +9,10 @@ import * as assert from 'assert'; import URI from 'vs/base/common/uri'; import { ExtHostDocumentData } from 'vs/workbench/api/node/extHostDocumentData'; import { Position } from 'vs/workbench/api/node/extHostTypes'; -import { Range as CodeEditorRange } from 'vs/editor/common/core/range'; +import { Range } from 'vs/editor/common/core/range'; import { MainThreadDocumentsShape } from 'vs/workbench/api/node/extHost.protocol'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IModelChangedData } from 'vs/editor/common/model/mirrorModel2'; +import { IModelChangedEvent } from 'vs/editor/common/model/mirrorModel2'; suite('ExtHostDocumentData', () => { @@ -97,13 +97,15 @@ suite('ExtHostDocumentData', () => { assert.equal(line.isEmptyOrWhitespace, false); assert.equal(line.firstNonWhitespaceCharacterIndex, 0); - data.onEvents([{ - range: { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }, - text: '\t ', + data.onEvents({ + changes: [{ + range: { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }, + rangeLength: undefined, + text: '\t ' + }], eol: undefined, versionId: undefined, - rangeLength: undefined, - }]); + }); // line didn't change assert.equal(line.text, 'This is line one'); @@ -151,13 +153,15 @@ suite('ExtHostDocumentData', () => { test('offsetAt, after remove', function () { - data.onEvents([{ - range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 }, - text: '', + data.onEvents({ + changes: [{ + range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 }, + rangeLength: undefined, + text: '' + }], eol: undefined, versionId: undefined, - rangeLength: undefined, - }]); + }); assertOffsetAt(0, 1, 1); assertOffsetAt(0, 13, 13); @@ -166,13 +170,15 @@ suite('ExtHostDocumentData', () => { test('offsetAt, after replace', function () { - data.onEvents([{ - range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 }, - text: 'is could be', + data.onEvents({ + changes: [{ + range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 }, + rangeLength: undefined, + text: 'is could be' + }], eol: undefined, versionId: undefined, - rangeLength: undefined, - }]); + }); assertOffsetAt(0, 1, 1); assertOffsetAt(0, 24, 24); @@ -181,13 +187,15 @@ suite('ExtHostDocumentData', () => { test('offsetAt, after insert line', function () { - data.onEvents([{ - range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 }, - text: 'is could be\na line with number', + data.onEvents({ + changes: [{ + range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 }, + rangeLength: undefined, + text: 'is could be\na line with number' + }], eol: undefined, versionId: undefined, - rangeLength: undefined, - }]); + }); assertOffsetAt(0, 1, 1); assertOffsetAt(0, 13, 13); @@ -199,13 +207,15 @@ suite('ExtHostDocumentData', () => { test('offsetAt, after remove line', function () { - data.onEvents([{ - range: { startLineNumber: 1, startColumn: 3, endLineNumber: 2, endColumn: 6 }, - text: '', + data.onEvents({ + changes: [{ + range: { startLineNumber: 1, startColumn: 3, endLineNumber: 2, endColumn: 6 }, + rangeLength: undefined, + text: '' + }], eol: undefined, versionId: undefined, - rangeLength: undefined, - }]); + }); assertOffsetAt(0, 1, 1); assertOffsetAt(0, 2, 2); @@ -301,30 +311,32 @@ suite('ExtHostDocumentData updates line mapping', () => { } } - function createChangeEvent(range: CodeEditorRange, text: string, eol?: string): IModelChangedData { + function createChangeEvent(range: Range, text: string, eol?: string): IModelChangedEvent { return { - range: range, - text: text, + changes: [{ + range: range, + rangeLength: undefined, + text: text + }], eol: eol, versionId: undefined, - rangeLength: undefined, }; } - function testLineMappingDirectionAfterEvents(lines: string[], eol: string, direction: AssertDocumentLineMappingDirection, events: IModelChangedData[]): void { + function testLineMappingDirectionAfterEvents(lines: string[], eol: string, direction: AssertDocumentLineMappingDirection, e: IModelChangedEvent): void { let myDocument = new ExtHostDocumentData(undefined, URI.file(''), lines.slice(0), eol, 'text', 1, false); assertDocumentLineMapping(myDocument, direction); - myDocument.onEvents(events); + myDocument.onEvents(e); assertDocumentLineMapping(myDocument, direction); } - function testLineMappingAfterEvents(lines: string[], events: IModelChangedData[]): void { - testLineMappingDirectionAfterEvents(lines, '\n', AssertDocumentLineMappingDirection.PositionToOffset, events); - testLineMappingDirectionAfterEvents(lines, '\n', AssertDocumentLineMappingDirection.OffsetToPosition, events); + function testLineMappingAfterEvents(lines: string[], e: IModelChangedEvent): void { + testLineMappingDirectionAfterEvents(lines, '\n', AssertDocumentLineMappingDirection.PositionToOffset, e); + testLineMappingDirectionAfterEvents(lines, '\n', AssertDocumentLineMappingDirection.OffsetToPosition, e); - testLineMappingDirectionAfterEvents(lines, '\r\n', AssertDocumentLineMappingDirection.PositionToOffset, events); - testLineMappingDirectionAfterEvents(lines, '\r\n', AssertDocumentLineMappingDirection.OffsetToPosition, events); + testLineMappingDirectionAfterEvents(lines, '\r\n', AssertDocumentLineMappingDirection.PositionToOffset, e); + testLineMappingDirectionAfterEvents(lines, '\r\n', AssertDocumentLineMappingDirection.OffsetToPosition, e); } test('line mapping', () => { @@ -333,7 +345,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 }); }); test('after remove', () => { @@ -342,7 +354,7 @@ suite('ExtHostDocumentData updates line mapping', () => { 'and this is line number two', 'it is followed by #3', 'and finished with the fourth.', - ], [createChangeEvent(new CodeEditorRange(1, 3, 1, 6), '')]); + ], createChangeEvent(new Range(1, 3, 1, 6), '')); }); test('after replace', () => { @@ -351,7 +363,7 @@ suite('ExtHostDocumentData updates line mapping', () => { 'and this is line number two', 'it is followed by #3', 'and finished with the fourth.', - ], [createChangeEvent(new CodeEditorRange(1, 3, 1, 6), 'is could be')]); + ], createChangeEvent(new Range(1, 3, 1, 6), 'is could be')); }); test('after insert line', () => { @@ -360,7 +372,7 @@ suite('ExtHostDocumentData updates line mapping', () => { 'and this is line number two', 'it is followed by #3', 'and finished with the fourth.', - ], [createChangeEvent(new CodeEditorRange(1, 3, 1, 6), 'is could be\na line with number')]); + ], createChangeEvent(new Range(1, 3, 1, 6), 'is could be\na line with number')); }); test('after insert two lines', () => { @@ -369,7 +381,7 @@ suite('ExtHostDocumentData updates line mapping', () => { 'and this is line number two', 'it is followed by #3', 'and finished with the fourth.', - ], [createChangeEvent(new CodeEditorRange(1, 3, 1, 6), 'is could be\na line with number\nyet another line')]); + ], createChangeEvent(new Range(1, 3, 1, 6), 'is could be\na line with number\nyet another line')); }); test('after remove line', () => { @@ -378,7 +390,7 @@ suite('ExtHostDocumentData updates line mapping', () => { 'and this is line number two', 'it is followed by #3', 'and finished with the fourth.', - ], [createChangeEvent(new CodeEditorRange(1, 3, 2, 6), '')]); + ], createChangeEvent(new Range(1, 3, 2, 6), '')); }); test('after remove two lines', () => { @@ -387,7 +399,7 @@ suite('ExtHostDocumentData updates line mapping', () => { 'and this is line number two', 'it is followed by #3', 'and finished with the fourth.', - ], [createChangeEvent(new CodeEditorRange(1, 3, 3, 6), '')]); + ], createChangeEvent(new Range(1, 3, 3, 6), '')); }); test('after deleting entire content', () => { @@ -396,7 +408,7 @@ suite('ExtHostDocumentData updates line mapping', () => { 'and this is line number two', 'it is followed by #3', 'and finished with the fourth.', - ], [createChangeEvent(new CodeEditorRange(1, 3, 4, 30), '')]); + ], createChangeEvent(new Range(1, 3, 4, 30), '')); }); test('after replacing entire content', () => { @@ -405,7 +417,7 @@ suite('ExtHostDocumentData updates line mapping', () => { 'and this is line number two', 'it is followed by #3', 'and finished with the fourth.', - ], [createChangeEvent(new CodeEditorRange(1, 3, 4, 30), 'some new text\nthat\nspans multiple lines')]); + ], createChangeEvent(new Range(1, 3, 4, 30), 'some new text\nthat\nspans multiple lines')); }); test('after changing EOL to CRLF', () => { @@ -414,7 +426,7 @@ suite('ExtHostDocumentData updates line mapping', () => { 'and this is line number two', 'it is followed by #3', 'and finished with the fourth.', - ], [createChangeEvent(new CodeEditorRange(1, 1, 1, 1), '', '\r\n')]); + ], createChangeEvent(new Range(1, 1, 1, 1), '', '\r\n')); }); test('after changing EOL to LF', () => { @@ -423,6 +435,6 @@ suite('ExtHostDocumentData updates line mapping', () => { 'and this is line number two', 'it is followed by #3', 'and finished with the fourth.', - ], [createChangeEvent(new CodeEditorRange(1, 1, 1, 1), '', '\n')]); + ], createChangeEvent(new Range(1, 1, 1, 1), '', '\n')); }); }); diff --git a/src/vs/workbench/test/electron-browser/api/extHostDocumentSaveParticipant.test.ts b/src/vs/workbench/test/electron-browser/api/extHostDocumentSaveParticipant.test.ts index 4b913d8b289..9337d637623 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostDocumentSaveParticipant.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostDocumentSaveParticipant.test.ts @@ -285,12 +285,15 @@ suite('ExtHostDocumentSaveParticipant', () => { let sub = participant.onWillSaveTextDocumentEvent(function (e) { // concurrent change from somewhere - documents.$acceptModelChanged(resource.toString(), [{ - versionId: 2, - range: { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }, - text: 'bar', - rangeLength: undefined, eol: undefined - }], true); + documents.$acceptModelChanged(resource.toString(), { + changes: [{ + range: { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }, + rangeLength: undefined, + text: 'bar' + }], + eol: undefined, + versionId: 2 + }, true); e.waitUntil(TPromise.as([TextEdit.insert(new Position(0, 0), 'bar')])); }); @@ -310,12 +313,15 @@ suite('ExtHostDocumentSaveParticipant', () => { $applyWorkspaceEdit(_edits: IResourceEdit[]) { for (const { resource, newText, range } of _edits) { - documents.$acceptModelChanged(resource.toString(), [{ - range, - text: newText, - versionId: documents.getDocumentData(resource).version + 1, - rangeLength: undefined, eol: undefined - }], true); + documents.$acceptModelChanged(resource.toString(), { + changes: [{ + range, + rangeLength: undefined, + text: newText + }], + eol: undefined, + versionId: documents.getDocumentData(resource).version + 1 + }, true); } return TPromise.as(true); }