From f80adf8a85e8eca690d3cd740c7e9f447fa35e89 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 20 Oct 2017 22:08:44 +0200 Subject: [PATCH] Fix #35219 --- build/lib/i18n.resources.json | 4 ++ .../browser/actions/workspaceActions.ts | 8 +-- .../files/browser/views/explorerViewer.ts | 2 +- .../workspace/common/workspaceEditing.ts | 11 ++++ .../workspace/node/workspaceEditingService.ts | 52 ++++++++++++++++++- 5 files changed, 70 insertions(+), 7 deletions(-) diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index 9325369a2a5a..9aafba7dc49a 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -186,6 +186,10 @@ "name": "vs/workbench/services/textMate", "project": "vscode-workbench" }, + { + "name": "vs/workbench/services/workspace", + "project": "vscode-workbench" + }, { "name": "setup_messages", "project": "vscode-workbench" diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index 50a08486f98d..ea253e702184 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -119,7 +119,7 @@ export class AddRootFolderAction extends BaseWorkspacesAction { return TPromise.as(null); } - addFoldersPromise = this.contextService.addFolders(folders.map(folder => URI.file(folder))); + addFoldersPromise = this.workspaceEditingService.addFolders(folders.map(folder => URI.file(folder))); } // Empty or Folder @@ -163,7 +163,7 @@ export class GlobalRemoveRootFolderAction extends BaseWorkspacesAction { } // Workspace: remove folder - return this.contextService.removeFolders([folder.uri]).then(() => true); + return this.workspaceEditingService.removeFolders([folder.uri]).then(() => true); } return true; @@ -216,13 +216,13 @@ export class RemoveRootFolderAction extends Action { private rootUri: URI, id: string, label: string, - @IWorkspaceContextService private contextService: IWorkspaceContextService + @IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService ) { super(id, label); } public run(): TPromise { - return this.contextService.removeFolders([this.rootUri]); + return this.workspaceEditingService.removeFolders([this.rootUri]); } } diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 8c02ed1ac07f..21617036d53b 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -910,7 +910,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { const folders = result.filter(result => result.stat.isDirectory).map(result => result.stat.resource); if (folders.length > 0) { if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { - return this.contextService.addFolders(folders); + return this.workspaceEditingService.addFolders(folders); } // If we are in single-folder context, ask for confirmation to create a workspace diff --git a/src/vs/workbench/services/workspace/common/workspaceEditing.ts b/src/vs/workbench/services/workspace/common/workspaceEditing.ts index 8f5e6cd634d8..e7d86635073a 100644 --- a/src/vs/workbench/services/workspace/common/workspaceEditing.ts +++ b/src/vs/workbench/services/workspace/common/workspaceEditing.ts @@ -7,6 +7,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; +import URI from 'vs/base/common/uri'; export const IWorkspaceEditingService = createDecorator('workspaceEditingService'); @@ -14,6 +15,16 @@ export interface IWorkspaceEditingService { _serviceBrand: ServiceIdentifier; + /** + * Add folders to the existing workspace + */ + addFolders(folders: URI[]): TPromise; + + /** + * Remove folders from the existing workspace + */ + removeFolders(folders: URI[]): TPromise; + /** * creates a new workspace with the provided folders and opens it. if path is provided * the workspace will be saved into that location. diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index f5711bdfb21e..5fa421760f46 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -7,10 +7,11 @@ import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import URI from 'vs/base/common/uri'; +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWindowService, IEnterWorkspaceResult } from 'vs/platform/windows/common/windows'; -import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; +import { IJSONEditingService, JSONEditingError, JSONEditingErrorCode } from 'vs/workbench/services/configuration/common/jsonEditing'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; @@ -22,6 +23,8 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { BackupFileService } from 'vs/workbench/services/backup/node/backupFileService'; +import { IChoiceService, Severity, IMessageService } from 'vs/platform/message/common/message'; +import { ICommandService } from 'vs/platform/commands/common/commands'; export class WorkspaceEditingService implements IWorkspaceEditingService { @@ -34,10 +37,23 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { @IWorkspaceConfigurationService private workspaceConfigurationService: IWorkspaceConfigurationService, @IStorageService private storageService: IStorageService, @IExtensionService private extensionService: IExtensionService, - @IBackupFileService private backupFileService: IBackupFileService + @IBackupFileService private backupFileService: IBackupFileService, + @IChoiceService private choiceService: IChoiceService, + @IMessageService private messageService: IMessageService, + @ICommandService private commandService: ICommandService ) { } + public addFolders(folders: URI[]): TPromise { + return this.contextService.addFolders(folders) + .then(() => null, error => this.handleWorkspaceConfigurationEditingError(error)); + } + + public removeFolders(folders: URI[]): TPromise { + return this.contextService.removeFolders(folders) + .then(() => null, error => this.handleWorkspaceConfigurationEditingError(error)); + } + public createAndEnterWorkspace(folderPaths?: string[], path?: string): TPromise { return this.doEnterWorkspace(() => this.windowService.createAndEnterWorkspace(folderPaths, path)); } @@ -46,6 +62,38 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { return this.doEnterWorkspace(() => this.windowService.saveAndEnterWorkspace(path)); } + private handleWorkspaceConfigurationEditingError(error: JSONEditingError): TPromise { + switch (error.code) { + case JSONEditingErrorCode.ERROR_INVALID_FILE: + return this.onInvalidWorkspaceConfigurationFileError(); + case JSONEditingErrorCode.ERROR_FILE_DIRTY: + return this.onWorkspaceConfigurationFileDirtyError(); + } + this.messageService.show(Severity.Error, error.message); + return TPromise.as(void 0); + } + + private onInvalidWorkspaceConfigurationFileError(): TPromise { + const message = nls.localize('errorInvalidTaskConfiguration', "Unable to write into workspace configuration file. Please open the file to correct errors/warnings in it and try again."); + return this.askToOpenWorkspaceConfigurationFile(message); + } + + private onWorkspaceConfigurationFileDirtyError(): TPromise { + const message = nls.localize('errorWorkspaceConfigurationFileDirty', "Unable to write into workspace configuration file because the file is dirty. Please save it and try again."); + return this.askToOpenWorkspaceConfigurationFile(message); + } + + private askToOpenWorkspaceConfigurationFile(message: string): TPromise { + return this.choiceService.choose(Severity.Error, message, [nls.localize('openWorkspaceConfigurationFile', "Open Workspace Configuration File"), nls.localize('close', "Close")], 1) + .then(option => { + switch (option) { + case 0: + this.commandService.executeCommand('workbench.action.openWorkspaceConfigFile'); + break; + } + }); + } + private doEnterWorkspace(mainSidePromise: () => TPromise): TPromise { // Stop the extension host first to give extensions most time to shutdown