Fixes #2586: Both model content change event strategies should reach the same versionId; Do not guess composition case in textareaState if text contains new line

This commit is contained in:
Alex Dima 2016-02-04 16:47:08 +01:00
parent db2464fa4c
commit dd751e45ee
4 changed files with 49 additions and 5 deletions

View file

@ -163,7 +163,13 @@ export abstract class TextAreaState {
if (currentSelectionStart === currentSelectionEnd) {
// composition accept case
// [blahblah] => blahblah|
if (previousValue === currentValue && previousSelectionStart === 0 && previousSelectionEnd === previousValue.length && currentSelectionStart === currentValue.length) {
if (
previousValue === currentValue
&& previousSelectionStart === 0
&& previousSelectionEnd === previousValue.length
&& currentSelectionStart === currentValue.length
&& currentValue.indexOf('\n') === -1
) {
return {
text: '',
replaceCharCnt: 0

View file

@ -334,6 +334,9 @@ export class EditableTextModel extends TextModelWithDecorations implements Edito
currentLineEdits: ILineEdit[] = [],
currentLineNumber = 0;
var lastContentChangedVersionId = this.getVersionId();
let lastContentChanged2VersionId = this.getVersionId();
var adjustLineNumbers = (toLineNumber:number, delta:number): void => {
// console.log('adjustLineNumbers: ' + toLineNumber + ' by ' + delta + ', lines.length: ' + this._lines.length);
if (delta !== 0) {
@ -351,6 +354,7 @@ export class EditableTextModel extends TextModelWithDecorations implements Edito
if (editLineNumber !== currentLineNumber) {
if (currentLineEdits.length > 0) {
this._applyLineEdits(deferredEventsBuilder, currentLineNumber, currentLineEdits);
lastContentChangedVersionId = this.getVersionId();
currentLineEdits = [];
}
currentLineNumber = editLineNumber;
@ -374,14 +378,13 @@ export class EditableTextModel extends TextModelWithDecorations implements Edito
var r = 0;
if (currentLineEdits.length > 0) {
r = this._applyLineEdits(deferredEventsBuilder, currentLineNumber, currentLineEdits);
lastContentChangedVersionId = this.getVersionId();
currentLineEdits = [];
}
currentLineNumber = 0;
return r;
};
let lastContentChanged2VersionId = this.getVersionId();
let lastRealOpIndex = 0;
for (let i = operations.length - 1; i >= 0; i--) {
if (!operations[i].isNoOp) {
@ -483,6 +486,7 @@ export class EditableTextModel extends TextModelWithDecorations implements Edito
this.emitModelContentChangedLineChangedEvent(spliceStart);
this.emitModelContentChangedLinesDeletedEvent(spliceStart + 1, spliceStart + spliceCnt);
lastContentChangedVersionId = this.getVersionId();
// this.emitModelContentChangedLinesInsertedEvent(startLineNumber + editingLinesCnt + 1, startLineNumber + insertingLinesCnt, newLinesContent.join('\n'));
}
@ -521,6 +525,7 @@ export class EditableTextModel extends TextModelWithDecorations implements Edito
this._lines[startLineNumber + insertingLinesCnt - 1].append(deferredEventsBuilder.changedMarkers, leftoverLine);
this.emitModelContentChangedLinesInsertedEvent(startLineNumber + editingLinesCnt + 1, startLineNumber + insertingLinesCnt, newLinesContent.join('\n'));
lastContentChangedVersionId = this.getVersionId();
}
// console.log('~~~');
@ -548,6 +553,10 @@ export class EditableTextModel extends TextModelWithDecorations implements Edito
this._emitContentChanged2(seqEdit.range.startLineNumber, seqEdit.range.startColumn, seqEdit.range.endLineNumber, seqEdit.range.endColumn, seqEdit.rangeLength, seqEdit.text, this._isUndoing, this._isRedoing);
}
if (this.getVersionId() > lastContentChangedVersionId) {
// TODO@Alex: need to rewrite the eventing logic
this.emitModelContentChangedLineChangedEventNoVersionBump(baseLineNumber);
}
adjustLineNumbers(this._lines.length, deltaLines);
});
@ -687,8 +696,7 @@ export class EditableTextModel extends TextModelWithDecorations implements Edito
}
}
private emitModelContentChangedLineChangedEvent(lineNumber: number): void {
this._increaseVersionId();
private emitModelContentChangedLineChangedEventNoVersionBump(lineNumber: number): void {
var e:EditorCommon.IModelContentChangedLineChangedEvent = {
changeType: EditorCommon.EventType.ModelContentChangedLineChanged,
lineNumber: lineNumber,
@ -702,6 +710,11 @@ export class EditableTextModel extends TextModelWithDecorations implements Edito
}
}
private emitModelContentChangedLineChangedEvent(lineNumber: number): void {
this._increaseVersionId();
this.emitModelContentChangedLineChangedEventNoVersionBump(lineNumber);
}
private emitModelContentChangedLinesDeletedEvent(fromLineNumber: number, toLineNumber: number): void {
this._increaseVersionId();
var e:EditorCommon.IModelContentChangedLinesDeletedEvent = {

View file

@ -230,6 +230,15 @@ suite('TextAreaState', () => {
);
});
test('issue #2586: Replacing selected end-of-line with newline locks up the document', () => {
testDeduceInput(
new IENarratorTextAreaState(null, ']\n', 1, 2, false, 0),
']\n',
2, 2, false,
'\n', 0
);
});
test('extractNewText - no previous state without selection', () => {
testDeduceInput(
null,

View file

@ -1174,6 +1174,22 @@ suite('EditorModel - EditableTextModel.applyEdits', () => {
);
});
test('issue #2586 Replacing selected end-of-line with newline locks up the document', () => {
testApplyEdits(
[
'something',
'interesting'
],
[
editOp(1, 10, 2, 1, ['', ''])
],
[
'something',
'interesting'
]
);
});
function assertSyncedModels(text:string, callback:(model:EditableTextModel, assertMirrorModels:()=>void)=>void, setup:(model:EditableTextModel)=>void = null): void {
var model = new EditableTextModel([], TextModel.toRawText(text), null);
model.setEOL(EditorCommon.EndOfLineSequence.LF);