Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use events instead of PPromise for search IPC #53536

Merged
merged 3 commits into from
Jul 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/vs/workbench/services/search/node/fileSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { IProgress, IUncachedSearchStats } from 'vs/platform/search/common/searc

import * as extfs from 'vs/base/node/extfs';
import * as flow from 'vs/base/node/flow';
import { IRawFileMatch, ISerializedSearchComplete, IRawSearch, ISearchEngine, IFolderSearch } from './search';
import { IRawFileMatch, IRawSearch, ISearchEngine, IFolderSearch, ISerializedSearchSuccess } from './search';
import { spawnRipgrepCmd } from './ripgrepFileSearch';
import { rgErrorMsgForDisplay } from './ripgrepTextSearch';

Expand Down Expand Up @@ -721,9 +721,10 @@ export class Engine implements ISearchEngine<IRawFileMatch> {
this.walker = new FileWalker(config);
}

public search(onResult: (result: IRawFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void {
public search(onResult: (result: IRawFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchSuccess) => void): void {
this.walker.walk(this.folderQueries, this.extraFiles, onResult, onProgress, (err: Error, isLimitHit: boolean) => {
done(err, {
type: 'success',
limitHit: isLimitHit,
stats: this.walker.getStats()
});
Expand Down
229 changes: 132 additions & 97 deletions src/vs/workbench/services/search/node/rawSearchService.ts

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions src/vs/workbench/services/search/node/ripgrepTextSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import * as encoding from 'vs/base/node/encoding';
import * as extfs from 'vs/base/node/extfs';
import { IProgress } from 'vs/platform/search/common/search';
import { rgPath } from 'vscode-ripgrep';
import { FileMatch, IFolderSearch, IRawSearch, ISerializedFileMatch, ISerializedSearchComplete, LineMatch } from './search';
import { FileMatch, IFolderSearch, IRawSearch, ISerializedFileMatch, LineMatch, ISerializedSearchSuccess } from './search';

// If vscode-ripgrep is in an .asar file, then the binary is unpacked.
const rgDiskPath = rgPath.replace(/\bnode_modules\.asar\b/, 'node_modules.asar.unpacked');
Expand All @@ -44,10 +44,11 @@ export class RipgrepEngine {
}

// TODO@Rob - make promise-based once the old search is gone, and I don't need them to have matching interfaces anymore
search(onResult: (match: ISerializedFileMatch) => void, onMessage: (message: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void {
search(onResult: (match: ISerializedFileMatch) => void, onMessage: (message: IProgress) => void, done: (error: Error, complete: ISerializedSearchSuccess) => void): void {
if (!this.config.folderQueries.length && !this.config.extraFiles.length) {
process.removeListener('exit', this.killRgProcFn);
done(null, {
type: 'success',
limitHit: false,
stats: null
});
Expand Down Expand Up @@ -94,6 +95,7 @@ export class RipgrepEngine {
this.cancel();
process.removeListener('exit', this.killRgProcFn);
done(null, {
type: 'success',
limitHit: true,
stats: null
});
Expand Down Expand Up @@ -124,11 +126,13 @@ export class RipgrepEngine {
process.removeListener('exit', this.killRgProcFn);
if (stderr && !gotData && (displayMsg = rgErrorMsgForDisplay(stderr))) {
done(new Error(displayMsg), {
type: 'success',
limitHit: false,
stats: null
});
} else {
done(null, {
type: 'success',
limitHit: false,
stats: null
});
Expand Down
35 changes: 29 additions & 6 deletions src/vs/workbench/services/search/node/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@

'use strict';

import { PPromise, TPromise } from 'vs/base/common/winjs.base';
import { TPromise } from 'vs/base/common/winjs.base';
import { IExpression } from 'vs/base/common/glob';
import { IProgress, ILineMatch, IPatternInfo, ISearchStats } from 'vs/platform/search/common/search';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { Event } from 'vs/base/common/event';

export interface IFolderSearch {
folder: string;
Expand Down Expand Up @@ -41,10 +42,10 @@ export interface ITelemetryEvent {
}

export interface IRawSearchService {
fileSearch(search: IRawSearch): PPromise<ISerializedSearchComplete, ISerializedSearchProgressItem>;
textSearch(search: IRawSearch): PPromise<ISerializedSearchComplete, ISerializedSearchProgressItem>;
fileSearch(search: IRawSearch): Event<ISerializedSearchProgressItem | ISerializedSearchComplete>;
textSearch(search: IRawSearch): Event<ISerializedSearchProgressItem | ISerializedSearchComplete>;
clearCache(cacheKey: string): TPromise<void>;
fetchTelemetry(): PPromise<void, ITelemetryEvent>;
readonly onTelemetry: Event<ITelemetryEvent>;
}

export interface IRawFileMatch {
Expand All @@ -55,15 +56,37 @@ export interface IRawFileMatch {
}

export interface ISearchEngine<T> {
search: (onResult: (matches: T) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void) => void;
search: (onResult: (matches: T) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchSuccess) => void) => void;
cancel: () => void;
}

export interface ISerializedSearchComplete {
export interface ISerializedSearchSuccess {
type: 'success';
limitHit: boolean;
stats: ISearchStats;
}

export interface ISerializedSearchError {
type: 'error';
error: any;
}

export type ISerializedSearchComplete = ISerializedSearchSuccess | ISerializedSearchError;

export function isSerializedSearchComplete(arg: ISerializedSearchProgressItem | ISerializedSearchComplete): arg is ISerializedSearchComplete {
if ((arg as any).type === 'error') {
return true;
} else if ((arg as any).type === 'success') {
return true;
} else {
return false;
}
}

export function isSerializedSearchSuccess(arg: ISerializedSearchComplete): arg is ISerializedSearchSuccess {
return arg.type === 'success';
}

export interface ISerializedFileMatch {
path: string;
lineMatches?: ILineMatch[];
Expand Down
36 changes: 18 additions & 18 deletions src/vs/workbench/services/search/node/searchIpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,55 @@

'use strict';

import { PPromise, TPromise } from 'vs/base/common/winjs.base';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IRawSearchService, IRawSearch, ISerializedSearchComplete, ISerializedSearchProgressItem, ITelemetryEvent } from './search';
import { Event } from 'vs/base/common/event';

export interface ISearchChannel extends IChannel {
call(command: 'fileSearch', search: IRawSearch): PPromise<ISerializedSearchComplete, ISerializedSearchProgressItem>;
call(command: 'textSearch', search: IRawSearch): PPromise<ISerializedSearchComplete, ISerializedSearchProgressItem>;
listen(event: 'telemetry'): Event<ITelemetryEvent>;
listen(event: 'fileSearch', search: IRawSearch): Event<ISerializedSearchProgressItem | ISerializedSearchComplete>;
listen(event: 'textSearch', search: IRawSearch): Event<ISerializedSearchProgressItem | ISerializedSearchComplete>;
call(command: 'clearCache', cacheKey: string): TPromise<void>;
call(command: 'fetchTelemetry'): PPromise<void, ITelemetryEvent>;
call(command: string, arg: any): TPromise<any>;
}

export class SearchChannel implements ISearchChannel {

constructor(private service: IRawSearchService) { }

listen<T>(event: string, arg?: any): Event<T> {
throw new Error('No events');
listen<T>(event: string, arg?: any): Event<any> {
switch (event) {
case 'telemetry': return this.service.onTelemetry;
case 'fileSearch': return this.service.fileSearch(arg);
case 'textSearch': return this.service.textSearch(arg);
}
throw new Error('Event not found');
}

call(command: string, arg?: any): TPromise<any> {
switch (command) {
case 'fileSearch': return this.service.fileSearch(arg);
case 'textSearch': return this.service.textSearch(arg);
case 'clearCache': return this.service.clearCache(arg);
case 'fetchTelemetry': return this.service.fetchTelemetry();
}
return undefined;
throw new Error('Call not found');
}
}

export class SearchChannelClient implements IRawSearchService {

get onTelemetry(): Event<ITelemetryEvent> { return this.channel.listen('telemetry'); }

constructor(private channel: ISearchChannel) { }

fileSearch(search: IRawSearch): PPromise<ISerializedSearchComplete, ISerializedSearchProgressItem> {
return this.channel.call('fileSearch', search);
fileSearch(search: IRawSearch): Event<ISerializedSearchProgressItem | ISerializedSearchComplete> {
return this.channel.listen('fileSearch', search);
}

textSearch(search: IRawSearch): PPromise<ISerializedSearchComplete, ISerializedSearchProgressItem> {
return this.channel.call('textSearch', search);
textSearch(search: IRawSearch): Event<ISerializedSearchProgressItem | ISerializedSearchComplete> {
return this.channel.listen('textSearch', search);
}

clearCache(cacheKey: string): TPromise<void> {
return this.channel.call('clearCache', cacheKey);
}

fetchTelemetry(): PPromise<void, ITelemetryEvent> {
return this.channel.call('fetchTelemetry');
}
}
38 changes: 31 additions & 7 deletions src/vs/workbench/services/search/node/searchService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { IProgress, LineMatch, FileMatch, ISearchComplete, ISearchProgressItem,
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IRawSearch, ISerializedSearchComplete, ISerializedSearchProgressItem, ISerializedFileMatch, IRawSearchService, ITelemetryEvent } from './search';
import { IRawSearch, ISerializedSearchComplete, ISerializedSearchProgressItem, ISerializedFileMatch, IRawSearchService, ITelemetryEvent, isSerializedSearchComplete, isSerializedSearchSuccess, ISerializedSearchSuccess } from './search';
import { ISearchChannel, SearchChannelClient } from './searchIpc';
import { IEnvironmentService, IDebugParams } from 'vs/platform/environment/common/environment';
import { ResourceMap } from 'vs/base/common/map';
Expand All @@ -26,6 +26,7 @@ import { Schemas } from 'vs/base/common/network';
import * as pfs from 'vs/base/node/pfs';
import { ILogService } from 'vs/platform/log/common/log';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { Event } from 'vs/base/common/event';

export class SearchService implements ISearchService {
public _serviceBrand: any;
Expand Down Expand Up @@ -320,14 +321,14 @@ export class DiskSearch implements ISearchResultProvider {
const existingFolders = folderQueries.filter((q, index) => exists[index]);
const rawSearch = this.rawSearchQuery(query, existingFolders);

let request: PPromise<ISerializedSearchComplete, ISerializedSearchProgressItem>;
let event: Event<ISerializedSearchProgressItem | ISerializedSearchComplete>;
if (query.type === QueryType.File) {
request = this.raw.fileSearch(rawSearch);
event = this.raw.fileSearch(rawSearch);
} else {
request = this.raw.textSearch(rawSearch);
event = this.raw.textSearch(rawSearch);
}

return DiskSearch.collectResults(request);
return DiskSearch.collectResultsFromEvent(event);
});
}

Expand Down Expand Up @@ -372,7 +373,28 @@ export class DiskSearch implements ISearchResultProvider {
return rawSearch;
}

public static collectResults(request: PPromise<ISerializedSearchComplete, ISerializedSearchProgressItem>): PPromise<ISearchComplete, ISearchProgressItem> {
public static collectResultsFromEvent(event: Event<ISerializedSearchProgressItem | ISerializedSearchComplete>): PPromise<ISearchComplete, ISearchProgressItem> {
const promise = new PPromise<ISerializedSearchSuccess, ISerializedSearchProgressItem>((c, e, p) => {
setTimeout(() => {
const listener = event(ev => {
if (isSerializedSearchComplete(ev)) {
if (isSerializedSearchSuccess(ev)) {
c(ev);
} else {
e(ev.error);
}
listener.dispose();
} else {
p(ev);
}
});
}, 0);
});

return DiskSearch.collectResults(promise);
}

public static collectResults(request: PPromise<ISerializedSearchSuccess, ISerializedSearchProgressItem>): PPromise<ISearchComplete, ISearchProgressItem> {
let result: IFileMatch[] = [];
return new PPromise<ISearchComplete, ISearchProgressItem>((c, e, p) => {
request.done((complete) => {
Expand Down Expand Up @@ -420,6 +442,8 @@ export class DiskSearch implements ISearchResultProvider {
}

public fetchTelemetry(): PPromise<void, ITelemetryEvent> {
return this.raw.fetchTelemetry();
return new PPromise<void, ITelemetryEvent>((c, e, p) => {
this.raw.onTelemetry(p);
});
}
}
5 changes: 3 additions & 2 deletions src/vs/workbench/services/search/node/textSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
import { IProgress } from 'vs/platform/search/common/search';
import { FileWalker } from 'vs/workbench/services/search/node/fileSearch';

import { ISerializedFileMatch, ISerializedSearchComplete, IRawSearch, ISearchEngine } from './search';
import { ISerializedFileMatch, IRawSearch, ISearchEngine, ISerializedSearchSuccess } from './search';
import { ISearchWorker } from './worker/searchWorkerIpc';
import { ITextSearchWorkerProvider } from './textSearchWorkerProvider';

Expand Down Expand Up @@ -60,7 +60,7 @@ export class Engine implements ISearchEngine<ISerializedFileMatch[]> {
});
}

search(onResult: (match: ISerializedFileMatch[]) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void {
search(onResult: (match: ISerializedFileMatch[]) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchSuccess) => void): void {
this.workers = this.workerProvider.getWorkers();
this.initializeWorkers();

Expand All @@ -86,6 +86,7 @@ export class Engine implements ISearchEngine<ISerializedFileMatch[]> {
if (!this.isDone && this.processedBytes === this.totalBytes && this.walkerIsDone) {
this.isDone = true;
done(this.walkerError, {
type: 'success',
limitHit: this.limitReached,
stats: this.walker.getStats()
});
Expand Down
Loading