@@ -27,7 +27,7 @@ import { GroupIdentifier, IEditorInput } from 'vs/workbench/common/editor';
2727import { IEditorService , SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService' ;
2828import { IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsService' ;
2929import { asThenable } from 'vs/base/common/async' ;
30- import { CancellationToken } from 'vs/base/common/cancellation' ;
30+ import { CancellationToken , CancellationTokenSource } from 'vs/base/common/cancellation' ;
3131
3232export const GOTO_SYMBOL_PREFIX = '@' ;
3333export 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