diff --git a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts index 1f39e8c702c..d58ce7c1744 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts @@ -59,11 +59,10 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { // --- search --- $startSearch(include: string, exclude: string, maxResults: number, requestId: number): Thenable { - if (this._contextService.getWorkbenchState() === WorkbenchState.EMPTY) { + const workspace = this._contextService.getWorkspace(); + if (!workspace.roots.length) { return undefined; } - - const workspace = this._contextService.getWorkspace(); const query: ISearchQuery = { folderQueries: workspace.roots.map(root => ({ folder: root })), type: QueryType.File, diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index 57a029520dc..ee384bf7d00 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -75,11 +75,9 @@ export abstract class BaseWorkspacesAction extends Action { protected pickFolders(buttonLabel: string, title: string): string[] { let defaultPath: string; - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - const workspace = this.contextService.getWorkspace(); - if (workspace.roots.length > 0) { - defaultPath = dirname(workspace.roots[0].fsPath); // pick the parent of the first root by default - } + const workspace = this.contextService.getWorkspace(); + if (workspace.roots.length > 0) { + defaultPath = dirname(workspace.roots[0].fsPath); // pick the parent of the first root by default } return this.windowService.showOpenDialog({ @@ -110,23 +108,16 @@ export class AddRootFolderAction extends BaseWorkspacesAction { } public run(): TPromise { - switch (this.contextService.getWorkbenchState()) { - - case WorkbenchState.EMPTY: - return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, []).run(); - - case WorkbenchState.FOLDER: - return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, this.contextService.getWorkspace().roots).run(); - - case WorkbenchState.WORKSPACE: - const folders = super.pickFolders(mnemonicButtonLabel(nls.localize({ key: 'add', comment: ['&& denotes a mnemonic'] }, "&&Add")), nls.localize('addFolderToWorkspaceTitle', "Add Folder to Workspace")); - if (!folders || !folders.length) { - return TPromise.as(null); - } - return this.workspaceEditingService.addRoots(folders.map(folder => URI.file(folder))).then(() => { - return this.viewletService.openViewlet(this.viewletService.getDefaultViewletId(), true); - }); + if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { + const folders = super.pickFolders(mnemonicButtonLabel(nls.localize({ key: 'add', comment: ['&& denotes a mnemonic'] }, "&&Add")), nls.localize('addFolderToWorkspaceTitle', "Add Folder to Workspace")); + if (!folders || !folders.length) { + return TPromise.as(null); + } + return this.workspaceEditingService.addRoots(folders.map(folder => URI.file(folder))).then(() => { + return this.viewletService.openViewlet(this.viewletService.getDefaultViewletId(), true); + }); } + return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, this.contextService.getWorkspace().roots).run(); } } @@ -277,8 +268,7 @@ export class OpenWorkspaceConfigFileAction extends Action { ) { super(id, label); - const workspace = this.workspaceContextService.getWorkspace(); - this.enabled = workspace && !!workspace.configuration; + this.enabled = !!this.workspaceContextService.getWorkspace().configuration; } public run(): TPromise { diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index cf0c71ace23..ab03feddd0b 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -192,27 +192,17 @@ export class TitlebarPart extends Part implements ITitleService { const input = this.editorService.getActiveEditorInput(); const workspace = this.contextService.getWorkspace(); - // root resource is either workspace configuration file or the first root - let root: URI = workspace ? workspace.configuration || workspace.roots[0] : null; - // Compute folder resource // Single Root Workspace: always the root single workspace in this case - // Multi Root Workspace: root folder of the currently active file if any - let folder: URI; - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - if (workspace.roots.length === 1) { - folder = workspace.roots[0]; - } else { - folder = this.contextService.getRoot(toResource(input, { supportSideBySide: true, filter: 'file' })); - } - } + // Otherwise: root folder of the currently active file if any + let folder: URI = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER ? workspace.roots[0] : this.contextService.getRoot(toResource(input, { supportSideBySide: true, filter: 'file' })); // Variables const activeEditorShort = input ? input.getTitle(Verbosity.SHORT) : ''; const activeEditorMedium = input ? input.getTitle(Verbosity.MEDIUM) : activeEditorShort; const activeEditorLong = input ? input.getTitle(Verbosity.LONG) : activeEditorMedium; - const rootName = workspace ? workspace.name : ''; - const rootPath = root ? labels.getPathLabel(root, void 0, this.environmentService) : ''; + const rootName = workspace.name; + const rootPath = labels.getPathLabel(workspace.configuration || workspace.roots[0], void 0, this.environmentService) || ''; const folderName = folder ? (paths.basename(folder.fsPath) || folder.fsPath) : ''; const folderPath = folder ? labels.getPathLabel(folder, void 0, this.environmentService) : ''; const dirty = input && input.isDirty() ? TitlebarPart.TITLE_DIRTY : ''; diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts index 3bf29ca9d9b..7ee3341fcac 100644 --- a/src/vs/workbench/common/resources.ts +++ b/src/vs/workbench/common/resources.ts @@ -8,7 +8,7 @@ import URI from 'vs/base/common/uri'; import objects = require('vs/base/common/objects'); import paths = require('vs/base/common/paths'); -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import Event, { Emitter } from 'vs/base/common/event'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -106,17 +106,15 @@ export class ResourceGlobMatcher { let changed = false; // Add excludes per workspaces that got added - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - this.contextService.getWorkspace().roots.forEach(root => { - const rootExcludes = this.globFn(root); - if (!this.mapRootToExpressionConfig.has(root.toString()) || !objects.equals(this.mapRootToExpressionConfig.get(root.toString()), rootExcludes)) { - changed = true; + this.contextService.getWorkspace().roots.forEach(root => { + const rootExcludes = this.globFn(root); + if (!this.mapRootToExpressionConfig.has(root.toString()) || !objects.equals(this.mapRootToExpressionConfig.get(root.toString()), rootExcludes)) { + changed = true; - this.mapRootToParsedExpression.set(root.toString(), this.parseFn(rootExcludes)); - this.mapRootToExpressionConfig.set(root.toString(), objects.clone(rootExcludes)); - } - }); - } + this.mapRootToParsedExpression.set(root.toString(), this.parseFn(rootExcludes)); + this.mapRootToExpressionConfig.set(root.toString(), objects.clone(rootExcludes)); + } + }); // Remove excludes per workspace no longer present this.mapRootToExpressionConfig.forEach((value, root) => { diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index f48b79e1522..7d00adf6ec4 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -22,7 +22,6 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { realpath } from 'vs/base/node/pfs'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; -import path = require('path'); import gracefulFs = require('graceful-fs'); import { IInitData } from 'vs/workbench/services/timer/common/timerService'; import { TimerService } from 'vs/workbench/services/timer/node/timerService'; @@ -80,7 +79,7 @@ function openWorkbench(configuration: IWindowConfiguration): TPromise { // right before startup of the workbench shell to have its data ready for consumers return createAndInitializeWorkspaceService(configuration, environmentService, mainServices.get(IWorkspacesService)).then(workspaceService => { const timerService = new TimerService((window).MonacoEnvironment.timers as IInitData, workspaceService.getWorkbenchState() === WorkbenchState.EMPTY); - const storageService = createStorageService(configuration, workspaceService, environmentService); + const storageService = createStorageService(workspaceService, environmentService); timerService.beforeDOMContentLoaded = Date.now(); @@ -116,10 +115,10 @@ function createAndInitializeWorkspaceService(configuration: IWindowConfiguration if (configuration.workspace || configuration.folderPath) { workspaceService = new WorkspaceServiceImpl(configuration.workspace || configuration.folderPath, environmentService, workspacesService); } else { - workspaceService = new EmptyWorkspaceServiceImpl(environmentService); + workspaceService = new EmptyWorkspaceServiceImpl(configuration, environmentService); } - return workspaceService.initialize().then(() => workspaceService, error => new EmptyWorkspaceServiceImpl(environmentService)); + return workspaceService.initialize().then(() => workspaceService, error => new EmptyWorkspaceServiceImpl(configuration, environmentService)); }); } @@ -147,8 +146,7 @@ function validateWorkspacePath(configuration: IWindowConfiguration): TPromiseworkspaceService.getWorkspace(); +function createStorageService(workspaceService: IWorkspaceContextService, environmentService: IEnvironmentService): IStorageService { let workspaceId: string; let secondaryWorkspaceId: number; @@ -157,12 +155,13 @@ function createStorageService(configuration: IWindowConfiguration, workspaceServ // in multi root workspace mode we use the provided ID as key for workspace storage case WorkbenchState.WORKSPACE: - workspaceId = uri.from({ path: workspace.id, scheme: 'root' }).toString(); + workspaceId = uri.from({ path: workspaceService.getWorkspace().id, scheme: 'root' }).toString(); break; // in single folder mode we use the path of the opened folder as key for workspace storage // the ctime is used as secondary workspace id to clean up stale UI state if necessary case WorkbenchState.FOLDER: + const workspace: Workspace = workspaceService.getWorkspace(); workspaceId = workspace.roots[0].toString(); secondaryWorkspaceId = workspace.ctime; break; @@ -174,9 +173,7 @@ function createStorageService(configuration: IWindowConfiguration, workspaceServ // We use basename() to produce a short identifier, we do not need the full path. We use a custom // scheme so that we can later distinguish these identifiers from the workspace one. case WorkbenchState.EMPTY: - if (configuration.backupPath) { - workspaceId = uri.from({ path: path.basename(configuration.backupPath), scheme: 'empty' }).toString(); - } + workspaceId = workspaceService.getWorkspace().id; break; } diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 40b88cbed2c..9940e015191 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -294,12 +294,7 @@ export class ElectronWindow extends Themable { // Single folder or no workspace: create workspace and open else { - const workspaceFolders: URI[] = []; - - // Folder of workspace is the first of multi root workspace, so add it - if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { - workspaceFolders.push(...this.contextService.getWorkspace().roots); - } + const workspaceFolders: URI[] = [...this.contextService.getWorkspace().roots]; // Fill in remaining ones from request workspaceFolders.push(...request.foldersToAdd.map(folderToAdd => URI.file(folderToAdd.filePath))); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts index 6de54d487cc..0fa50d596b8 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts @@ -26,7 +26,7 @@ import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/plat import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IFileService } from 'vs/platform/files/common/files'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IDebugConfigurationProvider, IRawAdapter, ICompound, IDebugConfiguration, DEBUG_SCHEME, IConfig, IEnvConfig, IGlobalConfig, IConfigurationManager, ILaunch } from 'vs/workbench/parts/debug/common/debug'; @@ -353,7 +353,7 @@ export class ConfigurationManager implements IConfigurationManager { } private initLaunches(): void { - this.launches = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots.map(root => this.instantiationService.createInstance(Launch, this, root)) : []; + this.launches = this.contextService.getWorkspace().roots.map(root => this.instantiationService.createInstance(Launch, this, root)); if (this.launches.indexOf(this._selectedLaunch) === -1) { this._selectedLaunch = undefined; } diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 02f40b0c980..5f07e5d0f04 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -838,7 +838,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { return fromDesktop || isCopy ? DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY(true) : DRAG_OVER_ACCEPT_BUBBLE_DOWN(true); } - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.contextService.getWorkspace().roots.every(r => r.toString() !== target.resource.toString())) { + if (this.contextService.getWorkspace().roots.every(r => r.toString() !== target.resource.toString())) { return fromDesktop || isCopy ? DRAG_OVER_ACCEPT_BUBBLE_UP_COPY : DRAG_OVER_ACCEPT_BUBBLE_UP; } } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts index d0b1b0e5e16..d0872cca42f 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts @@ -56,7 +56,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { attachStylerCallback } from 'vs/platform/theme/common/styler'; import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import Event, { Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -886,12 +886,10 @@ class SettingsEditorContribution extends AbstractSettingsEditorContribution impl return true; } - if (this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - for (const root of this.workspaceContextService.getWorkspace().roots) { - const folderSettingsResource = this.preferencesService.getFolderSettingsResource(root); - if (folderSettingsResource && folderSettingsResource.fsPath === model.uri.fsPath) { - return true; - } + for (const root of this.workspaceContextService.getWorkspace().roots) { + const folderSettingsResource = this.preferencesService.getFolderSettingsResource(root); + if (folderSettingsResource && folderSettingsResource.fsPath === model.uri.fsPath) { + return true; } } diff --git a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts index ba472378c0e..eaa5f82e0e7 100644 --- a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts +++ b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts @@ -14,7 +14,7 @@ import { IWindowsService, IWindowService, IWindowsConfiguration } from 'vs/platf import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { localize } from 'vs/nls'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; interface IConfiguration extends IWindowsConfiguration { @@ -43,13 +43,9 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { @IWorkspaceContextService private contextService: IWorkspaceContextService, @IExtensionService private extensionService: IExtensionService ) { - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - const workspace = this.contextService.getWorkspace(); - this.rootCount = workspace.roots.length; - this.firstRootPath = workspace.roots.length > 0 ? workspace.roots[0].fsPath : void 0; - } else { - this.rootCount = 0; - } + const workspace = this.contextService.getWorkspace(); + this.rootCount = workspace.roots.length; + this.firstRootPath = workspace.roots.length > 0 ? workspace.roots[0].fsPath : void 0; this.onConfigurationChange(configurationService.getConfiguration(), false); diff --git a/src/vs/workbench/parts/search/browser/openFileHandler.ts b/src/vs/workbench/parts/search/browser/openFileHandler.ts index 09f7ea977af..e25d03cd56d 100644 --- a/src/vs/workbench/parts/search/browser/openFileHandler.ts +++ b/src/vs/workbench/parts/search/browser/openFileHandler.ts @@ -28,7 +28,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IQueryOptions, ISearchService, ISearchStats, ISearchQuery } from 'vs/platform/search/common/search'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IRange } from 'vs/editor/common/core/range'; import { getOutOfWorkspaceEditorResources } from 'vs/workbench/parts/search/common/search'; @@ -164,7 +164,7 @@ export class OpenFileHandler extends QuickOpenHandler { iconClass = 'file'; // only use a generic file icon if we are forced to use an icon and have no icon theme set otherwise } - const folderResources = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots : []; + const folderResources = this.contextService.getWorkspace().roots; return this.searchService.search(this.queryBuilder.file(folderResources, query)).then((complete) => { const results: QuickOpenEntry[] = []; for (let i = 0; i < complete.results.length; i++) { @@ -199,7 +199,7 @@ export class OpenFileHandler extends QuickOpenHandler { useRipgrep: this.experimentService.getExperiments().ripgrepQuickSearch }; - const folderResources = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots : []; + const folderResources = this.contextService.getWorkspace().roots; const query = this.queryBuilder.file(folderResources, options); return query; diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index c1e493bb0b2..27a1845e66c 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -870,8 +870,8 @@ export class SearchViewlet extends Viewlet { public searchInFolder(resource: URI): void { let folderPath = null; - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY && resource) { - const workspace = this.contextService.getWorkspace(); + const workspace = this.contextService.getWorkspace(); + if (resource) { if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { // Show relative path from the root for single-root mode folderPath = paths.relative(workspace.roots[0].fsPath, resource.fsPath); @@ -960,7 +960,7 @@ export class SearchViewlet extends Viewlet { excludePattern, includePattern }; - const folderResources = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots : []; + const folderResources = this.contextService.getWorkspace().roots; const onQueryValidationError = (err: Error) => { this.searchWidget.searchInput.showMessage({ content: err.message, type: MessageType.ERROR }); diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 599deb6e35c..7e811f487fc 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -34,6 +34,7 @@ import { ExtensionsRegistry, ExtensionMessageCollector } from 'vs/platform/exten import { IConfigurationNode, IConfigurationRegistry, Extensions, editorConfigurationSchemaId, IDefaultConfigurationExtension, validateProperty, ConfigurationScope, schemaId } from 'vs/platform/configuration/common/configurationRegistry'; import { createHash } from 'crypto'; import { getWorkspaceLabel, IWorkspacesService, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IStoredWorkspaceFolder, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; +import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; interface IStat { resource: URI; @@ -199,21 +200,22 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } public getWorkbenchState(): WorkbenchState { - if (this.workspace) { - if (this.workspace.configuration) { - return WorkbenchState.WORKSPACE; - } + // Workspace has configuration file + if (this.workspace.configuration) { + return WorkbenchState.WORKSPACE; + } + + // Folder has single root + if (this.workspace.roots.length === 1) { return WorkbenchState.FOLDER; } + + // Empty return WorkbenchState.EMPTY; } public getRoot(resource: URI): URI { - return this.workspace ? this.workspace.getRoot(resource) : null; - } - - private get workspaceUri(): URI { - return this.workspace ? this.workspace.roots[0] : null; + return this.workspace.getRoot(resource); } public isInsideWorkspace(resource: URI): boolean { @@ -221,19 +223,17 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } public isCurrentWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): boolean { - if (!this.workspace) { - return false; + switch (this.getWorkbenchState()) { + case WorkbenchState.FOLDER: + return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && this.pathEquals(this.workspace.roots[0].fsPath, workspaceIdentifier); + case WorkbenchState.WORKSPACE: + return isWorkspaceIdentifier(workspaceIdentifier) && this.workspace.id === workspaceIdentifier.id; } - - if (this.workspace.configuration) { - return isWorkspaceIdentifier(workspaceIdentifier) && this.workspace.id === workspaceIdentifier.id; - } - - return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && this.pathEquals(this.workspace.roots[0].fsPath, workspaceIdentifier); + return false; } public toResource(workspaceRelativePath: string): URI { - if (this.workspace && this.workspace.roots.length) { + if (this.workspace.roots.length) { return URI.file(paths.join(this.workspace.roots[0].fsPath, workspaceRelativePath)); } return null; @@ -312,8 +312,10 @@ export class EmptyWorkspaceServiceImpl extends WorkspaceService { private baseConfigurationService: GlobalConfigurationService; - constructor(environmentService: IEnvironmentService) { + constructor(configuration: IWindowConfiguration, environmentService: IEnvironmentService) { super(); + let id = configuration.backupPath ? URI.from({ path: paths.basename(configuration.backupPath), scheme: 'empty' }).toString() : ''; + this.workspace = new Workspace(id, '', []); this.baseConfigurationService = this._register(new GlobalConfigurationService(environmentService)); this._register(this.baseConfigurationService.onDidUpdateConfiguration(e => this.onBaseConfigurationChanged(e))); this.resetCaches(); diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index 3e974c0487f..c08df2e04c3 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -296,14 +296,14 @@ export class ConfigurationEditingService implements IConfigurationEditingService // Check for prefix if (config.key === key) { - const jsonPath = workspace && workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath ? [key] : []; + const jsonPath = workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath ? [key] : []; return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource, isWorkspaceStandalone: true }; } // Check for prefix. const keyPrefix = `${key}.`; if (config.key.indexOf(keyPrefix) === 0) { - const jsonPath = workspace && workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath ? [key, config.key.substr(keyPrefix.length)] : [config.key.substr(keyPrefix.length)]; + const jsonPath = workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath ? [key, config.key.substr(keyPrefix.length)] : [config.key.substr(keyPrefix.length)]; return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource, isWorkspaceStandalone: true }; } } @@ -316,7 +316,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService } const resource = this.getConfigurationFileResource(target, WORKSPACE_CONFIG_DEFAULT_PATH, overrides.resource); - if (workspace && workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath) { + if (workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath) { jsonPath = ['settings', ...jsonPath]; } return { key, jsonPath, value: config.value, resource }; diff --git a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts index d6bf47c961c..358c6d64603 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts @@ -45,6 +45,7 @@ import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; import { IChoiceService, IMessageService } from 'vs/platform/message/common/message'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; +import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; class SettingsTestEnvironmentService extends EnvironmentService { @@ -117,30 +118,32 @@ suite('ConfigurationEditingService', () => { const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile); instantiationService.stub(IEnvironmentService, environmentService); const workspacesService = instantiationService.stub(IWorkspacesService, {}); - const workspaceService = noWorkspace ? new EmptyWorkspaceServiceImpl(environmentService) : new WorkspaceServiceImpl(workspaceDir, environmentService, workspacesService); + const workspaceService = noWorkspace ? new EmptyWorkspaceServiceImpl({}, environmentService) : new WorkspaceServiceImpl(workspaceDir, environmentService, workspacesService); instantiationService.stub(IWorkspaceContextService, workspaceService); - instantiationService.stub(IConfigurationService, workspaceService); - instantiationService.stub(ILifecycleService, new TestLifecycleService()); - instantiationService.stub(IEditorGroupService, new TestEditorGroupService()); - instantiationService.stub(ITelemetryService, NullTelemetryService); - instantiationService.stub(IModeService, ModeServiceImpl); - instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl)); - instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), new TestConfigurationService(), { disableWatcher: true })); - instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService)); - instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); - instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); - instantiationService.stub(IBackupFileService, new TestBackupFileService()); - choiceService = instantiationService.stub(IChoiceService, { - choose: (severity, message, options, cancelId): TPromise => { - return TPromise.as(cancelId); - } - }); - instantiationService.stub(IMessageService, { - show: (severity, message, options, cancelId): void => { } - }); + return workspaceService.initialize().then(() => { + instantiationService.stub(IConfigurationService, workspaceService); + instantiationService.stub(ILifecycleService, new TestLifecycleService()); + instantiationService.stub(IEditorGroupService, new TestEditorGroupService()); + instantiationService.stub(ITelemetryService, NullTelemetryService); + instantiationService.stub(IModeService, ModeServiceImpl); + instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl)); + instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), new TestConfigurationService(), { disableWatcher: true })); + instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService)); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + instantiationService.stub(IBackupFileService, new TestBackupFileService()); + choiceService = instantiationService.stub(IChoiceService, { + choose: (severity, message, options, cancelId): TPromise => { + return TPromise.as(cancelId); + } + }); + instantiationService.stub(IMessageService, { + show: (severity, message, options, cancelId): void => { } + }); - testObject = instantiationService.createInstance(ConfigurationEditingService); - return workspaceService.initialize(); + testObject = instantiationService.createInstance(ConfigurationEditingService); + return workspaceService.initialize(); + }); } teardown(() => { diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index d5ce241b833..c6b81d34478 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -15,7 +15,7 @@ import { toResource } from 'vs/workbench/common/editor'; import { FileOperation, FileOperationEvent, IFileService, IFilesConfiguration, IResolveFileOptions, IFileStat, IResolveFileResult, IContent, IStreamContent, IImportResult, IResolveContentOptions, IUpdateContentOptions, FileChangesEvent } from 'vs/platform/files/common/files'; import { FileService as NodeFileService, IFileServiceOptions, IEncodingOverride } from 'vs/workbench/services/files/node/fileService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { Action } from 'vs/base/common/actions'; import { ResourceMap } from 'vs/base/common/map'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -146,11 +146,9 @@ export class FileService implements IFileService { private getEncodingOverrides(): IEncodingOverride[] { const encodingOverride: IEncodingOverride[] = []; encodingOverride.push({ resource: uri.file(this.environmentService.appSettingsHome), encoding: encoding.UTF8 }); - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - this.contextService.getWorkspace().roots.forEach(root => { - encodingOverride.push({ resource: uri.file(paths.join(root.fsPath, '.vscode')), encoding: encoding.UTF8 }); - }); - } + this.contextService.getWorkspace().roots.forEach(root => { + encodingOverride.push({ resource: uri.file(paths.join(root.fsPath, '.vscode')), encoding: encoding.UTF8 }); + }); return encodingOverride; } diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts index a22c3d618cb..59010bd922b 100644 --- a/src/vs/workbench/services/files/node/fileService.ts +++ b/src/vs/workbench/services/files/node/fileService.ts @@ -25,7 +25,7 @@ import uri from 'vs/base/common/uri'; import nls = require('vs/nls'); import { isWindows, isLinux } from 'vs/base/common/platform'; import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import pfs = require('vs/base/node/pfs'); import encoding = require('vs/base/node/encoding'); @@ -101,7 +101,7 @@ export class FileService implements IFileService { this.toDispose = []; this.options = options || Object.create(null); this.tmpPath = this.options.tmpDir || os.tmpdir(); - this.currentWorkspaceRootsCount = contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? contextService.getWorkspace().roots.length : 0; + this.currentWorkspaceRootsCount = contextService.getWorkspace().roots.length; this._onFileChanges = new Emitter(); this.toDispose.push(this._onFileChanges); @@ -129,7 +129,7 @@ export class FileService implements IFileService { } private onDidChangeWorkspaceRoots(): void { - const newRootCount = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots.length : 0; + const newRootCount = this.contextService.getWorkspace().roots.length; let restartWorkspaceWatcher = false; if (this.currentWorkspaceRootsCount <= 1 && newRootCount > 1) { diff --git a/src/vs/workbench/services/telemetry/common/workspaceStats.ts b/src/vs/workbench/services/telemetry/common/workspaceStats.ts index 6c2386e8b25..6246daee2b6 100644 --- a/src/vs/workbench/services/telemetry/common/workspaceStats.ts +++ b/src/vs/workbench/services/telemetry/common/workspaceStats.ts @@ -324,8 +324,7 @@ export class WorkspaceStats { } public reportCloudStats(): void { - const workspace = this.contextService.getWorkspace(); - const uris = workspace && workspace.roots; + const uris = this.contextService.getWorkspace().roots; if (uris && uris.length && this.fileService) { this.reportRemoteDomains(uris); this.reportRemotes(uris); diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index e172715a3d6..364f9b8c6dd 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -19,7 +19,7 @@ import diagnostics = require('vs/base/common/diagnostics'); import types = require('vs/base/common/types'); import { IMode } from 'vs/editor/common/modes'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent } from 'vs/workbench/services/textfile/common/textfiles'; import { EncodingMode } from 'vs/workbench/common/editor'; @@ -745,13 +745,10 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } // Check for workspace settings file - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - return this.contextService.getWorkspace().roots.some(root => { - return paths.isEqualOrParent(this.resource.fsPath, path.join(root.fsPath, '.vscode')); - }); - } + return this.contextService.getWorkspace().roots.some(root => { + return paths.isEqualOrParent(this.resource.fsPath, path.join(root.fsPath, '.vscode')); + }); - return false; } private doTouch(): TPromise { diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index bd896c78398..d851cd92cce 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -53,10 +53,9 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { } private isSupported(): boolean { - const workspace = this.contextService.getWorkspace(); return ( this.environmentService.appQuality !== 'stable' // not yet enabled in stable - && workspace && !!workspace.configuration // we need a workspace configuration file to begin with + && !!this.contextService.getWorkspace().configuration // we need a workspace configuration file to begin with ); }