diff --git a/extensions/mssql/package.json b/extensions/mssql/package.json index f35f071fed..4c0d0adc2a 100644 --- a/extensions/mssql/package.json +++ b/extensions/mssql/package.json @@ -20,6 +20,11 @@ "postinstall": "node ./build/postinstall.js" }, "contributes": { + "problemMatchers": [ + { + "name": "tasks" + } + ], "commands": [ { "command": "mssql.exportSqlAsNotebook", diff --git a/samples/sqlservices/.vscode/tasks.json b/samples/sqlservices/.vscode/tasks.json index d9f760b3da..ac12af572e 100644 --- a/samples/sqlservices/.vscode/tasks.json +++ b/samples/sqlservices/.vscode/tasks.json @@ -11,4 +11,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/vs/workbench/api/browser/extensionHost.contribution.ts b/src/vs/workbench/api/browser/extensionHost.contribution.ts index caf27de61e..d1a50e2b88 100644 --- a/src/vs/workbench/api/browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/browser/extensionHost.contribution.ts @@ -59,7 +59,7 @@ import './mainThreadWebviewManager'; import './mainThreadWorkspace'; import './mainThreadComments'; import './mainThreadNotebook'; -// import './mainThreadTask'; {{SQL CARBON EDIT}} @anthonydresser comment out task +import './mainThreadTask'; import './mainThreadLabelService'; import './mainThreadTunnelService'; import './mainThreadAuthentication'; diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index baad27b312..4017a30dbd 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -60,7 +60,7 @@ import { ExtHostLabelService } from 'vs/workbench/api/common/extHostLabelService import { getRemoteName } from 'vs/platform/remote/common/remoteHosts'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IExtHostDecorations } from 'vs/workbench/api/common/extHostDecorations'; -// import { IExtHostTask } from 'vs/workbench/api/common/extHostTask'; +import { IExtHostTask } from 'vs/workbench/api/common/extHostTask'; // import { IExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService'; import { IExtHostSearch } from 'vs/workbench/api/common/extHostSearch'; import { ILogService } from 'vs/platform/log/common/log'; @@ -124,7 +124,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, accessor.get(IExtHostTerminalService)); // const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, accessor.get(IExtHostDebugService)); {{SQL CARBON EDIT}} remove debug service const extHostSearch = rpcProtocol.set(ExtHostContext.ExtHostSearch, accessor.get(IExtHostSearch)); - // const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, accessor.get(IExtHostTask)); {{SQL CARBON EDIT}} remove tasks service + const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, accessor.get(IExtHostTask)); const extHostOutputService = rpcProtocol.set(ExtHostContext.ExtHostOutputService, accessor.get(IExtHostOutputService)); // manually create and register addressable instances @@ -155,8 +155,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I // Check that no named customers are missing // {{SQL CARBON EDIT}} filter out the services we don't expose - const filtered: ProxyIdentifier[] = [ExtHostContext.ExtHostDebugService, ExtHostContext.ExtHostTask]; + const filtered: ProxyIdentifier[] = [ExtHostContext.ExtHostDebugService]; const expected: ProxyIdentifier[] = values(ExtHostContext).filter(v => !filtered.find(x => x === v)); + rpcProtocol.assertRegistered(expected); // Other instances @@ -755,7 +756,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I return extHostDocumentContentProviders.registerTextDocumentContentProvider(scheme, provider); }, registerTaskProvider: (type: string, provider: vscode.TaskProvider) => { - throw new Error('Tasks api is not allowed in Azure Data Studio'); // {{SQL CARBON EDIT}} disable task + extHostApiDeprecation.report('window.registerTaskProvider', extension, + `Use the corresponding function on the 'tasks' namespace instead`); + + return extHostTask.registerTaskProvider(extension, type, provider); }, registerFileSystemProvider(scheme, provider, options) { return extHostFileSystem.registerFileSystemProvider(scheme, provider, options); @@ -911,38 +915,30 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I } }; - const tasks: typeof vscode.tasks = { // {{SQL CARBON EDIT}} disable tasks api + const tasks: typeof vscode.tasks = { registerTaskProvider: (type: string, provider: vscode.TaskProvider) => { - extHostLogService.warn('Tasks API is disabled in Azure Data Studio'); - return undefined!; + return extHostTask.registerTaskProvider(extension, type, provider); }, fetchTasks: (filter?: vscode.TaskFilter): Thenable => { - extHostLogService.warn('Tasks API is disabled in Azure Data Studio'); - return undefined!; + return extHostTask.fetchTasks(filter); }, executeTask: (task: vscode.Task): Thenable => { - extHostLogService.warn('Tasks API is disabled in Azure Data Studio'); - return undefined!; + return extHostTask.executeTask(extension, task); }, get taskExecutions(): vscode.TaskExecution[] { - extHostLogService.warn('Tasks API is disabled in Azure Data Studio'); - return undefined!; + return extHostTask.taskExecutions; }, onDidStartTask: (listeners, thisArgs?, disposables?) => { - extHostLogService.warn('Tasks API is disabled in Azure Data Studio'); - return undefined!; + return extHostTask.onDidStartTask(listeners, thisArgs, disposables); }, onDidEndTask: (listeners, thisArgs?, disposables?) => { - extHostLogService.warn('Tasks API is disabled in Azure Data Studio'); - return undefined!; + return extHostTask.onDidEndTask(listeners, thisArgs, disposables); }, onDidStartTaskProcess: (listeners, thisArgs?, disposables?) => { - extHostLogService.warn('Tasks API is disabled in Azure Data Studio'); - return undefined!; + return extHostTask.onDidStartTaskProcess(listeners, thisArgs, disposables); }, onDidEndTaskProcess: (listeners, thisArgs?, disposables?) => { - extHostLogService.warn('Tasks API is disabled in Azure Data Studio'); - return undefined!; + return extHostTask.onDidEndTaskProcess(listeners, thisArgs, disposables); } }; diff --git a/src/vs/workbench/api/common/extHost.common.services.ts b/src/vs/workbench/api/common/extHost.common.services.ts index a7d79d2d30..dbaacb6f54 100644 --- a/src/vs/workbench/api/common/extHost.common.services.ts +++ b/src/vs/workbench/api/common/extHost.common.services.ts @@ -11,7 +11,7 @@ import { IExtHostConfiguration, ExtHostConfiguration } from 'vs/workbench/api/co import { IExtHostCommands, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; import { IExtHostDocumentsAndEditors, ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; import { IExtHostTerminalService, WorkerExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService'; -// import { IExtHostTask, WorkerExtHostTask } from 'vs/workbench/api/common/extHostTask'; +import { IExtHostTask, WorkerExtHostTask } from 'vs/workbench/api/common/extHostTask'; // import { IExtHostDebugService, WorkerExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService'; import { IExtHostSearch, ExtHostSearch } from 'vs/workbench/api/common/extHostSearch'; import { IExtensionStoragePaths, ExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths'; @@ -34,7 +34,7 @@ registerSingleton(IExtHostFileSystemInfo, ExtHostFileSystemInfo); registerSingleton(IExtHostOutputService, ExtHostOutputService); registerSingleton(IExtHostSearch, ExtHostSearch); registerSingleton(IExtHostStorage, ExtHostStorage); -// registerSingleton(IExtHostTask, WorkerExtHostTask); +registerSingleton(IExtHostTask, WorkerExtHostTask); registerSingleton(IExtHostTerminalService, WorkerExtHostTerminalService); registerSingleton(IExtHostTunnelService, ExtHostTunnelService); registerSingleton(IExtHostWindow, ExtHostWindow); diff --git a/src/vs/workbench/api/node/extHost.node.services.ts b/src/vs/workbench/api/node/extHost.node.services.ts index 84ddcde4ac..0224200c04 100644 --- a/src/vs/workbench/api/node/extHost.node.services.ts +++ b/src/vs/workbench/api/node/extHost.node.services.ts @@ -6,7 +6,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ExtHostOutputService2 } from 'vs/workbench/api/node/extHostOutputService'; import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService'; -// import { ExtHostTask } from 'vs/workbench/api/node/extHostTask'; +import { ExtHostTask } from 'vs/workbench/api/node/extHostTask'; // import { ExtHostDebugService } from 'vs/workbench/api/node/extHostDebugService'; import { NativeExtHostSearch } from 'vs/workbench/api/node/extHostSearch'; import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService'; @@ -16,7 +16,7 @@ import { ExtHostTunnelService } from 'vs/workbench/api/node/extHostTunnelService import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService'; import { IExtHostOutputService } from 'vs/workbench/api/common/extHostOutput'; import { IExtHostSearch } from 'vs/workbench/api/common/extHostSearch'; -// import { IExtHostTask } from 'vs/workbench/api/common/extHostTask'; +import { IExtHostTask } from 'vs/workbench/api/common/extHostTask'; import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService'; import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService'; import { ILogService } from 'vs/platform/log/common/log'; @@ -33,6 +33,6 @@ registerSingleton(ILogService, ExtHostLogService); // registerSingleton(IExtHostDebugService, ExtHostDebugService); registerSingleton(IExtHostOutputService, ExtHostOutputService2); registerSingleton(IExtHostSearch, NativeExtHostSearch); -// registerSingleton(IExtHostTask, ExtHostTask); +registerSingleton(IExtHostTask, ExtHostTask); registerSingleton(IExtHostTerminalService, ExtHostTerminalService); registerSingleton(IExtHostTunnelService, ExtHostTunnelService); diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index 30182d6e7a..da6ce49c40 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -82,6 +82,12 @@ import { isWorkspaceFolder, TaskQuickPickEntry, QUICKOPEN_DETAIL_CONFIG, TaskQui import { ILogService } from 'vs/platform/log/common/log'; import { once } from 'vs/base/common/functional'; +// {{ SQL CARBON EDIT }} +// integration with tasks view panel +import { ITaskService as ISqlTaskService, TaskStatusChangeArgs } from 'sql/workbench/services/tasks/common/tasksService'; +import { TaskStatus } from 'sql/workbench/api/common/extHostBackgroundTaskManagement'; +import { TaskInfo } from 'azdata'; + const QUICKOPEN_HISTORY_LIMIT_CONFIG = 'task.quickOpen.history'; const PROBLEM_MATCHER_NEVER_CONFIG = 'task.problemMatchers.neverPrompt'; const USE_SLOW_PICKER = 'task.quickOpen.showAll'; @@ -227,6 +233,9 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer private _waitForSupportedExecutions: Promise; private _onDidRegisterSupportedExecutions: Emitter = new Emitter(); + // {{SQL CARBON EDIT}} + private lastRunTasksViewTask: TaskInfo; + constructor( @IConfigurationService private readonly configurationService: IConfigurationService, @IMarkerService protected readonly markerService: IMarkerService, @@ -258,7 +267,8 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer @ITextModelService private readonly textModelResolverService: ITextModelService, @IPreferencesService private readonly preferencesService: IPreferencesService, @IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService, - @ILogService private readonly logService: ILogService + @ILogService private readonly logService: ILogService, + @ISqlTaskService private readonly sqlTaskService: ISqlTaskService ) { super(); @@ -882,7 +892,6 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer if (!task) { throw new TaskError(Severity.Info, nls.localize('TaskServer.noTask', 'Task to execute is undefined'), TaskErrors.TaskNotFound); } - return new Promise(async (resolve) => { let resolver = this.createResolver(); if (options && options.attachProblemMatcher && this.shouldAttachProblemMatcher(task) && !InMemoryTask.is(task)) { @@ -1473,8 +1482,25 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer const execTask = async (task: Task, resolver: ITaskResolver): Promise => { return ProblemMatcherRegistry.onReady().then(() => { + // {{ SQL CARBON EDIT }} + const taskNodeId = UUID.generateUuid(); + let taskInfo: TaskInfo = { + databaseName: undefined, + serverName: undefined, + description: undefined, + isCancelable: false, + name: task._label, + providerName: undefined, + taskExecutionMode: 0, + taskId: taskNodeId, + status: TaskStatus.NotStarted + }; + this.sqlTaskService.createNewTask(taskInfo); + this.lastRunTasksViewTask = taskInfo; + let executeResult = this.getTaskSystem().run(task, resolver); - return this.handleExecuteResult(executeResult, runSource); + // {{ SQL CARBON EDIT }} + return this.handleExecuteResult(executeResult, runSource, taskNodeId); }); }; @@ -1511,7 +1537,8 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer } } - private async handleExecuteResult(executeResult: ITaskExecuteResult, runSource?: TaskRunSource): Promise { + // {{SQL CARBON EDIT}} + private async handleExecuteResult(executeResult: ITaskExecuteResult, runSource?: TaskRunSource, taskNodeId?: string): Promise { if (executeResult.task.taskLoadMessages && executeResult.task.taskLoadMessages.length > 0) { executeResult.task.taskLoadMessages.forEach(loadMessage => { this._outputChannel.append(loadMessage + '\n'); @@ -1546,6 +1573,19 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer throw new TaskError(Severity.Warning, nls.localize('TaskSystem.active', 'There is already a task running. Terminate it first before executing another task.'), TaskErrors.RunningTask); } } + // {{ SQL CARBON EDIT }} + executeResult.promise.then((summary: ITaskSummary) => { + let args: TaskStatusChangeArgs = { + taskId: taskNodeId ? taskNodeId : executeResult.task._id, + status: undefined + }; + if (summary.exitCode === 0) { + args.status = TaskStatus.Succeeded; + } else if (summary.exitCode === 1) { + args.status = TaskStatus.Failed; + } + this.sqlTaskService.handleTaskComplete(args); + }); return executeResult.promise; } @@ -2555,9 +2595,16 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer ProblemMatcherRegistry.onReady().then(() => { return this.editorService.saveAll({ reason: SaveReason.AUTO }).then(() => { // make sure all dirty editors are saved + // {{SQL CARBON EDIT}} + let lastRunTasksViewTask = this.lastRunTasksViewTask; + lastRunTasksViewTask.taskId = UUID.generateUuid(); + this.sqlTaskService.createNewTask(lastRunTasksViewTask); + this.lastRunTasksViewTask = lastRunTasksViewTask; + let executeResult = this.getTaskSystem().rerun(); if (executeResult) { - return this.handleExecuteResult(executeResult); + // {{SQL CARBON EDIT}} + return this.handleExecuteResult(executeResult, undefined, lastRunTasksViewTask.taskId); } else { this.doRunTaskCommand(); return Promise.resolve(undefined); diff --git a/src/vs/workbench/services/configuration/common/configuration.ts b/src/vs/workbench/services/configuration/common/configuration.ts index b5e9ad27b3..8361bf31b6 100644 --- a/src/vs/workbench/services/configuration/common/configuration.ts +++ b/src/vs/workbench/services/configuration/common/configuration.ts @@ -5,7 +5,9 @@ import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; +// {{SQL CARBON EDIT}} export const FOLDER_CONFIG_FOLDER_NAME = '.azuredatastudio'; +export const TASKS_FOLDER_CONFIG_FOLDER_NAME = '.vscode'; export const FOLDER_SETTINGS_NAME = 'settings'; export const FOLDER_SETTINGS_PATH = `${FOLDER_CONFIG_FOLDER_NAME}/${FOLDER_SETTINGS_NAME}.json`; @@ -26,7 +28,7 @@ export const TASKS_CONFIGURATION_KEY = 'tasks'; export const LAUNCH_CONFIGURATION_KEY = 'launch'; export const WORKSPACE_STANDALONE_CONFIGURATIONS = Object.create(null); -WORKSPACE_STANDALONE_CONFIGURATIONS[TASKS_CONFIGURATION_KEY] = `${FOLDER_CONFIG_FOLDER_NAME}/${TASKS_CONFIGURATION_KEY}.json`; +WORKSPACE_STANDALONE_CONFIGURATIONS[TASKS_CONFIGURATION_KEY] = `${TASKS_FOLDER_CONFIG_FOLDER_NAME}/${TASKS_CONFIGURATION_KEY}.json`; WORKSPACE_STANDALONE_CONFIGURATIONS[LAUNCH_CONFIGURATION_KEY] = `${FOLDER_CONFIG_FOLDER_NAME}/${LAUNCH_CONFIGURATION_KEY}.json`; export const USER_STANDALONE_CONFIGURATIONS = Object.create(null); USER_STANDALONE_CONFIGURATIONS[TASKS_CONFIGURATION_KEY] = `${TASKS_CONFIGURATION_KEY}.json`; diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts index fea8446e19..962ffb2c6a 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts @@ -96,6 +96,10 @@ suite('ConfigurationEditingService', () => { globalTasksFile = path.join(workspaceDir, 'tasks.json'); workspaceSettingsDir = path.join(workspaceDir, '.azuredatastudio'); // {{SQL CARBON EDIT}} .vscode to .azuredatastudio + // {{SQL CARBON EDIT}} add .vscode folder for tasks tests + const tasksSettingsDir = path.join(workspaceDir, '.vscode'); + await mkdirp(tasksSettingsDir, 493); + return await mkdirp(workspaceSettingsDir, 493); } diff --git a/src/vs/workbench/services/extensions/common/extensionHostManager.ts b/src/vs/workbench/services/extensions/common/extensionHostManager.ts index 10baa5bcef..0844687b0e 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostManager.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostManager.ts @@ -206,7 +206,7 @@ export class ExtensionHostManager extends Disposable { // Check that no named customers are missing // {{SQL CARBON EDIT}} filter out services we don't expose - const filtered: ProxyIdentifier[] = [MainContext.MainThreadDebugService, MainContext.MainThreadTask]; + const filtered: ProxyIdentifier[] = [MainContext.MainThreadDebugService]; const expected: ProxyIdentifier[] = Object.keys(MainContext).map((key) => (MainContext)[key]).filter(v => !filtered.some(x => x === v)); this._rpcProtocol.assertRegistered(expected); diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index cdcb262189..796c7d810c 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -331,7 +331,7 @@ import 'vs/workbench/contrib/terminal/browser/terminalView'; import 'vs/workbench/contrib/relauncher/browser/relauncher.contribution'; // Tasks -// import 'vs/workbench/contrib/tasks/browser/task.contribution'; {{SQL CARBON EDIT}} +import 'vs/workbench/contrib/tasks/browser/task.contribution'; // Remote import 'vs/workbench/contrib/remote/common/remote.contribution';