提交 52f98f46 编写于 作者: J Johannes Rieken

move find-file logic into fsprovider, wire things up end to end

上级 af195c96
......@@ -14,14 +14,13 @@ declare module 'vscode' {
resolveContents(resource: Uri): string | Thenable<string>;
writeContents(resource: Uri, contents: string): void | Thenable<void>;
}
export interface SearchProvider {
provideSearchResults(query: any, progress: Progress<Uri>, token?: CancellationToken): Thenable<void>;
// -- search
// todo@joh - extract into its own provider?
findFiles(query: string, progress: Progress<Uri>, token?: CancellationToken): Thenable<void>;
}
export namespace workspace {
export function registerFileSystemProvider(authority: string, provider: FileSystemProvider): Disposable;
}
......
......@@ -6,7 +6,7 @@
import { isPromiseCanceledError } from 'vs/base/common/errors';
import URI from 'vs/base/common/uri';
import { ISearchService, QueryType, ISearchQuery } from 'vs/platform/search/common/search';
import { ISearchService, QueryType, ISearchQuery, ISearchProgressItem, ISearchComplete } from 'vs/platform/search/common/search';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
......@@ -16,8 +16,8 @@ import { TPromise, PPromise } from 'vs/base/common/winjs.base';
import { MainThreadWorkspaceShape, ExtHostWorkspaceShape, ExtHostContext, MainContext, IExtHostContext } from '../node/extHost.protocol';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IFileService } from 'vs/platform/files/common/files';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { RemoteFileService, IRemoteFileSystemProvider } from 'vs/workbench/services/files/electron-browser/remoteFileService';
import { IDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle';
import { RemoteFileService } from 'vs/workbench/services/files/electron-browser/remoteFileService';
import { Emitter } from 'vs/base/common/event';
import { extHostNamedCustomer } from "vs/workbench/api/electron-browser/extHostCustomers";
......@@ -101,53 +101,6 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
// --- save & edit resources ---
private readonly _searchProvider = new Map<number, IDisposable>();
private readonly _searchSession = new Map<number, { resolve: Function, reject: Function, progress: Function }>();
private _searchSessionIdPool: number = 0;
$registerSearchProvider(handle: number, type: number): void {
this._searchProvider.set(handle, this._searchService.registerSearchResultProvider({
search: (query) => {
if (query.type !== type) {
return null;
}
const session = ++this._searchSessionIdPool;
return new PPromise<any, any>((resolve, reject, progress) => {
this._searchSession.set(session, { resolve, reject, progress });
this._proxy.$startSearch(handle, session, query);
}, () => {
this._proxy.$cancelSearch(handle, session);
});
}
}));
}
$unregisterSearchProvider(handle: number): void {
const registration = this._searchProvider.get(handle);
if (registration) {
registration.dispose();
this._searchProvider.delete(handle);
}
}
$updateSearchSession(session: number, data): void {
if (this._searchSession.has(session)) {
this._searchSession.get(session).progress(data);
}
}
$finishSearchSession(session: number, err?: any): void {
if (this._searchSession.has(session)) {
const { resolve, reject } = this._searchSession.get(session);
this._searchSession.delete(session);
if (err) {
reject(err);
} else {
resolve();
}
}
}
$saveAll(includeUntitled?: boolean): Thenable<boolean> {
return this._textFileService.saveAll(includeUntitled).then(result => {
return result.results.every(each => each.success === true);
......@@ -171,7 +124,9 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
// --- EXPERIMENT: workspace provider
private _provider = new Map<number, [IRemoteFileSystemProvider, Emitter<URI>]>();
private _idPool: number = 0;
private readonly _provider = new Map<number, [IDisposable, Emitter<URI>]>();
private readonly _searchSessions = new Map<number, { resolve: (result: ISearchComplete) => void, reject: Function, progress: (item: ISearchProgressItem) => void, matches: URI[] }>();
$registerFileSystemProvider(handle: number, authority: string): void {
if (!(this._fileService instanceof RemoteFileService)) {
......@@ -187,13 +142,60 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
return this._proxy.$storeFile(handle, resource, value);
}
};
this._provider.set(handle, [provider, emitter]);
this._fileService.registerProvider(authority, provider);
const searchProvider = {
search: (query) => {
if (query.type !== QueryType.File) {
return undefined;
}
const session = ++this._idPool;
return new PPromise<any, any>((resolve, reject, progress) => {
this._searchSessions.set(session, { resolve, reject, progress, matches: [] });
this._proxy.$startSearch(handle, session, query.filePattern);
}, () => {
this._proxy.$cancelSearch(handle, session);
});
}
};
const registrations = combinedDisposable([
this._fileService.registerProvider(authority, provider),
this._searchService.registerSearchResultProvider(searchProvider),
]);
this._provider.set(handle, [registrations, emitter]);
}
$unregisterFileSystemProvider(handle: number): void {
if (this._provider.has(handle)) {
dispose(this._provider.get(handle)[0]);
this._provider.delete(handle);
}
}
$onFileSystemChange(handle: number, resource: URI) {
const [, emitter] = this._provider.get(handle);
emitter.fire(resource);
};
$updateSearchSession(session: number, data: URI): void {
if (this._searchSessions.has(session)) {
this._searchSessions.get(session).progress({ resource: data });
this._searchSessions.get(session).matches.push(data);
}
}
$finishSearchSession(session: number, err?: any): void {
if (this._searchSessions.has(session)) {
const { matches, resolve, reject } = this._searchSessions.get(session);
this._searchSessions.delete(session);
if (err) {
reject(err);
} else {
resolve({
limitHit: false,
stats: undefined,
results: matches.map(resource => ({ resource }))
});
}
}
}
}
......@@ -278,11 +278,10 @@ export interface MainThreadWorkspaceShape extends IDisposable {
$cancelSearch(requestId: number): Thenable<boolean>;
$saveAll(includeUntitled?: boolean): Thenable<boolean>;
$applyWorkspaceEdit(edits: IResourceEdit[]): TPromise<boolean>;
$registerFileSystemProvider(handle: number, authority: string): void;
$unregisterFileSystemProvider(handle): void;
$onFileSystemChange(handle: number, resource: URI): void;
$registerSearchProvider(handle: number, type: number): void;
$unregisterSearchProvider(handle: number): void;
$updateSearchSession(session: number, data): void;
$finishSearchSession(session: number, err?: any): void;
}
......@@ -426,7 +425,7 @@ export interface ExtHostWorkspaceShape {
$resolveFile(handle: number, resource: URI): TPromise<string>;
$storeFile(handle: number, resource: URI, content: string): TPromise<any>;
$startSearch(handle: number, session: number, query): void;
$startSearch(handle: number, session: number, query: string): void;
$cancelSearch(handle: number, session: number): void;
}
......
......@@ -212,7 +212,6 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
private _handlePool = 0;
private readonly _fsProvider = new Map<number, vscode.FileSystemProvider>();
private readonly _searchProvider = new Map<number, vscode.SearchProvider>();
private readonly _searchSession = new Map<number, CancellationTokenSource>();
registerFileSystemProvider(authority: string, provider: vscode.FileSystemProvider): vscode.Disposable {
......@@ -236,19 +235,13 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
return asWinJsPromise(token => provider.writeContents(resource, content));
}
registerSearchProvider(provider: vscode.SearchProvider): vscode.Disposable {
const handle = ++this._handlePool;
this._searchProvider.set(handle, provider);
return new Disposable(() => this._fsProvider.delete(handle));
}
$startSearch(handle: number, session: number, query): void {
const provider = this._searchProvider.get(handle);
$startSearch(handle: number, session: number, query: string): void {
const provider = this._fsProvider.get(handle);
const source = new CancellationTokenSource();
const progress = new Progress<any>(chunk => this._proxy.$updateSearchSession(session, chunk));
this._searchSession.set(session, source);
TPromise.wrap(provider.provideSearchResults(query, progress, source.token)).then(() => {
TPromise.wrap(provider.findFiles(query, progress, source.token)).then(() => {
this._proxy.$finishSearchSession(session);
}, err => {
this._proxy.$finishSearchSession(session, err);
......
......@@ -104,7 +104,7 @@ export class SearchService implements ISearchService {
// Allow caller to register progress callback
process.nextTick(() => localResults.values().filter((res) => !!res).forEach(onProgress));
const providerPromises = this.resultProvider.map(provider => provider.search(query).then(e => e,
const providerPromises = this.resultProvider.map(provider => TPromise.wrap(provider.search(query)).then(e => e,
err => {
// TODO@joh
// single provider fail. fail all?
......@@ -134,6 +134,9 @@ export class SearchService implements ISearchService {
// TODO@joh
// sorting, disjunct results, individual stats/limit?
for (const value of values) {
if (!value) {
continue;
}
result.limitHit = value.limitHit || result.limitHit;
for (const match of value.results) {
if (!localResults.has(match.resource)) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册