Skip to content

Commit

Permalink
remote - move out search provider, #45000
Browse files Browse the repository at this point in the history
  • Loading branch information
jrieken committed Mar 20, 2018
1 parent aa14020 commit 73e3488
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 74 deletions.
52 changes: 30 additions & 22 deletions src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,24 +203,6 @@ declare module 'vscode' {
type: FileType;
}

export interface TextSearchQuery {
pattern: string;
isRegex?: boolean;
isCaseSensitive?: boolean;
isWordMatch?: boolean;
}

export interface TextSearchOptions {
includes: GlobPattern[];
excludes: GlobPattern[];
}

export interface TextSearchResult {
uri: Uri;
range: Range;
preview: { leading: string, matching: string, trailing: string };
}

// todo@joh discover files etc
// todo@joh CancellationToken everywhere
// todo@joh add open/close calls?
Expand Down Expand Up @@ -265,15 +247,41 @@ declare module 'vscode' {

// todo@remote
// create(resource: Uri): Thenable<FileStat>;
}

export namespace workspace {
export function registerFileSystemProvider(scheme: string, provider: FileSystemProvider): Disposable;
}

// find files by names
// todo@joh, move into its own provider
findFiles?(query: string, progress: Progress<Uri>, token: CancellationToken): Thenable<void>;
//#endregion

//#region Joh: remote, search provider

export interface TextSearchQuery {
pattern: string;
isRegex?: boolean;
isCaseSensitive?: boolean;
isWordMatch?: boolean;
}

export interface TextSearchOptions {
includes: GlobPattern[];
excludes: GlobPattern[];
}

export interface TextSearchResult {
uri: Uri;
range: Range;
preview: { leading: string, matching: string, trailing: string };
}

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

export namespace workspace {
export function registerFileSystemProvider(scheme: string, provider: FileSystemProvider): Disposable;
export function registerSearchProvider(scheme: string, provider: SearchProvider): Disposable;
}

//#endregion
Expand Down
85 changes: 53 additions & 32 deletions src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import { isFalsyOrEmpty } from 'vs/base/common/arrays';
export class MainThreadFileSystem implements MainThreadFileSystemShape {

private readonly _proxy: ExtHostFileSystemShape;
private readonly _provider = new Map<number, RemoteFileSystemProvider>();
private readonly _fileProvider = new Map<number, RemoteFileSystemProvider>();
private readonly _searchProvider = new Map<number, RemoteSearchProvider>();

constructor(
extHostContext: IExtHostContext,
Expand All @@ -31,31 +32,38 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape {
}

dispose(): void {
this._provider.forEach(value => dispose());
this._provider.clear();
this._fileProvider.forEach(value => dispose());
this._fileProvider.clear();
}

$registerFileSystemProvider(handle: number, scheme: string): void {
this._provider.set(handle, new RemoteFileSystemProvider(this._fileService, this._searchService, scheme, handle, this._proxy));
this._fileProvider.set(handle, new RemoteFileSystemProvider(this._fileService, scheme, handle, this._proxy));
}

$unregisterFileSystemProvider(handle: number): void {
dispose(this._provider.get(handle));
this._provider.delete(handle);
$registerSearchProvider(handle: number, scheme: string): void {
this._searchProvider.set(handle, new RemoteSearchProvider(this._searchService, scheme, handle, this._proxy));
}

$unregisterProvider(handle: number): void {
dispose(this._fileProvider.get(handle));
this._fileProvider.delete(handle);

dispose(this._searchProvider.get(handle));
this._searchProvider.delete(handle);
}

$onFileSystemChange(handle: number, changes: IFileChangeDto[]): void {
this._provider.get(handle).$onFileSystemChange(changes);
this._fileProvider.get(handle).$onFileSystemChange(changes);
}

$reportFileChunk(handle: number, session: number, chunk: number[]): void {
this._provider.get(handle).reportFileChunk(session, chunk);
this._fileProvider.get(handle).reportFileChunk(session, chunk);
}

// --- search

$handleFindMatch(handle: number, session, data: UriComponents | [UriComponents, ILineMatch]): void {
this._provider.get(handle).handleFindMatch(session, data);
this._searchProvider.get(handle).handleFindMatch(session, data);
}
}

Expand All @@ -71,40 +79,22 @@ class FileReadOperation {
}
}

class SearchOperation {

private static _idPool = 0;

constructor(
readonly progress: (match: IFileMatch) => any,
readonly id: number = ++SearchOperation._idPool,
readonly matches = new Map<string, IFileMatch>()
) {
//
}
}

class RemoteFileSystemProvider implements IFileSystemProvider, ISearchResultProvider {
class RemoteFileSystemProvider implements IFileSystemProvider {

private readonly _onDidChange = new Emitter<IFileChange[]>();
private readonly _registrations: IDisposable[];
private readonly _reads = new Map<number, FileReadOperation>();
private readonly _searches = new Map<number, SearchOperation>();

readonly onDidChange: Event<IFileChange[]> = this._onDidChange.event;


constructor(
fileService: IFileService,
searchService: ISearchService,
private readonly _scheme: string,
scheme: string,
private readonly _handle: number,
private readonly _proxy: ExtHostFileSystemShape
) {
this._registrations = [
fileService.registerProvider(_scheme, this),
searchService.registerSearchResultProvider(this),
];
this._registrations = [fileService.registerProvider(scheme, this)];
}

dispose(): void {
Expand Down Expand Up @@ -159,8 +149,39 @@ class RemoteFileSystemProvider implements IFileSystemProvider, ISearchResultProv
rmdir(resource: URI): TPromise<void, any> {
return this._proxy.$rmdir(this._handle, resource);
}
}

// --- search
class SearchOperation {

private static _idPool = 0;

constructor(
readonly progress: (match: IFileMatch) => any,
readonly id: number = ++SearchOperation._idPool,
readonly matches = new Map<string, IFileMatch>()
) {
//
}
}

class RemoteSearchProvider implements ISearchResultProvider {

private readonly _registrations: IDisposable[];
private readonly _searches = new Map<number, SearchOperation>();


constructor(
searchService: ISearchService,
private readonly _scheme: string,
private readonly _handle: number,
private readonly _proxy: ExtHostFileSystemShape
) {
this._registrations = [searchService.registerSearchResultProvider(this)];
}

dispose(): void {
dispose(this._registrations);
}

search(query: ISearchQuery): PPromise<ISearchComplete, ISearchProgressItem> {

Expand Down
7 changes: 5 additions & 2 deletions src/vs/workbench/api/node/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,8 +517,11 @@ export function createApiFactory(
registerTaskProvider: (type: string, provider: vscode.TaskProvider) => {
return extHostTask.registerTaskProvider(extension, provider);
},
registerFileSystemProvider: proposedApiFunction(extension, (authority, provider) => {
return extHostFileSystem.registerFileSystemProvider(authority, provider);
registerFileSystemProvider: proposedApiFunction(extension, (scheme, provider) => {
return extHostFileSystem.registerFileSystemProvider(scheme, provider);
}),
registerSearchProvider: proposedApiFunction(extension, (scheme, provider) => {
return extHostFileSystem.registerSearchProvider(scheme, provider);
})
};

Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/api/node/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,8 @@ export interface IFileChangeDto {

export interface MainThreadFileSystemShape extends IDisposable {
$registerFileSystemProvider(handle: number, scheme: string): void;
$unregisterFileSystemProvider(handle: number): void;
$registerSearchProvider(handle: number, scheme: string): void;
$unregisterProvider(handle: number): void;

$onFileSystemChange(handle: number, resource: IFileChangeDto[]): void;
$reportFileChunk(handle: number, session: number, chunk: number[] | null): void;
Expand Down
47 changes: 30 additions & 17 deletions src/vs/workbench/api/node/extHostFileSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ class FsLinkProvider implements vscode.DocumentLinkProvider {
export class ExtHostFileSystem implements ExtHostFileSystemShape {

private readonly _proxy: MainThreadFileSystemShape;
private readonly _provider = new Map<number, vscode.FileSystemProvider>();
private readonly _fsProvider = new Map<number, vscode.FileSystemProvider>();
private readonly _searchProvider = new Map<number, vscode.SearchProvider>();
private readonly _linkProvider = new FsLinkProvider();

private _handlePool: number = 0;
Expand All @@ -71,7 +72,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
registerFileSystemProvider(scheme: string, provider: vscode.FileSystemProvider) {
const handle = this._handlePool++;
this._linkProvider.add(scheme);
this._provider.set(handle, provider);
this._fsProvider.set(handle, provider);
this._proxy.$registerFileSystemProvider(handle, scheme);
let reg: IDisposable;
if (provider.onDidChange) {
Expand All @@ -83,58 +84,70 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
reg.dispose();
}
this._linkProvider.delete(scheme);
this._provider.delete(handle);
this._proxy.$unregisterFileSystemProvider(handle);
this._fsProvider.delete(handle);
this._proxy.$unregisterProvider(handle);
}
};
}

registerSearchProvider(scheme: string, provider: vscode.SearchProvider) {
const handle = this._handlePool++;
this._searchProvider.set(handle, provider);
this._proxy.$registerSearchProvider(handle, scheme);
return {
dispose: () => {
this._searchProvider.delete(handle);
this._proxy.$unregisterProvider(handle);
}
};
}

$utimes(handle: number, resource: UriComponents, mtime: number, atime: number): TPromise<IStat, any> {
return asWinJsPromise(token => this._provider.get(handle).utimes(URI.revive(resource), mtime, atime));
return asWinJsPromise(token => this._fsProvider.get(handle).utimes(URI.revive(resource), mtime, atime));
}
$stat(handle: number, resource: UriComponents): TPromise<IStat, any> {
return asWinJsPromise(token => this._provider.get(handle).stat(URI.revive(resource)));
return asWinJsPromise(token => this._fsProvider.get(handle).stat(URI.revive(resource)));
}
$read(handle: number, session: number, offset: number, count: number, resource: UriComponents): TPromise<number> {
const progress = {
report: chunk => {
this._proxy.$reportFileChunk(handle, session, [].slice.call(chunk));
}
};
return asWinJsPromise(token => this._provider.get(handle).read(URI.revive(resource), offset, count, progress));
return asWinJsPromise(token => this._fsProvider.get(handle).read(URI.revive(resource), offset, count, progress));
}
$write(handle: number, resource: UriComponents, content: number[]): TPromise<void, any> {
return asWinJsPromise(token => this._provider.get(handle).write(URI.revive(resource), Buffer.from(content)));
return asWinJsPromise(token => this._fsProvider.get(handle).write(URI.revive(resource), Buffer.from(content)));
}
$unlink(handle: number, resource: UriComponents): TPromise<void, any> {
return asWinJsPromise(token => this._provider.get(handle).unlink(URI.revive(resource)));
return asWinJsPromise(token => this._fsProvider.get(handle).unlink(URI.revive(resource)));
}
$move(handle: number, resource: UriComponents, target: UriComponents): TPromise<IStat, any> {
return asWinJsPromise(token => this._provider.get(handle).move(URI.revive(resource), URI.revive(target)));
return asWinJsPromise(token => this._fsProvider.get(handle).move(URI.revive(resource), URI.revive(target)));
}
$mkdir(handle: number, resource: UriComponents): TPromise<IStat, any> {
return asWinJsPromise(token => this._provider.get(handle).mkdir(URI.revive(resource)));
return asWinJsPromise(token => this._fsProvider.get(handle).mkdir(URI.revive(resource)));
}
$readdir(handle: number, resource: UriComponents): TPromise<[UriComponents, IStat][], any> {
return asWinJsPromise(token => this._provider.get(handle).readdir(URI.revive(resource)));
return asWinJsPromise(token => this._fsProvider.get(handle).readdir(URI.revive(resource)));
}
$rmdir(handle: number, resource: UriComponents): TPromise<void, any> {
return asWinJsPromise(token => this._provider.get(handle).rmdir(URI.revive(resource)));
return asWinJsPromise(token => this._fsProvider.get(handle).rmdir(URI.revive(resource)));
}
$findFiles(handle: number, session: number, query: string): TPromise<void> {
const provider = this._provider.get(handle);
if (!provider.findFiles) {
const provider = this._searchProvider.get(handle);
if (!provider.provideFileSearchResults) {
return TPromise.as(undefined);
}
const progress = {
report: (uri) => {
this._proxy.$handleFindMatch(handle, session, uri);
}
};
return asWinJsPromise(token => provider.findFiles(query, progress, token));
return asWinJsPromise(token => provider.provideFileSearchResults(query, progress, token));
}
$provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, options: { includes: string[], excludes: string[] }): TPromise<void> {
const provider = this._provider.get(handle);
const provider = this._searchProvider.get(handle);
if (!provider.provideTextSearchResults) {
return TPromise.as(undefined);
}
Expand Down

0 comments on commit 73e3488

Please sign in to comment.