diff --git a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts index 631e2d1483a91ecd5934f274c8b87d84fc37487d..bfa416d8b519d54d5bb3f05849217d03db097d36 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts @@ -166,7 +166,7 @@ export class TrimFinalNewLinesParticipant implements ISaveParticipantParticipant currentLineIsEmptyOrWhitespace = strings.lastNonWhitespaceIndex(currentLine) === -1; } - const deletionRange = new Range(currentLineNumber + 1, 1, lineCount + 1, 1); + const deletionRange = model.validateRange(new Range(currentLineNumber + 1, 1, lineCount + 1, 1)); if (!deletionRange.isEmpty()) { model.pushEditOperations(prevSelection, [EditOperation.delete(deletionRange)], edits => prevSelection); } diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts index 995c2d814a84891a73a17440fc3fb178ae1a6631..f0465f76568840419532e82ce649feedd0bc420d 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts @@ -139,4 +139,31 @@ suite('MainThreadSaveParticipant', function () { }); }); + test('trim final new lines bug#46075', function () { + const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8'); + + return model.load().then(() => { + const configService = new TestConfigurationService(); + configService.setUserConfiguration('files', { 'trimFinalNewlines': true }); + + const participant = new TrimFinalNewLinesParticipant(configService, undefined); + + const textContent = 'Test'; + const eol = `${model.textEditorModel.getEOL()}`; + + let content = `${textContent}${eol}${eol}`; + model.textEditorModel.setValue(content); + // save many times + for (let i = 0; i < 10; i++) { + participant.participate(model, { reason: SaveReason.EXPLICIT }); + } + // confirm trimming + assert.equal(snapshotToString(model.createSnapshot()), `${textContent}${eol}`); + // undo should go back to previous content immediately + model.textEditorModel.undo(); + assert.equal(snapshotToString(model.createSnapshot()), `${textContent}${eol}${eol}`); + model.textEditorModel.redo(); + assert.equal(snapshotToString(model.createSnapshot()), `${textContent}${eol}`); + }); + }); });