Skip to content

Commit 0ee556c

Browse files
author
Benjamin Pasero
committed
goto symbol - proper cancellation and editor change handling
1 parent ee6a21f commit 0ee556c

2 files changed

Lines changed: 50 additions & 23 deletions

File tree

src/vs/editor/contrib/quickOpen/quickOpen.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ export function getDocumentSymbols(model: ITextModel, flat: boolean, token: Canc
3131

3232
return Promise.all(promises).then(() => {
3333
let flatEntries: DocumentSymbol[] = [];
34+
if (token.isCancellationRequested) {
35+
return flatEntries;
36+
}
3437
if (flat) {
3538
flatten(flatEntries, roots, '');
3639
} else {

src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { GroupIdentifier, IEditorInput } from 'vs/workbench/common/editor';
2727
import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
2828
import { IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsService';
2929
import { asThenable } from 'vs/base/common/async';
30-
import { CancellationToken } from 'vs/base/common/cancellation';
30+
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
3131

3232
export const GOTO_SYMBOL_PREFIX = '@';
3333
export const SCOPE_PREFIX = ':';
@@ -361,29 +361,47 @@ export class GotoSymbolHandler extends QuickOpenHandler {
361361

362362
static readonly ID = 'workbench.picker.filesymbols';
363363

364-
private outlineToModelCache: { [modelId: string]: OutlineModel; };
365364
private rangeHighlightDecorationId: IEditorLineDecoration;
366365
private lastKnownEditorViewState: IEditorViewState;
367366

367+
private cachedOutlineRequest: TPromise<OutlineModel>;
368+
private pendingOutlineRequest: CancellationTokenSource;
369+
368370
constructor(
369371
@IEditorService private editorService: IEditorService
370372
) {
371373
super();
372374

373-
this.outlineToModelCache = {};
375+
this.registerListeners();
376+
}
377+
378+
private registerListeners(): void {
379+
this.editorService.onDidActiveEditorChange(() => this.onDidActiveEditorChange());
380+
}
381+
382+
private onDidActiveEditorChange(): void {
383+
this.clearOutlineRequest();
384+
385+
this.lastKnownEditorViewState = void 0;
386+
this.rangeHighlightDecorationId = void 0;
374387
}
375388

376389
getResults(searchValue: string, token: CancellationToken): TPromise<QuickOpenModel> {
377390
searchValue = searchValue.trim();
378391

392+
// Support to cancel pending outline requests
393+
if (!this.pendingOutlineRequest) {
394+
this.pendingOutlineRequest = new CancellationTokenSource();
395+
}
396+
379397
// Remember view state to be able to restore on cancel
380398
if (!this.lastKnownEditorViewState) {
381399
const activeTextEditorWidget = this.editorService.activeTextEditorWidget;
382400
this.lastKnownEditorViewState = activeTextEditorWidget.saveViewState();
383401
}
384402

385403
// Resolve Outline Model
386-
return this.doGetActiveOutline(token).then(outline => {
404+
return this.getOutline().then(outline => {
387405
if (token.isCancellationRequested) {
388406
return outline;
389407
}
@@ -460,7 +478,15 @@ export class GotoSymbolHandler extends QuickOpenHandler {
460478
return results;
461479
}
462480

463-
private doGetActiveOutline(token: CancellationToken): TPromise<OutlineModel> {
481+
private getOutline(): TPromise<OutlineModel> {
482+
if (!this.cachedOutlineRequest) {
483+
this.cachedOutlineRequest = this.doGetActiveOutline();
484+
}
485+
486+
return this.cachedOutlineRequest;
487+
}
488+
489+
private doGetActiveOutline(): TPromise<OutlineModel> {
464490
const activeTextEditorWidget = this.editorService.activeTextEditorWidget;
465491
if (activeTextEditorWidget) {
466492
let model = activeTextEditorWidget.getModel();
@@ -469,20 +495,8 @@ export class GotoSymbolHandler extends QuickOpenHandler {
469495
}
470496

471497
if (model && types.isFunction((<ITextModel>model).getLanguageIdentifier)) {
472-
473-
// Ask cache first
474-
const modelId = (<ITextModel>model).id;
475-
if (this.outlineToModelCache[modelId]) {
476-
return TPromise.as(this.outlineToModelCache[modelId]);
477-
}
478-
479-
return TPromise.wrap(asThenable(() => getDocumentSymbols(<ITextModel>model, true, token)).then(entries => {
480-
const model = new OutlineModel(this.toQuickOpenEntries(entries));
481-
482-
this.outlineToModelCache = {}; // Clear cache, only keep 1 outline
483-
this.outlineToModelCache[modelId] = model;
484-
485-
return model;
498+
return TPromise.wrap(asThenable(() => getDocumentSymbols(<ITextModel>model, true, this.pendingOutlineRequest.token)).then(entries => {
499+
return new OutlineModel(this.toQuickOpenEntries(entries));
486500
}));
487501
}
488502
}
@@ -537,7 +551,7 @@ export class GotoSymbolHandler extends QuickOpenHandler {
537551
});
538552
}
539553

540-
clearDecorations(): void {
554+
private clearDecorations(): void {
541555
if (this.rangeHighlightDecorationId) {
542556
this.editorService.visibleControls.forEach(editor => {
543557
if (editor.group.id === this.rangeHighlightDecorationId.groupId) {
@@ -557,8 +571,8 @@ export class GotoSymbolHandler extends QuickOpenHandler {
557571

558572
onClose(canceled: boolean): void {
559573

560-
// Clear Cache
561-
this.outlineToModelCache = {};
574+
// Cancel any pending/cached outline request now
575+
this.clearOutlineRequest();
562576

563577
// Clear Highlight Decorations if present
564578
this.clearDecorations();
@@ -569,8 +583,18 @@ export class GotoSymbolHandler extends QuickOpenHandler {
569583
if (activeTextEditorWidget) {
570584
activeTextEditorWidget.restoreViewState(this.lastKnownEditorViewState);
571585
}
586+
587+
this.lastKnownEditorViewState = null;
588+
}
589+
}
590+
591+
private clearOutlineRequest(): void {
592+
if (this.pendingOutlineRequest) {
593+
this.pendingOutlineRequest.cancel();
594+
this.pendingOutlineRequest.dispose();
595+
this.pendingOutlineRequest = void 0;
572596
}
573597

574-
this.lastKnownEditorViewState = null;
598+
this.cachedOutlineRequest = null;
575599
}
576600
}

0 commit comments

Comments
 (0)