Skip to content

Commit 95d7950

Browse files
authored
- when model changes race reset against real elements - some polish (microsoft#164017)
- when model changes race reset against real elements - some polish fixes microsoft#162128
1 parent 9d3fbb3 commit 95d7950

File tree

2 files changed

+69
-46
lines changed

2 files changed

+69
-46
lines changed

src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export class StickyScrollController extends Disposable implements IEditorContrib
7676
this._sessionStore.add(this._editor.onDidScrollChange(() => this.renderStickyScroll()));
7777
this._sessionStore.add(this._editor.onDidLayoutChange(() => this.onDidResize()));
7878
this._sessionStore.add(this._editor.onDidChangeModelTokens((e) => this.onTokensChange(e)));
79-
this._sessionStore.add(this._stickyLineCandidateProvider.onStickyScrollChange(() => this.renderStickyScroll()));
79+
this._sessionStore.add(this._stickyLineCandidateProvider.onDidChangeStickyScroll(() => this.renderStickyScroll()));
8080
const lineNumberOption = this._editor.getOption(EditorOption.lineNumbers);
8181
if (lineNumberOption.renderType === RenderLineNumbersType.Relative) {
8282
this._sessionStore.add(this._editor.onDidChangeCursorPosition(() => this.renderStickyScroll()));

src/vs/editor/contrib/stickyScroll/browser/stickyScrollProvider.ts

Lines changed: 68 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import { binarySearch } from 'vs/base/common/arrays';
1616
import { Iterable } from 'vs/base/common/iterator';
1717
import { FoldingController } from 'vs/editor/contrib/folding/browser/folding';
1818
import { FoldingModel } from 'vs/editor/contrib/folding/browser/foldingModel';
19+
import { URI } from 'vs/base/common/uri';
20+
import { isEqual } from 'vs/base/common/resources';
1921

2022
export class StickyRange {
2123
constructor(
@@ -33,19 +35,20 @@ export class StickyLineCandidate {
3335
}
3436

3537
export class StickyLineCandidateProvider extends Disposable {
36-
private readonly onStickyScrollChangeEmitter = this._register(new Emitter<void>());
37-
public readonly onStickyScrollChange = this.onStickyScrollChangeEmitter.event;
3838

3939
static readonly ID = 'store.contrib.stickyScrollController';
40+
41+
private readonly _onDidChangeStickyScroll = this._store.add(new Emitter<void>());
42+
public readonly onDidChangeStickyScroll = this._onDidChangeStickyScroll.event;
43+
4044
private readonly _editor: ICodeEditor;
4145
private readonly _languageFeaturesService: ILanguageFeaturesService;
4246
private readonly _updateSoon: RunOnceScheduler;
4347

44-
private _cts: CancellationTokenSource | undefined;
45-
private _outlineModel: StickyOutlineElement | undefined;
4648
private readonly _sessionStore: DisposableStore = new DisposableStore();
47-
private _modelVersionId: number = 0;
48-
private _providerID: string | undefined = undefined;
49+
private _cts: CancellationTokenSource | undefined;
50+
51+
private _model: StickyOutlineModel | undefined;
4952

5053
constructor(
5154
editor: ICodeEditor,
@@ -63,67 +66,81 @@ export class StickyLineCandidateProvider extends Disposable {
6366
this.readConfiguration();
6467
}
6568

69+
override dispose(): void {
70+
super.dispose();
71+
this._sessionStore.dispose();
72+
}
73+
6674
private readConfiguration() {
6775
const options = this._editor.getOption(EditorOption.stickyScroll);
6876
if (options.enabled === false) {
6977
this._sessionStore.clear();
7078
return;
7179
} else {
7280
this._sessionStore.add(this._editor.onDidChangeModel(() => {
73-
this._providerID = undefined;
7481
this.update();
7582
}));
7683
this._sessionStore.add(this._editor.onDidChangeHiddenAreas(() => this.update()));
7784
this._sessionStore.add(this._editor.onDidChangeModelContent(() => this._updateSoon.schedule()));
7885
this._sessionStore.add(this._languageFeaturesService.documentSymbolProvider.onDidChange(() => {
79-
this._providerID = undefined;
86+
8087
this.update();
8188
}));
8289
this.update();
8390
}
8491
}
8592

8693
public getVersionId() {
87-
return this._modelVersionId;
94+
return this._model?.version ?? -1;
8895
}
8996

9097
public async update(): Promise<void> {
9198
this._cts?.dispose(true);
9299
this._cts = new CancellationTokenSource();
93100
await this.updateOutlineModel(this._cts.token);
94-
this.onStickyScrollChangeEmitter.fire();
101+
this._onDidChangeStickyScroll.fire();
95102
}
96103

97-
private async updateOutlineModel(token: CancellationToken) {
98-
if (this._editor.hasModel()) {
99-
const model = this._editor.getModel();
100-
const modelVersionId = model.getVersionId();
101-
const outlineModel = await OutlineModel.create(this._languageFeaturesService.documentSymbolProvider, model, token) as OutlineModel;
104+
private async updateOutlineModel(token: CancellationToken): Promise<void> {
105+
if (!this._editor.hasModel()) {
106+
return;
107+
}
108+
109+
const model = this._editor.getModel();
110+
const modelVersionId = model.getVersionId();
111+
const isDifferentModel = this._model ? !isEqual(this._model.uri, model.uri) : false;
112+
113+
// clear sticky scroll to not show stale data for too long
114+
const resetHandle = isDifferentModel ? setTimeout(() => {
115+
if (!token.isCancellationRequested) {
116+
this._model = new StickyOutlineModel(model.uri, model.getVersionId(), undefined, undefined);
117+
this._onDidChangeStickyScroll.fire();
118+
}
119+
}, 75) : undefined;
120+
121+
// get elements from outline or folding model
122+
const outlineModel = await OutlineModel.create(this._languageFeaturesService.documentSymbolProvider, model, token);
123+
if (token.isCancellationRequested) {
124+
return;
125+
}
126+
if (outlineModel.children.size !== 0) {
127+
const { stickyOutlineElement, providerID } = StickyOutlineElement.fromOutlineModel(outlineModel, this._model?.outlineProviderId);
128+
this._model = new StickyOutlineModel(model.uri, modelVersionId, stickyOutlineElement, providerID);
129+
130+
} else {
131+
const foldingController = FoldingController.get(this._editor);
132+
const foldingModel = await foldingController?.getFoldingModel();
102133
if (token.isCancellationRequested) {
103134
return;
104135
}
105-
if (outlineModel.children.size !== 0) {
106-
const { stickyOutlineElement, providerID } = StickyOutlineElement.fromOutlineModel(outlineModel, this._providerID);
107-
this._outlineModel = stickyOutlineElement;
108-
this._providerID = providerID;
136+
if (foldingModel && foldingModel.regions.length !== 0) {
137+
const foldingElement = StickyOutlineElement.fromFoldingModel(foldingModel);
138+
this._model = new StickyOutlineModel(model.uri, modelVersionId, foldingElement, undefined);
109139
} else {
110-
const foldingController = FoldingController.get(this._editor);
111-
const foldingModel = await foldingController?.getFoldingModel();
112-
if (token.isCancellationRequested) {
113-
return;
114-
}
115-
if (foldingModel && foldingModel.regions.length !== 0) {
116-
this._outlineModel = StickyOutlineElement.fromFoldingModel(foldingModel);
117-
} else {
118-
this._outlineModel = new StickyOutlineElement(
119-
new StickyRange(-1, -1),
120-
[],
121-
undefined
122-
);
123-
}
140+
this._model = undefined;
124141
}
125-
this._modelVersionId = modelVersionId;
126142
}
143+
clearTimeout(resetHandle);
127144
}
128145

129146
private updateIndex(index: number) {
@@ -169,8 +186,11 @@ export class StickyLineCandidateProvider extends Disposable {
169186
}
170187

171188
public getCandidateStickyLinesIntersecting(range: StickyRange): StickyLineCandidate[] {
189+
if (!this._model?.element) {
190+
return [];
191+
}
172192
let stickyLineCandidates: StickyLineCandidate[] = [];
173-
this.getCandidateStickyLinesIntersectingFromOutline(range, this._outlineModel as StickyOutlineElement, stickyLineCandidates, 0, -1);
193+
this.getCandidateStickyLinesIntersectingFromOutline(range, this._model.element, stickyLineCandidates, 0, -1);
174194
const hiddenRanges: Range[] | undefined = this._editor._getViewModel()?.getHiddenAreas();
175195
if (hiddenRanges) {
176196
for (const hiddenRange of hiddenRanges) {
@@ -179,11 +199,6 @@ export class StickyLineCandidateProvider extends Disposable {
179199
}
180200
return stickyLineCandidates;
181201
}
182-
183-
override dispose(): void {
184-
super.dispose();
185-
this._sessionStore.dispose();
186-
}
187202
}
188203

189204
class StickyOutlineElement {
@@ -214,13 +229,12 @@ class StickyOutlineElement {
214229
return new StickyOutlineElement(range, children, undefined);
215230
}
216231

217-
public static fromOutlineModel(outlineModel: OutlineModel, providerID: string | undefined): { stickyOutlineElement: StickyOutlineElement; providerID: string | undefined } {
232+
public static fromOutlineModel(outlineModel: OutlineModel, preferredProvider: string | undefined): { stickyOutlineElement: StickyOutlineElement; providerID: string | undefined } {
218233

219-
let ID: string | undefined = providerID;
220234
let outlineElements: Map<string, OutlineElement>;
221235
// When several possible outline providers
222236
if (Iterable.first(outlineModel.children.values()) instanceof OutlineGroup) {
223-
const provider = Iterable.find(outlineModel.children.values(), outlineGroupOfModel => outlineGroupOfModel.id === providerID);
237+
const provider = Iterable.find(outlineModel.children.values(), outlineGroupOfModel => outlineGroupOfModel.id === preferredProvider);
224238
if (provider) {
225239
outlineElements = provider.children;
226240
} else {
@@ -235,7 +249,7 @@ class StickyOutlineElement {
235249
tempID = outlineGroup.id;
236250
}
237251
}
238-
ID = tempID;
252+
preferredProvider = tempID;
239253
outlineElements = optimalOutlineGroup!.children;
240254
}
241255
} else {
@@ -254,7 +268,7 @@ class StickyOutlineElement {
254268

255269
return {
256270
stickyOutlineElement: stickyOutlineElement,
257-
providerID: ID
271+
providerID: preferredProvider
258272
};
259273
}
260274

@@ -319,3 +333,12 @@ class StickyOutlineElement {
319333
) {
320334
}
321335
}
336+
337+
class StickyOutlineModel {
338+
constructor(
339+
readonly uri: URI,
340+
readonly version: number,
341+
readonly element: StickyOutlineElement | undefined,
342+
readonly outlineProviderId: string | undefined
343+
) { }
344+
}

0 commit comments

Comments
 (0)