2
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
4
*--------------------------------------------------------------------------------------------*/
5
- import { CancellationToken } from 'vs/base/common/cancellation' ;
5
+ import { CancellationToken , CancellationTokenSource } from 'vs/base/common/cancellation' ;
6
6
import { IMatch } from 'vs/base/common/filters' ;
7
7
import { DisposableStore , IDisposable } from 'vs/base/common/lifecycle' ;
8
8
import { ResourceSet } from 'vs/base/common/map' ;
@@ -22,12 +22,12 @@ import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspac
22
22
import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor' ;
23
23
import { IViewsService } from 'vs/workbench/services/views/common/viewsService' ;
24
24
import { searchDetailsIcon , searchOpenInFileIcon , searchActivityBarIcon } from 'vs/workbench/contrib/search/browser/searchIcons' ;
25
- import { FileMatch , Match , RenderableMatch , SearchModel , searchComparer } from 'vs/workbench/contrib/search/browser/searchModel' ;
25
+ import { FileMatch , Match , RenderableMatch , SearchModel , SearchModelLocation , searchComparer } from 'vs/workbench/contrib/search/browser/searchModel' ;
26
26
import { SearchView , getEditorSelectionFromMatch } from 'vs/workbench/contrib/search/browser/searchView' ;
27
27
import { IWorkbenchSearchConfiguration , getOutOfWorkspaceEditorResources } from 'vs/workbench/contrib/search/common/search' ;
28
28
import { ACTIVE_GROUP , IEditorService , SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService' ;
29
29
import { ITextQueryBuilderOptions , QueryBuilder } from 'vs/workbench/services/search/common/queryBuilder' ;
30
- import { IPatternInfo , ITextQuery , VIEW_ID } from 'vs/workbench/services/search/common/search' ;
30
+ import { IPatternInfo , ISearchComplete , ITextQuery , VIEW_ID } from 'vs/workbench/services/search/common/search' ;
31
31
32
32
export const TEXT_SEARCH_QUICK_ACCESS_PREFIX = '%' ;
33
33
@@ -45,6 +45,10 @@ const MAX_RESULTS_PER_FILE = 10;
45
45
export class TextSearchQuickAccess extends PickerQuickAccessProvider < IPickerQuickAccessItem > {
46
46
private queryBuilder : QueryBuilder ;
47
47
private searchModel : SearchModel ;
48
+ private currentAsyncSearch : Promise < ISearchComplete > = Promise . resolve ( {
49
+ results : [ ] ,
50
+ messages : [ ]
51
+ } ) ;
48
52
49
53
private _getTextQueryBuilderOptions ( charsPerLine : number ) : ITextQueryBuilderOptions {
50
54
return {
@@ -74,6 +78,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<IPickerQuic
74
78
75
79
this . queryBuilder = this . _instantiationService . createInstance ( QueryBuilder ) ;
76
80
this . searchModel = this . _instantiationService . createInstance ( SearchModel ) ;
81
+ this . searchModel . location = SearchModelLocation . QUICK_ACCESS ;
77
82
}
78
83
79
84
override dispose ( ) : void {
@@ -89,7 +94,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<IPickerQuic
89
94
picker . customButton = true ;
90
95
picker . customLabel = '$(link-external)' ;
91
96
picker . onDidCustom ( ( ) => {
92
- this . moveToSearchViewlet ( this . searchModel , undefined ) ;
97
+ this . moveToSearchViewlet ( undefined ) ;
93
98
picker . hide ( ) ;
94
99
} ) ;
95
100
disposables . add ( super . provide ( picker , token , runOptions ) ) ;
@@ -137,6 +142,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<IPickerQuic
137
142
const result = this . searchModel . search ( query , undefined , token ) ;
138
143
139
144
const getAsyncResults = async ( ) => {
145
+ this . currentAsyncSearch = result . asyncResults ;
140
146
await result . asyncResults ;
141
147
const syncResultURIs = new ResourceSet ( result . syncResults . map ( e => e . resource ) ) ;
142
148
return this . searchModel . searchResult . matches ( ) . filter ( e => ! syncResultURIs . has ( e . resource ) ) ;
@@ -147,12 +153,15 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<IPickerQuic
147
153
} ;
148
154
}
149
155
150
- private moveToSearchViewlet ( model : SearchModel , currentElem : RenderableMatch | undefined ) {
151
- // this function takes this._searchModel.searchResult and moves it to the search viewlet's search model.
152
- // then, this._searchModel will construct a new (empty) SearchResult, and the search viewlet's search result will be disposed .
156
+ private moveToSearchViewlet ( currentElem : RenderableMatch | undefined ) {
157
+ // this function takes this._searchModel and moves it to the search viewlet's search model.
158
+ // then, this._searchModel will construct a new (empty) SearchModel .
153
159
this . _viewsService . openView ( VIEW_ID , false ) ;
154
160
const viewlet : SearchView | undefined = this . _viewsService . getActiveViewWithId ( VIEW_ID ) as SearchView ;
155
- viewlet . importSearchResult ( model ) ;
161
+ viewlet . replaceSearchModel ( this . searchModel , this . currentAsyncSearch ) ;
162
+
163
+ this . searchModel = this . _instantiationService . createInstance ( SearchModel ) ;
164
+ this . searchModel . location = SearchModelLocation . QUICK_ACCESS ;
156
165
157
166
const viewer : WorkbenchCompressibleObjectTree < RenderableMatch > | undefined = viewlet ?. getControl ( ) ;
158
167
if ( currentElem ) {
@@ -181,7 +190,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<IPickerQuic
181
190
label : localize ( 'QuickSearchSeeMoreFiles' , "See More Files" ) ,
182
191
iconClass : ThemeIcon . asClassName ( searchDetailsIcon ) ,
183
192
accept : async ( ) => {
184
- this . moveToSearchViewlet ( this . searchModel , matches [ limit ] ) ;
193
+ this . moveToSearchViewlet ( matches [ limit ] ) ;
185
194
}
186
195
} ) ;
187
196
break ;
@@ -212,7 +221,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<IPickerQuic
212
221
label : localize ( 'QuickSearchMore' , "More" ) ,
213
222
iconClass : ThemeIcon . asClassName ( searchDetailsIcon ) ,
214
223
accept : async ( ) => {
215
- this . moveToSearchViewlet ( this . searchModel , element ) ;
224
+ this . moveToSearchViewlet ( element ) ;
216
225
}
217
226
} ) ;
218
227
break ;
@@ -243,7 +252,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<IPickerQuic
243
252
} ) ;
244
253
} ,
245
254
trigger : ( ) : TriggerAction => {
246
- this . moveToSearchViewlet ( this . searchModel , element ) ;
255
+ this . moveToSearchViewlet ( element ) ;
247
256
return TriggerAction . CLOSE_PICKER ;
248
257
}
249
258
} ) ;
@@ -270,11 +279,22 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<IPickerQuic
270
279
271
280
protected _getPicks ( contentPattern : string , disposables : DisposableStore , token : CancellationToken ) : Picks < IQuickPickItem > | Promise < Picks < IQuickPickItem > | FastAndSlowPicks < IQuickPickItem > > | FastAndSlowPicks < IQuickPickItem > | null {
272
281
282
+ const conditionalTokenCts = disposables . add ( new CancellationTokenSource ( ) ) ;
283
+
284
+ const searchModelAtTimeOfSearch = this . searchModel ;
285
+
286
+ disposables . add ( token . onCancellationRequested ( ( ) => {
287
+ if ( searchModelAtTimeOfSearch . location === SearchModelLocation . QUICK_ACCESS ) {
288
+ // if the search model has not been imported to the panel, you can cancel
289
+ conditionalTokenCts . cancel ( ) ;
290
+ }
291
+ } ) ) ;
292
+
273
293
if ( contentPattern === '' ) {
274
294
this . searchModel . searchResult . clear ( ) ;
275
295
return [ ] ;
276
296
}
277
- const allMatches = this . doSearch ( contentPattern , token ) ;
297
+ const allMatches = this . doSearch ( contentPattern , conditionalTokenCts . token ) ;
278
298
279
299
if ( ! allMatches ) {
280
300
return null ;
0 commit comments