Skip to content

Commit f0ec837

Browse files
committed
Recompute whitespace entirely in case of larger changes (microsoft#84726)
1 parent c003207 commit f0ec837

1 file changed

Lines changed: 43 additions & 42 deletions

File tree

src/vs/editor/common/viewLayout/linesLayout.ts

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -104,40 +104,20 @@ export class LinesLayout {
104104
private static INSTANCE_COUNT = 0;
105105

106106
private readonly _instanceId: string;
107-
108107
private readonly _pendingChanges: PendingChanges;
109-
110-
private readonly _arr: EditorWhitespace[];
111-
112-
/**
113-
* _arr[i].prefixSum, 1 <= i <= prefixSumValidIndex can be trusted
114-
*/
115-
private _prefixSumValidIndex: number;
116-
117-
/**
118-
* last whitespace id issued
119-
*/
120108
private _lastWhitespaceId: number;
121-
109+
private _arr: EditorWhitespace[];
110+
private _prefixSumValidIndex: number;
122111
private _minWidth: number;
123-
124-
/**
125-
* Keep track of the total number of lines.
126-
* This is useful for doing binary searches or for doing hit-testing.
127-
*/
128112
private _lineCount: number;
129-
130-
/**
131-
* The height of a line in pixels.
132-
*/
133113
private _lineHeight: number;
134114

135115
constructor(lineCount: number, lineHeight: number) {
136116
this._instanceId = strings.singleLetterHash(++LinesLayout.INSTANCE_COUNT);
137117
this._pendingChanges = new PendingChanges();
118+
this._lastWhitespaceId = 0;
138119
this._arr = [];
139120
this._prefixSumValidIndex = -1;
140-
this._lastWhitespaceId = 0;
141121
this._minWidth = -1; /* marker for not being computed */
142122
this._lineCount = lineCount;
143123
this._lineHeight = lineHeight;
@@ -200,18 +180,15 @@ export class LinesLayout {
200180
const id = this._instanceId + (++this._lastWhitespaceId);
201181
this._pendingChanges.insert(new EditorWhitespace(id, afterLineNumber, ordinal, heightInPx, minWidth));
202182
return id;
203-
// return this._insertWhitespace(afterLineNumber, ordinal, heightInPx, minWidth);
204183
},
205184
changeOneWhitespace: (id: string, newAfterLineNumber: number, newHeight: number): void => {
206185
newAfterLineNumber = newAfterLineNumber | 0;
207186
newHeight = newHeight | 0;
208187

209188
this._pendingChanges.change({ id, newAfterLineNumber, newHeight });
210-
// this._changeOneWhitespace(id, newAfterLineNumber, newHeight);
211189
},
212190
removeWhitespace: (id: string): void => {
213191
this._pendingChanges.remove({ id });
214-
// this._removeWhitespace(id);
215192
}
216193
};
217194
return callback(accessor);
@@ -221,17 +198,24 @@ export class LinesLayout {
221198
}
222199

223200
public _commitPendingChanges(inserts: EditorWhitespace[], changes: IPendingChange[], removes: IPendingRemove[]): void {
224-
if (!false || inserts.length + changes.length + removes.length <= 1) {
201+
if (inserts.length > 0 || removes.length > 0) {
202+
this._minWidth = -1; /* marker for not being computed */
203+
}
204+
205+
if (inserts.length + changes.length + removes.length <= 1) {
225206
// when only one thing happened, handle it "delicately"
226207
for (const insert of inserts) {
227208
this._insertWhitespace(insert);
228-
this._minWidth = -1; /* marker for not being computed */
229209
}
230210
for (const change of changes) {
231211
this._changeOneWhitespace(change.id, change.newAfterLineNumber, change.newHeight);
232212
}
233213
for (const remove of removes) {
234-
this._removeWhitespace(remove.id);
214+
const index = this._findWhitespaceIndex(remove.id);
215+
if (index === -1) {
216+
continue;
217+
}
218+
this._removeWhitespace(index);
235219
}
236220
return;
237221
}
@@ -248,12 +232,38 @@ export class LinesLayout {
248232
toChange.set(change.id, change);
249233
}
250234

251-
this._minWidth = -1; /* marker for not being computed */
235+
const applyRemoveAndChange = (whitespaces: EditorWhitespace[]): EditorWhitespace[] => {
236+
let result: EditorWhitespace[] = [];
237+
for (const whitespace of whitespaces) {
238+
if (toRemove.has(whitespace.id)) {
239+
continue;
240+
}
241+
if (toChange.has(whitespace.id)) {
242+
const change = toChange.get(whitespace.id)!;
243+
whitespace.afterLineNumber = change.newAfterLineNumber;
244+
whitespace.height = change.newHeight;
245+
}
246+
result.push(whitespace);
247+
}
248+
return result;
249+
};
250+
251+
const result = applyRemoveAndChange(this._arr).concat(applyRemoveAndChange(inserts));
252+
result.sort((a, b) => {
253+
if (a.afterLineNumber === b.afterLineNumber) {
254+
return a.ordinal - b.ordinal;
255+
}
256+
return a.afterLineNumber - b.afterLineNumber;
257+
});
258+
259+
this._arr = result;
260+
this._prefixSumValidIndex = -1;
252261
}
253262

254263
private _checkPendingChanges(): void {
255264
if (this._pendingChanges.mustCommit()) {
256-
console.log(`I should commit pending changes!`);//TODO
265+
console.warn(`Commiting pending changes before change accessor leaves due to read access.`);
266+
this._pendingChanges.commit(this);
257267
}
258268
}
259269

@@ -289,7 +299,7 @@ export class LinesLayout {
289299
const whitespace = this._arr[index];
290300

291301
// Since changing `afterLineNumber` can trigger a reordering, we're gonna remove this whitespace
292-
this._removeWhitespaceAtIndex(index);
302+
this._removeWhitespace(index);
293303

294304
whitespace.afterLineNumber = newAfterLineNumber;
295305

@@ -298,16 +308,7 @@ export class LinesLayout {
298308
}
299309
}
300310

301-
private _removeWhitespace(id: string): void {
302-
const index = this._findWhitespaceIndex(id);
303-
if (index === -1) {
304-
return;
305-
}
306-
this._removeWhitespaceAtIndex(index);
307-
this._minWidth = -1; /* marker for not being computed */
308-
}
309-
310-
private _removeWhitespaceAtIndex(removeIndex: number): void {
311+
private _removeWhitespace(removeIndex: number): void {
311312
this._arr.splice(removeIndex, 1);
312313
this._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, removeIndex - 1);
313314
}

0 commit comments

Comments
 (0)