diff --git a/src/vs/workbench/services/search/common/search.ts b/src/vs/workbench/services/search/common/search.ts index 6973bb23b628907077786408f2bdd734c3f9b31c..58fc5fb9df7a9fd740ecf001c4cffc13b8aac438 100644 --- a/src/vs/workbench/services/search/common/search.ts +++ b/src/vs/workbench/services/search/common/search.ts @@ -181,13 +181,19 @@ export function resultIsMatch(result: ITextSearchResult): result is ITextSearchM return !!(result).preview; } -export interface IProgress { - total?: number; - worked?: number; +export interface IProgressMessage { message?: string; } -export type ISearchProgressItem = IFileMatch | IProgress; +export type ISearchProgressItem = IFileMatch | IProgressMessage; + +export function isFileMatch(p: ISearchProgressItem): p is IFileMatch { + return !!(p).resource; +} + +export function isProgressMessage(p: ISearchProgressItem): p is IProgressMessage { + return !isFileMatch(p); +} export interface ISearchCompleteStats { limitHit?: boolean; @@ -410,7 +416,7 @@ export interface IRawFileMatch { } export interface ISearchEngine { - search: (onResult: (matches: T) => void, onProgress: (progress: IProgress) => void, done: (error: Error | null, complete: ISearchEngineSuccess) => void) => void; + search: (onResult: (matches: T) => void, onProgress: (progress: IProgressMessage) => void, done: (error: Error | null, complete: ISearchEngineSuccess) => void) => void; cancel: () => void; } @@ -460,8 +466,8 @@ export interface ISerializedFileMatch { } // Type of the possible values for progress calls from the engine -export type ISerializedSearchProgressItem = ISerializedFileMatch | ISerializedFileMatch[] | IProgress; -export type IFileSearchProgressItem = IRawFileMatch | IRawFileMatch[] | IProgress; +export type ISerializedSearchProgressItem = ISerializedFileMatch | ISerializedFileMatch[] | IProgressMessage; +export type IFileSearchProgressItem = IRawFileMatch | IRawFileMatch[] | IProgressMessage; export class SerializableFileMatch implements ISerializedFileMatch { diff --git a/src/vs/workbench/services/search/node/fileSearch.ts b/src/vs/workbench/services/search/node/fileSearch.ts index c9db0fc66ffde99170a188c07aa5f7eb4f474a3a..2cf8da8fddcb89f3dff48e679a22dda1a2aa437b 100644 --- a/src/vs/workbench/services/search/node/fileSearch.ts +++ b/src/vs/workbench/services/search/node/fileSearch.ts @@ -21,7 +21,7 @@ import * as types from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import * as extfs from 'vs/base/node/extfs'; import * as flow from 'vs/base/node/flow'; -import { IFileQuery, IFolderQuery, IProgress, ISearchEngineStats, IRawFileMatch, ISearchEngine, ISearchEngineSuccess } from 'vs/workbench/services/search/common/search'; +import { IFileQuery, IFolderQuery, IProgressMessage, ISearchEngineStats, IRawFileMatch, ISearchEngine, ISearchEngineSuccess } from 'vs/workbench/services/search/common/search'; import { spawnRipgrepCmd } from './ripgrepFileSearch'; interface IDirectoryEntry { @@ -106,7 +106,7 @@ export class FileWalker { this.isCanceled = true; } - walk(folderQueries: IFolderQuery[], extraFiles: URI[], onResult: (result: IRawFileMatch) => void, onMessage: (message: IProgress) => void, done: (error: Error | null, isLimitHit: boolean) => void): void { + walk(folderQueries: IFolderQuery[], extraFiles: URI[], onResult: (result: IRawFileMatch) => void, onMessage: (message: IProgressMessage) => void, done: (error: Error | null, isLimitHit: boolean) => void): void { this.fileWalkSW = StopWatch.create(false); // Support that the file pattern is a full path to a file that exists @@ -154,7 +154,7 @@ export class FileWalker { } } - private cmdTraversal(folderQuery: IFolderQuery, onResult: (result: IRawFileMatch) => void, onMessage: (message: IProgress) => void, cb: (err?: Error) => void): void { + private cmdTraversal(folderQuery: IFolderQuery, onResult: (result: IRawFileMatch) => void, onMessage: (message: IProgressMessage) => void, cb: (err?: Error) => void): void { const rootFolder = folderQuery.folder.fsPath; const isMac = platform.isMacintosh; let cmd: childProcess.ChildProcess; @@ -285,7 +285,7 @@ export class FileWalker { }); } - private collectStdout(cmd: childProcess.ChildProcess, encoding: string, onMessage: (message: IProgress) => void, cb: (err: Error | null, stdout?: string, last?: boolean) => void): void { + private collectStdout(cmd: childProcess.ChildProcess, encoding: string, onMessage: (message: IProgressMessage) => void, cb: (err: Error | null, stdout?: string, last?: boolean) => void): void { let onData = (err: Error | null, stdout?: string, last?: boolean) => { if (err || last) { onData = () => { }; @@ -590,7 +590,7 @@ export class Engine implements ISearchEngine { this.walker = new FileWalker(config); } - search(onResult: (result: IRawFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISearchEngineSuccess) => void): void { + search(onResult: (result: IRawFileMatch) => void, onProgress: (progress: IProgressMessage) => void, done: (error: Error, complete: ISearchEngineSuccess) => void): void { this.walker.walk(this.folderQueries, this.extraFiles, onResult, onProgress, (err: Error, isLimitHit: boolean) => { done(err, { limitHit: isLimitHit, diff --git a/src/vs/workbench/services/search/node/fileSearchManager.ts b/src/vs/workbench/services/search/node/fileSearchManager.ts index 5f9cc9add44ade57ac5c9aa2fbb6ee72fae24ef4..d78ded834d1bb13b69b5266b0831a4fcec1c4389 100644 --- a/src/vs/workbench/services/search/node/fileSearchManager.ts +++ b/src/vs/workbench/services/search/node/fileSearchManager.ts @@ -344,7 +344,7 @@ export class FileSearchManager { engine.cancel(); }); - const _onResult = match => { + const _onResult = (match: IInternalFileMatch) => { if (match) { batch.push(match); if (batchSize > 0 && batch.length >= batchSize) { diff --git a/src/vs/workbench/services/search/node/rawSearchService.ts b/src/vs/workbench/services/search/node/rawSearchService.ts index 7c6bf16feb897badba867f8c1852c6656afec5ed..1d5ed2ca55e66cda72909866b79343bc91f093e5 100644 --- a/src/vs/workbench/services/search/node/rawSearchService.ts +++ b/src/vs/workbench/services/search/node/rawSearchService.ts @@ -17,14 +17,14 @@ import * as strings from 'vs/base/common/strings'; import { URI, UriComponents } from 'vs/base/common/uri'; import { compareItemsByScore, IItemAccessor, prepareQuery, ScorerCache } from 'vs/base/parts/quickopen/common/quickOpenScorer'; import { MAX_FILE_SIZE } from 'vs/platform/files/node/fileConstants'; -import { ICachedSearchStats, IFileQuery, IFileSearchStats, IFolderQuery, IProgress, IRawFileQuery, IRawQuery, IRawTextQuery, ITextQuery, IFileSearchProgressItem, IRawFileMatch, IRawSearchService, ISearchEngine, ISearchEngineSuccess, ISerializedFileMatch, ISerializedSearchComplete, ISerializedSearchProgressItem, ISerializedSearchSuccess } from 'vs/workbench/services/search/common/search'; +import { ICachedSearchStats, IFileQuery, IFileSearchStats, IFolderQuery, IProgressMessage, IRawFileQuery, IRawQuery, IRawTextQuery, ITextQuery, IFileSearchProgressItem, IRawFileMatch, IRawSearchService, ISearchEngine, ISearchEngineSuccess, ISerializedFileMatch, ISerializedSearchComplete, ISerializedSearchProgressItem, ISerializedSearchSuccess } from 'vs/workbench/services/search/common/search'; import { Engine as FileSearchEngine } from 'vs/workbench/services/search/node/fileSearch'; import { TextSearchEngineAdapter } from 'vs/workbench/services/search/node/textSearchAdapter'; gracefulFs.gracefulify(fs); -type IProgressCallback = (p: ISerializedSearchProgressItem) => void; -type IFileProgressCallback = (p: IFileSearchProgressItem) => void; +export type IProgressCallback = (p: ISerializedSearchProgressItem) => void; +export type IFileProgressCallback = (p: IFileSearchProgressItem) => void; export class SearchService implements IRawSearchService { @@ -97,7 +97,7 @@ export class SearchService implements IRawSearchService { resultCount++; progressCallback(this.rawMatchToSearchItem(progress)); } else { - progressCallback(progress); + progressCallback(progress); } }; @@ -383,13 +383,13 @@ export class SearchService implements IRawSearchService { cancel() { // Do nothing } - then(resolve, reject) { + then(resolve: any, reject: any) { return promise.then(resolve, reject); } - catch(reject?) { + catch(reject?: any) { return this.then(undefined, reject); } - finally(onFinally) { + finally(onFinally: any) { return promise.finally(onFinally); } }; diff --git a/src/vs/workbench/services/search/node/ripgrepSearchUtils.ts b/src/vs/workbench/services/search/node/ripgrepSearchUtils.ts index 3d8e787c3427a089e2febc4c0bc052faaf14b6c3..e14cc3372ad6afcbb5931a3c6c6dca1074e69004 100644 --- a/src/vs/workbench/services/search/node/ripgrepSearchUtils.ts +++ b/src/vs/workbench/services/search/node/ripgrepSearchUtils.ts @@ -42,7 +42,7 @@ function searchRangeToRange(range: SearchRange): Range { } export class Position { - constructor(readonly line, readonly character) { } + constructor(readonly line: number, readonly character: number) { } isBefore(other: Position): boolean { return false; } isBeforeOrEqual(other: Position): boolean { return false; } diff --git a/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts b/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts index f201ae9dc01dd8d038c77db9a9bffd20ce4083af..ee16b5b7e41accf8be437fcc7e2cb1a59bd68fbd 100644 --- a/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts +++ b/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts @@ -165,10 +165,11 @@ export class RipgrepParser extends EventEmitter { } - on(event: 'result', listener: (result: vscode.TextSearchResult) => void); - on(event: 'hitLimit', listener: () => void); - on(event: string, listener: (...args: any[]) => void) { + on(event: 'result', listener: (result: vscode.TextSearchResult) => void): this; + on(event: 'hitLimit', listener: () => void): this; + on(event: string, listener: (...args: any[]) => void): this { super.on(event, listener); + return this; } handleData(data: Buffer | string): void { diff --git a/src/vs/workbench/services/search/node/searchService.ts b/src/vs/workbench/services/search/node/searchService.ts index 705148d4cc95e39618d5c0c8e8710ab6437bc518..c378fda6f10be039e2b0f68633ceed66cd20032b 100644 --- a/src/vs/workbench/services/search/node/searchService.ts +++ b/src/vs/workbench/services/search/node/searchService.ts @@ -26,7 +26,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import { deserializeSearchError, FileMatch, ICachedSearchStats, IFileMatch, IFileQuery, IFileSearchStats, IFolderQuery, IProgress, IRawSearchService, ISearchComplete, ISearchConfiguration, ISearchEngineStats, ISearchProgressItem, ISearchQuery, ISearchResultProvider, ISearchService, ISerializedFileMatch, ISerializedSearchComplete, ISerializedSearchProgressItem, isSerializedSearchComplete, isSerializedSearchSuccess, ITextQuery, pathIncludedInQuery, QueryType, SearchError, SearchErrorCode, SearchProviderType } from 'vs/workbench/services/search/common/search'; +import { deserializeSearchError, FileMatch, ICachedSearchStats, IFileMatch, IFileQuery, IFileSearchStats, IFolderQuery, IProgressMessage, IRawSearchService, ISearchComplete, ISearchConfiguration, ISearchEngineStats, ISearchProgressItem, ISearchQuery, ISearchResultProvider, ISearchService, ISerializedFileMatch, ISerializedSearchComplete, ISerializedSearchProgressItem, isSerializedSearchComplete, isSerializedSearchSuccess, ITextQuery, pathIncludedInQuery, QueryType, SearchError, SearchErrorCode, SearchProviderType, isFileMatch, isProgressMessage } from 'vs/workbench/services/search/common/search'; import { addContextToEditorMatches, editorMatchesToTextSearchResults } from 'vs/workbench/services/search/common/searchHelpers'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { SearchChannelClient } from './searchIpc'; @@ -78,18 +78,18 @@ export class SearchService extends Disposable implements ISearchService { arrays.coalesce(localResults.values()).forEach(onProgress); } - const onProviderProgress = progress => { - if (progress.resource) { + const onProviderProgress = (progress: ISearchProgressItem) => { + if (isFileMatch(progress)) { // Match if (!localResults.has(progress.resource) && onProgress) { // don't override local results onProgress(progress); } } else if (onProgress) { // Progress - onProgress(progress); + onProgress(progress); } - if (progress.message) { + if (isProgressMessage(progress)) { this.logService.debug('SearchService#search', progress.message); } }; @@ -142,7 +142,7 @@ export class SearchService extends Disposable implements ISearchService { return { limitHit: completes[0] && completes[0].limitHit, stats: completes[0].stats, - results: arrays.flatten(completes.map(c => c.results)) + results: arrays.flatten(completes.map((c: ISearchComplete) => c.results)) }; }); @@ -497,7 +497,7 @@ export class DiskSearch implements ISearchResultProvider { let event: Event; event = this.raw.fileSearch(query); - const onProgress = (p: IProgress) => { + const onProgress = (p: IProgressMessage) => { if (p.message) { // Should only be for logs this.logService.debug('SearchService#search', p.message); @@ -561,7 +561,7 @@ export class DiskSearch implements ISearchResultProvider { // Progress else if (onProgress) { - onProgress(ev); + onProgress(ev); } } }); diff --git a/src/vs/workbench/services/search/node/textSearchAdapter.ts b/src/vs/workbench/services/search/node/textSearchAdapter.ts index cbb3549bc9394dd18afaa3a693460da90a8c917a..9b2ff13c08a8f8c197c37b222207a93ea03ad5ba 100644 --- a/src/vs/workbench/services/search/node/textSearchAdapter.ts +++ b/src/vs/workbench/services/search/node/textSearchAdapter.ts @@ -5,7 +5,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import * as extfs from 'vs/base/node/extfs'; -import { IFileMatch, IProgress, ITextQuery, ITextSearchStats, ITextSearchMatch, ISerializedFileMatch, ISerializedSearchSuccess } from 'vs/workbench/services/search/common/search'; +import { IFileMatch, IProgressMessage, ITextQuery, ITextSearchStats, ITextSearchMatch, ISerializedFileMatch, ISerializedSearchSuccess } from 'vs/workbench/services/search/common/search'; import { RipgrepTextSearchEngine } from 'vs/workbench/services/search/node/ripgrepTextSearchEngine'; import { TextSearchManager } from 'vs/workbench/services/search/node/textSearchManager'; @@ -14,7 +14,7 @@ export class TextSearchEngineAdapter { constructor(private query: ITextQuery) { } - search(token: CancellationToken, onResult: (matches: ISerializedFileMatch[]) => void, onMessage: (message: IProgress) => void): Promise { + search(token: CancellationToken, onResult: (matches: ISerializedFileMatch[]) => void, onMessage: (message: IProgressMessage) => void): Promise { if ((!this.query.folderQueries || !this.query.folderQueries.length) && (!this.query.extraFileResources || !this.query.extraFileResources.length)) { return Promise.resolve({ type: 'success', @@ -26,7 +26,7 @@ export class TextSearchEngineAdapter { } const pretendOutputChannel = { - appendLine(msg) { + appendLine(msg: string) { onMessage({ message: msg }); } }; diff --git a/src/vs/workbench/services/search/test/node/rawSearchService.test.ts b/src/vs/workbench/services/search/test/node/rawSearchService.test.ts index a05e1e03a6ce6c2327d7612a2c4996fc4dd958be..4060adff5f03e1d3af6944ec25c73a99413441ce 100644 --- a/src/vs/workbench/services/search/test/node/rawSearchService.test.ts +++ b/src/vs/workbench/services/search/test/node/rawSearchService.test.ts @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import * as path from 'vs/base/common/path'; import { getPathFromAmdModule } from 'vs/base/common/amd'; import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; import { Emitter, Event } from 'vs/base/common/event'; +import * as path from 'vs/base/common/path'; import { URI } from 'vs/base/common/uri'; -import { IFileQuery, IFileSearchStats, IFolderQuery, IProgress, ISearchEngineStats, QueryType, IRawFileMatch, ISearchEngine, ISearchEngineSuccess, ISerializedFileMatch, ISerializedSearchComplete, ISerializedSearchProgressItem, ISerializedSearchSuccess } from 'vs/workbench/services/search/common/search'; -import { SearchService as RawSearchService } from 'vs/workbench/services/search/node/rawSearchService'; +import { IFileMatch, IFileQuery, IFileSearchStats, IFolderQuery, IProgressMessage, IRawFileMatch, ISearchEngine, ISearchEngineStats, ISearchEngineSuccess, ISerializedFileMatch, ISerializedSearchComplete, ISerializedSearchProgressItem, ISerializedSearchSuccess, QueryType } from 'vs/workbench/services/search/common/search'; +import { IProgressCallback, SearchService as RawSearchService } from 'vs/workbench/services/search/node/rawSearchService'; import { DiskSearch } from 'vs/workbench/services/search/node/searchService'; const TEST_FOLDER_QUERIES = [ @@ -40,7 +40,7 @@ class TestSearchEngine implements ISearchEngine { TestSearchEngine.last = this; } - search(onResult: (match: IRawFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISearchEngineSuccess) => void): void { + search(onResult: (match: IRawFileMatch) => void, onProgress: (progress: IProgressMessage) => void, done: (error: Error, complete: ISearchEngineSuccess) => void): void { const self = this; (function next() { process.nextTick(() => { @@ -157,7 +157,7 @@ suite('RawSearchService', () => { } const progressResults: any[] = []; - const onProgress = match => { + const onProgress = (match: IFileMatch) => { assert.strictEqual(match.resource.path, uriPath); progressResults.push(match); }; @@ -217,7 +217,7 @@ suite('RawSearchService', () => { const service = new RawSearchService(); const results: any[] = []; - const cb = value => { + const cb: IProgressCallback = value => { if (Array.isArray(value)) { results.push(...value.map(v => v.path)); } else { @@ -243,7 +243,7 @@ suite('RawSearchService', () => { const service = new RawSearchService(); const results: number[] = []; - const cb = value => { + const cb: IProgressCallback = value => { if (Array.isArray(value)) { value.forEach(m => { assert.deepStrictEqual(m, match); @@ -276,7 +276,7 @@ suite('RawSearchService', () => { const service = new RawSearchService(); const results: any[] = []; - const cb = value => { + const cb: IProgressCallback = value => { if (Array.isArray(value)) { results.push(...value.map(v => v.path)); } else { @@ -294,7 +294,7 @@ suite('RawSearchService', () => { assert.deepStrictEqual(results, [path.normalize('/some/where/bcb'), path.normalize('/some/where/bbc'), path.normalize('/some/where/aab')]); }).then(async () => { const results: any[] = []; - const cb = value => { + const cb: IProgressCallback = value => { if (Array.isArray(value)) { results.push(...value.map(v => v.path)); } else { @@ -323,7 +323,7 @@ suite('RawSearchService', () => { size: 3 }); const results: any[] = []; - const cb = value => { + const cb: IProgressCallback = value => { if (Array.isArray(value)) { results.push(...value.map(v => v.path)); } else { diff --git a/src/vs/workbench/services/search/test/node/ripgrepTextSearchEngine.test.ts b/src/vs/workbench/services/search/test/node/ripgrepTextSearchEngine.test.ts index f61f184e8e33c1bea88f3ef4d6b9e4f188c12686..7aab0611e31fa7acca358ce8c819e5bf8a175f7c 100644 --- a/src/vs/workbench/services/search/test/node/ripgrepTextSearchEngine.test.ts +++ b/src/vs/workbench/services/search/test/node/ripgrepTextSearchEngine.test.ts @@ -42,7 +42,7 @@ suite('RipgrepTextSearchEngine', () => { }); test('fixRegexCRMatchingWhitespaceClass', () => { - function testFixRegexCRMatchingWhitespaceClass([inputReg, isMultiline, testStr, shouldMatch]): void { + function testFixRegexCRMatchingWhitespaceClass([inputReg, isMultiline, testStr, shouldMatch]: [string, boolean, string, boolean]): void { const fixed = fixRegexCRMatchingWhitespaceClass(inputReg, isMultiline); const reg = new RegExp(fixed); assert.equal(reg.test(testStr), shouldMatch, `${inputReg} => ${reg}, ${testStr}, ${shouldMatch}`); @@ -66,7 +66,7 @@ suite('RipgrepTextSearchEngine', () => { }); test('fixRegexCRMatchingNonWordClass', () => { - function testRegexCRMatchingNonWordClass([inputReg, isMultiline, testStr, shouldMatch]): void { + function testRegexCRMatchingNonWordClass([inputReg, isMultiline, testStr, shouldMatch]: [string, boolean, string, boolean]): void { const fixed = fixRegexCRMatchingNonWordClass(inputReg, isMultiline); const reg = new RegExp(fixed); assert.equal(reg.test(testStr), shouldMatch, `${inputReg} => ${reg}, ${testStr}, ${shouldMatch}`); @@ -90,7 +90,7 @@ suite('RipgrepTextSearchEngine', () => { }); test('fixRegexNewline', () => { - function testFixRegexNewline([inputReg, testStr, shouldMatch]): void { + function testFixRegexNewline([inputReg, testStr, shouldMatch]: [string, string, boolean]): void { const fixed = fixRegexNewline(inputReg); const reg = new RegExp(fixed); assert.equal(reg.test(testStr), shouldMatch, `${inputReg} => ${reg}, ${testStr}, ${shouldMatch}`); @@ -111,7 +111,7 @@ suite('RipgrepTextSearchEngine', () => { }); test('fixNewline', () => { - function testFixNewline([inputReg, testStr, shouldMatch = true]): void { + function testFixNewline([inputReg, testStr, shouldMatch = true]: [string, string, boolean]): void { const fixed = fixNewline(inputReg); const reg = new RegExp(fixed); assert.equal(reg.test(testStr), shouldMatch, `${inputReg} => ${reg}, ${testStr}, ${shouldMatch}`);