/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation'; import { OutputChannel } from 'vs/workbench/services/search/node/ripgrepSearchUtils'; import { RipgrepTextSearchEngine } from 'vs/workbench/services/search/node/ripgrepTextSearchEngine'; import { TextSearchProvider, TextSearchComplete, TextSearchResult, TextSearchQuery, TextSearchOptions } from 'vs/workbench/services/search/common/searchExtTypes'; import { Progress } from 'vs/platform/progress/common/progress'; export class RipgrepSearchProvider implements TextSearchProvider { private inProgress: Set = new Set(); constructor(private outputChannel: OutputChannel) { process.once('exit', () => this.dispose()); } provideTextSearchResults(query: TextSearchQuery, options: TextSearchOptions, progress: Progress, token: CancellationToken): Promise { const engine = new RipgrepTextSearchEngine(this.outputChannel); return this.withToken(token, token => engine.provideTextSearchResults(query, options, progress, token)); } private async withToken(token: CancellationToken, fn: (token: CancellationToken) => Promise): Promise { const merged = mergedTokenSource(token); this.inProgress.add(merged); const result = await fn(merged.token); this.inProgress.delete(merged); return result; } private dispose() { this.inProgress.forEach(engine => engine.cancel()); } } function mergedTokenSource(token: CancellationToken): CancellationTokenSource { const tokenSource = new CancellationTokenSource(); token.onCancellationRequested(() => tokenSource.cancel()); return tokenSource; }