Skip to content

Commit 1b2ae42

Browse files
committed
Fixes microsoft#1580: sync eol change to extension host documents
1 parent 2de43b8 commit 1b2ae42

5 files changed

Lines changed: 71 additions & 1 deletion

File tree

src/vs/editor/common/editorCommon.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,6 +1859,10 @@ export interface IModelContentChangedEvent2 {
18591859
* The new text for the range.
18601860
*/
18611861
text: string;
1862+
/**
1863+
* The end-of-line character.
1864+
*/
1865+
eol: string;
18621866
/**
18631867
* The new version id the model has transitioned to.
18641868
*/

src/vs/editor/common/model/mirrorModel2.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@ export class MirrorModel2 {
3636
}
3737

3838
onEvents(events: IModelContentChangedEvent2[]): void {
39+
let newEOL: string = null;
40+
for (let i = 0, len = events.length; i < len; i++) {
41+
let e = events[i];
42+
if (e.eol) {
43+
newEOL = e.eol;
44+
}
45+
}
46+
if (newEOL && newEOL !== this._eol) {
47+
this._eol = newEOL;
48+
this._lineStarts = null;
49+
}
50+
3951
// Update my lines
4052
let lastVersionId = -1;
4153
for (let i = 0, len = events.length; i < len; i++) {

src/vs/editor/common/model/textModel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements EditorCommo
124124
range: new Range(startLineNumber, startColumn, endLineNumber, endColumn),
125125
rangeLength: rangeLength,
126126
text: text,
127+
eol: this._EOL,
127128
versionId: this.getVersionId(),
128129
isUndoing: isUndoing,
129130
isRedoing: isRedoing

src/vs/editor/test/common/model/editableTextModel.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,35 @@ suite('EditorModel - EditableTextModel.applyEdits', () => {
12841284
});
12851285
});
12861286
});
1287+
1288+
test('issue #1580: Changes in line endings are not correctly reflected in the extension host, leading to invalid offsets sent to external refactoring tools', () => {
1289+
let model = new EditableTextModel([], TextModel.toRawText('Hello\nWorld!'), null);
1290+
assert.equal(model.getEOL(), '\n');
1291+
1292+
let mirrorModel2 = new MirrorModel2(null, model.toRawText().lines, model.toRawText().EOL, model.getVersionId());
1293+
let mirrorModel2PrevVersionId = model.getVersionId();
1294+
1295+
model.addListener(EditorCommon.EventType.ModelContentChanged2, (e:EditorCommon.IModelContentChangedEvent2) => {
1296+
let versionId = e.versionId;
1297+
if (versionId < mirrorModel2PrevVersionId) {
1298+
console.warn('Model version id did not advance between edits (2)');
1299+
}
1300+
mirrorModel2PrevVersionId = versionId;
1301+
mirrorModel2.onEvents([e]);
1302+
});
1303+
1304+
let assertMirrorModels = () => {
1305+
model._assertLineNumbersOK();
1306+
assert.equal(mirrorModel2.getText(), model.getValue(), 'mirror model 2 text OK');
1307+
assert.equal(mirrorModel2.version, model.getVersionId(), 'mirror model 2 version OK');
1308+
};
1309+
1310+
model.setEOL(EditorCommon.EndOfLineSequence.CRLF);
1311+
assertMirrorModels();
1312+
1313+
model.dispose();
1314+
mirrorModel2.dispose();
1315+
});
12871316
});
12881317

12891318
interface ILightWeightMarker {

src/vs/workbench/test/common/api/extHostDocuments.test.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ suite("PluginHostDocument", () => {
6969
data.onEvents([{
7070
range: { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 },
7171
text: '\t ',
72+
eol: undefined,
7273
isRedoing: undefined,
7374
isUndoing: undefined,
7475
versionId: undefined,
@@ -105,6 +106,7 @@ suite("PluginHostDocument", () => {
105106
data.onEvents([{
106107
range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 },
107108
text: '',
109+
eol: undefined,
108110
isRedoing: undefined,
109111
isUndoing: undefined,
110112
versionId: undefined,
@@ -121,6 +123,7 @@ suite("PluginHostDocument", () => {
121123
data.onEvents([{
122124
range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 },
123125
text: 'is could be',
126+
eol: undefined,
124127
isRedoing: undefined,
125128
isUndoing: undefined,
126129
versionId: undefined,
@@ -137,6 +140,7 @@ suite("PluginHostDocument", () => {
137140
data.onEvents([{
138141
range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 },
139142
text: 'is could be\na line with number',
143+
eol: undefined,
140144
isRedoing: undefined,
141145
isUndoing: undefined,
142146
versionId: undefined,
@@ -156,6 +160,7 @@ suite("PluginHostDocument", () => {
156160
data.onEvents([{
157161
range: { startLineNumber: 1, startColumn: 3, endLineNumber: 2, endColumn: 6 },
158162
text: '',
163+
eol: undefined,
159164
isRedoing: undefined,
160165
isUndoing: undefined,
161166
versionId: undefined,
@@ -222,10 +227,11 @@ suite("PluginHostDocument updates line mapping", () => {
222227
}
223228
}
224229

225-
function createChangeEvent(range:CodeEditorRange, text:string): EditorCommon.IModelContentChangedEvent2 {
230+
function createChangeEvent(range:CodeEditorRange, text:string, eol?:string): EditorCommon.IModelContentChangedEvent2 {
226231
return {
227232
range: range,
228233
text: text,
234+
eol: eol,
229235
isRedoing: undefined,
230236
isUndoing: undefined,
231237
versionId: undefined,
@@ -329,4 +335,22 @@ suite("PluginHostDocument updates line mapping", () => {
329335
'and finished with the fourth.',
330336
], [createChangeEvent(new CodeEditorRange(1, 3, 4, 30), 'some new text\nthat\nspans multiple lines')]);
331337
});
338+
339+
test('after changing EOL to CRLF', () => {
340+
testLineMappingAfterEvents([
341+
'This is line one',
342+
'and this is line number two',
343+
'it is followed by #3',
344+
'and finished with the fourth.',
345+
], [createChangeEvent(new CodeEditorRange(1, 1, 1, 1), '', '\r\n')]);
346+
});
347+
348+
test('after changing EOL to LF', () => {
349+
testLineMappingAfterEvents([
350+
'This is line one',
351+
'and this is line number two',
352+
'it is followed by #3',
353+
'and finished with the fourth.',
354+
], [createChangeEvent(new CodeEditorRange(1, 1, 1, 1), '', '\n')]);
355+
});
332356
});

0 commit comments

Comments
 (0)