Skip to content

Commit

Permalink
Change SearchProvider to be URI-based, not string-based. #50788
Browse files Browse the repository at this point in the history
  • Loading branch information
roblourens committed Jul 3, 2018
1 parent e0e9c3d commit 0ef1c31
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 172 deletions.
70 changes: 25 additions & 45 deletions extensions/search-rg/src/cachedSearchProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ import * as vscode from 'vscode';
import * as arrays from './common/arrays';
import { compareItemsByScore, IItemAccessor, prepareQuery, ScorerCache } from './common/fileSearchScorer';
import * as strings from './common/strings';
import { joinPath } from './ripgrepHelpers';

interface IProviderArgs {
query: vscode.FileSearchQuery;
options: vscode.FileSearchOptions;
progress: vscode.Progress<string>;
progress: vscode.Progress<vscode.Uri>;
token: vscode.CancellationToken;
}

export interface IInternalFileSearchProvider {
provideFileSearchResults(options: vscode.FileSearchOptions, progress: vscode.Progress<string>, token: vscode.CancellationToken): Thenable<void>;
}

export class CachedSearchProvider {

private static readonly BATCH_SIZE = 512;
Expand All @@ -25,12 +30,12 @@ export class CachedSearchProvider {
constructor(private outputChannel: vscode.OutputChannel) {
}

provideFileSearchResults(provider: vscode.SearchProvider, query: vscode.FileSearchQuery, options: vscode.FileSearchOptions, progress: vscode.Progress<string>, token: vscode.CancellationToken): Thenable<void> {
provideFileSearchResults(provider: IInternalFileSearchProvider, query: vscode.FileSearchQuery, options: vscode.FileSearchOptions, progress: vscode.Progress<vscode.Uri>, token: vscode.CancellationToken): Thenable<void> {
const onResult = (result: IInternalFileMatch) => {
progress.report(result.relativePath);
progress.report(joinPath(options.folder, result.relativePath));
};

const providerArgs = {
const providerArgs: IProviderArgs = {
query, options, progress, token
};

Expand All @@ -52,23 +57,14 @@ export class CachedSearchProvider {
});
}

private doSortedSearch(args: IProviderArgs, provider: vscode.SearchProvider): Promise<IInternalFileMatch[]> {
let searchPromise: Promise<void>;
private doSortedSearch(args: IProviderArgs, provider: IInternalFileSearchProvider): Promise<IInternalFileMatch[]> {
let allResultsPromise = new Promise<IInternalFileMatch[]>((c, e) => {
let results: IInternalFileMatch[] = [];

const onResult = (progress: OneOrMore<IInternalFileMatch>) => {
if (Array.isArray(progress)) {
results.push(...progress);
} else {
results.push(progress);
}
};
const results: IInternalFileMatch[] = [];
const onResult = (progress: IInternalFileMatch[]) => results.push(...progress);

searchPromise = this.doSearch(args, provider, onResult, CachedSearchProvider.BATCH_SIZE)
.then(() => {
c(results);
}, e);
// set maxResult = null
this.doSearch(args, provider, onResult, CachedSearchProvider.BATCH_SIZE)
.then(() => c(results), e);
});

let cache: Cache;
Expand All @@ -80,12 +76,9 @@ export class CachedSearchProvider {
});
}

return new Promise<IInternalFileMatch[]>((c, e) => {
allResultsPromise.then(results => {
const scorerCache: ScorerCache = cache ? cache.scorerCache : Object.create(null);
return this.sortResults(args, results, scorerCache)
.then(c);
}, e);
return allResultsPromise.then(results => {
const scorerCache: ScorerCache = cache ? cache.scorerCache : Object.create(null);
return this.sortResults(args, results, scorerCache);
});
}

Expand Down Expand Up @@ -119,7 +112,7 @@ export class CachedSearchProvider {
const preparedQuery = prepareQuery(args.query.pattern);
const compare = (matchA: IInternalFileMatch, matchB: IInternalFileMatch) => compareItemsByScore(matchA, matchB, preparedQuery, true, FileMatchItemAccessor, scorerCache);

return arrays.topAsync(results, compare, args.options.maxResults || 10000, 10000);
return arrays.topAsync(results, compare, args.options.maxResults || 0, 10000);
}

private getResultsFromCache(cache: Cache, searchValue: string, onResult: (results: IInternalFileMatch) => void): Promise<[IInternalFileMatch[], CacheStats]> {
Expand Down Expand Up @@ -177,7 +170,7 @@ export class CachedSearchProvider {
});
}

private doSearch(args: IProviderArgs, provider: vscode.SearchProvider, onResult: (result: OneOrMore<IInternalFileMatch>) => void, batchSize?: number): Promise<void> {
private doSearch(args: IProviderArgs, provider: IInternalFileSearchProvider, onResult: (result: IInternalFileMatch[]) => void, batchSize: number): Promise<void> {
return new Promise<void>((c, e) => {
let batch: IInternalFileMatch[] = [];
const onProviderResult = (match: string) => {
Expand All @@ -187,19 +180,15 @@ export class CachedSearchProvider {
basename: path.basename(match)
};

if (batchSize) {
batch.push(internalMatch);
if (batchSize > 0 && batch.length >= batchSize) {
onResult(batch);
batch = [];
}
} else {
onResult(internalMatch);
batch.push(internalMatch);
if (batchSize > 0 && batch.length >= batchSize) {
onResult(batch);
batch = [];
}
}
};

provider.provideFileSearchResults(args.query, args.options, { report: onProviderResult }, args.token).then(() => {
provider.provideFileSearchResults(args.options, { report: onProviderResult }, args.token).then(() => {
if (batch.length) {
onResult(batch);
}
Expand All @@ -221,13 +210,6 @@ export class CachedSearchProvider {
}
}

function joinPath(resource: vscode.Uri, pathFragment: string): vscode.Uri {
const joinedPath = path.join(resource.path || '/', pathFragment);
return resource.with({
path: joinedPath
});
}

interface IInternalFileMatch {
relativePath?: string; // Not present for extraFiles or absolute path matches
basename: string;
Expand All @@ -246,8 +228,6 @@ interface CacheEntry<T> {
onResult?: Event<T>;
}

type OneOrMore<T> = T | T[];

class Cache {
public resultsToSearchCache: { [searchValue: string]: CacheEntry<IInternalFileMatch> } = Object.create(null);
public scorerCache: ScorerCache = Object.create(null);
Expand Down
2 changes: 1 addition & 1 deletion extensions/search-rg/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class RipgrepSearchProvider implements vscode.SearchProvider {
return engine.provideTextSearchResults(query, options, progress, token);
}

provideFileSearchResults(query: vscode.FileSearchQuery, options: vscode.SearchOptions, progress: vscode.Progress<string>, token: vscode.CancellationToken): Thenable<void> {
provideFileSearchResults(query: vscode.FileSearchQuery, options: vscode.SearchOptions, progress: vscode.Progress<vscode.Uri>, token: vscode.CancellationToken): Thenable<void> {
const engine = new RipgrepFileSearch(this.outputChannel);
return this.cachedProvider.provideFileSearchResults(engine, query, options, progress, token);
}
Expand Down
5 changes: 3 additions & 2 deletions extensions/search-rg/src/ripgrepFileSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import { normalizeNFC, normalizeNFD } from './common/normalization';
import { rgPath } from './ripgrep';
import { anchorGlob } from './ripgrepHelpers';
import { rgErrorMsgForDisplay } from './ripgrepTextSearch';
import { IInternalFileSearchProvider } from './cachedSearchProvider';

const isMac = process.platform === 'darwin';

// 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');

export class RipgrepFileSearch {
export class RipgrepFileSearch implements IInternalFileSearchProvider {
private rgProc: cp.ChildProcess;
private killRgProcFn: (code?: number) => void;

Expand All @@ -30,7 +31,7 @@ export class RipgrepFileSearch {
process.removeListener('exit', this.killRgProcFn);
}

provideFileSearchResults(query: vscode.FileSearchQuery, options: vscode.FileSearchOptions, progress: vscode.Progress<string>, token: vscode.CancellationToken): Thenable<void> {
provideFileSearchResults(options: vscode.FileSearchOptions, progress: vscode.Progress<string>, token: vscode.CancellationToken): Thenable<void> {
this.outputChannel.appendLine(`provideFileSearchResults ${JSON.stringify({
...options,
...{
Expand Down
10 changes: 8 additions & 2 deletions extensions/search-rg/src/ripgrepHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@

'use strict';

import * as vscode from 'vscode';

import * as path from 'path';
import * as vscode from 'vscode';

export function fixDriveC(_path: string): string {
const root = path.parse(_path).root;
Expand All @@ -19,3 +18,10 @@ export function fixDriveC(_path: string): string {
export function anchorGlob(glob: string): string {
return glob.startsWith('**') || glob.startsWith('/') ? glob : `/${glob}`;
}

export function joinPath(resource: vscode.Uri, pathFragment: string): vscode.Uri {
const joinedPath = path.join(resource.path || '/', pathFragment);
return resource.with({
path: joinedPath
});
}
3 changes: 2 additions & 1 deletion extensions/search-rg/src/ripgrepTextSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import * as cp from 'child_process';
import { EventEmitter } from 'events';
import * as path from 'path';
import { NodeStringDecoder, StringDecoder } from 'string_decoder';
import * as vscode from 'vscode';
import { rgPath } from './ripgrep';
Expand Down Expand Up @@ -291,7 +292,7 @@ export class RipgrepParser extends EventEmitter {
lineMatches
.map(range => {
return <vscode.TextSearchResult>{
path: this.currentFile,
uri: vscode.Uri.file(path.join(this.rootFolder, this.currentFile)),
range,
preview: {
text: preview,
Expand Down
4 changes: 2 additions & 2 deletions src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ declare module 'vscode' {
export interface FileSearchOptions extends SearchOptions { }

export interface TextSearchResult {
path: string;
uri: Uri;
range: Range;

// For now, preview must be a single line of text
preview: { text: string, match: Range };
}

export interface SearchProvider {
provideFileSearchResults?(query: FileSearchQuery, options: FileSearchOptions, progress: Progress<string>, token: CancellationToken): Thenable<void>;
provideFileSearchResults?(query: FileSearchQuery, options: FileSearchOptions, progress: Progress<Uri>, token: CancellationToken): Thenable<void>;
provideTextSearchResults?(query: TextSearchQuery, options: TextSearchOptions, progress: Progress<TextSearchResult>, token: CancellationToken): Thenable<void>;
}

Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/node/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ export interface MainThreadFileSystemShape extends IDisposable {
export interface MainThreadSearchShape extends IDisposable {
$registerSearchProvider(handle: number, scheme: string): void;
$unregisterProvider(handle: number): void;
$handleFileMatch(handle: number, session: number, data: UriComponents | UriComponents[]): void;
$handleFileMatch(handle: number, session: number, data: UriComponents[]): void;
$handleTextMatch(handle: number, session: number, data: IRawFileMatch2[]): void;
$handleTelemetry(eventName: string, data: any): void;
}
Expand Down
Loading

0 comments on commit 0ef1c31

Please sign in to comment.