Skip to content

Commit b859bde

Browse files
committed
Preserves collapsed range states
1 parent 5557c0b commit b859bde

File tree

5 files changed

+70
-22
lines changed

5 files changed

+70
-22
lines changed

src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
88
import { IObservable, IReader, ISettableObservable, ITransaction, derived, observableSignal, observableSignalFromEvent, observableValue, transaction, waitForState } from 'vs/base/common/observable';
99
import { autorunWithStore2 } from 'vs/base/common/observableImpl/autorun';
1010
import { isDefined } from 'vs/base/common/types';
11-
import { LineRange } from 'vs/editor/common/core/lineRange';
11+
import { ISerializedLineRange, LineRange } from 'vs/editor/common/core/lineRange';
1212
import { Range } from 'vs/editor/common/core/range';
1313
import { IDocumentDiff, IDocumentDiffProvider } from 'vs/editor/common/diff/documentDiffProvider';
1414
import { LineRangeMapping, MovedText, RangeMapping, SimpleLineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer';
@@ -137,20 +137,6 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo
137137
.filter(r => !!r)
138138
.map(r => LineRange.fromRange(r!));
139139

140-
for (const r of newUnchangedRegions) {
141-
for (let i = 0; i < lastUnchangedRegions.regions.length; i++) {
142-
if (r.originalRange.intersectsStrict(lastUnchangedRegionsOrigRanges[i])
143-
&& r.modifiedRange.intersectsStrict(lastUnchangedRegionsModRanges[i])) {
144-
r.setState(
145-
lastUnchangedRegions.regions[i].visibleLineCountTop.get(),
146-
lastUnchangedRegions.regions[i].visibleLineCountBottom.get(),
147-
undefined,
148-
);
149-
break;
150-
}
151-
}
152-
}
153-
154140
const originalDecorationIds = model.original.deltaDecorations(
155141
lastUnchangedRegions.originalDecorationIds,
156142
newUnchangedRegions.map(r => ({ range: r.originalRange.toInclusiveRange()!, options: { description: 'unchanged' } }))
@@ -161,6 +147,16 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo
161147
);
162148

163149
transaction(tx => {
150+
for (const r of newUnchangedRegions) {
151+
for (let i = 0; i < lastUnchangedRegions.regions.length; i++) {
152+
if (r.originalRange.intersectsStrict(lastUnchangedRegionsOrigRanges[i])
153+
&& r.modifiedRange.intersectsStrict(lastUnchangedRegionsModRanges[i])) {
154+
r.setHiddenModifiedRange(lastUnchangedRegions.regions[i].getHiddenModifiedRange(undefined), tx);
155+
break;
156+
}
157+
}
158+
}
159+
164160
this._lastDiff = result;
165161
this._diff.set(DiffState.fromDiffResult(result), tx);
166162
this._isDiffUpToDate.set(true, tx);
@@ -208,6 +204,32 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo
208204
public async waitForDiff(): Promise<void> {
209205
await waitForState(this.isDiffUpToDate, s => s);
210206
}
207+
208+
public serializeState(): SerializedState {
209+
const regions = this._unchangedRegions.get();
210+
return {
211+
collapsedRegions: regions.regions.map(r => ({ range: r.getHiddenModifiedRange(undefined).serialize() }))
212+
};
213+
}
214+
215+
public restoreSerializedState(state: SerializedState): void {
216+
const ranges = state.collapsedRegions.map(r => LineRange.deserialize(r.range));
217+
const regions = this._unchangedRegions.get();
218+
transaction(tx => {
219+
for (const r of regions.regions) {
220+
for (const range of ranges) {
221+
if (r.modifiedRange.intersect(range)) {
222+
r.setHiddenModifiedRange(range, tx);
223+
break;
224+
}
225+
}
226+
}
227+
});
228+
}
229+
}
230+
231+
interface SerializedState {
232+
collapsedRegions: { range: ISerializedLineRange }[];
211233
}
212234

213235
export class DiffState {
@@ -334,6 +356,12 @@ export class UnchangedRegion {
334356
);
335357
}
336358

359+
public setHiddenModifiedRange(range: LineRange, tx: ITransaction) {
360+
const visibleLineCountTop = range.startLineNumber - this.modifiedLineNumber;
361+
const visibleLineCountBottom = (this.modifiedLineNumber + this.lineCount) - range.endLineNumberExclusive;
362+
this.setState(visibleLineCountTop, visibleLineCountBottom, tx);
363+
}
364+
337365
public getMaxVisibleLineCountTop() {
338366
return this.lineCount - this._visibleLineCountBottom.get();
339367
}
@@ -357,8 +385,8 @@ export class UnchangedRegion {
357385
}
358386

359387
public setState(visibleLineCountTop: number, visibleLineCountBottom: number, tx: ITransaction | undefined): void {
360-
visibleLineCountTop = Math.min(visibleLineCountTop, this.lineCount);
361-
visibleLineCountBottom = Math.min(visibleLineCountBottom, this.lineCount - visibleLineCountTop);
388+
visibleLineCountTop = Math.max(Math.min(visibleLineCountTop, this.lineCount), 0);
389+
visibleLineCountBottom = Math.max(Math.min(visibleLineCountBottom, this.lineCount - visibleLineCountTop), 0);
362390

363391
this._visibleLineCountTop.set(visibleLineCountTop, tx);
364392
this._visibleLineCountBottom.set(visibleLineCountBottom, tx);

src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,8 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor {
283283
const modifiedViewState = this._editors.modified.saveViewState();
284284
return {
285285
original: originalViewState,
286-
modified: modifiedViewState
286+
modified: modifiedViewState,
287+
modelState: this._diffModel.get()?.serializeState(),
287288
};
288289
}
289290

@@ -292,6 +293,7 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor {
292293
const diffEditorState = s as IDiffEditorViewState;
293294
this._editors.original.restoreViewState(diffEditorState.original);
294295
this._editors.modified.restoreViewState(diffEditorState.modified);
296+
this._diffModel.get()?.restoreSerializedState(diffEditorState.modelState as any);
295297
}
296298
}
297299

src/vs/editor/common/core/lineRange.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ export class LineRange {
105105
return new LineRange(startLineNumber, startLineNumber + length);
106106
}
107107

108+
/**
109+
* @internal
110+
*/
111+
public static deserialize(lineRange: ISerializedLineRange): LineRange {
112+
return new LineRange(lineRange[0], lineRange[1]);
113+
}
114+
108115
/**
109116
* The start line number.
110117
*/
@@ -211,4 +218,13 @@ export class LineRange {
211218
}
212219
return result;
213220
}
221+
222+
/**
223+
* @internal
224+
*/
225+
public serialize(): ISerializedLineRange {
226+
return [this.startLineNumber, this.endLineNumberExclusive];
227+
}
214228
}
229+
230+
export type ISerializedLineRange = [startLineNumber: number, endLineNumberExclusive: number];

src/vs/editor/common/editorCommon.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import { Event } from 'vs/base/common/event';
67
import { IMarkdownString } from 'vs/base/common/htmlContent';
78
import { IDisposable } from 'vs/base/common/lifecycle';
8-
import { Event } from 'vs/base/common/event';
9+
import { ThemeColor } from 'vs/base/common/themables';
910
import { URI, UriComponents } from 'vs/base/common/uri';
1011
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
12+
import { IDimension } from 'vs/editor/common/core/dimension';
1113
import { IPosition, Position } from 'vs/editor/common/core/position';
1214
import { IRange, Range } from 'vs/editor/common/core/range';
1315
import { ISelection, Selection } from 'vs/editor/common/core/selection';
14-
import { IModelDecorationsChangeAccessor, ITextModel, OverviewRulerLane, TrackedRangeStickiness, IValidEditOperation, IModelDeltaDecoration, IModelDecoration } from 'vs/editor/common/model';
15-
import { ThemeColor } from 'vs/base/common/themables';
16-
import { IDimension } from 'vs/editor/common/core/dimension';
16+
import { IModelDecoration, IModelDecorationsChangeAccessor, IModelDeltaDecoration, ITextModel, IValidEditOperation, OverviewRulerLane, TrackedRangeStickiness } from 'vs/editor/common/model';
1717
import { IModelDecorationsChangedEvent } from 'vs/editor/common/textModelEvents';
1818

1919
/**
@@ -195,6 +195,7 @@ export interface ICodeEditorViewState {
195195
export interface IDiffEditorViewState {
196196
original: ICodeEditorViewState | null;
197197
modified: ICodeEditorViewState | null;
198+
modelState: unknown;
198199
}
199200
/**
200201
* An editor view state.

src/vs/monaco.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2707,6 +2707,7 @@ declare namespace monaco.editor {
27072707
export interface IDiffEditorViewState {
27082708
original: ICodeEditorViewState | null;
27092709
modified: ICodeEditorViewState | null;
2710+
modelState: unknown;
27102711
}
27112712

27122713
/**

0 commit comments

Comments
 (0)