diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index e0732599290..9495412463a 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -58,7 +58,7 @@ import * as extHostTypes from 'vs/workbench/api/node/extHostTypes'; import { ExtHostUrls } from 'vs/workbench/api/node/extHostUrls'; import { ExtHostWebviews } from 'vs/workbench/api/node/extHostWebview'; import { ExtHostWindow } from 'vs/workbench/api/node/extHostWindow'; -import { ExtHostWorkspace, ExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; +import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { IExtensionDescription, throwProposedApiError, checkProposedApiEnabled, nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier'; import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry'; @@ -67,7 +67,7 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { originalFSPath } from 'vs/base/common/resources'; export interface IExtensionApiFactory { - (extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, workspaceProvider: ExtHostWorkspaceProvider, configProvider: ExtHostConfigProvider): typeof vscode; + (extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode; } function proposedApiFunction(extension: IExtensionDescription, fn: T): T { @@ -143,7 +143,7 @@ export function createApiFactory( // Register API-ish commands ExtHostApiCommands.register(extHostCommands); - return function (extension: IExtensionDescription, extensionRegistry: ExtensionDescriptionRegistry, workspaceProvider: ExtHostWorkspaceProvider, configProvider: ExtHostConfigProvider): typeof vscode { + return function (extension: IExtensionDescription, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode { // Check document selectors for being overly generic. Technically this isn't a problem but // in practice many extensions say they support `fooLang` but need fs-access to do so. Those @@ -516,34 +516,34 @@ export function createApiFactory( // namespace: workspace const workspace: typeof vscode.workspace = { get rootPath() { - return workspaceProvider.getPath(); + return extHostWorkspace.getPath(); }, set rootPath(value) { throw errors.readonly(); }, getWorkspaceFolder(resource) { - return workspaceProvider.getWorkspaceFolder(resource); + return extHostWorkspace.getWorkspaceFolder(resource); }, get workspaceFolders() { - return workspaceProvider.getWorkspaceFolders(); + return extHostWorkspace.getWorkspaceFolders(); }, get name() { - return workspaceProvider.name; + return extHostWorkspace.name; }, set name(value) { throw errors.readonly(); }, updateWorkspaceFolders: (index, deleteCount, ...workspaceFoldersToAdd) => { - return workspaceProvider.updateWorkspaceFolders(extension, index, deleteCount || 0, ...workspaceFoldersToAdd); + return extHostWorkspace.updateWorkspaceFolders(extension, index, deleteCount || 0, ...workspaceFoldersToAdd); }, onDidChangeWorkspaceFolders: function (listener, thisArgs?, disposables?) { - return workspaceProvider.onDidChangeWorkspace(listener, thisArgs, disposables); + return extHostWorkspace.onDidChangeWorkspace(listener, thisArgs, disposables); }, asRelativePath: (pathOrUri, includeWorkspace) => { - return workspaceProvider.getRelativePath(pathOrUri, includeWorkspace); + return extHostWorkspace.getRelativePath(pathOrUri, includeWorkspace); }, findFiles: (include, exclude, maxResults?, token?) => { - return workspaceProvider.findFiles(typeConverters.GlobPattern.from(include), typeConverters.GlobPattern.from(exclude), maxResults, extension.identifier, token); + return extHostWorkspace.findFiles(typeConverters.GlobPattern.from(include), typeConverters.GlobPattern.from(exclude), maxResults, extension.identifier, token); }, findTextInFiles: (query: vscode.TextSearchQuery, optionsOrCallback, callbackOrToken?, token?: vscode.CancellationToken) => { let options: vscode.FindTextInFilesOptions; @@ -558,10 +558,10 @@ export function createApiFactory( token = callbackOrToken; } - return workspaceProvider.findTextInFiles(query, options || {}, callback, extension.identifier, token); + return extHostWorkspace.findTextInFiles(query, options || {}, callback, extension.identifier, token); }, saveAll: (includeUntitled?) => { - return workspaceProvider.saveAll(includeUntitled); + return extHostWorkspace.saveAll(includeUntitled); }, applyEdit(edit: vscode.WorkspaceEdit): Thenable { return extHostEditors.applyWorkspaceEdit(edit); @@ -874,11 +874,11 @@ class Extension implements vscode.Extension { } } -export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory, extensionRegistry: ExtensionDescriptionRegistry, workspaceProvider: ExtHostWorkspaceProvider, configProvider: ExtHostConfigProvider): Promise { - return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie, extensionRegistry, workspaceProvider, configProvider)); +export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): Promise { + return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie, extensionRegistry, configProvider)); } -function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchTree, extensionRegistry: ExtensionDescriptionRegistry, workspaceProvider: ExtHostWorkspaceProvider, configProvider: ExtHostConfigProvider): void { +function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchTree, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): void { // each extension is meant to get its own api implementation const extApiImpl = new Map(); @@ -896,7 +896,7 @@ function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchT if (ext) { let apiImpl = extApiImpl.get(ExtensionIdentifier.toKey(ext.identifier)); if (!apiImpl) { - apiImpl = factory(ext, extensionRegistry, workspaceProvider, configProvider); + apiImpl = factory(ext, extensionRegistry, configProvider); extApiImpl.set(ExtensionIdentifier.toKey(ext.identifier), apiImpl); } return apiImpl; @@ -907,7 +907,7 @@ function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchT let extensionPathsPretty = ''; extensionPaths.forEach((value, index) => extensionPathsPretty += `\t${index} -> ${value.identifier.value}\n`); console.warn(`Could not identify extension for 'vscode' require call from ${parent.filename}. These are the extension path mappings: \n${extensionPathsPretty}`); - defaultApiImpl = factory(nullExtensionDescription, extensionRegistry, workspaceProvider, configProvider); + defaultApiImpl = factory(nullExtensionDescription, extensionRegistry, configProvider); } return defaultApiImpl; }; diff --git a/src/vs/workbench/api/node/extHostConfiguration.ts b/src/vs/workbench/api/node/extHostConfiguration.ts index be43259afaf..6b4e53f964d 100644 --- a/src/vs/workbench/api/node/extHostConfiguration.ts +++ b/src/vs/workbench/api/node/extHostConfiguration.ts @@ -7,7 +7,7 @@ import { mixin, deepClone } from 'vs/base/common/objects'; import { URI } from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; import * as vscode from 'vscode'; -import { ExtHostWorkspace, ExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; +import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData, IConfigurationInitData } from './extHost.protocol'; import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes'; import { IConfigurationData, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration'; @@ -57,10 +57,8 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { } $initializeConfiguration(data: IConfigurationInitData): void { - this._extHostWorkspace.getWorkspaceProvider().then(workspaceProvider => { - this._actual = new ExtHostConfigProvider(this._proxy, workspaceProvider, data); - this._barrier.open(); - }); + this._actual = new ExtHostConfigProvider(this._proxy, this._extHostWorkspace, data); + this._barrier.open(); } $acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData): void { @@ -72,11 +70,11 @@ export class ExtHostConfigProvider { private readonly _onDidChangeConfiguration = new Emitter(); private readonly _proxy: MainThreadConfigurationShape; - private readonly _extHostWorkspace: ExtHostWorkspaceProvider; + private readonly _extHostWorkspace: ExtHostWorkspace; private _configurationScopes: { [key: string]: ConfigurationScope }; private _configuration: Configuration; - constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspaceProvider, data: IConfigurationInitData) { + constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationInitData) { this._proxy = proxy; this._extHostWorkspace = extHostWorkspace; this._configuration = ExtHostConfigProvider.parse(data); diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts index 81cd56d5583..1b44f2898d4 100644 --- a/src/vs/workbench/api/node/extHostDebugService.ts +++ b/src/vs/workbench/api/node/extHostDebugService.ts @@ -16,7 +16,7 @@ import { import * as vscode from 'vscode'; import { Disposable, Position, Location, SourceBreakpoint, FunctionBreakpoint, DebugAdapterServer, DebugAdapterExecutable } from 'vs/workbench/api/node/extHostTypes'; import { ExecutableDebugAdapter, SocketDebugAdapter, AbstractDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter'; -import { ExtHostWorkspace, ExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; +import { IExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService'; import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors'; import { ITerminalSettings, IDebuggerContribution, IConfig, IDebugAdapter, IDebugAdapterServer, IDebugAdapterExecutable, IAdapterDescriptor } from 'vs/workbench/contrib/debug/common/debug'; @@ -82,7 +82,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { constructor(mainContext: IMainContext, - private _workspaceService: ExtHostWorkspace, + private _workspaceService: IExtHostWorkspaceProvider, private _extensionService: ExtHostExtensionService, private _editorsService: ExtHostDocumentsAndEditors, private _configurationService: ExtHostConfiguration, @@ -359,12 +359,12 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { } public async $substituteVariables(folderUri: UriComponents | undefined, config: IConfig): Promise { - const [workspaceProvider, configProvider] = await Promise.all([this._workspaceService.getWorkspaceProvider(), this._configurationService.getConfigProvider()]); + const [workspaceFolders, configProvider] = await Promise.all([this._workspaceService.getWorkspaceFolders2(), this._configurationService.getConfigProvider()]); if (!this._variableResolver) { - this._variableResolver = new ExtHostVariableResolverService(workspaceProvider, this._editorsService, configProvider); + this._variableResolver = new ExtHostVariableResolverService(workspaceFolders, this._editorsService, configProvider); } let ws: IWorkspaceFolder | undefined; - const folder = this.getFolder(folderUri, workspaceProvider); + const folder = await this.getFolder(folderUri); if (folder) { ws = { uri: folder.uri, @@ -379,10 +379,9 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { } public async $startDASession(debugAdapterHandle: number, sessionDto: IDebugSessionDto): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); const mythis = this; - const session = this.getSession(sessionDto, workspaceProvider); + const session = await this.getSession(sessionDto); return this.getAdapterDescriptor(this.getAdapterFactoryByType(session.type), session).then(x => { const adapter = this.convertToDto(x); @@ -547,7 +546,6 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { } public async $provideDebugConfigurations(configProviderHandle: number, folderUri: UriComponents | undefined): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); let provider = this.getConfigProviderByHandle(configProviderHandle); if (!provider) { return Promise.reject(new Error('no handler found')); @@ -555,11 +553,11 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { if (!provider.provideDebugConfigurations) { return Promise.reject(new Error('handler has no method provideDebugConfigurations')); } - return asPromise(() => provider.provideDebugConfigurations(this.getFolder(folderUri, workspaceProvider), CancellationToken.None)); + const folder = await this.getFolder(folderUri); + return asPromise(() => provider.provideDebugConfigurations(folder, CancellationToken.None)); } public async $resolveDebugConfiguration(configProviderHandle: number, folderUri: UriComponents | undefined, debugConfiguration: vscode.DebugConfiguration): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); let provider = this.getConfigProviderByHandle(configProviderHandle); if (!provider) { return Promise.reject(new Error('no handler found')); @@ -567,12 +565,12 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { if (!provider.resolveDebugConfiguration) { return Promise.reject(new Error('handler has no method resolveDebugConfiguration')); } - return asPromise(() => provider.resolveDebugConfiguration(this.getFolder(folderUri, workspaceProvider), debugConfiguration, CancellationToken.None)); + const folder = await this.getFolder(folderUri); + return asPromise(() => provider.resolveDebugConfiguration(folder, debugConfiguration, CancellationToken.None)); } // TODO@AW legacy public async $legacyDebugAdapterExecutable(configProviderHandle: number, folderUri: UriComponents | undefined): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); let provider = this.getConfigProviderByHandle(configProviderHandle); if (!provider) { return Promise.reject(new Error('no handler found')); @@ -580,26 +578,26 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { if (!provider.debugAdapterExecutable) { return Promise.reject(new Error('handler has no method debugAdapterExecutable')); } - return asPromise(() => provider.debugAdapterExecutable(this.getFolder(folderUri, workspaceProvider), CancellationToken.None)).then(x => this.convertToDto(x)); + const folder = await this.getFolder(folderUri); + return asPromise(() => provider.debugAdapterExecutable(folder, CancellationToken.None)).then(x => this.convertToDto(x)); } public async $provideDebugAdapter(adapterProviderHandle: number, sessionDto: IDebugSessionDto): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); let adapterProvider = this.getAdapterProviderByHandle(adapterProviderHandle); if (!adapterProvider) { return Promise.reject(new Error('no handler found')); } - return this.getAdapterDescriptor(adapterProvider, this.getSession(sessionDto, workspaceProvider)).then(x => this.convertToDto(x)); + const session = await this.getSession(sessionDto); + return this.getAdapterDescriptor(adapterProvider, session).then(x => this.convertToDto(x)); } public async $acceptDebugSessionStarted(sessionDto: IDebugSessionDto): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); - this._onDidStartDebugSession.fire(this.getSession(sessionDto, workspaceProvider)); + const session = await this.getSession(sessionDto); + this._onDidStartDebugSession.fire(session); } public async $acceptDebugSessionTerminated(sessionDto: IDebugSessionDto): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); - const session = this.getSession(sessionDto, workspaceProvider); + const session = await this.getSession(sessionDto); if (session) { this._onDidTerminateDebugSession.fire(session); this._debugSessions.delete(session.id); @@ -607,15 +605,14 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { } public async $acceptDebugSessionActiveChanged(sessionDto: IDebugSessionDto | undefined): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); - this._activeDebugSession = sessionDto ? this.getSession(sessionDto, workspaceProvider) : undefined; + this._activeDebugSession = sessionDto ? await this.getSession(sessionDto) : undefined; this._onDidChangeActiveDebugSession.fire(this._activeDebugSession); } public async $acceptDebugSessionCustomEvent(sessionDto: IDebugSessionDto, event: any): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); + const session = await this.getSession(sessionDto); const ee: vscode.DebugSessionCustomEvent = { - session: this.getSession(sessionDto, workspaceProvider), + session: session, event: event.event, body: event.body }; @@ -780,12 +777,13 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { } } - private getSession(dto: IDebugSessionDto, workspaceProvider: ExtHostWorkspaceProvider): ExtHostDebugSession { + private async getSession(dto: IDebugSessionDto): Promise { if (dto) { if (typeof dto === 'string') { return this._debugSessions.get(dto); } else { - const debugSession = new ExtHostDebugSession(this._debugServiceProxy, dto.id, dto.type, dto.name, this.getFolder(dto.folderUri, workspaceProvider), dto.configuration); + const folder = await this.getFolder(dto.folderUri); + const debugSession = new ExtHostDebugSession(this._debugServiceProxy, dto.id, dto.type, dto.name, folder, dto.configuration); this._debugSessions.set(debugSession.id, debugSession); return debugSession; } @@ -793,10 +791,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { return undefined; } - private getFolder(_folderUri: UriComponents | undefined, workspaceProvider: ExtHostWorkspaceProvider): vscode.WorkspaceFolder | undefined { + private async getFolder(_folderUri: UriComponents | undefined): Promise { if (_folderUri) { const folderURI = URI.revive(_folderUri); - return workspaceProvider.resolveWorkspaceFolder(folderURI); + return await this._workspaceService.resolveWorkspaceFolder2(folderURI); } return undefined; } @@ -857,10 +855,9 @@ export class ExtHostDebugConsole implements vscode.DebugConsole { export class ExtHostVariableResolverService extends AbstractVariableResolverService { - constructor(workspaceService: ExtHostWorkspaceProvider, editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfigProvider) { + constructor(folders: vscode.WorkspaceFolder[], editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfigProvider) { super({ getFolderUri: (folderName: string): URI => { - const folders = workspaceService.getWorkspaceFolders(); const found = folders.filter(f => f.name === folderName); if (found && found.length > 0) { return found[0].uri; @@ -868,7 +865,7 @@ export class ExtHostVariableResolverService extends AbstractVariableResolverServ return undefined; }, getWorkspaceFolderCount: (): number => { - return workspaceService.getWorkspaceFolders().length; + return folders.length; }, getConfigurationValue: (folderUri: URI, section: string) => { return configurationService.getConfiguration(undefined, folderUri).get(section); diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index ad668857a8a..2f0c9249f94 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -18,7 +18,7 @@ import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration import { ActivatedExtension, EmptyExtension, ExtensionActivatedByAPI, ExtensionActivatedByEvent, ExtensionActivationReason, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionContext, IExtensionMemento, IExtensionModule, HostExtension } from 'vs/workbench/api/node/extHostExtensionActivator'; import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService'; import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage'; -import { ExtHostWorkspace, ExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; +import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry'; import { connectProxyResolver } from 'vs/workbench/services/extensions/node/proxyResolver'; @@ -245,10 +245,10 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { private async _initialize(): Promise { try { const configProvider = await this._extHostConfiguration.getConfigProvider(); - const workspaceProvider = await this._extHostWorkspace.getWorkspaceProvider(); - await initializeExtensionApi(this, this._extensionApiFactory, this._registry, workspaceProvider, configProvider); + await this._extHostWorkspace.waitForInitializeCall(); + await initializeExtensionApi(this, this._extensionApiFactory, this._registry, configProvider); // Do this when extension service exists, but extensions are not being activated yet. - await connectProxyResolver(workspaceProvider, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy); + await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy); this._barrier.open(); } catch (err) { errors.onUnexpectedError(err); @@ -490,12 +490,12 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { // -- eager activation // Handle "eager" activation extensions - private _handleEagerExtensions(workspaceProvider: ExtHostWorkspaceProvider): Promise { + private _handleEagerExtensions(): Promise { this._activateByEvent('*', true).then(undefined, (err) => { console.error(err); }); - return this._handleWorkspaceContainsEagerExtensions(workspaceProvider.workspace); + return this._handleWorkspaceContainsEagerExtensions(this._extHostWorkspace.workspace); } private _handleWorkspaceContainsEagerExtensions(workspace: IWorkspace | undefined): Promise { @@ -658,8 +658,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { this._started = true; return this._barrier.wait() - .then(() => this._extHostWorkspace.getWorkspaceProvider()) - .then(workspaceProvider => this._handleEagerExtensions(workspaceProvider)) + .then(() => this._handleEagerExtensions()) .then(() => this._handleExtensionTests()) .then(() => { this._extHostLogService.info(`eager extensions activated`); diff --git a/src/vs/workbench/api/node/extHostQuickOpen.ts b/src/vs/workbench/api/node/extHostQuickOpen.ts index c2a196eb685..7b8dd2432ee 100644 --- a/src/vs/workbench/api/node/extHostQuickOpen.ts +++ b/src/vs/workbench/api/node/extHostQuickOpen.ts @@ -8,7 +8,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { Emitter } from 'vs/base/common/event'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands'; -import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; +import { IExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; import { InputBox, InputBoxOptions, QuickInput, QuickInputButton, QuickPick, QuickPickItem, QuickPickOptions, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode'; import { ExtHostQuickOpenShape, IMainContext, MainContext, MainThreadQuickOpenShape, TransferQuickPickItems, TransferQuickInput, TransferQuickInputButton } from './extHost.protocol'; import { URI } from 'vs/base/common/uri'; @@ -21,7 +21,7 @@ export type Item = string | QuickPickItem; export class ExtHostQuickOpen implements ExtHostQuickOpenShape { private _proxy: MainThreadQuickOpenShape; - private _workspace: ExtHostWorkspace; + private _workspace: IExtHostWorkspaceProvider; private _commands: ExtHostCommands; private _onDidSelectItem: (handle: number) => void; @@ -31,7 +31,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape { private _instances = 0; - constructor(mainContext: IMainContext, workspace: ExtHostWorkspace, commands: ExtHostCommands) { + constructor(mainContext: IMainContext, workspace: IExtHostWorkspaceProvider, commands: ExtHostCommands) { this._proxy = mainContext.getProxy(MainContext.MainThreadQuickOpen); this._workspace = workspace; this._commands = commands; @@ -159,12 +159,12 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape { // ---- workspace folder picker showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions, token = CancellationToken.None): Promise { - return this._commands.executeCommand('_workbench.pickWorkspaceFolder', [options]).then((selectedFolder: WorkspaceFolder) => { + return this._commands.executeCommand('_workbench.pickWorkspaceFolder', [options]).then(async (selectedFolder: WorkspaceFolder) => { if (!selectedFolder) { return undefined; } - - return this._workspace.getWorkspaceProvider().then(workspaceProvider => workspaceProvider.getWorkspaceFolders().filter(folder => folder.uri.toString() === selectedFolder.uri.toString())[0]); + const workspaceFolders = await this._workspace.getWorkspaceFolders2(); + return workspaceFolders.filter(folder => folder.uri.toString() === selectedFolder.uri.toString())[0]; }); } diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index 3a61710c362..cf5f6b0dcfd 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -16,7 +16,7 @@ import { IExtensionDescription } from 'vs/workbench/services/extensions/common/e import { MainContext, MainThreadTaskShape, ExtHostTaskShape, IMainContext } from 'vs/workbench/api/node/extHost.protocol'; import * as types from 'vs/workbench/api/node/extHostTypes'; -import { ExtHostWorkspace, ExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; +import { ExtHostWorkspace, IExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; import * as vscode from 'vscode'; import { TaskDefinitionDTO, TaskExecutionDTO, TaskPresentationOptionsDTO, ProcessExecutionOptionsDTO, ProcessExecutionDTO, @@ -222,7 +222,7 @@ namespace TaskDTO { }; return result; } - export function to(value: TaskDTO, workspace: ExtHostWorkspaceProvider): types.Task { + export async function to(value: TaskDTO, workspace: IExtHostWorkspaceProvider): Promise { if (value === undefined || value === null) { return undefined; } @@ -239,7 +239,7 @@ namespace TaskDTO { if (typeof value.source.scope === 'number') { scope = value.source.scope; } else { - scope = workspace.resolveWorkspaceFolder(URI.revive(value.source.scope)); + scope = await workspace.resolveWorkspaceFolder2(URI.revive(value.source.scope)); } } else { scope = types.TaskScope.Workspace; @@ -299,8 +299,8 @@ class TaskExecutionImpl implements vscode.TaskExecution { } namespace TaskExecutionDTO { - export function to(value: TaskExecutionDTO, tasks: ExtHostTask, workspaceProvider: ExtHostWorkspaceProvider): vscode.TaskExecution { - return new TaskExecutionImpl(tasks, value.id, TaskDTO.to(value.task, workspaceProvider)); + export async function to(value: TaskExecutionDTO, tasks: ExtHostTask, workspaceProvider: IExtHostWorkspaceProvider): Promise { + return new TaskExecutionImpl(tasks, value.id, await TaskDTO.to(value.task, workspaceProvider)); } export function from(value: vscode.TaskExecution): TaskExecutionDTO { return { @@ -318,7 +318,7 @@ interface HandlerData { export class ExtHostTask implements ExtHostTaskShape { private _proxy: MainThreadTaskShape; - private _workspaceService: ExtHostWorkspace; + private _workspaceProvider: IExtHostWorkspaceProvider; private _editorService: ExtHostDocumentsAndEditors; private _configurationService: ExtHostConfiguration; private _handleCounter: number; @@ -333,7 +333,7 @@ export class ExtHostTask implements ExtHostTaskShape { constructor(mainContext: IMainContext, workspaceService: ExtHostWorkspace, editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfiguration) { this._proxy = mainContext.getProxy(MainContext.MainThreadTask); - this._workspaceService = workspaceService; + this._workspaceProvider = workspaceService; this._editorService = editorService; this._configurationService = configurationService; this._handleCounter = 0; @@ -361,9 +361,8 @@ export class ExtHostTask implements ExtHostTaskShape { public fetchTasks(filter?: vscode.TaskFilter): Promise { return this._proxy.$fetchTasks(TaskFilterDTO.from(filter)).then(async (values) => { let result: vscode.Task[] = []; - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); for (let value of values) { - let task = TaskDTO.to(value, workspaceProvider); + let task = await TaskDTO.to(value, this._workspaceProvider); if (task) { result.push(task); } @@ -373,17 +372,16 @@ export class ExtHostTask implements ExtHostTaskShape { } public async executeTask(extension: IExtensionDescription, task: vscode.Task): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); let tTask = (task as types.Task); // We have a preserved ID. So the task didn't change. if (tTask._id !== undefined) { - return this._proxy.$executeTask(TaskHandleDTO.from(tTask)).then(value => this.getTaskExecution(value, workspaceProvider, task)); + return this._proxy.$executeTask(TaskHandleDTO.from(tTask)).then(value => this.getTaskExecution(value, task)); } else { let dto = TaskDTO.from(task, extension); if (dto === undefined) { return Promise.reject(new Error('Task is not valid')); } - return this._proxy.$executeTask(dto).then(value => this.getTaskExecution(value, workspaceProvider, task)); + return this._proxy.$executeTask(dto).then(value => this.getTaskExecution(value, task)); } } @@ -405,9 +403,8 @@ export class ExtHostTask implements ExtHostTaskShape { } public async $onDidStartTask(execution: TaskExecutionDTO): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); this._onDidExecuteTask.fire({ - execution: this.getTaskExecution(execution, workspaceProvider) + execution: await this.getTaskExecution(execution) }); } @@ -416,8 +413,7 @@ export class ExtHostTask implements ExtHostTaskShape { } public async $OnDidEndTask(execution: TaskExecutionDTO): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); - const _execution = this.getTaskExecution(execution, workspaceProvider); + const _execution = await this.getTaskExecution(execution); this._taskExecutions.delete(execution.id); this._onDidTerminateTask.fire({ execution: _execution @@ -429,8 +425,7 @@ export class ExtHostTask implements ExtHostTaskShape { } public async $onDidStartTaskProcess(value: TaskProcessStartedDTO): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); - const execution = this.getTaskExecution(value.id, workspaceProvider); + const execution = await this.getTaskExecution(value.id); if (execution) { this._onDidTaskProcessStarted.fire({ execution: execution, @@ -444,8 +439,7 @@ export class ExtHostTask implements ExtHostTaskShape { } public async $onDidEndTaskProcess(value: TaskProcessEndedDTO): Promise { - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); - const execution = this.getTaskExecution(value.id, workspaceProvider); + const execution = await this.getTaskExecution(value.id); if (execution) { this._onDidTaskProcessEnded.fire({ execution: execution, @@ -478,14 +472,14 @@ export class ExtHostTask implements ExtHostTaskShape { public async $resolveVariables(uriComponents: UriComponents, toResolve: { process?: { name: string; cwd?: string; path?: string }, variables: string[] }): Promise<{ process?: string, variables: { [key: string]: string; } }> { const configProvider = await this._configurationService.getConfigProvider(); - const workspaceProvider = await this._workspaceService.getWorkspaceProvider(); let uri: URI = URI.revive(uriComponents); let result = { process: undefined as string, variables: Object.create(null) }; - let workspaceFolder = workspaceProvider.resolveWorkspaceFolder(uri); - let resolver = new ExtHostVariableResolverService(workspaceProvider, this._editorService, configProvider); + let workspaceFolder = await this._workspaceProvider.resolveWorkspaceFolder2(uri); + const workspaceFolders = await this._workspaceProvider.getWorkspaceFolders2(); + let resolver = new ExtHostVariableResolverService(workspaceFolders, this._editorService, configProvider); let ws: IWorkspaceFolder = { uri: workspaceFolder.uri, name: workspaceFolder.name, @@ -518,7 +512,7 @@ export class ExtHostTask implements ExtHostTaskShape { return this._handleCounter++; } - private getTaskExecution(execution: TaskExecutionDTO | string, workspaceProvider: ExtHostWorkspaceProvider, task?: vscode.Task): TaskExecutionImpl { + private async getTaskExecution(execution: TaskExecutionDTO | string, task?: vscode.Task): Promise { if (typeof execution === 'string') { return this._taskExecutions.get(execution); } @@ -527,7 +521,7 @@ export class ExtHostTask implements ExtHostTaskShape { if (result) { return result; } - result = new TaskExecutionImpl(this, execution.id, task ? task : TaskDTO.to(execution.task, workspaceProvider)); + result = new TaskExecutionImpl(this, execution.id, task ? task : await TaskDTO.to(execution.task, this._workspaceProvider)); this._taskExecutions.set(execution.id, result); return result; } diff --git a/src/vs/workbench/api/node/extHostWorkspace.ts b/src/vs/workbench/api/node/extHostWorkspace.ts index 4cd66f5e7c6..6de98c9c63c 100644 --- a/src/vs/workbench/api/node/extHostWorkspace.ts +++ b/src/vs/workbench/api/node/extHostWorkspace.ts @@ -22,10 +22,17 @@ import { Range, RelativePattern } from 'vs/workbench/api/node/extHostTypes'; import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; import * as vscode from 'vscode'; -import { ExtHostWorkspaceShape, IWorkspaceData, MainThreadMessageServiceShape, MainThreadWorkspaceShape, IMainContext, MainContext } from './extHost.protocol'; +import { ExtHostWorkspaceShape, IWorkspaceData, MainThreadMessageServiceShape, MainThreadWorkspaceShape, IMainContext, MainContext, IStaticWorkspaceData } from './extHost.protocol'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { Barrier } from 'vs/base/common/async'; +export interface IExtHostWorkspaceProvider { + getWorkspaceFolder2(uri: vscode.Uri, resolveParent?: boolean): Promise; + resolveWorkspaceFolder2(uri: vscode.Uri): Promise; + getWorkspaceFolders2(): Promise; + resolveProxy(url: string): Promise; +} + function isFolderEqual(folderA: URI, folderB: URI): boolean { return isEqual(folderA, folderB, !isLinux); } @@ -109,7 +116,7 @@ class ExtHostWorkspaceImpl extends Workspace { private readonly _workspaceFolders: vscode.WorkspaceFolder[] = []; private readonly _structure = TernarySearchTree.forPaths(); - private constructor(id: string, private _name: string, folders: vscode.WorkspaceFolder[]) { + constructor(id: string, private _name: string, folders: vscode.WorkspaceFolder[]) { super(id, folders.map(f => new WorkspaceFolder(f))); // setup the workspace folder data structure @@ -140,51 +147,14 @@ class ExtHostWorkspaceImpl extends Workspace { } } -export class ExtHostWorkspace implements ExtHostWorkspaceShape { +export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspaceProvider { + + private readonly _onDidChangeWorkspace = new Emitter(); + readonly onDidChangeWorkspace: Event = this._onDidChangeWorkspace.event; - private readonly _mainContext: IMainContext; private readonly _logService: ILogService; private readonly _requestIdProvider: Counter; private readonly _barrier: Barrier; - private _actual: ExtHostWorkspaceProvider | null; - - constructor( - mainContext: IMainContext, - logService: ILogService, - requestIdProvider: Counter - ) { - this._mainContext = mainContext; - this._logService = logService; - this._requestIdProvider = requestIdProvider; - this._barrier = new Barrier(); - this._actual = null; - } - - public getWorkspaceProvider(): Promise { - return this._barrier.wait().then(_ => this._actual!); - } - - $initializeWorkspace(data: IWorkspaceData): void { - this._actual = new ExtHostWorkspaceProvider(this._mainContext, data, this._logService, this._requestIdProvider); - this._barrier.open(); - } - - $acceptWorkspaceData(workspace: IWorkspaceData): void { - if (this._actual) { - this._actual.$acceptWorkspaceData(workspace); - } - } - - $handleTextSearchResult(result: IRawFileMatch2, requestId: number): void { - if (this._actual) { - this._actual.$handleTextSearchResult(result, requestId); - } - } - -} -export class ExtHostWorkspaceProvider { - - private readonly _onDidChangeWorkspace = new Emitter(); private _confirmedWorkspace?: ExtHostWorkspaceImpl; private _unconfirmedWorkspace?: ExtHostWorkspaceImpl; @@ -192,19 +162,30 @@ export class ExtHostWorkspaceProvider { private readonly _proxy: MainThreadWorkspaceShape; private readonly _messageService: MainThreadMessageServiceShape; - readonly onDidChangeWorkspace: Event = this._onDidChangeWorkspace.event; - private readonly _activeSearchCallbacks: ((match: IRawFileMatch2) => any)[] = []; constructor( mainContext: IMainContext, - data: IWorkspaceData | null, - private _logService: ILogService, - private _requestIdProvider: Counter + logService: ILogService, + requestIdProvider: Counter, + data?: IStaticWorkspaceData ) { + this._logService = logService; + this._requestIdProvider = requestIdProvider; + this._barrier = new Barrier(); + this._proxy = mainContext.getProxy(MainContext.MainThreadWorkspace); this._messageService = mainContext.getProxy(MainContext.MainThreadMessageService); - this._confirmedWorkspace = ExtHostWorkspaceImpl.toExtHostWorkspace(data).workspace || undefined; + this._confirmedWorkspace = data ? new ExtHostWorkspaceImpl(data.id, data.name, []) : undefined; + } + + $initializeWorkspace(data: IWorkspaceData): void { + this.$acceptWorkspaceData(data); + this._barrier.open(); + } + + waitForInitializeCall(): Promise { + return this._barrier.wait(); } // --- workspace --- @@ -228,6 +209,14 @@ export class ExtHostWorkspaceProvider { return this._actualWorkspace.workspaceFolders.slice(0); } + async getWorkspaceFolders2(): Promise { + await this._barrier.wait(); + if (!this._actualWorkspace) { + return undefined; + } + return this._actualWorkspace.workspaceFolders.slice(0); + } + updateWorkspaceFolders(extension: IExtensionDescription, index: number, deleteCount: number, ...workspaceFoldersToAdd: { uri: vscode.Uri, name?: string }[]): boolean { const validatedDistinctWorkspaceFoldersToAdd: { uri: vscode.Uri, name?: string }[] = []; if (Array.isArray(workspaceFoldersToAdd)) { @@ -299,6 +288,14 @@ export class ExtHostWorkspaceProvider { return this._actualWorkspace.getWorkspaceFolder(uri, resolveParent); } + async getWorkspaceFolder2(uri: vscode.Uri, resolveParent?: boolean): Promise { + await this._barrier.wait(); + if (!this._actualWorkspace) { + return undefined; + } + return this._actualWorkspace.getWorkspaceFolder(uri, resolveParent); + } + resolveWorkspaceFolder(uri: vscode.Uri): vscode.WorkspaceFolder | undefined { if (!this._actualWorkspace) { return undefined; @@ -306,6 +303,14 @@ export class ExtHostWorkspaceProvider { return this._actualWorkspace.resolveWorkspaceFolder(uri); } + async resolveWorkspaceFolder2(uri: vscode.Uri): Promise { + await this._barrier.wait(); + if (!this._actualWorkspace) { + return undefined; + } + return this._actualWorkspace.resolveWorkspaceFolder(uri); + } + getPath(): string | undefined { // this is legacy from the days before having diff --git a/src/vs/workbench/services/extensions/node/extensionHostMain.ts b/src/vs/workbench/services/extensions/node/extensionHostMain.ts index 6f62be729ad..66e03162e40 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostMain.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostMain.ts @@ -73,7 +73,7 @@ export class ExtensionHostMain { this.disposables.push(this._extHostLogService); this._searchRequestIdProvider = new Counter(); - const extHostWorkspace = new ExtHostWorkspace(rpcProtocol, this._extHostLogService, this._searchRequestIdProvider); + const extHostWorkspace = new ExtHostWorkspace(rpcProtocol, this._extHostLogService, this._searchRequestIdProvider, initData.workspace); this._extHostLogService.info('extension host started'); this._extHostLogService.trace('initData', initData); diff --git a/src/vs/workbench/services/extensions/node/proxyResolver.ts b/src/vs/workbench/services/extensions/node/proxyResolver.ts index a59b0a6b358..98fed1fac42 100644 --- a/src/vs/workbench/services/extensions/node/proxyResolver.ts +++ b/src/vs/workbench/services/extensions/node/proxyResolver.ts @@ -8,7 +8,7 @@ import * as https from 'https'; import * as nodeurl from 'url'; import { assign } from 'vs/base/common/objects'; -import { ExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; +import { IExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; import { ExtHostConfigProvider } from 'vs/workbench/api/node/extHostConfiguration'; import { ProxyAgent } from 'vscode-proxy-agent'; import { MainThreadTelemetryShape } from 'vs/workbench/api/node/extHost.protocol'; @@ -25,7 +25,7 @@ interface ConnectionResult { } export function connectProxyResolver( - extHostWorkspace: ExtHostWorkspaceProvider, + extHostWorkspace: IExtHostWorkspaceProvider, configProvider: ExtHostConfigProvider, extensionService: ExtHostExtensionService, extHostLogService: ExtHostLogService, @@ -39,7 +39,7 @@ export function connectProxyResolver( const maxCacheEntries = 5000; // Cache can grow twice that much due to 'oldCache'. function setupProxyResolution( - extHostWorkspace: ExtHostWorkspaceProvider, + extHostWorkspace: IExtHostWorkspaceProvider, configProvider: ExtHostConfigProvider, extHostLogService: ExtHostLogService, mainThreadTelemetry: MainThreadTelemetryShape diff --git a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts index e8d1abc034c..ac0062c6c24 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import { URI } from 'vs/base/common/uri'; -import { ExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; +import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { ExtHostConfigProvider } from 'vs/workbench/api/node/extHostConfiguration'; import { MainThreadConfigurationShape, IConfigurationInitData } from 'vs/workbench/api/node/extHost.protocol'; import { ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; @@ -31,7 +31,7 @@ suite('ExtHostConfiguration', function () { if (!shape) { shape = new class extends mock() { }; } - return new ExtHostConfigProvider(shape, new ExtHostWorkspaceProvider(new TestRPCProtocol(), null, new NullLogService(), new Counter()), createConfigurationData(contents)); + return new ExtHostConfigProvider(shape, new ExtHostWorkspace(new TestRPCProtocol(), new NullLogService(), new Counter()), createConfigurationData(contents)); } function createConfigurationData(contents: any): IConfigurationInitData { @@ -265,7 +265,7 @@ suite('ExtHostConfiguration', function () { test('inspect in no workspace context', function () { const testObject = new ExtHostConfigProvider( new class extends mock() { }, - new ExtHostWorkspaceProvider(new TestRPCProtocol(), null, new NullLogService(), new Counter()), + new ExtHostWorkspace(new TestRPCProtocol(), new NullLogService(), new Counter()), { defaults: new ConfigurationModel({ 'editor': { @@ -306,13 +306,15 @@ suite('ExtHostConfiguration', function () { } }, ['editor.wordWrap']); folders[workspaceUri.toString()] = workspace; + const extHostWorkspace = new ExtHostWorkspace(new TestRPCProtocol(), new NullLogService(), new Counter()); + extHostWorkspace.$initializeWorkspace({ + 'id': 'foo', + 'folders': [aWorkspaceFolder(URI.file('foo'), 0)], + 'name': 'foo' + }); const testObject = new ExtHostConfigProvider( new class extends mock() { }, - new ExtHostWorkspaceProvider(new TestRPCProtocol(), { - 'id': 'foo', - 'folders': [aWorkspaceFolder(URI.file('foo'), 0)], - 'name': 'foo' - }, new NullLogService(), new Counter()), + extHostWorkspace, { defaults: new ConfigurationModel({ 'editor': { @@ -380,13 +382,15 @@ suite('ExtHostConfiguration', function () { }, ['editor.wordWrap']); folders[thirdRoot.toString()] = new ConfigurationModel({}, []); + const extHostWorkspace = new ExtHostWorkspace(new TestRPCProtocol(), new NullLogService(), new Counter()); + extHostWorkspace.$initializeWorkspace({ + 'id': 'foo', + 'folders': [aWorkspaceFolder(firstRoot, 0), aWorkspaceFolder(secondRoot, 1)], + 'name': 'foo' + }); const testObject = new ExtHostConfigProvider( new class extends mock() { }, - new ExtHostWorkspaceProvider(new TestRPCProtocol(), { - 'id': 'foo', - 'folders': [aWorkspaceFolder(firstRoot, 0), aWorkspaceFolder(secondRoot, 1)], - 'name': 'foo' - }, new NullLogService(), new Counter()), + extHostWorkspace, { defaults: new ConfigurationModel({ 'editor': { @@ -589,13 +593,15 @@ suite('ExtHostConfiguration', function () { test('configuration change event', (done) => { const workspaceFolder = aWorkspaceFolder(URI.file('folder1'), 0); + const extHostWorkspace = new ExtHostWorkspace(new TestRPCProtocol(), new NullLogService(), new Counter()); + extHostWorkspace.$initializeWorkspace({ + 'id': 'foo', + 'folders': [workspaceFolder], + 'name': 'foo' + }); const testObject = new ExtHostConfigProvider( new class extends mock() { }, - new ExtHostWorkspaceProvider(new TestRPCProtocol(), { - 'id': 'foo', - 'folders': [workspaceFolder], - 'name': 'foo' - }, new NullLogService(), new Counter()), + extHostWorkspace, createConfigurationData({ 'farboo': { 'config': false, diff --git a/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts b/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts index 8cc4279dfd9..40de7dbe2b3 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts @@ -6,15 +6,21 @@ import * as assert from 'assert'; import { URI } from 'vs/base/common/uri'; import { basename } from 'vs/base/common/path'; -import { ExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; +import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { TestRPCProtocol } from './testRPCProtocol'; import { IWorkspaceFolderData } from 'vs/platform/workspace/common/workspace'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; -import { NullLogService } from 'vs/platform/log/common/log'; -import { IMainContext } from 'vs/workbench/api/node/extHost.protocol'; +import { NullLogService, ILogService } from 'vs/platform/log/common/log'; +import { IMainContext, IWorkspaceData } from 'vs/workbench/api/node/extHost.protocol'; import { Counter } from 'vs/base/common/numbers'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; +function createExtHostWorkspace(mainContext: IMainContext, data: IWorkspaceData, logService: ILogService, requestIdProvider: Counter): ExtHostWorkspace { + const result = new ExtHostWorkspace(mainContext, logService, requestIdProvider); + result.$initializeWorkspace(data); + return result; +} + suite('ExtHostWorkspace', function () { const extensionDescriptor: IExtensionDescription = { @@ -29,14 +35,14 @@ suite('ExtHostWorkspace', function () { version: undefined! }; - function assertAsRelativePath(workspace: ExtHostWorkspaceProvider, input: string, expected: string, includeWorkspace?: boolean) { + function assertAsRelativePath(workspace: ExtHostWorkspace, input: string, expected: string, includeWorkspace?: boolean) { const actual = workspace.getRelativePath(input, includeWorkspace); assert.equal(actual, expected); } test('asRelativePath', () => { - const ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/Applications/NewsWoWBot'), 0)], name: 'Test' }, new NullLogService(), new Counter()); + const ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/Applications/NewsWoWBot'), 0)], name: 'Test' }, new NullLogService(), new Counter()); assertAsRelativePath(ws, '/Coding/Applications/NewsWoWBot/bernd/das/brot', 'bernd/das/brot'); assertAsRelativePath(ws, '/Apps/DartPubCache/hosted/pub.dartlang.org/convert-2.0.1/lib/src/hex.dart', @@ -50,7 +56,7 @@ suite('ExtHostWorkspace', function () { test('asRelativePath, same paths, #11402', function () { const root = '/home/aeschli/workspaces/samples/docker'; const input = '/home/aeschli/workspaces/samples/docker'; - const ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService(), new Counter()); + const ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService(), new Counter()); assertAsRelativePath(ws, input, input); @@ -59,20 +65,20 @@ suite('ExtHostWorkspace', function () { }); test('asRelativePath, no workspace', function () { - const ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), null!, new NullLogService(), new Counter()); + const ws = createExtHostWorkspace(new TestRPCProtocol(), null!, new NullLogService(), new Counter()); assertAsRelativePath(ws, '', ''); assertAsRelativePath(ws, '/foo/bar', '/foo/bar'); }); test('asRelativePath, multiple folders', function () { - const ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/One'), 0), aWorkspaceFolderData(URI.file('/Coding/Two'), 1)], name: 'Test' }, new NullLogService(), new Counter()); + const ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/One'), 0), aWorkspaceFolderData(URI.file('/Coding/Two'), 1)], name: 'Test' }, new NullLogService(), new Counter()); assertAsRelativePath(ws, '/Coding/One/file.txt', 'One/file.txt'); assertAsRelativePath(ws, '/Coding/Two/files/out.txt', 'Two/files/out.txt'); assertAsRelativePath(ws, '/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt'); }); test('slightly inconsistent behaviour of asRelativePath and getWorkspaceFolder, #31553', function () { - const mrws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/One'), 0), aWorkspaceFolderData(URI.file('/Coding/Two'), 1)], name: 'Test' }, new NullLogService(), new Counter()); + const mrws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/One'), 0), aWorkspaceFolderData(URI.file('/Coding/Two'), 1)], name: 'Test' }, new NullLogService(), new Counter()); assertAsRelativePath(mrws, '/Coding/One/file.txt', 'One/file.txt'); assertAsRelativePath(mrws, '/Coding/One/file.txt', 'One/file.txt', true); @@ -84,7 +90,7 @@ suite('ExtHostWorkspace', function () { assertAsRelativePath(mrws, '/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt', true); assertAsRelativePath(mrws, '/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt', false); - const srws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/One'), 0)], name: 'Test' }, new NullLogService(), new Counter()); + const srws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/One'), 0)], name: 'Test' }, new NullLogService(), new Counter()); assertAsRelativePath(srws, '/Coding/One/file.txt', 'file.txt'); assertAsRelativePath(srws, '/Coding/One/file.txt', 'file.txt', false); assertAsRelativePath(srws, '/Coding/One/file.txt', 'One/file.txt', true); @@ -94,24 +100,24 @@ suite('ExtHostWorkspace', function () { }); test('getPath, legacy', function () { - let ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }, new NullLogService(), new Counter()); + let ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }, new NullLogService(), new Counter()); assert.equal(ws.getPath(), undefined); - ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), null!, new NullLogService(), new Counter()); + ws = createExtHostWorkspace(new TestRPCProtocol(), null!, new NullLogService(), new Counter()); assert.equal(ws.getPath(), undefined); - ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), undefined!, new NullLogService(), new Counter()); + ws = createExtHostWorkspace(new TestRPCProtocol(), undefined!, new NullLogService(), new Counter()); assert.equal(ws.getPath(), undefined); - ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.file('Folder'), 0), aWorkspaceFolderData(URI.file('Another/Folder'), 1)] }, new NullLogService(), new Counter()); + ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.file('Folder'), 0), aWorkspaceFolderData(URI.file('Another/Folder'), 1)] }, new NullLogService(), new Counter()); assert.equal(ws.getPath()!.replace(/\\/g, '/'), '/Folder'); - ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.file('/Folder'), 0)] }, new NullLogService(), new Counter()); + ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.file('/Folder'), 0)] }, new NullLogService(), new Counter()); assert.equal(ws.getPath()!.replace(/\\/g, '/'), '/Folder'); }); test('WorkspaceFolder has name and index', function () { - const ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/One'), 0), aWorkspaceFolderData(URI.file('/Coding/Two'), 1)], name: 'Test' }, new NullLogService(), new Counter()); + const ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/One'), 0), aWorkspaceFolderData(URI.file('/Coding/Two'), 1)], name: 'Test' }, new NullLogService(), new Counter()); const [one, two] = ws.getWorkspaceFolders()!; @@ -122,7 +128,7 @@ suite('ExtHostWorkspace', function () { }); test('getContainingWorkspaceFolder', () => { - const ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { + const ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [ @@ -170,7 +176,7 @@ suite('ExtHostWorkspace', function () { }); test('Multiroot change event should have a delta, #29641', function (done) { - let ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }, new NullLogService(), new Counter()); + let ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }, new NullLogService(), new Counter()); let finished = false; const finish = (error?: any) => { @@ -233,7 +239,7 @@ suite('ExtHostWorkspace', function () { }); test('Multiroot change keeps existing workspaces live', function () { - let ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0)] }, new NullLogService(), new Counter()); + let ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0)] }, new NullLogService(), new Counter()); let firstFolder = ws.getWorkspaceFolders()![0]; ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar2'), 0), aWorkspaceFolderData(URI.parse('foo:bar'), 1, 'renamed')] }); @@ -253,7 +259,7 @@ suite('ExtHostWorkspace', function () { }); test('updateWorkspaceFolders - invalid arguments', function () { - let ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }, new NullLogService(), new Counter()); + let ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }, new NullLogService(), new Counter()); assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, null!, null!)); assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, 0, 0)); @@ -262,7 +268,7 @@ suite('ExtHostWorkspace', function () { assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, -1, 0)); assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, -1, -1)); - ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0)] }, new NullLogService(), new Counter()); + ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0)] }, new NullLogService(), new Counter()); assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, 1, 1)); assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, 0, 2)); @@ -284,7 +290,7 @@ suite('ExtHostWorkspace', function () { assertRegistered: undefined! }; - const ws = new ExtHostWorkspaceProvider(protocol, { id: 'foo', name: 'Test', folders: [] }, new NullLogService(), new Counter()); + const ws = createExtHostWorkspace(protocol, { id: 'foo', name: 'Test', folders: [] }, new NullLogService(), new Counter()); // // Add one folder @@ -517,7 +523,7 @@ suite('ExtHostWorkspace', function () { } }; - let ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }, new NullLogService(), new Counter()); + let ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }, new NullLogService(), new Counter()); let sub = ws.onDidChangeWorkspace(e => { try { assert.throws(() => { @@ -536,7 +542,7 @@ suite('ExtHostWorkspace', function () { }); test('`vscode.workspace.getWorkspaceFolder(file)` don\'t return workspace folder when file open from command line. #36221', function () { - let ws = new ExtHostWorkspaceProvider(new TestRPCProtocol(), { + let ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [ aWorkspaceFolderData(URI.file('c:/Users/marek/Desktop/vsc_test/'), 0) ]