diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index e3ab792c05e..987372c1348 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -913,7 +913,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer }).then((value) => { if (runSource === TaskRunSource.User) { this.getWorkspaceTasks().then(workspaceTasks => { - RunAutomaticTasks.promptForPermission(this, this.storageService, this.notificationService, this.workspaceTrustService, workspaceTasks); + RunAutomaticTasks.promptForPermission(this, this.storageService, this.notificationService, this.workspaceTrustService, this.openerService, workspaceTasks); }); } return value; diff --git a/src/vs/workbench/contrib/tasks/browser/runAutomaticTasks.ts b/src/vs/workbench/contrib/tasks/browser/runAutomaticTasks.ts index 743b1c75374..7c5b14327d3 100644 --- a/src/vs/workbench/contrib/tasks/browser/runAutomaticTasks.ts +++ b/src/vs/workbench/contrib/tasks/browser/runAutomaticTasks.ts @@ -4,17 +4,21 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; +import * as resources from 'vs/base/common/resources'; import { Disposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { ITaskService, WorkspaceFolderTaskResult } from 'vs/workbench/contrib/tasks/common/taskService'; import { forEach } from 'vs/base/common/collections'; -import { RunOnOptions, Task, TaskRunSource, TASKS_CATEGORY } from 'vs/workbench/contrib/tasks/common/tasks'; +import { RunOnOptions, Task, TaskRunSource, TaskSource, TaskSourceKind, TASKS_CATEGORY, WorkspaceFileTaskSource, WorkspaceTaskSource } from 'vs/workbench/contrib/tasks/common/tasks'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IQuickPickItem, IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { Action2 } from 'vs/platform/actions/common/actions'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IWorkspaceTrustService, WorkspaceTrustState } from 'vs/platform/workspace/common/workspaceTrust'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { IOpenerService } from 'vs/platform/opener/common/opener'; +import { URI } from 'vs/base/common/uri'; const ARE_AUTOMATIC_TASKS_ALLOWED_IN_WORKSPACE = 'tasks.run.allowAutomatic'; @@ -55,9 +59,24 @@ export class RunAutomaticTasks extends Disposable implements IWorkbenchContribut }); } - private static findAutoTasks(taskService: ITaskService, workspaceTaskResult: Map): { tasks: Array>, taskNames: Array } { + private static getTaskSource(source: TaskSource): URI | undefined { + const taskKind = TaskSourceKind.toConfigurationTarget(source.kind); + switch (taskKind) { + case ConfigurationTarget.WORKSPACE_FOLDER: { + return resources.joinPath((source).config.workspaceFolder!.uri, (source).config.file); + } + case ConfigurationTarget.WORKSPACE: { + return (source).config.workspace?.configuration ?? undefined; + } + } + return undefined; + } + + private static findAutoTasks(taskService: ITaskService, workspaceTaskResult: Map): { tasks: Array>, taskNames: Array, locations: Map } { const tasks = new Array>(); const taskNames = new Array(); + const locations = new Map(); + if (workspaceTaskResult) { workspaceTaskResult.forEach(resultElement => { if (resultElement.set) { @@ -65,6 +84,10 @@ export class RunAutomaticTasks extends Disposable implements IWorkbenchContribut if (task.runOptions.runOn === RunOnOptions.folderOpen) { tasks.push(task); taskNames.push(task._label); + const location = RunAutomaticTasks.getTaskSource(task._source); + if (location) { + locations.set(location.fsPath, location); + } } }); } @@ -79,16 +102,20 @@ export class RunAutomaticTasks extends Disposable implements IWorkbenchContribut } else { taskNames.push(configedTask.value.configures.task); } + const location = RunAutomaticTasks.getTaskSource(configedTask.value._source); + if (location) { + locations.set(location.fsPath, location); + } } }); } }); } - return { tasks, taskNames }; + return { tasks, taskNames, locations }; } public static async promptForPermission(taskService: ITaskService, storageService: IStorageService, notificationService: INotificationService, workspaceTrustService: IWorkspaceTrustService, - workspaceTaskResult: Map) { + openerService: IOpenerService, workspaceTaskResult: Map) { const isWorkspaceTrusted = await workspaceTrustService.requireWorkspaceTrust({ immediate: false }) === WorkspaceTrustState.Trusted; if (!isWorkspaceTrusted) { return; @@ -99,10 +126,10 @@ export class RunAutomaticTasks extends Disposable implements IWorkbenchContribut return; } - let { tasks, taskNames } = RunAutomaticTasks.findAutoTasks(taskService, workspaceTaskResult); + let { tasks, taskNames, locations } = RunAutomaticTasks.findAutoTasks(taskService, workspaceTaskResult); if (taskNames.length > 0) { // We have automatic tasks, prompt to allow. - this.showPrompt(notificationService, storageService, taskService, taskNames).then(allow => { + this.showPrompt(notificationService, storageService, taskService, openerService, taskNames, locations).then(allow => { if (allow) { RunAutomaticTasks.runTasks(taskService, tasks); } @@ -111,9 +138,13 @@ export class RunAutomaticTasks extends Disposable implements IWorkbenchContribut } private static showPrompt(notificationService: INotificationService, storageService: IStorageService, taskService: ITaskService, - taskNames: Array): Promise { + openerService: IOpenerService, taskNames: Array, locations: Map): Promise { return new Promise(resolve => { - notificationService.prompt(Severity.Info, nls.localize('tasks.run.allowAutomatic', "This folder has tasks ({0}) defined in \'tasks.json\' that run automatically when you open this folder. Do you allow automatic tasks to run when you open this folder?", taskNames.join(', ')), + notificationService.prompt(Severity.Info, nls.localize('tasks.run.allowAutomatic', + "This workspace has tasks ({0}) defined ({1}) that run automatically when you open this workspace. Do you allow automatic tasks to run when you open this workspace?", + taskNames.join(', '), + Array.from(locations.keys()).join(', ') + ), [{ label: nls.localize('allow', "Allow and run"), run: () => { @@ -129,9 +160,11 @@ export class RunAutomaticTasks extends Disposable implements IWorkbenchContribut } }, { - label: nls.localize('openTasks', "Open tasks.json"), - run: () => { - taskService.openConfig(undefined); + label: locations.size === 1 ? nls.localize('openTask', "Open file") : nls.localize('openTasks', "Open files"), + run: async () => { + for (const location of locations) { + await openerService.open(location[1]); + } resolve(false); } }]