Skip to content

Commit 40a85d8

Browse files
authored
Merge pull request microsoft#227025 from microsoft/andreamah/issue227001
Old FileSearchProvider session not properly cancelled
2 parents c293d5a + 0e62f01 commit 40a85d8

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

src/vs/workbench/services/search/common/fileSearchManager.ts

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { URI } from 'vs/base/common/uri';
1313
import { IFileMatch, IFileSearchProviderStats, IFolderQuery, ISearchCompleteStats, IFileQuery, QueryGlobTester, resolvePatternsForProvider, hasSiblingFn, excludeToGlobPattern, DEFAULT_MAX_SEARCH_RESULTS } from 'vs/workbench/services/search/common/search';
1414
import { FileSearchProviderFolderOptions, FileSearchProviderNew, FileSearchProviderOptions } from 'vs/workbench/services/search/common/searchExtTypes';
1515
import { TernarySearchTree } from 'vs/base/common/ternarySearchTree';
16+
import { Disposable } from 'vs/base/common/lifecycle';
17+
import { OldFileSearchProviderConverter } from 'vs/workbench/services/search/common/searchExtConversionTypes';
1618

1719
interface IInternalFileMatch {
1820
base: URI;
@@ -53,7 +55,7 @@ class FileSearchEngine {
5355

5456
private globalExcludePattern?: glob.ParsedExpression;
5557

56-
constructor(private config: IFileQuery, private provider: FileSearchProviderNew, private sessionToken?: unknown) {
58+
constructor(private config: IFileQuery, private provider: FileSearchProviderNew, private sessionLifecycle?: SessionLifecycle) {
5759
this.filePattern = config.filePattern;
5860
this.includePattern = config.includePattern && glob.parse(config.includePattern);
5961
this.maxResults = config.maxResults || undefined;
@@ -116,10 +118,11 @@ class FileSearchEngine {
116118
private async doSearch(fqs: IFolderQuery<URI>[], onResult: (match: IInternalFileMatch) => void): Promise<IFileSearchProviderStats | null> {
117119
const cancellation = new CancellationTokenSource();
118120
const folderOptions = fqs.map(fq => this.getSearchOptionsForFolder(fq));
121+
const session = this.provider instanceof OldFileSearchProviderConverter ? this.sessionLifecycle?.tokenSource.token : this.sessionLifecycle?.obj;
119122
const options: FileSearchProviderOptions = {
120123
folderOptions,
121124
maxResults: this.config.maxResults ?? DEFAULT_MAX_SEARCH_RESULTS,
122-
session: this.sessionToken
125+
session
123126
};
124127

125128

@@ -301,11 +304,30 @@ interface IInternalSearchComplete {
301304
stats?: IFileSearchProviderStats;
302305
}
303306

307+
/**
308+
* For backwards compatibility, store both a cancellation token and a session object. The session object is the new implementation, where
309+
*/
310+
class SessionLifecycle extends Disposable {
311+
public readonly obj: object;
312+
public readonly tokenSource: CancellationTokenSource;
313+
314+
constructor() {
315+
super();
316+
this.obj = new Object();
317+
this.tokenSource = new CancellationTokenSource();
318+
}
319+
320+
public override dispose(): void {
321+
this.tokenSource.cancel();
322+
super.dispose();
323+
}
324+
}
325+
304326
export class FileSearchManager {
305327

306328
private static readonly BATCH_SIZE = 512;
307329

308-
private readonly sessions = new Map<string, unknown>();
330+
private readonly sessions = new Map<string, SessionLifecycle>();
309331

310332
fileSearch(config: IFileQuery, provider: FileSearchProviderNew, onBatch: (matches: IFileMatch[]) => void, token: CancellationToken): Promise<ISearchCompleteStats> {
311333
const sessionTokenSource = this.getSessionTokenSource(config.cacheKey);
@@ -333,17 +355,19 @@ export class FileSearchManager {
333355
}
334356

335357
clearCache(cacheKey: string): void {
358+
// cancel the token
359+
this.sessions.get(cacheKey)?.dispose();
336360
// with no reference to this, it will be removed from WeakMaps
337361
this.sessions.delete(cacheKey);
338362
}
339363

340-
private getSessionTokenSource(cacheKey: string | undefined): unknown {
364+
private getSessionTokenSource(cacheKey: string | undefined): SessionLifecycle | undefined {
341365
if (!cacheKey) {
342366
return undefined;
343367
}
344368

345369
if (!this.sessions.has(cacheKey)) {
346-
this.sessions.set(cacheKey, new Object());
370+
this.sessions.set(cacheKey, new SessionLifecycle());
347371
}
348372

349373
return this.sessions.get(cacheKey);

src/vscode-dts/vscode.proposed.fileSearchProviderNew.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ declare module 'vscode' {
5757
* and searches with the same session object can search the same cache. When the object is garbage-collected, the session is complete and the cache can be cleared.
5858
* Please do not store any references to the session object, except via a weak reference (e.g. `WeakRef` or `WeakMap`).
5959
*/
60-
session: unknown;
60+
session: object;
6161

6262
/**
6363
* The maximum number of results to be returned.

0 commit comments

Comments
 (0)